Bug 998711. r=jesup
authorPaul Adenot <paul@paul.cx>
Fri, 25 Apr 2014 15:15:21 +0200
changeset 181369 8a69388a1a2116e1b9c3b36e11bd78ba9b98d378
parent 181368 27cd1a1fd1d7f8ec0384888f0936fd6c8e1b5f0b
child 181370 2557b51a47a0ea0a6f6ceec5877a76dd42221eb0
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjesup
bugs998711
milestone32.0a1
Bug 998711. r=jesup
content/media/AudioSegment.h
content/media/MediaStreamGraph.cpp
--- a/content/media/AudioSegment.h
+++ b/content/media/AudioSegment.h
@@ -182,16 +182,17 @@ public:
     for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
       nsAutoTArray<nsTArray<T>, GUESS_AUDIO_CHANNELS> output;
       nsAutoTArray<const T*, GUESS_AUDIO_CHANNELS> bufferPtrs;
       AudioChunk& c = *ci;
       // If this chunk is null, don't bother resampling, just alter its duration
       if (c.IsNull()) {
         c.mDuration *= aOutRate / aInRate;
         mDuration += c.mDuration;
+        continue;
       }
       uint32_t channels = c.mChannelData.Length();
       output.SetLength(channels);
       bufferPtrs.SetLength(channels);
       uint32_t inFrames = c.mDuration,
       outFrames = c.mDuration * aOutRate / aInRate;
       for (uint32_t i = 0; i < channels; i++) {
         const T* in = static_cast<const T*>(c.mChannelData[i]);
@@ -260,17 +261,24 @@ public:
     return chunk;
   }
   void ApplyVolume(float aVolume);
   void WriteTo(uint64_t aID, AudioStream* aOutput, AudioMixer* aMixer = nullptr);
 
   int ChannelCount() {
     NS_WARN_IF_FALSE(!mChunks.IsEmpty(),
         "Cannot query channel count on a AudioSegment with no chunks.");
-    return mChunks.IsEmpty() ? 0 : mChunks[0].mChannelData.Length();
+    // Find the first chunk that has non-zero channels. A chunk that hs zero
+    // channels is just silence and we can simply discard it.
+    for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
+      if (ci->ChannelCount()) {
+        return ci->ChannelCount();
+      }
+    }
+    return 0;
   }
 
   static Type StaticType() { return AUDIO; }
 
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -2272,22 +2272,27 @@ SourceMediaStream::ResampleAudioToGraphS
 {
   if (aSegment->GetType() != MediaSegment::AUDIO ||
       aTrackData->mInputRate == GraphImpl()->AudioSampleRate()) {
     return;
   }
   AudioSegment* segment = static_cast<AudioSegment*>(aSegment);
   if (!aTrackData->mResampler) {
     int channels = segment->ChannelCount();
-    SpeexResamplerState* state = speex_resampler_init(channels,
-                                                      aTrackData->mInputRate,
-                                                      GraphImpl()->AudioSampleRate(),
-                                                      SPEEX_RESAMPLER_QUALITY_DEFAULT,
-                                                      nullptr);
-    if (state) {
+
+    // If this segment is just silence, we delay instanciating the resampler.
+    if (channels) {
+      SpeexResamplerState* state = speex_resampler_init(channels,
+                                                        aTrackData->mInputRate,
+                                                        GraphImpl()->AudioSampleRate(),
+                                                        SPEEX_RESAMPLER_QUALITY_DEFAULT,
+                                                        nullptr);
+      if (!state) {
+        return;
+      }
       aTrackData->mResampler.own(state);
     }
   }
   segment->ResampleChunks(aTrackData->mResampler);
 }
 
 bool
 SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegment *aRawSegment)