James Almer: > This BSF takes Temporal Units split across different AVPackets and merges them > by looking for Temporal Delimiter OBUs. > > Signed-off-by: James Almer <jamr...@gmail.com> > --- > configure | 1 + > libavcodec/Makefile | 1 + > libavcodec/av1_frame_merge_bsf.c | 153 +++++++++++++++++++++++++++++++ > libavcodec/bitstream_filters.c | 1 + > 4 files changed, 156 insertions(+) > create mode 100644 libavcodec/av1_frame_merge_bsf.c > > diff --git a/configure b/configure > index 1de90e93fd..70f60997c1 100755 > --- a/configure > +++ b/configure > @@ -3115,6 +3115,7 @@ vc1_parser_select="vc1dsp" > > # bitstream_filters > aac_adtstoasc_bsf_select="adts_header" > +av1_frame_merge_bsf_select="cbs_av1" > av1_frame_split_bsf_select="cbs_av1" > av1_metadata_bsf_select="cbs_av1" > eac3_core_bsf_select="ac3_parser" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index b990c6ba87..006a472a6d 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -1075,6 +1075,7 @@ OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o > # bitstream filters > OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o > OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o > +OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o > OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o > OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o > OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o > diff --git a/libavcodec/av1_frame_merge_bsf.c > b/libavcodec/av1_frame_merge_bsf.c > new file mode 100644 > index 0000000000..943cfcb426 > --- /dev/null > +++ b/libavcodec/av1_frame_merge_bsf.c > @@ -0,0 +1,153 @@ > +/* > + * Copyright (c) 2019 James Almer <jamr...@gmail.com> > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#include "avcodec.h" > +#include "bsf.h" > +#include "cbs.h" > +#include "cbs_av1.h" > + > +typedef struct AV1FMergeContext { > + CodedBitstreamContext *cbc; > + CodedBitstreamFragment temporal_unit; > + CodedBitstreamFragment frag; > +} AV1FMergeContext; > + > +static int av1_frame_merge_filter(AVBSFContext *bsf, AVPacket *pkt) > +{ > + AV1FMergeContext *ctx = bsf->priv_data; > + CodedBitstreamFragment *frag = &ctx->frag, *tu = &ctx->temporal_unit; > + int err, i; > + > + err = ff_bsf_get_packet_ref(bsf, pkt); > + if (err < 0) { > + if (err == AVERROR_EOF && tu->nb_units > 0)
Right now ffmpeg (the cli) does not flush bsf at the end when doing streamcopy. Can you test whether the following patch works with this bsf? https://github.com/mkver/FFmpeg/commit/340a091f5f6b474de096a8b64dd0ce3a8c7f6c24 > + goto eof; > + return err; > + } > + > + err = ff_cbs_read_packet(ctx->cbc, frag, pkt); > + if (err < 0) { > + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); > + goto fail; > + } > + > + if (frag->nb_units == 0) { > + av_log(bsf, AV_LOG_ERROR, "No OBU in packet.\n"); > + err = AVERROR_INVALIDDATA; > + goto fail; > + } > + > + if (tu->nb_units == 0 && frag->units[0].type != > AV1_OBU_TEMPORAL_DELIMITER) { > + av_log(bsf, AV_LOG_ERROR, "Missing Temporal Delimiter.\n"); > + err = AVERROR_INVALIDDATA; > + goto fail; > + } > + > + if (tu->nb_units > 0 && frag->units[0].type == > AV1_OBU_TEMPORAL_DELIMITER) { > +eof: > + err = ff_cbs_write_packet(ctx->cbc, pkt, tu); > + if (err < 0) { > + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); > + goto fail; > + } > + ff_cbs_fragment_reset(ctx->cbc, tu); > + > + for (i = 0; i < frag->nb_units; i++) { > + if (i && frag->units[i].type == AV1_OBU_TEMPORAL_DELIMITER) { > + av_log(bsf, AV_LOG_ERROR, "Temporal Delimiter in the middle > of a packet.\n"); > + err = AVERROR_INVALIDDATA; > + goto fail; > + } > + err = ff_cbs_insert_unit_content(ctx->cbc, tu, -1, > frag->units[i].type, > + frag->units[i].content, > frag->units[i].content_ref); > + if (err < 0) > + goto fail; > + } > + ff_cbs_fragment_reset(ctx->cbc, frag); > + > + return err; > + } > + > + for (i = 0; i < frag->nb_units; i++) { > + if (i && frag->units[i].type == AV1_OBU_TEMPORAL_DELIMITER) { > + av_log(bsf, AV_LOG_ERROR, "Temporal Delimiter in the middle of a > packet.\n"); > + err = AVERROR_INVALIDDATA; > + goto fail; > + } > + err = ff_cbs_insert_unit_content(ctx->cbc, tu, -1, > frag->units[i].type, > + frag->units[i].content, > frag->units[i].content_ref); > + if (err < 0) > + goto fail; > + } > + ff_cbs_fragment_reset(ctx->cbc, frag); > + av_packet_unref(pkt); > + > + return err < 0 ? err : AVERROR(EAGAIN); > + > +fail: > + ff_cbs_fragment_reset(ctx->cbc, tu); > + ff_cbs_fragment_reset(ctx->cbc, frag); > + av_packet_unref(pkt); > + > + return err; > +} > + > +static int av1_frame_merge_init(AVBSFContext *bsf) > +{ > + AV1FMergeContext *ctx = bsf->priv_data; > + int ret; > + > + ret = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_AV1, bsf); > + if (ret < 0) > + return ret; > + > + return 0; > +} > + > +static void av1_frame_merge_flush(AVBSFContext *bsf) > +{ > + AV1FMergeContext *ctx = bsf->priv_data; > + > + ff_cbs_fragment_reset(ctx->cbc, &ctx->temporal_unit); > + ff_cbs_fragment_reset(ctx->cbc, &ctx->frag); > +} > + > +static void av1_frame_merge_close(AVBSFContext *bsf) > +{ > + AV1FMergeContext *ctx = bsf->priv_data; > + > + ff_cbs_fragment_free(ctx->cbc, &ctx->temporal_unit); > + ff_cbs_fragment_free(ctx->cbc, &ctx->frag); > + ff_cbs_close(&ctx->cbc); > +} > + > +static const enum AVCodecID av1_frame_merge_codec_ids[] = { > + AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, > +}; > + > +const AVBitStreamFilter ff_av1_frame_merge_bsf = { > + .name = "av1_frame_merge", > + .priv_data_size = sizeof(AV1FMergeContext), > + .init = av1_frame_merge_init, > + .flush = av1_frame_merge_flush, > + .close = av1_frame_merge_close, > + .filter = av1_frame_merge_filter, > + .codec_ids = av1_frame_merge_codec_ids, > +}; > diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c > index 463003966a..6b5ffe4d70 100644 > --- a/libavcodec/bitstream_filters.c > +++ b/libavcodec/bitstream_filters.c > @@ -25,6 +25,7 @@ > #include "bsf.h" > > extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; > +extern const AVBitStreamFilter ff_av1_frame_merge_bsf; > extern const AVBitStreamFilter ff_av1_frame_split_bsf; > extern const AVBitStreamFilter ff_av1_metadata_bsf; > extern const AVBitStreamFilter ff_chomp_bsf; > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".