我只想了解如何在代码中使用ffmpeg中的psnr过滤器。
我已遵循https://ffmpeg.org/ffmpeg-filters.html#psnr中所述的代码:
sprintf(args, "movie=ref_movie.avi [main];[main][ref] psnr=\"stats_file=stats.log\" [out]");
err = avfilter_graph_create_filter(&psnrCtx, psnrFilter, "psnr", args, NULL, m_filterGraph);
if ( err < 0 ) {
avfilter_graph_free(&m_filterGraph);
m_filterGraph = NULL;
return false; }
但错误信息会回复给我:
Option 'movie' not found
我也试试这个:
sprintf(args, "stats_file=stats.log");
err = avfilter_graph_create_filter(&psnrCtx, psnrFilter, "psnr", args, NULL, m_filterGraph);
if ( err < 0 ) {
avfilter_graph_free(&m_filterGraph);
m_filterGraph = NULL;
return false; }
err = avfilter_link(last_ctx, 0, psnrCtx, 0);
if ( err < 0 ) {
avfilter_graph_free(&m_filterGraph);
m_filterGraph = NULL;
return false;}
...
err = avfilter_graph_config(m_filterGraph, NULL);
if ( err < 0 ) {
avfilter_graph_free(&m_filterGraph);
m_filterGraph = NULL;
return false;
}
但是错误消息返回给我:
Input pad "reference" with type video of the filter instance "psnr" of psnr not connected to any source
我在代码中搜索psnr过滤器,但没有太多关于它的信息。任何人都可以帮忙吗?
答案 0 :(得分:3)
您正在使用avfilter_graph_create_filter()
创建过滤器图形而不是过滤器。请改用avfilter_graph_parse2()
来创建整个过滤器图表。
过滤器图形与您在ffmpeg命令行中的-filter_complex中输入的图形相同。例如,参见这个用作获取电影元素的输入字符串的示例:
ffmpeg -filter_complex 'movie=file.mpg[in];movie=ref.mpg[ref];[in][ref]psnr[out]' -map '[out]' -f null -
在解析过滤器图表之前,不要忘记调用avfilter_register_all()
和av_register_all()
,否则电影元素将不会被注册。
完整的示例代码:
#include <assert.h>
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavformat/avformat.h"
int main() {
AVFilterGraph *filter_graph;
AVFilterInOut *inputs = NULL, *outputs = NULL;
AVFilterContext *buffersink_ctx;
AVFrame *f;
avfilter_register_all();
av_register_all();
filter_graph = avfilter_graph_alloc();
int ret;
ret = avfilter_graph_parse2(filter_graph,
"movie=file.mpg[in];"
"movie=ref.mpg[ref];"
"[in][ref]psnr[out];"
"[out]buffersink",
&inputs, &outputs);
if (ret < 0) return ret;
ret = avfilter_graph_config(filter_graph, NULL);
if (ret < 0) return ret;
buffersink_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffersink_3");
assert(buffersink_ctx != NULL);
f = av_frame_alloc();
for (;;) {
ret = av_buffersink_get_frame(buffersink_ctx, f);
if (ret < 0) break;
av_frame_unref(f);
}
av_frame_free(&f);
avfilter_graph_free(&filter_graph);
return 0;
}
要从循环内的f
中提取每帧PSN值,请使用以下内容:
static void parse_psnr(AVFrame *f) {
AVDictionary *metadata = av_frame_get_metadata(f);
float psnr[4];
#define parse(a, b) \
sscanf(av_dict_get(metadata, a, NULL, 0)->value, "%f", &b)
parse("lavfi.psnr.psnr.y", psnr[0]);
parse("lavfi.psnr.psnr.u", psnr[1]);
parse("lavfi.psnr.psnr.v", psnr[2]);
parse("lavfi.psnr.psnr_avg", psnr[3]);
}
要获取打印到stdout(序列范围的PSNR)的最终值,可以使用av_log_set_callback()
设置日志回调并适当地解析字符串。