Bug 945085 - Improve comments in PlatformDecoderModule.h. r=kinetik
authorChris Pearce <cpearce@mozilla.com>
Wed, 04 Dec 2013 13:47:12 +1300
changeset 174341 4531393b5af60091a724103e26a5d338180b83f1
parent 174340 b96d513cd89f5aff1841c6a6c926481807864589
child 174342 ccb5e249ab111dfaf81f75c9b3e618c2d8bf36ab
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs945085
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 945085 - Improve comments in PlatformDecoderModule.h. r=kinetik Adds comments to PlatformDecoderModule.h, and describes the call model better. Renames CreateAudioDecoder and CreateVideoDecoder to CreateAACDecoder and CreateH264Decoder. We may change them to accept a codec parameter and have more general names in future when we need to support more codecs here.
content/media/fmp4/BlankDecoderModule.cpp
content/media/fmp4/MP4Reader.cpp
content/media/fmp4/PlatformDecoderModule.cpp
content/media/fmp4/PlatformDecoderModule.h
content/media/fmp4/wmf/WMFDecoderModule.cpp
content/media/fmp4/wmf/WMFDecoderModule.h
--- a/content/media/fmp4/BlankDecoderModule.cpp
+++ b/content/media/fmp4/BlankDecoderModule.cpp
@@ -193,28 +193,28 @@ class BlankDecoderModule : public Platfo
 public:
 
   // Called when the decoders have shutdown. Main thread only.
   virtual nsresult Shutdown() MOZ_OVERRIDE {
     return NS_OK;
   }
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateVideoDecoder(layers::LayersBackend aLayersBackend,
-                                               layers::ImageContainer* aImageContainer) MOZ_OVERRIDE {
+  virtual MediaDataDecoder* CreateH264Decoder(layers::LayersBackend aLayersBackend,
+                                              layers::ImageContainer* aImageContainer) MOZ_OVERRIDE {
     BlankVideoDataCreator* decoder = new BlankVideoDataCreator(aImageContainer);
     return new BlankMediaDataDecoder<BlankVideoDataCreator>(decoder);
   }
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateAudioDecoder(uint32_t aChannelCount,
-                                               uint32_t aSampleRate,
-                                               uint16_t aBitsPerSample,
-                                               const uint8_t* aUserData,
-                                               uint32_t aUserDataLength) MOZ_OVERRIDE {
+  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
+                                             uint32_t aSampleRate,
+                                             uint16_t aBitsPerSample,
+                                             const uint8_t* aUserData,
+                                             uint32_t aUserDataLength) MOZ_OVERRIDE {
     BlankAudioDataCreator* decoder = new BlankAudioDataCreator(aChannelCount,
                                                                aSampleRate,
                                                                aBitsPerSample);
     return new BlankMediaDataDecoder<BlankAudioDataCreator>(decoder);
   }
 };
 
 PlatformDecoderModule* CreateBlankDecoderModule()
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -155,31 +155,31 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
   // If we have video, we *only* allow H.264 to be decoded.
   if (mHasVideo && video.codec() != kCodecH264) {
     return NS_ERROR_FAILURE;
   }
 
   if (mHasAudio) {
     mInfo.mAudio.mRate = audio.samples_per_second();
     mInfo.mAudio.mChannels = ChannelLayoutToChannelCount(audio.channel_layout());
-    mAudioDecoder = mPlatform->CreateAudioDecoder(mInfo.mAudio.mChannels,
-                                                  mInfo.mAudio.mRate,
-                                                  audio.bits_per_channel(),
-                                                  audio.extra_data(),
-                                                  audio.extra_data_size());
+    mAudioDecoder = mPlatform->CreateAACDecoder(mInfo.mAudio.mChannels,
+                                                mInfo.mAudio.mRate,
+                                                audio.bits_per_channel(),
+                                                audio.extra_data(),
+                                                audio.extra_data_size());
     NS_ENSURE_TRUE(mAudioDecoder != nullptr, NS_ERROR_FAILURE);
   }
 
   mInfo.mVideo.mHasVideo = mHasVideo = mDemuxer->HasVideo();
   if (mHasVideo) {
     const VideoDecoderConfig& config = mDemuxer->VideoConfig();
     IntSize sz = config.natural_size();
     mInfo.mVideo.mDisplay = nsIntSize(sz.width(), sz.height());
-    mVideoDecoder = mPlatform->CreateVideoDecoder(mLayersBackendType,
-                                                  mDecoder->GetImageContainer());
+    mVideoDecoder = mPlatform->CreateH264Decoder(mLayersBackendType,
+                                                 mDecoder->GetImageContainer());
     NS_ENSURE_TRUE(mVideoDecoder != nullptr, NS_ERROR_FAILURE);
   }
 
   // Get the duration, and report it to the decoder if we have it.
   Microseconds duration = mDemuxer->Duration();
   if (duration != -1) {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mDecoder->SetMediaDuration(duration);
--- a/content/media/fmp4/PlatformDecoderModule.cpp
+++ b/content/media/fmp4/PlatformDecoderModule.cpp
@@ -25,19 +25,9 @@ PlatformDecoderModule::Create()
   nsAutoPtr<WMFDecoderModule> m(new WMFDecoderModule());
   if (NS_SUCCEEDED(m->Init())) {
     return m.forget();
   }
 #endif
   return nullptr;
 }
 
