Bug 963502 - [MediaEncoder] OMXAudioEncoder will be out of input buffers if input segment is too big. r=roc

This commit is contained in:
John Lin 2014-01-29 08:20:55 -05:00
Родитель dd066d6108
Коммит 32620ae17c
3 изменённых файлов: 47 добавлений и 16 удалений

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

@ -207,8 +207,6 @@ OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer)
isCSD = true;
} else if (outFlags & OMXCodecWrapper::BUFFER_EOS) { // last frame
mEncodingComplete = true;
} else {
MOZ_ASSERT(frameData.Length() == OMXCodecWrapper::kAACFrameSize);
}
nsRefPtr<EncodedFrame> audiodata = new EncodedFrame();
@ -243,19 +241,31 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
segment.AppendFrom(&mRawSegment);
}
if (!mEosSetInEncoder) {
if (mEndOfStream) {
nsresult rv;
if (segment.GetDuration() == 0) {
// Notify EOS at least once, even if segment is empty.
if (mEndOfStream && !mEosSetInEncoder) {
mEosSetInEncoder = true;
}
if (segment.GetDuration() > 0 || mEndOfStream) {
// Notify EOS at least once, even when segment is empty.
nsresult rv = mEncoder->Encode(segment,
mEndOfStream ? OMXCodecWrapper::BUFFER_EOS : 0);
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS);
NS_ENSURE_SUCCESS(rv, rv);
}
// Nothing to encode but encoder could still have encoded data for earlier
// input.
return AppendEncodedFrames(aData);
}
return AppendEncodedFrames(aData);
// OMX encoder has limited input buffers only so we have to feed input and get
// output more than once if there are too many samples pending in segment.
while (segment.GetDuration() > 0) {
rv = mEncoder->Encode(segment,
mEndOfStream ? OMXCodecWrapper::BUFFER_EOS : 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendEncodedFrames(aData);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
}

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

@ -420,7 +420,7 @@ private:
};
nsresult
OMXAudioEncoder::Encode(const AudioSegment& aSegment, int aInputFlags)
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
{
#ifndef MOZ_SAMPLE_TYPE_S16
#error MediaCodec accepts only 16-bit PCM data.
@ -433,6 +433,11 @@ OMXAudioEncoder::Encode(const AudioSegment& aSegment, int aInputFlags)
// Get input buffer.
InputBufferHelper buffer(mCodec, mInputBufs);
status_t result = buffer.Dequeue();
if (result == -EAGAIN) {
// All input buffers are full. Caller can try again later after consuming
// some output buffers.
return NS_OK;
}
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
size_t samplesCopied = 0; // Number of copied samples.
@ -448,14 +453,20 @@ OMXAudioEncoder::Encode(const AudioSegment& aSegment, int aInputFlags)
if (bytesToCopy > buffer.AvailableSize()) {
// Not enough space left in input buffer. Send it to encoder and get a
// new one.
// Don't signal EOS since there is more data to copy.
result = buffer.Enqueue(mTimestamp, aInputFlags & ~BUFFER_EOS);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
result = buffer.Dequeue();
if (result == -EAGAIN) {
// All input buffers are full. Caller can try again later after
// consuming some output buffers.
aSegment.RemoveLeading(samplesCopied);
return NS_OK;
}
mTimestamp += samplesCopied * mSampleDuration;
samplesCopied = 0;
result = buffer.Dequeue();
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
}
@ -473,6 +484,9 @@ OMXAudioEncoder::Encode(const AudioSegment& aSegment, int aInputFlags)
buffer.IncreaseOffset(bytesToCopy);
iter.Next();
}
if (samplesCopied > 0) {
aSegment.RemoveLeading(samplesCopied);
}
} else if (aInputFlags & BUFFER_EOS) {
// No audio data left in segment but we still have to feed something to
// MediaCodec in order to notify EOS.
@ -483,7 +497,12 @@ OMXAudioEncoder::Encode(const AudioSegment& aSegment, int aInputFlags)
}
if (samplesCopied > 0) {
result = buffer.Enqueue(mTimestamp, aInputFlags);
int flags = aInputFlags;
if (aSegment.GetDuration() > 0) {
// Don't signal EOS until source segment is empty.
flags &= ~BUFFER_EOS;
}
result = buffer.Enqueue(mTimestamp, flags);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
mTimestamp += samplesCopied * mSampleDuration;

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

@ -177,9 +177,11 @@ public:
/**
* Encode 16-bit PCM audio samples stored in aSegment. To notify end of
* stream, set aInputFlags to BUFFER_EOS.
* stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
* this function might not be able to encode all chunks in one call, however
* it will remove chunks it consumes from aSegment.
*/
nsresult Encode(const mozilla::AudioSegment& aSegment, int aInputFlags = 0);
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
protected:
virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,