FFmpeg: libavcodec/bsf/dts2pts.c Source File
Go to the documentation of this file. 1 /*
2 * Copyright (c) 2022 James Almer
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * Derive PTS by reordering DTS from supported streams
24 */
25
26 #include <stdbool.h>
27
32
35 #include "cbs.h"
42
49
56
65
71
76
77 // Codec specific function pointers and constants
82
85
86 union {
90
95
96 // AVTreeNode callbacks
98 {
103 }
104
106 {
113 }
114
116 {
118 int dec = *(int *)opaque;
120 return 0;
121 }
122
124 {
127 return 0;
128 }
129
130 // Shared functions
132 int poc, int poc_diff, int gop)
133 {
135 for (
int i = 0;
i < poc_diff;
i++) {
138 if (!node)
141 if (!poc_node) {
144 }
149 if (
ret &&
ret != poc_node) {
153 }
154 }
155 return 0;
156 }
157
158 // H.264
164 };
165
167 {
170
173
174 s->nb_frame = -(
ctx->par_in->video_delay << 1);
176
177 return 0;
178 }
179
181 {
182 if (
header->nal_unit_header.nal_ref_idc == 0 ||
183 !
header->adaptive_ref_pic_marking_mode_flag)
184 return 0;
185
187 if (
header->mmco[
i].memory_management_control_operation == 0)
188 return 0;
189 else if (
header->mmco[
i].memory_management_control_operation == 5)
190 return 1;
191 }
192
193 return 0;
194 }
195
197 {
202
206 if (poc < 0) {
208 s->nb_frame -= poc_diff;
209 }
210 // Check if there was a POC reset (Like an IDR slice)
213 s->gop = (
s->gop + 1) %
s->fifo_size;
215 }
216
222 s->nb_frame += poc_diff;
223
224 // Add frame to output FIFO only once
225 if (*queued)
226 return 0;
227
231 *queued = 1;
232
233 return 0;
234 }
235
237 {
242 int output_picture_number = INT_MIN;
243 int field_poc[2];
245
249
250 ret = ff_cbs_read_packet(
s->cbc, au, in);
254 }
255
258
259 switch (unit->
type) {
265 // fall-through
271 int got_reset;
272
277 }
278 // Initialize the SPS struct with the fields ff_h264_init_poc() cares about
288
291 header->field_pic_flag +
header->bottom_field_flag : 3);
292
298
299 field_poc[0] = field_poc[1] = INT_MAX;
302 header->nal_unit_header.nal_ref_idc);
306 }
307
311 if (
header->nal_unit_header.nal_ref_idc != 0) {
313 if (got_reset)
315 else
317 }
318
319 if (output_picture_number != h264->
last_poc) {
322
323 if ((output_picture_number < 0) && !h264->
last_poc)
328 }
334 }
335 }
336 }
337 h264->
last_poc = output_picture_number;
339
343 }
344 break;
345 }
346 default:
347 break;
348 }
349 }
350
351 if (output_picture_number == INT_MIN) {
355 }
356
359 ff_cbs_fragment_reset(au);
360 if (!queued)
362
364 }
365
367 {
370
371 memset(&h264->
sps, 0,
sizeof(h264->
sps));
372 memset(&h264->
poc, 0,
sizeof(h264->
poc));
373 s->nb_frame = -(
ctx->par_in->video_delay << 1);
375 }
376
378 {
381
385 s->nb_frame = -
ctx->par_in->video_delay;
386
387 return 0;
388 }
389
391 {
393 }
394
396 {
400
403
404 int latency =
vps->vps_max_num_reorder_pics[0];
405 if (
vps->vps_max_latency_increase_plus1[0])
406 latency +=
vps->vps_max_latency_increase_plus1[0] - 1;
407
408 s->nb_frame = poc - latency;
410 latency, poc,
s->nb_frame);
411
412 return 0;
413 }
414
416 {
418 int gop = ((int *)opaque)[1];
420 }
421
423 {
427
428 if (hevc->
gop == -1) {
433 }
434
438 s->gop = (
s->gop + 1) %
s->fifo_size;
440 }
441
442 if (poc < s->nb_frame && hevc->
gop ==
s->gop) {
443 int tmp[] = {
s->nb_frame - poc,
s->gop};
444
445 s->nb_frame -=
tmp[0];
447 }
448
452
454 poc,
s->gop,
s->nb_frame,
pkt->
dts);
456
459 .poc = poc,
460 .poc_diff = 1,
462 };
466
467 *queued = true;
468
469 return 0;
470 }
471
473 {
478 bool queued = 0;
482
483 ret = ff_cbs_read_packet(
s->cbc, au, in);
487 }
488
492
495 if (!is_slice)
496 continue;
497
500 continue;
501
508 }
509
510 int poc;
512 poc = 0;
513 hevc->
gop = (hevc->
gop + 1) %
s->fifo_size;
514 } else {
515 unsigned log2_max_poc_lsb =
sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
517
519 }
520
527 }
528
532 break;
533 }
534
535 if (!queued) {
538 }
539
541 ff_cbs_fragment_reset(au);
542 if (!queued)
545 }
546
547 // Core functions
548 static const struct {
557 };
558
560 {
564
571 break;
572 }
573 }
577
581
584
587
588 ret = ff_cbs_init(&
s->cbc,
ctx->par_in->codec_id,
ctx);
591
596 }
597
598 if (!
ctx->par_in->extradata_size)
599 return 0;
600
601 ret = ff_cbs_read_extradata(
s->cbc, au,
ctx->par_in);
604
605 ff_cbs_fragment_reset(au);
606
607 return 0;
608 }
609
611 {
616
617 // Fill up the FIFO and POC tree
624 }
625 }
626
629
630 // Fetch a packet from the FIFO
635
636 // Search the timestamp for the requested POC and set PTS
638 if (!poc_node) {
639 poc_node = next[1];
640 if (!poc_node || poc_node->
poc !=
frame.poc)
641 poc_node = next[0];
642 }
643 if (poc_node && poc_node->
poc ==
frame.poc) {
646 // Remove the found entry from the tree
650 if (!poc_node || poc_node->
dts !=
out->pts)
651 continue;
656 }
657 }
658 }
else if (
s->eof &&
frame.poc > INT_MIN) {
661 if (poc_node && poc_node->
poc == dup.
poc) {
670 }
672 "generated from POC %d, GOP %d, dts %"PRId64", duration %"PRId64"\n",
675 } else
677 } else
681
682 return 0;
683 }
684
686 {
689
694
697
701
702 ff_cbs_fragment_reset(&
s->au);
704 ff_cbs_flush(
s->cbc);
705 }
706
708 {
710
712
715 ff_cbs_fragment_free(&
s->au);
716 ff_cbs_close(&
s->cbc);
717 }
718
723 };
724
733 };
int32_t offset_for_ref_frame[256]
static int hevc_init(AVBSFContext *ctx)
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
#define AV_LOG_WARNING
Something somehow does not look correct.
AVRefStructPool * node_pool
size_t av_fifo_can_write(const AVFifo *f)
static int cmp_find(const void *key, const void *node)
int frame_num_offset
for POC type 2
Filter the word "frame" indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
static void dts2pts_flush(AVBSFContext *ctx)
int offset_for_non_ref_pic
#define AVERROR_EOF
End of file.
void * av_tree_insert(AVTreeNode **tp, void *key, int(*cmp)(const void *key, const void *b), AVTreeNode **next)
Insert or remove an element.
void * content
Pointer to the decomposed form of this unit.
Context structure for coded bitstream operations.
CodedBitstreamUnitType type
Codec-specific type of this unit.
static int dts2pts_filter(AVBSFContext *ctx, AVPacket *out)
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
static int alloc_and_insert_node(AVBSFContext *ctx, int64_t ts, int64_t duration, int poc, int poc_diff, int gop)
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
static int h264_init(AVBSFContext *ctx)
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
void av_tree_enumerate(AVTreeNode *t, void *opaque, int(*cmp)(void *opaque, void *elem), int(*enu)(void *opaque, void *elem))
Apply enu(opaque, &elem) to all the elements in the tree in a given range.
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
The bitstream filter state.
int prev_poc_lsb
poc_lsb of the last reference pic for POC type 0
Coded bitstream unit structure.
int poc_type
pic_order_cnt_type
static const struct @67 func_tab[]
static av_cold void close(AVCodecParserContext *s)
int prev_frame_num
frame_num of the last pic for POC type 1/2
static int same_gop(void *opaque, void *elem)
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
const H264RawSPS * active_sps
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
#define FFDIFFSIGN(x, y)
Comparator.
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
CodedBitstreamContext * cbc
Coded bitstream fragment structure, combining one or more units.
const FFBitStreamFilter ff_dts2pts_bsf
int prev_frame_num_offset
for POC type 2
int(* filter)(AVBSFContext *ctx)
int(* filter)(AVBSFContext *ctx)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
static void h264_flush(AVBSFContext *ctx)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
void(* flush)(AVBSFContext *ctx)
size_t av_fifo_can_read(const AVFifo *f)
void(* flush)(AVBSFContext *ctx)
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
static int FUNC() vps(CodedBitstreamContext *ctx, RWContext *rw, H265RawVPS *current)
static int get_mmco_reset(const H264RawSliceHeader *header)
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
void av_tree_destroy(AVTreeNode *t)
AVCodecID
Identify the syntax and semantics of the bitstream.
static int dts2pts_init(AVBSFContext *ctx)
AVBitStreamFilter p
The public AVBitStreamFilter.
static enum AVCodecID dts2pts_codec_ids[]
int(* init)(AVBSFContext *ctx)
static int hevc_filter(AVBSFContext *ctx)
static int free_node(void *opaque, void *elem)
int poc_cycle_length
num_ref_frames_in_pic_order_cnt_cycle
#define AV_NOPTS_VALUE
Undefined timestamp value.
int(* init)(AVBSFContext *ctx)
static const uint8_t header[24]
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
int offset_for_top_to_bottom_field
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
H264RawSliceHeader header
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
int log2_max_poc_lsb
log2_max_pic_order_cnt_lsb_minus4
#define i(width, name, range_min, range_max)
static int h264_filter(AVBSFContext *ctx)
static int dec_poc(void *opaque, void *elem)
CodedBitstreamFragment au
int ff_hevc_compute_poc2(unsigned log2_max_poc_lsb, int pocTid0, int poc_lsb, int nal_unit_type)
Compute POC of the current frame and return it.
const H265RawSPS * active_sps
static int cmp_insert(const void *key, const void *node)
static void hevc_flush(AVBSFContext *ctx)
int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc, const SPS *sps, H264POCContext *pc, int picture_structure, int nal_ref_idc)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
AVRefStructPool * av_refstruct_pool_alloc(size_t size, unsigned flags)
Equivalent to av_refstruct_pool_alloc(size, flags, NULL, NULL, NULL, NULL, NULL)
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
#define AV_REFSTRUCT_POOL_FLAG_NO_ZEROING
If this flag is not set, every object in the pool will be zeroed before the init callback is called o...
static void dts2pts_close(AVBSFContext *ctx)
const H265RawVPS * active_vps
static const CodedBitstreamUnitType h264_decompose_unit_types[]
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(const void *key, const void *b), void *next[2])
static int hevc_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, bool *queued)
union DTS2PTSContext::@68 u
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
This structure stores compressed data.
static int hevc_init_nb_frame(AVBSFContext *ctx, int poc)
static int h264_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, int *queued)
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
int prev_poc_msb
poc_msb of the last reference pic for POC type 0
void * priv_data
Format private data.
int nb_units
Number of units in this fragment.
int log2_max_frame_num
log2_max_frame_num_minus4 + 4
Generated on Tue Nov 18 2025 19:22:02 for FFmpeg by
doxygen
1.8.17