#filter #ffmpeg
#Фильтр #ffmpeg
Вопрос:
Я просто хочу узнать, как использовать фильтр psnr в ffmpeg в кодах.
Я следовал кодам, указанным в 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(amp;psnrCtx, psnrFilter, "psnr", args, NULL, m_filterGraph);
if ( err < 0 ) {
avfilter_graph_free(amp;m_filterGraph);
m_filterGraph = NULL;
return false; }
Но сообщение об ошибке возвращается ко мне:
Option 'movie' not found
Я также пытаюсь это:
sprintf(args, "stats_file=stats.log");
err = avfilter_graph_create_filter(amp;psnrCtx, psnrFilter, "psnr", args, NULL, m_filterGraph);
if ( err < 0 ) {
avfilter_graph_free(amp;m_filterGraph);
m_filterGraph = NULL;
return false; }
err = avfilter_link(last_ctx, 0, psnrCtx, 0);
if ( err < 0 ) {
avfilter_graph_free(amp;m_filterGraph);
m_filterGraph = NULL;
return false;}
...
err = avfilter_graph_config(m_filterGraph, NULL);
if ( err < 0 ) {
avfilter_graph_free(amp;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 в кодах, но информации об этом не так много. Кто-нибудь может помочь в этом?
Ответ №1:
Вы используете avfilter_graph_create_filter()
для создания фильтра-графика вместо фильтра. Используйте avfilter_graph_parse2()
вместо этого для создания целых графиков фильтров.
Графики фильтров идентичны тем, которые вы вводите в -filter_complex в командной строке ffmpeg. Смотрите, например, Этот пример того, какую строку вы бы использовали в качестве входных данных для получения элемента movie:
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()
перед анализом вашего графика фильтра, иначе элемент movie еще не будет зарегистрирован.
Полный фрагмент примера кода:
#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",
amp;inputs, amp;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(amp;f);
avfilter_graph_free(amp;filter_graph);
return 0;
}
Чтобы извлечь значения PSN для каждого кадра f
внутри цикла, используйте что-то вроде этого:
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", amp;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]);
}
Чтобы получить окончательные значения, которые выводятся в стандартный вывод (PSNR для всей последовательности), вы можете установить обратный вызов журнала с помощью av_log_set_callback()
и соответствующим образом проанализировать строку.
Комментарии:
1. Спасибо за ваш ответ, еще одна вещь, которую я хочу спросить, касается SSIM, какие параметры можно выбрать, точно так же, как lavfi.psnr.psnr. y в PSNR
2. lavfi.ssim.dB.Y, lavfi.ssim.dB.U, lavfi.ssim.dB.V и lavfi.ssim.dB