我正在为Android做一个视频压缩项目,我正在考虑通过设计一个新的视频编解码器来实现它(我已经设计了算法)。我已经阅读了视频压缩的基础知识,相关的相关算法和编解码器基础知识。我还发现 FFmpeg 可以作为Android上非常好的解决方案。
现在我的问题来了:
如何在FFmpeg中编写 新视频编解码器?我仍然是编写编解码器的初学者,但是 我该如何开始?我有一个粗略的想法,你必须首先编写至少一个解复用器,然后是特定的编码器和解码器等。 (请在这里索取参考资料。)
由于我的编解码器不能简单地调整视频属性,如fps,分辨率,比特率等。 在官方Android SDK中阅读 MediaCodec API和MediaPlayer API是否足以编写新的编解码器? (因为上次我看到它只支持MPEG-4 SP,H.263和H.264。我无法找到你是否可以直接编写自己的类和函数。)
谢谢。
答案 0 :(得分:2)
您可以在Android上使用ffmpeg作为工具或ffmpeg库集(libavcodec,libaviformat,...)。您可以以跨平台方式添加或更改ffmpeg编解码器,因为此项目非常强调平台独立性。您可以改用MediaCodec API。 但是没有办法扩展MediaCodec API (更新可以扩展MediaCodec,它记录在http://source.android.com/devices/media.html#codecs)并且没有简单的方法让ffmpeg使用此API。
答案 1 :(得分:2)
如果你是一个新手并且“只想在SW中做”,那就不要在SW中做了。我假设您的算法不需要是实时的,并且可以动态压缩视频数据,或者您需要使用HW编解码器。
这是Android MediaCodec Reference
MediaCodec codec = MediaCodec.createDecoderByType(type);
codec.configure(format, ...);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
for (;;) {
int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferIndex >= 0) {
// fill inputBuffers[inputBufferIndex] with valid data
...
codec.queueInputBuffer(inputBufferIndex, ...);
}
int outputBufferIndex = codec.dequeueOutputBuffer(timeoutUs);
if (outputBufferIndex >= 0) {
// outputBuffer is ready to be processed or rendered.
...
codec.releaseOutputBuffer(outputBufferIndex, ...);
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
MediaFormat format = codec.getOutputFormat();
...
}
}
codec.stop();
codec.release();
codec = null;
在读取“// outputBuffer已准备好处理或呈现”的行上应用您的编解码器。
那是你的第一帧将是outputBuffers [0]到outputBuffers [outputBufferIndex]。保存outputBufferIndex,即outputBufferIndex_old = outputBufferIndex;那么你的下一帧将是outputbuffers [outputBufferIndex_old]到outputbuffers [outputBufferIndex]。但这是一个循环缓冲区,所以在for循环中...啊啊啊
类似的东西:
//init
int old = 0;
int len = codec.BufferInfo().size,buff_len=outputBuffers.size;
Byte[] processBuffer = new Byte[len];
... // outputBuffer ready
for (int i=old; i<old+len; i++){
processBuffer[i-old] = outputBuffers[i%buff_len];
}
old = outputBufferIndex;
Here就是一个很好的例子。您可能需要查看MediaMetadataRetriever以获取有关输入视频的信息。高度和宽度等。每个像素的字节大小,如果您希望编码器对不同类型的视频具有鲁棒性。无论如何,这应该让你开始。
我强烈建议使用Matlab(或GNU Octave)进行视频编解码器的原型设计。它将为您节省大量时间。这意味着在尝试在几乎不可能的系统上实现它之前,您应该确保您的预期编解码算法有效,以便像Android一样进行调试。
希望这有帮助。
答案 2 :(得分:0)
如果有人偶然发现这个老问题,答案是:
就是这样。 ;)
需要考虑的事项: