我正在解码视频文件,然后编码为较小尺寸/比特率的视频文件。我已完成解码和获取原始视频输出缓冲区的过程,但是当我将原始输出缓冲区排队到编码器的输入缓冲区时,它会抛出溢出异常。由于输入缓冲区的容量太小而无法容纳原始输出缓冲区。
我发现如果我将编码器的输出格式的宽度和高度配置得更大,编码器的输入和输出缓冲器的容量也会更大。它们的值非常接近。当我将宽度和高度配置为原始视频大小,输入缓冲区大到足以容纳解码器的原始输出缓冲区,我得到输出视频文件。但我希望获得更小的尺寸和更小的位视频。< / 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希望与您讨论并得到您的帮助。谢谢!
答案 0 :(得分:2)
MediaCodec中的解码器无法自动调整大小,它始终以实际大小输出帧。 编码器还对帧进行编码并使用实际大小作为输入,并且无法在内部调整大小。因此,如果您想将帧放入大小不等于解码帧的编码器,则需要调整大小。
您还可以查看INDE Media Pack:https://software.intel.com/en-us/intel-inde/media-pack,它有MediaComposer类,可让您轻松调整视频大小