Bug 1153049: Part1. Merge MediaInfo and mp4_demuxer::TrackConfig. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 14 Apr 2015 15:15:46 +1000
changeset 270338 0a4a18ee6c8267d685243851a485c96030211ec4
parent 270337 818a69e48d385ef4df7e055d6910f4172a58b2c1
child 270339 3e617cb207c5261e89a35d364753726b69d721cd
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1153049
milestone40.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 1153049: Part1. Merge MediaInfo and mp4_demuxer::TrackConfig. r=cpearce
dom/html/HTMLMediaElement.cpp
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaInfo.h
dom/media/ogg/OggReader.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1887,21 +1887,21 @@ HTMLMediaElement::CaptureStreamInternal(
   // back into the output stream.
   out->mStream->GetStream()->ChangeExplicitBlockerCount(1);
   if (mDecoder) {
     mDecoder->AddOutputStream(out->mStream->GetStream()->AsProcessedStream(),
                               aFinishWhenEnded);
     if (mReadyState >= HAVE_METADATA) {
       // Expose the tracks to JS directly.
       if (HasAudio()) {
-        TrackID audioTrackId = mMediaInfo.mAudio.mTrackInfo.mOutputId;
+        TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
         out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO);
       }
       if (HasVideo()) {
-        TrackID videoTrackId = mMediaInfo.mVideo.mTrackInfo.mOutputId;
+        TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
         out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO);
       }
     }
   }
   nsRefPtr<DOMMediaStream> result = out->mStream;
   return result.forget();
 }
 
