2017-03-27 8 views
1

initialisiert wird Ich möchte das transcoding.c-Beispiel implementieren, das auf der FFMPEG-Website gehostet wird. Die avfilter_graph_create_filter-Funktion ist jedoch mit einem Rückkehrcode -22 (Zeile 175) fehlgeschlagen. Ich habe nur eine kleine Änderung am Quellcode vorgenommen, damit dieser in meiner C++ - Konsolenanwendung ausgeführt werden kann. Ich habe es auch online gesucht, konnte aber keine hilfreichen Informationen finden. Unten ist mein Code:FFMPEG: avfilter_graph_create_filter-Methode fehlgeschlagen, wenn Filter

extern "C" 
{ 
#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include <libavfilter/avfiltergraph.h> 
#include <libavfilter/buffersink.h> 
#include <libavfilter/buffersrc.h> 
#include <libavutil/opt.h> 
#include <libavutil/pixdesc.h> 
} 
static AVFormatContext *ifmt_ctx; 
static AVFormatContext *ofmt_ctx; 
typedef struct FilteringContext { 
    AVFilterContext *buffersink_ctx; 
    AVFilterContext *buffersrc_ctx; 
    AVFilterGraph *filter_graph; 
} FilteringContext; 
static FilteringContext *filter_ctx; 

static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, 
    AVCodecContext *enc_ctx, const char *filter_spec) 
{ 
    char args[512]; 
    int ret = 0; 
    AVFilter *buffersrc = NULL; 
    AVFilter *buffersink = NULL; 
    AVFilterContext *buffersrc_ctx = NULL; 
    AVFilterContext *buffersink_ctx = NULL; 
    AVFilterInOut *outputs = avfilter_inout_alloc(); 
    AVFilterInOut *inputs = avfilter_inout_alloc(); 
    AVFilterGraph *filter_graph = avfilter_graph_alloc(); 
    if (!outputs || !inputs || !filter_graph) { 
     ret = AVERROR(ENOMEM); 
     goto end; 
    } 
    if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { 
     buffersrc = avfilter_get_by_name("buffer"); 
     buffersink = avfilter_get_by_name("buffersink"); 
     if (!buffersrc || !buffersink) { 
      av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n"); 
      ret = AVERROR_UNKNOWN; 
      goto end; 
     } 
     /*sprintf(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);*/ 
     ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", 
      args, NULL, filter_graph); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n"); 
      goto end; 
     } 
     ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", 
      NULL, NULL, filter_graph); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n"); 
      goto end; 
     } 
     ret = av_opt_set_bin(buffersink_ctx, "pix_fmts", 
      (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt), 
      AV_OPT_SEARCH_CHILDREN); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n"); 
      goto end; 
     } 
    } 
    else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { 
     buffersrc = avfilter_get_by_name("abuffer"); 
     buffersink = avfilter_get_by_name("abuffersink"); 
     if (!buffersrc || !buffersink) { 
      av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n"); 
      ret = AVERROR_UNKNOWN; 
      goto end; 
     } 
     if (!dec_ctx->channel_layout) 
      dec_ctx->channel_layout = 
      av_get_default_channel_layout(dec_ctx->channels); 
     /*snprintf(args, sizeof(args), 
      "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, 
      dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, 
      av_get_sample_fmt_name(dec_ctx->sample_fmt), 
      dec_ctx->channel_layout);*/ 
     ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", 
      args, NULL, filter_graph); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n"); 
      goto end; 
     } 
     ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", 
      NULL, NULL, filter_graph); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n"); 
      goto end; 
     } 
     ret = av_opt_set_bin(buffersink_ctx, "sample_fmts", 
      (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt), 
      AV_OPT_SEARCH_CHILDREN); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n"); 
      goto end; 
     } 
     ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", 
      (uint8_t*)&enc_ctx->channel_layout, 
      sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); 
      goto end; 
     } 
     ret = av_opt_set_bin(buffersink_ctx, "sample_rates", 
      (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate), 
      AV_OPT_SEARCH_CHILDREN); 
     if (ret < 0) { 
      av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n"); 
      goto end; 
     } 
    } 
    else { 
     ret = AVERROR_UNKNOWN; 
     goto end; 
    } 
    /* Endpoints for the filter graph. */ 
    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; 
    if (!outputs->name || !inputs->name) { 
     ret = AVERROR(ENOMEM); 
     goto end; 
    } 
    if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec, 
     &inputs, &outputs, NULL)) < 0) 
     goto end; 
    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) 
     goto end; 
    /* Fill FilteringContext */ 
    fctx->buffersrc_ctx = buffersrc_ctx; 
    fctx->buffersink_ctx = buffersink_ctx; 
    fctx->filter_graph = filter_graph; 
