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 {
#define MAX_FRAMES_TO_DROP 48000
static const int DEFAULT_CHANNELS = 1;
static const int DEFAULT_SAMPLING_RATE = 16000;
void
AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
@ -34,16 +35,25 @@ AudioTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
AudioSegment::ChunkIterator iter(*audio);
while (!iter.IsEnded()) {
AudioChunk chunk = *iter;
if (chunk.mBuffer) {
Init(chunk.mChannelData.Length(), aTrackRate);
break;
// 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;
}
} else {
mSilentDuration += chunk.mDuration;
}
iter.Next();
}
}
// Append and consume this raw segment.
AppendAudioSegment(audio);
if (mInitialized) {
AppendAudioSegment(audio);
}
// The stream has stopped and reached the end of track.
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.
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();
}
nsresult
AudioTrackEncoder::AppendAudioSegment(MediaSegment* aSegment)
{
// Drop the in-coming segment if buffer(mRawSegment) is overflow.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
AudioSegment* audio = static_cast<AudioSegment*>(aSegment);
AudioSegment::ChunkIterator iter(*audio);
if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP) {
while(!iter.IsEnded()) {
AudioChunk chunk = *iter;
if (chunk.mBuffer) {
mRawSegment->AppendAndConsumeChunk(&chunk);
}
iter.Next();
}
if (mRawSegment->GetDuration() >= GetPacketDuration()) {
mReentrantMonitor.NotifyAll();
}
// 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;
}
#ifdef DEBUG
else {
LOG("[AudioTrackEncoder]: A segment has dropped!");
while (!iter.IsEnded()) {
AudioChunk chunk = *iter;
// Append and consume both non-null and null chunks.
mRawSegment->AppendAndConsumeChunk(&chunk);
iter.Next();
}
if (mRawSegment->GetDuration() >= GetPacketDuration()) {
mReentrantMonitor.NotifyAll();
}
#endif
return NS_OK;
}

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

@ -74,6 +74,7 @@ public:
, mRawSegment(new AudioSegment())
, mEndOfStream(false)
, mCanceled(false)
, mSilentDuration(0)
{}
void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
@ -176,6 +177,12 @@ protected:
* mReentrantMonitor.
*/
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