void Utility::FilterApplier::initFilters() { int ret=0; filterGraph_=avfilter_graph_alloc(); if(!filterGraph_) { throw std::runtime_error("Could not create filtergraph"); } AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); std::string args="video_size="+std::to_string(width_)+"x"+std::to_string( height_)+":pix_fmt="+std::to_string(pixelFormat_)+":time_base=1/1"; ret=avfilter_graph_create_filter(&buffersourceContext_, buffersrc, "in",args.c_str(), NULL, filterGraph_); if(ret<0) { throw std::runtime_error("Could not create the buffersource for the filtergraph."); } ret = avfilter_graph_create_filter(&buffersinkContext_, buffersink, "out",NULL, NULL, filterGraph_); if(ret<0) { throw std::runtime_error("Could not create the buffersink for the filtergraph."); } enum AVPixelFormat pixelFormats[]= {AV_PIX_FMT_RGB24,AV_PIX_FMT_NONE}; ret = av_opt_set_int_list(buffersinkContext_, "pix_fmts", pixelFormats,AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { throw std::runtime_error("Could net set output pixelformat for the graph"); } AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); outputs->name = av_strdup("in"); outputs->filter_ctx = buffersourceContext_; outputs->pad_idx = 0; outputs->next = NULL; inputs->name = av_strdup("out"); inputs->filter_ctx = buffersinkContext_; inputs->pad_idx = 0; inputs->next = NULL; ret = avfilter_graph_parse_ptr(filterGraph_, filterDescription_.c_str(), &inputs, &outputs, NULL); if(ret<0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); throw std::runtime_error("Could not parse the filter descritopns."); } ret = avfilter_graph_config(filterGraph_, NULL); if(ret<0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); throw std::runtime_error("Could not configure filtergraph."); } }
int CDVDVideoCodecFFmpeg::FilterOpen(const std::string& filters, bool scale) { int result; if (m_pFilterGraph) FilterClose(); if (filters.empty() && !scale) return 0; if (m_pHardware) { CLog::Log(LOGWARNING, "CDVDVideoCodecFFmpeg::FilterOpen - skipped opening filters on hardware decode"); return 0; } if (!(m_pFilterGraph = avfilter_graph_alloc())) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - unable to alloc filter graph"); return -1; } AVFilter* srcFilter = avfilter_get_by_name("buffer"); AVFilter* outFilter = avfilter_get_by_name("buffersink"); // should be last filter in the graph for now std::string args = StringUtils::Format("%d:%d:%d:%d:%d:%d:%d", m_pCodecContext->width, m_pCodecContext->height, m_pCodecContext->pix_fmt, m_pCodecContext->time_base.num ? m_pCodecContext->time_base.num : 1, m_pCodecContext->time_base.num ? m_pCodecContext->time_base.den : 1, m_pCodecContext->sample_aspect_ratio.num != 0 ? m_pCodecContext->sample_aspect_ratio.num : 1, m_pCodecContext->sample_aspect_ratio.num != 0 ? m_pCodecContext->sample_aspect_ratio.den : 1); if ((result = avfilter_graph_create_filter(&m_pFilterIn, srcFilter, "src", args.c_str(), NULL, m_pFilterGraph)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_create_filter: src"); return result; } if ((result = avfilter_graph_create_filter(&m_pFilterOut, outFilter, "out", NULL, NULL, m_pFilterGraph)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_create_filter: out"); return result; } if ((result = av_opt_set_int_list(m_pFilterOut, "pix_fmts", &m_formats[0], AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - failed settings pix formats"); return result; } if (!filters.empty()) { AVFilterInOut* outputs = avfilter_inout_alloc(); AVFilterInOut* inputs = avfilter_inout_alloc(); outputs->name = av_strdup("in"); outputs->filter_ctx = m_pFilterIn; outputs->pad_idx = 0; outputs->next = nullptr; inputs->name = av_strdup("out"); inputs->filter_ctx = m_pFilterOut; inputs->pad_idx = 0; inputs->next = nullptr; if ((result = avfilter_graph_parse_ptr(m_pFilterGraph, (const char*)m_filters.c_str(), &inputs, &outputs, NULL)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_parse"); return result; } avfilter_inout_free(&outputs); avfilter_inout_free(&inputs); } else { if ((result = avfilter_link(m_pFilterIn, 0, m_pFilterOut, 0)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_link"); return result; } } if ((result = avfilter_graph_config(m_pFilterGraph, nullptr)) < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_config"); return result; } m_filterEof = false; return result; }
static int init_filters(const char *filters_descr) { char args[512]; int ret = 0; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base; enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } /* buffer video source: the decoded frames from the decoder will be inserted here. */ snprintf(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, time_base.num, 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; } /* buffer video sink: to terminate the filter chain. */ 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_int_list(buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n"); goto end; } /* * Set the endpoints for the filter graph. The filter_graph will * be linked to the graph described by filters_descr. */ /* * The buffer source output must be connected to the input pad of * the first filter described by filters_descr; since the first * filter input label is not specified, it is set to "in" by * default. */ outputs->name = av_strdup("in"); outputs->filter_ctx = buffersrc_ctx; outputs->pad_idx = 0; outputs->next = NULL; /* * The buffer sink input must be connected to the output pad of * the last filter described by filters_descr; since the last * filter output label is not specified, it is set to "out" by * default. */ inputs->name = av_strdup("out"); inputs->filter_ctx = buffersink_ctx; inputs->pad_idx = 0; inputs->next = NULL; if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, &inputs, &outputs, NULL)) < 0) goto end; if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) goto end; end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }
void configure_filtergraph() { if (filtergraph_.empty()) { video_graph_.reset(); return; } video_graph_.reset( avfilter_graph_alloc(), [](AVFilterGraph* p) { avfilter_graph_free(&p); }); const auto vsrc_options = (boost::format("video_size=%1%x%2%:pix_fmt=%3%:time_base=%4%/%5%:pixel_aspect=%6%/%7%") % in_width_ % in_height_ % in_pix_format_ % in_time_base_.num % in_time_base_.den % in_sample_aspect_ratio_.num % in_sample_aspect_ratio_.den).str(); AVFilterContext* filt_vsrc = nullptr; FF(avfilter_graph_create_filter( &filt_vsrc, avfilter_get_by_name("buffer"), "filter_buffer", vsrc_options.c_str(), nullptr, video_graph_.get())); AVFilterContext* filt_vsink = nullptr; FF(avfilter_graph_create_filter( &filt_vsink, avfilter_get_by_name("buffersink"), "filter_buffersink", nullptr, nullptr, video_graph_.get())); #pragma warning (push) #pragma warning (disable : 4245) FF(av_opt_set_int_list( filt_vsink, "pix_fmts", out_pix_fmts_.data(), -1, AV_OPT_SEARCH_CHILDREN)); #pragma warning (pop) try { configure_filtergraph( *video_graph_, filtergraph_, *filt_vsrc, *filt_vsink); video_graph_in_ = filt_vsrc; video_graph_out_ = filt_vsink; CASPAR_LOG(trace) << L"Filter configured:\n" << avfilter_graph_dump(video_graph_.get(), nullptr); } catch (...) { CASPAR_LOG(error) << L"Cannot configure filtergraph: " << filtergraph_.c_str(); filtergraph_.clear(); // disable filtering on configure_filtergraph failure } }
static int init_filters(const char *filters_descr) { char args[512]; int ret = 0; AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 }; static const int64_t out_channel_layouts[] = { AV_CH_LAYOUT_MONO, -1 }; static const int out_sample_rates[] = { 8000, -1 }; const AVFilterLink *outlink; AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base; filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } /* buffer audio source: the decoded frames from the decoder will be inserted here. */ 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, time_base.num, 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, abuffersrc, "in", args, NULL, filter_graph); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n"); goto end; } /* buffer audio sink: to terminate the filter chain. */ ret = avfilter_graph_create_filter(&buffersink_ctx, abuffersink, "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_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1, 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_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1, 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_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n"); 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 ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, &inputs, &outputs, NULL)) < 0) goto end; if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) goto end; /* Print summary of the sink buffer * Note: args buffer is reused to store channel layout string */ outlink = buffersink_ctx->inputs[0]; av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout); av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", (int)outlink->sample_rate, (char *)av_x_if_null(av_get_sample_fmt_name(outlink->format), "?"), args); end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }
static bool recreate_graph(struct af_instance *af, struct mp_audio *config) { void *tmp = talloc_new(NULL); struct priv *p = af->priv; AVFilterContext *in = NULL, *out = NULL; int r; if (bstr0(p->cfg_graph).len == 0) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "lavfi: no filter graph set\n"); return false; } destroy_graph(af); mp_msg(MSGT_AFILTER, MSGL_V, "lavfi: create graph: '%s'\n", p->cfg_graph); AVFilterGraph *graph = avfilter_graph_alloc(); if (!graph) goto error; if (parse_avopts(graph, p->cfg_avopts) < 0) { mp_msg(MSGT_VFILTER, MSGL_FATAL, "lavfi: could not set opts: '%s'\n", p->cfg_avopts); goto error; } AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); if (!outputs || !inputs) goto error; char *src_args = talloc_asprintf(tmp, "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d:" "channel_layout=0x%"PRIx64, config->rate, av_get_sample_fmt_name(af_to_avformat(config->format)), config->channels.num, 1, config->rate, mp_chmap_to_lavc(&config->channels)); if (avfilter_graph_create_filter(&in, avfilter_get_by_name("abuffer"), "src", src_args, NULL, graph) < 0) goto error; if (avfilter_graph_create_filter(&out, avfilter_get_by_name("abuffersink"), "out", NULL, NULL, graph) < 0) goto error; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; r = av_opt_set_int_list(out, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (r < 0) goto error; r = av_opt_set_int(out, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN); if (r < 0) goto error; outputs->name = av_strdup("in"); outputs->filter_ctx = in; inputs->name = av_strdup("out"); inputs->filter_ctx = out; if (graph_parse(graph, p->cfg_graph, inputs, outputs, NULL) < 0) goto error; if (avfilter_graph_config(graph, NULL) < 0) goto error; p->in = in; p->out = out; p->graph = graph; assert(out->nb_inputs == 1); assert(in->nb_outputs == 1); talloc_free(tmp); return true; error: mp_msg(MSGT_AFILTER, MSGL_FATAL, "Can't configure libavfilter graph.\n"); avfilter_graph_free(&graph); talloc_free(tmp); return false; }
HRESULT CLAVVideo::Filter(LAVFrame *pFrame) { int ret = 0; BOOL bFlush = pFrame->flags & LAV_FRAME_FLAG_FLUSH; if (m_Decoder.IsInterlaced(FALSE) && m_settings.DeintMode != DeintMode_Disable && (m_settings.SWDeintMode == SWDeintMode_YADIF || m_settings.SWDeintMode == SWDeintMode_W3FDIF_Simple || m_settings.SWDeintMode == SWDeintMode_W3FDIF_Complex) && ((bFlush && m_pFilterGraph) || pFrame->format == LAVPixFmt_YUV420 || pFrame->format == LAVPixFmt_YUV422 || pFrame->format == LAVPixFmt_NV12)) { AVPixelFormat ff_pixfmt = (pFrame->format == LAVPixFmt_YUV420) ? AV_PIX_FMT_YUV420P : (pFrame->format == LAVPixFmt_YUV422) ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_NV12; if (!bFlush && (!m_pFilterGraph || pFrame->format != m_filterPixFmt || pFrame->width != m_filterWidth || pFrame->height != m_filterHeight)) { DbgLog((LOG_TRACE, 10, L":Filter()(init) Initializing YADIF deinterlacing filter...")); if (m_pFilterGraph) { avfilter_graph_free(&m_pFilterGraph); m_pFilterBufferSrc = nullptr; m_pFilterBufferSink = nullptr; } m_filterPixFmt = pFrame->format; m_filterWidth = pFrame->width; m_filterHeight = pFrame->height; char args[512]; enum AVPixelFormat pix_fmts[3]; if (ff_pixfmt == AV_PIX_FMT_NV12) { pix_fmts[0] = AV_PIX_FMT_NV12; pix_fmts[1] = AV_PIX_FMT_YUV420P; } else { pix_fmts[0] = ff_pixfmt; pix_fmts[1] = AV_PIX_FMT_NONE; } pix_fmts[2] = AV_PIX_FMT_NONE; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); m_pFilterGraph = avfilter_graph_alloc(); av_opt_set(m_pFilterGraph, "thread_type", "slice", AV_OPT_SEARCH_CHILDREN); av_opt_set_int(m_pFilterGraph, "threads", FFMAX(1, av_cpu_count() / 2), AV_OPT_SEARCH_CHILDREN); // 0/0 is not a valid value for avfilter, make sure it doesn't happen AVRational aspect_ratio = pFrame->aspect_ratio; if (aspect_ratio.num == 0 || aspect_ratio.den == 0) aspect_ratio = { 0, 1 }; _snprintf_s(args, sizeof(args), "video_size=%dx%d:pix_fmt=%s:time_base=1/10000000:pixel_aspect=%d/%d", pFrame->width, pFrame->height, av_get_pix_fmt_name(ff_pixfmt), pFrame->aspect_ratio.num, pFrame->aspect_ratio.den); ret = avfilter_graph_create_filter(&m_pFilterBufferSrc, buffersrc, "in", args, nullptr, m_pFilterGraph); if (ret < 0) { DbgLog((LOG_TRACE, 10, L"::Filter()(init) Creating the input buffer filter failed with code %d", ret)); avfilter_graph_free(&m_pFilterGraph); goto deliver; } ret = avfilter_graph_create_filter(&m_pFilterBufferSink, buffersink, "out", nullptr, nullptr, m_pFilterGraph); if (ret < 0) { DbgLog((LOG_TRACE, 10, L"::Filter()(init) Creating the buffer sink filter failed with code %d", ret)); avfilter_free(m_pFilterBufferSrc); m_pFilterBufferSrc = nullptr; avfilter_graph_free(&m_pFilterGraph); goto deliver; } /* set allowed pixfmts on the output */ av_opt_set_int_list(m_pFilterBufferSink->priv, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, 0); /* Endpoints for the filter graph. */ outputs->name = av_strdup("in"); outputs->filter_ctx = m_pFilterBufferSrc; outputs->pad_idx = 0; outputs->next = nullptr; inputs->name = av_strdup("out"); inputs->filter_ctx = m_pFilterBufferSink; inputs->pad_idx = 0; inputs->next = nullptr; if (m_settings.SWDeintMode == SWDeintMode_YADIF) _snprintf_s(args, sizeof(args), "yadif=mode=%s:parity=auto:deint=interlaced", (m_settings.SWDeintOutput == DeintOutput_FramePerField) ? "send_field" : "send_frame"); else if (m_settings.SWDeintMode == SWDeintMode_W3FDIF_Simple) _snprintf_s(args, sizeof(args), "w3fdif=filter=simple:deint=interlaced"); else if (m_settings.SWDeintMode == SWDeintMode_W3FDIF_Complex) _snprintf_s(args, sizeof(args), "w3fdif=filter=complex:deint=interlaced"); else ASSERT(0); if ((ret = avfilter_graph_parse_ptr(m_pFilterGraph, args, &inputs, &outputs, nullptr)) < 0) { DbgLog((LOG_TRACE, 10, L"::Filter()(init) Parsing the graph failed with code %d", ret)); avfilter_graph_free(&m_pFilterGraph); goto deliver; } if ((ret = avfilter_graph_config(m_pFilterGraph, nullptr)) < 0) { DbgLog((LOG_TRACE, 10, L"::Filter()(init) Configuring the graph failed with code %d", ret)); avfilter_graph_free(&m_pFilterGraph); goto deliver; } DbgLog((LOG_TRACE, 10, L":Filter()(init) avfilter Initialization complete")); } if (!m_pFilterGraph) goto deliver; if (pFrame->direct) { HRESULT hr = DeDirectFrame(pFrame, true); if (FAILED(hr)) { ReleaseFrame(&pFrame); return hr; } } AVFrame *in_frame = nullptr; BOOL refcountedFrame = (m_Decoder.HasThreadSafeBuffers() == S_OK); // When flushing, we feed a NULL frame if (!bFlush) { in_frame = av_frame_alloc(); for (int i = 0; i < 4; i++) { in_frame->data[i] = pFrame->data[i]; in_frame->linesize[i] = (int)pFrame->stride[i]; } in_frame->width = pFrame->width; in_frame->height = pFrame->height; in_frame->format = ff_pixfmt; in_frame->pts = pFrame->rtStart; in_frame->interlaced_frame = pFrame->interlaced; in_frame->top_field_first = pFrame->tff; in_frame->sample_aspect_ratio = pFrame->aspect_ratio; if (refcountedFrame) { AVBufferRef *pFrameBuf = av_buffer_create(nullptr, 0, lav_free_lavframe, pFrame, 0); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((AVPixelFormat)in_frame->format); int planes = (in_frame->format == AV_PIX_FMT_NV12) ? 2 : desc->nb_components; for (int i = 0; i < planes; i++) { int h_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; int plane_size = (in_frame->height >> h_shift) * in_frame->linesize[i]; AVBufferRef *planeRef = av_buffer_ref(pFrameBuf); in_frame->buf[i] = av_buffer_create(in_frame->data[i], plane_size, lav_unref_frame, planeRef, AV_BUFFER_FLAG_READONLY); } av_buffer_unref(&pFrameBuf); } m_FilterPrevFrame = *pFrame; memset(m_FilterPrevFrame.data, 0, sizeof(m_FilterPrevFrame.data)); m_FilterPrevFrame.destruct = nullptr; } else {
static vod_status_t audio_filter_init_sink( request_context_t* request_context, AVFilterGraph *filter_graph, media_track_t* reference_track, const u_char* sink_name, audio_filter_sink_t* sink, AVFilterInOut** inputs) { AVCodecContext* encoder; AVFilterInOut* input_link; enum AVSampleFormat out_sample_fmts[2]; int64_t out_channel_layouts[2]; uint64_t channel_layout; uint8_t channel_config; int out_sample_rates[2]; int avrc; // Note: matching the output to some reference track, may need to change in the future // if filters such as 'join' will be added channel_config = reference_track->media_info.u.audio.codec_config.channel_config; if (channel_config < vod_array_entries(aac_channel_layout)) { channel_layout = aac_channel_layout[channel_config]; } else { channel_layout = 0; } // create the buffer sink avrc = avfilter_graph_create_filter( &sink->buffer_sink, buffersink_filter, (char*)sink_name, NULL, NULL, filter_graph); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: avfilter_graph_create_filter failed %d", avrc); return VOD_ALLOC_FAILED; } // configure the buffer sink out_sample_fmts[0] = ENCODER_INPUT_SAMPLE_FORMAT; out_sample_fmts[1] = -1; avrc = av_opt_set_int_list( sink->buffer_sink, BUFFERSINK_PARAM_SAMPLE_FORMATS, out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: av_opt_set_int_list(sample formats) failed %d", avrc); return VOD_UNEXPECTED; } out_channel_layouts[0] = channel_layout; out_channel_layouts[1] = -1; avrc = av_opt_set_int_list( sink->buffer_sink, BUFFERSINK_PARAM_CHANNEL_LAYOUTS, out_channel_layouts, -1, AV_OPT_SEARCH_CHILDREN); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: av_opt_set_int_list(channel layouts) failed %d", avrc); return VOD_UNEXPECTED; } out_sample_rates[0] = reference_track->media_info.u.audio.sample_rate; out_sample_rates[1] = -1; avrc = av_opt_set_int_list( sink->buffer_sink, BUFFERSINK_PARAM_SAMPLE_RATES, out_sample_rates, -1, AV_OPT_SEARCH_CHILDREN); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: av_opt_set_int_list(sample rates) failed %d", avrc); return VOD_UNEXPECTED; } // init the encoder encoder = avcodec_alloc_context3(encoder_codec); if (encoder == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: avcodec_alloc_context3 failed"); return VOD_ALLOC_FAILED; } sink->encoder = encoder; encoder->sample_fmt = ENCODER_INPUT_SAMPLE_FORMAT; encoder->sample_rate = reference_track->media_info.u.audio.sample_rate; encoder->channel_layout = channel_layout; encoder->channels = reference_track->media_info.u.audio.channels; encoder->bit_rate = reference_track->media_info.bitrate; encoder->flags |= CODEC_FLAG_GLOBAL_HEADER; // make the codec generate the extra data avrc = avcodec_open2(encoder, encoder_codec, NULL); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: avcodec_open2 failed %d", avrc); return VOD_UNEXPECTED; } // add to the inputs list input_link = avfilter_inout_alloc(); if (input_link == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_sink: avfilter_inout_alloc failed"); return VOD_ALLOC_FAILED; } input_link->filter_ctx = sink->buffer_sink; input_link->pad_idx = 0; input_link->next = *inputs; *inputs = input_link; input_link->name = av_strdup((const char*)sink_name); if (input_link->name == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_init_source: av_strdup failed"); return VOD_ALLOC_FAILED; } return VOD_OK; }
static vod_status_t audio_filter_init_filters( audio_filter_state_t* state, mpeg_stream_metadata_t* stream_metadata, const char *filters_descr) { char filter_args[sizeof(BUFFERSRC_ARGS_FORMAT) + 4 * VOD_INT64_LEN + MAX_SAMPLE_FORMAT_NAME_LEN]; enum AVSampleFormat out_sample_fmts[2]; int64_t out_channel_layouts[2]; int out_sample_rates[2]; AVFilterInOut *outputs = NULL; AVFilterInOut *inputs = NULL; int ret; int rc; // allocate the filter graph state->filter_graph = avfilter_graph_alloc(); if (state->filter_graph == NULL) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_graph_alloc failed"); rc = VOD_ALLOC_FAILED; goto end; } // create the buffer source vod_sprintf(filter_args, BUFFERSRC_ARGS_FORMAT, state->decoder->time_base.num, state->decoder->time_base.den, state->decoder->sample_rate, av_get_sample_fmt_name(state->decoder->sample_fmt), state->decoder->channel_layout); ret = avfilter_graph_create_filter( &state->buffer_src, buffersrc_filter, INPUT_FILTER_NAME, filter_args, NULL, state->filter_graph); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_graph_create_filter(input) failed %d", ret); rc = VOD_ALLOC_FAILED; goto end; } // create the buffer sink ret = avfilter_graph_create_filter( &state->buffer_sink, buffersink_filter, OUTPUT_FILTER_NAME, NULL, NULL, state->filter_graph); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_graph_create_filter(output) failed %d", ret); rc = VOD_ALLOC_FAILED; goto end; } // configure the buffer sink out_sample_fmts[0] = ENCODER_INPUT_SAMPLE_FORMAT; out_sample_fmts[1] = -1; ret = av_opt_set_int_list( state->buffer_sink, BUFFERSINK_PARAM_SAMPLE_FORMATS, out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: av_opt_set_int_list(sample format) failed %d", ret); rc = VOD_UNEXPECTED; goto end; } out_channel_layouts[0] = state->decoder->channel_layout; out_channel_layouts[1] = -1; ret = av_opt_set_int_list( state->buffer_sink, BUFFERSINK_PARAM_CHANNEL_LAYOUTS, out_channel_layouts, -1, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: av_opt_set_int_list(channel layouts) failed %d", ret); rc = VOD_UNEXPECTED; goto end; } out_sample_rates[0] = state->decoder->sample_rate; out_sample_rates[1] = -1; ret = av_opt_set_int_list( state->buffer_sink, BUFFERSINK_PARAM_SAMPLE_RATES, out_sample_rates, -1, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: av_opt_set_int_list(sample rates) failed %d", ret); rc = VOD_UNEXPECTED; goto end; } // create the filter outputs outputs = avfilter_inout_alloc(); if (outputs == NULL) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_inout_alloc failed (1)"); rc = VOD_ALLOC_FAILED; goto end; } outputs->name = av_strdup(INPUT_FILTER_NAME); outputs->filter_ctx = state->buffer_src; outputs->pad_idx = 0; outputs->next = NULL; // create the filter inputs inputs = avfilter_inout_alloc(); if (inputs == NULL) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_inout_alloc failed (2)"); rc = VOD_ALLOC_FAILED; goto end; } inputs->name = av_strdup(OUTPUT_FILTER_NAME); inputs->filter_ctx = state->buffer_sink; inputs->pad_idx = 0; inputs->next = NULL; // parse the filter description ret = avfilter_graph_parse_ptr(state->filter_graph, filters_descr, &inputs, &outputs, NULL); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_graph_parse_ptr failed %d", ret); rc = VOD_UNEXPECTED; goto end; } // validate and configure the graph ret = avfilter_graph_config(state->filter_graph, NULL); if (ret < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_init_filters: avfilter_graph_config failed %d", ret); rc = VOD_UNEXPECTED; goto end; } // set the buffer sink frame size if ((state->encoder->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) == 0) { av_buffersink_set_frame_size(state->buffer_sink, state->encoder->frame_size); } rc = VOD_OK; end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return rc; }
static int init_filters(const char *filters_descr) { char args[512]; int ret = 0; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base; enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; AVFilter *vdpau = avfilter_get_by_name("vdpau"); filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } /* buffer video source: the decoded frames from the decoder will be inserted here. */ snprintf(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, time_base.num, 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; } /* buffer video sink: to terminate the filter chain. */ 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_int_list(buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n"); goto end; } ret = avfilter_graph_create_filter(&vdpau_ctx, vdpau, "vdpau", NULL, NULL, filter_graph); vdpau_ctx->hw_device_ctx = device_ref; if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create vdpau filter.\n"); goto end; } /* Connect the filters; * in this simple case the filters just form a linear chain. */ ret = avfilter_link(buffersrc_ctx, 0, vdpau_ctx, 0); if (ret >= 0) ret = avfilter_link(vdpau_ctx, 0, buffersink_ctx, 0); if (ret < 0) { fprintf(stderr, "Error connecting filters\n"); return ret; } if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) goto end; end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }
static int init_filters(AVStream *audio_stream, int audio_stream_index) { AVCodecContext *dec_ctx = audio_stream->codec; char args[512]; int ret = 0; AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }; static const int64_t out_channel_layouts[] = { AV_CH_LAYOUT_STEREO, -1 }; static const int out_sample_rates[] = { dec_ctx->sample_rate, -1 }; const AVFilterLink *outlink; AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base; filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } /* buffer audio source: the decoded frames from the decoder will be inserted here. */ if (!dec_ctx->channel_layout) dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels); _snprintf_s(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64d", time_base.num, 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, abuffersrc, "in", args, NULL, filter_graph); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n"); goto end; } /* buffer audio sink: to terminate the filter chain. */ ret = avfilter_graph_create_filter(&buffersink_ctx, abuffersink, "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_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1, 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_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1, 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_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n"); goto end; } last_flt_ctx = buffersink_ctx; int index = 1; while(filter_descr[index]) { const char* name = NULL; const char* arg = NULL; char tmp[64] = {0}; char* pos = NULL; strncpy_s(tmp, 64, filter_descr[index], 64); pos = strchr(tmp, '='); if (pos != NULL) { *pos = '\0'; name = tmp; arg = pos + 1; } else { name = filter_descr[index]; arg = NULL; } insert_filter(name, arg, &last_flt_ctx); index++; } /* 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 = last_flt_ctx; inputs->pad_idx = 0; inputs->next = NULL; if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr[0], &inputs, &outputs, NULL)) < 0) goto end; if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) goto end; /* Print summary of the sink buffer * Note: args buffer is reused to store channel layout string */ outlink = buffersink_ctx->inputs[0]; av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout); av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", (int)outlink->sample_rate, (char *)av_x_if_null(av_get_sample_fmt_name((AVSampleFormat)outlink->format), "?"), args); end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }
int Filters::init(VideoDecoder *decoder) { char args[512]; int ret = 0; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB8, AV_PIX_FMT_NONE }; mFilterGraphPtr = avfilter_graph_alloc(); if (!inputs || !outputs || !mFilterGraphPtr) { LOGE("Alloc filter graph failed"); goto end; } snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", decoder->mVideoCodecCtxPtr->width, decoder->mVideoCodecCtxPtr->height, decoder->mVideoCodecCtxPtr->pix_fmt, decoder->mVideoCodecCtxPtr->time_base.num, decoder->mVideoCodecCtxPtr->time_base.den, decoder->mVideoCodecCtxPtr->sample_aspect_ratio.num, decoder->mVideoCodecCtxPtr->sample_aspect_ratio.den); LOGD("Buffer args: %s", args); ret = avfilter_graph_create_filter(&(mBufSrcCtxPtr), buffersrc, "in", args, NULL, mFilterGraphPtr); if (ret < 0) { LOGE("Create buffer src context failed"); goto end; } ret = avfilter_graph_create_filter(&(mBufSinkCtxPtr), buffersink, "out", NULL, NULL, mFilterGraphPtr); if (ret < 0) { LOGE("Create buffer sink context failed"); goto end; } ret = av_opt_set_int_list(mBufSinkCtxPtr, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { LOGE("Cannot set output pixel format"); goto end; } outputs->name = av_strdup("in"); outputs->filter_ctx = mBufSrcCtxPtr; outputs->pad_idx = 0; outputs->next = NULL; inputs->name = av_strdup("out"); inputs->filter_ctx = mBufSinkCtxPtr; inputs->pad_idx = 0; inputs->next = NULL; setPixFmt(decoder->mPixFmt); LOGD("Filter desc %s", mDesc.c_str()); if ((ret = avfilter_graph_parse_ptr(mFilterGraphPtr, mDesc.c_str(), &inputs, &outputs, NULL)) < 0) { LOGE("Parse filter graph failed"); goto end; } if ((ret = avfilter_graph_config(mFilterGraphPtr, NULL)) < 0) { LOGE("Config filter graph failed"); goto end; } end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }
//初始化滤波器 int init_filters(const char *filters_descr) { char args[512]; int ret = 0; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); AVRational time_base = pFormatCtx->streams[video_stream_index]->time_base; enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }; filter_graph = avfilter_graph_alloc(); if (!outputs || !inputs || !filter_graph) { ret = AVERROR(ENOMEM); goto end; } /* buffer video source: the decoded frames from the decoder will be inserted here. */ snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, time_base.num, time_base.den, pCodecCtx->sample_aspect_ratio.num, pCodecCtx->sample_aspect_ratio.den); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph); if (ret < 0) { LOGE("Cannot create buffer source\n"); goto end; } /* buffer video sink: to terminate the filter chain. */ ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph); if (ret < 0) { LOGE("Cannot create buffer sink\n"); goto end; } ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { LOGE("Cannot set output pixel format\n"); goto end; } 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 ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, &inputs, &outputs, NULL)) < 0) goto end; if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) goto end; end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; }