static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; if (s->picref) avfilter_unref_buffer(s->picref); s->picref = NULL; avfilter_free(s->scale); s->scale = NULL; }
void avfilter_graph_free(AVFilterGraph **graph) { if (!*graph) return; for (; (*graph)->filter_count > 0; (*graph)->filter_count--) avfilter_free((*graph)->filters[(*graph)->filter_count - 1]); av_freep(&(*graph)->scale_sws_opts); av_freep(&(*graph)->filters); av_freep(graph); }
static void remove_filter(AVFilterContext **filt_ctx) { AVFilterLink *outlink = (*filt_ctx)->outputs[0]; AVFilterContext *src = (*filt_ctx)->inputs[0]->src; (*filt_ctx)->outputs[0] = NULL; avfilter_free(*filt_ctx); *filt_ctx = NULL; set_link_source(src, outlink); }
static void mix_shutdown(mix_t *mix) { if (mix->amix_ctx) avfilter_free(mix->amix_ctx); mix->amix_ctx = NULL; if (mix->sink_ctx) avfilter_free(mix->sink_ctx); mix->sink_ctx = NULL; for (int i = 0; i < NUM_INPUTS; i++) { if (mix->src_ctxs[i]) avfilter_free(mix->src_ctxs[i]); mix->src_ctxs[i] = NULL; } resample_shutdown(&mix->resample); avfilter_graph_free(&mix->graph); format_init(&mix->format); }
static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; while (s->fifo && av_fifo_size(s->fifo)) { AVFilterBufferRef *buf; av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL); avfilter_unref_buffer(buf); } av_fifo_free(s->fifo); s->fifo = NULL; avfilter_free(s->scale); s->scale = NULL; }
/** * Create an instance of a filter, initialize and insert it in the * filtergraph in *ctx. * * @param filt_ctx put here a filter context in case of successful creation and configuration, NULL otherwise. * @param ctx the filtergraph context * @param index an index which is supposed to be unique for each filter instance added to the filtergraph * @param filt_name the name of the filter to create * @param args the arguments provided to the filter during its initialization * @param log_ctx the log context to use * @return >= 0 in case of success, a negative AVERROR code otherwise */ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *filt_name, const char *args, void *log_ctx) { AVFilter *filt; char inst_name[30]; char *tmp_args = NULL; int ret; snprintf(inst_name, sizeof(inst_name), "Parsed_%s_%d", filt_name, index); filt = avfilter_get_by_name(filt_name); if (!filt) { av_log(log_ctx, AV_LOG_ERROR, "No such filter: '%s'\n", filt_name); return AVERROR(EINVAL); } *filt_ctx = avfilter_graph_alloc_filter(ctx, filt, inst_name); if (!*filt_ctx) { av_log(log_ctx, AV_LOG_ERROR, "Error creating filter '%s'\n", filt_name); return AVERROR(ENOMEM); } if (!strcmp(filt_name, "scale") && args && !strstr(args, "flags") && ctx->scale_sws_opts) { tmp_args = av_asprintf("%s:%s", args, ctx->scale_sws_opts); if (!tmp_args) return AVERROR(ENOMEM); args = tmp_args; } ret = avfilter_init_str(*filt_ctx, args); if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, "Error initializing filter '%s'", filt_name); if (args) av_log(log_ctx, AV_LOG_ERROR, " with args '%s'", args); av_log(log_ctx, AV_LOG_ERROR, "\n"); avfilter_free(*filt_ctx); *filt_ctx = NULL; } av_free(tmp_args); return ret; }
/** * Create an instance of a filter, initialize and insert it in the * filtergraph in *ctx. * * @param ctx the filtergraph context * @param put here a filter context in case of successful creation and configuration, NULL otherwise. * @param index an index which is supposed to be unique for each filter instance added to the filtergraph * @param filt_name the name of the filter to create * @param args the arguments provided to the filter during its initialization * @param log_ctx the log context to use * @return 0 in case of success, a negative AVERROR code otherwise */ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *filt_name, const char *args, void *log_ctx) { AVFilter *filt; char inst_name[30]; char tmp_args[256]; int ret; snprintf(inst_name, sizeof(inst_name), "Parsed filter %d %s", index, filt_name); filt = avfilter_get_by_name(filt_name); if (!filt) { av_log(log_ctx, AV_LOG_ERROR, "No such filter: '%s'\n", filt_name); return AVERROR(EINVAL); } ret = avfilter_open(filt_ctx, filt, inst_name); if (!*filt_ctx) { av_log(log_ctx, AV_LOG_ERROR, "Error creating filter '%s'\n", filt_name); return ret; } if ((ret = avfilter_graph_add_filter(ctx, *filt_ctx)) < 0) { avfilter_free(*filt_ctx); return ret; } if (!strcmp(filt_name, "scale") && args && !strstr(args, "flags") && ctx->scale_sws_opts) { snprintf(tmp_args, sizeof(tmp_args), "%s:%s", args, ctx->scale_sws_opts); args = tmp_args; } if ((ret = avfilter_init_filter(*filt_ctx, args, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Error initializing filter '%s' with args '%s'\n", filt_name, args); return ret; } return 0; }
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx) { int ret; if ((ret = avfilter_open(filt_ctx, filt, name)) < 0) goto fail; if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0) goto fail; if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0) goto fail; return 0; fail: if (*filt_ctx) avfilter_free(*filt_ctx); *filt_ctx = NULL; return ret; }
static int insert_filter(ABufferSourceContext *abuffer, AVFilterLink *link, AVFilterContext **filt_ctx, const char *filt_name) { int ret; if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0) return ret; link->src->outputs[0] = NULL; if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) { link->src->outputs[0] = link; return ret; } set_link_source(*filt_ctx, link); if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) { avfilter_free(*filt_ctx); return ret; } return 0; }
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, void *log_ctx) { int ret; AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) goto fail; /* First input can be omitted if it is "[in]" */ if (inputs && !inputs->name) inputs->name = av_strdup("in"); for (cur = inputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Not enough inputs specified for the \"%s\" filter.\n", cur->filter_ctx->filter->name); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_outputs))) continue; ret = avfilter_link(match->filter_ctx, match->pad_idx, cur->filter_ctx, cur->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } /* Last output can be omitted if it is "[out]" */ if (outputs && !outputs->name) outputs->name = av_strdup("out"); for (cur = outputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filters); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_inputs))) continue; ret = avfilter_link(cur->filter_ctx, cur->pad_idx, match->filter_ctx, match->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } fail: if (ret < 0) { for (; graph->filter_count > 0; graph->filter_count--) avfilter_free(graph->filters[graph->filter_count - 1]); av_freep(&graph->filters); } avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); avfilter_inout_free(&open_inputs); avfilter_inout_free(&open_outputs); return ret; }
int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, AVFilterBufferRef *picref, int flags) { BufferSourceContext *c = buffer_filter->priv; AVFilterLink *outlink = buffer_filter->outputs[0]; int ret; if (c->picref) { if (flags & AV_VSRC_BUF_FLAG_OVERWRITE) { avfilter_unref_buffer(c->picref); c->picref = NULL; } else { av_log(buffer_filter, AV_LOG_ERROR, "Buffering several frames is not supported. " "Please consume all available frames before adding a new one.\n"); return AVERROR(EINVAL); } } if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) { AVFilterContext *scale = buffer_filter->outputs[0]->dst; AVFilterLink *link; char scale_param[1024]; av_log(buffer_filter, AV_LOG_INFO, "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name); if (!scale || strcmp(scale->filter->name, "scale")) { AVFilter *f = avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0) return ret; snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param); if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) { avfilter_free(scale); return ret; } if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) { avfilter_free(scale); return ret; } scale->outputs[0]->time_base = scale->inputs[0]->time_base; scale->outputs[0]->format= c->pix_fmt; } else if (!strcmp(scale->filter->name, "scale")) { snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param); scale->filter->init(scale, scale_param, NULL); } c->pix_fmt = scale->inputs[0]->format = picref->format; c->w = scale->inputs[0]->w = picref->video->w; c->h = scale->inputs[0]->h = picref->video->h; link = scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } c->picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, picref->video->w, picref->video->h); av_image_copy(c->picref->data, c->picref->linesize, picref->data, picref->linesize, picref->format, picref->video->w, picref->video->h); avfilter_copy_buffer_ref_props(c->picref, picref); return 0; }
int main(int argc, char **argv) { const AVFilter *filter; AVFilterContext *filter_ctx; AVFilterGraph *graph_ctx; const char *filter_name; const char *filter_args = NULL; int i; int ret = 0; av_log_set_level(AV_LOG_DEBUG); if (argc < 2) { fprintf(stderr, "Missing filter name as argument\n"); return 1; } filter_name = argv[1]; if (argc > 2) filter_args = argv[2]; /* allocate graph */ graph_ctx = avfilter_graph_alloc(); if (!graph_ctx) return 1; avfilter_register_all(); /* get a corresponding filter and open it */ if (!(filter = avfilter_get_by_name(filter_name))) { fprintf(stderr, "Unrecognized filter with name '%s'\n", filter_name); return 1; } /* open filter and add it to the graph */ if (!(filter_ctx = avfilter_graph_alloc_filter(graph_ctx, filter, filter_name))) { fprintf(stderr, "Impossible to open filter with name '%s'\n", filter_name); return 1; } if (avfilter_init_str(filter_ctx, filter_args) < 0) { fprintf(stderr, "Impossible to init filter '%s' with arguments '%s'\n", filter_name, filter_args); return 1; } /* create a link for each of the input pads */ for (i = 0; i < filter_ctx->nb_inputs; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); if (!link) { fprintf(stderr, "Unable to allocate memory for filter input link\n"); ret = 1; goto fail; } link->type = avfilter_pad_get_type(filter_ctx->input_pads, i); filter_ctx->inputs[i] = link; } for (i = 0; i < filter_ctx->nb_outputs; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); if (!link) { fprintf(stderr, "Unable to allocate memory for filter output link\n"); ret = 1; goto fail; } link->type = avfilter_pad_get_type(filter_ctx->output_pads, i); filter_ctx->outputs[i] = link; } if (filter->query_formats) filter->query_formats(filter_ctx); else ff_default_query_formats(filter_ctx); print_formats(filter_ctx); fail: avfilter_free(filter_ctx); avfilter_graph_free(&graph_ctx); fflush(stdout); return ret; }
int av_vsrc_buffer_add_frame2(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts, AVRational pixel_aspect, int width, int height, enum PixelFormat pix_fmt, const char *sws_param) { BufferSourceContext *c = buffer_filter->priv; int ret; if (c->has_frame) { av_log(buffer_filter, AV_LOG_ERROR, "Buffering several frames is not supported. " "Please consume all available frames before adding a new one.\n" ); //return -1; } if(width != c->w || height != c->h || pix_fmt != c->pix_fmt){ AVFilterContext *scale= buffer_filter->outputs[0]->dst; AVFilterLink *link; av_log(buffer_filter, AV_LOG_INFO, "Changing filter graph input to accept %dx%d %d (%d %d)\n", width,height,pix_fmt, c->pix_fmt, scale->outputs[0]->format); if(!scale || strcmp(scale->filter->name,"scale")){ AVFilter *f= avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if(avfilter_open(&scale, f, "Input equalizer") < 0) return -1; if((ret=avfilter_init_filter(scale, sws_param, NULL))<0){ avfilter_free(scale); return ret; } if((ret=avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0))<0){ avfilter_free(scale); return ret; } scale->outputs[0]->format= c->pix_fmt; } c->pix_fmt= scale->inputs[0]->format= pix_fmt; c->w= scale->inputs[0]->w= width; c->h= scale->inputs[0]->h= height; link= scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } memcpy(c->frame.data , frame->data , sizeof(frame->data)); memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); c->frame.interlaced_frame= frame->interlaced_frame; c->frame.top_field_first = frame->top_field_first; c->frame.key_frame = frame->key_frame; c->frame.pict_type = frame->pict_type; c->pts = pts; c->pixel_aspect = pixel_aspect; c->has_frame = 1; return 0; }
int main(int argc, char **argv) { AVFilter *filter; AVFilterContext *filter_ctx; const char *filter_name; const char *filter_args = NULL; int i; av_log_set_level(AV_LOG_DEBUG); if (!argv[1]) { fprintf(stderr, "Missing filter name as argument\n"); return 1; } filter_name = argv[1]; if (argv[2]) filter_args = argv[2]; avfilter_register_all(); /* get a corresponding filter and open it */ if (!(filter = avfilter_get_by_name(filter_name))) { fprintf(stderr, "Unrecognized filter with name '%s'\n", filter_name); return 1; } if (avfilter_open(&filter_ctx, filter, NULL) < 0) { fprintf(stderr, "Impossible to open filter with name '%s'\n", filter_name); return 1; } if (avfilter_init_filter(filter_ctx, filter_args, NULL) < 0) { fprintf(stderr, "Impossible to init filter '%s' with arguments '%s'\n", filter_name, filter_args); return 1; } /* create a link for each of the input pads */ for (i = 0; i < filter_ctx->input_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->inputs[i].type; filter_ctx->inputs[i] = link; } for (i = 0; i < filter_ctx->output_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->outputs[i].type; filter_ctx->outputs[i] = link; } if (filter->query_formats) filter->query_formats(filter_ctx); else avfilter_default_query_formats(filter_ctx); print_formats(filter_ctx); avfilter_free(filter_ctx); fflush(stdout); return 0; }
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 {
int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs) { int index = 0, ret = 0; char chr = 0; AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; filters += strspn(filters, WHITESPACES); if ((ret = parse_sws_flags(&filters, graph)) < 0) goto fail; do { AVFilterContext *filter; filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, graph)) < 0) goto end; if ((ret = parse_filter(&filter, &filters, graph, index, graph)) < 0) goto end; if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, graph)) < 0) goto end; if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, graph)) < 0) goto end; filters += strspn(filters, WHITESPACES); chr = *filters++; if (chr == ';' && curr_inputs) append_inout(&open_outputs, &curr_inputs); index++; } while (chr == ',' || chr == ';'); if (chr) { av_log(graph, AV_LOG_ERROR, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); goto end; } append_inout(&open_outputs, &curr_inputs); *inputs = open_inputs; *outputs = open_outputs; return 0; fail:end: while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); avfilter_inout_free(&open_inputs); avfilter_inout_free(&open_outputs); avfilter_inout_free(&curr_inputs); *inputs = NULL; *outputs = NULL; return ret; }
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, void *log_ctx) { int ret; AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) goto fail; /* First input can be omitted if it is "[in]" */ if (inputs && !inputs->name) inputs->name = av_strdup("in"); for (cur = inputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Not enough inputs specified for the \"%s\" filter.\n", cur->filter_ctx->filter->name); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_outputs))) continue; ret = avfilter_link(match->filter_ctx, match->pad_idx, cur->filter_ctx, cur->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } /* Last output can be omitted if it is "[out]" */ if (outputs && !outputs->name) outputs->name = av_strdup("out"); for (cur = outputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filters); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_inputs))) continue; ret = avfilter_link(cur->filter_ctx, cur->pad_idx, match->filter_ctx, match->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } fail: if (ret < 0) { while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); } avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); avfilter_inout_free(&open_inputs); avfilter_inout_free(&open_outputs); return ret; #else int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx) { return avfilter_graph_parse_ptr(graph, filters, inputs, outputs, log_ctx); #endif } int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx) { int index = 0, ret = 0; char chr = 0; AVFilterInOut *curr_inputs = NULL; AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; if ((ret = parse_sws_flags(&filters, graph)) < 0) goto end; do { AVFilterContext *filter; const char *filterchain = filters; filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) goto end; if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) goto end; if (filter->nb_inputs == 1 && !curr_inputs && !index) { /* First input pad, assume it is "[in]" if not specified */ const char *tmp = "[in]"; if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) goto end; } if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) goto end; if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto end; filters += strspn(filters, WHITESPACES); chr = *filters++; if (chr == ';' && curr_inputs) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filterchain); ret = AVERROR(EINVAL); goto end; } index++; } while (chr == ',' || chr == ';'); if (chr) { av_log(log_ctx, AV_LOG_ERROR, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); goto end; } if (curr_inputs) { /* Last output pad, assume it is "[out]" if not specified */ const char *tmp = "[out]"; if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto end; } end: /* clear open_in/outputs only if not passed as parameters */ if (open_inputs_ptr) *open_inputs_ptr = open_inputs; else avfilter_inout_free(&open_inputs); if (open_outputs_ptr) *open_outputs_ptr = open_outputs; else avfilter_inout_free(&open_outputs); avfilter_inout_free(&curr_inputs); if (ret < 0) { while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); } return ret; }
Filter::~Filter() { avfilter_free(_context); }
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, AVClass *log_ctx) { int index = 0, ret; char chr = 0; AVFilterInOut *curr_inputs = NULL; do { AVFilterContext *filter; const char *filterchain = filters; filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) goto fail; if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) goto fail; if (filter->input_count == 1 && !curr_inputs && !index) { /* First input can be omitted if it is "[in]" */ const char *tmp = "[in]"; if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) goto fail; } if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) goto fail; if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto fail; filters += strspn(filters, WHITESPACES); chr = *filters++; if (chr == ';' && curr_inputs) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filterchain); ret = AVERROR(EINVAL); goto fail; } index++; } while (chr == ',' || chr == ';'); if (chr) { av_log(log_ctx, AV_LOG_ERROR, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); goto fail; } if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) { /* Last output can be omitted if it is "[out]" */ const char *tmp = "[out]"; if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto fail; } return 0; fail: for (; graph->filter_count > 0; graph->filter_count--) avfilter_free(graph->filters[graph->filter_count - 1]); av_freep(&graph->filters); free_inout(open_inputs); free_inout(open_outputs); free_inout(curr_inputs); return ret; }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter (JNIEnv * env, jclass clazz, jstring filePath, jobject surface, jstring filterDescr){ int ret; const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE); const char *filter_descr = (*env)->GetStringUTFChars(env, filterDescr, JNI_FALSE); //打开输入文件 if(!is_playing){ LOGI("open_input..."); if((ret = open_input(env, file_name, surface)) < 0){ LOGE("Couldn't allocate video frame."); goto end; } //注册滤波器 avfilter_register_all(); filter_frame = av_frame_alloc(); if(filter_frame == NULL) { LOGE("Couldn't allocate filter frame."); ret = -1; goto end; } //初始化音频解码器 if ((ret = init_audio(env, clazz)) < 0){ LOGE("Couldn't init_audio."); goto end; } } //初始化滤波器 if ((ret = init_filters(filter_descr)) < 0){ LOGE("init_filter error, ret=%d\n", ret); goto end; } is_playing = 1; int frameFinished; AVPacket packet; while(av_read_frame(pFormatCtx, &packet)>=0 && !release) { //切换滤波器,退出当初播放 if(again){ goto again; } //判断是否为视频流 if(packet.stream_index == video_stream_index) { //对该帧进行解码 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if (frameFinished) { //把解码后视频帧添加到filter_graph if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { LOGE("Error while feeding the filter_graph\n"); break; } //把滤波后的视频帧从filter graph取出来 ret = av_buffersink_get_frame(buffersink_ctx, filter_frame); if (ret >= 0){ // lock native window ANativeWindow_lock(nativeWindow, &windowBuffer, 0); // 格式转换 sws_scale(sws_ctx, (uint8_t const * const *)filter_frame->data, filter_frame->linesize, 0, pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize); // 获取stride uint8_t * dst = windowBuffer.bits; int dstStride = windowBuffer.stride * 4; uint8_t * src = pFrameRGBA->data[0]; int srcStride = pFrameRGBA->linesize[0]; // 由于window的stride和帧的stride不同,因此需要逐行复制 int h; for (h = 0; h < pCodecCtx->height; h++) { memcpy(dst + h * dstStride, src + h * srcStride, (size_t) srcStride); } ANativeWindow_unlockAndPost(nativeWindow); } av_frame_unref(filter_frame); } //延迟等待 if (!playAudio){ usleep((unsigned long) (1000 * 40));//1000 * 40 } } else if(packet.stream_index == audio_stream_index){//音频帧 if (playAudio){ play_audio(env, &packet, pFrame); } } av_packet_unref(&packet); } end: is_playing = 0; //释放内存以及关闭文件 av_free(buffer); av_free(pFrameRGBA); av_free(filter_frame); av_free(pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); avfilter_free(buffersrc_ctx); avfilter_free(buffersink_ctx); avfilter_graph_free(&filter_graph); avcodec_close(audioCodecCtx); free(buffer); free(sws_ctx); free(&windowBuffer); free(out_buffer); free(audio_swr_ctx); free(audio_track); free(audio_track_write_mid); ANativeWindow_release(nativeWindow); (*env)->ReleaseStringUTFChars(env, filePath, file_name); (*env)->ReleaseStringUTFChars(env, filterDescr, filter_descr); LOGE("do release..."); again: again = 0; LOGE("play again..."); return ret; }