[英]ffmpeg library transcode from h263 to h264 video out of sync
目前,我设法实现了一个 function,它将给定的 h263 视频(3gp)转码为 h264 视频(mp4)。 除了视频编解码器之外,输入/输出文件中的所有其他内容都是相同的(例如音频编解码器、比特率、帧速率、分辨率……等)。
但是转码文件的视频 stream 与音频 stream 不同步,视频比音频慢约 1.5 倍。
为了确保转码时帧率和时基保持不变,我检查了我的编解码器和过滤器设置(如下面的示例代码所示),但我无法在我的代码中发现任何问题,这对解决问题没有帮助,我不明白这是怎么发生的,我在设置中遗漏了什么吗?
代码片段
对于编码器设置,它只是从输入容器的解码器中复制参数。
static void _app_config_dst_encoder(
AVCodecContext *enc_ctx, AVCodecContext *dec_ctx)
{
const AVCodec *encoder = enc_ctx->codec;
if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
enc_ctx->height = dec_ctx->height ;
enc_ctx->width = dec_ctx->width ;
enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
if (encoder->pix_fmts)
enc_ctx->pix_fmt = encoder->pix_fmts[0];
else
enc_ctx->pix_fmt = dec_ctx->pix_fmt;
enc_ctx->time_base = dec_ctx->time_base;
enc_ctx->framerate = dec_ctx->framerate;
enc_ctx->bit_rate = dec_ctx->bit_rate;
} else { // AVMEDIA_TYPE_AUDIO
enc_ctx->sample_rate = dec_ctx->sample_rate;
enc_ctx->bit_rate = dec_ctx->bit_rate;
enc_ctx->channel_layout = dec_ctx->channel_layout;
enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
enc_ctx->sample_fmt = encoder->sample_fmts[0];
enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate};
}
} // end of _app_config_dst_encoder
对于视频滤镜,为了简单起见,我没有使用额外的滤镜(例如scale
, setpts
, fps
...等),这里的代码主要来自ffmpeg 转码示例
typedef struct {
AVCodecContext *dec_ctx;
AVCodecContext *enc_ctx;
AVFilterContext *filt_sink_ctx;
AVFilterContext *filt_src_ctx;
AVFilterGraph *filter_graph;
size_t last_recovered_pkt_idx;
} StreamContext;
static int init_filter_video(
StreamContext *sctx, AVFilterGraph *filt_graph,
AVFilterContext **filt_ctx_src, AVFilterContext **filt_ctx_sink)
{
int ret = 0;
char args[512] = {0};
const AVFilter *buffersrc = avfilter_get_by_name("buffer");
const AVFilter *buffersink = avfilter_get_by_name("buffersink");
AVCodecContext *dec_ctx = sctx->dec_ctx;
AVCodecContext *enc_ctx = sctx->enc_ctx;
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
dec_ctx->time_base.num, dec_ctx->time_base.den,
dec_ctx->sample_aspect_ratio.num,
dec_ctx->sample_aspect_ratio.den );
avfilter_graph_create_filter(filt_ctx_src, buffersrc, "in", args, NULL, filt_graph);
avfilter_graph_create_filter(filt_ctx_sink, buffersink, "out", NULL, NULL, filt_graph);
av_opt_set_bin(*filt_ctx_sink, "pix_fmts", (uint8_t*)&enc_ctx->pix_fmt,
sizeof(enc_ctx->pix_fmt), AV_OPT_SEARCH_CHILDREN);
return ret;
} // end of init_filter_video
int init_filters(AVFormatContext *fmt_i_ctx)
{
int ret = 0;
int idx = 0;
int (*init_filter_fns[2])(StreamContext *, AVFilterGraph *, AVFilterContext **,
AVFilterContext **) = {init_filter_video, init_filter_audio};
// skip init_filter_audio() because it works without problem;
for (idx = 0; (!ret) && (idx < fmt_i_ctx->nb_streams); idx++)
{
StreamContext *sctx = &bd->stream_ctx[idx];
sctx->filt_sink_ctx = NULL;
sctx->filt_src_ctx = NULL;
sctx->filter_graph = NULL;
char filter_spec[128] = {0};
enum AVMediaType codectype = fmt_i_ctx->streams[idx]->codecpar->codec_type;
switch (codectype) {
case AVMEDIA_TYPE_VIDEO: // passthrough filter specification for video
snprintf(filter_spec, sizeof(filter_spec), "null");
break;
case AVMEDIA_TYPE_AUDIO: // passthrough filter specification for audio
snprintf(filter_spec, sizeof(filter_spec), "anull");
break;
default:
continue;
}
AVFilterContext *buffersrc_ctx = NULL;
AVFilterContext *buffersink_ctx = NULL;
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
AVFilterGraph *filter_graph = avfilter_graph_alloc();
ret = init_filter_fns[codectype](sctx, filter_graph, &buffersrc_ctx, &buffersink_ctx);
if(ret) { goto end; }
outputs->name = av_strdup("in");
outputs->filter_ctx = buffersrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = buffersink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
ret = avfilter_graph_parse_ptr(filter_graph, &filter_spec[0], &inputs, &outputs, NULL);
ret = avfilter_graph_config(filter_graph, NULL);
sctx->filt_src_ctx = buffersrc_ctx;
sctx->filt_sink_ctx = buffersink_ctx;
sctx->filter_graph = filter_graph;
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);
} // end of loop
return ret;
} // end of init_filters
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.