我使用 ffmpeg 解码 h264 并转码为 jpeg。
我以前用的2.8版本,现在改成4.0了。
新版本 avcodec_decode_video2 已弃用,因此我使用新 API(发送、接收)。
发现新版ffmpeg在解码h264时比旧版慢很多。
这是为什么?如何达到原来的速度?
这是解码器初始化代码?
版本 2.8
//2.8
if (avformat_open_input(&format_, path, NULL, &options) != 0) {
printf("FileMediaBase: open input failed\n");
return -1;
}
if (avformat_find_stream_info(format_, NULL) < 0) {
printf("FileMediaBase: avformat_find_stream_info failed\n");
avformat_close_input(&format_);
return -1;
}
AVCodecContext *code_ctx = 0;
AVCodec *codec = 0;
// Find the first audio and video stream
for (int i = 0; i < format_->nb_streams; i++) {
code_ctx = format_->streams[i]->codec;
codec = avcodec_find_decoder(code_ctx->codec_id);
if (code_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
vcode_ctx_ = code_ctx;
vstream_ = format_->streams[i];
}else if (code_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
acode_ctx_ = code_ctx;
astream_ = format_->streams[i];
}
// Open the codec
if (!codec || (avcodec_open2(code_ctx, codec, NULL) < 0)) {
printf("avcodec_open2() failed\n");
avformat_close_input(&format_);
return -1;
}
Run Code Online (Sandbox Code Playgroud)
版本 4.0
if (avformat_open_input(&format_, path, NULL, &options) != 0) {
printf("FileMediaBase: open input failed\n");
return -1;
}
if (avformat_find_stream_info(format_, NULL) < 0) {
printf("FileMediaBase: avformat_find_stream_info failed\n");
avformat_close_input(&format_);
return -1;
}
AVStream *st;
AVCodec *dec = NULL;
AVDictionary *opts = NULL;
ret = av_find_best_stream(format_, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (ret < 0) {
return ret;
}
else {
stream_index = ret;
st = format_->streams[stream_index];
/* find decoder for the stream */
dec = avcodec_find_decoder(st->codecpar->codec_id);
if (!dec) {
fprintf(stderr, "Failed to find %s codec\n",
av_get_media_type_string(type));
return AVERROR(EINVAL);
}
/* Allocate a codec context for the decoder */
*dec_ctx = avcodec_alloc_context3(dec);
if (!*dec_ctx) {
fprintf(stderr, "Failed to allocate the %s codec context\n",
av_get_media_type_string(type));
return AVERROR(ENOMEM);
}
/* Copy codec parameters from input stream to output codec context */
if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) {
fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",
av_get_media_type_string(type));
avcodec_free_context(dec_ctx);
return ret;
}
/*if (dec->id == AV_CODEC_ID_H264) {
(*dec_ctx)->flags |= AV_CODEC_FLAG_TRUNCATED;
}*/
/* Init the decoders, with or without reference counting */
//av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0);
if ((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) {
fprintf(stderr, "Failed to open %s codec\n",
av_get_media_type_string(type));
avcodec_free_context(dec_ctx);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我打印出在某些 API 上花费的时间

我已经解决了这个问题,将解码线程的数量(4.0 版默认为 1)更改为 6(2.8 版默认为 6)。
(*dec_ctx)->thread_count = 6;
Run Code Online (Sandbox Code Playgroud)
小智 5
我在使用 ffmpeg 2.8.14 和 4.0.1 版本解码 h264 视频流时遇到了同样的问题。在这两种情况下,在 avformat_find_stream_info() 之后访问编解码器上下文时
AVFormatContext *pFormatCtx;
AVCodecContext* pCodecCtxOrig;
...
avformat_find_stream_info(pFormatCtx, NULL)
...
for (uint i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
pCodecCtxOrig = pFormatCtx->streams[i]->codec;
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后 pCodecCtxOrig::thread_count 实际上设置为 0,这意味着 ffmpeg 库在使用avcodec_open2(). 在我的情况下,线程数设置为 5。
在 2.8.14 的情况下,pCodecCtxOrig::thread_count 设置为 0 并且从它进行复制时
AVCodecContext* pCodecCtxOrig;
AVCodecContext* pCodecCtx;
....
avcodec_copy_context(pCodecCtx, pCodecCtxOrig)
Run Code Online (Sandbox Code Playgroud)
thread_count 也被复制。
在 4.0.1 的情况下,avcodec_copy_context()不推荐使用 ,而avcodec_parameters_to_context()应使用 。应对结构AVCodecParameters不包含 thread_count 因此信息丢失。线程数保持默认值 1,由 设置avcodec_alloc_context3。thread_count在打开编解码器上下文之前克服设置为 0的问题。
| 归档时间: |
|
| 查看次数: |
1021 次 |
| 最近记录: |