qsv滤镜使用遇到的各种报错

[mjpeg_qsv] get_buffer() failed

qsv解码后,使用滤镜经常会遇到这个问题。报这个错误是因为GPU的显存数据无法直接使用。
如下:
qsv滤镜使用遇到的各种报错_第1张图片

访问qsv解码后存入GPU的数据有两种方式。
1.把显存的数据copy到系统内存

re = av_hwframe_transfer_data(sw_pframe, praw_frame, 0);

这个接口的问题是,从GPU->CPU的数据拷贝,过于消耗cpu,也费时,远大于系统内存之间的拷贝,可能因为显卡是外设的原因吧。因此有了下面这一种不拷贝的方式。

2.将显存中的数据映射成可以访问的数据。
(此时数据依然还在显存中,只是我们拥有了访问的能力。若未经映射,即使有地址如praw_frame->data,一读写就报错),笔者环境为intel N6000,4核4线程,切换为这种方式后,id节省了10%。
但用它也经常会带来一些问题。

re = av_hwframe_map(sw_pframe, praw_frame, 0);

就比如标题中的报错问题
我们用滤镜如下,用2.映射地址的方式,将sw_pframe传入滤镜。
若此时不进行其中的像素格式转换,就会报标题的错误。

av_bprintf(&args,
"buffer=video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d[main];"
"buffer=video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d[logo];"
"[main][logo]overlay=x=10:y=10[result];"
"[result]format=yuv420p[result_2];"
"[result_2]buffersink",
frame->width, frame->height, frame->format, tb.num, tb.den, sar.num, sar.den, fr.num, fr.den,
logo_frame->width, logo_frame->height, logo_frame->format, logo_tb.num, logo_tb.den,
logo_sar.num, logo_sar.den, logo_fr.num, logo_fr.den);

然后add输入,get数据。注意result_frame->data的内存是接口分配的。因此从sw_pframe到result_frame其实是一次深拷贝。并且从显存copy到系统内存了。而av_buffersink_get_frame_flags并不具备这个能力,因此才会报上述错误。
加上像素格式转换就正常了呢,因此可以看出滤镜的像素格式转换拥有av_hwframe_transfer_data的能力。
发现进行nv12的像素格式转换,依然报上述错误。因为数据inter硬件解码后就是nv12,不会进行这步。因此也没有完成av_hwframe_transfer_data过程。

AVFrame *result_frame = av_frame_alloc();
....//伪代码
ret = av_buffersrc_add_frame_flags(mainsrc_ctx, sw_pframe,AV_BUFFERSRC_FLAG_PUSH);

ret = av_buffersink_get_frame_flags(resultsink_ctx, result_frame,AV_BUFFERSINK_FLAG_NO_REQUEST);

测试发现,未调用下面这个函数,也报以上错误。

av_hwframe_ctx_init(avctx->hw_frames_ctx);
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d"
			":frame_rate=%d/%d",
			dec_ctx->width, dec_ctx->height, AV_PIX_FMT_QSV, // dec_ctx->pix_fmt, AV_PIX_FMT_NV12 AV_PIX_FMT_QSV
			dec_ctx->time_base.num, dec_ctx->time_base.den,
			dec_ctx->sample_aspect_ratio.num,
			dec_ctx->sample_aspect_ratio.den,
			dec_ctx->framerate.num, dec_ctx->framerate.den);
			
cout << "dec_ctx->width:" << dec_ctx->width << " dec_ctx->height:" << dec_ctx->height << " frame->format:" << AV_PIX_FMT_QSV << " tb.num:" << dec_ctx->time_base.num << " tb.den:" << dec_ctx->time_base.den << " sar.num:" << dec_ctx->sample_aspect_ratio.num  << " sar.den:" << dec_ctx->sample_aspect_ratio.den << " framerate.num:" << dec_ctx->framerate.num << " framerate.den:" << dec_ctx->framerate.den << endl; 

avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
			args, NULL, filter_graph);
[in @ 0x7f1cb0007400] Changing video frame properties on the fly is not supported by all filters.

报以上错误是因为QSV的滤镜时,以上像素格式只能是AV_PIX_FMT_QSV。

[in @ 0x7fffc4014940] Invalid parameters provided.
Cannot create buffer source

报以上错误时程序在av_buffersrc_add_frame_flags段错误,日志如下:

dec_ctx->width:1920 dec_ctx->height:1080 frame->format:114 tb.num:0 tb.den:1 sar.num:0 sar.den:1 framerate.num:0 framerate.den:1

正确的日志如下:

dec_ctx->width:1920 dec_ctx->height:1080 frame->format:114 tb.num:1 tb.den:30 sar.num:0 sar.den:1 framerate.num:30 framerate.den:1

可以看出因为传给滤镜的帧率和时间基出了问题导致这个错误。这时候可以用一下函数进行复制

decodec_ctx->framerate = video_st->avg_frame_rate;
decodec_ctx->time_base = av_inv_q(decodec_ctx->framerate);

avcodec_parameters_to_context(decodec_ctx, video_st->codecpar);函数并不能完成上面的操作,因为video_st->codecpar里不包含这两个字段。

如果是竖拼比如1088x1920,那么编码器的宽高一定要配置好,不然就好报如下错误,其中@@@是av_strerror(errNum, buf, sizeof(buf));打印的日志:

[h264_qsv @ 0x56181c705b40] Error during encoding: undefined behavior (-16)
@@@buf:Internal bug, should not have happened@@@

实测应该这样配置:

encodec_ctx->height = 1920;//decodec_ctx->height;//1920;
encodec_ctx->width = 1088;//decodec_ctx->width;//1088;
或
encodec_ctx->width = 1080;//decodec_ctx->width;//1088;

对于enc_frame->width可以为1088也可以为1080

enc_frame->width = encodec_ctx->width;//encodec_ctx->width;//1088;
enc_frame->height = encodec_ctx->height;//encodec_ctx->height;//1920;
avcodec_send_frame(encodec_ctx, enc_frame);

ffmpeg是音视频必备,但即使从业数年,它似乎依然有无穷的秘密,感兴趣添加笔者微信:YQW1163720468,加入ffmpeg微信群讨论。但记得备注:ffmpeg爱好者

你可能感兴趣的:(ffmpeg,INFO,ffmpeg,qsv,滤镜,get_buffer)