Bug 1197669 - Part2 - 1. Ensure the EOS is sent to MediaCodec. 2. mEndOfStream should be protected by monitor. r=sotaro

This commit is contained in:
Benjamin Chen 2015-09-01 11:25:35 +08:00
parent f2148a94f9
commit 05d8b5b006
4 changed files with 31 additions and 15 deletions

View File

@ -134,11 +134,8 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
? nullptr : mLastFrame.GetImage();
rv = mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs,
OMXCodecWrapper::BUFFER_EOS);
OMXCodecWrapper::BUFFER_EOS, &mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
// Keep sending EOS signal until OMXVideoEncoder gets it.
mEosSetInEncoder = true;
}
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
@ -219,6 +216,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
PROFILER_LABEL("OmxAACAudioTrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
AudioSegment segment;
bool EOS;
// Move all the samples from mRawSegment to segment. We only hold
// the monitor in this block.
{
@ -234,14 +232,15 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
}
segment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
nsresult rv;
if (segment.GetDuration() == 0) {
// Notify EOS at least once, even if segment is empty.
if (mEndOfStream && !mEosSetInEncoder) {
mEosSetInEncoder = true;
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS);
if (EOS && !mEosSetInEncoder) {
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS,
&mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
}
// Nothing to encode but encoder could still have encoded data for earlier
@ -252,8 +251,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& 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);
rv = mEncoder->Encode(segment, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendEncodedFrames(aData);

View File

@ -446,6 +446,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
{
PROFILER_LABEL("VP8TrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
bool EOS;
{
// Move all the samples from mRawSegment to mSourceSegment. We only hold
// the monitor in this block.
@ -461,6 +462,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
return NS_ERROR_FAILURE;
}
mSourceSegment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
VideoSegment::ChunkIterator iter(mSourceSegment);
@ -534,7 +536,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
VP8LOG("RemoveLeading %lld\n",totalProcessedDuration);
// End of stream, pull the rest frames in encoder.
if (mEndOfStream) {
if (EOS) {
VP8LOG("mEndOfStream is true\n");
mEncodingComplete = true;
if (vpx_codec_encode(mVPXContext, nullptr, mEncodedTimestamp,

View File

@ -382,7 +382,7 @@ ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination)
nsresult
OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags)
int64_t aTimestamp, int aInputFlags, bool* aSendEOS)
{
MOZ_ASSERT(mStarted, "Configure() should be called before Encode().");
@ -456,6 +456,9 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
// Queue this input buffer.
result = mCodec->queueInputBuffer(index, 0, dstSize, aTimestamp, aInputFlags);
if (aSendEOS && (aInputFlags & BUFFER_EOS) && result == OK) {
*aSendEOS = true;
}
return result == OK ? NS_OK : NS_ERROR_FAILURE;
}
@ -822,7 +825,8 @@ OMXAudioEncoder::~OMXAudioEncoder()
}
nsresult
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags,
bool* aSendEOS)
{
#ifndef MOZ_SAMPLE_TYPE_S16
#error MediaCodec accepts only 16-bit PCM data.
@ -877,7 +881,9 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
}
result = buffer.Enqueue(mTimestamp, flags);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
if (aSendEOS && (aInputFlags & BUFFER_EOS)) {
*aSendEOS = true;
}
return NS_OK;
}

View File

@ -224,8 +224,13 @@ public:
* 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.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0,
bool* aSendEOS = nullptr);
~OMXAudioEncoder();
protected:
@ -298,9 +303,14 @@ public:
* semi-planar YUV420 format stored in the buffer of aImage. aTimestamp gives
* the frame timestamp/presentation time (in microseconds). To notify end of
* stream, set aInputFlags to BUFFER_EOS.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(const mozilla::layers::Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags = 0);
int64_t aTimestamp, int aInputFlags = 0,
bool* aSendEOS = nullptr);
#if ANDROID_VERSION >= 18
/** Set encoding bitrate (in kbps). */