Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Truncate video with MediaCodec

I've used Android MediaCodec library to transcode video files (mainly change the resolution Sample code here)

Another thing I want to achieve is to truncate the video - to only take the beginning 15 seconds. The logic is to check videoExtractor.getSampleTime() if it's greater than the 15 seconds, I'll just write an EOS to the decoder buffer.

But I get an exception Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff3

Here is my code:

        while ((!videoEncoderDone) || (!audioEncoderDone)) {
        while (!videoExtractorDone
                && (encoderOutputVideoFormat == null || muxing)) {
            int decoderInputBufferIndex = videoDecoder.dequeueInputBuffer(TIMEOUT_USEC);
            if (decoderInputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
                break;

            ByteBuffer decoderInputBuffer = videoDecoderInputBuffers[decoderInputBufferIndex];
            int size = videoExtractor.readSampleData(decoderInputBuffer, 0);
            long presentationTime = videoExtractor.getSampleTime();

            if (size >= 0) {
                videoDecoder.queueInputBuffer(
                        decoderInputBufferIndex,
                        0,
                        size,
                        presentationTime,
                        videoExtractor.getSampleFlags());
            }
            videoExtractorDone = !videoExtractor.advance();

            if (!videoExtractorDone && videoExtractor.getSampleTime() > mVideoDurationLimit * 1000000) {
                videoExtractorDone = true;
            }

            if (videoExtractorDone)
                videoDecoder.queueInputBuffer(decoderInputBufferIndex,
                        0, 0, 0,  MediaCodec.BUFFER_FLAG_END_OF_STREAM);
            break;
        }

The full source code can be found here.

like image 832
Qylin Avatar asked Sep 19 '16 08:09

Qylin


1 Answers

I am not sure if this is the source of the error or not, but i think it is not safe write EOS to decoder buffer at arbitrary point.

The reason is when the input video is using H264 Main Profile or above, pts may not be in increasing order (because the existence of B-frame) so you may miss several frames at the end of the video. Also, when the last frame you send to the decoder is B-frame, decoder might be expecting the next packet but you send the EOS flag and produce error (not quite sure).

What you can do though, you can send EOS flag to the encoder using videoEncoder.signalEndOfInputStream() after you reach your desired frame, (pts of the output of decoder is guaranted to be in increasing order, at least after android version >= 4.3 ?)

like image 157
jfawkes Avatar answered Oct 17 '22 23:10

jfawkes