Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-10-03 Thread James Almer

On 9/28/2022 12:39 PM, Anton Khirnov wrote:

Quoting James Almer (2022-09-23 16:27:32)

On 9/23/2022 10:06 AM, Anton Khirnov wrote:

+static int dts2pts_filter(AVBSFContext *ctx, AVPacket *out)
+{
+DTS2PTSContext *s = ctx->priv_data;
+DTS2PTSNode *poc_node = NULL, *next[2] = { NULL, NULL };
+DTS2PTSFrame frame;
+int ret;
+
+// Fill up the FIFO and POC tree
+if (!s->eof && av_fifo_can_write(s->fifo)) {


More than one packet can be available, so this should probably be a
loop.


What do you mean? AVBSFContext can contain at most one buffered packet.


I'd prefer if filters didn't make any such assumptions.


Will make that change and apply.
___
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".


Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-09-28 Thread Anton Khirnov
Quoting James Almer (2022-09-23 16:27:32)
> On 9/23/2022 10:06 AM, Anton Khirnov wrote:
> >> +static int dts2pts_filter(AVBSFContext *ctx, AVPacket *out)
> >> +{
> >> +DTS2PTSContext *s = ctx->priv_data;
> >> +DTS2PTSNode *poc_node = NULL, *next[2] = { NULL, NULL };
> >> +DTS2PTSFrame frame;
> >> +int ret;
> >> +
> >> +// Fill up the FIFO and POC tree
> >> +if (!s->eof && av_fifo_can_write(s->fifo)) {
> > 
> > More than one packet can be available, so this should probably be a
> > loop.
> 
> What do you mean? AVBSFContext can contain at most one buffered packet.

I'd prefer if filters didn't make any such assumptions.

-- 
Anton Khirnov
___
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".


Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-09-23 Thread James Almer

On 9/23/2022 10:06 AM, Anton Khirnov wrote:

Quoting James Almer (2022-09-05 03:09:55)

+static int h264_init(AVBSFContext *ctx)
+{
+DTS2PTSContext *s = ctx->priv_data;
+DTS2PTSH264Context *h264 = >u.h264;
+
+s->cbc->decompose_unit_types= h264_decompose_unit_types;
+s->cbc->nb_decompose_unit_types = 
FF_ARRAY_ELEMS(h264_decompose_unit_types);
+
+s->nb_frame = -(ctx->par_in->video_delay << 1);
+h264->last_poc = h264->highest_poc = INT_MIN;


just call h264_flush()?


Ok. I avoided doing that since the memsets in there would be run for no 
gain. But this is init() after all, so called only once.





+return 0;
+}
+
+static int get_mmco_reset(const H264RawSliceHeader *header)
+{
+if (header->nal_unit_header.nal_ref_idc == 0 ||
+!header->adaptive_ref_pic_marking_mode_flag)
+return 0;
+
+for (int i = 0; i < H264_MAX_MMCO_COUNT; i++) {
+if (header->mmco[i].memory_management_control_operation == 0)
+return 0;
+else if (header->mmco[i].memory_management_control_operation == 5)
+return 1;
+}
+
+return 0;
+}
+
+static int h264_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, int 
*queued)
+{
+DTS2PTSContext *s = ctx->priv_data;
+DTS2PTSH264Context *h264 = >u.h264;
+DTS2PTSFrame frame;
+int poc_diff, ret;
+
+poc_diff = (h264->picture_structure == 3) + 1;
+if (h264->sps.frame_mbs_only_flag && h264->poc_diff)
+poc_diff = FFMIN(poc_diff, h264->poc_diff);
+if (poc < 0) {
+av_tree_enumerate(s->root, _diff, NULL, dec_poc);
+s->nb_frame -= poc_diff;
+}
+// Check if there was a POC reset (Like an IDR slice)


I don't think this is enough. You should bump the sequence counter on
- IDR
- MMCO type 5
- SPS change
- H264_NAL_END_SEQUENCE/STREAM


This is handled when parsing the packet. ff_h264_init_poc() will return 
the actual POC value for the frame as coded in the bistream, which 
should have been reset in all those cases.



Then every sequence should get a separate tree and you sort POCs in each
tree.


When POC is reset, for example on an IDR, the last few frames of the 
previous GOP are meant to have as PTS the DTS from the first few frames 
in the new GOP. Is using separate trees really simplifying things if i 
still need to cross tree boundaries to fetch timestamps?





+if (s->nb_frame > h264->highest_poc) {
+s->nb_frame = 0;
+s->gop = (s->gop + 1) % s->fifo_size;
+h264->highest_poc = h264->last_poc;
+}
+
+ret = alloc_and_insert_node(ctx, pkt->dts, pkt->duration, s->nb_frame, 
poc_diff, s->gop);
+if (ret < 0)
+return ret;
+av_log(ctx, AV_LOG_DEBUG, "Queueing frame with POC %d, GOP %d, dts 
%"PRId64"\n",
+   poc, s->gop, pkt->dts);
+s->nb_frame += poc_diff;
+
+// Add frame to output FIFO only once
+if (*queued)
+return 0;
+
+frame = (DTS2PTSFrame) { pkt, poc, poc_diff, s->gop };
+ret = av_fifo_write(s->fifo, , 1);
+av_assert2(ret >= 0);
+*queued = 1;
+
+return 0;
+}
+
+static int h264_filter(AVBSFContext *ctx)
+{
+DTS2PTSContext *s = ctx->priv_data;
+DTS2PTSH264Context *h264 = >u.h264;
+CodedBitstreamFragment *au = >au;
+AVPacket *in;
+int output_picture_number = INT_MIN;
+int field_poc[2];
+int queued = 0, ret;
+
+ret = ff_bsf_get_packet(ctx, );
+if (ret < 0)
+return ret;
+
+ret = ff_cbs_read_packet(s->cbc, au, in);
+if (ret < 0) {
+av_log(ctx, AV_LOG_WARNING, "Failed to parse access unit.\n");
+goto fail;
+}
+
+for (int i = 0; i < au->nb_units; i++) {
+CodedBitstreamUnit *unit = >units[i];
+
+switch (unit->type) {
+case H264_NAL_IDR_SLICE:
+h264->poc.prev_frame_num= 0;
+h264->poc.prev_frame_num_offset = 0;
+h264->poc.prev_poc_msb  =
+h264->poc.prev_poc_lsb  = 0;
+// fall-through
+case H264_NAL_SLICE: {
+const H264RawSlice *slice = unit->content;
+const H264RawSliceHeader *header = >header;
+const CodedBitstreamH264Context *cbs_h264 = s->cbc->priv_data;
+const H264RawSPS *sps = cbs_h264->active_sps;
+int got_reset;
+
+if (!sps) {
+av_log(ctx, AV_LOG_ERROR, "No active SPS for a slice\n");
+goto fail;
+}
+// Initialize the SPS struct with the fields ff_h264_init_poc() 
cares about
+h264->sps.frame_mbs_only_flag= 
sps->frame_mbs_only_flag;
+h264->sps.log2_max_frame_num = 
sps->log2_max_frame_num_minus4 + 4;
+h264->sps.poc_type   = sps->pic_order_cnt_type;
+h264->sps.log2_max_poc_lsb   = 
sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
+h264->sps.offset_for_non_ref_pic = 
sps->offset_for_non_ref_pic;
+

Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-09-23 Thread Anton Khirnov
Quoting James Almer (2022-09-05 03:09:55)
> +static int h264_init(AVBSFContext *ctx)
> +{
> +DTS2PTSContext *s = ctx->priv_data;
> +DTS2PTSH264Context *h264 = >u.h264;
> +
> +s->cbc->decompose_unit_types= h264_decompose_unit_types;
> +s->cbc->nb_decompose_unit_types = 
> FF_ARRAY_ELEMS(h264_decompose_unit_types);
> +
> +s->nb_frame = -(ctx->par_in->video_delay << 1);
> +h264->last_poc = h264->highest_poc = INT_MIN;

just call h264_flush()?

> +return 0;
> +}
> +
> +static int get_mmco_reset(const H264RawSliceHeader *header)
> +{
> +if (header->nal_unit_header.nal_ref_idc == 0 ||
> +!header->adaptive_ref_pic_marking_mode_flag)
> +return 0;
> +
> +for (int i = 0; i < H264_MAX_MMCO_COUNT; i++) {
> +if (header->mmco[i].memory_management_control_operation == 0)
> +return 0;
> +else if (header->mmco[i].memory_management_control_operation == 5)
> +return 1;
> +}
> +
> +return 0;
> +}
> +
> +static int h264_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, int 
> *queued)
> +{
> +DTS2PTSContext *s = ctx->priv_data;
> +DTS2PTSH264Context *h264 = >u.h264;
> +DTS2PTSFrame frame;
> +int poc_diff, ret;
> +
> +poc_diff = (h264->picture_structure == 3) + 1;
> +if (h264->sps.frame_mbs_only_flag && h264->poc_diff)
> +poc_diff = FFMIN(poc_diff, h264->poc_diff);
> +if (poc < 0) {
> +av_tree_enumerate(s->root, _diff, NULL, dec_poc);
> +s->nb_frame -= poc_diff;
> +}
> +// Check if there was a POC reset (Like an IDR slice)

I don't think this is enough. You should bump the sequence counter on
- IDR
- MMCO type 5
- SPS change
- H264_NAL_END_SEQUENCE/STREAM
Then every sequence should get a separate tree and you sort POCs in each
tree.

> +if (s->nb_frame > h264->highest_poc) {
> +s->nb_frame = 0;
> +s->gop = (s->gop + 1) % s->fifo_size;
> +h264->highest_poc = h264->last_poc;
> +}
> +
> +ret = alloc_and_insert_node(ctx, pkt->dts, pkt->duration, s->nb_frame, 
> poc_diff, s->gop);
> +if (ret < 0)
> +return ret;
> +av_log(ctx, AV_LOG_DEBUG, "Queueing frame with POC %d, GOP %d, dts 
> %"PRId64"\n",
> +   poc, s->gop, pkt->dts);
> +s->nb_frame += poc_diff;
> +
> +// Add frame to output FIFO only once
> +if (*queued)
> +return 0;
> +
> +frame = (DTS2PTSFrame) { pkt, poc, poc_diff, s->gop };
> +ret = av_fifo_write(s->fifo, , 1);
> +av_assert2(ret >= 0);
> +*queued = 1;
> +
> +return 0;
> +}
> +
> +static int h264_filter(AVBSFContext *ctx)
> +{
> +DTS2PTSContext *s = ctx->priv_data;
> +DTS2PTSH264Context *h264 = >u.h264;
> +CodedBitstreamFragment *au = >au;
> +AVPacket *in;
> +int output_picture_number = INT_MIN;
> +int field_poc[2];
> +int queued = 0, ret;
> +
> +ret = ff_bsf_get_packet(ctx, );
> +if (ret < 0)
> +return ret;
> +
> +ret = ff_cbs_read_packet(s->cbc, au, in);
> +if (ret < 0) {
> +av_log(ctx, AV_LOG_WARNING, "Failed to parse access unit.\n");
> +goto fail;
> +}
> +
> +for (int i = 0; i < au->nb_units; i++) {
> +CodedBitstreamUnit *unit = >units[i];
> +
> +switch (unit->type) {
> +case H264_NAL_IDR_SLICE:
> +h264->poc.prev_frame_num= 0;
> +h264->poc.prev_frame_num_offset = 0;
> +h264->poc.prev_poc_msb  =
> +h264->poc.prev_poc_lsb  = 0;
> +// fall-through
> +case H264_NAL_SLICE: {
> +const H264RawSlice *slice = unit->content;
> +const H264RawSliceHeader *header = >header;
> +const CodedBitstreamH264Context *cbs_h264 = s->cbc->priv_data;
> +const H264RawSPS *sps = cbs_h264->active_sps;
> +int got_reset;
> +
> +if (!sps) {
> +av_log(ctx, AV_LOG_ERROR, "No active SPS for a slice\n");
> +goto fail;
> +}
> +// Initialize the SPS struct with the fields ff_h264_init_poc() 
> cares about
> +h264->sps.frame_mbs_only_flag= 
> sps->frame_mbs_only_flag;
> +h264->sps.log2_max_frame_num = 
> sps->log2_max_frame_num_minus4 + 4;
> +h264->sps.poc_type   = 
> sps->pic_order_cnt_type;
> +h264->sps.log2_max_poc_lsb   = 
> sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
> +h264->sps.offset_for_non_ref_pic = 
> sps->offset_for_non_ref_pic;
> +h264->sps.offset_for_top_to_bottom_field = 
> sps->offset_for_top_to_bottom_field;
> +h264->sps.poc_cycle_length   = 
> sps->num_ref_frames_in_pic_order_cnt_cycle;
> +for (int i = 0; i < h264->sps.poc_cycle_length; i++)

moderately evil shadowing

> +h264->sps.offset_for_ref_frame[i] = 
> sps->offset_for_ref_frame[i];
> +
> +

[FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-09-04 Thread James Almer
Starting with an h264 implementation. Can be extended to support other codecs.

A few caveats:
- OpenGOP streams are currently not supported. The firt packet must be an IDR
  frame.
- In some streams, a few frames at the end may not get a reordered PTS when
  they reference frames past EOS. The code added to derive timestamps from
  previous frames needs to be extended.

Addresses ticket #502.

Signed-off-by: James Almer 
---
Changes since v1:
- Properly handle video delay frames when building the tree instead of looking
  for negative dts.
- Increase the amount of packets to buffer by four.
- Keep track of poc reset in the tree by also identifying the GOP each POC came
  from.
  
TODO:
- More thorough garbage collection in the tree.
- Support streams that don't start with an IDR.
- Handle frames that reference POC past EOS in all cases.

 configure  |   1 +
 libavcodec/Makefile|   1 +
 libavcodec/bitstream_filters.c |   1 +
 libavcodec/dts2pts_bsf.c   | 534 +
 4 files changed, 537 insertions(+)
 create mode 100644 libavcodec/dts2pts_bsf.c

diff --git a/configure b/configure
index 932ea5b553..91ee5eb303 100755
--- a/configure
+++ b/configure
@@ -3275,6 +3275,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
 av1_frame_merge_bsf_select="cbs_av1"
 av1_frame_split_bsf_select="cbs_av1"
 av1_metadata_bsf_select="cbs_av1"
+dts2pts_bsf_select="cbs_h264 h264parse"
 eac3_core_bsf_select="ac3_parser"
 filter_units_bsf_select="cbs"
 h264_metadata_bsf_deps="const_nan"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index cb80f73d99..858e110b79 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1176,6 +1176,7 @@ 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
 OBJS-$(CONFIG_DCA_CORE_BSF)   += dca_core_bsf.o
+OBJS-$(CONFIG_DTS2PTS_BSF)+= dts2pts_bsf.o
 OBJS-$(CONFIG_DV_ERROR_MARKER_BSF)+= dv_error_marker_bsf.o
 OBJS-$(CONFIG_EAC3_CORE_BSF)  += eac3_core_bsf.o
 OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF)  += extract_extradata_bsf.o\
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 23ae93..a3bebefe5f 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
 extern const FFBitStreamFilter ff_chomp_bsf;
 extern const FFBitStreamFilter ff_dump_extradata_bsf;
 extern const FFBitStreamFilter ff_dca_core_bsf;
+extern const FFBitStreamFilter ff_dts2pts_bsf;
 extern const FFBitStreamFilter ff_dv_error_marker_bsf;
 extern const FFBitStreamFilter ff_eac3_core_bsf;
 extern const FFBitStreamFilter ff_extract_extradata_bsf;
diff --git a/libavcodec/dts2pts_bsf.c b/libavcodec/dts2pts_bsf.c
new file mode 100644
index 00..aaa1d1c370
--- /dev/null
+++ b/libavcodec/dts2pts_bsf.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2022 James Almer
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * Derive PTS by reordering DTS from supported streams
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/tree.h"
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "cbs.h"
+#include "cbs_h264.h"
+#include "h264_parse.h"
+#include "h264_ps.h"
+
+typedef struct DTS2PTSNode {
+int64_t  dts;
+int64_t duration;
+int  poc;
+int  gop;
+} DTS2PTSNode;
+
+typedef struct DTS2PTSFrame {
+AVPacket*pkt;
+int  poc;
+int poc_diff;
+int  gop;
+} DTS2PTSFrame;
+
+typedef struct DTS2PTSH264Context {
+H264POCContext poc;
+SPS sps;
+int poc_diff;
+int last_poc;
+int highest_poc;
+int picture_structure;
+} DTS2PTSH264Context;
+
+typedef struct DTS2PTSContext {
+struct AVTreeNode *root;
+AVFifo *fifo;
+
+// Codec specific function pointers and constants
+int (*init)(AVBSFContext *ctx);
+int (*filter)(AVBSFContext *ctx);
+void (*flush)(AVBSFContext *ctx);
+size_t fifo_size;
+
+CodedBitstreamContext *cbc;
+

Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-08-30 Thread Andreas Rheinhardt
James Almer:
> On 8/30/2022 11:30 AM, Andreas Rheinhardt wrote:
>> James Almer:
>>> Starting with an h264 implementation. Can be extended to support
>>> other codecs.
>>>
>>> Addresses ticket #502.
>>>
>>> Signed-off-by: James Almer 
>>> ---
>>>   configure  |   1 +
>>>   libavcodec/Makefile    |   1 +
>>>   libavcodec/bitstream_filters.c |   1 +
>>>   libavcodec/dts2pts_bsf.c   | 477 +
>>>   4 files changed, 480 insertions(+)
>>>   create mode 100644 libavcodec/dts2pts_bsf.c
>>>
>>> diff --git a/configure b/configure
>>> index 932ea5b553..91ee5eb303 100755
>>> --- a/configure
>>> +++ b/configure
>>> @@ -3275,6 +3275,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
>>>   av1_frame_merge_bsf_select="cbs_av1"
>>>   av1_frame_split_bsf_select="cbs_av1"
>>>   av1_metadata_bsf_select="cbs_av1"
>>> +dts2pts_bsf_select="cbs_h264 h264parse"
>>>   eac3_core_bsf_select="ac3_parser"
>>>   filter_units_bsf_select="cbs"
>>>   h264_metadata_bsf_deps="const_nan"
>>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>>> index cb80f73d99..858e110b79 100644
>>> --- a/libavcodec/Makefile
>>> +++ b/libavcodec/Makefile
>>> @@ -1176,6 +1176,7 @@ 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
>>>   OBJS-$(CONFIG_DCA_CORE_BSF)   += dca_core_bsf.o
>>> +OBJS-$(CONFIG_DTS2PTS_BSF)    += dts2pts_bsf.o
>>>   OBJS-$(CONFIG_DV_ERROR_MARKER_BSF)    += dv_error_marker_bsf.o
>>>   OBJS-$(CONFIG_EAC3_CORE_BSF)  += eac3_core_bsf.o
>>>   OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF)  +=
>>> extract_extradata_bsf.o    \
>>> diff --git a/libavcodec/bitstream_filters.c
>>> b/libavcodec/bitstream_filters.c
>>> index 23ae93..a3bebefe5f 100644
>>> --- a/libavcodec/bitstream_filters.c
>>> +++ b/libavcodec/bitstream_filters.c
>>> @@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
>>>   extern const FFBitStreamFilter ff_chomp_bsf;
>>>   extern const FFBitStreamFilter ff_dump_extradata_bsf;
>>>   extern const FFBitStreamFilter ff_dca_core_bsf;
>>> +extern const FFBitStreamFilter ff_dts2pts_bsf;
>>>   extern const FFBitStreamFilter ff_dv_error_marker_bsf;
>>>   extern const FFBitStreamFilter ff_eac3_core_bsf;
>>>   extern const FFBitStreamFilter ff_extract_extradata_bsf;
>>> diff --git a/libavcodec/dts2pts_bsf.c b/libavcodec/dts2pts_bsf.c
>>> new file mode 100644
>>> index 00..f600150a6b
>>> --- /dev/null
>>> +++ b/libavcodec/dts2pts_bsf.c
>>> @@ -0,0 +1,477 @@
>>> +/*
>>> + * Copyright (c) 2022 James Almer
>>> + *
>>> + * 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
>>> + */
>>> +
>>> +/**
>>> + * @file
>>> + * Derive PTS by reordering DTS from supported streams
>>> + */
>>> +
>>> +#include "libavutil/avassert.h"
>>> +#include "libavutil/eval.h"

Unused.

>>> +#include "libavutil/fifo.h"
>>> +#include "libavutil/opt.h"
>>> +#include "libavutil/tree.h"
>>> +
>>> +#include "bsf.h"
>>> +#include "bsf_internal.h"
>>> +#include "cbs.h"
>>> +#include "cbs_h264.h"
>>> +#include "h264_parse.h"
>>> +#include "h264_ps.h"
>>> +
>>> +typedef struct DTS2PTSNode {
>>> +    int64_t  dts;
>>> +    int64_t duration;
>>> +    int  poc;
>>> +} DTS2PTSNode;
>>> +
>>> +typedef struct DTS2PTSFrame {
>>> +    AVPacket    *pkt;
>>> +    int  poc;
>>> +    int poc_diff;
>>> +} DTS2PTSFrame;
>>> +
>>> +typedef struct DTS2PTSH264Context {
>>> +    H264POCContext poc;
>>> +    SPS sps;
>>> +    int last_poc;
>>> +    int highest_poc;
>>> +    int picture_structure;
>>> +} DTS2PTSH264Context;
>>> +
>>> +typedef struct DTS2PTSContext {
>>> +    struct AVTreeNode *root;
>>> +    AVFifo *fifo;
>>> +
>>> +    // Codec specific function pointers
>>> +    int (*init)(AVBSFContext *ctx);
>>> +    int (*filter)(AVBSFContext *ctx);
>>> +    void (*flush)(AVBSFContext *ctx);
>>> +
>>> +    CodedBitstreamContext *cbc;
>>> +    CodedBitstreamFragment au;
>>> +
>>> +    union {
>>> +    DTS2PTSH264Context h264;
>>> +    } u;
>>> +
>>> +    int nb_frame;
>>> +    int eof;
>>> +} DTS2PTSContext;
>>> +
>>> 

Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-08-30 Thread James Almer

On 8/30/2022 11:30 AM, Andreas Rheinhardt wrote:

James Almer:

Starting with an h264 implementation. Can be extended to support other codecs.

Addresses ticket #502.

Signed-off-by: James Almer 
---
  configure  |   1 +
  libavcodec/Makefile|   1 +
  libavcodec/bitstream_filters.c |   1 +
  libavcodec/dts2pts_bsf.c   | 477 +
  4 files changed, 480 insertions(+)
  create mode 100644 libavcodec/dts2pts_bsf.c

diff --git a/configure b/configure
index 932ea5b553..91ee5eb303 100755
--- a/configure
+++ b/configure
@@ -3275,6 +3275,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
  av1_frame_merge_bsf_select="cbs_av1"
  av1_frame_split_bsf_select="cbs_av1"
  av1_metadata_bsf_select="cbs_av1"
+dts2pts_bsf_select="cbs_h264 h264parse"
  eac3_core_bsf_select="ac3_parser"
  filter_units_bsf_select="cbs"
  h264_metadata_bsf_deps="const_nan"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index cb80f73d99..858e110b79 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1176,6 +1176,7 @@ 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
  OBJS-$(CONFIG_DCA_CORE_BSF)   += dca_core_bsf.o
+OBJS-$(CONFIG_DTS2PTS_BSF)+= dts2pts_bsf.o
  OBJS-$(CONFIG_DV_ERROR_MARKER_BSF)+= dv_error_marker_bsf.o
  OBJS-$(CONFIG_EAC3_CORE_BSF)  += eac3_core_bsf.o
  OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF)  += extract_extradata_bsf.o\
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 23ae93..a3bebefe5f 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
  extern const FFBitStreamFilter ff_chomp_bsf;
  extern const FFBitStreamFilter ff_dump_extradata_bsf;
  extern const FFBitStreamFilter ff_dca_core_bsf;
+extern const FFBitStreamFilter ff_dts2pts_bsf;
  extern const FFBitStreamFilter ff_dv_error_marker_bsf;
  extern const FFBitStreamFilter ff_eac3_core_bsf;
  extern const FFBitStreamFilter ff_extract_extradata_bsf;
diff --git a/libavcodec/dts2pts_bsf.c b/libavcodec/dts2pts_bsf.c
new file mode 100644
index 00..f600150a6b
--- /dev/null
+++ b/libavcodec/dts2pts_bsf.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2022 James Almer
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * Derive PTS by reordering DTS from supported streams
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/eval.h"
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/tree.h"
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "cbs.h"
+#include "cbs_h264.h"
+#include "h264_parse.h"
+#include "h264_ps.h"
+
+typedef struct DTS2PTSNode {
+int64_t  dts;
+int64_t duration;
+int  poc;
+} DTS2PTSNode;
+
+typedef struct DTS2PTSFrame {
+AVPacket*pkt;
+int  poc;
+int poc_diff;
+} DTS2PTSFrame;
+
+typedef struct DTS2PTSH264Context {
+H264POCContext poc;
+SPS sps;
+int last_poc;
+int highest_poc;
+int picture_structure;
+} DTS2PTSH264Context;
+
+typedef struct DTS2PTSContext {
+struct AVTreeNode *root;
+AVFifo *fifo;
+
+// Codec specific function pointers
+int (*init)(AVBSFContext *ctx);
+int (*filter)(AVBSFContext *ctx);
+void (*flush)(AVBSFContext *ctx);
+
+CodedBitstreamContext *cbc;
+CodedBitstreamFragment au;
+
+union {
+DTS2PTSH264Context h264;
+} u;
+
+int nb_frame;
+int eof;
+} DTS2PTSContext;
+
+// AVTreeNode callbacks
+static int cmp_insert(const void *key, const void *node)
+{
+return ((const DTS2PTSNode *) key)->poc - ((const DTS2PTSNode *) 
node)->poc;
+}
+
+static int cmp_find(const void *key, const void *node)
+{
+return *(const int *)key - ((const DTS2PTSNode *) node)->poc;
+}
+
+static int dec_poc(void *opaque, void *elem)
+{
+DTS2PTSNode *node = elem;
+int dec = *(int *)opaque;
+node->poc -= dec;
+return 0;
+}
+
+static int free_node(void *opaque, void *elem)
+{
+DTS2PTSNode *node = elem;
+av_free(node);
+return 0;

Re: [FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-08-30 Thread Andreas Rheinhardt
James Almer:
> Starting with an h264 implementation. Can be extended to support other codecs.
> 
> Addresses ticket #502.
> 
> Signed-off-by: James Almer 
> ---
>  configure  |   1 +
>  libavcodec/Makefile|   1 +
>  libavcodec/bitstream_filters.c |   1 +
>  libavcodec/dts2pts_bsf.c   | 477 +
>  4 files changed, 480 insertions(+)
>  create mode 100644 libavcodec/dts2pts_bsf.c
> 
> diff --git a/configure b/configure
> index 932ea5b553..91ee5eb303 100755
> --- a/configure
> +++ b/configure
> @@ -3275,6 +3275,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
>  av1_frame_merge_bsf_select="cbs_av1"
>  av1_frame_split_bsf_select="cbs_av1"
>  av1_metadata_bsf_select="cbs_av1"
> +dts2pts_bsf_select="cbs_h264 h264parse"
>  eac3_core_bsf_select="ac3_parser"
>  filter_units_bsf_select="cbs"
>  h264_metadata_bsf_deps="const_nan"
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index cb80f73d99..858e110b79 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -1176,6 +1176,7 @@ 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
>  OBJS-$(CONFIG_DCA_CORE_BSF)   += dca_core_bsf.o
> +OBJS-$(CONFIG_DTS2PTS_BSF)+= dts2pts_bsf.o
>  OBJS-$(CONFIG_DV_ERROR_MARKER_BSF)+= dv_error_marker_bsf.o
>  OBJS-$(CONFIG_EAC3_CORE_BSF)  += eac3_core_bsf.o
>  OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF)  += extract_extradata_bsf.o\
> diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
> index 23ae93..a3bebefe5f 100644
> --- a/libavcodec/bitstream_filters.c
> +++ b/libavcodec/bitstream_filters.c
> @@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
>  extern const FFBitStreamFilter ff_chomp_bsf;
>  extern const FFBitStreamFilter ff_dump_extradata_bsf;
>  extern const FFBitStreamFilter ff_dca_core_bsf;
> +extern const FFBitStreamFilter ff_dts2pts_bsf;
>  extern const FFBitStreamFilter ff_dv_error_marker_bsf;
>  extern const FFBitStreamFilter ff_eac3_core_bsf;
>  extern const FFBitStreamFilter ff_extract_extradata_bsf;
> diff --git a/libavcodec/dts2pts_bsf.c b/libavcodec/dts2pts_bsf.c
> new file mode 100644
> index 00..f600150a6b
> --- /dev/null
> +++ b/libavcodec/dts2pts_bsf.c
> @@ -0,0 +1,477 @@
> +/*
> + * Copyright (c) 2022 James Almer
> + *
> + * 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
> + */
> +
> +/**
> + * @file
> + * Derive PTS by reordering DTS from supported streams
> + */
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/eval.h"
> +#include "libavutil/fifo.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/tree.h"
> +
> +#include "bsf.h"
> +#include "bsf_internal.h"
> +#include "cbs.h"
> +#include "cbs_h264.h"
> +#include "h264_parse.h"
> +#include "h264_ps.h"
> +
> +typedef struct DTS2PTSNode {
> +int64_t  dts;
> +int64_t duration;
> +int  poc;
> +} DTS2PTSNode;
> +
> +typedef struct DTS2PTSFrame {
> +AVPacket*pkt;
> +int  poc;
> +int poc_diff;
> +} DTS2PTSFrame;
> +
> +typedef struct DTS2PTSH264Context {
> +H264POCContext poc;
> +SPS sps;
> +int last_poc;
> +int highest_poc;
> +int picture_structure;
> +} DTS2PTSH264Context;
> +
> +typedef struct DTS2PTSContext {
> +struct AVTreeNode *root;
> +AVFifo *fifo;
> +
> +// Codec specific function pointers
> +int (*init)(AVBSFContext *ctx);
> +int (*filter)(AVBSFContext *ctx);
> +void (*flush)(AVBSFContext *ctx);
> +
> +CodedBitstreamContext *cbc;
> +CodedBitstreamFragment au;
> +
> +union {
> +DTS2PTSH264Context h264;
> +} u;
> +
> +int nb_frame;
> +int eof;
> +} DTS2PTSContext;
> +
> +// AVTreeNode callbacks
> +static int cmp_insert(const void *key, const void *node)
> +{
> +return ((const DTS2PTSNode *) key)->poc - ((const DTS2PTSNode *) 
> node)->poc;
> +}
> +
> +static int cmp_find(const void *key, const void *node)
> +{
> +return *(const int *)key - ((const DTS2PTSNode *) node)->poc;
> +}
> +
> +static int dec_poc(void *opaque, void *elem)
> +{

[FFmpeg-devel] [PATCH] avcodec: add a bsf to reorder DTS into PTS

2022-08-29 Thread James Almer
Starting with an h264 implementation. Can be extended to support other codecs.

Addresses ticket #502.

Signed-off-by: James Almer 
---
 configure  |   1 +
 libavcodec/Makefile|   1 +
 libavcodec/bitstream_filters.c |   1 +
 libavcodec/dts2pts_bsf.c   | 477 +
 4 files changed, 480 insertions(+)
 create mode 100644 libavcodec/dts2pts_bsf.c

diff --git a/configure b/configure
index 932ea5b553..91ee5eb303 100755
--- a/configure
+++ b/configure
@@ -3275,6 +3275,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
 av1_frame_merge_bsf_select="cbs_av1"
 av1_frame_split_bsf_select="cbs_av1"
 av1_metadata_bsf_select="cbs_av1"
+dts2pts_bsf_select="cbs_h264 h264parse"
 eac3_core_bsf_select="ac3_parser"
 filter_units_bsf_select="cbs"
 h264_metadata_bsf_deps="const_nan"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index cb80f73d99..858e110b79 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1176,6 +1176,7 @@ 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
 OBJS-$(CONFIG_DCA_CORE_BSF)   += dca_core_bsf.o
+OBJS-$(CONFIG_DTS2PTS_BSF)+= dts2pts_bsf.o
 OBJS-$(CONFIG_DV_ERROR_MARKER_BSF)+= dv_error_marker_bsf.o
 OBJS-$(CONFIG_EAC3_CORE_BSF)  += eac3_core_bsf.o
 OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF)  += extract_extradata_bsf.o\
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 23ae93..a3bebefe5f 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
 extern const FFBitStreamFilter ff_chomp_bsf;
 extern const FFBitStreamFilter ff_dump_extradata_bsf;
 extern const FFBitStreamFilter ff_dca_core_bsf;
+extern const FFBitStreamFilter ff_dts2pts_bsf;
 extern const FFBitStreamFilter ff_dv_error_marker_bsf;
 extern const FFBitStreamFilter ff_eac3_core_bsf;
 extern const FFBitStreamFilter ff_extract_extradata_bsf;
diff --git a/libavcodec/dts2pts_bsf.c b/libavcodec/dts2pts_bsf.c
new file mode 100644
index 00..f600150a6b
--- /dev/null
+++ b/libavcodec/dts2pts_bsf.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2022 James Almer
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * Derive PTS by reordering DTS from supported streams
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/eval.h"
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/tree.h"
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "cbs.h"
+#include "cbs_h264.h"
+#include "h264_parse.h"
+#include "h264_ps.h"
+
+typedef struct DTS2PTSNode {
+int64_t  dts;
+int64_t duration;
+int  poc;
+} DTS2PTSNode;
+
+typedef struct DTS2PTSFrame {
+AVPacket*pkt;
+int  poc;
+int poc_diff;
+} DTS2PTSFrame;
+
+typedef struct DTS2PTSH264Context {
+H264POCContext poc;
+SPS sps;
+int last_poc;
+int highest_poc;
+int picture_structure;
+} DTS2PTSH264Context;
+
+typedef struct DTS2PTSContext {
+struct AVTreeNode *root;
+AVFifo *fifo;
+
+// Codec specific function pointers
+int (*init)(AVBSFContext *ctx);
+int (*filter)(AVBSFContext *ctx);
+void (*flush)(AVBSFContext *ctx);
+
+CodedBitstreamContext *cbc;
+CodedBitstreamFragment au;
+
+union {
+DTS2PTSH264Context h264;
+} u;
+
+int nb_frame;
+int eof;
+} DTS2PTSContext;
+
+// AVTreeNode callbacks
+static int cmp_insert(const void *key, const void *node)
+{
+return ((const DTS2PTSNode *) key)->poc - ((const DTS2PTSNode *) 
node)->poc;
+}
+
+static int cmp_find(const void *key, const void *node)
+{
+return *(const int *)key - ((const DTS2PTSNode *) node)->poc;
+}
+
+static int dec_poc(void *opaque, void *elem)
+{
+DTS2PTSNode *node = elem;
+int dec = *(int *)opaque;
+node->poc -= dec;
+return 0;
+}
+
+static int free_node(void *opaque, void *elem)
+{
+DTS2PTSNode *node = elem;
+av_free(node);
+return 0;
+}
+
+// Shared functions
+static int alloc_and_insert_node(AVBSFContext *ctx, int64_t ts,