[Libav-user] Using buffersrc and buffersink for full hardware accelerated pipeline
Tomislav Timic
tomislavtimic98 at gmail.com
Sat Jun 7 17:02:12 EEST 2025
Hello,
I am having problem implementing logic for transcoding with nvdec and nvenc
codecs with buffersrc and buffersink.
Without buffersrc and buffersink it works, but when i put those 2 in frames
get stuck in buffersrc or sink I cannot figure it out. This is how i create
buffersrc and buffersink.
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
AVRational input_framerate = av_guess_frame_rate(decoder->avfc,
decoder->video_avs, NULL);
const AVFilter *vbuffersrc = avfilter_get_by_name("buffer");
const AVFilter *vbuffersink = avfilter_get_by_name("buffersink");
AVRational time_base = decoder->avfc->streams[decoder->video_index]->time_base;
AVBufferSrcParameters *input_par;
input_par = av_buffersrc_parameters_alloc();
if (!input_par)
{
fprintf(stderr, "Could not allocate input_par \n");
return -2;
}
input_par->hw_frames_ctx = av_buffer_ref(decoder->hwFramesRef);
input_par->time_base = time_base;
input_par->width = 1920;
input_par->height = 1080;
input_par->sample_aspect_ratio = (AVRational) {1, 1};
input_par->frame_rate = (AVRational) {25, 1};
input_par->format = AV_PIX_FMT_CUDA;
char args[512];
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
decoder->video_avcc->width, decoder->video_avcc->height,
AV_PIX_FMT_CUDA,
time_base.num, time_base.den,
decoder->video_avcc->sample_aspect_ratio.num,
decoder->video_avcc->sample_aspect_ratio.den);
fprintf(stderr, "args = %s\n", args);
int error = avfilter_graph_create_filter(&vbuffersrc_ctx, vbuffersrc,
"in", args, NULL, vfilter_graph);
if (error < 0)
{
fprintf(stderr, "Cannot create buffer source\n");
return error;
}
vbuffersrc_ctx->hw_device_ctx = av_buffer_ref(decoder->hwDevCtx);
error = av_buffersrc_parameters_set(vbuffersrc_ctx, input_par);
av_freep(&input_par);
if (error < 0)
{
fprintf(stderr, "Could not allocate buffersrc parameters, error:
%s\n", av_err2str(error));
return error;
}
error = avfilter_graph_create_filter(&vbuffersink_ctx1, vbuffersink,
NULL, NULL, NULL, vfilter_graph);
if (error < 0)
{
fprintf(stderr, "Cannot create buffer sink\n");
return error;
}
vbuffersink_ctx1->hw_device_ctx = av_buffer_ref(decoder->hwDevCtx);
avfilter_link(vbuffersrc_ctx, 0, vbuffersink_ctx1, 0);
if ((error = avfilter_graph_config(vfilter_graph, NULL)) < 0)
{
fprintf(stderr, "Error while configuring filter graph\n");
return error;
}
and this is the trascode video function
int error;
error = avcodec_send_packet(decoder->video_avcc, input_packet);
if (error < 0)
{
av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the
decoder %s\n", av_err2str(error));
return error;
}
while (error >= 0)
{
error = avcodec_receive_frame(decoder->video_avcc, input_frame);
if (error == AVERROR(EAGAIN) || error == AVERROR_EOF)
{
break;
} else if (error < 0)
{
av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from
the decoder\n");
return -1;
}
input_frame->pts = input_frame->best_effort_timestamp;
if (av_buffersrc_add_frame_flags(buffersrc_ctx,
input_frame,
AV_BUFFERSRC_FLAG_KEEP_REF) < 0)
{
av_log(NULL, AV_LOG_ERROR, "Error while feeding the audio
filtergraph\n");
continue;
}
av_frame_unref(input_frame);
while (true)
{
error = av_buffersink_get_frame(buffersink_ctx, filt_frame);
if (error == AVERROR(EAGAIN) || error == AVERROR_EOF)
break;
if (error < 0)
return -1;
filt_frame->time_base = av_buffersink_get_time_base(buffersink_ctx);;
filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
AVPacket *output_packet = av_packet_alloc();
if (!output_packet)
{
fprintf(stderr, "could not allocate memory for output packet\n");
return -1;
}
int response = avcodec_send_frame(encoder->video_avcc, filt_frame);
while (response >= 0)
{
response = avcodec_receive_packet(encoder->video_avcc,
output_packet);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
{
break;
} else if (response < 0)
{
fprintf(stderr, "Error while receiving packet from
encoder: %s\n", av_err2str(response));
return -1;
}
output_packet->stream_index = encoder->video_avs->index;
av_packet_rescale_ts(output_packet,
encoder->video_avcc->time_base,
encoder->video_avs->time_base);
if (output_packet->pts != AV_NOPTS_VALUE)
{
output_packet->pts = av_rescale_q(output_packet->pts,
decoder->avfc->streams[decoder->video_index]->time_base,
encoder->avfc->streams[decoder->video_index]->time_base);
}
if (output_packet->dts != AV_NOPTS_VALUE)
{
output_packet->dts = av_rescale_q(output_packet->dts,
decoder->avfc->streams[decoder->video_index]->time_base,
encoder->avfc->streams[decoder->video_index]->time_base);
}
response = av_interleaved_write_frame(encoder->avfc, output_packet);
if (response != 0)
{
fprintf(stderr, "Error %d writing interleaved frame:
%s\n", response,
av_err2str(response));
continue;
}
av_frame_unref(filt_frame);
}
av_packet_unref(output_packet);
av_packet_free(&output_packet);
}
av_frame_unref(input_frame);
}
return 0;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20250607/011bac5f/attachment.htm>
More information about the Libav-user
mailing list