diff --git a/dom/media/encoder/OmxTrackEncoder.cpp b/dom/media/encoder/OmxTrackEncoder.cpp index 2203dd0c244..f78a9826624 100644 --- a/dom/media/encoder/OmxTrackEncoder.cpp +++ b/dom/media/encoder/OmxTrackEncoder.cpp @@ -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); diff --git a/dom/media/encoder/VP8TrackEncoder.cpp b/dom/media/encoder/VP8TrackEncoder.cpp index 28d109ed270..f6efac6a523 100644 --- a/dom/media/encoder/VP8TrackEncoder.cpp +++ b/dom/media/encoder/VP8TrackEncoder.cpp @@ -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, diff --git a/dom/media/omx/OMXCodecWrapper.cpp b/dom/media/omx/OMXCodecWrapper.cpp index c19025b7a5d..0ea79c928c4 100644 --- a/dom/media/omx/OMXCodecWrapper.cpp +++ b/dom/media/omx/OMXCodecWrapper.cpp @@ -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; } diff --git a/dom/media/omx/OMXCodecWrapper.h b/dom/media/omx/OMXCodecWrapper.h index 592573e4285..8860bb371b0 100644 --- a/dom/media/omx/OMXCodecWrapper.h +++ b/dom/media/omx/OMXCodecWrapper.h @@ -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). */