1 /*****************************************************************************
2 * hxxx_helper.c: AnnexB / avcC helper for dumb decoders
3 *****************************************************************************
4 * Copyright (C) 2017 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
28 #include <vlc_common.h>
31 #include "hxxx_helper.h"
32 #include "../packetizer/hxxx_nal.h"
33 #include "../packetizer/h264_slice.h"
36 hxxx_helper_init(struct hxxx_helper
*hh
, vlc_object_t
*p_obj
,
37 vlc_fourcc_t i_codec
, bool b_need_xvcC
)
39 assert(i_codec
== VLC_CODEC_H264
|| i_codec
== VLC_CODEC_HEVC
);
41 memset(hh
, 0, sizeof(struct hxxx_helper
));
43 hh
->i_codec
= i_codec
;
44 hh
->b_need_xvcC
= b_need_xvcC
;
47 #define RELEASE_NALS(list, max, release) \
48 for (size_t i = 0; i <= max; ++i) \
53 block_Release(hnal->b); \
59 helper_clear_sei(struct hxxx_helper
*hh
)
61 if (hh
->i_codec
!= VLC_CODEC_HEVC
)
64 for (uint8_t i
=0; i
<hh
->hevc
.i_sei_count
; i
++)
66 if(hh
->hevc
.sei_list
[i
].b
)
68 block_Release(hh
->hevc
.sei_list
[i
].b
);
69 hh
->hevc
.sei_list
[i
].b
= NULL
;
72 hh
->hevc
.i_sei_count
= 0;
76 hxxx_helper_clean(struct hxxx_helper
*hh
)
78 struct hxxx_helper_nal
*hnal
;
82 RELEASE_NALS(hh
->h264
.sps_list
, H264_SPS_ID_MAX
,
83 h264_release_sps(hnal
->h264_sps
));
84 RELEASE_NALS(hh
->h264
.pps_list
, H264_PPS_ID_MAX
,
85 h264_release_pps(hnal
->h264_pps
));
86 memset(&hh
->h264
, 0, sizeof(hh
->h264
));
89 RELEASE_NALS(hh
->hevc
.vps_list
, HEVC_VPS_ID_MAX
,
90 hevc_rbsp_release_vps(hnal
->hevc_vps
));
91 RELEASE_NALS(hh
->hevc
.sps_list
, HEVC_SPS_ID_MAX
,
92 hevc_rbsp_release_sps(hnal
->hevc_sps
));
93 RELEASE_NALS(hh
->hevc
.pps_list
, HEVC_PPS_ID_MAX
,
94 hevc_rbsp_release_pps(hnal
->hevc_pps
));
96 memset(&hh
->hevc
, 0, sizeof(hh
->hevc
));
99 vlc_assert_unreachable();
103 #define HELPER_FOREACH_NAL(it, p_nal_list, i_nal_count, i_nal_max) \
104 for (size_t ii = 0, i_nal_found = 0; ii < i_nal_max && i_nal_count > i_nal_found; ++ii) \
105 if (p_nal_list[ii].b != NULL && (it = &p_nal_list[ii]) && ++i_nal_found)
108 helper_dup_buf(struct hxxx_helper_nal
*p_nal
,
109 const uint8_t *p_nal_buf
, size_t i_nal_buf
)
113 p_nal
->b
= block_Alloc(i_nal_buf
);
117 else if (p_nal
->b
!= NULL
&& i_nal_buf
> p_nal
->b
->i_buffer
)
119 block_t
*b
= block_TryRealloc(p_nal
->b
, 0, i_nal_buf
);
124 memcpy(p_nal
->b
->p_buffer
, p_nal_buf
, i_nal_buf
);
125 p_nal
->b
->i_buffer
= i_nal_buf
;
129 static inline const struct hxxx_helper_nal
*
130 helper_search_nal(const struct hxxx_helper_nal
*p_nal_list
, size_t i_nal_count
,
131 size_t i_nal_max
, const void *p_nal_buf
, size_t i_nal_buf
)
134 for (size_t i
= 0; i
< i_nal_max
&& i_nal_count
> i_nal_nb
; ++i
)
136 const struct hxxx_helper_nal
*p_nal
= &p_nal_list
[i
];
137 if (p_nal
->b
== NULL
)
140 const int i_diff
= i_nal_buf
- p_nal
->b
->i_buffer
;
141 if (i_diff
== 0 && memcmp(p_nal_buf
, p_nal
->b
->p_buffer
, i_nal_buf
) == 0)
148 helper_nal_length_valid(struct hxxx_helper
*hh
)
150 return hh
->i_nal_length_size
== 1 || hh
->i_nal_length_size
== 2
151 || hh
->i_nal_length_size
== 4;
155 helper_load_sei(struct hxxx_helper
*hh
, const uint8_t *p_nal
, size_t i_nal
)
157 if(hh
->i_codec
!= VLC_CODEC_HEVC
)
160 if(hh
->hevc
.i_sei_count
== HXXX_HELPER_SEI_COUNT
)
163 struct hxxx_helper_nal
*hnal
= &hh
->hevc
.sei_list
[hh
->hevc
.i_sei_count
];
164 if (helper_dup_buf(hnal
, p_nal
, i_nal
))
166 hh
->hevc
.i_sei_count
++;
169 #define LOAD_xPS(list, count, id, max, xpstype, xpsdecode, xpsrelease) \
170 if (helper_search_nal(list, count, max+1, p_nal, i_nal) != NULL)\
172 xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
174 return VLC_EGENERIC;\
176 struct hxxx_helper_nal *hnal = &list[id];\
177 if (helper_dup_buf(hnal, p_nal, i_nal))\
180 return VLC_EGENERIC;\
183 xpsrelease(hnal->xps);\
188 *p_config_changed = true
191 h264_helper_parse_nal(struct hxxx_helper
*hh
, const uint8_t *p_buf
, size_t i_buf
,
192 uint8_t i_nal_length_size
, bool *p_config_changed
)
194 const uint8_t *p_nal
;
196 hxxx_iterator_ctx_t it
;
197 hxxx_iterator_init(&it
, p_buf
, i_buf
, i_nal_length_size
);
198 *p_config_changed
= false;
200 while ((i_nal_length_size
) ? hxxx_iterate_next(&it
, &p_nal
, &i_nal
)
201 : hxxx_annexb_iterate_next(&it
, &p_nal
, &i_nal
))
206 const enum h264_nal_unit_type_e i_nal_type
= p_nal
[0] & 0x1F;
208 if (i_nal_type
== H264_NAL_SPS
)
210 LOAD_xPS(hh
->h264
.sps_list
, hh
->h264
.i_sps_count
,
211 p_xps
->i_id
, H264_SPS_ID_MAX
,
212 h264_sequence_parameter_set_t
,
215 hh
->h264
.i_current_sps
= ((h264_sequence_parameter_set_t
*)p_xps
)->i_id
;
216 msg_Dbg(hh
->p_obj
, "new SPS parsed: %u", hh
->h264
.i_current_sps
);
218 else if (i_nal_type
== H264_NAL_PPS
)
220 LOAD_xPS(hh
->h264
.pps_list
, hh
->h264
.i_pps_count
,
221 p_xps
->i_id
, H264_PPS_ID_MAX
,
222 h264_picture_parameter_set_t
,
225 msg_Dbg(hh
->p_obj
, "new PPS parsed: %u", ((h264_picture_parameter_set_t
*)p_xps
)->i_id
);
227 else if (i_nal_type
<= H264_NAL_SLICE_IDR
228 && i_nal_type
!= H264_NAL_UNKNOWN
)
230 if (hh
->h264
.i_sps_count
> 1)
232 /* There is more than one SPS. Get the PPS id of the current
233 * SLICE in order to get the current SPS id */
235 /* Get the PPS id from the slice: inspirated from
236 * h264_decode_slice() */
238 bs_init(&s
, p_nal
, i_nal
);
242 unsigned i_pps_id
= bs_read_ue(&s
);
243 if (i_pps_id
> H264_PPS_ID_MAX
)
246 struct hxxx_helper_nal
*hpps
= &hh
->h264
.pps_list
[i_pps_id
];
250 struct hxxx_helper_nal
*hsps
=
251 &hh
->h264
.sps_list
[hpps
->h264_pps
->i_sps_id
];
255 assert(hpps
->h264_pps
->i_sps_id
== hsps
->h264_sps
->i_id
);
256 if (hsps
->h264_sps
->i_id
!= hh
->h264
.i_current_sps
)
258 hh
->h264
.i_current_sps
= hsps
->h264_sps
->i_id
;
259 *p_config_changed
= true;
262 break; /* No need to parse further NAL */
269 helper_check_sei_au(struct hxxx_helper
*hh
, uint8_t i_nal_type
)
271 if ((i_nal_type
<= HEVC_NAL_IRAP_VCL23
&&
272 hh
->hevc
.i_previous_nal_type
!= HEVC_NAL_PREF_SEI
) ||
273 (i_nal_type
== HEVC_NAL_PREF_SEI
&&
274 hh
->hevc
.i_previous_nal_type
!= HEVC_NAL_PREF_SEI
))
275 helper_clear_sei(hh
);
276 hh
->hevc
.i_previous_nal_type
= i_nal_type
;
280 hevc_helper_parse_nal(struct hxxx_helper
*hh
, const uint8_t *p_buf
, size_t i_buf
,
281 uint8_t i_nal_length_size
, bool *p_config_changed
)
283 const uint8_t *p_nal
;
285 hxxx_iterator_ctx_t it
;
286 hxxx_iterator_init(&it
, p_buf
, i_buf
, i_nal_length_size
);
287 *p_config_changed
= false;
289 while ((i_nal_length_size
) ? hxxx_iterate_next(&it
, &p_nal
, &i_nal
)
290 : hxxx_annexb_iterate_next(&it
, &p_nal
, &i_nal
))
292 if (i_nal
< 2 || hevc_getNALLayer(p_nal
) > 0)
295 const uint8_t i_nal_type
= hevc_getNALType(p_nal
);
297 /* we need to clear sei not belonging to this access unit */
298 helper_check_sei_au(hh
, i_nal_type
);
300 if (i_nal_type
== HEVC_NAL_VPS
)
303 if( !hevc_get_xps_id(p_nal
, i_nal
, &i_id
) )
305 LOAD_xPS(hh
->hevc
.vps_list
, hh
->hevc
.i_vps_count
,
306 i_id
, HEVC_VPS_ID_MAX
,
307 hevc_video_parameter_set_t
,
309 hevc_rbsp_release_vps
);
310 msg_Dbg(hh
->p_obj
, "new VPS parsed: %u", i_id
);
312 else if (i_nal_type
== HEVC_NAL_SPS
)
315 if( !hevc_get_xps_id(p_nal
, i_nal
, &i_id
) )
317 LOAD_xPS(hh
->hevc
.sps_list
, hh
->hevc
.i_sps_count
,
318 i_id
, HEVC_SPS_ID_MAX
,
319 hevc_sequence_parameter_set_t
,
321 hevc_rbsp_release_sps
);
322 msg_Dbg(hh
->p_obj
, "new SPS parsed: %u", i_id
);
324 else if (i_nal_type
== HEVC_NAL_PPS
)
327 if( !hevc_get_xps_id(p_nal
, i_nal
, &i_id
) )
329 LOAD_xPS(hh
->hevc
.pps_list
, hh
->hevc
.i_pps_count
,
330 i_id
, HEVC_PPS_ID_MAX
,
331 hevc_picture_parameter_set_t
,
333 hevc_rbsp_release_pps
);
334 msg_Dbg(hh
->p_obj
, "new PPS parsed: %u", i_id
);
336 else if (i_nal_type
<= HEVC_NAL_IRAP_VCL23
)
338 if (hh
->hevc
.i_sps_count
> 1 || hh
->hevc
.i_vps_count
> 1)
340 /* Get the PPS id from the slice: inspirated from
341 * h264_decode_slice() */
343 bs_init(&s
, p_nal
, i_nal
);
345 unsigned i_id
= bs_read_ue(&s
);
346 if (i_id
> HEVC_PPS_ID_MAX
)
349 struct hxxx_helper_nal
*xps
= &hh
->hevc
.pps_list
[i_id
];
353 const uint8_t i_spsid
= hevc_get_pps_sps_id(xps
->hevc_pps
);
354 xps
= &hh
->hevc
.sps_list
[i_spsid
];
358 i_id
= hevc_get_sps_vps_id(xps
->hevc_sps
);
359 xps
= &hh
->hevc
.vps_list
[i_id
];
361 if (i_spsid
!= hh
->hevc
.i_current_sps
||
362 i_id
!= hh
->hevc
.i_current_vps
)
364 hh
->hevc
.i_current_sps
= i_spsid
;
365 hh
->hevc
.i_current_vps
= i_id
;
366 *p_config_changed
= true;
369 break; /* No need to parse further NAL */
371 else if(i_nal_type
== HEVC_NAL_PREF_SEI
||
372 i_nal_type
== HEVC_NAL_SUFF_SEI
)
374 helper_load_sei(hh
, p_nal
, i_nal
);
381 helper_process_avcC_h264(struct hxxx_helper
*hh
, const uint8_t *p_buf
,
384 if (i_buf
< H264_MIN_AVCC_SIZE
)
387 p_buf
+= 5; i_buf
-= 5;
389 for (unsigned int j
= 0; j
< 2 && i_buf
> 0; j
++)
391 /* First time is SPS, Second is PPS */
392 const unsigned int i_num_nal
= p_buf
[0] & (j
== 0 ? 0x1f : 0xff);
395 for (unsigned int i
= 0; i
< i_num_nal
&& i_buf
>= 2; i
++)
397 uint16_t i_nal_size
= (p_buf
[0] << 8) | p_buf
[1];
398 if (i_nal_size
> i_buf
- 2)
401 int i_ret
= h264_helper_parse_nal(hh
, p_buf
, i_nal_size
+ 2, 2,
403 if (i_ret
!= VLC_SUCCESS
)
405 p_buf
+= i_nal_size
+ 2;
406 i_buf
-= i_nal_size
+ 2;
414 hxxx_extra_isannexb(const void *p_extra
, size_t i_extra
)
417 || (i_extra
> 4 && memcmp(p_extra
, annexb_startcode4
, 4) == 0);
421 h264_helper_set_extra(struct hxxx_helper
*hh
, const void *p_extra
,
424 if (h264_isavcC(p_extra
, i_extra
))
426 hh
->i_nal_length_size
= (((uint8_t*)p_extra
)[4] & 0x03) + 1;
427 if (!helper_nal_length_valid(hh
))
429 hh
->b_is_xvcC
= true;
431 /* XXX h264_AVC_to_AnnexB() works only with a i_nal_length_size of 4.
432 * If nal_length_size is smaller than 4, fallback to SW decoding. I
433 * don't know if it's worth the effort to fix h264_AVC_to_AnnexB() for
434 * a smaller nal_length_size. Indeed, this case will happen only with
435 * very small resolutions, where hardware decoders are not that useful.
437 if (!hh
->b_need_xvcC
&& hh
->i_nal_length_size
!= 4)
439 msg_Dbg(hh
->p_obj
, "nal_length_size is too small");
443 return helper_process_avcC_h264(hh
, p_extra
, i_extra
);
445 else if (hxxx_extra_isannexb(p_extra
, i_extra
))
447 hh
->i_nal_length_size
= 4;
449 return i_extra
== 0 ? VLC_SUCCESS
:
450 h264_helper_parse_nal(hh
, p_extra
, i_extra
, 0, &unused
);
457 helper_process_hvcC_hevc(struct hxxx_helper
*hh
, const uint8_t *p_buf
,
460 if (i_buf
< HEVC_MIN_HVCC_SIZE
)
463 const uint8_t i_num_array
= p_buf
[22];
464 p_buf
+= 23; i_buf
-= 23;
466 for( uint8_t i
= 0; i
< i_num_array
; i
++ )
471 const uint16_t i_num_nalu
= p_buf
[1] << 8 | p_buf
[2];
472 p_buf
+= 3; i_buf
-= 3;
474 for( uint16_t j
= 0; j
< i_num_nalu
; j
++ )
479 const uint16_t i_nalu_length
= p_buf
[0] << 8 | p_buf
[1];
480 if(i_buf
< (size_t)i_nalu_length
+ 2)
484 hevc_helper_parse_nal( hh
, &p_buf
[0],
485 i_nalu_length
+ 2, 2, &foo
);
487 p_buf
+= i_nalu_length
+ 2;
488 i_buf
-= i_nalu_length
+ 2;
496 hevc_helper_set_extra(struct hxxx_helper
*hh
, const void *p_extra
,
499 if (hevc_ishvcC(p_extra
, i_extra
))
501 hh
->i_nal_length_size
= hevc_getNALLengthSize(p_extra
);
502 if (!helper_nal_length_valid(hh
))
504 hh
->b_is_xvcC
= true;
506 return helper_process_hvcC_hevc( hh
, p_extra
, i_extra
);
508 else if (hxxx_extra_isannexb(p_extra
, i_extra
))
510 hh
->i_nal_length_size
= 4;
512 return i_extra
== 0 ? VLC_SUCCESS
:
513 hevc_helper_parse_nal(hh
, p_extra
, i_extra
, 0, &unused
);
519 static inline block_t
*
520 helper_process_block_hxxx_annexb(struct hxxx_helper
*hh
,
521 int(*parser
)(struct hxxx_helper
*,
522 const uint8_t*, size_t,uint8_t,bool*),
523 block_t
*p_block
, bool *p_config_changed
)
525 if (p_config_changed
!= NULL
)
527 int i_ret
= parser(hh
, p_block
->p_buffer
, p_block
->i_buffer
,
528 0, p_config_changed
);
529 if (i_ret
!= VLC_SUCCESS
)
531 block_Release(p_block
);
539 helper_process_block_h264_annexb(struct hxxx_helper
*hh
, block_t
*p_block
,
540 bool *p_config_changed
)
542 if (p_config_changed
!= NULL
)
543 return helper_process_block_hxxx_annexb(hh
, h264_helper_parse_nal
,
544 p_block
,p_config_changed
);
549 helper_process_block_hevc_annexb(struct hxxx_helper
*hh
, block_t
*p_block
,
550 bool *p_config_changed
)
552 if (p_config_changed
!= NULL
)
553 return helper_process_block_hxxx_annexb(hh
, hevc_helper_parse_nal
,
554 p_block
,p_config_changed
);
559 helper_process_block_xvcc2annexb(struct hxxx_helper
*hh
, block_t
*p_block
,
560 bool *p_config_changed
)
562 assert(helper_nal_length_valid(hh
));
563 h264_AVC_to_AnnexB(p_block
->p_buffer
, p_block
->i_buffer
,
564 hh
->i_nal_length_size
);
565 return helper_process_block_h264_annexb(hh
, p_block
, p_config_changed
);
569 helper_process_block_h264_annexb2avcc(struct hxxx_helper
*hh
, block_t
*p_block
,
570 bool *p_config_changed
)
572 p_block
= helper_process_block_h264_annexb(hh
, p_block
, p_config_changed
);
573 return p_block
? hxxx_AnnexB_to_xVC(p_block
, hh
->i_nal_length_size
) : NULL
;
577 helper_process_block_hevc_annexb2hvcc(struct hxxx_helper
*hh
, block_t
*p_block
,
578 bool *p_config_changed
)
580 p_block
= helper_process_block_hevc_annexb(hh
, p_block
, p_config_changed
);
581 return p_block
? hxxx_AnnexB_to_xVC(p_block
, hh
->i_nal_length_size
) : NULL
;
585 helper_process_block_h264_avcc(struct hxxx_helper
*hh
, block_t
*p_block
,
586 bool *p_config_changed
)
588 if (p_config_changed
!= NULL
)
590 int i_ret
= h264_helper_parse_nal(hh
, p_block
->p_buffer
,
592 hh
->i_nal_length_size
,
594 if (i_ret
!= VLC_SUCCESS
)
596 block_Release(p_block
);
604 helper_process_block_hevc_hvcc(struct hxxx_helper
*hh
, block_t
*p_block
,
605 bool *p_config_changed
)
607 if (p_config_changed
!= NULL
)
609 int i_ret
= hevc_helper_parse_nal(hh
, p_block
->p_buffer
,
611 hh
->i_nal_length_size
,
613 if (i_ret
!= VLC_SUCCESS
)
615 block_Release(p_block
);
623 hxxx_helper_set_extra(struct hxxx_helper
*hh
, const void *p_extra
,
630 i_ret
= h264_helper_set_extra(hh
, p_extra
, i_extra
);
633 i_ret
= hevc_helper_set_extra(hh
, p_extra
, i_extra
);
636 vlc_assert_unreachable();
638 if (i_ret
!= VLC_SUCCESS
)
647 hh
->pf_process_block
= helper_process_block_h264_avcc
;
649 hh
->pf_process_block
= helper_process_block_xvcc2annexb
;
654 hh
->pf_process_block
= helper_process_block_h264_annexb2avcc
;
656 hh
->pf_process_block
= helper_process_block_h264_annexb
;
663 hh
->pf_process_block
= helper_process_block_hevc_hvcc
;
665 hh
->pf_process_block
= helper_process_block_xvcc2annexb
;
670 hh
->pf_process_block
= helper_process_block_hevc_annexb2hvcc
;
672 hh
->pf_process_block
= helper_process_block_hevc_annexb
;
676 vlc_assert_unreachable();
682 hxxx_helper_get_annexb_config( const struct hxxx_helper_nal
*pp_nal_lists
[],
683 const size_t p_nal_counts
[],
684 const size_t p_nal_maxs
[],
685 size_t i_lists_size
)
687 static const uint8_t annexb_startcode
[] = { 0x00, 0x00, 0x00, 0x01 };
689 block_t
*p_block_list
= NULL
, *p_current
;
690 for (size_t i
= 0; i
< i_lists_size
; ++i
)
692 size_t i_nals_size
= 0;
693 const struct hxxx_helper_nal
*p_nal
;
694 HELPER_FOREACH_NAL(p_nal
, pp_nal_lists
[i
], p_nal_counts
[i
], p_nal_maxs
[i
])
696 i_nals_size
+= p_nal
->b
->i_buffer
+ sizeof annexb_startcode
;
699 block_t
*p_block
= block_Alloc(i_nals_size
);
702 if (p_block_list
!= NULL
)
703 block_Release(p_block_list
);
707 p_block
->i_buffer
= 0;
708 HELPER_FOREACH_NAL(p_nal
, pp_nal_lists
[i
], p_nal_counts
[i
], p_nal_maxs
[i
])
710 memcpy(&p_block
->p_buffer
[p_block
->i_buffer
], annexb_startcode
,
711 sizeof annexb_startcode
);
712 p_block
->i_buffer
+= sizeof annexb_startcode
;
713 memcpy(&p_block
->p_buffer
[p_block
->i_buffer
], p_nal
->b
->p_buffer
,
715 p_block
->i_buffer
+= p_nal
->b
->i_buffer
;
717 if (p_block_list
== NULL
)
718 p_current
= p_block_list
= p_block
;
721 p_current
->p_next
= p_block
;
730 h264_helper_get_annexb_config(const struct hxxx_helper
*hh
)
732 if (hh
->h264
.i_sps_count
== 0 || hh
->h264
.i_pps_count
== 0)
735 const struct hxxx_helper_nal
*pp_nal_lists
[] = {
736 hh
->h264
.sps_list
, hh
->h264
.pps_list
};
737 const size_t p_nal_counts
[] = { hh
->h264
.i_sps_count
, hh
->h264
.i_pps_count
};
738 const size_t p_nal_maxs
[] = { H264_SPS_ID_MAX
+1, H264_PPS_ID_MAX
+1 };
740 return hxxx_helper_get_annexb_config( pp_nal_lists
, p_nal_counts
, p_nal_maxs
, 2 );
744 hevc_helper_get_annexb_config(const struct hxxx_helper
*hh
)
746 if (hh
->hevc
.i_vps_count
== 0 || hh
->hevc
.i_sps_count
== 0 ||
747 hh
->hevc
.i_pps_count
== 0 )
750 const struct hxxx_helper_nal
*pp_nal_lists
[] = {
751 hh
->hevc
.vps_list
, hh
->hevc
.sps_list
, hh
->hevc
.pps_list
};
752 const size_t p_nal_counts
[] = { hh
->hevc
.i_vps_count
, hh
->hevc
.i_sps_count
,
753 hh
->hevc
.i_pps_count
};
754 const size_t p_nal_maxs
[] = { HEVC_VPS_ID_MAX
+1, HEVC_SPS_ID_MAX
+1, HEVC_PPS_ID_MAX
+1 };
756 return hxxx_helper_get_annexb_config( pp_nal_lists
, p_nal_counts
, p_nal_maxs
, 3 );
760 h264_helper_get_avcc_config(const struct hxxx_helper
*hh
)
762 const struct hxxx_helper_nal
*p_nal
;
763 const uint8_t *pp_sps_bufs
[hh
->h264
.i_sps_count
];
764 size_t p_sps_sizes
[hh
->h264
.i_sps_count
];
765 HELPER_FOREACH_NAL(p_nal
, hh
->h264
.sps_list
, hh
->h264
.i_sps_count
,
768 pp_sps_bufs
[i_nal_found
- 1] = p_nal
->b
->p_buffer
;
769 p_sps_sizes
[i_nal_found
- 1] = p_nal
->b
->i_buffer
;
772 const uint8_t *pp_pps_bufs
[hh
->h264
.i_pps_count
];
773 size_t p_pps_sizes
[hh
->h264
.i_pps_count
];
774 HELPER_FOREACH_NAL(p_nal
, hh
->h264
.pps_list
, hh
->h264
.i_pps_count
,
777 pp_pps_bufs
[i_nal_found
- 1] = p_nal
->b
->p_buffer
;
778 p_pps_sizes
[i_nal_found
- 1] = p_nal
->b
->i_buffer
;
780 return h264_NAL_to_avcC(4, pp_sps_bufs
, p_sps_sizes
, hh
->h264
.i_sps_count
,
781 pp_pps_bufs
, p_pps_sizes
, hh
->h264
.i_pps_count
);
785 hevc_helper_get_hvcc_config(const struct hxxx_helper
*hh
)
787 struct hevc_dcr_params params
= {};
788 const struct hxxx_helper_nal
*p_nal
;
790 HELPER_FOREACH_NAL(p_nal
, hh
->hevc
.vps_list
, hh
->hevc
.i_vps_count
,
793 params
.p_vps
[params
.i_vps_count
] = p_nal
->b
->p_buffer
;
794 params
.rgi_vps
[params
.i_vps_count
++] = p_nal
->b
->i_buffer
;
797 HELPER_FOREACH_NAL(p_nal
, hh
->hevc
.sps_list
, hh
->hevc
.i_sps_count
,
800 params
.p_sps
[params
.i_sps_count
] = p_nal
->b
->p_buffer
;
801 params
.rgi_sps
[params
.i_sps_count
++] = p_nal
->b
->i_buffer
;
804 HELPER_FOREACH_NAL(p_nal
, hh
->hevc
.pps_list
, hh
->hevc
.i_pps_count
,
807 params
.p_pps
[params
.i_pps_count
] = p_nal
->b
->p_buffer
;
808 params
.rgi_pps
[params
.i_pps_count
++] = p_nal
->b
->i_buffer
;
811 HELPER_FOREACH_NAL(p_nal
, hh
->hevc
.sei_list
, hh
->hevc
.i_sei_count
,
814 if (hevc_getNALType(p_nal
->b
->p_buffer
) == HEVC_NAL_PREF_SEI
)
816 params
.p_seipref
[params
.i_seipref_count
] = p_nal
->b
->p_buffer
;
817 params
.rgi_seipref
[params
.i_seipref_count
++] = p_nal
->b
->i_buffer
;
821 params
.p_seisuff
[params
.i_seisuff_count
] = p_nal
->b
->p_buffer
;
822 params
.rgi_seisuff
[params
.i_seisuff_count
++] = p_nal
->b
->i_buffer
;
827 uint8_t *p_dcr
= hevc_create_dcr(¶ms
, 4, true, &i_dcr
);
831 return block_heap_Alloc(p_dcr
, i_dcr
);
834 static const struct hxxx_helper_nal
*
835 h264_helper_get_current_sps(const struct hxxx_helper
*hh
)
837 if (hh
->h264
.i_sps_count
== 0)
840 const struct hxxx_helper_nal
*hsps
=
841 &hh
->h264
.sps_list
[hh
->h264
.i_current_sps
];
842 assert(hsps
->b
!= NULL
);
847 hxxx_helper_get_current_picture_size(const struct hxxx_helper
*hh
,
848 unsigned *p_w
, unsigned *p_h
,
849 unsigned *p_vw
, unsigned *p_vh
)
851 if(hh
->i_codec
== VLC_CODEC_H264
)
853 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
854 if (hsps
&& h264_get_picture_size(hsps
->h264_sps
, p_w
, p_h
, p_vw
, p_vh
))
857 else if(hh
->i_codec
== VLC_CODEC_HEVC
)
859 const struct hxxx_helper_nal
*hsps
= &hh
->hevc
.sps_list
[hh
->hevc
.i_current_sps
];
860 if(hsps
&& hsps
->hevc_sps
&& hevc_get_picture_size(hsps
->hevc_sps
, p_w
, p_h
, p_vw
, p_vh
))
867 hxxx_helper_get_current_sar(const struct hxxx_helper
*hh
, int *p_num
, int *p_den
)
869 if(hh
->i_codec
== VLC_CODEC_H264
)
871 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
874 *p_num
= hsps
->h264_sps
->vui
.i_sar_num
;
875 *p_den
= hsps
->h264_sps
->vui
.i_sar_den
;
879 else if(hh
->i_codec
== VLC_CODEC_HEVC
)
881 const struct hxxx_helper_nal
*hsps
= &hh
->hevc
.sps_list
[hh
->hevc
.i_current_sps
];
883 if(hsps
&& hsps
->hevc_sps
&& hevc_get_aspect_ratio(hsps
->hevc_sps
, &num
, &den
))
894 h264_helper_get_current_dpb_values(const struct hxxx_helper
*hh
,
895 uint8_t *p_depth
, unsigned *p_delay
)
897 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
900 return h264_get_dpb_values(hsps
->h264_sps
, p_depth
, p_delay
) ?
901 VLC_SUCCESS
: VLC_EGENERIC
;
905 hxxx_helper_get_current_profile_level(const struct hxxx_helper
*hh
,
906 uint8_t *p_profile
, uint8_t *p_level
)
908 if(hh
->i_codec
== VLC_CODEC_H264
)
910 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
913 *p_profile
= hsps
->h264_sps
->i_profile
;
914 *p_level
= hsps
->h264_sps
->i_level
;
918 else if(hh
->i_codec
== VLC_CODEC_HEVC
)
920 const struct hxxx_helper_nal
*hsps
= &hh
->hevc
.sps_list
[hh
->hevc
.i_current_sps
];
921 if (hsps
&& hsps
->hevc_sps
&&
922 hevc_get_sps_profile_tier_level(hsps
->hevc_sps
, p_profile
, p_level
))
929 hxxx_helper_get_chroma_chroma(const struct hxxx_helper
*hh
, uint8_t *pi_chroma_format
,
930 uint8_t *pi_depth_luma
, uint8_t *pi_depth_chroma
)
936 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
939 return h264_get_chroma_luma(hsps
->h264_sps
, pi_chroma_format
, pi_depth_luma
,
941 == true ? VLC_SUCCESS
: VLC_EGENERIC
;
945 const struct hxxx_helper_nal
*hsps
= &hh
->hevc
.sps_list
[hh
->hevc
.i_current_sps
];
946 if (hsps
== NULL
|| hsps
->hevc_sps
== NULL
)
949 return hevc_get_chroma_luma(hsps
->hevc_sps
, pi_chroma_format
, pi_depth_luma
,
951 == true ? VLC_SUCCESS
: VLC_EGENERIC
;
954 vlc_assert_unreachable();
960 hxxx_helper_get_colorimetry(const struct hxxx_helper
*hh
,
961 video_color_primaries_t
*p_primaries
,
962 video_transfer_func_t
*p_transfer
,
963 video_color_space_t
*p_colorspace
,
970 const struct hxxx_helper_nal
*hsps
= h264_helper_get_current_sps(hh
);
973 return h264_get_colorimetry(hsps
->h264_sps
, p_primaries
, p_transfer
,
974 p_colorspace
, p_full_range
)
975 == true ? VLC_SUCCESS
: VLC_EGENERIC
;
979 const struct hxxx_helper_nal
*hsps
= &hh
->hevc
.sps_list
[hh
->hevc
.i_current_sps
];
980 if (hsps
== NULL
|| hsps
->hevc_sps
== NULL
)
983 return hevc_get_colorimetry(hsps
->hevc_sps
, p_primaries
, p_transfer
,
984 p_colorspace
, p_full_range
)
985 == true ? VLC_SUCCESS
: VLC_EGENERIC
;
988 vlc_assert_unreachable();