FFmpeg coverage


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