Bug 928765 - Create MediaDecoderReader::GetBuffered() base implementation that estimates buffered ranges, so that subclasses do have to keep reimplementing the estimation. r=doublec
authorChris Pearce <cpearce@mozilla.com>
Mon, 21 Oct 2013 16:31:05 +1300
changeset 165299 23c23b472a4f73cef13cbd0c9a160402e840b456
parent 165298 b24213ae8b6818dbf06a825ab952b09333d112f0
child 165301 c6fc35c53c3726c452bcb8b220234be031bfdca1
child 165302 230b8bcc394d3c0c7815b2abc29b3d3fc544c16b
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs928765
milestone27.0a1
first release with
nightly linux32
23c23b472a4f / 27.0a1 / 20131021030203 / files
nightly linux64
23c23b472a4f / 27.0a1 / 20131021030203 / files
nightly mac
23c23b472a4f / 27.0a1 / 20131021030203 / files
nightly win32
23c23b472a4f / 27.0a1 / 20131021030203 / files
nightly win64
23c23b472a4f / 27.0a1 / 20131021030203 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 928765 - Create MediaDecoderReader::GetBuffered() base implementation that estimates buffered ranges, so that subclasses do have to keep reimplementing the estimation. r=doublec
content/media/MediaDecoderReader.cpp
content/media/MediaDecoderReader.h
content/media/apple/AppleMP3Reader.cpp
content/media/apple/AppleMP3Reader.h
content/media/directshow/DirectShowReader.cpp
content/media/directshow/DirectShowReader.h
content/media/ogg/OggReader.cpp
content/media/plugins/MediaPluginReader.cpp
content/media/plugins/MediaPluginReader.h
content/media/wmf/WMFReader.cpp
content/media/wmf/WMFReader.h
--- a/content/media/MediaDecoderReader.cpp
+++ b/content/media/MediaDecoderReader.cpp
@@ -597,10 +597,24 @@ nsresult MediaDecoderReader::DecodeToTar
     }
   }
 
   LOG(PR_LOG_DEBUG, ("MediaDecoderReader::DecodeToTarget(%lld) End", aTarget));
 
   return NS_OK;
 }
 
+nsresult
+MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
+                                int64_t aStartTime)
+{
+  MediaResource* stream = mDecoder->GetResource();
+  int64_t durationUs = 0;
+  {
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    durationUs = mDecoder->GetMediaDuration();
+  }
+  GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
+  return NS_OK;
+}
+
 } // namespace mozilla
 
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -520,19 +520,31 @@ protected:
   // Queue of video frames. This queue is threadsafe, and is accessed from
   // the decoder, state machine, and main threads.
   MediaQueue<VideoData> mVideoQueue;
 
 public:
   // Populates aBuffered with the time ranges which are buffered. aStartTime
   // must be the presentation time of the first frame in the media, e.g.
   // the media time corresponding to playback time/position 0. This function
-  // should only be called on the main thread.
+  // is called on the main, decode, and state machine threads.
+  //
+  // This base implementation in MediaDecoderReader estimates the time ranges
+  // buffered by interpolating the cached byte ranges with the duration
+  // of the media. Reader subclasses should override this method if they
+  // can quickly calculate the buffered ranges more accurately.
+  //
+  // The primary advantage of this implementation in the reader base class
+  // is that it's a fast approximation, which does not perform any I/O.
+  //
+  // The OggReader relies on this base implementation not performing I/O,
+  // since in FirefoxOS we can't do I/O on the main thread, where this is
+  // called.
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
-                               int64_t aStartTime) = 0;
+                               int64_t aStartTime);
 
   class VideoQueueMemoryFunctor : public nsDequeFunctor {
   public:
     VideoQueueMemoryFunctor() : mResult(0) {}
 
     virtual void* operator()(void* anObject);
 
     int64_t mResult;
--- a/content/media/apple/AppleMP3Reader.cpp
+++ b/content/media/apple/AppleMP3Reader.cpp
@@ -510,21 +510,9 @@ AppleMP3Reader::Seek(int64_t aTime,
 
   mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, byteOffset);
 
   ResetDecode();
 
   return NS_OK;
 }
 
-
-nsresult
-AppleMP3Reader::GetBuffered(dom::TimeRanges* aBuffered,
-                            int64_t aStartTime)
-{
-  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  GetEstimatedBufferedTimeRanges(mDecoder->GetResource(),
-                                 mDecoder->GetMediaDuration(),
-                                 aBuffered);
-  return NS_OK;
-}
-
 } // namespace mozilla
--- a/content/media/apple/AppleMP3Reader.h
+++ b/content/media/apple/AppleMP3Reader.h
@@ -33,19 +33,16 @@ public:
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags) MOZ_OVERRIDE;
 
   virtual nsresult Seek(int64_t aTime,
                         int64_t aStartTime,
                         int64_t aEndTime,
                         int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
-                               int64_t aStartTime) MOZ_OVERRIDE;
-
   void AudioSampleCallback(UInt32 aNumBytes,
                            UInt32 aNumPackets,
                            const void *aData,
                            AudioStreamPacketDescription *aPackets);
 
   void AudioMetadataCallback(AudioFileStreamID aFileStream,
                              AudioFileStreamPropertyID aPropertyID,
                              UInt32 *aFlags);
--- a/content/media/directshow/DirectShowReader.cpp
+++ b/content/media/directshow/DirectShowReader.cpp
@@ -326,30 +326,16 @@ DirectShowReader::Seek(int64_t aTargetUs
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   hr = mControl->Run();
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   return DecodeToTarget(aTargetUs);
 }
 
