как добавить ссылочный фильм в фильтр ffmpeg psnr в кодах (вычисление psnr)

#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