end: 
    avfilter_inout_free(&inputs); 
    avfilter_inout_free(&outputs); 
    return ret; 
} 
static int init_filters(void) 
{ 
    const char *filter_spec; 
    unsigned int i; 
    int ret; 
    filter_ctx = (FilteringContext *)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx)); 
    if (!filter_ctx) 
     return AVERROR(ENOMEM); 
    for (i = 0; i < ifmt_ctx->nb_streams; i++) { 
     filter_ctx[i].buffersrc_ctx = NULL; 
     filter_ctx[i].buffersink_ctx = NULL; 
     filter_ctx[i].filter_graph = NULL; 
     if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO 
      || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) 
      continue; 
     if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
      filter_spec = "null"; /* passthrough (dummy) filter for video */ 
     else 
      filter_spec = "anull"; /* passthrough (dummy) filter for audio */ 
     ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec, 
      ofmt_ctx->streams[i]->codec, filter_spec); 
     if (ret) 
      return ret; 
    } 
    return 0; 
} 

int main(int argc, char **argv) 
{ 
    int ret; 
    AVPacket packet = { NULL, 0 }; 
    AVFrame *frame = NULL; 
    enum AVMediaType type; 
    unsigned int stream_index; 
    unsigned int i; 
    int got_frame; 
    int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *); 

    av_register_all(); 
    avfilter_register_all(); 

    if ((ret = init_filters()) < 0) 
     goto end; 
    /*...*/ 
    system("Pause"); 
    return ret ? 1 : 0; 
} 
+1

Bitte bearbeiten Sie Ihren Code, um ihn auf [mcve] Ihres Problems zu reduzieren. Ihr aktueller Code enthält eine Vielzahl von Problemen, die für Ihr Problem typisch sind. Ein minimales Beispiel ähnelt normalerweise einem guten Komponententest: Es wird nur eine Aufgabe ausgeführt, wobei die Eingabewerte für die Reproduzierbarkeit angegeben werden. –

+0

Danke für die Antwort, ich habe die Codes entfernt, von denen ich denke, dass sie nichts mit dieser Frage zu tun haben. –

Antwort

1

Der Fehlercode -22 oder EINVAL im Falle eines oder mehrerer ungültiger Argumente zurückgegeben. Der Filter buffersrc, den Sie erstellen möchten, benötigt eine zusätzliche Argument-Zeichenfolge (args), die die Abmessungen und das Format des eingehenden Videos beschreibt. Sie kommentieren die Erzeugung der Zeichenkette aus, weshalb der Fehler erzeugt wird.

// this should not be comment out, or replaced with way of setting the arguments 
/*sprintf(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);*/ 
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", 
            args, NULL, filter_graph); 

Wenn die Filter nicht wissen, wie groß die eingehenden Frames sind und wie die gelesenen Werte zu interpretieren (zB gibt es 3 RGB-Kanäle oder 3 YUV-Kanäle? Wie sind solche angelegt, dh sie sind eben oder gepackte ?) dann, wie sollte es sie lesen? Richtig, kann es nicht und es versucht dir das mit der Fehlermeldung zu sagen.

+0

Ja, du hast Recht. Ich habe es auskommentiert, weil in meinem C++ - Code ein Compilerfehler aufgetreten ist. Ich habe es behoben, indem ich den zweiten Parameter entfernt habe und jetzt funktioniert es wie erwartet. –

+0

Eine bessere Lösung besteht darin, die 'sizeof args' beizubehalten, aber' snprintf() 'aufzurufen, was anscheinend beabsichtigt ist. –

Verwandte Themen