1 /*****************************************************************************
2 * h264.h: ISO/IEC 14496-10 (video)
3 *****************************************************************************
4 * Copyright (C) 2013 VideoLAN
5 *
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject
14 * to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *****************************************************************************/
27
28 /*
29 * Normative references:
30 * - ISO/IEC 14496-10 (advanced video coding)
31 * - ISO/IEC 14496-15 (advanced video coding file format)
32 */
33
34 #ifndef __BITSTREAM_MPEG_H264_H__
35 #define __BITSTREAM_MPEG_H264_H__
36
37 #include <stdint.h> /* uint8_t, uint16_t, etc... */
38 #include <stdbool.h> /* bool */
39 #include <string.h> /* memset */
40
41 #ifdef __cplusplus
42 extern "C"
43 {
44 #endif
45
46 /*****************************************************************************
47 * H264 network abstraction layer (annex B)
48 *****************************************************************************/
49 #define H264NAL_TYPE_NONIDR 1
50 #define H264NAL_TYPE_PARTA 2
51 #define H264NAL_TYPE_PARTB 3
52 #define H264NAL_TYPE_PARTC 4
53 #define H264NAL_TYPE_IDR 5
54 #define H264NAL_TYPE_SEI 6
55 #define H264NAL_TYPE_SPS 7
56 #define H264NAL_TYPE_PPS 8
57 #define H264NAL_TYPE_AUD 9
58 #define H264NAL_TYPE_ENDSEQ 10
59 #define H264NAL_TYPE_ENDSTR 11
60 #define H264NAL_TYPE_FILLER 12
61 #define H264NAL_TYPE_SPSX 13
62 #define H264NAL_TYPE_PFX 14
63 #define H264NAL_TYPE_SSPS 15
64
h264nal_init(uint8_t * p_h264nal)65 static inline void h264nal_init(uint8_t *p_h264nal)
66 {
67 p_h264nal[0] = 0x0;
68 p_h264nal[1] = 0x0;
69 p_h264nal[2] = 0x1;
70 p_h264nal[3] = 0;
71 }
72
h264nal_set_ref(uint8_t * p_h264nal,uint8_t ref)73 static inline void h264nal_set_ref(uint8_t *p_h264nal, uint8_t ref)
74 {
75 p_h264nal[3] &= 0x1f;
76 p_h264nal[3] |= ref << 5;
77 }
78
h264nal_get_ref(const uint8_t * p_h264nal)79 static inline uint8_t h264nal_get_ref(const uint8_t *p_h264nal)
80 {
81 return (p_h264nal[3] & 0x60) >> 5;
82 }
83
h264nal_set_type(uint8_t * p_h264nal,uint8_t type)84 static inline void h264nal_set_type(uint8_t *p_h264nal, uint8_t type)
85 {
86 p_h264nal[3] &= 0xe0;
87 p_h264nal[3] |= type;
88 }
89
h264nal_get_type(const uint8_t * p_h264nal)90 static inline uint8_t h264nal_get_type(const uint8_t *p_h264nal)
91 {
92 return p_h264nal[3] & 0x1f;
93 }
94
h264nalst_init(uint8_t * p_start)95 static inline void h264nalst_init(uint8_t *p_start)
96 {
97 p_start[0] = 0;
98 }
99
h264nalst_set_ref(uint8_t * p_start,uint8_t ref)100 static inline void h264nalst_set_ref(uint8_t *p_start, uint8_t ref)
101 {
102 p_start[0] &= 0x1f;
103 p_start[0] |= ref << 5;
104 }
105
h264nalst_get_ref(uint8_t start)106 static inline uint8_t h264nalst_get_ref(uint8_t start)
107 {
108 return (start & 0x60) >> 5;
109 }
110
h264nalst_set_type(uint8_t * p_start,uint8_t type)111 static inline void h264nalst_set_type(uint8_t *p_start, uint8_t type)
112 {
113 p_start[0] &= 0xe0;
114 p_start[0] |= type;
115 }
116
h264nalst_get_type(uint8_t start)117 static inline uint8_t h264nalst_get_type(uint8_t start)
118 {
119 return start & 0x1f;
120 }
121
h264naltype_is_slice(uint8_t type)122 static inline bool h264naltype_is_slice(uint8_t type)
123 {
124 switch (type) {
125 case H264NAL_TYPE_IDR:
126 case H264NAL_TYPE_NONIDR:
127 case H264NAL_TYPE_PARTA:
128 case H264NAL_TYPE_PARTB:
129 case H264NAL_TYPE_PARTC:
130 return true;
131 default:
132 return false;
133 }
134 }
135
h264naltype_is_vcl(uint8_t type)136 static inline bool h264naltype_is_vcl(uint8_t type)
137 {
138 switch (type) {
139 case H264NAL_TYPE_IDR:
140 case H264NAL_TYPE_NONIDR:
141 case H264NAL_TYPE_PARTA:
142 case H264NAL_TYPE_PARTB:
143 case H264NAL_TYPE_PARTC:
144 case H264NAL_TYPE_SEI:
145 return true;
146 default:
147 return false;
148 }
149 }
150
151 /*****************************************************************************
152 * H264 supplemental enhancement information
153 *****************************************************************************/
154 #define H264SEI_HEADER_SIZE 4
155
156 #define H264SEI_BUFFERING_PERIOD 0
157 #define H264SEI_PIC_TIMING 1
158 #define H264SEI_PAN_SCAN_RECT 2
159 #define H264SEI_FILLER_PAYLOAD 3
160 #define H264SEI_USER_T_T35 4
161 #define H264SEI_USER_UNREGISTERED 5
162 #define H264SEI_RECOVERY_POINT 6
163 #define H264SEI_DEC_REF_PIC_MARK_R 7
164 #define H264SEI_SPARE_PIC 8
165 #define H264SEI_SCENE_INFO 9
166 #define H264SEI_SUB_SEQ_INFO 10
167 #define H264SEI_SUB_SEQ_LAYER_CHAR 11
168 #define H264SEI_SUB_SEQ_CHAR 12
169 #define H264SEI_FULL_FRAME_FREEZE 13
170 #define H264SEI_FULL_FRAME_FREEZE_R 14
171 #define H264SEI_FULL_FRAME_SNAP 15
172 #define H264SEI_PROG_REF_SEGMENT_S 16
173 #define H264SEI_PROG_REF_SEGMENT_E 17
174 #define H264SEI_MOTION_CONS_SGRP_S 18
175 #define H264SEI_FILM_GRAIN_CHAR 19
176 #define H264SEI_DEBLOCK_DIS_PREF 20
177 #define H264SEI_STEREO_VIDEO_INFO 21
178 #define H264SEI_POST_FILTER_HINT 22
179 #define H264SEI_TONE_MAPPING_INFO 23
180 #define H264SEI_SCALABILITY_INFO 24
181 #define H264SEI_SUBPIC_SCAL_LAYER 25
182 #define H264SEI_NONREQ_LAYER_REP 26
183 #define H264SEI_PRIO_LAYER_INFO 27
184 #define H264SEI_LAYERS_NOT_PRES 28
185 #define H264SEI_LAYER_DEP_CHANGE 29
186 #define H264SEI_SCALABLE_NESTING 30
187 #define H264SEI_BASE_LAYER_TEMP_HRD 31
188 #define H264SEI_QUAL_LAYER_INT_CHK 32
189 #define H264SEI_REDUND_PIC_PROP 33
190 #define H264SEI_TL0_DEP_REP 34
191 #define H264SEI_TL_SWITCHING_POINT 35
192 #define H264SEI_PARALLEL_DEC_INFO 36
193 #define H264SEI_MVC_SCAL_NESTING 37
194 #define H264SEI_VIEW_SCAL_INFO 38
195 #define H264SEI_MULTIVIEW_SCN_INFO 39
196 #define H264SEI_MULTIVIEW_ACQ_INFO 40
197 #define H264SEI_NONREQ_VIEW_COMP 41
198 #define H264SEI_VIEW_DEP_CHANGE 42
199 #define H264SEI_OP_POINTS_NOT_PRES 43
200 #define H264SEI_BASE_VIEW_TEMP_HRD 44
201 #define H264SEI_FRAME_PACK_ARRANG 45
202
203 #define H264SEI_STRUCT_FRAME 0
204 #define H264SEI_STRUCT_TOP 1
205 #define H264SEI_STRUCT_BOT 2
206 #define H264SEI_STRUCT_TOP_BOT 3
207 #define H264SEI_STRUCT_BOT_TOP 4
208 #define H264SEI_STRUCT_TOP_BOT_TOP 5
209 #define H264SEI_STRUCT_BOT_TOP_BOT 6
210 #define H264SEI_STRUCT_DOUBLE 7
211 #define H264SEI_STRUCT_TRIPLE 8
212
h264sei_init(uint8_t * p_h264sei)213 static inline void h264sei_init(uint8_t *p_h264sei)
214 {
215 h264nal_init(p_h264sei);
216 h264nal_set_type(p_h264sei, H264NAL_TYPE_SEI);
217 }
218
219 /*****************************************************************************
220 * H264 sequence parameter set
221 *****************************************************************************/
222 #define H264SPS_HEADER_SIZE 7
223
224 #define H264SPS_ID_MAX 32
225
226 #define H264SPS_CHROMA_MONO 0
227 #define H264SPS_CHROMA_420 1
228 #define H264SPS_CHROMA_422 2
229 #define H264SPS_CHROMA_444 3
230
h264sps_init(uint8_t * p_h264sps)231 static inline void h264sps_init(uint8_t *p_h264sps)
232 {
233 h264nal_init(p_h264sps);
234 h264nal_set_ref(p_h264sps, 1);
235 h264nal_set_type(p_h264sps, H264NAL_TYPE_SPS);
236 p_h264sps[5] = 0x0;
237 }
238
h264sps_set_profile(uint8_t * p_h264sps,uint8_t i_profile)239 static inline void h264sps_set_profile(uint8_t *p_h264sps, uint8_t i_profile)
240 {
241 p_h264sps[4] = i_profile;
242 }
243
h264sps_get_profile(const uint8_t * p_h264sps)244 static inline uint8_t h264sps_get_profile(const uint8_t *p_h264sps)
245 {
246 return p_h264sps[4];
247 }
248
249 /* Note: doesn't do the constrained profile checks */
h264_sps_get_profile_txt(uint8_t i_profile)250 static inline const char *h264_sps_get_profile_txt(uint8_t i_profile)
251 {
252 return i_profile == 44 ? "CAVLC 4:4:4 Intra" :
253 i_profile == 66 ? "Baseline" :
254 i_profile == 77 ? "Main" :
255 i_profile == 88 ? "Extended" :
256 i_profile == 100 ? "High" :
257 i_profile == 110 ? "High 10" :
258 i_profile == 122 ? "High 4:2:2" :
259 i_profile == 144 ? "High 4:4:4 Predictive" : "Reserved";
260 }
261
h264sps_set_level(uint8_t * p_h264sps,uint8_t i_level)262 static inline void h264sps_set_level(uint8_t *p_h264sps, uint8_t i_level)
263 {
264 p_h264sps[6] = i_level;
265 }
266
h264sps_get_level(const uint8_t * p_h264sps)267 static inline uint8_t h264sps_get_level(const uint8_t *p_h264sps)
268 {
269 return p_h264sps[6];
270 }
271
272 /*****************************************************************************
273 * H264 picture parameter set
274 *****************************************************************************/
275 #define H264PPS_HEADER_SIZE 7
276
277 #define H264PPS_ID_MAX 256
278
h264pps_init(uint8_t * p_h264pps)279 static inline void h264pps_init(uint8_t *p_h264pps)
280 {
281 h264nal_init(p_h264pps);
282 h264nal_set_ref(p_h264pps, 1);
283 h264nal_set_type(p_h264pps, H264NAL_TYPE_PPS);
284 }
285
286 /*****************************************************************************
287 * H264 access unit delimiter
288 *****************************************************************************/
289 #define H264AUD_HEADER_SIZE 5
290
h264aud_init(uint8_t * p_h264aud)291 static inline void h264aud_init(uint8_t *p_h264aud)
292 {
293 h264nal_init(p_h264aud);
294 h264nal_set_type(p_h264aud, H264NAL_TYPE_AUD);
295 p_h264aud[4] = 0x10;
296 }
297
h264aud_set_pic_type(uint8_t * p_h264aud,uint8_t i_type)298 static inline void h264aud_set_pic_type(uint8_t *p_h264aud, uint8_t i_type)
299 {
300 p_h264aud[4] = i_type << 5;
301 }
302
h264aud_get_pic_type(const uint8_t * p_h264aud)303 static inline uint8_t h264aud_get_pic_type(const uint8_t *p_h264aud)
304 {
305 return p_h264aud[4] >> 5;
306 }
307
308 /*****************************************************************************
309 * H264 end sequence
310 *****************************************************************************/
311 #define H264ENDSEQ_HEADER_SIZE 4
312
h264endseq_init(uint8_t * p_h264endseq)313 static inline void h264endseq_init(uint8_t *p_h264endseq)
314 {
315 h264nal_init(p_h264endseq);
316 h264nal_set_type(p_h264endseq, H264NAL_TYPE_ENDSEQ);
317 }
318
319 /*****************************************************************************
320 * H264 end stream
321 *****************************************************************************/
322 #define H264ENDSTR_HEADER_SIZE 4
323
h264endstr_init(uint8_t * p_h264endstr)324 static inline void h264endstr_init(uint8_t *p_h264endstr)
325 {
326 h264nal_init(p_h264endstr);
327 h264nal_set_type(p_h264endstr, H264NAL_TYPE_ENDSTR);
328 }
329
330 /*****************************************************************************
331 * H264 sequence parameter set extension
332 *****************************************************************************/
333 #define H264SPSX_HEADER_SIZE 4
334
h264spsx_init(uint8_t * p_h264spsx)335 static inline void h264spsx_init(uint8_t *p_h264spsx)
336 {
337 h264nal_init(p_h264spsx);
338 h264nal_set_ref(p_h264spsx, 1);
339 h264nal_set_type(p_h264spsx, H264NAL_TYPE_SPSX);
340 }
341
342 /*****************************************************************************
343 * H264 subset sequence parameter set
344 *****************************************************************************/
345 #define H264SSPS_HEADER_SIZE 4
346
h264ssps_init(uint8_t * p_h264ssps)347 static inline void h264ssps_init(uint8_t *p_h264ssps)
348 {
349 h264nal_init(p_h264ssps);
350 h264nal_set_ref(p_h264ssps, 1);
351 h264nal_set_type(p_h264ssps, H264NAL_TYPE_SSPS);
352 }
353
354 /*****************************************************************************
355 * H264 video usability information
356 *****************************************************************************/
357 #define H264VUI_AR_EXTENDED 255
358
359 /*****************************************************************************
360 * H264 slices
361 *****************************************************************************/
362 #define H264SLI_TYPE_P 0
363 #define H264SLI_TYPE_B 1
364 #define H264SLI_TYPE_I 2
365 #define H264SLI_TYPE_SP 3
366 #define H264SLI_TYPE_SI 4
367
368 /*****************************************************************************
369 * H264 avcC structure
370 *****************************************************************************/
371 #define H264AVCC_HEADER 6
372 #define H264AVCC_HEADER2 1
373 #define H264AVCC_SPS_HEADER 2
374 #define H264AVCC_PPS_HEADER 2
375
h264avcc_init(uint8_t * p)376 static inline void h264avcc_init(uint8_t *p)
377 {
378 p[0] = 1; /* version */
379 p[4] = 0xfc;
380 p[5] = 0xe0;
381 }
382
h264avcc_set_profile(uint8_t * p,uint8_t val)383 static inline void h264avcc_set_profile(uint8_t *p, uint8_t val)
384 {
385 p[1] = val;
386 }
387
h264avcc_get_profile(const uint8_t * p)388 static inline uint8_t h264avcc_get_profile(const uint8_t *p)
389 {
390 return p[1];
391 }
392
h264avcc_set_profile_compatibility(uint8_t * p,uint8_t val)393 static inline void h264avcc_set_profile_compatibility(uint8_t *p, uint8_t val)
394 {
395 p[2] = val;
396 }
397
h264avcc_get_profile_compatibility(const uint8_t * p)398 static inline uint8_t h264avcc_get_profile_compatibility(const uint8_t *p)
399 {
400 return p[2];
401 }
402
h264avcc_set_level(uint8_t * p,uint8_t val)403 static inline void h264avcc_set_level(uint8_t *p, uint8_t val)
404 {
405 p[3] = val;
406 }
407
h264avcc_get_level(const uint8_t * p)408 static inline uint8_t h264avcc_get_level(const uint8_t *p)
409 {
410 return p[3];
411 }
412
h264avcc_set_length_size_1(uint8_t * p,uint8_t val)413 static inline void h264avcc_set_length_size_1(uint8_t *p, uint8_t val)
414 {
415 p[4] = 0xfc | val;
416 }
417
h264avcc_get_length_size_1(const uint8_t * p)418 static inline uint8_t h264avcc_get_length_size_1(const uint8_t *p)
419 {
420 return p[4] & 0x3;
421 }
422
h264avcc_set_nb_sps(uint8_t * p,uint8_t val)423 static inline void h264avcc_set_nb_sps(uint8_t *p, uint8_t val)
424 {
425 p[5] = 0xe0 | val;
426 }
427
h264avcc_get_nb_sps(const uint8_t * p)428 static inline uint8_t h264avcc_get_nb_sps(const uint8_t *p)
429 {
430 return p[5] & 0x1f;
431 }
432
h264avcc_spsh_set_length(uint8_t * p,uint16_t val)433 static inline void h264avcc_spsh_set_length(uint8_t *p, uint16_t val)
434 {
435 p[0] = val >> 8;
436 p[1] = val & 0xff;
437 }
438
h264avcc_spsh_get_length(const uint8_t * p)439 static inline uint16_t h264avcc_spsh_get_length(const uint8_t *p)
440 {
441 return (p[0] << 8) | p[1];
442 }
443
h264avcc_spsh_get_sps(const uint8_t * p)444 static inline uint8_t *h264avcc_spsh_get_sps(const uint8_t *p)
445 {
446 return (uint8_t *)p + H264AVCC_SPS_HEADER;
447 }
448
h264avcc_get_spsh(const uint8_t * p,uint8_t n)449 static inline uint8_t *h264avcc_get_spsh(const uint8_t *p, uint8_t n)
450 {
451 p += H264AVCC_HEADER;
452 while (n) {
453 uint16_t length = h264avcc_spsh_get_length(p);
454 p += H264AVCC_SPS_HEADER + length;
455 n--;
456 }
457 return (uint8_t *)p;
458 }
459
h264avcc_set_nb_pps(uint8_t * p,uint8_t val)460 static inline void h264avcc_set_nb_pps(uint8_t *p, uint8_t val)
461 {
462 p = h264avcc_get_spsh(p, h264avcc_get_nb_sps(p));
463 p[0] = val;
464 }
465
h264avcc_get_nb_pps(const uint8_t * p)466 static inline uint8_t h264avcc_get_nb_pps(const uint8_t *p)
467 {
468 p = h264avcc_get_spsh(p, h264avcc_get_nb_sps(p));
469 return p[0];
470 }
471
h264avcc_ppsh_set_length(uint8_t * p,uint16_t val)472 static inline void h264avcc_ppsh_set_length(uint8_t *p, uint16_t val)
473 {
474 p[0] = val >> 8;
475 p[1] = val & 0xff;
476 }
477
h264avcc_ppsh_get_length(const uint8_t * p)478 static inline uint16_t h264avcc_ppsh_get_length(const uint8_t *p)
479 {
480 return (p[0] << 8) | p[1];
481 }
482
h264avcc_ppsh_get_pps(const uint8_t * p)483 static inline uint8_t *h264avcc_ppsh_get_pps(const uint8_t *p)
484 {
485 return (uint8_t *)p + H264AVCC_PPS_HEADER;
486 }
487
h264avcc_get_ppsh(const uint8_t * p,uint8_t n)488 static inline uint8_t *h264avcc_get_ppsh(const uint8_t *p, uint8_t n)
489 {
490 p = h264avcc_get_spsh(p, h264avcc_get_nb_sps(p));
491 p += H264AVCC_HEADER2;
492 while (n) {
493 uint16_t length = h264avcc_ppsh_get_length(p);
494 p += H264AVCC_PPS_HEADER + length;
495 n--;
496 }
497 return (uint8_t *)p;
498 }
499
h264avcc_validate(const uint8_t * p,size_t size)500 static inline bool h264avcc_validate(const uint8_t *p, size_t size)
501 {
502 if (p[0] != 1)
503 return false;
504 /* don't check reserved bits as it is a common mistake */
505
506 if (size < H264AVCC_HEADER + H264AVCC_HEADER2)
507 return false;
508
509 uint8_t nb = h264avcc_get_nb_sps(p);
510 uint8_t n = 0;
511 while (n < nb)
512 if (h264avcc_get_spsh(p, n++) + H264AVCC_SPS_HEADER > p + size)
513 return false;
514
515 if (h264avcc_get_spsh(p, n) + H264AVCC_HEADER2 > p + size)
516 return false;
517
518 nb = h264avcc_get_nb_pps(p);
519 n = 0;
520 while (n < nb)
521 if (h264avcc_get_ppsh(p, n++) + H264AVCC_PPS_HEADER > p + size)
522 return false;
523
524 if (h264avcc_get_ppsh(p, n) > p + size)
525 return false;
526 return true;
527 }
528
529 #ifdef __cplusplus
530 }
531 #endif
532
533 #endif
534