Bug 971641 - Add AMR metadata. r=cpearce
authorAlfredo Yang <ayang@mozilla.com>
Tue, 18 Mar 2014 08:20:18 -0400
changeset 174042 b7f5aaff655899c7f4cd041dd4eae936b9c15519
parent 174041 a6abe0d4e0be64d787308215604efa8ffb51ddb6
child 174043 819d7aa12df955cc139c091d468403bc9c559d16
push id26440
push userkwierso@gmail.com
push dateTue, 18 Mar 2014 20:50:53 +0000
treeherdermozilla-central@3ac88ba5f2d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs971641
milestone31.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 971641 - Add AMR metadata. r=cpearce
content/media/encoder/TrackMetadataBase.h
content/media/encoder/fmp4_muxer/ISOControl.cpp
content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp
content/media/encoder/fmp4_muxer/ISOTrackMetadata.h
--- a/content/media/encoder/TrackMetadataBase.h
+++ b/content/media/encoder/TrackMetadataBase.h
@@ -16,45 +16,52 @@ class TrackMetadataBase
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackMetadataBase)
   enum MetadataKind {
     METADATA_OPUS,    // Represent the Opus metadata
     METADATA_VP8,
     METADATA_VORBIS,
     METADATA_AVC,
     METADATA_AAC,
+    METADATA_AMR,
     METADATA_UNKNOWN  // Metadata Kind not set
   };
   virtual ~TrackMetadataBase() {}
   // Return the specific metadata kind
   virtual MetadataKind GetKind() const = 0;
 };
 
 // The base class for audio metadata.
 class AudioTrackMetadata : public TrackMetadataBase {
 public:
   // The duration of each sample set generated by encoder. (counted by samples)
   // If the duration is variant, this value should return 0.
   virtual uint32_t GetAudioFrameDuration() = 0;
+
   // The size of each sample set generated by encoder. (counted by byte)
   // If the size is variant, this value should return 0.
   virtual uint32_t GetAudioFrameSize() = 0;
+
   // AudioSampleRate is the number of audio sample per second.
   virtual uint32_t GetAudioSampleRate() = 0;
+
   virtual uint32_t GetAudioChannels() = 0;
 };
 
 // The base class for video metadata.
 class VideoTrackMetadata : public TrackMetadataBase {
 public:
   virtual uint32_t GetVideoHeight() = 0;
+
   virtual uint32_t GetVideoWidth() = 0;
+
   // VideoClockRate is the number of samples per second in video frame's
   // timestamp.
   // For example, if VideoClockRate is 90k Hz and VideoFrameRate is
   // 30 fps, each frame's sample duration will be 3000 Hz.
   virtual uint32_t GetVideoClockRate() = 0;
+
   // VideoFrameRate is numner of frames per second.
   virtual uint32_t GetVideoFrameRate() = 0;
 };
 
 }
 #endif
--- a/content/media/encoder/fmp4_muxer/ISOControl.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOControl.cpp
@@ -56,35 +56,36 @@ FragmentBuffer::AddFrame(EncodedFrame* a
 {
   // already EOS, it rejects all new data.
   if (mEOS) {
     MOZ_ASSERT(0);
     return NS_OK;
   }
 
   EncodedFrame::FrameType type = aFrame->GetFrameType();
-  if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD) {
+  if (type == EncodedFrame::AAC_CSD || type == EncodedFrame::AVC_CSD ||
+      type == EncodedFrame::AMR_AUDIO_CSD) {
     mCSDFrame = aFrame;
-    // Ue CSD's timestamp as the start time. Encoder should send CSD frame first
-    // and data frames.
+    // Use CSD's timestamp as the start time. Encoder should send CSD frame first
+    // and then data frames.
     mMediaStartTime = aFrame->GetTimeStamp();
     mFragmentNumber = 1;
     return NS_OK;
   }
 
   // if the timestamp is incorrect, abort it.
   if (aFrame->GetTimeStamp() < mMediaStartTime) {
     MOZ_ASSERT(false);
     return NS_ERROR_FAILURE;
   }
 
   mFragArray.LastElement().AppendElement(aFrame);
 
   // check if current fragment is reach the fragment duration.
-  if ((aFrame->GetTimeStamp() - mMediaStartTime) > (mFragDuration * mFragmentNumber)) {
+  if ((aFrame->GetTimeStamp() - mMediaStartTime) >= (mFragDuration * mFragmentNumber)) {
     mFragArray.AppendElement();
     mFragmentNumber++;
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
@@ -158,18 +158,23 @@ TrackRunBox::fillSampleTable()
         frame_time = frames.ElementAt(i)->GetTimeStamp() -
                      frames.ElementAt(i - 1)->GetTimeStamp();
         // Keep the last frame time of current fagment, it will be used to calculate
         // the first frame duration of next fragment.
         if ((len - 1) == i) {
           frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp());
         }
       }
-      sample_info_table[i].sample_duration =
-        frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S;
+
+      // In TrackRunBox, there should be exactly one type, either audio or video.
+      MOZ_ASSERT((mTrackType & Video_Track) ^ (mTrackType & Audio_Track));
+      sample_info_table[i].sample_duration = (mTrackType & Video_Track ?
+        frame_time * mVideoMeta->GetVideoClockRate() / USECS_PER_S :
+        frame_time * mAudioMeta->GetAudioSampleRate() / USECS_PER_S);
+
       table_size += sizeof(uint32_t);
     }
 
     sample_info_table[i].sample_composition_time_offset = 0;
   }
   return table_size;
 }
 
