avcodec_open 仅适用于未压缩格式
avcodec_open only works with uncompressed format
上下文:我有一个名为 libffmpeg.so 的文件,它是我从 Android
应用程序的 APK
中获取的,该应用程序使用 FFMPEG
对文件进行编码和解码几个 Codecs
。因此,我理所当然地认为这是在启用编码选项的情况下编译的,并且这个 .so 文件在某处包含所有编解码器。此文件是为 ARM
(我们在 Android
上称为 ARMEABI
配置文件)编译的。
我还有一个非常完整的 class,带有从 ffmpeg
调用 API
的互操作。无论此 static library
的来源是什么,所有呼叫响应都很好,并且大多数端点都存在。如果不是,我添加它们或修复已弃用的。
当我要创建ffmpeg
Encoder
时,返回的编码器是正确的。
var thisIsSuccessful = avcodec_find_encoder(myAVCodec.id);
现在,我遇到了 Codecs
的问题。问题是——假设出于好奇——我遍历了所有编解码器的列表,看看我可以用 avcodec_open 调用打开哪个编解码器 ...
AVCodec codec;
var res = FFmpeg.av_codec_next(&codec);
while((res = FFmpeg.av_codec_next(res)) != null)
{
var name = res->longname;
AVCodec* encoder = FFmpeg.avcodec_find_encoder(res->id);
if (encoder != null) {
AVCodecContext c = new AVCodecContext ();
/* put sample parameters */
c.bit_rate = 64000;
c.sample_rate = 22050;
c.channels = 1;
if (FFmpeg.avcodec_open (ref c, encoder) >= 0) {
System.Diagnostics.Debug.WriteLine ("[YES] - " + name);
}
} else {
System.Diagnostics.Debug.WriteLine ("[NO ] - " + name);
}
}
... 那么只有未压缩的编解码器才能工作。 (YUV、FFmpeg 视频 1 等)
我的假设是:
- 编译到 .so 文件时缺少一个选项
- av_open_codec 调用取决于我在调用中引用的 AVCodecContext 的属性。
我很好奇为什么只返回最少的未压缩编解码器集?
[编辑]
@ronald-s-bultje 的回答让我阅读了 AVCodecContext API 描述,并且在编码器上使用时有很多带有 "MUST be set by user" 的强制字段。在 AVCodecContext
上为这些参数设置一个值可以使用大部分不错的编解码器:
c.time_base = new AVRational (); // Output framerate. Here, 30fps
c.time_base.num = 1;
c.time_base.den = 30;
c.me_method = 1; // Motion-estimation mode on compression -> 1 is none
c.width = 640; // Source width
c.height = 480; // Source height
c.gop_size = 30; // Used by h264. Just here for test purposes.
c.bit_rate = c.width * c.height * 4; // Randomly set to that...
c.pix_fmt = FFmpegSharp.Interop.Util.PixelFormat.PIX_FMT_YUV420P; // Source pixel format
The av_open_codec calls is acting depending on the properties of the
AVCodecContext I've referenced in the call.
基本上就是这样。我的意思是,对于视频编码器,你甚至没有设置 width/height,所以大多数编码器真的不能指望做任何有用的事情,而且错误是正确的。
您可以设置默认参数,例如avcodec_get_context_defaults3(),这应该可以帮助您在 AVCodecContext 中获得一些有用的设置。之后,将典型的 width/height/pix_fmt 设置为描述输入格式的那些(如果你想进行音频编码 - 这实际上从你的问题中不清楚,你需要设置一些不同的像 sample_fmt/sample_rate/channels,但想法相同)。然后你应该就比较好走了。
上下文:我有一个名为 libffmpeg.so 的文件,它是我从 Android
应用程序的 APK
中获取的,该应用程序使用 FFMPEG
对文件进行编码和解码几个 Codecs
。因此,我理所当然地认为这是在启用编码选项的情况下编译的,并且这个 .so 文件在某处包含所有编解码器。此文件是为 ARM
(我们在 Android
上称为 ARMEABI
配置文件)编译的。
我还有一个非常完整的 class,带有从 ffmpeg
调用 API
的互操作。无论此 static library
的来源是什么,所有呼叫响应都很好,并且大多数端点都存在。如果不是,我添加它们或修复已弃用的。
当我要创建ffmpeg
Encoder
时,返回的编码器是正确的。
var thisIsSuccessful = avcodec_find_encoder(myAVCodec.id);
现在,我遇到了 Codecs
的问题。问题是——假设出于好奇——我遍历了所有编解码器的列表,看看我可以用 avcodec_open 调用打开哪个编解码器 ...
AVCodec codec;
var res = FFmpeg.av_codec_next(&codec);
while((res = FFmpeg.av_codec_next(res)) != null)
{
var name = res->longname;
AVCodec* encoder = FFmpeg.avcodec_find_encoder(res->id);
if (encoder != null) {
AVCodecContext c = new AVCodecContext ();
/* put sample parameters */
c.bit_rate = 64000;
c.sample_rate = 22050;
c.channels = 1;
if (FFmpeg.avcodec_open (ref c, encoder) >= 0) {
System.Diagnostics.Debug.WriteLine ("[YES] - " + name);
}
} else {
System.Diagnostics.Debug.WriteLine ("[NO ] - " + name);
}
}
... 那么只有未压缩的编解码器才能工作。 (YUV、FFmpeg 视频 1 等)
我的假设是:
- 编译到 .so 文件时缺少一个选项
- av_open_codec 调用取决于我在调用中引用的 AVCodecContext 的属性。
我很好奇为什么只返回最少的未压缩编解码器集?
[编辑]
@ronald-s-bultje 的回答让我阅读了 AVCodecContext API 描述,并且在编码器上使用时有很多带有 "MUST be set by user" 的强制字段。在 AVCodecContext
上为这些参数设置一个值可以使用大部分不错的编解码器:
c.time_base = new AVRational (); // Output framerate. Here, 30fps
c.time_base.num = 1;
c.time_base.den = 30;
c.me_method = 1; // Motion-estimation mode on compression -> 1 is none
c.width = 640; // Source width
c.height = 480; // Source height
c.gop_size = 30; // Used by h264. Just here for test purposes.
c.bit_rate = c.width * c.height * 4; // Randomly set to that...
c.pix_fmt = FFmpegSharp.Interop.Util.PixelFormat.PIX_FMT_YUV420P; // Source pixel format
The av_open_codec calls is acting depending on the properties of the AVCodecContext I've referenced in the call.
基本上就是这样。我的意思是,对于视频编码器,你甚至没有设置 width/height,所以大多数编码器真的不能指望做任何有用的事情,而且错误是正确的。
您可以设置默认参数,例如avcodec_get_context_defaults3(),这应该可以帮助您在 AVCodecContext 中获得一些有用的设置。之后,将典型的 width/height/pix_fmt 设置为描述输入格式的那些(如果你想进行音频编码 - 这实际上从你的问题中不清楚,你需要设置一些不同的像 sample_fmt/sample_rate/channels,但想法相同)。然后你应该就比较好走了。