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