-void
-PlatformDecoderModule::OnDecodeThreadStart()
-{
-}
-
-void
-PlatformDecoderModule::OnDecodeThreadFinish()
-{
-}
-
 } // namespace mozilla
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -11,74 +11,150 @@
 #include "mozilla/layers/LayersTypes.h"
 
 namespace mozilla {
 
 namespace layers {
 class ImageContainer;
 }
 
+class MediaDataDecoder;
 typedef int64_t Microseconds;
 
+// The PlatformDecoderModule interface is used by the MP4Reader to abstract
+// access to the H264 and AAC decoders provided by various platforms. It
+// may be extended to support other codecs in future. Each platform (Windows,
+// MacOSX, Linux etc) must implement a PlatformDecoderModule to provide access
+// to its decoders in order to get decompressed H.264/AAC from the MP4Reader.
+//
+// Platforms that don't have a corresponding PlatformDecoderModule won't be
+// able to play the H.264/AAC data output by the MP4Reader. In practice this
+// means that we won't have fragmented MP4 supported in Media Source
+// Extensions on platforms without PlatformDecoderModules.
+//
+// A cross-platform decoder module that discards input and produces "blank"
+// output samples exists for testing, and is created if the pref
+// "media.fragmented-mp4.use-blank-decoder" is true.
+class PlatformDecoderModule {
+public:
+
+  // Factory method that creates the appropriate PlatformDecoderModule for
+  // the platform we're running on. Caller is responsible for deleting this
+  // instance. It's expected that there will be multiple
+  // PlatformDecoderModules alive at the same time. There is one
+  // PlatformDecoderModule's created per MP4Reader.
+  // This is called on the main thread.
+  static PlatformDecoderModule* Create();
+
+  // Called to shutdown the decoder module and cleanup state. This should
+  // block until shutdown is complete. This is called after Shutdown() has
+  // been called on all MediaDataDecoders created from this
+  // PlatformDecoderModule.
+  // Called on the main thread only.
+  virtual nsresult Shutdown() = 0;
+
+  // Creates and initializes an H.264 decoder. The layers backend is
+  // passed in so that decoders can determine whether hardware accelerated
+  // decoding can be used. Returns nullptr if the decoder can't be
+  // initialized.
+  // Called on decode thread.
+  virtual MediaDataDecoder* CreateH264Decoder(layers::LayersBackend aLayersBackend,
+                                              layers::ImageContainer* aImageContainer) = 0;
+
+  // Creates and initializes an AAC decoder with the specified properties.
+  // The raw AAC AudioSpecificConfig as contained in the esds box. Some
+  // decoders need that to initialize. The caller owns the AAC config,
+  // so it must be copied if it is to be retained by the decoder.
+  // Returns nullptr if the decoder can't be initialized.
+  // Called on decode thread.
+  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
+                                             uint32_t aSampleRate,
+                                             uint16_t aBitsPerSample,
+                                             const uint8_t* aAACConfig,
+                                             uint32_t aAACConfigLength) = 0;
+
+  // Called when a decode thread is started. Called on decode thread.
+  virtual void OnDecodeThreadStart() {}
+
+  // Called just before a decode thread is finishing. Called on decode thread.
+  virtual void OnDecodeThreadFinish() {}
+
+  virtual ~PlatformDecoderModule() {}
+protected:
+  PlatformDecoderModule() {}
+};
+
+// Return value of the MediaDataDecoder functions.
 enum DecoderStatus {
-  DECODE_STATUS_NOT_ACCEPTING, // Can't accept input at this time.
-  DECODE_STATUS_NEED_MORE_INPUT, // Nothing in pipeline to produce output with at this time.
+  DECODE_STATUS_NOT_ACCEPTING, // Can't accept input at this time. Decoder can produce output.
+  DECODE_STATUS_NEED_MORE_INPUT, // Can't produce output. Decoder can accept input.
   DECODE_STATUS_OK,
   DECODE_STATUS_ERROR
 };
 
