FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/dts2pts.c
Date: 2026-09-02 11:02:20
Exec Total Coverage
Lines: 349 437 79.9%
Functions: 19 21 90.5%
Branches: 169 253 66.8%

Line Branch Exec Source
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
28 #include "libavutil/attributes.h"
29 #include "libavutil/avassert.h"
30 #include "libavutil/fifo.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/tree.h"
33 #include "libavutil/refstruct.h"
34
35 #include "libavcodec/bsf.h"
36 #include "libavcodec/bsf_internal.h"
37 #include "libavcodec/cbs.h"
38 #include "libavcodec/cbs_h264.h"
39 #include "libavcodec/cbs_h265.h"
40 #include "libavcodec/h264_parse.h"
41 #include "libavcodec/h264_ps.h"
42 #include "libavcodec/hevc/ps.h"
43
44 // Damaged frames leave their up to 2 timestamp nodes behind unconsumed.
45 // This many damaged frames are tolerated before the oldest leftovers are
46 // evicted; no timestamp of a valid frame is lost below this.
47 #define MAX_DAMAGED_FRAMES 32
48
49 typedef struct DTS2PTSNode {
50 int64_t dts;
51 int64_t duration;
52 int poc;
53 int gop;
54 int64_t serial; // insertion order, evicting the stalest node first
55 struct DTS2PTSNode *next; // valid only during same-gop re-keying
56 } DTS2PTSNode;
57
58 typedef struct DTS2PTSFrame {
59 AVPacket *pkt;
60 int poc;
61 int poc_diff;
62 int gop;
63 } DTS2PTSFrame;
64
65 typedef struct DTS2PTSH264Context {
66 H264POCContext poc;
67 SPS sps;
68 int poc_diff;
69 int last_poc;
70 int highest_poc;
71 int picture_structure;
72 } DTS2PTSH264Context;
73
74 typedef struct DTS2PTSHEVCContext {
75 int gop;
76 int poc_tid0;
77 int highest_poc;
78 } DTS2PTSHEVCContext;
79
80 typedef struct DTS2PTSContext {
81 struct AVTreeNode *root;
82 AVFifo *fifo;
83 AVRefStructPool *node_pool;
84
85 // Codec specific function pointers and constants
86 int (*init)(AVBSFContext *ctx);
87 int (*filter)(AVBSFContext *ctx);
88 void (*flush)(AVBSFContext *ctx);
89 size_t fifo_size;
90
91 CodedBitstreamContext *cbc;
92 CodedBitstreamFragment au;
93
94 union {
95 DTS2PTSH264Context h264;
96 DTS2PTSHEVCContext hevc;
97 } u;
98
99 int nb_nodes;
100 int nb_pending;
101 int64_t serial;
102 int nb_frame;
103 int gop;
104 int eof;
105 } DTS2PTSContext;
106
107 // AVTreeNode callbacks
108 2586 static int cmp_insert(const void *key, const void *node)
109 {
110 2586 int ret = ((const DTS2PTSNode *)key)->poc - ((const DTS2PTSNode *)node)->poc;
111
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 2340 times.
2586 if (!ret)
112 246 ret = ((const DTS2PTSNode *)key)->gop - ((const DTS2PTSNode *)node)->gop;
113 2586 return ret;
114 }
115
116 2237 static int cmp_find(const void *key, const void *node)
117 {
118 2237 const DTS2PTSFrame * key1 = key;
119 2237 const DTS2PTSNode *node1 = node;
120 2237 int ret = FFDIFFSIGN(key1->poc, node1->poc);
121
2/2
✓ Branch 0 taken 349 times.
✓ Branch 1 taken 1888 times.
2237 if (!ret)
122 349 ret = key1->gop - node1->gop;
123 2237 return ret;
124 }
125
126 static int dec_poc(void *opaque, void *elem)
127 {
128 DTS2PTSNode *node = elem;
129 int dec = *(int *)opaque;
130 node->poc -= dec;
131 return 0;
132 }
133
134 175 static int free_node(void *opaque, void *elem)
135 {
136 175 DTS2PTSNode *node = elem;
137 175 av_refstruct_unref(&node);
138 175 return 0;
139 }
140
141 static int find_stalest(void *opaque, void *elem)
142 {
143 DTS2PTSNode **stalest = opaque;
144 DTS2PTSNode *node = elem;
145 if (!*stalest || node->serial < (*stalest)->serial)
146 *stalest = node;
147 return 0;
148 }
149
150 // Shared functions
151 304 static int alloc_and_insert_node(AVBSFContext *ctx, int64_t ts, int64_t duration,
152 int poc, int poc_diff, int gop)
153 {
154 304 DTS2PTSContext *s = ctx->priv_data;
155
156
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 304 times.
629 for (int i = 0; i < poc_diff; i++) {
157 325 struct AVTreeNode *node = av_tree_node_alloc();
158 DTS2PTSNode *poc_node, *ret;
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (!node)
160 return AVERROR(ENOMEM);
161 325 poc_node = av_refstruct_pool_get(s->node_pool);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (!poc_node) {
163 av_free(node);
164 return AVERROR(ENOMEM);
165 }
166
3/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 304 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
325 if (i && ts != AV_NOPTS_VALUE)
167 21 ts += duration / poc_diff;
168 325 *poc_node = (DTS2PTSNode) { ts, duration, poc++, gop, s->serial++ };
169 325 ret = av_tree_insert(&s->root, poc_node, cmp_insert, &node);
170
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 300 times.
325 if (ret && ret != poc_node) {
171 *ret = *poc_node;
172 av_refstruct_unref(&poc_node);
173 av_free(node);
174 } else
175 325 s->nb_nodes++;
176 }
177 304 return 0;
178 }
179
180 // H.264
181 static const CodedBitstreamUnitType h264_decompose_unit_types[] = {
182 H264_NAL_SPS,
183 H264_NAL_PPS,
184 H264_NAL_IDR_SLICE,
185 H264_NAL_SLICE,
186 };
187
188 1 static int h264_init(AVBSFContext *ctx)
189 {
190 1 DTS2PTSContext *s = ctx->priv_data;
191 1 DTS2PTSH264Context *h264 = &s->u.h264;
192
193 1 s->cbc->decompose_unit_types = h264_decompose_unit_types;
194 1 s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(h264_decompose_unit_types);
195
196 1 s->nb_frame = -(ctx->par_in->video_delay << 1);
197 1 h264->last_poc = h264->highest_poc = INT_MIN;
198
199 1 return 0;
200 }
201
202 79 static int get_mmco_reset(const H264RawSliceHeader *header)
203 {
204
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 51 times.
79 if (header->nal_unit_header.nal_ref_idc == 0 ||
205
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 !header->adaptive_ref_pic_marking_mode_flag)
206 79 return 0;
207
208 for (int i = 0; i < H264_MAX_MMCO_COUNT; i++) {
209 if (header->mmco[i].memory_management_control_operation == 0)
210 return 0;
211 else if (header->mmco[i].memory_management_control_operation == 5)
212 return 1;
213 }
214
215 return 0;
216 }
217
218 79 static int h264_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, int *queued)
219 {
220 79 DTS2PTSContext *s = ctx->priv_data;
221 79 DTS2PTSH264Context *h264 = &s->u.h264;
222 DTS2PTSFrame frame;
223 int poc_diff, ret;
224
225
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 58 times.
79 poc_diff = (h264->picture_structure == 3) + 1;
226
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
79 if (h264->sps.frame_mbs_only_flag && h264->poc_diff)
227 poc_diff = FFMIN(poc_diff, h264->poc_diff);
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (poc < 0) {
229 av_tree_enumerate(s->root, &poc_diff, NULL, dec_poc);
230 s->nb_frame -= poc_diff;
231 }
232 // Check if there was a POC reset (Like an IDR slice)
233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (s->nb_frame > h264->highest_poc) {
234 s->nb_frame = 0;
235 s->gop = (s->gop + 1) % s->fifo_size;
236 h264->highest_poc = h264->last_poc;
237 }
238
239 79 ret = alloc_and_insert_node(ctx, pkt->dts, pkt->duration, s->nb_frame, poc_diff, s->gop);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0)
241 return ret;
242 79 av_log(ctx, AV_LOG_DEBUG, "Queueing frame with POC %d, GOP %d, dts %"PRId64"\n",
243 poc, s->gop, pkt->dts);
244 79 s->nb_frame += poc_diff;
245
246 // Add frame to output FIFO only once
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (*queued)
248 return 0;
249
250 79 frame = (DTS2PTSFrame) { pkt, poc, poc_diff, s->gop };
251 79 ret = av_fifo_write(s->fifo, &frame, 1);
252 av_assert2(ret >= 0);
253 79 s->nb_pending += poc_diff;
254 79 *queued = 1;
255
256 79 return 0;
257 }
258
259 159 static int h264_filter(AVBSFContext *ctx)
260 {
261 159 DTS2PTSContext *s = ctx->priv_data;
262 159 DTS2PTSH264Context *h264 = &s->u.h264;
263 159 CodedBitstreamFragment *au = &s->au;
264 AVPacket *in;
265 159 int output_picture_number = INT_MIN;
266 int field_poc[2];
267 159 int queued = 0, ret;
268
269 159 ret = ff_bsf_get_packet(ctx, &in);
270
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 79 times.
159 if (ret < 0)
271 80 return ret;
272
273 79 ret = ff_cbs_read_packet(s->cbc, au, in);
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0) {
275 av_log(ctx, AV_LOG_WARNING, "Failed to parse access unit.\n");
276 goto fail;
277 }
278
279
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 79 times.
161 for (int i = 0; i < au->nb_units; i++) {
280 82 CodedBitstreamUnit *unit = &au->units[i];
281
282
3/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 3 times.
82 switch (unit->type) {
283 1 case H264_NAL_IDR_SLICE:
284 1 h264->poc.prev_frame_num = 0;
285 1 h264->poc.prev_frame_num_offset = 0;
286 1 h264->poc.prev_poc_msb =
287 1 h264->poc.prev_poc_lsb = 0;
288 av_fallthrough;
289 79 case H264_NAL_SLICE: {
290 79 const H264RawSlice *slice = unit->content;
291 79 const H264RawSliceHeader *header = &slice->header;
292 79 const CodedBitstreamH264Context *cbs_h264 = s->cbc->priv_data;
293 79 const H264RawSPS *sps = cbs_h264->active_sps;
294 int got_reset;
295
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!sps) {
297 av_log(ctx, AV_LOG_ERROR, "No active SPS for a slice\n");
298 ret = AVERROR_INVALIDDATA;
299 goto fail;
300 }
301 // Initialize the SPS struct with the fields ff_h264_init_poc() cares about
302 79 h264->sps.frame_mbs_only_flag = sps->frame_mbs_only_flag;
303 79 h264->sps.log2_max_frame_num = sps->log2_max_frame_num_minus4 + 4;
304 79 h264->sps.poc_type = sps->pic_order_cnt_type;
305 79 h264->sps.log2_max_poc_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
306 79 h264->sps.offset_for_non_ref_pic = sps->offset_for_non_ref_pic;
307 79 h264->sps.offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field;
308 79 h264->sps.poc_cycle_length = sps->num_ref_frames_in_pic_order_cnt_cycle;
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 for (int j = 0; j < h264->sps.poc_cycle_length; j++)
310 h264->sps.offset_for_ref_frame[j] = sps->offset_for_ref_frame[j];
311
312
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
158 h264->picture_structure = sps->frame_mbs_only_flag ? 3 :
313 79 (header->field_pic_flag ?
314
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 21 times.
79 header->field_pic_flag + header->bottom_field_flag : 3);
315
316 79 h264->poc.frame_num = header->frame_num;
317 79 h264->poc.poc_lsb = header->pic_order_cnt_lsb;
318 79 h264->poc.delta_poc_bottom = header->delta_pic_order_cnt_bottom;
319 79 h264->poc.delta_poc[0] = header->delta_pic_order_cnt[0];
320 79 h264->poc.delta_poc[1] = header->delta_pic_order_cnt[1];
321
322 79 field_poc[0] = field_poc[1] = INT_MAX;
323 79 ret = ff_h264_init_poc(field_poc, &output_picture_number, &h264->sps,
324 &h264->poc, h264->picture_structure,
325 79 header->nal_unit_header.nal_ref_idc);
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0) {
327 av_log(ctx, AV_LOG_ERROR, "ff_h264_init_poc() failure\n");
328 goto fail;
329 }
330
331 79 got_reset = get_mmco_reset(header);
332
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 h264->poc.prev_frame_num = got_reset ? 0 : h264->poc.frame_num;
333
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 h264->poc.prev_frame_num_offset = got_reset ? 0 : h264->poc.frame_num_offset;
334
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 51 times.
79 if (header->nal_unit_header.nal_ref_idc != 0) {
335
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 h264->poc.prev_poc_msb = got_reset ? 0 : h264->poc.poc_msb;
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (got_reset)
337 h264->poc.prev_poc_lsb = h264->picture_structure == 2 ? 0 : field_poc[0];
338 else
339 28 h264->poc.prev_poc_lsb = h264->poc.poc_lsb;
340 }
341
342
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 if (output_picture_number != h264->last_poc) {
343
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1 times.
79 if (h264->last_poc != INT_MIN) {
344 78 int64_t diff = FFABS(h264->last_poc - (int64_t)output_picture_number);
345
346
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
78 if ((output_picture_number < 0) && !h264->last_poc)
347 h264->poc_diff = 0;
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 else if (FFABS((int64_t)output_picture_number) < h264->poc_diff) {
349 diff = FFABS(output_picture_number);
350 h264->poc_diff = 0;
351 }
352
5/6
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
78 if ((!h264->poc_diff || (h264->poc_diff > diff)) && diff <= INT_MAX) {
353 2 h264->poc_diff = diff;
354
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 if (h264->poc_diff == 1 && h264->sps.frame_mbs_only_flag) {
355 av_tree_enumerate(s->root, &h264->poc_diff, NULL, dec_poc);
356 s->nb_frame -= 2;
357 }
358 }
359 }
360 79 h264->last_poc = output_picture_number;
361 79 h264->highest_poc = FFMAX(h264->highest_poc, output_picture_number);
362
363 79 ret = h264_queue_frame(ctx, in, output_picture_number, &queued);
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0)
365 goto fail;
366 }
367 79 break;
368 }
369 3 default:
370 3 break;
371 }
372 }
373
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (output_picture_number == INT_MIN) {
375 av_log(ctx, AV_LOG_ERROR, "No slices in access unit\n");
376 ret = AVERROR_INVALIDDATA;
377 goto fail;
378 }
379
380 79 ret = 0;
381 79 fail:
382 79 ff_cbs_fragment_reset(au);
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!queued)
384 av_packet_free(&in);
385
386 79 return ret;
387 }
388
389 1 static void h264_flush(AVBSFContext *ctx)
390 {
391 1 DTS2PTSContext *s = ctx->priv_data;
392 1 DTS2PTSH264Context *h264 = &s->u.h264;
393
394 1 memset(&h264->sps, 0, sizeof(h264->sps));
395 1 memset(&h264->poc, 0, sizeof(h264->poc));
396 1 s->nb_frame = -(ctx->par_in->video_delay << 1);
397 1 h264->last_poc = h264->highest_poc = INT_MIN;
398 1 }
399
400 6 static int hevc_init(AVBSFContext *ctx)
401 {
402 6 DTS2PTSContext *s = ctx->priv_data;
403 6 DTS2PTSHEVCContext *hevc = &s->u.hevc;
404
405 6 hevc->gop = -1;
406 6 hevc->poc_tid0 = 0;
407 6 hevc->highest_poc = INT_MIN;
408 6 s->nb_frame = -ctx->par_in->video_delay;
409
410 6 return 0;
411 }
412
413 3 static void hevc_flush(AVBSFContext *ctx)
414 {
415 3 hevc_init(ctx);
416 3 }
417
418 1 static int hevc_init_nb_frame(AVBSFContext *ctx, int poc)
419 {
420 1 DTS2PTSContext *s = ctx->priv_data;
421 1 const CodedBitstreamH265Context *cbs_hevc = s->cbc->priv_data;
422 1 const H265RawVPS *vps = cbs_hevc->active_vps;
423
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!vps)
425 return AVERROR_INVALIDDATA;
426
427 1 int latency = vps->vps_max_num_reorder_pics[0];
428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (vps->vps_max_latency_increase_plus1[0])
429 latency += vps->vps_max_latency_increase_plus1[0] - 1;
430
431 1 s->nb_frame = poc - latency;
432 1 av_log(ctx, AV_LOG_DEBUG, "Latency %d, poc %d, nb_frame %d\n",
433 latency, poc, s->nb_frame);
434
435 1 return 0;
436 }
437
438 typedef struct DTS2PTSCollect {
439 int gop;
440 DTS2PTSNode *head, *tail;
441 } DTS2PTSCollect;
442
443 65 static int collect_same_gop(void *opaque, void *elem)
444 {
445 65 DTS2PTSCollect *c = opaque;
446 65 DTS2PTSNode *node = elem;
447
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 59 times.
65 if (node->gop == c->gop) {
448
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (c->tail)
449 3 c->tail->next = node;
450 else
451 3 c->head = node;
452 6 c->tail = node;
453 6 node->next = NULL;
454 }
455 65 return 0;
456 }
457
458 223 static int hevc_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, bool *queued)
459 {
460 223 DTS2PTSContext *s = ctx->priv_data;
461 223 DTS2PTSHEVCContext *hevc = &s->u.hevc;
462 int ret;
463
464
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 222 times.
223 if (hevc->gop == -1) {
465 1 ret = hevc_init_nb_frame(ctx, poc);
466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
467 return ret;
468 1 hevc->gop = s->gop;
469 }
470
471 223 hevc->highest_poc = FFMAX(hevc->highest_poc, poc);
472
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 221 times.
223 if (s->nb_frame > hevc->highest_poc) {
473 2 s->nb_frame = 0;
474 2 s->gop = (s->gop + 1) % s->fifo_size;
475 2 hevc->highest_poc = poc;
476 }
477
478
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 6 times.
223 if (poc < s->nb_frame && hevc->gop == s->gop) {
479 5 int dec = s->nb_frame - poc;
480 5 DTS2PTSCollect c = { s->gop, NULL, NULL };
481
482 5 s->nb_frame -= dec;
483
484 // Crafted streams can exceed any DPB-based estimate of the node count,
485 // so chain the matching nodes through their next pointers instead of
486 // collecting them into a fixed size array. The chain is in ascending
487 // poc order; processing it in this order keeps the new keys collision
488 // free as any potential collision partner is re-keyed first.
489 5 av_tree_enumerate(s->root, &c, NULL, collect_same_gop);
490
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 while (c.head) {
491 6 struct AVTreeNode *tnode = NULL;
492 6 DTS2PTSNode *node = c.head, *r;
493 6 c.head = node->next;
494 6 av_tree_insert(&s->root, node, cmp_insert, &tnode);
495 6 node->poc -= dec;
496 6 r = av_tree_insert(&s->root, node, cmp_insert, &tnode);
497
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6 if (r && r != node) {
498 *r = *node;
499 av_refstruct_unref(&node);
500 av_free(tnode);
501 s->nb_nodes--;
502 }
503 }
504 }
505
506 223 ret = alloc_and_insert_node(ctx, pkt->dts, pkt->duration, s->nb_frame, 1, s->gop);
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (ret < 0)
508 return ret;
509
510 223 av_log(ctx, AV_LOG_DEBUG, "Queueing frame with POC %d, GOP %d, nb_frame %d, dts %"PRId64"\n",
511 poc, s->gop, s->nb_frame, pkt->dts);
512 223 s->nb_frame++;
513
514 223 DTS2PTSFrame frame = {
515 .pkt = pkt,
516 .poc = poc,
517 .poc_diff = 1,
518 223 .gop = s->gop,
519 };
520 223 ret = av_fifo_write(s->fifo, &frame, 1);
521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (ret < 0)
522 return ret;
523 223 s->nb_pending += frame.poc_diff;
524
525 223 *queued = true;
526
527 223 return 0;
528 }
529
530 449 static int hevc_filter(AVBSFContext *ctx)
531 {
532 449 DTS2PTSContext *s = ctx->priv_data;
533 449 DTS2PTSHEVCContext *hevc = &s->u.hevc;
534 449 CodedBitstreamFragment *au = &s->au;
535 AVPacket *in;
536 449 bool queued = 0;
537 449 int ret = ff_bsf_get_packet(ctx, &in);
538
2/2
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 223 times.
449 if (ret < 0)
539 226 return ret;
540
541 223 ret = ff_cbs_read_packet(s->cbc, au, in);
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (ret < 0) {
543 av_log(ctx, AV_LOG_WARNING, "Failed to parse access unit.\n");
544 goto fail;
545 }
546
547
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 for (int i = 0; i < au->nb_units; i++) {
548 361 CodedBitstreamUnit *unit = &au->units[i];
549 361 CodedBitstreamUnitType type = unit->type;
550
551
5/6
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 147 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 138 times.
361 bool is_slice = type <= HEVC_NAL_RASL_R || (type >= HEVC_NAL_BLA_W_LP &&
552 type <= HEVC_NAL_CRA_NUT);
553
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 223 times.
361 if (!is_slice)
554 138 continue;
555
556 223 const H265RawSliceHeader *slice = unit->content;
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (!slice->first_slice_segment_in_pic_flag)
558 continue;
559
560 223 const CodedBitstreamH265Context *cbs_hevc = s->cbc->priv_data;
561 223 const H265RawSPS *sps = cbs_hevc->active_sps;
562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (!sps) {
563 av_log(ctx, AV_LOG_ERROR, "No active SPS for a slice\n");
564 ret = AVERROR_INVALIDDATA;
565 goto fail;
566 }
567
568 int poc;
569
3/4
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
223 if (type == HEVC_NAL_IDR_W_RADL || type == HEVC_NAL_IDR_N_LP) {
570 4 poc = 0;
571 4 hevc->gop = (hevc->gop + 1) % s->fifo_size;
572 } else {
573 219 unsigned log2_max_poc_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
574 219 int poc_lsb = slice->slice_pic_order_cnt_lsb;
575
576 219 poc = ff_hevc_compute_poc2(log2_max_poc_lsb, hevc->poc_tid0, poc_lsb, type);
577 }
578
579
3/4
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
✓ Branch 3 taken 83 times.
223 if (slice->nal_unit_header.nuh_temporal_id_plus1 == 1 &&
580
2/4
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
140 type != HEVC_NAL_TRAIL_N && type != HEVC_NAL_TSA_N &&
581
4/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 20 times.
140 type != HEVC_NAL_STSA_N && type != HEVC_NAL_RADL_N &&
582
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 15 times.
112 type != HEVC_NAL_RASL_N && type != HEVC_NAL_RADL_R &&
583 type != HEVC_NAL_RASL_R) {
584 91 hevc->poc_tid0 = poc;
585 }
586
587 223 ret = hevc_queue_frame(ctx, in, poc, &queued);
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (ret < 0)
589 goto fail;
590 223 break;
591 }
592
593
1/2
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
223 if (!queued) {
594 av_log(ctx, AV_LOG_ERROR, "No slices in access unit\n");
595 ret = AVERROR_INVALIDDATA;
596 }
597
598 223 fail:
599 223 ff_cbs_fragment_reset(au);
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 223 times.
223 if (!queued)
601 av_packet_free(&in);
602 223 return ret;
603 }
604
605 // Core functions
606 static const struct {
607 enum AVCodecID id;
608 int (*init)(AVBSFContext *ctx);
609 int (*filter)(AVBSFContext *ctx);
610 void (*flush)(AVBSFContext *ctx);
611 size_t fifo_size;
612 } func_tab[] = {
613 { AV_CODEC_ID_H264, h264_init, h264_filter, h264_flush, H264_MAX_DPB_FRAMES * 2 * 2 },
614 { AV_CODEC_ID_HEVC, hevc_init, hevc_filter, hevc_flush, HEVC_MAX_DPB_SIZE * 2 },
615 };
616
617 4 static int dts2pts_init(AVBSFContext *ctx)
618 {
619 4 DTS2PTSContext *s = ctx->priv_data;
620 4 CodedBitstreamFragment *au = &s->au;
621 int i, ret;
622
623
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 for (i = 0; i < FF_ARRAY_ELEMS(func_tab); i++) {
624
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (func_tab[i].id == ctx->par_in->codec_id) {
625 4 s->init = func_tab[i].init;
626 4 s->filter = func_tab[i].filter;
627 4 s->flush = func_tab[i].flush;
628 4 s->fifo_size = func_tab[i].fifo_size;
629 4 break;
630 }
631 }
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (i == FF_ARRAY_ELEMS(func_tab))
633 return AVERROR_BUG;
634
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 av_assert0(s->filter && s->fifo_size);
635
636 4 s->fifo = av_fifo_alloc2(s->fifo_size, sizeof(DTS2PTSFrame), 0);
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->fifo)
638 return AVERROR(ENOMEM);
639
640 4 s->node_pool = av_refstruct_pool_alloc(sizeof(DTS2PTSNode),
641 AV_REFSTRUCT_POOL_FLAG_NO_ZEROING);
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->node_pool)
644 return AVERROR(ENOMEM);
645
646 4 ret = ff_cbs_init(&s->cbc, ctx->par_in->codec_id, ctx);
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
648 return ret;
649
650
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (s->init) {
651 4 ret = s->init(ctx);
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
653 return ret;
654 }
655
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!ctx->par_in->extradata_size)
657 return 0;
658
659 4 ret = ff_cbs_read_extradata(s->cbc, au, ctx->par_in);
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
661 av_log(ctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
662
663 4 ff_cbs_fragment_reset(au);
664
665 4 return 0;
666 }
667
668 564 static int dts2pts_filter(AVBSFContext *ctx, AVPacket *out)
669 {
670 564 DTS2PTSContext *s = ctx->priv_data;
671 564 DTS2PTSNode *poc_node = NULL, *next[2] = { NULL, NULL };
672 DTS2PTSFrame frame;
673 int ret;
674
675 // Fill up the FIFO and POC tree
676
4/4
✓ Branch 0 taken 754 times.
✓ Branch 1 taken 116 times.
✓ Branch 3 taken 608 times.
✓ Branch 4 taken 146 times.
1434 while (!s->eof && av_fifo_can_write(s->fifo)) {
677 608 ret = s->filter(ctx);
678
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 306 times.
608 if (ret < 0) {
679
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 4 times.
306 if (ret != AVERROR_EOF)
680 302 return ret;
681 4 s->eof = 1;
682 }
683 }
684
685
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 260 times.
262 if (!av_fifo_can_read(s->fifo))
686 2 return AVERROR_EOF;
687
688 // Fetch a packet from the FIFO
689 260 ret = av_fifo_read(s->fifo, &frame, 1);
690 av_assert2(ret >= 0);
691 260 s->nb_pending -= frame.poc_diff;
692 260 av_packet_move_ref(out, frame.pkt);
693 260 av_packet_free(&frame.pkt);
694
695 // Search the timestamp for the requested POC and set PTS
696 260 poc_node = av_tree_find(s->root, &frame, cmp_find, (void **)next);
697
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 249 times.
260 if (!poc_node) {
698 11 poc_node = next[1];
699
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
11 if (!poc_node || poc_node->poc != frame.poc)
700 6 poc_node = next[0];
701 }
702
3/4
✓ Branch 0 taken 260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 256 times.
✓ Branch 3 taken 4 times.
260 if (poc_node && poc_node->poc == frame.poc) {
703 256 out->pts = poc_node->dts;
704
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 110 times.
256 if (!s->eof) {
705 // Remove the found entry from the tree
706 146 DTS2PTSFrame dup = (DTS2PTSFrame) { NULL, frame.poc + 1, frame.poc_diff, frame.gop };
707 146 int64_t dts = out->pts;
708
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 146 times.
298 for (; dup.poc_diff > 0; dup.poc++, dup.poc_diff--) {
709 152 struct AVTreeNode *node = NULL;
710
3/4
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 150 times.
152 if (!poc_node || poc_node->dts != dts)
711 2 continue;
712 // 2nd field nodes were inserted with this offset added
713
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 if (dts != AV_NOPTS_VALUE)
714 150 dts += poc_node->duration / frame.poc_diff;
715 150 av_tree_insert(&s->root, poc_node, cmp_insert, &node);
716 150 av_refstruct_unref(&poc_node);
717 150 av_free(node);
718 150 s->nb_nodes--;
719 150 poc_node = av_tree_find(s->root, &dup, cmp_find, NULL);
720 }
721 }
722
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 } else if (s->eof && frame.poc > INT_MIN) {
723 4 DTS2PTSFrame dup = (DTS2PTSFrame) { NULL, frame.poc - 1, frame.poc_diff, frame.gop };
724 4 poc_node = av_tree_find(s->root, &dup, cmp_find, NULL);
725
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 if (poc_node && poc_node->poc == dup.poc) {
726 2 out->pts = poc_node->dts;
727
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (out->pts != AV_NOPTS_VALUE)
728 2 out->pts += poc_node->duration;
729 2 ret = alloc_and_insert_node(ctx, out->pts, out->duration,
730 frame.poc, frame.poc_diff, frame.gop);
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
732 av_packet_unref(out);
733 return ret;
734 }
735 2 av_log(ctx, AV_LOG_DEBUG, "Queueing frame for POC %d, GOP %d, dts %"PRId64", "
736 "generated from POC %d, GOP %d, dts %"PRId64", duration %"PRId64"\n",
737 frame.poc, frame.gop, out->pts,
738 2 poc_node->poc, poc_node->gop, poc_node->dts, poc_node->duration);
739 } else
740 2 av_log(ctx, AV_LOG_WARNING, "No timestamp for POC %d in tree\n", frame.poc);
741 } else
742 av_log(ctx, AV_LOG_WARNING, "No timestamp for POC %d in tree\n", frame.poc);
743
744 // The pending packets consume nb_pending nodes; frames whose lookup above
745 // missed leave nodes behind which nothing consumes anymore. Keep the
746 // leftovers of up to MAX_DAMAGED_FRAMES frames, then evict the nodes
747 // unconsumed the longest.
748 // At EOF nodes are deliberately kept to regenerate timestamps from.
749
3/4
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 146 times.
260 while (!s->eof && s->nb_nodes > s->nb_pending + 2 * MAX_DAMAGED_FRAMES) {
750 DTS2PTSNode *stale = NULL;
751 struct AVTreeNode *tnode = NULL;
752 av_tree_enumerate(s->root, &stale, NULL, find_stalest);
753 av_log(ctx, AV_LOG_WARNING, "Evicting unconsumed POC %d, GOP %d\n",
754 stale->poc, stale->gop);
755 av_tree_insert(&s->root, stale, cmp_insert, &tnode);
756 av_refstruct_unref(&stale);
757 av_free(tnode);
758 s->nb_nodes--;
759 }
760
761 260 av_log(ctx, AV_LOG_DEBUG, "Returning frame for POC %d, GOP %d, dts %"PRId64", pts %"PRId64"\n",
762 frame.poc, frame.gop, out->dts, out->pts);
763
764 260 return 0;
765 }
766
767 4 static void dts2pts_flush(AVBSFContext *ctx)
768 {
769 4 DTS2PTSContext *s = ctx->priv_data;
770 DTS2PTSFrame frame;
771
772
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (s->flush)
773 4 s->flush(ctx);
774 4 s->eof = 0;
775 4 s->gop = 0;
776
777
3/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 4 times.
46 while (s->fifo && av_fifo_read(s->fifo, &frame, 1) >= 0)
778 42 av_packet_free(&frame.pkt);
779
780 4 av_tree_enumerate(s->root, NULL, NULL, free_node);
781 4 av_tree_destroy(s->root);
782 4 s->root = NULL;
783 4 s->nb_nodes = 0;
784 4 s->nb_pending = 0;
785
786 4 ff_cbs_fragment_reset(&s->au);
787
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (s->cbc)
788 4 ff_cbs_flush(s->cbc);
789 4 }
790
791 4 static void dts2pts_close(AVBSFContext *ctx)
792 {
793 4 DTS2PTSContext *s = ctx->priv_data;
794
795 4 dts2pts_flush(ctx);
796
797 4 av_fifo_freep2(&s->fifo);
798 4 av_refstruct_pool_uninit(&s->node_pool);
799 4 ff_cbs_fragment_free(&s->au);
800 4 ff_cbs_close(&s->cbc);
801 4 }
802
803 static const enum AVCodecID dts2pts_codec_ids[] = {
804 AV_CODEC_ID_H264,
805 AV_CODEC_ID_HEVC,
806 AV_CODEC_ID_NONE,
807 };
808
809 const FFBitStreamFilter ff_dts2pts_bsf = {
810 .p.name = "dts2pts",
811 .p.codec_ids = dts2pts_codec_ids,
812 .priv_data_size = sizeof(DTS2PTSContext),
813 .init = dts2pts_init,
814 .flush = dts2pts_flush,
815 .close = dts2pts_close,
816 .filter = dts2pts_filter,
817 };
818