9

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.

Community
  • 1
  • 1
Qylin
  • 1,501
  • 1
  • 16
  • 26
  • 1
    if you want, take a look at [Google's ExoPlayer](https://github.com/google/ExoPlayer). it has more simple API – Crocodilys Sep 26 '16 at 14:03
  • Can you post your full logcat output? – Willis Sep 26 '16 at 14:56
  • @crocodilys Is exoplayer just a player? I don't think it can transcode video. Am I wrong? – Qylin Sep 27 '16 at 06:42
  • @willis Thank your for your reply. I think the whole idea is incorrect. Actually I'm using a OSS android-transcoder. It's much better than the raw api. I would say the main gain is the performance. The transcoding time was improved to 5~6 seconds from 11 seconds. – Qylin Sep 27 '16 at 06:44
  • I would like to prefer you ffmpeg. Please check the answer here, http://stackoverflow.com/a/38299320/3992798 – parik dhakan Sep 28 '16 at 04:41
  • @parikdhakan I considered that before. But since the MediaCodec is the official API, I think it's more future proof. – Qylin Sep 28 '16 at 06:53
  • wow it works like a charm . thank you –  Sep 28 '16 at 07:39
  • I'm an author of linked QA, but I'm not maintaining this code anymore... Another team member bring me exacly same error code, have you resolved this issue? (in my case it started to occur in Android 10 when targeting it) – snachmsm Sep 17 '19 at 10:40
  • @Qylin & snamchmsm : I am getting same issue in android 10 any fix then please help – Mohsin Khan May 02 '20 at 08:24

1 Answers1

1

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 ?)

jfawkes
  • 396
  • 1
  • 7