FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cbs_h264.c
Date: 2026-03-13 22:30:28
Exec Total Coverage
Lines: 190 255 74.5%
Functions: 9 9 100.0%
Branches: 109 169 64.5%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "libavutil/mem.h"
20 #include "libavutil/refstruct.h"
21 #include "bytestream.h"
22 #include "cbs.h"
23 #include "cbs_internal.h"
24 #include "cbs_h2645.h"
25 #include "cbs_h264.h"
26 #include "cbs_sei.h"
27 #include "get_bits.h"
28
29 #define HEADER(name) do { \
30 ff_cbs_trace_header(ctx, name); \
31 } while (0)
32
33 #define CHECK(call) do { \
34 err = (call); \
35 if (err < 0) \
36 return err; \
37 } while (0)
38
39 #define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
40 #define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name)
41 #define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name)
42 #define FUNC_NAME2_EXPORT(rw, codec, name) ff_cbs_ ## codec ## _ ## rw ## _ ## name
43 #define FUNC_NAME1_EXPORT(rw, codec, name) FUNC_NAME2_EXPORT(rw, codec, name)
44 #define FUNC_SEI(name) FUNC_NAME1_EXPORT(READWRITE, sei, name)
45
46 #define SEI_FUNC(name, args) \
47 static int FUNC_H264(name) args; \
48 static int FUNC_H264(name ## _internal)(CodedBitstreamContext *ctx, \
49 RWContext *rw, void *cur, \
50 SEIMessageState *state) \
51 { \
52 return FUNC_H264(name)(ctx, rw, cur, state); \
53 } \
54 static int FUNC_H264(name) args
55
56 #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
57
58 #define u(width, name, range_min, range_max) \
59 xu(width, name, current->name, range_min, range_max, 0, )
60 #define flag(name) ub(1, name)
61 #define ue(name, range_min, range_max) \
62 xue(name, current->name, range_min, range_max, 0, )
63 #define i(width, name, range_min, range_max) \
64 xi(width, name, current->name, range_min, range_max, 0, )
65 #define ib(width, name) \
66 xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, )
67 #define se(name, range_min, range_max) \
68 xse(name, current->name, range_min, range_max, 0, )
69
70 #define us(width, name, range_min, range_max, subs, ...) \
71 xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
72 #define ubs(width, name, subs, ...) \
73 xu(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
74 #define flags(name, subs, ...) \
75 xu(1, name, current->name, 0, 1, subs, __VA_ARGS__)
76 #define ues(name, range_min, range_max, subs, ...) \
77 xue(name, current->name, range_min, range_max, subs, __VA_ARGS__)
78 #define is(width, name, range_min, range_max, subs, ...) \
79 xi(width, name, current->name, range_min, range_max, subs, __VA_ARGS__)
80 #define ibs(width, name, subs, ...) \
81 xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), subs, __VA_ARGS__)
82 #define ses(name, range_min, range_max, subs, ...) \
83 xse(name, current->name, range_min, range_max, subs, __VA_ARGS__)
84
85 #define fixed(width, name, value) do { \
86 av_unused uint32_t fixed_value = value; \
87 xu(width, name, fixed_value, value, value, 0, ); \
88 } while (0)
89
90
91 #define READ
92 #define READWRITE read
93 #define RWContext GetBitContext
94
95 #define ub(width, name) do { \
96 uint32_t value; \
97 CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \
98 &value)); \
99 current->name = value; \
100 } while (0)
101 #define xu(width, name, var, range_min, range_max, subs, ...) do { \
102 uint32_t value; \
103 CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
104 SUBSCRIPTS(subs, __VA_ARGS__), \
105 &value, range_min, range_max)); \
106 var = value; \
107 } while (0)
108 #define xue(name, var, range_min, range_max, subs, ...) do { \
109 uint32_t value; \
110 CHECK(ff_cbs_read_ue_golomb(ctx, rw, #name, \
111 SUBSCRIPTS(subs, __VA_ARGS__), \
112 &value, range_min, range_max)); \
113 var = value; \
114 } while (0)
115 #define xi(width, name, var, range_min, range_max, subs, ...) do { \
116 int32_t value; \
117 CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
118 SUBSCRIPTS(subs, __VA_ARGS__), \
119 &value, range_min, range_max)); \
120 var = value; \
121 } while (0)
122 #define xse(name, var, range_min, range_max, subs, ...) do { \
123 int32_t value; \
124 CHECK(ff_cbs_read_se_golomb(ctx, rw, #name, \
125 SUBSCRIPTS(subs, __VA_ARGS__), \
126 &value, range_min, range_max)); \
127 var = value; \
128 } while (0)
129
130
131 #define infer(name, value) do { \
132 current->name = value; \
133 } while (0)
134
135 #define more_rbsp_data(var) ((var) = ff_cbs_h2645_read_more_rbsp_data(rw))
136
137 #define bit_position(rw) (get_bits_count(rw))
138 #define byte_alignment(rw) (get_bits_count(rw) % 8)
139
140 #define allocate(name, size) do { \
141 name ## _ref = av_buffer_allocz(size + \
142 AV_INPUT_BUFFER_PADDING_SIZE); \
143 if (!name ## _ref) \
144 return AVERROR(ENOMEM); \
145 name = name ## _ref->data; \
146 } while (0)
147
148 #define FUNC(name) FUNC_H264(name)
149 #include "cbs_h264_syntax_template.c"
150 #undef FUNC
151
152
153 #undef READ
154 #undef READWRITE
155 #undef RWContext
156 #undef ub
157 #undef xu
158 #undef xi
159 #undef xue
160 #undef xse
161 #undef infer
162 #undef more_rbsp_data
163 #undef bit_position
164 #undef byte_alignment
165 #undef allocate
166 #undef allocate_struct
167
168
169 #define WRITE
170 #define READWRITE write
171 #define RWContext PutBitContext
172
173 #define ub(width, name) do { \
174 uint32_t value = current->name; \
175 CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \
176 value)); \
177 } while (0)
178 #define xu(width, name, var, range_min, range_max, subs, ...) do { \
179 uint32_t value = var; \
180 CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
181 SUBSCRIPTS(subs, __VA_ARGS__), \
182 value, range_min, range_max)); \
183 } while (0)
184 #define xue(name, var, range_min, range_max, subs, ...) do { \
185 uint32_t value = var; \
186 CHECK(ff_cbs_write_ue_golomb(ctx, rw, #name, \
187 SUBSCRIPTS(subs, __VA_ARGS__), \
188 value, range_min, range_max)); \
189 } while (0)
190 #define xi(width, name, var, range_min, range_max, subs, ...) do { \
191 int32_t value = var; \
192 CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
193 SUBSCRIPTS(subs, __VA_ARGS__), \
194 value, range_min, range_max)); \
195 } while (0)
196 #define xse(name, var, range_min, range_max, subs, ...) do { \
197 int32_t value = var; \
198 CHECK(ff_cbs_write_se_golomb(ctx, rw, #name, \
199 SUBSCRIPTS(subs, __VA_ARGS__), \
200 value, range_min, range_max)); \
201 } while (0)
202
203 #define infer(name, value) do { \
204 if (current->name != (value)) { \
205 av_log(ctx->log_ctx, AV_LOG_ERROR, \
206 "%s does not match inferred value: " \
207 "%"PRId64", but should be %"PRId64".\n", \
208 #name, (int64_t)current->name, (int64_t)(value)); \
209 return AVERROR_INVALIDDATA; \
210 } \
211 } while (0)
212
213 #define more_rbsp_data(var) (var)
214
215 #define bit_position(rw) (put_bits_count(rw))
216 #define byte_alignment(rw) (put_bits_count(rw) % 8)
217
218 #define allocate(name, size) do { \
219 if (!name) { \
220 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s must be set " \
221 "for writing.\n", #name); \
222 return AVERROR_INVALIDDATA; \
223 } \
224 } while (0)
225
226 #define FUNC(name) FUNC_H264(name)
227 #include "cbs_h264_syntax_template.c"
228 #undef FUNC
229
230 #undef WRITE
231 #undef READWRITE
232 #undef RWContext
233 #undef ub
234 #undef xu
235 #undef xi
236 #undef xue
237 #undef xse
238 #undef u
239 #undef i
240 #undef flag
241 #undef ue
242 #undef se
243 #undef infer
244 #undef more_rbsp_data
245 #undef bit_position
246 #undef byte_alignment
247 #undef allocate
248
249
250
251 3414 static int cbs_h264_split_fragment(CodedBitstreamContext *ctx,
252 CodedBitstreamFragment *frag,
253 int header)
254 {
255 3414 enum AVCodecID codec_id = ctx->codec->codec_id;
256 3414 CodedBitstreamH264Context *priv = ctx->priv_data;
257 3414 CodedBitstreamH2645Context *h2645 = &priv->common;
258 GetByteContext gbc;
259 int err;
260
261
2/4
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3414 times.
3414 av_assert0(frag->data && frag->nb_units == 0);
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3414 times.
3414 if (frag->data_size == 0)
263 return 0;
264
265
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 3387 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 19 times.
3422 if (header && frag->data[0]) {
266 // AVCC header.
267 size_t size, start, end;
268 int i, count, version;
269
270 8 h2645->mp4 = 1;
271
272 8 bytestream2_init(&gbc, frag->data, frag->data_size);
273
274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (bytestream2_get_bytes_left(&gbc) < 6)
275 return AVERROR_INVALIDDATA;
276
277 8 version = bytestream2_get_byte(&gbc);
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (version != 1) {
279 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: "
280 "first byte %u.\n", version);
281 return AVERROR_INVALIDDATA;
282 }
283
284 8 bytestream2_skip(&gbc, 3);
285 8 h2645->nal_length_size = (bytestream2_get_byte(&gbc) & 3) + 1;
286
287 // SPS array.
288 8 count = bytestream2_get_byte(&gbc) & 0x1f;
289 8 start = bytestream2_tell(&gbc);
290
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8 times.
15 for (i = 0; i < count; i++) {
291
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
292 return AVERROR_INVALIDDATA;
293 7 size = bytestream2_get_be16(&gbc);
294
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(&gbc) < size)
295 return AVERROR_INVALIDDATA;
296 7 bytestream2_skip(&gbc, size);
297 }
298 8 end = bytestream2_tell(&gbc);
299
300 8 err = ff_h2645_packet_split(&h2645->read_packet,
301 8 frag->data + start, end - start,
302 ctx->log_ctx, 2, AV_CODEC_ID_H264,
303 H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0) {
305 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n");
306 return err;
307 }
308 8 err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0)
310 return err;
311
312 // PPS array.
313 8 count = bytestream2_get_byte(&gbc);
314 8 start = bytestream2_tell(&gbc);
315
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8 times.
15 for (i = 0; i < count; i++) {
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(&gbc) < 2 * (count - i))
317 return AVERROR_INVALIDDATA;
318 7 size = bytestream2_get_be16(&gbc);
319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(&gbc) < size)
320 return AVERROR_INVALIDDATA;
321 7 bytestream2_skip(&gbc, size);
322 }
323 8 end = bytestream2_tell(&gbc);
324
325 8 err = ff_h2645_packet_split(&h2645->read_packet,
326 8 frag->data + start, end - start,
327 ctx->log_ctx, 2, AV_CODEC_ID_H264,
328 H2645_FLAG_IS_NALFF | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF);
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0) {
330 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n");
331 return err;
332 }
333 8 err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0)
335 return err;
336
337
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
8 if (bytestream2_get_bytes_left(&gbc) > 0) {
338 2 av_log(ctx->log_ctx, AV_LOG_WARNING, "%u bytes left at end of AVCC "
339 "header.\n", bytestream2_get_bytes_left(&gbc));
340 }
341 } else {
342
2/2
✓ Branch 0 taken 629 times.
✓ Branch 1 taken 2777 times.
3406 int flags = (H2645_FLAG_IS_NALFF * !!h2645->mp4) | H2645_FLAG_SMALL_PADDING | H2645_FLAG_USE_REF;
343 // Annex B, or later MP4 with already-known parameters.
344
345 3406 err = ff_h2645_packet_split(&h2645->read_packet,
346 3406 frag->data, frag->data_size,
347 ctx->log_ctx,
348 h2645->nal_length_size,
349 codec_id, flags);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3406 times.
3406 if (err < 0)
351 return err;
352
353 3406 err = ff_cbs_h2645_fragment_add_nals(ctx, frag, &h2645->read_packet);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3406 times.
3406 if (err < 0)
355 return err;
356 }
357
358 3414 return 0;
359 }
360
361 #define cbs_h2645_replace_ps(ps_name, ps_var, id_element) \
362 static int cbs_h264_replace_ ## ps_var(CodedBitstreamContext *ctx, \
363 CodedBitstreamUnit *unit) \
364 { \
365 CodedBitstreamH264Context *priv = ctx->priv_data; \
366 H264Raw ## ps_name *ps_var = unit->content; \
367 unsigned int id = ps_var->id_element; \
368 int err = ff_cbs_make_unit_refcounted(ctx, unit); \
369 if (err < 0) \
370 return err; \
371 if (priv->ps_var[id] == priv->active_ ## ps_var) \
372 priv->active_ ## ps_var = NULL ; \
373 av_assert0(unit->content_ref); \
374 av_refstruct_replace(&priv->ps_var[id], unit->content_ref); \
375 return 0; \
376 }
377
378
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
✓ Branch 3 taken 111 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 152 times.
152 cbs_h2645_replace_ps(SPS, sps, seq_parameter_set_id)
379
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2996 times.
✓ Branch 3 taken 2941 times.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2996 times.
2996 cbs_h2645_replace_ps(PPS, pps, pic_parameter_set_id)
380
381 9323 static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
382 CodedBitstreamUnit *unit)
383 {
384 GetBitContext gbc;
385 int err;
386
387 9323 err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9323 times.
9323 if (err < 0)
389 return err;
390
391 9323 err = ff_cbs_alloc_unit_content(ctx, unit);
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9323 times.
9323 if (err < 0)
393 return err;
394
395
7/9
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1499 times.
✓ Branch 3 taken 6056 times.
✓ Branch 4 taken 739 times.
✓ Branch 5 taken 915 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
9323 switch (unit->type) {
396 77 case H264_NAL_SPS:
397 {
398 77 H264RawSPS *sps = unit->content;
399
400 77 err = cbs_h264_read_sps(ctx, &gbc, sps);
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (err < 0)
402 return err;
403
404 77 err = cbs_h264_replace_sps(ctx, unit);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (err < 0)
406 return err;
407 }
408 77 break;
409
410 case H264_NAL_SPS_EXT:
411 {
412 err = cbs_h264_read_sps_extension(ctx, &gbc, unit->content);
413 if (err < 0)
414 return err;
415 }
416 break;
417
418 1499 case H264_NAL_PPS:
419 {
420 1499 H264RawPPS *pps = unit->content;
421
422 1499 err = cbs_h264_read_pps(ctx, &gbc, pps);
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1499 times.
1499 if (err < 0)
424 return err;
425
426 1499 err = cbs_h264_replace_pps(ctx, unit);
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1499 times.
1499 if (err < 0)
428 return err;
429 }
430 1499 break;
431
432 6056 case H264_NAL_SLICE:
433 case H264_NAL_IDR_SLICE:
434 case H264_NAL_AUXILIARY_SLICE:
435 {
436 6056 H264RawSlice *slice = unit->content;
437 int pos, len;
438
439 6056 err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header);
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6056 times.
6056 if (err < 0)
441 return err;
442
443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6056 times.
6056 if (!ff_cbs_h2645_read_more_rbsp_data(&gbc))
444 return AVERROR_INVALIDDATA;
445
446 6056 pos = get_bits_count(&gbc);
447 6056 len = unit->data_size;
448
449 6056 slice->data_size = len - pos / 8;
450 6056 slice->data_ref = av_buffer_ref(unit->data_ref);
451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6056 times.
6056 if (!slice->data_ref)
452 return AVERROR(ENOMEM);
453 6056 slice->data = unit->data + pos / 8;
454 6056 slice->data_bit_start = pos % 8;
455 }
456 6056 break;
457
458 739 case H264_NAL_AUD:
459 {
460 739 err = cbs_h264_read_aud(ctx, &gbc, unit->content);
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 739 times.
739 if (err < 0)
462 return err;
463 }
464 739 break;
465
466 915 case H264_NAL_SEI:
467 {
468 915 err = cbs_h264_read_sei(ctx, &gbc, unit->content);
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 915 times.
915 if (err < 0)
470 return err;
471 }
472 915 break;
473
474 34 case H264_NAL_FILLER_DATA:
475 {
476 34 err = cbs_h264_read_filler(ctx, &gbc, unit->content);
477
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (err < 0)
478 1 return err;
479 }
480 33 break;
481
482 3 case H264_NAL_END_SEQUENCE:
483 case H264_NAL_END_STREAM:
484 {
485 3 err = (unit->type == H264_NAL_END_SEQUENCE ?
486
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 cbs_h264_read_end_of_sequence :
487 3 cbs_h264_read_end_of_stream)(ctx, &gbc, unit->content);
488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err < 0)
489 return err;
490 }
491 3 break;
492
493 default:
494 return AVERROR(ENOSYS);
495 }
496
497 9322 return 0;
498 }
499
500 7963 static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx,
501 CodedBitstreamUnit *unit,
502 PutBitContext *pbc)
503 {
504 int err;
505
506
7/10
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1497 times.
✓ Branch 3 taken 5579 times.
✓ Branch 4 taken 302 times.
✓ Branch 5 taken 507 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
7963 switch (unit->type) {
507 75 case H264_NAL_SPS:
508 {
509 75 H264RawSPS *sps = unit->content;
510
511 75 err = cbs_h264_write_sps(ctx, pbc, sps);
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (err < 0)
513 return err;
514
515 75 err = cbs_h264_replace_sps(ctx, unit);
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (err < 0)
517 return err;
518 }
519 75 break;
520
521 case H264_NAL_SPS_EXT:
522 {
523 H264RawSPSExtension *sps_ext = unit->content;
524
525 err = cbs_h264_write_sps_extension(ctx, pbc, sps_ext);
526 if (err < 0)
527 return err;
528 }
529 break;
530
531 1497 case H264_NAL_PPS:
532 {
533 1497 H264RawPPS *pps = unit->content;
534
535 1497 err = cbs_h264_write_pps(ctx, pbc, pps);
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1497 times.
1497 if (err < 0)
537 return err;
538
539 1497 err = cbs_h264_replace_pps(ctx, unit);
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1497 times.
1497 if (err < 0)
541 return err;
542 }
543 1497 break;
544
545 5579 case H264_NAL_SLICE:
546 case H264_NAL_IDR_SLICE:
547 case H264_NAL_AUXILIARY_SLICE:
548 {
549 5579 H264RawSlice *slice = unit->content;
550
551 5579 err = cbs_h264_write_slice_header(ctx, pbc, &slice->header);
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5579 times.
5579 if (err < 0)
553 return err;
554
555
1/2
✓ Branch 0 taken 5579 times.
✗ Branch 1 not taken.
5579 if (slice->data) {
556 5579 err = ff_cbs_h2645_write_slice_data(ctx, pbc, slice->data,
557 slice->data_size,
558 slice->data_bit_start);
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5579 times.
5579 if (err < 0)
560 return err;
561 } else {
562 // No slice data - that was just the header.
563 // (Bitstream may be unaligned!)
564 }
565 }
566 5579 break;
567
568 302 case H264_NAL_AUD:
569 {
570 302 err = cbs_h264_write_aud(ctx, pbc, unit->content);
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 302 times.
302 if (err < 0)
572 return err;
573 }
574 302 break;
575
576 507 case H264_NAL_SEI:
577 {
578 507 err = cbs_h264_write_sei(ctx, pbc, unit->content);
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 507 times.
507 if (err < 0)
580 return err;
581 }
582 507 break;
583
584 case H264_NAL_FILLER_DATA:
585 {
586 err = cbs_h264_write_filler(ctx, pbc, unit->content);
587 if (err < 0)
588 return err;
589 }
590 break;
591
592 1 case H264_NAL_END_SEQUENCE:
593 {
594 1 err = cbs_h264_write_end_of_sequence(ctx, pbc, unit->content);
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
596 return err;
597 }
598 1 break;
599
600 2 case H264_NAL_END_STREAM:
601 {
602 2 err = cbs_h264_write_end_of_stream(ctx, pbc, unit->content);
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (err < 0)
604 return err;
605 }
606 2 break;
607
608 default:
609 av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
610 "NAL unit type %"PRIu32".\n", unit->type);
611 return AVERROR_PATCHWELCOME;
612 }
613
614 7963 return 0;
615 }
616
617 756 static int cbs_h264_discarded_nal_unit(CodedBitstreamContext *ctx,
618 const CodedBitstreamUnit *unit,
619 enum AVDiscard skip)
620 {
621 H264RawNALUnitHeader *header;
622 H264RawSliceHeader *slice;
623 int slice_type_i, slice_type_b, slice_type_si;
624
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 if (skip <= AVDISCARD_DEFAULT)
626 return 0;
627
628 // keep non-VCL
629
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 500 times.
756 if (unit->type != H264_NAL_SLICE &&
630
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 4 times.
256 unit->type != H264_NAL_IDR_SLICE &&
631
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 unit->type != H264_NAL_AUXILIARY_SLICE)
632 252 return 0;
633
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 if (skip >= AVDISCARD_ALL)
635 return 1;
636
637
4/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 378 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 1 times.
504 if (skip >= AVDISCARD_NONKEY && unit->type != H264_NAL_IDR_SLICE)
638 125 return 1;
639
640 379 header = (H264RawNALUnitHeader *)unit->content;
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 379 times.
379 if (!header) {
642 av_log(ctx->log_ctx, AV_LOG_WARNING,
643 "h264 nal unit header is null, missing decompose?\n");
644 return 0;
645 }
646
647
3/4
✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 196 times.
379 if (skip >= AVDISCARD_NONREF && !header->nal_ref_idc)
648 183 return 1;
649
650 196 slice = (H264RawSliceHeader *)unit->content;
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 196 times.
196 if (!slice) {
652 av_log(ctx->log_ctx, AV_LOG_WARNING,
653 "h264 slice header is null, missing decompose?\n");
654 return 0;
655 }
656
657 196 slice_type_i = slice->slice_type % 5 == 2;
658 196 slice_type_b = slice->slice_type % 5 == 1;
659 196 slice_type_si = slice->slice_type % 5 == 4;
660
661
4/4
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 71 times.
196 if (skip >= AVDISCARD_BIDIR && slice_type_b)
662 60 return 1;
663
5/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 29 times.
✗ Branch 5 not taken.
136 if (skip >= AVDISCARD_NONINTRA && !slice_type_i && !slice_type_si)
664 29 return 1;
665
666 107 return 0;
667 }
668
669 1 static av_cold void cbs_h264_flush(CodedBitstreamContext *ctx)
670 {
671 1 CodedBitstreamH264Context *h264 = ctx->priv_data;
672
673
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 for (int i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
674 32 av_refstruct_unref(&h264->sps[i]);
675
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 1 times.
257 for (int i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
676 256 av_refstruct_unref(&h264->pps[i]);
677
678 1 h264->active_sps = NULL;
679 1 h264->active_pps = NULL;
680 1 h264->last_slice_nal_unit_type = 0;
681 1 }
682
683 47 static av_cold void cbs_h264_close(CodedBitstreamContext *ctx)
684 {
685 47 CodedBitstreamH264Context *h264 = ctx->priv_data;
686 int i;
687
688 47 ff_h2645_packet_uninit(&h264->common.read_packet);
689
690
2/2
✓ Branch 0 taken 1504 times.
✓ Branch 1 taken 47 times.
1551 for (i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++)
691 1504 av_refstruct_unref(&h264->sps[i]);
692
2/2
✓ Branch 0 taken 12032 times.
✓ Branch 1 taken 47 times.
12079 for (i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++)
693 12032 av_refstruct_unref(&h264->pps[i]);
694 47 }
695
696 915 static void cbs_h264_free_sei(AVRefStructOpaque unused, void *content)
697 {
698 915 H264RawSEI *sei = content;
699 915 ff_cbs_sei_free_message_list(&sei->message_list);
700 915 }
701
702 static CodedBitstreamUnitTypeDescriptor cbs_h264_unit_types[] = {
703 CBS_UNIT_TYPE_POD(H264_NAL_SPS, H264RawSPS),
704 CBS_UNIT_TYPE_POD(H264_NAL_SPS_EXT, H264RawSPSExtension),
705
706 CBS_UNIT_TYPE_INTERNAL_REF(H264_NAL_PPS, H264RawPPS, slice_group_id),
707
708 CBS_UNIT_TYPES_INTERNAL_REF((H264_NAL_IDR_SLICE,
709 H264_NAL_SLICE,
710 H264_NAL_AUXILIARY_SLICE), H264RawSlice, data),
711
712 CBS_UNIT_TYPE_POD(H264_NAL_AUD, H264RawAUD),
713 CBS_UNIT_TYPE_POD(H264_NAL_FILLER_DATA, H264RawFiller),
714 CBS_UNIT_TYPE_POD(H264_NAL_END_SEQUENCE, H264RawNALUnitHeader),
715 CBS_UNIT_TYPE_POD(H264_NAL_END_STREAM, H264RawNALUnitHeader),
716
717 CBS_UNIT_TYPE_COMPLEX(H264_NAL_SEI, H264RawSEI, &cbs_h264_free_sei),
718
719 CBS_UNIT_TYPE_END_OF_LIST
720 };
721
722 const CodedBitstreamType ff_cbs_type_h264 = {
723 .codec_id = AV_CODEC_ID_H264,
724
725 .priv_data_size = sizeof(CodedBitstreamH264Context),
726
727 .unit_types = cbs_h264_unit_types,
728
729 .split_fragment = &cbs_h264_split_fragment,
730 .read_unit = &cbs_h264_read_nal_unit,
731 .write_unit = &cbs_h264_write_nal_unit,
732 .discarded_unit = &cbs_h264_discarded_nal_unit,
733 .assemble_fragment = &ff_cbs_h2645_assemble_fragment,
734
735 .flush = &cbs_h264_flush,
736 .close = &cbs_h264_close,
737 };
738
739 // Macro for the read/write pair.
740 #define SEI_MESSAGE_RW(codec, name) \
741 .read = cbs_ ## codec ## _read_ ## name ## _internal, \
742 .write = cbs_ ## codec ## _write_ ## name ## _internal
743
744 const SEIMessageTypeDescriptor ff_cbs_sei_h264_types[] = {
745 {
746 SEI_TYPE_BUFFERING_PERIOD,
747 1, 0,
748 sizeof(H264RawSEIBufferingPeriod),
749 SEI_MESSAGE_RW(h264, sei_buffering_period),
750 },
751 {
752 SEI_TYPE_PIC_TIMING,
753 1, 0,
754 sizeof(H264RawSEIPicTiming),
755 SEI_MESSAGE_RW(h264, sei_pic_timing),
756 },
757 {
758 SEI_TYPE_PAN_SCAN_RECT,
759 1, 0,
760 sizeof(H264RawSEIPanScanRect),
761 SEI_MESSAGE_RW(h264, sei_pan_scan_rect),
762 },
763 {
764 SEI_TYPE_RECOVERY_POINT,
765 1, 0,
766 sizeof(H264RawSEIRecoveryPoint),
767 SEI_MESSAGE_RW(h264, sei_recovery_point),
768 },
769 {
770 SEI_TYPE_FILM_GRAIN_CHARACTERISTICS,
771 1, 0,
772 sizeof(H264RawFilmGrainCharacteristics),
773 SEI_MESSAGE_RW(h264, film_grain_characteristics),
774 },
775 {
776 SEI_TYPE_FRAME_PACKING_ARRANGEMENT,
777 1, 0,
778 sizeof(H264RawSEIFramePackingArrangement),
779 SEI_MESSAGE_RW(h264, sei_frame_packing_arrangement),
780 },
781 {
782 SEI_TYPE_DISPLAY_ORIENTATION,
783 1, 0,
784 sizeof(H264RawSEIDisplayOrientation),
785 SEI_MESSAGE_RW(h264, sei_display_orientation),
786 },
787 SEI_MESSAGE_TYPE_END
788 };
789