Bug 895730 - AudioTrackEncoder should handle the case where audio chunk is null. r=roc

This commit is contained in:
Shelly Lin 2013-07-31 12:21:29 +08:00
Родитель 32d3b06b96
Коммит 546e3d0f33
2 изменённых файлов: 45 добавлений и 21 удалений

Просмотреть файл

@ -16,7 +16,8 @@
namespace mozilla { namespace mozilla {
#define MAX_FRAMES_TO_DROP 48000 static const int DEFAULT_CHANNELS = 1;
static const int DEFAULT_SAMPLING_RATE = 16000;
void void
AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
@ -34,16 +35,25 @@ AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
AudioSegment::ChunkIterator iter(*audio); AudioSegment::ChunkIterator iter(*audio);
while (!iter.IsEnded()) { while (!iter.IsEnded()) {
AudioChunk chunk = *iter; AudioChunk chunk = *iter;
if (chunk.mBuffer) {
Init(chunk.mChannelData.Length(), aTrackRate); // The number of channels is determined by the first non-null chunk, and
// thus the audio encoder is initialized at this time.
if (!chunk.IsNull()) {
nsresult rv = Init(chunk.mChannelData.Length(), aTrackRate);
if (NS_SUCCEEDED(rv)) {
break; break;
} }
} else {
mSilentDuration += chunk.mDuration;
}
iter.Next(); iter.Next();
} }
} }
// Append and consume this raw segment. // Append and consume this raw segment.
if (mInitialized) {
AppendAudioSegment(audio); AppendAudioSegment(audio);
}
// The stream has stopped and reached the end of track. // The stream has stopped and reached the end of track.
if (aTrackEvents == MediaStreamListener::TRACK_EVENT_ENDED) { if (aTrackEvents == MediaStreamListener::TRACK_EVENT_ENDED) {
@ -57,35 +67,42 @@ AudioTrackEncoder::NotifyRemoved(MediaStreamGraph* aGraph)
{ {
// In case that MediaEncoder does not receive a TRACK_EVENT_ENDED event. // In case that MediaEncoder does not receive a TRACK_EVENT_ENDED event.
LOG("[AudioTrackEncoder]: NotifyRemoved."); LOG("[AudioTrackEncoder]: NotifyRemoved.");
// If source audio chunks are completely silent till the end of encoding,
// initialize the encoder with default channel counts and sampling rate, and
// append this many null data to the segment of track encoder.
if (!mInitialized && mSilentDuration > 0) {
Init(DEFAULT_CHANNELS, DEFAULT_SAMPLING_RATE);
mRawSegment->AppendNullData(mSilentDuration);
mSilentDuration = 0;
}
NotifyEndOfStream(); NotifyEndOfStream();
} }
nsresult nsresult
AudioTrackEncoder::AppendAudioSegment(MediaSegment* aSegment) AudioTrackEncoder::AppendAudioSegment(MediaSegment* aSegment)
{ {
// Drop the in-coming segment if buffer(mRawSegment) is overflow.
ReentrantMonitorAutoEnter mon(mReentrantMonitor); ReentrantMonitorAutoEnter mon(mReentrantMonitor);
AudioSegment* audio = static_cast<AudioSegment*>(aSegment); AudioSegment* audio = static_cast<AudioSegment*>(aSegment);
AudioSegment::ChunkIterator iter(*audio); AudioSegment::ChunkIterator iter(*audio);
if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP) { // Append this many null data to our queued segment if there is a complete
// silence before the audio track encoder has initialized.
if (mSilentDuration > 0) {
mRawSegment->AppendNullData(mSilentDuration);
mSilentDuration = 0;
}
while (!iter.IsEnded()) { while (!iter.IsEnded()) {
AudioChunk chunk = *iter; AudioChunk chunk = *iter;
if (chunk.mBuffer) { // Append and consume both non-null and null chunks.
mRawSegment->AppendAndConsumeChunk(&chunk); mRawSegment->AppendAndConsumeChunk(&chunk);
}
iter.Next(); iter.Next();
} }
if (mRawSegment->GetDuration() >= GetPacketDuration()) { if (mRawSegment->GetDuration() >= GetPacketDuration()) {
mReentrantMonitor.NotifyAll(); mReentrantMonitor.NotifyAll();
} }
}
#ifdef DEBUG
else {
LOG("[AudioTrackEncoder]: A segment has dropped!");
}
#endif
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -74,6 +74,7 @@ public:
, mRawSegment(new AudioSegment()) , mRawSegment(new AudioSegment())
, mEndOfStream(false) , mEndOfStream(false)
, mCanceled(false) , mCanceled(false)
, mSilentDuration(0)
{} {}
void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
@ -176,6 +177,12 @@ protected:
* mReentrantMonitor. * mReentrantMonitor.
*/ */
bool mCanceled; bool mCanceled;
/**
* The total duration of null chunks we have received from MediaStreamGraph
* before initializing the audio track encoder.
*/
TrackTicks mSilentDuration;
}; };
class VideoTrackEncoder : public TrackEncoder class VideoTrackEncoder : public TrackEncoder