如何配置MediaCodec创建的编码器输入缓冲区大小?

时间:2014-10-06 06:05:19

标签: android encode mediacodec

我正在解码视频文件,然后编码为较小尺寸/比特率的视频文件。我已完成解码和获取原始视频输出缓冲区的过程,但是当我将原始输出缓冲区排队到编码器的输入缓冲区时,它会抛出溢出异常。由于输入缓冲区的容量太小而无法容纳原始输出缓冲区。

我发现如果我将编码器的输出格式的宽度和高度配置得更大,编码器的输入和输出缓冲器的容量也会更大。它们的值非常接近。当我将宽度和高度配置为原始视频大小,输入缓冲区大到足以容纳解码器的原始输出缓冲区,我得到输出视频文件。但我希望获得更小的尺寸和更小的位视频。< / p>

关键代码如下。

MediaCodecInfo codecInfo = selectCodec("video/avc");

MediaFormat outformat = MediaFormat.createVideoFormat("video/avc", 1280, 720);

int colorfmt = selectColorFormat(codecInfo, "video/avc");

outformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorfmt);//2141391876);    

outformat.setInteger(MediaFormat.KEY_BIT_RATE, 178*1024*8);

outformat.setInteger(MediaFormat.KEY_FRAME_RATE, 24);

outformat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

//outformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 3400000);;

MediaCodec encoder = MediaCodec.createEncoderByType("video/avc");

encoder.configure(outformat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

encoder.start();

提取视频和解码

   int inIndex = decoder.dequeueInputBuffer(10000);

   if (inIndex >= 0) {

   ByteBuffer buffer = inputBuffers[inIndex];

   int sampleSize = extractor.readSampleData(buffer, 0);

   if (sampleSize < 0) {

       decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);

       isEOS = true;

   } else {

       decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);

    extractor.advance();

   }

}

将mpcode和mux编码到mp4文件

int outIndex = decoder.dequeueOutputBuffer(info, 10000);

switch (outIndex) {

case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:

    Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");

    outputBuffers = decoder.getOutputBuffers();

    break;

case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:

    Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());

    MediaFormat infmt = decoder.getOutputFormat();

    break;

case MediaCodec.INFO_TRY_AGAIN_LATER:

    Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");

    break;

default:

    ByteBuffer buffer = outputBuffers[outIndex];
    buffer.position(info.offset);
    buffer.limit(info.offset + info.size);
    int encInputIndex = encoder.dequeueInputBuffer(10000);
    if (encInputIndex >= 0) {
        ByteBuffer encBuffer = encInputBuf[encInputIndex];
        encBuffer.clear();
        encBuffer.put(buffer);
        encoder.queueInputBuffer(encInputIndex, 0, info.size, info.presentationTimeUs,0);
    }



ByteBuffer[] encOutputBuf = encoder.getOutputBuffers();
   int trackindex = 0;
   while(true) {
       MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
       int encoderStatus = encoder.dequeueOutputBuffer(bufferInfo, 10000);
       if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
          // no output available yet
          break;                
       } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
          // not expected for an encoder
          encOutputBuf = encoder.getOutputBuffers();
       } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
          MediaFormat newFormat = encoder.getOutputFormat();
          // now that we have the Magic Goodies, start the muxer
          trackindex = muxer.addTrack(newFormat);
          muxer.start();
     } else if (encoderStatus < 0) {
          // let's ignore it
     } else {
          ByteBuffer buf = encOutputBuf[encoderStatus];
          muxer.writeSampleData(trackindex, buf, bufferInfo);
          encoder.releaseOutputBuffer(encoderStatus, false);
     }
}

@fadden希望与您讨论并得到您的帮助。谢谢!

1 个答案:

答案 0 :(得分:2)

MediaCodec中的解码器无法自动调整大小,它始终以实际大小输出帧。 编码器还对帧进行编码并使用实际大小作为输入,并且无法在内部调整大小。因此,如果您想将帧放入大小不等于解码帧的编码器,则需要调整大小。

您还可以查看INDE Media Pack:https://software.intel.com/en-us/intel-inde/media-pack,它有MediaComposer类,可让您轻松调整视频大小