-nsresult
-DirectShowReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
-                              int64_t aStartTime)
-{
-  MediaResource* stream = mDecoder->GetResource();
-  int64_t durationUs = 0;
-  {
-    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-    durationUs = mDecoder->GetMediaDuration();
-  }
-  GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
-  return NS_OK;
-}
-
 void
 DirectShowReader::OnDecodeThreadStart()
 {
   MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
   NS_ENSURE_TRUE_VOID(SUCCEEDED(hr));
 }
 
--- a/content/media/directshow/DirectShowReader.h
+++ b/content/media/directshow/DirectShowReader.h
@@ -60,19 +60,16 @@ public:
   nsresult ReadMetadata(MediaInfo* aInfo,
                         MetadataTags** aTags) MOZ_OVERRIDE;
 
   nsresult Seek(int64_t aTime,
                 int64_t aStartTime,
                 int64_t aEndTime,
                 int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered,
-                       int64_t aStartTime) MOZ_OVERRIDE;
-
   void OnDecodeThreadStart() MOZ_OVERRIDE;
   void OnDecodeThreadFinish() MOZ_OVERRIDE;
 
   void NotifyDataArrived(const char* aBuffer,
                          uint32_t aLength,
                          int64_t aOffset) MOZ_OVERRIDE;
 
 private:
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -1750,25 +1750,17 @@ nsresult OggReader::SeekBisection(int64_
 nsresult OggReader::GetBuffered(TimeRanges* aBuffered, int64_t aStartTime)
 {
   {
     mozilla::ReentrantMonitorAutoEnter mon(mMonitor);
     if (mIsChained)
       return NS_ERROR_FAILURE;
   }
 #ifdef OGG_ESTIMATE_BUFFERED
-  MediaResource* stream = mDecoder->GetResource();
-  int64_t durationUs = 0;
-  {
-    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-    durationUs = mDecoder->GetMediaDuration();
-  }
-  GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
-
-  return NS_OK;
+  return MediaDecoderReader::GetBuffered(aBuffered, aStartTime);
 #else
   // HasAudio and HasVideo are not used here as they take a lock and cause
   // a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
   // after metadata is read.
   if (!mInfo.HasValidMedia()) {
     // No need to search through the file if there are no audio or video tracks
     return NS_OK;
   }
--- a/content/media/plugins/MediaPluginReader.cpp
+++ b/content/media/plugins/MediaPluginReader.cpp
@@ -324,31 +324,16 @@ nsresult MediaPluginReader::Seek(int64_t
   mVideoQueue.Erase();
   mAudioQueue.Erase();
 
   mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
 
   return DecodeToTarget(aTarget);
 }
 
-nsresult MediaPluginReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime)
-{
-  if (!mPlugin)
-    return NS_OK;
-
-  MediaResource* stream = mDecoder->GetResource();
-
-  int64_t durationUs = 0;
-  mPlugin->GetDuration(mPlugin, &durationUs);
-
-  GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
-  
-  return NS_OK;
-}
-
 MediaPluginReader::ImageBufferCallback::ImageBufferCallback(mozilla::layers::ImageContainer *aImageContainer) :
   mImageContainer(aImageContainer)
 {
 }
 
 void *
 MediaPluginReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeight,
                                                      MPAPI::ColorFormat aColorFormat)
--- a/content/media/plugins/MediaPluginReader.h
+++ b/content/media/plugins/MediaPluginReader.h
@@ -59,17 +59,16 @@ public:
   virtual bool HasVideo()
   {
     return mHasVideo;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
-  virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime);
   class ImageBufferCallback : public MPAPI::BufferCallback {
     typedef mozilla::layers::Image Image;
   public:
     ImageBufferCallback(mozilla::layers::ImageContainer *aImageContainer);
     void *operator()(size_t aWidth, size_t aHeight,
                      MPAPI::ColorFormat aColorFormat) MOZ_OVERRIDE;
     already_AddRefed<Image> GetImage();
   private:
--- a/content/media/wmf/WMFReader.cpp
+++ b/content/media/wmf/WMFReader.cpp
@@ -1023,22 +1023,9 @@ WMFReader::Seek(int64_t aTargetUs,
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   hr = mSourceReader->SetCurrentPosition(GUID_NULL, var);
   NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
 
   return DecodeToTarget(aTargetUs);
 }
 
-nsresult
-WMFReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime)
-{
-  MediaResource* stream = mDecoder->GetResource();
-  int64_t durationUs = 0;
-  {
-    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-    durationUs = mDecoder->GetMediaDuration();
-  }
-  GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
-  return NS_OK;
-}
-
 } // namespace mozilla
--- a/content/media/wmf/WMFReader.h
+++ b/content/media/wmf/WMFReader.h
@@ -43,19 +43,16 @@ public:
   nsresult ReadMetadata(MediaInfo* aInfo,
                         MetadataTags** aTags) MOZ_OVERRIDE;
 
   nsresult Seek(int64_t aTime,
                 int64_t aStartTime,
                 int64_t aEndTime,
                 int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered,
-                       int64_t aStartTime) MOZ_OVERRIDE;
-
   void OnDecodeThreadStart() MOZ_OVERRIDE;
   void OnDecodeThreadFinish() MOZ_OVERRIDE;
 
 private:
 
   HRESULT ConfigureAudioDecoder();
   HRESULT ConfigureVideoDecoder();
   HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType);