0

I want to create mp4 video from YUV images sequence. I test this code on my Nexus 5, Android 4.4

Problem is i have no output data from encoder. Encoder give me data just 2 times

  • 1-st time 26 bytes of csd-0 csd-1
  • 2-nd time 3K of encoded data ?

And then encoder.dequeueOutputBuffer(info, TIMEOUT_USEC) alway return -1INFO_TRY_AGAIN_LATER

CODE

    String type="video/avc";

    MediaCodecInfo codecInfo = selectCodec(type);
    int colorFormat = selectColorFormat(codecInfo, type); // This return 21

    MediaFormat format = MediaFormat.createVideoFormat(type,
            videowidth, videoheight); //"video/avc" 1280 720
    // Set some properties
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 17000000);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
    format.setInteger(MediaFormat.KEY_WIDTH,videowidth);
    format.setInteger(MediaFormat.KEY_HEIGHT,videoheight);

    encoder = MediaCodec.createByCodecName(codecInfo.getName());
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    encoder.start(); //ок

    ByteBuffer[] encoderInputBuffers = encoder.getInputBuffers();
    ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();

    BufferInfo info = new BufferInfo();
    int k = 0; // just counter
    int inputBufIndex;
    int encoderStatus=0;
    int col=20; // i want to encode 20 frames


    info = new BufferInfo();

    while (k < col) {
        k++;
            try {
                Thread.sleep(33); //some pause
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


            //input to buffer always works fine
            inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);

            if (inputBufIndex >= 0) {

                if (k == col) { //EOS
                    encoder.queueInputBuffer(inputBufIndex, 0, 0, ptsUsec,
                            MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    Log.v(TAG, "sent input EOS (with zero-length frame)");
                } else {

                    ByteBuffer inputBuf = encoderInputBuffers[inputBufIndex];

                    inputBuf.clear();

                    byte[] frameData = new byte[videowidth * videoheight * 3 / 2]; //1 plane w*h Y + 2 planes w*h/2 Cb Cr

                    Arrays.fill(frameData, (byte) 0); // zero for example 
                    inputBuf.put(frameData);
                    encoder.queueInputBuffer(inputBufIndex, 0,
                            frameData.length, ptsUsec, 0);
                    Log.v(TAG, "submitted frame " + k + " to enc");
                }

            } else {
                // either all in use, or we timed out during initial setup
                Log.v(TAG, "input buffer not available");
            }


            // output Buffer have problems
             info = new BufferInfo();
             encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
            // 1-st time encoderStatus =-2 INFO_OUTPUT_FORMAT_CHANGED
            // 2-nd time encoderStatus =0
            // 3 to 20 times encoderStatus =-1
            if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
                // no output available yet
                Log.v(TAG, "no output from encoder available");
            } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                encoderOutputBuffers = encoder.getOutputBuffers();
                Log.v(TAG, "encoder output buffers changed");

            } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                Log.v(TAG, "encoder output format changed: " +encoder.getOutputFormat() );
            } else if (encoderStatus < 0) {
                 Log.v(TAG, "unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
            } else { // encoderStatus >= 0
                ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
                if (encodedData == null) {
                     Log.v(TAG, "encoderOutputBuffer " + encoderStatus + " was null");
                } 
                else 
                {
                    Log.v(TAG, "encoderOutputBuffer " + info.size+" | "+encoderStatus+" | "+info );
                }




                encoder.releaseOutputBuffer(encoderStatus, false);
            } 

    }

    Log.d(TAG, "-finish-");

LOG:


08-13 17:23:32.927: V/CAR_DVR(20874): encoder output format: {frame-rate=30, bitrate=17000000, height=720, mime=video/avc, color-format=21, i-frame-interval=10, width=1280} 08-13 17:23:35.347: V/CAR_DVR(20874): submitted frame 1 to enc 08-13 17:23:37.637: V/CAR_DVR(20874): encoder output format changed: {csd-1=java.nio.ByteArrayBuffer[position=0,limit=8,capacity=8], height=720, mime=video/avc, csd-0=java.nio.ByteArrayBuffer[position=0,limit=18,capacity=18], what=1869968451, width=1280} 08-13 17:23:38.537: V/CAR_DVR(20874): submitted frame 2 to enc 08-13 17:23:39.177: V/CAR_DVR(20874): encoderOutputBuffer 26 | 0 | android.media.MediaCodec$BufferInfo@4264dfb0 08-13 17:23:40.007: V/CAR_DVR(20874): submitted frame 3 to enc 08-13 17:23:55.207: V/CAR_DVR(20874): encoderOutputBuffer 3625 | 1 | android.media.MediaCodec$BufferInfo@42654b60 08-13 17:23:57.067: V/CAR_DVR(20874): submitted frame 4 to enc 08-13 17:24:03.187: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:10.167: V/CAR_DVR(20874): submitted frame 5 to enc 08-13 17:24:14.477: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:14.787: V/CAR_DVR(20874): submitted frame 6 to enc 08-13 17:24:14.787: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.047: V/CAR_DVR(20874): submitted frame 7 to enc 08-13 17:24:15.047: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.317: V/CAR_DVR(20874): submitted frame 8 to enc 08-13 17:24:15.317: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.577: V/CAR_DVR(20874): submitted frame 9 to enc 08-13 17:24:15.587: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:15.847: V/CAR_DVR(20874): submitted frame 10 to enc 08-13 17:24:15.847: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.107: V/CAR_DVR(20874): submitted frame 11 to enc 08-13 17:24:16.107: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.377: V/CAR_DVR(20874): submitted frame 12 to enc 08-13 17:24:16.377: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.637: V/CAR_DVR(20874): submitted frame 13 to enc 08-13 17:24:16.637: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:16.897: V/CAR_DVR(20874): submitted frame 14 to enc 08-13 17:24:16.897: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.157: V/CAR_DVR(20874): submitted frame 15 to enc 08-13 17:24:17.157: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.427: V/CAR_DVR(20874): submitted frame 16 to enc 08-13 17:24:17.427: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.697: V/CAR_DVR(20874): submitted frame 17 to enc 08-13 17:24:17.697: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:17.987: V/CAR_DVR(20874): submitted frame 18 to enc 08-13 17:24:17.987: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.257: V/CAR_DVR(20874): submitted frame 19 to enc 08-13 17:24:18.257: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.297: V/CAR_DVR(20874): sent input EOS (with zero-length frame) 08-13 17:24:18.297: V/CAR_DVR(20874): no output from encoder available 08-13 17:24:18.297: D/CAR_DVR(20874): -finish-

E.Abdel
  • 1,992
  • 1
  • 13
  • 24
ego
  • 63
  • 1
  • 7
  • If you loop until you see EOS on the output, rather than stopping immediately after supplying EOS on the input, does it work? I'm wondering if it's buffering the output because the input is trivial, and you're not seeing the actual output because the propagation delay through the codec means you're exiting the loop before it has a chance to deliver the output. Also, you should get rid of the `Thread.sleep()`, and compute `ptsUsec` based on the frame number. – fadden Aug 13 '14 at 15:34
  • Thank you, for your answer. If i loop until see EOS on the output, i take infinity loop. EOS never come to output. I think propagation delay does not matter in this case - the codec have enough time for encoding - over 1/30 sec. – ego Aug 14 '14 at 02:47
  • Thank you. Solved. Problem is, that i not compute ptsUsec. I just add ptsUsec=ptsUsec+33; and now all works fine. – ego Aug 14 '14 at 03:26

1 Answers1

4

Problem is, that i not compute ptsUsec. I just add ptsUsec=ptsUsec+33; and now all works fine.
ptsUsec - presentation time - is the time of current frame.
When ptsUsec not changed, codec thinking that it is already encoded frame does nothing

ego
  • 63
  • 1
  • 7