使用MediaCodec编码视频 - 具有空输出缓冲区

时间:2014-08-13 11:35:52

标签: android mediacodec

我想从mp4 video序列创建YUV images。我在Nexus 5,Android 4.4

上测试了这段代码

问题是我没有来自encoder的输出数据。 编码器只给我2次数据

  • 第一次26字节的csd-0 csd-1
  • 第2次编码数据3K?

然后编码.dequeueOutputBuffer(info,TIMEOUT_USEC)总是return -1 - INFO_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):编码器输出格式:   {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):提交第1帧至第08-13:17:23:37.637:   V / CAR_DVR(20874):编码器输出格式已更改:   {CSD-1 = java.nio.ByteArrayBuffer [位置= 0,极限= 8,容量= 8],   身高= 720,mime = video / avc,   CSD-0 = java.nio.ByteArrayBuffer [位置= 0,限制= 18,容量= 18],   what = 1869968451,width = 1280} 08-13 17:23:38.537:V / CAR_DVR(20874):   提交第2帧至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):第3帧提交至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):提交第4帧至08-13:17:03.187:   V / CAR_DVR(20874):编码器没有输出08-13 17:24:10.167:   V / CAR_DVR(20874):第5帧提交至08-13:17:24:14.477:   V / CAR_DVR(20874):编码器无输出08-13 17:24:14.787:   V / CAR_DVR(20874):提交第6帧至第08-13:17:24:14.787:   V / CAR_DVR(20874):编码器没有输出08-13 17:24:15.047:   V / CAR_DVR(20874):提交第7帧至08-13:17:24:15.047:   V / CAR_DVR(20874):编码器无输出08-13 17:24:15.317:   V / CAR_DVR(20874):提交第8帧至08-13:17:15:1517:   V / CAR_DVR(20874):编码器无输出08-13 17:24:15.577:   V / CAR_DVR(20874):提交第9帧至08-13:17:15:15.587:   V / CAR_DVR(20874):编码器无输出08-13 17:24:15.847:   V / CAR_DVR(20874):提交第10帧至08-13:17:15.847:   V / CAR_DVR(20874):编码器无输出08-13 17:24:16.107:   V / CAR_DVR(20874):提交第11帧至08-13:17:16:107:   V / CAR_DVR(20874):编码器无输出08-13 17:24:16.377:   V / CAR_DVR(20874):提交第12帧至08-13:17:16.377:   V / CAR_DVR(20874):编码器无输出08-13 17:24:16.637:   V / CAR_DVR(20874):提交第13帧至08-13:17:16.637:   V / CAR_DVR(20874):无编码器输出08-13 17:24:16.897:   V / CAR_DVR(20874):提交第14帧至08-13:24:16.897:   V / CAR_DVR(20874):编码器无输出08-13 17:24:17.157:   V / CAR_DVR(20874):提交第15帧至08-13:17:17:157:   V / CAR_DVR(20874):编码器无输出08-13 17:24:17.427:   V / CAR_DVR(20874):提交第16帧至08-13:17:17.427:   V / CAR_DVR(20874):编码器无输出08-13 17:24:17.697:   V / CAR_DVR(20874):提交第17帧至08-13:17:17:17.697:   V / CAR_DVR(20874):编码器无输出08-13 17:24:17.987:   V / CAR_DVR(20874):提交第18帧至08-13:17:17:1787:   V / CAR_DVR(20874):无编码器输出08-13 17:24:18.257:   V / CAR_DVR(20874):第19帧提交至08-13:17:24:18.257:   V / CAR_DVR(20874):无编码器输出08-13 17:24:18.297:   V / CAR_DVR(20874):发送输入EOS(零长度帧)08-13   17:24:18.297:V / CAR_DVR(20874):编码器无输出08-13   17:24:18.297:D / CAR_DVR(20874): - finish -

1 个答案:

答案 0 :(得分:3)

问题是,我没有计算ptsUsec。我只是添加ptsUsec = ptsUsec + 33;现在一切正常
ptsUsec - 表示时间 - 是当前帧的时间。
当ptsUsec没有改变时,编解码器认为它已经编码了帧没有任何内容