+// MediaDataDecoder is the interface exposed by decoders created by the
+// PlatformDecoderModule's Create*Decoder() functions. The type of
+// media data that the decoder accepts as valid input and produces as
+// output is determined when the MediaDataDecoder is created.
+// The decoder is assumed to be in one of three mutually exclusive and
+// implicit states: able to accept input, able to produce output, and
+// shutdown. The decoder is assumed to be able to accept input by the time
+// that it's returned by PlatformDecoderModule::Create*Decoder().
 class MediaDataDecoder {
 public:
   virtual ~MediaDataDecoder() {};
 
-  virtual nsresult Shutdown() = 0;
-
-  // Returns true if future decodes may produce output, or false
-  // on end of segment.
-  // Inserts data into the decoder's pipeline.
+  // Inserts aData into the decoding pipeline. Decoding may begin
+  // asynchronously. The caller owns aData, so it may need to be copied.
+  // The MP4Reader calls Input() with new input in a loop until Input()
+  // stops returning DECODE_STATUS_OK.
+  // Called on the media decode thread.
+  // Returns:
+  //  - DECODE_STATUS_OK if input was successfully inserted into
+  //    the decode pipeline.
+  //  - DECODE_STATUS_NOT_ACCEPTING if the decoder cannot accept any input
+  //    at this time. The MP4Reader will assume that the decoder can now
+  //    produce one or more output samples, and call the Output() function.
+  //    The MP4Reader will call Input() again with the same data later,
+  //    after the decoder's Output() function has stopped producing output.
+  //  - DECODE_STATUS_ERROR if the decoder has been shutdown, or some
+  //    unspecified error.
+  // This function should not return DECODE_STATUS_NEED_MORE_INPUT.
   virtual DecoderStatus Input(const uint8_t* aData,
                               uint32_t aLength,
                               Microseconds aDTS,
                               Microseconds aPTS,
                               int64_t aOffsetInStream) = 0;
 
-  // Blocks until decoded sample is produced by the deoder.
+  // Blocks until a decoded sample is produced by the deoder. The MP4Reader
+  // calls this until it stops returning DECODE_STATUS_OK.
+  // Called on the media decode thread.
+  // Returns:
+  //  - DECODE_STATUS_OK if an output sample was successfully placed in
+  //    aOutData. More samples for output may still be available, the
+  //    MP4Reader will call again to check.
+  //  - DECODE_STATUS_NEED_MORE_INPUT if the decoder needs more input to
+  //    produce a sample. The decoder should return this once it can no
+  //    longer produce output. This signals to the MP4Reader that it should
+  //    start feeding in data via the Input() function.
+  //  - DECODE_STATUS_ERROR if the decoder has been shutdown, or some
+  //    unspecified error.
+  // This function should not return DECODE_STATUS_NOT_ACCEPTING.
   virtual DecoderStatus Output(nsAutoPtr<MediaData>& aOutData) = 0;
 
+  // Causes all samples in the decoding pipeline to be discarded. When
+  // this function returns, the decoder must be ready to accept new input
+  // for decoding. This function is called when the demuxer seeks, before
+  // decoding resumes after the seek.
+  // Called on the media decode thread.
   virtual DecoderStatus Flush() = 0;
-};
-
-class PlatformDecoderModule {
-public:
 
-  // Creates the appropriate PlatformDecoderModule for this platform.
-  // Caller is responsible for deleting this instance. It's safe to have
-  // multiple PlatformDecoderModules alive at the same time.
-  // There is one PlatformDecoderModule's created per media decoder.
-  static PlatformDecoderModule* Create();
-
-  // Called when the decoders have shutdown. Main thread only.
+  // Cancels all decode operations, and shuts down the decoder. This should
+  // block until shutdown is complete. The decoder should return
+  // DECODE_STATUS_ERROR for all calls to its functions once this is called.
+  // Called on main thread.
   virtual nsresult Shutdown() = 0;
 
-  // TODO: Parameters for codec type.
-  // Decode thread.
-  virtual MediaDataDecoder* CreateVideoDecoder(layers::LayersBackend aLayersBackend,
-                                               layers::ImageContainer* aImageContainer) = 0;
-
-  // Decode thread.
-  virtual MediaDataDecoder* CreateAudioDecoder(uint32_t aChannelCount,
-                                               uint32_t aSampleRate,
-                                               uint16_t aBitsPerSample,
-                                               const uint8_t* aUserData,
-                                               uint32_t aUserDataLength) = 0;
-
-  // Platform decoders can override these. Base implementation does nothing.
-  virtual void OnDecodeThreadStart();
-  virtual void OnDecodeThreadFinish();
-
-  virtual ~PlatformDecoderModule() {}
-protected:
-  PlatformDecoderModule() {}
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/fmp4/wmf/WMFDecoderModule.cpp
+++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp
@@ -51,31 +51,31 @@ WMFDecoderModule::Shutdown()
 
   DebugOnly<HRESULT> hr = wmf::MFShutdown();
   NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
 
   return NS_OK;
 }
 
 MediaDataDecoder*