@@ -3191,21 +3191,21 @@ void HTMLMediaElement::MetadataLoaded(co
     }
     mPendingEncryptedInitData.mInitDatas.Clear();
 #endif // MOZ_EME
   }
 
   // Expose the tracks to JS directly.
   for (OutputMediaStream& out : mOutputStreams) {
     if (aInfo->HasAudio()) {
-      TrackID audioTrackId = aInfo->mAudio.mTrackInfo.mOutputId;
+      TrackID audioTrackId = aInfo->mAudio.mTrackId;
       out.mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO);
     }
     if (aInfo->HasVideo()) {
-      TrackID videoTrackId = aInfo->mVideo.mTrackInfo.mOutputId;
+      TrackID videoTrackId = aInfo->mVideo.mTrackId;
       out.mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO);
     }
   }
 
   // If this element had a video track, but consists only of an audio track now,
   // delete the VideoFrameContainer. This happens when the src is changed to an
   // audio only file.
   // Else update its dimensions.
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1918,26 +1918,26 @@ MediaDecoder::ConstructMediaTracks()
   if (!element) {
     return;
   }
 
   mMediaTracksConstructed = true;
 
   AudioTrackList* audioList = element->AudioTracks();
   if (audioList && mInfo->HasAudio()) {
-    TrackInfo info = mInfo->mAudio.mTrackInfo;
+    const TrackInfo& info = mInfo->mAudio;
     nsRefPtr<AudioTrack> track = MediaTrackList::CreateAudioTrack(
     info.mId, info.mKind, info.mLabel, info.mLanguage, info.mEnabled);
 
     audioList->AddTrack(track);
   }
 
   VideoTrackList* videoList = element->VideoTracks();
   if (videoList && mInfo->HasVideo()) {
-    TrackInfo info = mInfo->mVideo.mTrackInfo;
+    const TrackInfo& info = mInfo->mVideo;
     nsRefPtr<VideoTrack> track = MediaTrackList::CreateVideoTrack(
     info.mId, info.mKind, info.mLabel, info.mLanguage);
 
     videoList->AddTrack(track);
     track->SetEnabledInternal(info.mEnabled, MediaTrack::FIRE_NO_EVENTS);
   }
 }
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -402,26 +402,26 @@ void MediaDecoderStateMachine::SendStrea
       (!mInfo.HasAudio() || AudioQueue().IsFinished()) &&
       (!mInfo.HasVideo() || VideoQueue().IsFinished());
   if (mDecoder->IsSameOriginMedia()) {
     SourceMediaStream* mediaStream = stream->mStream;
     StreamTime endPosition = 0;
 
     if (!stream->mStreamInitialized) {
       if (mInfo.HasAudio()) {
-        TrackID audioTrackId = mInfo.mAudio.mTrackInfo.mOutputId;
+        TrackID audioTrackId = mInfo.mAudio.mTrackId;
         AudioSegment* audio = new AudioSegment();
         mediaStream->AddAudioTrack(audioTrackId, mInfo.mAudio.mRate, 0, audio,
                                    SourceMediaStream::ADDTRACK_QUEUED);
         stream->mStream->DispatchWhenNotEnoughBuffered(audioTrackId,
             TaskQueue(), GetWakeDecoderRunnable());
         stream->mNextAudioTime = mStartTime + stream->mInitialTime;
       }
       if (mInfo.HasVideo()) {
-        TrackID videoTrackId = mInfo.mVideo.mTrackInfo.mOutputId;
+        TrackID videoTrackId = mInfo.mVideo.mTrackId;
         VideoSegment* video = new VideoSegment();
         mediaStream->AddTrack(videoTrackId, 0, video,
                               SourceMediaStream::ADDTRACK_QUEUED);
         stream->mStream->DispatchWhenNotEnoughBuffered(videoTrackId,
             TaskQueue(), GetWakeDecoderRunnable());
 
         // TODO: We can't initialize |mNextVideoTime| until |mStartTime|
         // is set. This is a good indication that DecodedStreamData is in
@@ -430,17 +430,17 @@ void MediaDecoderStateMachine::SendStrea
         stream->mNextVideoTime = mStartTime + stream->mInitialTime;
       }
       mediaStream->FinishAddTracks();
       stream->mStreamInitialized = true;
     }
 
     if (mInfo.HasAudio()) {
       MOZ_ASSERT(stream->mNextAudioTime != -1, "Should've been initialized");
-      TrackID audioTrackId = mInfo.mAudio.mTrackInfo.mOutputId;
+      TrackID audioTrackId = mInfo.mAudio.mTrackId;
       nsAutoTArray<nsRefPtr<AudioData>,10> audio;
       // It's OK to hold references to the AudioData because AudioData
       // is ref-counted.
       AudioQueue().GetElementsAfter(stream->mNextAudioTime, &audio);
       AudioSegment output;
       for (uint32_t i = 0; i < audio.Length(); ++i) {
         SendStreamAudio(audio[i], stream, &output);
       }
@@ -456,17 +456,17 @@ void MediaDecoderStateMachine::SendStrea
       }
       endPosition = std::max(endPosition,
           mediaStream->TicksToTimeRoundDown(mInfo.mAudio.mRate,
                                             stream->mAudioFramesWritten));
     }
 
     if (mInfo.HasVideo()) {
       MOZ_ASSERT(stream->mNextVideoTime != -1, "Should've been initialized");
-      TrackID videoTrackId = mInfo.mVideo.mTrackInfo.mOutputId;
+      TrackID videoTrackId = mInfo.mVideo.mTrackId;
       nsAutoTArray<nsRefPtr<VideoData>,10> video;
       // It's OK to hold references to the VideoData because VideoData
       // is ref-counted.
       VideoQueue().GetElementsAfter(stream->mNextVideoTime, &video);
       VideoSegment output;
       for (uint32_t i = 0; i < video.Length(); ++i) {
         VideoData* v = video[i];
         if (stream->mNextVideoTime < v->mTime) {
@@ -567,17 +567,17 @@ bool MediaDecoderStateMachine::HaveEnoug
   if (!mAudioCaptured) {
     return true;
   }
 
   DecodedStreamData* stream = mDecoder->GetDecodedStream();
 
   if (stream && stream->mStreamInitialized && !stream->mHaveSentFinishAudio) {
     MOZ_ASSERT(mInfo.HasAudio());
-    TrackID audioTrackId = mInfo.mAudio.mTrackInfo.mOutputId;
+    TrackID audioTrackId = mInfo.mAudio.mTrackId;
     if (!stream->mStream->HaveEnoughBuffered(audioTrackId)) {
       return false;
     }
     stream->mStream->DispatchWhenNotEnoughBuffered(audioTrackId,
         TaskQueue(), GetWakeDecoderRunnable());
   }
 
   return true;
@@ -590,17 +590,17 @@ bool MediaDecoderStateMachine::HaveEnoug
   if (static_cast<uint32_t>(VideoQueue().GetSize()) < GetAmpleVideoFrames() * mPlaybackRate) {
     return false;
   }
 
   DecodedStreamData* stream = mDecoder->GetDecodedStream();
 
   if (stream && stream->mStreamInitialized && !stream->mHaveSentFinishVideo) {
     MOZ_ASSERT(mInfo.HasVideo());
-    TrackID videoTrackId = mInfo.mVideo.mTrackInfo.mOutputId;
+    TrackID videoTrackId = mInfo.mVideo.mTrackId;
     if (!stream->mStream->HaveEnoughBuffered(videoTrackId)) {
       return false;
     }
     stream->mStream->DispatchWhenNotEnoughBuffered(videoTrackId,
         TaskQueue(), GetWakeDecoderRunnable());
   }
 
   return true;
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -1,111 +1,194 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(MediaInfo_h)
 #define MediaInfo_h
 
+#include "nsRect.h"
+#include "nsRefPtr.h"
 #include "nsSize.h"
-#include "nsRect.h"
-#include "ImageTypes.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "ImageTypes.h"
+#include "MediaData.h"
 #include "StreamBuffer.h" // for TrackID
 
 namespace mozilla {
 
-struct TrackInfo {
-  void Init(const nsAString& aId,
+class TrackInfo {
+public:
+  enum TrackType {
+    kUndefinedTrack,
+    kAudioTrack,
+    kVideoTrack,
+    kTextTrack
+  };
+  TrackInfo(TrackType aType,
+            const nsAString& aId,
             const nsAString& aKind,
             const nsAString& aLabel,
             const nsAString& aLanguage,
             bool aEnabled,
-            TrackID aOutputId = TRACK_INVALID)
+            TrackID aTrackId = TRACK_INVALID)
+    : mId(aId)
+    , mKind(aKind)
+    , mLabel(aLabel)
+    , mLanguage(aLanguage)
+    , mEnabled(aEnabled)
+    , mTrackId(aTrackId)
+    , mDuration(0)
+    , mMediaTime(0)
+    , mType(aType)
+  {
+  }
+
+  // Only used for backward compatibility. Do not use in new code.
+  void Init(TrackType aType,
+            const nsAString& aId,
+            const nsAString& aKind,
+            const nsAString& aLabel,
+            const nsAString& aLanguage,
+            bool aEnabled,
+            TrackID aTrackId = TRACK_INVALID)
   {
     mId = aId;
     mKind = aKind;
     mLabel = aLabel;
     mLanguage = aLanguage;
     mEnabled = aEnabled;
-    mOutputId = aOutputId;
+    mTrackId = aTrackId;
+    mType = aType;
   }
 
+  // Fields common with MediaTrack object.
   nsString mId;
   nsString mKind;
   nsString mLabel;
   nsString mLanguage;
   bool mEnabled;
-  TrackID mOutputId;
+
+  TrackID mTrackId;
+
+  nsAutoCString mMimeType;
+  int64_t mDuration;
+  int64_t mMediaTime;
+  CryptoTrack mCrypto;
+
+  bool IsAudio() const
+  {
+    return mType == kAudioTrack;
+  }
+  bool IsVideo() const
+  {
+    return mType == kVideoTrack;
+  }
+  bool IsText() const
+  {
+    return mType == kTextTrack;
+  }
+  TrackType GetType() const
+  {
+    return mType;
+  }
+  bool virtual IsValid() const = 0;
+
+private:
+  TrackType mType;
 };
 
 // Stores info relevant to presenting media frames.
-class VideoInfo {
-private:
-  void Init(int32_t aWidth, int32_t aHeight, bool aHasVideo)
-  {
-    mDisplay = nsIntSize(aWidth, aHeight);
-    mStereoMode = StereoMode::MONO;
-    mHasVideo = aHasVideo;
-
-    // TODO: TrackInfo should be initialized by its specific codec decoder.
-    // This following call should be removed once we have that implemented.
-    mTrackInfo.Init(NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
-                    EmptyString(), EmptyString(), true, 2);
-  }
-
+class VideoInfo : public TrackInfo {
 public:
   VideoInfo()
+    : VideoInfo(0, 0, false)
   {
-    Init(0, 0, false);
   }
 
   VideoInfo(int32_t aWidth, int32_t aHeight)
+    : VideoInfo(aWidth, aHeight, true)
   {
-    Init(aWidth, aHeight, true);
+  }
+
+  VideoInfo(int32_t aWidth, int32_t aHeight, bool aHasVideo)
+    : TrackInfo(kVideoTrack, NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
+                EmptyString(), EmptyString(), true, 2)
+    , mDisplay(nsIntSize(aWidth, aHeight))
+    , mStereoMode(StereoMode::MONO)
+    , mImage(nsIntSize(aWidth, aHeight))
+    , mExtraData(new DataBuffer)
+    , mHasVideo(aHasVideo)
+  {
+  }
+
+  virtual bool IsValid() const override
+  {
+    return mDisplay.width > 0 && mDisplay.height > 0;
   }
 
   // Size in pixels at which the video is rendered. This is after it has
   // been scaled by its aspect ratio.
   nsIntSize mDisplay;
 
   // Indicates the frame layout for single track stereo videos.
   StereoMode mStereoMode;
 
+  // Size in pixels of decoded video's image.
+  nsIntSize mImage;
+
+  nsRefPtr<DataBuffer> mExtraData;
+
   // True if we have an active video bitstream.
   bool mHasVideo;
-
-  TrackInfo mTrackInfo;
 };
 
-class AudioInfo {
+class AudioInfo : public TrackInfo {
 public:
   AudioInfo()
-    : mRate(44100)
-    , mChannels(2)
+    : TrackInfo(kAudioTrack, NS_LITERAL_STRING("1"), NS_LITERAL_STRING("main"),
+                EmptyString(), EmptyString(), true, 1)
+    , mRate(0)
+    , mChannels(0)
+    , mBitDepth(0)
+    , mProfile(0)
+    , mExtendedProfile(0)
+    , mCodecSpecificConfig(new DataBuffer)
+    , mExtraData(new DataBuffer)
     , mHasAudio(false)
   {
-    // TODO: TrackInfo should be initialized by its specific codec decoder.
-    // This following call should be removed once we have that implemented.
-    mTrackInfo.Init(NS_LITERAL_STRING("1"), NS_LITERAL_STRING("main"),
-                    EmptyString(), EmptyString(), true, 1);
   }
 
   // Sample rate.
   uint32_t mRate;
 
   // Number of audio channels.
   uint32_t mChannels;
 
+  // Bits per sample.
+  uint32_t mBitDepth;
+
+  // Codec profile.
+  int8_t mProfile;
+
+  // Extended codec profile.
+  int8_t mExtendedProfile;
+
+  nsRefPtr<DataBuffer> mCodecSpecificConfig;
+  nsRefPtr<DataBuffer> mExtraData;
+
+  virtual bool IsValid() const override
+  {
+    return mChannels > 0 && mRate > 0;
+  }
+
   // True if we have an active audio bitstream.
   bool mHasAudio;
-
-  TrackInfo mTrackInfo;
 };
 
 class EncryptionInfo {
 public:
   struct InitData {
     template<typename AInitDatas>
     InitData(const nsAString& aType, AInitDatas&& aInitData)
       : mType(aType)
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -106,26 +106,30 @@ static const nsString GetKind(const nsCS
   } else if (aRole.Find("video/captioned") != -1) {
     return NS_LITERAL_STRING("captions");
   } else if (aRole.Find("video/subtitled") != -1) {
     return NS_LITERAL_STRING("subtitles");
   }
   return EmptyString();
 }
 
-static void InitTrack(MessageField* aMsgInfo, TrackInfo* aInfo, bool aEnable)
+static void InitTrack(TrackInfo::TrackType aTrackType,
+                      MessageField* aMsgInfo,
+                      TrackInfo* aInfo,
+                      bool aEnable)
 {
   MOZ_ASSERT(aMsgInfo);
   MOZ_ASSERT(aInfo);
 
   nsCString* sName = aMsgInfo->mValuesStore.Get(eName);
   nsCString* sRole = aMsgInfo->mValuesStore.Get(eRole);
   nsCString* sTitle = aMsgInfo->mValuesStore.Get(eTitle);
   nsCString* sLanguage = aMsgInfo->mValuesStore.Get(eLanguage);
-  aInfo->Init(sName? NS_ConvertUTF8toUTF16(*sName):EmptyString(),
+  aInfo->Init(aTrackType,
+              sName? NS_ConvertUTF8toUTF16(*sName):EmptyString(),
               sRole? GetKind(*sRole):EmptyString(),
               sTitle? NS_ConvertUTF8toUTF16(*sTitle):EmptyString(),
               sLanguage? NS_ConvertUTF8toUTF16(*sLanguage):EmptyString(),
               aEnable);
 }
 
 OggReader::OggReader(AbstractMediaDecoder* aDecoder)
   : MediaDecoderReader(aDecoder),
@@ -317,17 +321,20 @@ void OggReader::SetupMediaTracksInfo(con
 
     if (codecState->GetType() == OggCodecState::TYPE_THEORA) {
       TheoraState* theoraState = static_cast<TheoraState*>(codecState);
       if (!(mTheoraState && mTheoraState->mSerial == theoraState->mSerial)) {
         continue;
       }
 
       if (msgInfo) {
-        InitTrack(msgInfo, &mInfo.mVideo.mTrackInfo, mTheoraState == theoraState);
+        InitTrack(TrackInfo::kVideoTrack,
+                  msgInfo,
+                  &mInfo.mVideo,
+                  mTheoraState == theoraState);
       }
 
       nsIntRect picture = nsIntRect(theoraState->mInfo.pic_x,
                                     theoraState->mInfo.pic_y,
                                     theoraState->mInfo.pic_width,
                                     theoraState->mInfo.pic_height);
       nsIntSize displaySize = nsIntSize(theoraState->mInfo.pic_width,
                                         theoraState->mInfo.pic_height);
@@ -338,30 +345,36 @@ void OggReader::SetupMediaTracksInfo(con
       mInfo.mVideo.mHasVideo = IsValidVideoRegion(frameSize, picture, displaySize)? true:false;
     } else if (codecState->GetType() == OggCodecState::TYPE_VORBIS) {
       VorbisState* vorbisState = static_cast<VorbisState*>(codecState);
       if (!(mVorbisState && mVorbisState->mSerial == vorbisState->mSerial)) {
         continue;
       }
 
       if (msgInfo) {
-        InitTrack(msgInfo, &mInfo.mAudio.mTrackInfo, mVorbisState == vorbisState);
+        InitTrack(TrackInfo::kAudioTrack,
+                  msgInfo,
+                  &mInfo.mAudio,
+                  mVorbisState == vorbisState);
       }
 
       mInfo.mAudio.mHasAudio = true;
       mInfo.mAudio.mRate = vorbisState->mInfo.rate;
       mInfo.mAudio.mChannels = vorbisState->mInfo.channels;
     } else if (codecState->GetType() == OggCodecState::TYPE_OPUS) {
       OpusState* opusState = static_cast<OpusState*>(codecState);
       if (!(mOpusState && mOpusState->mSerial == opusState->mSerial)) {
         continue;
       }
 
       if (msgInfo) {
-        InitTrack(msgInfo, &mInfo.mAudio.mTrackInfo, mOpusState == opusState);
+        InitTrack(TrackInfo::kAudioTrack,
+                  msgInfo,
+                  &mInfo.mAudio,
+                  mOpusState == opusState);
       }
 
       mInfo.mAudio.mHasAudio = true;
       mInfo.mAudio.mRate = opusState->mRate;
       mInfo.mAudio.mChannels = opusState->mChannels;
     }
   }
 }
@@ -779,33 +792,33 @@ bool OggReader::ReadOggChain()
   if ((newVorbisState && ReadHeaders(newVorbisState)) &&
       (mVorbisState->mInfo.rate == newVorbisState->mInfo.rate) &&
       (mVorbisState->mInfo.channels == newVorbisState->mInfo.channels)) {
 
     SetupTargetVorbis(newVorbisState);
     LOG(PR_LOG_DEBUG, ("New vorbis ogg link, serial=%d\n", mVorbisSerial));
 
     if (msgInfo) {
-      InitTrack(msgInfo, &mInfo.mAudio.mTrackInfo, true);
+      InitTrack(TrackInfo::kAudioTrack, msgInfo, &mInfo.mAudio, true);
     }
     mInfo.mAudio.mRate = newVorbisState->mInfo.rate;
     mInfo.mAudio.mChannels = newVorbisState->mInfo.channels;
 
     chained = true;
     tags = newVorbisState->GetTags();
   }
 
   if ((newOpusState && ReadHeaders(newOpusState)) &&
       (mOpusState->mRate == newOpusState->mRate) &&
       (mOpusState->mChannels == newOpusState->mChannels)) {
 
     SetupTargetOpus(newOpusState);
 
     if (msgInfo) {
-      InitTrack(msgInfo, &mInfo.mAudio.mTrackInfo, true);
+      InitTrack(TrackInfo::kAudioTrack, msgInfo, &mInfo.mAudio, true);
     }
     mInfo.mAudio.mRate = newOpusState->mRate;
     mInfo.mAudio.mChannels = newOpusState->mChannels;
 
     chained = true;
     tags = newOpusState->GetTags();
   }