Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 58 additions & 75 deletions lib/upipe-av/upipe_avfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ struct upipe_avfilt_sub {
const char *name;
/** avfilter buffer source */
AVFilterContext *buffer_ctx;
/** reference to hardware frames context for input filters */
/** reference to hardware frames context for input filters */
AVBufferRef *hw_frames_ctx;
/** system clock offset */
uint64_t pts_sys_offset;
Expand Down Expand Up @@ -697,27 +697,28 @@ static void upipe_avfilt_sub_flush_cb(struct upump *upump)
*
* @param upipe description structure of the pipe or sub pipe
* @param flow_def input flow definition to build filter from
* @param name filter name
* @param hw_frames_ctx hardware context for input frames
* @param buffer_ctx filled with the AVFilter context on success
* @return an error code
*/
static int build_input_filter(struct upipe *upipe, struct uref *flow_def,
static int build_input_filter(struct upipe *upipe,
struct uref *flow_def,
const char *name,
AVBufferRef *hw_frames_ctx,
AVFilterContext **buffer_ctx)
{
struct upipe_avfilt *upipe_avfilt = NULL;
struct upipe_avfilt_sub *upipe_avfilt_sub = NULL;
const char *name = "input";
struct upipe_avfilt *upipe_avfilt;

if (!upipe || !upipe->mgr || !flow_def) {
if (!upipe || !upipe->mgr || !flow_def)
return UBASE_ERR_INVALID;
} else if (upipe->mgr->signature == UPIPE_AVFILT_SIGNATURE) {

if (upipe->mgr->signature == UPIPE_AVFILT_SIGNATURE)
upipe_avfilt = upipe_avfilt_from_upipe(upipe);
} else if (upipe->mgr->signature == UPIPE_AVFILT_SUB_SIGNATURE) {
upipe_avfilt_sub = upipe_avfilt_sub_from_upipe(upipe);
else if (upipe->mgr->signature == UPIPE_AVFILT_SUB_SIGNATURE)
upipe_avfilt = upipe_avfilt_from_sub_mgr(upipe->mgr);
name = upipe_avfilt_sub->name;
} else {
else
return UBASE_ERR_INVALID;
}

AVFilterGraph *filter_graph = upipe_avfilt->filter_graph;
if (!filter_graph || !name)
Expand Down Expand Up @@ -755,8 +756,7 @@ static int build_input_filter(struct upipe *upipe, struct uref *flow_def,
}
p->time_base.num = 1;
p->time_base.den = UCLOCK_FREQ;
if (upipe_avfilt_sub)
p->hw_frames_ctx = upipe_avfilt_sub->hw_frames_ctx;
p->hw_frames_ctx = hw_frames_ctx;

switch (type) {
case AVMEDIA_TYPE_VIDEO: {
Expand Down Expand Up @@ -844,7 +844,10 @@ static int upipe_avfilt_sub_create_filter(struct upipe *upipe)
if (unlikely(!upipe_avfilt->filter_graph))
return UBASE_ERR_INVALID;

return build_input_filter(upipe, flow_def, &upipe_avfilt_sub->buffer_ctx);
return build_input_filter(upipe, flow_def,
upipe_avfilt_sub->name,
upipe_avfilt_sub->hw_frames_ctx,
&upipe_avfilt_sub->buffer_ctx);
}

/** @internal @This allocates and initializes a avfilter sub pipe.
Expand Down Expand Up @@ -1716,7 +1719,39 @@ static int upipe_avfilt_set_flow_def(struct upipe *upipe,
AVFILTER_AUTO_CONVERT_NONE);
}

int ret = build_input_filter(upipe, flow_def, &upipe_avfilt->buffer_ctx);
return UBASE_ERR_NONE;
}

/** @internal @This initializes the source buffer filter with parameters
* from the first incoming frame.
*
* @param upipe description structure of the pipe
* @param frame input frame
* @return an error code
*/
static int upipe_avfilt_init_buffer_from_first_frame(struct upipe *upipe,
AVFrame *frame)
{
struct upipe_avfilt *upipe_avfilt = upipe_avfilt_from_upipe(upipe);

if (upipe_avfilt->filter_graph == NULL) {
if (!upipe_avfilt->flow_def_input)
return UBASE_ERR_INVALID;

// the filter description was reset, so we need to reinitialize the
// filter
struct uref *flow_def_input = upipe_avfilt->flow_def_input;
upipe_avfilt->flow_def_input = NULL;
int ret = upipe_avfilt_set_flow_def(upipe, flow_def_input);
uref_free(flow_def_input);
if (unlikely(!ubase_check(ret)))
return ret;
}

struct uref *flow_def = upipe_avfilt->flow_def_input;
int ret = build_input_filter(upipe, flow_def, "input",
frame->hw_frames_ctx,
&upipe_avfilt->buffer_ctx);
if (unlikely(!ubase_check(ret))) {
const char *def = "(none)";
uref_flow_get_def(flow_def, &def);
Expand All @@ -1741,9 +1776,9 @@ static int upipe_avfilt_set_flow_def(struct upipe *upipe,
upipe_avfilt->filters_desc,
NULL, &outputs,
NULL)) < 0) {
upipe_err_va(upipe, "cannot parse filter graph: %s",
av_err2str(err));
goto end;
upipe_err_va(upipe, "cannot parse filter graph: %s", av_err2str(err));
avfilter_inout_free(&outputs);
return UBASE_ERR_EXTERNAL;
}

if (outputs != NULL) {
Expand All @@ -1758,77 +1793,25 @@ static int upipe_avfilt_set_flow_def(struct upipe *upipe,
break;
default:
upipe_err(upipe, "unknown output media type");
err = -1;
goto end;
avfilter_inout_free(&outputs);
return UBASE_ERR_INVALID;
}

if ((err = avfilter_graph_parse_ptr(upipe_avfilt->filter_graph,
filters, NULL, &outputs,
NULL)) < 0) {
upipe_err_va(upipe, "cannot parse filter graph: %s",
av_err2str(err));
goto end;
avfilter_inout_free(&outputs);
return UBASE_ERR_EXTERNAL;
}

AVFilterGraph *graph = upipe_avfilt->filter_graph;
upipe_avfilt->buffersink_ctx = graph->filters[graph->nb_filters - 1];
}

end:
avfilter_inout_free(&outputs);

return err < 0 ? UBASE_ERR_INVALID : UBASE_ERR_NONE;
}

/** @internal @This initializes the source buffer filter with parameters
* from the first incoming frame.
*
* @param upipe description structure of the pipe
* @param frame input frame
* @return an error code
*/
static int upipe_avfilt_init_buffer_from_first_frame(struct upipe *upipe,
AVFrame *frame)
{
struct upipe_avfilt *upipe_avfilt = upipe_avfilt_from_upipe(upipe);

if (upipe_avfilt->filter_graph == NULL) {
if (!upipe_avfilt->flow_def_input)
return UBASE_ERR_INVALID;

// the filter description was reset, so we need to reinitialize the
// filter
struct uref *flow_def_input = upipe_avfilt->flow_def_input;
upipe_avfilt->flow_def_input = NULL;
int ret = upipe_avfilt_set_flow_def(upipe, flow_def_input);
uref_free(flow_def_input);
if (unlikely(!ubase_check(ret)))
return ret;
}

AVBufferSrcParameters *p = av_buffersrc_parameters_alloc();
if (p == NULL) {
upipe_err(upipe, "cannot alloc buffer parameters");
return UBASE_ERR_ALLOC;
}
p->format = frame->format;
p->width = frame->width;
p->height = frame->height;
p->hw_frames_ctx = frame->hw_frames_ctx;

#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(9, 16, 100)
p->color_space = frame->colorspace;
p->color_range = frame->color_range;
#endif

int err = av_buffersrc_parameters_set(upipe_avfilt->buffer_ctx, p);
av_free(p);
if (err < 0) {
upipe_err_va(upipe, "cannot set buffer parameters: %s",
av_err2str(err));
return UBASE_ERR_EXTERNAL;
}

AVBufferRef *device_ctx = upipe_avfilt->hw_device_ctx;
if (device_ctx == NULL && frame->hw_frames_ctx != NULL) {
AVHWFramesContext *hw_frames =
Expand Down
Loading