-WMFDecoderModule::CreateVideoDecoder(mozilla::layers::LayersBackend aLayersBackend,
-                                     mozilla::layers::ImageContainer* aImageContainer)
+WMFDecoderModule::CreateH264Decoder(mozilla::layers::LayersBackend aLayersBackend,
+                                    mozilla::layers::ImageContainer* aImageContainer)
 {
   nsAutoPtr<WMFVideoDecoder> decoder(new WMFVideoDecoder(mDXVAEnabled));
   nsresult rv = decoder->Init(aLayersBackend, aImageContainer);
   NS_ENSURE_SUCCESS(rv, nullptr);
   return decoder.forget();
 }
 
 MediaDataDecoder*
-WMFDecoderModule::CreateAudioDecoder(uint32_t aChannelCount,
-                                     uint32_t aSampleRate,
-                                     uint16_t aBitsPerSample,
-                                     const uint8_t* aUserData,
-                                     uint32_t aUserDataLength)
+WMFDecoderModule::CreateAACDecoder(uint32_t aChannelCount,
+                                   uint32_t aSampleRate,
+                                   uint16_t aBitsPerSample,
+                                   const uint8_t* aUserData,
+                                   uint32_t aUserDataLength)
 {
   nsAutoPtr<WMFAudioDecoder> decoder(new WMFAudioDecoder());
   nsresult rv = decoder->Init(aChannelCount,
                               aSampleRate,
                               aBitsPerSample,
                               aUserData,
                               aUserDataLength);
   NS_ENSURE_SUCCESS(rv, nullptr);
--- a/content/media/fmp4/wmf/WMFDecoderModule.h
+++ b/content/media/fmp4/wmf/WMFDecoderModule.h
@@ -21,25 +21,25 @@ public:
   nsresult Init();
 
   // Called when the decoders have shutdown. Main thread only.
   // Does this really need to be main thread only????
   virtual nsresult Shutdown() MOZ_OVERRIDE;
 
   // Decode thread.
   virtual MediaDataDecoder*
-  CreateVideoDecoder(mozilla::layers::LayersBackend aLayersBackend,
-                     mozilla::layers::ImageContainer* aImageContainer) MOZ_OVERRIDE;
+  CreateH264Decoder(mozilla::layers::LayersBackend aLayersBackend,
+                    mozilla::layers::ImageContainer* aImageContainer) MOZ_OVERRIDE;
 
   // Decode thread.
-  virtual MediaDataDecoder* CreateAudioDecoder(uint32_t aChannelCount,
-                                               uint32_t aSampleRate,
-                                               uint16_t aBitsPerSample,
-                                               const uint8_t* aUserData,
-                                               uint32_t aUserDataLength) MOZ_OVERRIDE;
+  virtual MediaDataDecoder* CreateAACDecoder(uint32_t aChannelCount,
+                                             uint32_t aSampleRate,
+                                             uint16_t aBitsPerSample,
+                                             const uint8_t* aUserData,
+                                             uint32_t aUserDataLength) MOZ_OVERRIDE;
 
   // Platform decoders can override these. Base implementation does nothing.
   virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
   virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
 private:
   const bool mDXVAEnabled;
 };