FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/dts2pts.c
Date: 2026-05-16 01:27:51
Exec Total Coverage
Lines: 328 392 83.7%
Functions: 20 20 100.0%
Branches: 156 233 67.0%

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