content/media/MediaResource.h

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:976c37d67790
1 /* vim:set ts=2 sw=2 sts=2 et cindent: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #if !defined(MediaResource_h_)
7 #define MediaResource_h_
8
9 #include "mozilla/Mutex.h"
10 #include "nsIChannel.h"
11 #include "nsIURI.h"
12 #include "nsIStreamingProtocolController.h"
13 #include "nsIStreamListener.h"
14 #include "nsIChannelEventSink.h"
15 #include "nsIInterfaceRequestor.h"
16 #include "MediaCache.h"
17 #include "mozilla/Attributes.h"
18 #include "mozilla/TimeStamp.h"
19 #include "nsThreadUtils.h"
20
21 // For HTTP seeking, if number of bytes needing to be
22 // seeked forward is less than this value then a read is
23 // done rather than a byte range request.
24 static const int64_t SEEK_VS_READ_THRESHOLD = 32*1024;
25
26 static const uint32_t HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE = 416;
27
28 // Number of bytes we have accumulated before we assume the connection download
29 // rate can be reliably calculated. 57 Segments at IW=3 allows slow start to
30 // reach a CWND of 30 (See bug 831998)
31 static const int64_t RELIABLE_DATA_THRESHOLD = 57 * 1460;
32
33 class nsIHttpChannel;
34 class nsIPrincipal;
35
36 namespace mozilla {
37
38 class MediaDecoder;
39
40 /**
41 * This class is useful for estimating rates of data passing through
42 * some channel. The idea is that activity on the channel "starts"
43 * and "stops" over time. At certain times data passes through the
44 * channel (usually while the channel is active; data passing through
45 * an inactive channel is ignored). The GetRate() function computes
46 * an estimate of the "current rate" of the channel, which is some
47 * kind of average of the data passing through over the time the
48 * channel is active.
49 *
50 * All methods take "now" as a parameter so the user of this class can
51 * control the timeline used.
52 */
53 class MediaChannelStatistics {
54 public:
55 MediaChannelStatistics() { Reset(); }
56
57 MediaChannelStatistics(MediaChannelStatistics * aCopyFrom)
58 {
59 MOZ_ASSERT(aCopyFrom);
60 mAccumulatedBytes = aCopyFrom->mAccumulatedBytes;
61 mAccumulatedTime = aCopyFrom->mAccumulatedTime;
62 mLastStartTime = aCopyFrom->mLastStartTime;
63 mIsStarted = aCopyFrom->mIsStarted;
64 }
65
66 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaChannelStatistics)
67
68 void Reset() {
69 mLastStartTime = TimeStamp();
70 mAccumulatedTime = TimeDuration(0);
71 mAccumulatedBytes = 0;
72 mIsStarted = false;
73 }
74 void Start() {
75 if (mIsStarted)
76 return;
77 mLastStartTime = TimeStamp::Now();
78 mIsStarted = true;
79 }
80 void Stop() {
81 if (!mIsStarted)
82 return;
83 mAccumulatedTime += TimeStamp::Now() - mLastStartTime;
84 mIsStarted = false;
85 }
86 void AddBytes(int64_t aBytes) {
87 if (!mIsStarted) {
88 // ignore this data, it may be related to seeking or some other
89 // operation we don't care about
90 return;
91 }
92 mAccumulatedBytes += aBytes;
93 }
94 double GetRateAtLastStop(bool* aReliable) {
95 double seconds = mAccumulatedTime.ToSeconds();
96 *aReliable = (seconds >= 1.0) ||
97 (mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
98 if (seconds <= 0.0)
99 return 0.0;
100 return static_cast<double>(mAccumulatedBytes)/seconds;
101 }
102 double GetRate(bool* aReliable) {
103 TimeDuration time = mAccumulatedTime;
104 if (mIsStarted) {
105 time += TimeStamp::Now() - mLastStartTime;
106 }
107 double seconds = time.ToSeconds();
108 *aReliable = (seconds >= 3.0) ||
109 (mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
110 if (seconds <= 0.0)
111 return 0.0;
112 return static_cast<double>(mAccumulatedBytes)/seconds;
113 }
114 private:
115 int64_t mAccumulatedBytes;
116 TimeDuration mAccumulatedTime;
117 TimeStamp mLastStartTime;
118 bool mIsStarted;
119 };
120
121 // Forward declaration for use in MediaByteRange.
122 class TimestampedMediaByteRange;
123
124 // Represents a section of contiguous media, with a start and end offset.
125 // Used to denote ranges of data which are cached.
126 class MediaByteRange {
127 public:
128 MediaByteRange() : mStart(0), mEnd(0) {}
129
130 MediaByteRange(int64_t aStart, int64_t aEnd)
131 : mStart(aStart), mEnd(aEnd)
132 {
133 NS_ASSERTION(mStart < mEnd, "Range should end after start!");
134 }
135
136 MediaByteRange(TimestampedMediaByteRange& aByteRange);
137
138 bool IsNull() const {
139 return mStart == 0 && mEnd == 0;
140 }
141
142 // Clears byte range values.
143 void Clear() {
144 mStart = 0;
145 mEnd = 0;
146 }
147
148 int64_t mStart, mEnd;
149 };
150
151 // Represents a section of contiguous media, with a start and end offset, and
152 // a timestamp representing the start time.
153 class TimestampedMediaByteRange : public MediaByteRange {
154 public:
155 TimestampedMediaByteRange() : MediaByteRange(), mStartTime(-1) {}
156
157 TimestampedMediaByteRange(int64_t aStart, int64_t aEnd, int64_t aStartTime)
158 : MediaByteRange(aStart, aEnd), mStartTime(aStartTime)
159 {
160 NS_ASSERTION(aStartTime >= 0, "Start time should not be negative!");
161 }
162
163 bool IsNull() const {
164 return MediaByteRange::IsNull() && mStartTime == -1;
165 }
166
167 // Clears byte range values.
168 void Clear() {
169 MediaByteRange::Clear();
170 mStartTime = -1;
171 }
172
173 // In usecs.
174 int64_t mStartTime;
175 };
176
177 inline MediaByteRange::MediaByteRange(TimestampedMediaByteRange& aByteRange)
178 : mStart(aByteRange.mStart), mEnd(aByteRange.mEnd)
179 {
180 NS_ASSERTION(mStart < mEnd, "Range should end after start!");
181 }
182
183 class RtspMediaResource;
184
185 /**
186 * Provides a thread-safe, seek/read interface to resources
187 * loaded from a URI. Uses MediaCache to cache data received over
188 * Necko's async channel API, thus resolving the mismatch between clients
189 * that need efficient random access to the data and protocols that do not
190 * support efficient random access, such as HTTP.
191 *
192 * Instances of this class must be created on the main thread.
193 * Most methods must be called on the main thread only. Read, Seek and
194 * Tell must only be called on non-main threads. In the case of the Ogg
195 * Decoder they are called on the Decode thread for example. You must
196 * ensure that no threads are calling these methods once Close is called.
197 *
198 * Instances of this class are reference counted. Use nsRefPtr for
199 * managing the lifetime of instances of this class.
200 *
201 * The generic implementation of this class is ChannelMediaResource, which can
202 * handle any URI for which Necko supports AsyncOpen.
203 * The 'file:' protocol can be implemented efficiently with direct random
204 * access, so the FileMediaResource implementation class bypasses the cache.
205 * MediaResource::Create automatically chooses the best implementation class.
206 */
207 class MediaResource : public nsISupports
208 {
209 public:
210 // Our refcounting is threadsafe, and when our refcount drops to zero
211 // we dispatch an event to the main thread to delete the MediaResource.
212 // Note that this means it's safe for references to this object to be
213 // released on a non main thread, but the destructor will always run on
214 // the main thread.
215 NS_DECL_THREADSAFE_ISUPPORTS
216
217 // The following can be called on the main thread only:
218 // Get the URI
219 virtual nsIURI* URI() const { return nullptr; }
220 // Close the resource, stop any listeners, channels, etc.
221 // Cancels any currently blocking Read request and forces that request to
222 // return an error.
223 virtual nsresult Close() = 0;
224 // Suspend any downloads that are in progress.
225 // If aCloseImmediately is set, resources should be released immediately
226 // since we don't expect to resume again any time soon. Otherwise we
227 // may resume again soon so resources should be held for a little
228 // while.
229 virtual void Suspend(bool aCloseImmediately) = 0;
230 // Resume any downloads that have been suspended.
231 virtual void Resume() = 0;
232 // Get the current principal for the channel
233 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0;
234 // If this returns false, then we shouldn't try to clone this MediaResource
235 // because its underlying resources are not suitable for reuse (e.g.
236 // because the underlying connection has been lost, or this resource
237 // just can't be safely cloned). If this returns true, CloneData could
238 // still fail. If this returns false, CloneData should not be called.
239 virtual bool CanClone() { return false; }
240 // Create a new stream of the same type that refers to the same URI
241 // with a new channel. Any cached data associated with the original
242 // stream should be accessible in the new stream too.
243 virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) = 0;
244 // Set statistics to be recorded to the object passed in.
245 virtual void RecordStatisticsTo(MediaChannelStatistics *aStatistics) { }
246
247 // These methods are called off the main thread.
248 // The mode is initially MODE_PLAYBACK.
249 virtual void SetReadMode(MediaCacheStream::ReadMode aMode) = 0;
250 // This is the client's estimate of the playback rate assuming
251 // the media plays continuously. The cache can't guess this itself
252 // because it doesn't know when the decoder was paused, buffering, etc.
253 virtual void SetPlaybackRate(uint32_t aBytesPerSecond) = 0;
254 // Read up to aCount bytes from the stream. The buffer must have
255 // enough room for at least aCount bytes. Stores the number of
256 // actual bytes read in aBytes (0 on end of file).
257 // May read less than aCount bytes if the number of
258 // available bytes is less than aCount. Always check *aBytes after
259 // read, and call again if necessary.
260 virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) = 0;
261 // Read up to aCount bytes from the stream. The read starts at
262 // aOffset in the stream, seeking to that location initially if
263 // it is not the current stream offset. The remaining arguments,
264 // results and requirements are the same as per the Read method.
265 virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
266 uint32_t aCount, uint32_t* aBytes) = 0;
267 // Seek to the given bytes offset in the stream. aWhence can be
268 // one of:
269 // NS_SEEK_SET
270 // NS_SEEK_CUR
271 // NS_SEEK_END
272 //
273 // In the Http strategy case the cancel will cause the http
274 // channel's listener to close the pipe, forcing an i/o error on any
275 // blocked read. This will allow the decode thread to complete the
276 // event.
277 //
278 // In the case of a seek in progress, the byte range request creates
279 // a new listener. This is done on the main thread via seek
280 // synchronously dispatching an event. This avoids the issue of us
281 // closing the listener but an outstanding byte range request
282 // creating a new one. They run on the same thread so no explicit
283 // synchronisation is required. The byte range request checks for
284 // the cancel flag and does not create a new channel or listener if
285 // we are cancelling.
286 //
287 // The default strategy does not do any seeking - the only issue is
288 // a blocked read which it handles by causing the listener to close
289 // the pipe, as per the http case.
290 //
291 // The file strategy doesn't block for any great length of time so
292 // is fine for a no-op cancel.
293 virtual nsresult Seek(int32_t aWhence, int64_t aOffset) = 0;
294 virtual void StartSeekingForMetadata() = 0;
295 virtual void EndSeekingForMetadata() = 0;
296 // Report the current offset in bytes from the start of the stream.
297 virtual int64_t Tell() = 0;
298 // Moves any existing channel loads into the background, so that they don't
299 // block the load event. Any new loads initiated (for example to seek)
300 // will also be in the background.
301 virtual void MoveLoadsToBackground() {}
302 // Ensures that the value returned by IsSuspendedByCache below is up to date
303 // (i.e. the cache has examined this stream at least once).
304 virtual void EnsureCacheUpToDate() {}
305
306 // These can be called on any thread.
307 // Cached blocks associated with this stream will not be evicted
308 // while the stream is pinned.
309 virtual void Pin() = 0;
310 virtual void Unpin() = 0;
311 // Get the estimated download rate in bytes per second (assuming no
312 // pausing of the channel is requested by Gecko).
313 // *aIsReliable is set to true if we think the estimate is useful.
314 virtual double GetDownloadRate(bool* aIsReliable) = 0;
315 // Get the length of the stream in bytes. Returns -1 if not known.
316 // This can change over time; after a seek operation, a misbehaving
317 // server may give us a resource of a different length to what it had
318 // reported previously --- or it may just lie in its Content-Length
319 // header and give us more or less data than it reported. We will adjust
320 // the result of GetLength to reflect the data that's actually arriving.
321 virtual int64_t GetLength() = 0;
322 // Returns the offset of the first byte of cached data at or after aOffset,
323 // or -1 if there is no such cached data.
324 virtual int64_t GetNextCachedData(int64_t aOffset) = 0;
325 // Returns the end of the bytes starting at the given offset
326 // which are in cache.
327 virtual int64_t GetCachedDataEnd(int64_t aOffset) = 0;
328 // Returns true if all the data from aOffset to the end of the stream
329 // is in cache. If the end of the stream is not known, we return false.
330 virtual bool IsDataCachedToEndOfResource(int64_t aOffset) = 0;
331 // Returns true if this stream is suspended by the cache because the
332 // cache is full. If true then the decoder should try to start consuming
333 // data, otherwise we may not be able to make progress.
334 // MediaDecoder::NotifySuspendedStatusChanged is called when this
335 // changes.
336 // For resources using the media cache, this returns true only when all
337 // streams for the same resource are all suspended.
338 virtual bool IsSuspendedByCache() = 0;
339 // Returns true if this stream has been suspended.
340 virtual bool IsSuspended() = 0;
341 // Reads only data which is cached in the media cache. If you try to read
342 // any data which overlaps uncached data, or if aCount bytes otherwise can't
343 // be read, this function will return failure. This function be called from
344 // any thread, and it is the only read operation which is safe to call on
345 // the main thread, since it's guaranteed to be non blocking.
346 virtual nsresult ReadFromCache(char* aBuffer,
347 int64_t aOffset,
348 uint32_t aCount) = 0;
349 // Returns true if the resource can be seeked to unbuffered ranges, i.e.
350 // for an HTTP network stream this returns true if HTTP1.1 Byte Range
351 // requests are supported by the connection/server.
352 virtual bool IsTransportSeekable() = 0;
353
354 /**
355 * Create a resource, reading data from the channel. Call on main thread only.
356 * The caller must follow up by calling resource->Open().
357 */
358 static already_AddRefed<MediaResource> Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
359
360 /**
361 * Open the stream. This creates a stream listener and returns it in
362 * aStreamListener; this listener needs to be notified of incoming data.
363 */
364 virtual nsresult Open(nsIStreamListener** aStreamListener) = 0;
365
366 /**
367 * Fills aRanges with MediaByteRanges representing the data which is cached
368 * in the media cache. Stream should be pinned during call and while
369 * aRanges is being used.
370 */
371 virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) = 0;
372
373 // Ensure that the media cache writes any data held in its partial block.
374 // Called on the main thread only.
375 virtual void FlushCache() { }
376
377 // Notify that the last data byte range was loaded.
378 virtual void NotifyLastByteRange() { }
379
380 // Returns the content type of the resource. This is copied from the
381 // nsIChannel when the MediaResource is created. Safe to call from
382 // any thread.
383 virtual const nsCString& GetContentType() const = 0;
384
385 // Get the RtspMediaResource pointer if this MediaResource really is a
386 // RtspMediaResource. For calling Rtsp specific functions.
387 virtual RtspMediaResource* GetRtspPointer() {
388 return nullptr;
389 }
390
391 // Return true if the stream is a live stream
392 virtual bool IsRealTime() {
393 return false;
394 }
395
396 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
397 return 0;
398 }
399
400 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
401 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
402 }
403
404 protected:
405 virtual ~MediaResource() {};
406
407 private:
408 void Destroy();
409 };
410
411 class BaseMediaResource : public MediaResource {
412 public:
413 virtual nsIURI* URI() const { return mURI; }
414 virtual void MoveLoadsToBackground();
415
416 virtual size_t SizeOfExcludingThis(
417 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
418 {
419 // Might be useful to track in the future:
420 // - mChannel
421 // - mURI (possibly owned, looks like just a ref from mChannel)
422 // Not owned:
423 // - mDecoder
424 size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
425 size += mContentType.SizeOfIncludingThisIfUnshared(aMallocSizeOf);
426
427 return size;
428 }
429
430 virtual size_t SizeOfIncludingThis(
431 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
432 {
433 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
434 }
435
436 protected:
437 BaseMediaResource(MediaDecoder* aDecoder,
438 nsIChannel* aChannel,
439 nsIURI* aURI,
440 const nsACString& aContentType) :
441 mDecoder(aDecoder),
442 mChannel(aChannel),
443 mURI(aURI),
444 mContentType(aContentType),
445 mLoadInBackground(false)
446 {
447 MOZ_COUNT_CTOR(BaseMediaResource);
448 NS_ASSERTION(!mContentType.IsEmpty(), "Must know content type");
449 }
450 virtual ~BaseMediaResource()
451 {
452 MOZ_COUNT_DTOR(BaseMediaResource);
453 }
454
455 virtual const nsCString& GetContentType() const MOZ_OVERRIDE
456 {
457 return mContentType;
458 }
459
460 // Set the request's load flags to aFlags. If the request is part of a
461 // load group, the request is removed from the group, the flags are set, and
462 // then the request is added back to the load group.
463 void ModifyLoadFlags(nsLoadFlags aFlags);
464
465 // Dispatches an event to call MediaDecoder::NotifyBytesConsumed(aNumBytes, aOffset)
466 // on the main thread. This is called automatically after every read.
467 void DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset);
468
469 // This is not an nsCOMPointer to prevent a circular reference
470 // between the decoder to the media stream object. The stream never
471 // outlives the lifetime of the decoder.
472 MediaDecoder* mDecoder;
473
474 // Channel used to download the media data. Must be accessed
475 // from the main thread only.
476 nsCOMPtr<nsIChannel> mChannel;
477
478 // URI in case the stream needs to be re-opened. Access from
479 // main thread only.
480 nsCOMPtr<nsIURI> mURI;
481
482 // Content-Type of the channel. This is copied from the nsIChannel when the
483 // MediaResource is created. This is constant, so accessing from any thread
484 // is safe.
485 const nsAutoCString mContentType;
486
487 // True if MoveLoadsToBackground() has been called, i.e. the load event
488 // has been fired, and all channel loads will be in the background.
489 bool mLoadInBackground;
490 };
491
492 /**
493 * This is the MediaResource implementation that wraps Necko channels.
494 * Much of its functionality is actually delegated to MediaCache via
495 * an underlying MediaCacheStream.
496 *
497 * All synchronization is performed by MediaCacheStream; all off-main-
498 * thread operations are delegated directly to that object.
499 */
500 class ChannelMediaResource : public BaseMediaResource
501 {
502 public:
503 ChannelMediaResource(MediaDecoder* aDecoder,
504 nsIChannel* aChannel,
505 nsIURI* aURI,
506 const nsACString& aContentType);
507 ~ChannelMediaResource();
508
509 // These are called on the main thread by MediaCache. These must
510 // not block or grab locks, because the media cache is holding its lock.
511 // Notify that data is available from the cache. This can happen even
512 // if this stream didn't read any data, since another stream might have
513 // received data for the same resource.
514 void CacheClientNotifyDataReceived();
515 // Notify that we reached the end of the stream. This can happen even
516 // if this stream didn't read any data, since another stream might have
517 // received data for the same resource.
518 void CacheClientNotifyDataEnded(nsresult aStatus);
519 // Notify that the principal for the cached resource changed.
520 void CacheClientNotifyPrincipalChanged();
521
522 // These are called on the main thread by MediaCache. These shouldn't block,
523 // but they may grab locks --- the media cache is not holding its lock
524 // when these are called.
525 // Start a new load at the given aOffset. The old load is cancelled
526 // and no more data from the old load will be notified via
527 // MediaCacheStream::NotifyDataReceived/Ended.
528 // This can fail.
529 nsresult CacheClientSeek(int64_t aOffset, bool aResume);
530 // Suspend the current load since data is currently not wanted
531 nsresult CacheClientSuspend();
532 // Resume the current load since data is wanted again
533 nsresult CacheClientResume();
534
535 // Ensure that the media cache writes any data held in its partial block.
536 // Called on the main thread.
537 virtual void FlushCache() MOZ_OVERRIDE;
538
539 // Notify that the last data byte range was loaded.
540 virtual void NotifyLastByteRange() MOZ_OVERRIDE;
541
542 // Main thread
543 virtual nsresult Open(nsIStreamListener** aStreamListener);
544 virtual nsresult Close();
545 virtual void Suspend(bool aCloseImmediately);
546 virtual void Resume();
547 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
548 // Return true if the stream has been closed.
549 bool IsClosed() const { return mCacheStream.IsClosed(); }
550 virtual bool CanClone();
551 virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
552 // Set statistics to be recorded to the object passed in. If not called,
553 // |ChannelMediaResource| will create it's own statistics objects in |Open|.
554 void RecordStatisticsTo(MediaChannelStatistics *aStatistics) MOZ_OVERRIDE {
555 NS_ASSERTION(aStatistics, "Statistics param cannot be null!");
556 MutexAutoLock lock(mLock);
557 if (!mChannelStatistics) {
558 mChannelStatistics = aStatistics;
559 }
560 }
561 virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
562 virtual void EnsureCacheUpToDate();
563
564 // Other thread
565 virtual void SetReadMode(MediaCacheStream::ReadMode aMode);
566 virtual void SetPlaybackRate(uint32_t aBytesPerSecond);
567 virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
568 virtual nsresult ReadAt(int64_t offset, char* aBuffer,
569 uint32_t aCount, uint32_t* aBytes);
570 virtual nsresult Seek(int32_t aWhence, int64_t aOffset);
571 virtual void StartSeekingForMetadata();
572 virtual void EndSeekingForMetadata();
573 virtual int64_t Tell();
574
575 // Any thread
576 virtual void Pin();
577 virtual void Unpin();
578 virtual double GetDownloadRate(bool* aIsReliable);
579 virtual int64_t GetLength();
580 virtual int64_t GetNextCachedData(int64_t aOffset);
581 virtual int64_t GetCachedDataEnd(int64_t aOffset);
582 virtual bool IsDataCachedToEndOfResource(int64_t aOffset);
583 virtual bool IsSuspendedByCache();
584 virtual bool IsSuspended();
585 virtual bool IsTransportSeekable() MOZ_OVERRIDE;
586
587 virtual size_t SizeOfExcludingThis(
588 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
589 // Might be useful to track in the future:
590 // - mListener (seems minor)
591 // - mChannelStatistics (seems minor)
592 // owned if RecordStatisticsTo is not called
593 // - mDataReceivedEvent (seems minor)
594 size_t size = BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
595 size += mCacheStream.SizeOfExcludingThis(aMallocSizeOf);
596
597 return size;
598 }
599
600 virtual size_t SizeOfIncludingThis(
601 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
602 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
603 }
604
605 class Listener MOZ_FINAL : public nsIStreamListener,
606 public nsIInterfaceRequestor,
607 public nsIChannelEventSink
608 {
609 public:
610 Listener(ChannelMediaResource* aResource) : mResource(aResource) {}
611 ~Listener() {}
612
613 NS_DECL_ISUPPORTS
614 NS_DECL_NSIREQUESTOBSERVER
615 NS_DECL_NSISTREAMLISTENER
616 NS_DECL_NSICHANNELEVENTSINK
617 NS_DECL_NSIINTERFACEREQUESTOR
618
619 void Revoke() { mResource = nullptr; }
620
621 private:
622 nsRefPtr<ChannelMediaResource> mResource;
623 };
624 friend class Listener;
625
626 nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
627
628 protected:
629 // These are called on the main thread by Listener.
630 nsresult OnStartRequest(nsIRequest* aRequest);
631 nsresult OnStopRequest(nsIRequest* aRequest, nsresult aStatus);
632 nsresult OnDataAvailable(nsIRequest* aRequest,
633 nsIInputStream* aStream,
634 uint32_t aCount);
635 nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, uint32_t aFlags);
636
637 // Opens the channel, using an HTTP byte range request to start at mOffset
638 // if possible. Main thread only.
639 nsresult OpenChannel(nsIStreamListener** aStreamListener);
640 nsresult RecreateChannel();
641 // Add headers to HTTP request. Main thread only.
642 void SetupChannelHeaders();
643 // Closes the channel. Main thread only.
644 void CloseChannel();
645
646 // Parses 'Content-Range' header and returns results via parameters.
647 // Returns error if header is not available, values are not parse-able or
648 // values are out of range.
649 nsresult ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
650 int64_t& aRangeStart,
651 int64_t& aRangeEnd,
652 int64_t& aRangeTotal);
653
654 void DoNotifyDataReceived();
655
656 static NS_METHOD CopySegmentToCache(nsIInputStream *aInStream,
657 void *aClosure,
658 const char *aFromSegment,
659 uint32_t aToOffset,
660 uint32_t aCount,
661 uint32_t *aWriteCount);
662
663 // Suspend the channel only if the channels is currently downloading data.
664 // If it isn't we set a flag, mIgnoreResume, so that PossiblyResume knows
665 // whether to acutually resume or not.
666 void PossiblySuspend();
667
668 // Resume from a suspend if we actually suspended (See PossiblySuspend).
669 void PossiblyResume();
670
671 // Main thread access only
672 int64_t mOffset;
673 nsRefPtr<Listener> mListener;
674 // A data received event for the decoder that has been dispatched but has
675 // not yet been processed.
676 nsRevocableEventPtr<nsRunnableMethod<ChannelMediaResource, void, false> > mDataReceivedEvent;
677 uint32_t mSuspendCount;
678 // When this flag is set, if we get a network error we should silently
679 // reopen the stream.
680 bool mReopenOnError;
681 // When this flag is set, we should not report the next close of the
682 // channel.
683 bool mIgnoreClose;
684
685 // Any thread access
686 MediaCacheStream mCacheStream;
687
688 // This lock protects mChannelStatistics
689 Mutex mLock;
690 nsRefPtr<MediaChannelStatistics> mChannelStatistics;
691
692 // True if we couldn't suspend the stream and we therefore don't want
693 // to resume later. This is usually due to the channel not being in the
694 // isPending state at the time of the suspend request.
695 bool mIgnoreResume;
696
697 // True if we are seeking to get the real duration of the file.
698 bool mSeekingForMetadata;
699
700 // Start and end offset of the bytes to be requested.
701 MediaByteRange mByteRange;
702
703 // True if the stream can seek into unbuffered ranged, i.e. if the
704 // connection supports byte range requests.
705 bool mIsTransportSeekable;
706 };
707
708 } // namespace mozilla
709
710 #endif

mercurial