From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 72C31479AF for ; Tue, 28 Nov 2023 04:00:18 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6F53668CF7B; Tue, 28 Nov 2023 06:00:15 +0200 (EET) Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id ABA4868CEEA for ; Tue, 28 Nov 2023 06:00:07 +0200 (EET) Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4SfTHn0mfyz9ssr for ; Tue, 28 Nov 2023 05:00:05 +0100 (CET) Message-ID: <2eeae382-e529-4cc1-a48b-ee6b6d7ce559@gyani.pro> Date: Tue, 28 Nov 2023 09:30:04 +0530 MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org References: <20231126012858.40388-1-jamrial@gmail.com> <20231127184357.3361-2-jamrial@gmail.com> Content-Language: en-US From: Gyan Doshi In-Reply-To: <20231127184357.3361-2-jamrial@gmail.com> Subject: Re: [FFmpeg-devel] [PATCH 11/13] avformat/demux: support inserting bitstream filters in demuxing scenarios X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: On 2023-11-28 12:13 am, James Almer wrote: > Packets will be passed to the bsf immediately after being generated by a > demuxer, and no further data will be read from the input until all packets > have been returned by the bsf. Do you plan to add a lib/cli option for user-specified insertions? Will be useful for something like dts2pts in some cases. Regards, Gyan > > Signed-off-by: James Almer > --- > libavformat/avformat.c | 47 ++++++++++++ > libavformat/demux.c | 162 ++++++++++++++++++++++++++++++----------- > libavformat/internal.h | 13 +++- > libavformat/mux.c | 43 ----------- > libavformat/mux.h | 11 --- > libavformat/rawenc.c | 1 + > 6 files changed, 181 insertions(+), 96 deletions(-) > > diff --git a/libavformat/avformat.c b/libavformat/avformat.c > index a02ec965dd..a41c0b391c 100644 > --- a/libavformat/avformat.c > +++ b/libavformat/avformat.c > @@ -1033,3 +1033,50 @@ FF_ENABLE_DEPRECATION_WARNINGS > *pb = NULL; > return ret; > } > + > +int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args) > +{ > + int ret; > + const AVBitStreamFilter *bsf; > + FFStream *const sti = ffstream(st); > + AVBSFContext *bsfc; > + > + av_assert0(!sti->bsfc); > + > + if (name) { > + bsf = av_bsf_get_by_name(name); > + if (!bsf) { > + av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name); > + return AVERROR_BSF_NOT_FOUND; > + } > + ret = av_bsf_alloc(bsf, &bsfc); > + } else > + ret = av_bsf_get_null_filter(&bsfc); > + if (ret < 0) > + return ret; > + > + bsfc->time_base_in = st->time_base; > + if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) { > + av_bsf_free(&bsfc); > + return ret; > + } > + > + if (args && bsfc->filter->priv_class) { > + if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { > + av_bsf_free(&bsfc); > + return ret; > + } > + } > + > + if ((ret = av_bsf_init(bsfc)) < 0) { > + av_bsf_free(&bsfc); > + return ret; > + } > + > + sti->bsfc = bsfc; > + > + av_log(NULL, AV_LOG_VERBOSE, > + "Automatically inserted bitstream filter '%s'; args='%s'\n", > + name, args ? args : ""); > + return 1; > +} > diff --git a/libavformat/demux.c b/libavformat/demux.c > index 6f640b92b1..fb9bf9e4ac 100644 > --- a/libavformat/demux.c > +++ b/libavformat/demux.c > @@ -540,6 +540,109 @@ static int update_wrap_reference(AVFormatContext *s, AVStream *st, int stream_in > return 1; > } > > +static void update_timestamps(AVFormatContext *s, AVStream *st, AVPacket *pkt) > +{ > + FFStream *const sti = ffstream(st); > + > + if (update_wrap_reference(s, st, pkt->stream_index, pkt) && sti->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) { > + // correct first time stamps to negative values > + if (!is_relative(sti->first_dts)) > + sti->first_dts = wrap_timestamp(st, sti->first_dts); > + if (!is_relative(st->start_time)) > + st->start_time = wrap_timestamp(st, st->start_time); > + if (!is_relative(sti->cur_dts)) > + sti->cur_dts = wrap_timestamp(st, sti->cur_dts); > + } > + > + pkt->dts = wrap_timestamp(st, pkt->dts); > + pkt->pts = wrap_timestamp(st, pkt->pts); > + > + force_codec_ids(s, st); > + > + /* TODO: audio: time filter; video: frame reordering (pts != dts) */ > + if (s->use_wallclock_as_timestamps) > + pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base); > +} > + > +static int filter_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt) > +{ > + FFFormatContext *const si = ffformatcontext(s); > + FFStream *const sti = ffstream(st); > + const AVPacket *pkt1; > + int err; > + > + if (!sti->bsfc) { > + const PacketListEntry *pktl = si->raw_packet_buffer.head; > + if (AVPACKET_IS_EMPTY(pkt)) > + return 0; > + > + update_timestamps(s, st, pkt); > + > + if (!pktl && sti->request_probe <= 0) > + return 0; > + > + err = avpriv_packet_list_put(&si->raw_packet_buffer, pkt, NULL, 0); > + if (err < 0) { > + av_packet_unref(pkt); > + return err; > + } > + > + pkt1 = &si->raw_packet_buffer.tail->pkt; > + si->raw_packet_buffer_size += pkt1->size; > + > + if (sti->request_probe <= 0) > + return 0; > + > + return probe_codec(s, s->streams[pkt1->stream_index], pkt1); > + } > + > + err = av_bsf_send_packet(sti->bsfc, pkt); > + if (err < 0) { > + av_log(s, AV_LOG_ERROR, > + "Failed to send packet to filter %s for stream %d\n", > + sti->bsfc->filter->name, st->index); > + return err; > + } > + > + do { > + AVStream *out_st; > + FFStream *out_sti; > + > + err = av_bsf_receive_packet(sti->bsfc, pkt); > + if (err < 0) { > + if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) > + return 0; > + av_log(s, AV_LOG_ERROR, "Error applying bitstream filters to an output " > + "packet for stream #%d: %s\n", st->index, av_err2str(err)); > + if (!(s->error_recognition & AV_EF_EXPLODE) && err != AVERROR(ENOMEM)) > + continue; > + return err; > + } > + out_st = s->streams[pkt->stream_index]; > + out_sti = ffstream(out_st); > + > + update_timestamps(s, out_st, pkt); > + > + err = avpriv_packet_list_put(&si->raw_packet_buffer, pkt, NULL, 0); > + if (err < 0) { > + av_packet_unref(pkt); > + return err; > + } > + > + pkt1 = &si->raw_packet_buffer.tail->pkt; > + si->raw_packet_buffer_size += pkt1->size; > + > + if (out_sti->request_probe <= 0) > + continue; > + > + err = probe_codec(s, out_st, pkt1); > + if (err < 0) > + return err; > + } while (1); > + > + return 0; > +} > + > int ff_read_packet(AVFormatContext *s, AVPacket *pkt) > { > FFFormatContext *const si = ffformatcontext(s); > @@ -557,9 +660,6 @@ FF_ENABLE_DEPRECATION_WARNINGS > > for (;;) { > PacketListEntry *pktl = si->raw_packet_buffer.head; > - AVStream *st; > - FFStream *sti; > - const AVPacket *pkt1; > > if (pktl) { > AVStream *const st = s->streams[pktl->pkt.stream_index]; > @@ -582,16 +682,27 @@ FF_ENABLE_DEPRECATION_WARNINGS > We must re-call the demuxer to get the real packet. */ > if (err == FFERROR_REDO) > continue; > - if (!pktl || err == AVERROR(EAGAIN)) > + if (err == AVERROR(EAGAIN)) > return err; > for (unsigned i = 0; i < s->nb_streams; i++) { > AVStream *const st = s->streams[i]; > FFStream *const sti = ffstream(st); > + int ret; > + > + // Drain buffered packets in the bsf context on eof > + if (err == AVERROR_EOF) > + if ((ret = filter_packet(s, st, pkt)) < 0) > + return ret; > + pktl = si->raw_packet_buffer.head; > + if (!pktl) > + continue; > if (sti->probe_packets || sti->request_probe > 0) > - if ((err = probe_codec(s, st, NULL)) < 0) > - return err; > + if ((ret = probe_codec(s, st, NULL)) < 0) > + return ret; > av_assert0(sti->request_probe <= 0); > } > + if (!pktl) > + return err; > continue; > } > > @@ -616,42 +727,11 @@ FF_ENABLE_DEPRECATION_WARNINGS > av_assert0(pkt->stream_index < (unsigned)s->nb_streams && > "Invalid stream index.\n"); > > - st = s->streams[pkt->stream_index]; > - sti = ffstream(st); > - > - if (update_wrap_reference(s, st, pkt->stream_index, pkt) && sti->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) { > - // correct first time stamps to negative values > - if (!is_relative(sti->first_dts)) > - sti->first_dts = wrap_timestamp(st, sti->first_dts); > - if (!is_relative(st->start_time)) > - st->start_time = wrap_timestamp(st, st->start_time); > - if (!is_relative(sti->cur_dts)) > - sti->cur_dts = wrap_timestamp(st, sti->cur_dts); > - } > - > - pkt->dts = wrap_timestamp(st, pkt->dts); > - pkt->pts = wrap_timestamp(st, pkt->pts); > - > - force_codec_ids(s, st); > - > - /* TODO: audio: time filter; video: frame reordering (pts != dts) */ > - if (s->use_wallclock_as_timestamps) > - pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base); > - > - if (!pktl && sti->request_probe <= 0) > - return 0; > - > - err = avpriv_packet_list_put(&si->raw_packet_buffer, > - pkt, NULL, 0); > - if (err < 0) { > - av_packet_unref(pkt); > - return err; > - } > - pkt1 = &si->raw_packet_buffer.tail->pkt; > - si->raw_packet_buffer_size += pkt1->size; > - > - if ((err = probe_codec(s, st, pkt1)) < 0) > + err = filter_packet(s, s->streams[pkt->stream_index], pkt); > + if (err < 0) > return err; > + if (!AVPACKET_IS_EMPTY(pkt)) > + return 0; > } > } > > diff --git a/libavformat/internal.h b/libavformat/internal.h > index c6181683ef..0a5d512697 100644 > --- a/libavformat/internal.h > +++ b/libavformat/internal.h > @@ -212,7 +212,7 @@ typedef struct FFStream { > /** > * bitstream filter to run on stream > * - encoding: Set by muxer using ff_stream_add_bitstream_filter > - * - decoding: unused > + * - decoding: Set by demuxer using ff_stream_add_bitstream_filter > */ > struct AVBSFContext *bsfc; > > @@ -757,4 +757,15 @@ int ff_match_url_ext(const char *url, const char *extensions); > struct FFOutputFormat; > void avpriv_register_devices(const struct FFOutputFormat * const o[], const AVInputFormat * const i[]); > > +/** > + * Add a bitstream filter to a stream. > + * > + * @param st output stream to add a filter to > + * @param name the name of the filter to add > + * @param args filter-specific argument string > + * @return >0 on success; > + * AVERROR code on failure > + */ > +int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args); > + > #endif /* AVFORMAT_INTERNAL_H */ > diff --git a/libavformat/mux.c b/libavformat/mux.c > index de10d2c008..4bc8627617 100644 > --- a/libavformat/mux.c > +++ b/libavformat/mux.c > @@ -1344,49 +1344,6 @@ int av_get_output_timestamp(struct AVFormatContext *s, int stream, > return 0; > } > > -int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args) > -{ > - int ret; > - const AVBitStreamFilter *bsf; > - FFStream *const sti = ffstream(st); > - AVBSFContext *bsfc; > - > - av_assert0(!sti->bsfc); > - > - if (!(bsf = av_bsf_get_by_name(name))) { > - av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name); > - return AVERROR_BSF_NOT_FOUND; > - } > - > - if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0) > - return ret; > - > - bsfc->time_base_in = st->time_base; > - if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) { > - av_bsf_free(&bsfc); > - return ret; > - } > - > - if (args && bsfc->filter->priv_class) { > - if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { > - av_bsf_free(&bsfc); > - return ret; > - } > - } > - > - if ((ret = av_bsf_init(bsfc)) < 0) { > - av_bsf_free(&bsfc); > - return ret; > - } > - > - sti->bsfc = bsfc; > - > - av_log(NULL, AV_LOG_VERBOSE, > - "Automatically inserted bitstream filter '%s'; args='%s'\n", > - name, args ? args : ""); > - return 1; > -} > - > int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, > AVFormatContext *src, int interleave) > { > diff --git a/libavformat/mux.h b/libavformat/mux.h > index b9ec75641d..ab3e8edd60 100644 > --- a/libavformat/mux.h > +++ b/libavformat/mux.h > @@ -171,17 +171,6 @@ const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream); > > int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset); > > -/** > - * Add a bitstream filter to a stream. > - * > - * @param st output stream to add a filter to > - * @param name the name of the filter to add > - * @param args filter-specific argument string > - * @return >0 on success; > - * AVERROR code on failure > - */ > -int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args); > - > /** > * Write a packet to another muxer than the one the user originally > * intended. Useful when chaining muxers, where one muxer internally > diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c > index f916db13a2..ec31d76d88 100644 > --- a/libavformat/rawenc.c > +++ b/libavformat/rawenc.c > @@ -25,6 +25,7 @@ > #include "libavutil/intreadwrite.h" > > #include "avformat.h" > +#include "internal.h" > #include "rawenc.h" > #include "mux.h" > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".