FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/dts2pts.c
Date: 2024-10-04 17:46:48
Exec Total Coverage
Lines: 216 286 75.5%
Functions: 13 14 92.9%
Branches: 96 173 55.5%

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 "libavutil/avassert.h"
27 #include "libavutil/fifo.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/tree.h"
30
31 #include "bsf.h"
32 #include "bsf_internal.h"
33 #include "cbs.h"
34 #include "cbs_h264.h"
35 #include "h264_parse.h"
36 #include "h264_ps.h"
37 #include "refstruct.h"
38
39 typedef struct DTS2PTSNode {
40 int64_t dts;
41 int64_t duration;
42 int poc;
43 int gop;
44 } DTS2PTSNode;
45
46 typedef struct DTS2PTSFrame {
47 AVPacket *pkt;
48 int poc;
49 int poc_diff;
50 int gop;
51 } DTS2PTSFrame;
52
53 typedef struct DTS2PTSH264Context {
54 H264POCContext poc;
55 SPS sps;
56 int poc_diff;
57 int last_poc;
58 int highest_poc;
59 int picture_structure;
60 } DTS2PTSH264Context;
61
62 typedef struct DTS2PTSContext {
63 struct AVTreeNode *root;
64 AVFifo *fifo;
65 FFRefStructPool *node_pool;
66
67 // Codec specific function pointers and constants
68 int (*init)(AVBSFContext *ctx);
69 int (*filter)(AVBSFContext *ctx);
70 void (*flush)(AVBSFContext *ctx);
71 size_t fifo_size;
72
73 CodedBitstreamContext *cbc;
74 CodedBitstreamFragment au;
75
76 union {
77 DTS2PTSH264Context h264;
78 } u;
79
80 int nb_frame;
81 int gop;
82 int eof;
83 } DTS2PTSContext;
84
85 // AVTreeNode callbacks
86 679 static int cmp_insert(const void *key, const void *node)
87 {
88 679 int ret = ((const DTS2PTSNode *)key)->poc - ((const DTS2PTSNode *)node)->poc;
89
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 657 times.
679 if (!ret)
90 22 ret = ((const DTS2PTSNode *)key)->gop - ((const DTS2PTSNode *)node)->gop;
91 679 return ret;
92 }
93
94 443 static int cmp_find(const void *key, const void *node)
95 {
96 443 const DTS2PTSFrame * key1 = key;
97 443 const DTS2PTSNode *node1 = node;
98 443 int ret = FFDIFFSIGN(key1->poc, node1->poc);
99
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 379 times.
443 if (!ret)
100 64 ret = key1->gop - node1->gop;
101 443 return ret;
102 }
103
104 static int dec_poc(void *opaque, void *elem)
105 {
106 DTS2PTSNode *node = elem;
107 int dec = *(int *)opaque;
108 node->poc -= dec;
109 return 0;
110 }
111
112 84 static int free_node(void *opaque, void *elem)
113 {
114 84 DTS2PTSNode *node = elem;
115 84 ff_refstruct_unref(&node);
116 84 return 0;
117 }
118
119 // Shared functions
120 79 static int alloc_and_insert_node(AVBSFContext *ctx, int64_t ts, int64_t duration,
121 int poc, int poc_diff, int gop)
122 {
123 79 DTS2PTSContext *s = ctx->priv_data;
124
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 79 times.
179 for (int i = 0; i < poc_diff; i++) {
125 100 struct AVTreeNode *node = av_tree_node_alloc();
126 DTS2PTSNode *poc_node, *ret;
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!node)
128 return AVERROR(ENOMEM);
129 100 poc_node = ff_refstruct_pool_get(s->node_pool);
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (!poc_node) {
131 av_free(node);
132 return AVERROR(ENOMEM);
133 }
134
3/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
100 if (i && ts != AV_NOPTS_VALUE)
135 21 ts += duration / poc_diff;
136 100 *poc_node = (DTS2PTSNode) { ts, duration, poc++, gop };
137 100 ret = av_tree_insert(&s->root, poc_node, cmp_insert, &node);
138
3/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
100 if (ret && ret != poc_node) {
139 *ret = *poc_node;
140 ff_refstruct_unref(&poc_node);
141 av_free(node);
142 }
143 }
144 79 return 0;
145 }
146
147 // H.264
148 static const CodedBitstreamUnitType h264_decompose_unit_types[] = {
149 H264_NAL_SPS,
150 H264_NAL_PPS,
151 H264_NAL_IDR_SLICE,
152 H264_NAL_SLICE,
153 };
154
155 1 static int h264_init(AVBSFContext *ctx)
156 {
157 1 DTS2PTSContext *s = ctx->priv_data;
158 1 DTS2PTSH264Context *h264 = &s->u.h264;
159
160 1 s->cbc->decompose_unit_types = h264_decompose_unit_types;
161 1 s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(h264_decompose_unit_types);
162
163 1 s->nb_frame = -(ctx->par_in->video_delay << 1);
164 1 h264->last_poc = h264->highest_poc = INT_MIN;
165
166 1 return 0;
167 }
168
169 79 static int get_mmco_reset(const H264RawSliceHeader *header)
170 {
171
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 51 times.
79 if (header->nal_unit_header.nal_ref_idc == 0 ||
172
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 !header->adaptive_ref_pic_marking_mode_flag)
173 79 return 0;
174
175 for (int i = 0; i < H264_MAX_MMCO_COUNT; i++) {
176 if (header->mmco[i].memory_management_control_operation == 0)
177 return 0;
178 else if (header->mmco[i].memory_management_control_operation == 5)
179 return 1;
180 }
181
182 return 0;
183 }
184
185 79 static int h264_queue_frame(AVBSFContext *ctx, AVPacket *pkt, int poc, int *queued)
186 {
187 79 DTS2PTSContext *s = ctx->priv_data;
188 79 DTS2PTSH264Context *h264 = &s->u.h264;
189 DTS2PTSFrame frame;
190 int poc_diff, ret;
191
192
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 58 times.
79 poc_diff = (h264->picture_structure == 3) + 1;
193
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)
194 poc_diff = FFMIN(poc_diff, h264->poc_diff);
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (poc < 0) {
196 av_tree_enumerate(s->root, &poc_diff, NULL, dec_poc);
197 s->nb_frame -= poc_diff;
198 }
199 // Check if there was a POC reset (Like an IDR slice)
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (s->nb_frame > h264->highest_poc) {
201 s->nb_frame = 0;
202 s->gop = (s->gop + 1) % s->fifo_size;
203 h264->highest_poc = h264->last_poc;
204 }
205
206 79 ret = alloc_and_insert_node(ctx, pkt->dts, pkt->duration, s->nb_frame, poc_diff, s->gop);
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0)
208 return ret;
209 79 av_log(ctx, AV_LOG_DEBUG, "Queueing frame with POC %d, GOP %d, dts %"PRId64"\n",
210 poc, s->gop, pkt->dts);
211 79 s->nb_frame += poc_diff;
212
213 // Add frame to output FIFO only once
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (*queued)
215 return 0;
216
217 79 frame = (DTS2PTSFrame) { pkt, poc, poc_diff, s->gop };
218 79 ret = av_fifo_write(s->fifo, &frame, 1);
219 av_assert2(ret >= 0);
220 79 *queued = 1;
221
222 79 return 0;
223 }
224
225 159 static int h264_filter(AVBSFContext *ctx)
226 {
227 159 DTS2PTSContext *s = ctx->priv_data;
228 159 DTS2PTSH264Context *h264 = &s->u.h264;
229 159 CodedBitstreamFragment *au = &s->au;
230 AVPacket *in;
231 159 int output_picture_number = INT_MIN;
232 int field_poc[2];
233 159 int queued = 0, ret;
234
235 159 ret = ff_bsf_get_packet(ctx, &in);
236
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 79 times.
159 if (ret < 0)
237 80 return ret;
238
239 79 ret = ff_cbs_read_packet(s->cbc, au, in);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0) {
241 av_log(ctx, AV_LOG_WARNING, "Failed to parse access unit.\n");
242 goto fail;
243 }
244
245
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 79 times.
161 for (int i = 0; i < au->nb_units; i++) {
246 82 CodedBitstreamUnit *unit = &au->units[i];
247
248
3/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 3 times.
82 switch (unit->type) {
249 1 case H264_NAL_IDR_SLICE:
250 1 h264->poc.prev_frame_num = 0;
251 1 h264->poc.prev_frame_num_offset = 0;
252 1 h264->poc.prev_poc_msb =
253 1 h264->poc.prev_poc_lsb = 0;
254 // fall-through
255 79 case H264_NAL_SLICE: {
256 79 const H264RawSlice *slice = unit->content;
257 79 const H264RawSliceHeader *header = &slice->header;
258 79 const CodedBitstreamH264Context *cbs_h264 = s->cbc->priv_data;
259 79 const H264RawSPS *sps = cbs_h264->active_sps;
260 int got_reset;
261
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!sps) {
263 av_log(ctx, AV_LOG_ERROR, "No active SPS for a slice\n");
264 goto fail;
265 }
266 // Initialize the SPS struct with the fields ff_h264_init_poc() cares about
267 79 h264->sps.frame_mbs_only_flag = sps->frame_mbs_only_flag;
268 79 h264->sps.log2_max_frame_num = sps->log2_max_frame_num_minus4 + 4;
269 79 h264->sps.poc_type = sps->pic_order_cnt_type;
270 79 h264->sps.log2_max_poc_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
271 79 h264->sps.offset_for_non_ref_pic = sps->offset_for_non_ref_pic;
272 79 h264->sps.offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field;
273 79 h264->sps.poc_cycle_length = sps->num_ref_frames_in_pic_order_cnt_cycle;
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 for (int j = 0; j < h264->sps.poc_cycle_length; j++)
275 h264->sps.offset_for_ref_frame[j] = sps->offset_for_ref_frame[j];
276
277
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
158 h264->picture_structure = sps->frame_mbs_only_flag ? 3 :
278 79 (header->field_pic_flag ?
279
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 21 times.
79 header->field_pic_flag + header->bottom_field_flag : 3);
280
281 79 h264->poc.frame_num = header->frame_num;
282 79 h264->poc.poc_lsb = header->pic_order_cnt_lsb;
283 79 h264->poc.delta_poc_bottom = header->delta_pic_order_cnt_bottom;
284 79 h264->poc.delta_poc[0] = header->delta_pic_order_cnt[0];
285 79 h264->poc.delta_poc[1] = header->delta_pic_order_cnt[1];
286
287 79 field_poc[0] = field_poc[1] = INT_MAX;
288 79 ret = ff_h264_init_poc(field_poc, &output_picture_number, &h264->sps,
289 &h264->poc, h264->picture_structure,
290 79 header->nal_unit_header.nal_ref_idc);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0) {
292 av_log(ctx, AV_LOG_ERROR, "ff_h264_init_poc() failure\n");
293 goto fail;
294 }
295
296 79 got_reset = get_mmco_reset(header);
297
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 h264->poc.prev_frame_num = got_reset ? 0 : h264->poc.frame_num;
298
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;
299
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 51 times.
79 if (header->nal_unit_header.nal_ref_idc != 0) {
300
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 h264->poc.prev_poc_msb = got_reset ? 0 : h264->poc.poc_msb;
301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (got_reset)
302 h264->poc.prev_poc_lsb = h264->picture_structure == 2 ? 0 : field_poc[0];
303 else
304 28 h264->poc.prev_poc_lsb = h264->poc.poc_lsb;
305 }
306
307
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 if (output_picture_number != h264->last_poc) {
308
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1 times.
79 if (h264->last_poc != INT_MIN) {
309 78 int64_t diff = FFABS(h264->last_poc - (int64_t)output_picture_number);
310
311
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)
312 h264->poc_diff = 0;
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 else if (FFABS((int64_t)output_picture_number) < h264->poc_diff) {
314 diff = FFABS(output_picture_number);
315 h264->poc_diff = 0;
316 }
317
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) {
318 2 h264->poc_diff = diff;
319
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) {
320 av_tree_enumerate(s->root, &h264->poc_diff, NULL, dec_poc);
321 s->nb_frame -= 2;
322 }
323 }
324 }
325 79 h264->last_poc = output_picture_number;
326 79 h264->highest_poc = FFMAX(h264->highest_poc, output_picture_number);
327
328 79 ret = h264_queue_frame(ctx, in, output_picture_number, &queued);
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0)
330 goto fail;
331 }
332 79 break;
333 }
334 3 default:
335 3 break;
336 }
337 }
338
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (output_picture_number == INT_MIN) {
340 av_log(ctx, AV_LOG_ERROR, "No slices in access unit\n");
341 ret = AVERROR_INVALIDDATA;
342 goto fail;
343 }
344
345 79 ret = 0;
346 79 fail:
347 79 ff_cbs_fragment_reset(au);
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!queued)
349 av_packet_free(&in);
350
351 79 return ret;
352 }
353
354 1 static void h264_flush(AVBSFContext *ctx)
355 {
356 1 DTS2PTSContext *s = ctx->priv_data;
357 1 DTS2PTSH264Context *h264 = &s->u.h264;
358
359 1 memset(&h264->sps, 0, sizeof(h264->sps));
360 1 memset(&h264->poc, 0, sizeof(h264->poc));
361 1 s->nb_frame = -(ctx->par_in->video_delay << 1);
362 1 h264->last_poc = h264->highest_poc = INT_MIN;
363 1 }
364
365 // Core functions
366 static const struct {
367 enum AVCodecID id;
368 int (*init)(AVBSFContext *ctx);
369 int (*filter)(AVBSFContext *ctx);
370 void (*flush)(AVBSFContext *ctx);
371 size_t fifo_size;
372 } func_tab[] = {
373 { AV_CODEC_ID_H264, h264_init, h264_filter, h264_flush, H264_MAX_DPB_FRAMES * 2 * 2 },
374 };
375
376 1 static int dts2pts_init(AVBSFContext *ctx)
377 {
378 1 DTS2PTSContext *s = ctx->priv_data;
379 1 CodedBitstreamFragment *au = &s->au;
380 int i, ret;
381
382
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 for (i = 0; i < FF_ARRAY_ELEMS(func_tab); i++) {
383
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (func_tab[i].id == ctx->par_in->codec_id) {
384 1 s->init = func_tab[i].init;
385 1 s->filter = func_tab[i].filter;
386 1 s->flush = func_tab[i].flush;
387 1 s->fifo_size = func_tab[i].fifo_size;
388 1 break;
389 }
390 }
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (i == FF_ARRAY_ELEMS(func_tab))
392 return AVERROR_BUG;
393
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 av_assert0(s->filter && s->fifo_size);
394
395 1 s->fifo = av_fifo_alloc2(s->fifo_size, sizeof(DTS2PTSFrame), 0);
396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!s->fifo)
397 return AVERROR(ENOMEM);
398
399 1 s->node_pool = ff_refstruct_pool_alloc(sizeof(DTS2PTSNode),
400 FF_REFSTRUCT_POOL_FLAG_NO_ZEROING);
401
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!s->node_pool)
403 return AVERROR(ENOMEM);
404
405 1 ret = ff_cbs_init(&s->cbc, ctx->par_in->codec_id, ctx);
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
407 return ret;
408
409
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s->init) {
410 1 ret = s->init(ctx);
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
412 return ret;
413 }
414
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ctx->par_in->extradata_size)
416 return 0;
417
418 1 ret = ff_cbs_read_extradata(s->cbc, au, ctx->par_in);
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
420 av_log(ctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
421
422 1 ff_cbs_fragment_reset(au);
423
424 1 return 0;
425 }
426
427 129 static int dts2pts_filter(AVBSFContext *ctx, AVPacket *out)
428 {
429 129 DTS2PTSContext *s = ctx->priv_data;
430 129 DTS2PTSNode *poc_node = NULL, *next[2] = { NULL, NULL };
431 DTS2PTSFrame frame;
432 int ret;
433
434 // Fill up the FIFO and POC tree
435
4/4
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 34 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 16 times.
338 while (!s->eof && av_fifo_can_write(s->fifo)) {
436 159 ret = s->filter(ctx);
437
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 80 times.
159 if (ret < 0) {
438
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 1 times.
80 if (ret != AVERROR_EOF)
439 79 return ret;
440 1 s->eof = 1;
441 }
442 }
443
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 if (!av_fifo_can_read(s->fifo))
445 return AVERROR_EOF;
446
447 // Fetch a packet from the FIFO
448 50 ret = av_fifo_read(s->fifo, &frame, 1);
449 av_assert2(ret >= 0);
450 50 av_packet_move_ref(out, frame.pkt);
451 50 av_packet_free(&frame.pkt);
452
453 // Search the timestamp for the requested POC and set PTS
454 50 poc_node = av_tree_find(s->root, &frame, cmp_find, (void **)next);
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!poc_node) {
456 poc_node = next[1];
457 if (!poc_node || poc_node->poc != frame.poc)
458 poc_node = next[0];
459 }
460
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
50 if (poc_node && poc_node->poc == frame.poc) {
461 50 out->pts = poc_node->dts;
462
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 34 times.
50 if (!s->eof) {
463 // Remove the found entry from the tree
464 16 DTS2PTSFrame dup = (DTS2PTSFrame) { NULL, frame.poc + 1, frame.poc_diff, frame.gop };
465
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 16 times.
38 for (; dup.poc_diff > 0; dup.poc++, dup.poc_diff--) {
466 22 struct AVTreeNode *node = NULL;
467
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 16 times.
22 if (!poc_node || poc_node->dts != out->pts)
468 6 continue;
469 16 av_tree_insert(&s->root, poc_node, cmp_insert, &node);
470 16 ff_refstruct_unref(&poc_node);
471 16 av_free(node);
472 16 poc_node = av_tree_find(s->root, &dup, cmp_find, NULL);
473 }
474 }
475 } else if (s->eof && frame.poc > INT_MIN) {
476 DTS2PTSFrame dup = (DTS2PTSFrame) { NULL, frame.poc - 1, frame.poc_diff, frame.gop };
477 poc_node = av_tree_find(s->root, &dup, cmp_find, NULL);
478 if (poc_node && poc_node->poc == dup.poc) {
479 out->pts = poc_node->dts;
480 if (out->pts != AV_NOPTS_VALUE)
481 out->pts += poc_node->duration;
482 ret = alloc_and_insert_node(ctx, out->pts, out->duration,
483 frame.poc, frame.poc_diff, frame.gop);
484 if (ret < 0) {
485 av_packet_unref(out);
486 return ret;
487 }
488 if (!ret)
489 av_log(ctx, AV_LOG_DEBUG, "Queueing frame for POC %d, GOP %d, dts %"PRId64", "
490 "generated from POC %d, GOP %d, dts %"PRId64", duration %"PRId64"\n",
491 frame.poc, frame.gop, out->pts,
492 poc_node->poc, poc_node->gop, poc_node->dts, poc_node->duration);
493 } else
494 av_log(ctx, AV_LOG_WARNING, "No timestamp for POC %d in tree\n", frame.poc);
495 } else
496 av_log(ctx, AV_LOG_WARNING, "No timestamp for POC %d in tree\n", frame.poc);
497 50 av_log(ctx, AV_LOG_DEBUG, "Returning frame for POC %d, GOP %d, dts %"PRId64", pts %"PRId64"\n",
498 frame.poc, frame.gop, out->dts, out->pts);
499
500 50 return 0;
501 }
502
503 1 static void dts2pts_flush(AVBSFContext *ctx)
504 {
505 1 DTS2PTSContext *s = ctx->priv_data;
506 DTS2PTSFrame frame;
507
508
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s->flush)
509 1 s->flush(ctx);
510 1 s->eof = 0;
511 1 s->gop = 0;
512
513
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 29 times.
✓ Branch 4 taken 1 times.
30 while (s->fifo && av_fifo_read(s->fifo, &frame, 1) >= 0)
514 29 av_packet_free(&frame.pkt);
515
516 1 av_tree_enumerate(s->root, NULL, NULL, free_node);
517 1 av_tree_destroy(s->root);
518 1 s->root = NULL;
519
520 1 ff_cbs_fragment_reset(&s->au);
521
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s->cbc)
522 1 ff_cbs_flush(s->cbc);
523 1 }
524
525 1 static void dts2pts_close(AVBSFContext *ctx)
526 {
527 1 DTS2PTSContext *s = ctx->priv_data;
528
529 1 dts2pts_flush(ctx);
530
531 1 av_fifo_freep2(&s->fifo);
532 1 ff_refstruct_pool_uninit(&s->node_pool);
533 1 ff_cbs_fragment_free(&s->au);
534 1 ff_cbs_close(&s->cbc);
535 1 }
536
537 static const enum AVCodecID dts2pts_codec_ids[] = {
538 AV_CODEC_ID_H264,
539 AV_CODEC_ID_NONE,
540 };
541
542 const FFBitStreamFilter ff_dts2pts_bsf = {
543 .p.name = "dts2pts",
544 .p.codec_ids = dts2pts_codec_ids,
545 .priv_data_size = sizeof(DTS2PTSContext),
546 .init = dts2pts_init,
547 .flush = dts2pts_flush,
548 .close = dts2pts_close,
549 .filter = dts2pts_filter,
550 };
551