--- a/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp
+++ b/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp
@@ -94,17 +94,19 @@ ISOMediaWriter::WriteEncodedTrack(const 
   if (!len) {
     // no frame? why bother to WriteEncodedTrack
     return NS_OK;
   }
   for (uint32_t i = 0; i < len; i++) {
     nsRefPtr<EncodedFrame> frame(aData.GetEncodedFrames()[i]);
     EncodedFrame::FrameType type = frame->GetFrameType();
     if (type == EncodedFrame::AAC_AUDIO_FRAME ||
-        type == EncodedFrame::AAC_CSD) {
+        type == EncodedFrame::AAC_CSD ||
+        type == EncodedFrame::AMR_AUDIO_FRAME ||
+        type == EncodedFrame::AMR_AUDIO_CSD) {
       frag = mAudioFragmentBuffer;
     } else if (type == EncodedFrame::AVC_I_FRAME ||
                type == EncodedFrame::AVC_P_FRAME ||
                type == EncodedFrame::AVC_B_FRAME ||
                type == EncodedFrame::AVC_CSD) {
       frag = mVideoFragmentBuffer;
     } else {
       MOZ_ASSERT(0);
@@ -199,17 +201,18 @@ ISOMediaWriter::GetContainerData(nsTArra
     return mControl->GetBufs(aOutputBufs);
   }
   return NS_OK;
 }
 
 nsresult
 ISOMediaWriter::SetMetadata(TrackMetadataBase* aMetadata)
 {
-  if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AAC ) {
+  if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AAC ||
+      aMetadata->GetKind() == TrackMetadataBase::METADATA_AMR) {
     mControl->SetMetadata(aMetadata);
     mAudioFragmentBuffer = new FragmentBuffer(Audio_Track, FRAG_DURATION);
     mControl->SetFragment(mAudioFragmentBuffer);
     return NS_OK;
   }
   if (aMetadata->GetKind() == TrackMetadataBase::METADATA_AVC) {
     mControl->SetMetadata(aMetadata);
     mVideoFragmentBuffer = new FragmentBuffer(Video_Track, FRAG_DURATION);
--- a/content/media/encoder/fmp4_muxer/ISOTrackMetadata.h
+++ b/content/media/encoder/fmp4_muxer/ISOTrackMetadata.h
@@ -60,11 +60,39 @@ public:
   }
   ~AVCTrackMetadata() { MOZ_COUNT_DTOR(AVCTrackMetadata); }
 
   uint32_t mHeight;
   uint32_t mWidth;
   uint32_t mFrameRate;       // frames per second
 };
 
+
+// AMR sample rate is 8000 samples/s.
+#define AMR_SAMPLE_RATE 8000
+
+// Channel number is always 1.
+#define AMR_CHANNELS    1
+
+// AMR speech codec, 3GPP TS 26.071. Encoder and continer support AMR-NB only
+// currently.
+class AMRTrackMetadata : public AudioTrackMetadata {
+public:
+  // AudioTrackMetadata members
+  //
+  // The number of sample sets generates by encoder is variant. So the
+  // frame duration and frame size are both 0.
+  uint32_t GetAudioFrameDuration() MOZ_OVERRIDE { return 0; }
+  uint32_t GetAudioFrameSize() MOZ_OVERRIDE { return 0; }
+  uint32_t GetAudioSampleRate() MOZ_OVERRIDE { return AMR_SAMPLE_RATE; }
+  uint32_t GetAudioChannels() MOZ_OVERRIDE { return AMR_CHANNELS; }
+
+  // TrackMetadataBase member
+  MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_AMR; }
+
+  // AMRTrackMetadata members
+  AMRTrackMetadata() { MOZ_COUNT_CTOR(AMRTrackMetadata); }
+  ~AMRTrackMetadata() { MOZ_COUNT_DTOR(AMRTrackMetadata); }
+};
+
 }
 
 #endif // ISOTrackMetadata_h_