packetizer: hevc: add poc debug
[vlc.git] / modules / codec / hxxx_helper.c
blobb5ec806e0db537ca64c2d57e81d565911cf075b2
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 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <stdint.h>
26 #include <assert.h>
28 #include <vlc_common.h>
29 #include <vlc_bits.h>
31 #include "hxxx_helper.h"
32 #include "../packetizer/hxxx_nal.h"
33 #include "../packetizer/h264_slice.h"
35 void
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));
42 hh->p_obj = p_obj;
43 hh->i_codec = i_codec;
44 switch (i_codec)
46 case VLC_CODEC_H264:
47 break;
49 hh->b_need_xvcC = b_need_xvcC;
52 #define RELEASE_NALS(list, max, release) \
53 for (size_t i = 0; i <= max; ++i) \
54 { \
55 hnal = &list[i]; \
56 if (hnal->b) \
57 { \
58 block_Release(hnal->b); \
59 release; \
60 } \
63 void
64 hxxx_helper_clean(struct hxxx_helper *hh)
66 struct hxxx_helper_nal *hnal;
67 switch (hh->i_codec)
69 case VLC_CODEC_H264:
70 RELEASE_NALS(hh->h264.sps_list, H264_SPS_ID_MAX,
71 h264_release_sps(hnal->h264_sps));
72 RELEASE_NALS(hh->h264.pps_list, H264_PPS_ID_MAX,
73 h264_release_pps(hnal->h264_pps));
74 break;
75 case VLC_CODEC_HEVC:
76 RELEASE_NALS(hh->hevc.vps_list, HEVC_VPS_ID_MAX,
77 hevc_rbsp_release_vps(hnal->hevc_vps));
78 RELEASE_NALS(hh->hevc.sps_list, HEVC_SPS_ID_MAX,
79 hevc_rbsp_release_sps(hnal->hevc_sps));
80 RELEASE_NALS(hh->hevc.pps_list, HEVC_PPS_ID_MAX,
81 hevc_rbsp_release_pps(hnal->hevc_pps));
82 break;
83 default:
84 vlc_assert_unreachable();
88 #define HELPER_FOREACH_NAL(it, p_nal_list, i_nal_count, i_nal_max) \
89 for (size_t ii = 0, i_nal_nb = 0; i < i_nal_max && i_nal_count > i_nal_nb; ++ii) \
90 if (p_nal_list[ii].b != NULL && (it = &p_nal_list[ii]) && ++i_nal_nb)
92 static int
93 helper_dup_buf(struct hxxx_helper_nal *p_nal,
94 const uint8_t *p_nal_buf, size_t i_nal_buf)
96 if (!p_nal->b)
98 p_nal->b = block_Alloc(i_nal_buf);
99 if (!p_nal->b)
100 return VLC_ENOMEM;
102 else if (p_nal->b != NULL && i_nal_buf > p_nal->b->i_buffer)
104 block_t *b = block_TryRealloc(p_nal->b, 0, i_nal_buf);
105 if (b == NULL)
106 return VLC_ENOMEM;
107 p_nal->b = b;
109 memcpy(p_nal->b->p_buffer, p_nal_buf, i_nal_buf);
110 p_nal->b->i_buffer = i_nal_buf;
111 return VLC_SUCCESS;
114 static inline const struct hxxx_helper_nal *
115 helper_search_nal(const struct hxxx_helper_nal *p_nal_list, size_t i_nal_count,
116 size_t i_nal_max, const void *p_nal_buf, size_t i_nal_buf)
118 size_t i_nal_nb = 0;
119 for (size_t i = 0; i < i_nal_max && i_nal_count > i_nal_nb; ++i)
121 const struct hxxx_helper_nal *p_nal = &p_nal_list[i];
122 if (p_nal->b == NULL)
123 continue;
124 i_nal_nb++;
125 const int i_diff = i_nal_buf - p_nal->b->i_buffer;
126 if (i_diff == 0 && memcmp(p_nal_buf, p_nal->b->p_buffer, i_nal_buf) == 0)
127 return p_nal;
129 return NULL;
132 static inline bool
133 helper_nal_length_valid(struct hxxx_helper *hh)
135 return hh->i_nal_length_size == 1 || hh->i_nal_length_size == 2
136 || hh->i_nal_length_size == 4;
139 #define LOAD_xPS(list, count, id, max, xpstype, xpsdecode, xpsrelease) \
140 if (helper_search_nal(list, count, max+1, p_nal, i_nal) != NULL)\
141 continue;\
142 xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
143 if (!p_xps)\
144 return VLC_EGENERIC;\
146 struct hxxx_helper_nal *hnal = &list[id];\
147 if (helper_dup_buf(hnal, p_nal, i_nal))\
149 xpsrelease(p_xps);\
150 return VLC_EGENERIC;\
152 if (hnal->xps)\
153 xpsrelease(hnal->xps);\
154 else\
155 count++;\
157 hnal->xps = p_xps;\
158 *p_config_changed = true
160 static int
161 h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
162 uint8_t i_nal_length_size, bool *p_config_changed)
164 const uint8_t *p_nal;
165 size_t i_nal;
166 hxxx_iterator_ctx_t it;
167 hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
168 *p_config_changed = false;
170 while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
171 : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
173 if (i_nal < 2)
174 continue;
176 const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
178 if (i_nal_type == H264_NAL_SPS)
180 LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count,
181 p_xps->i_id, H264_SPS_ID_MAX,
182 h264_sequence_parameter_set_t,
183 h264_decode_sps,
184 h264_release_sps);
185 hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id;
186 msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps);
188 else if (i_nal_type == H264_NAL_PPS)
190 LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count,
191 p_xps->i_id, H264_PPS_ID_MAX,
192 h264_picture_parameter_set_t,
193 h264_decode_pps,
194 h264_release_pps);
195 msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
197 else if (i_nal_type <= H264_NAL_SLICE_IDR
198 && i_nal_type != H264_NAL_UNKNOWN)
200 if (hh->h264.i_sps_count > 1)
202 /* There is more than one SPS. Get the PPS id of the current
203 * SLICE in order to get the current SPS id */
205 /* Get the PPS id from the slice: inspirated from
206 * h264_decode_slice() */
207 bs_t s;
208 bs_init(&s, p_nal, i_nal);
209 bs_skip(&s, 8);
210 bs_read_ue(&s);
211 bs_read_ue(&s);
212 unsigned i_pps_id = bs_read_ue(&s);
213 if (i_pps_id > H264_PPS_ID_MAX)
214 return VLC_EGENERIC;
216 struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
217 if (hpps->b == NULL)
218 return VLC_EGENERIC;
220 struct hxxx_helper_nal *hsps =
221 &hh->h264.sps_list[hpps->h264_pps->i_sps_id];
222 if (hsps->b == NULL)
223 return VLC_EGENERIC;
225 assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id);
226 if (hsps->h264_sps->i_id != hh->h264.i_current_sps)
228 hh->h264.i_current_sps = hsps->h264_sps->i_id;
229 *p_config_changed = true;
232 break; /* No need to parse further NAL */
235 return VLC_SUCCESS;
238 static int
239 hevc_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
240 uint8_t i_nal_length_size, bool *p_config_changed)
242 const uint8_t *p_nal;
243 size_t i_nal;
244 hxxx_iterator_ctx_t it;
245 hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
246 *p_config_changed = false;
248 while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
249 : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
251 if (i_nal < 2 || hevc_getNALLayer(p_nal) > 0)
252 continue;
254 const uint8_t i_nal_type = hevc_getNALType(p_nal);
255 if (i_nal_type == HEVC_NAL_VPS)
257 uint8_t i_id;
258 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
259 return VLC_EGENERIC;
260 LOAD_xPS(hh->hevc.vps_list, hh->hevc.i_vps_count,
261 i_id, HEVC_VPS_ID_MAX,
262 hevc_video_parameter_set_t,
263 hevc_decode_vps,
264 hevc_rbsp_release_vps);
265 msg_Dbg(hh->p_obj, "new VPS parsed: %u", i_id);
267 else if (i_nal_type == HEVC_NAL_SPS)
269 uint8_t i_id;
270 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
271 return VLC_EGENERIC;
272 LOAD_xPS(hh->hevc.sps_list, hh->hevc.i_sps_count,
273 i_id, HEVC_SPS_ID_MAX,
274 hevc_sequence_parameter_set_t,
275 hevc_decode_sps,
276 hevc_rbsp_release_sps);
277 msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id);
279 else if (i_nal_type == HEVC_NAL_PPS)
281 uint8_t i_id;
282 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
283 return VLC_EGENERIC;
284 LOAD_xPS(hh->hevc.pps_list, hh->hevc.i_pps_count,
285 i_id, HEVC_PPS_ID_MAX,
286 hevc_picture_parameter_set_t,
287 hevc_decode_pps,
288 hevc_rbsp_release_pps);
289 msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id);
291 else if (i_nal_type <= HEVC_NAL_IRAP_VCL23)
293 if (hh->hevc.i_sps_count > 1 || hh->hevc.i_vps_count > 1)
295 /* Get the PPS id from the slice: inspirated from
296 * h264_decode_slice() */
297 bs_t s;
298 bs_init(&s, p_nal, i_nal);
299 bs_skip(&s, 2);
300 unsigned i_id = bs_read_ue(&s);
301 if (i_id > HEVC_PPS_ID_MAX)
302 return VLC_EGENERIC;
304 struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
305 if (xps->b == NULL)
306 return VLC_EGENERIC;
308 const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
309 xps = &hh->hevc.sps_list[i_spsid];
310 if (xps->b == NULL)
311 return VLC_EGENERIC;
313 i_id = hevc_get_sps_vps_id(xps->hevc_sps);
314 xps = &hh->hevc.vps_list[i_id];
316 if (i_spsid != hh->hevc.i_current_sps ||
317 i_id != hh->hevc.i_current_vps)
319 hh->hevc.i_current_sps = i_spsid;
320 hh->hevc.i_current_vps = i_id;
321 *p_config_changed = true;
324 break; /* No need to parse further NAL */
327 return VLC_SUCCESS;
330 static int
331 helper_process_avcC_h264(struct hxxx_helper *hh, const uint8_t *p_buf,
332 size_t i_buf)
334 if (i_buf < H264_MIN_AVCC_SIZE)
335 return VLC_EGENERIC;
337 p_buf += 5; i_buf -= 5;
339 for (unsigned int j = 0; j < 2 && i_buf > 0; j++)
341 /* First time is SPS, Second is PPS */
342 const unsigned int i_num_nal = p_buf[0] & (j == 0 ? 0x1f : 0xff);
343 p_buf++; i_buf--;
345 for (unsigned int i = 0; i < i_num_nal && i_buf >= 2; i++)
347 uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1];
348 if (i_nal_size > i_buf - 2)
349 return VLC_EGENERIC;
350 bool b_unused;
351 int i_ret = h264_helper_parse_nal(hh, p_buf, i_nal_size + 2, 2,
352 &b_unused);
353 if (i_ret != VLC_SUCCESS)
354 return i_ret;
355 p_buf += i_nal_size + 2;
356 i_buf -= i_nal_size + 2;
360 return VLC_SUCCESS;
363 static int
364 h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
365 size_t i_extra)
367 if (i_extra == 0)
369 /* AnnexB case */
370 hh->i_nal_length_size = 4;
371 return VLC_SUCCESS;
373 else if (h264_isavcC(p_extra, i_extra))
375 hh->i_nal_length_size = (((uint8_t*)p_extra)[4] & 0x03) + 1;
376 if (!helper_nal_length_valid(hh))
377 return VLC_EGENERIC;
378 hh->b_is_xvcC = true;
380 /* XXX h264_AVC_to_AnnexB() works only with a i_nal_length_size of 4.
381 * If nal_length_size is smaller than 4, fallback to SW decoding. I
382 * don't know if it's worth the effort to fix h264_AVC_to_AnnexB() for
383 * a smaller nal_length_size. Indeed, this case will happen only with
384 * very small resolutions, where hardware decoders are not that useful.
385 * -Thomas */
386 if (!hh->b_need_xvcC && hh->i_nal_length_size != 4)
388 msg_Dbg(hh->p_obj, "nal_length_size is too small");
389 return VLC_EGENERIC;
392 return helper_process_avcC_h264(hh, p_extra, i_extra);
394 else /* Can't handle extra that is not avcC */
395 return VLC_EGENERIC;
398 static int
399 helper_process_hvcC_hevc(struct hxxx_helper *hh, const uint8_t *p_buf,
400 size_t i_buf)
402 if (i_buf < HEVC_MIN_HVCC_SIZE)
403 return VLC_EGENERIC;
405 const uint8_t i_num_array = p_buf[22];
406 p_buf += 23; i_buf -= 23;
408 for( uint8_t i = 0; i < i_num_array; i++ )
410 if(i_buf < 3)
411 return VLC_EGENERIC;
413 const uint16_t i_num_nalu = p_buf[1] << 8 | p_buf[2];
414 p_buf += 3; i_buf -= 3;
416 for( uint16_t j = 0; j < i_num_nalu; j++ )
418 if(i_buf < 2)
419 return VLC_EGENERIC;
421 const uint16_t i_nalu_length = p_buf[0] << 8 | p_buf[1];
422 if(i_buf < (size_t)i_nalu_length + 2)
423 return VLC_EGENERIC;
425 bool foo;
426 hevc_helper_parse_nal( hh, &p_buf[0],
427 i_nalu_length + 2, 2, &foo );
429 p_buf += i_nalu_length + 2;
430 i_buf -= i_nalu_length + 2;
434 return VLC_SUCCESS;
437 static int
438 hevc_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
439 size_t i_extra)
441 if (i_extra == 0)
443 /* AnnexB case */
444 hh->i_nal_length_size = 4;
445 return VLC_SUCCESS;
447 else if (hevc_ishvcC(p_extra, i_extra))
449 hh->i_nal_length_size = hevc_getNALLengthSize(p_extra);
450 if (!helper_nal_length_valid(hh))
451 return VLC_EGENERIC;
452 hh->b_is_xvcC = true;
454 return helper_process_hvcC_hevc( hh, p_extra, i_extra );
456 else /* Can't handle extra that is not hvcC */
457 return VLC_EGENERIC;
460 static inline block_t *
461 helper_process_block_hxxx_annexb(struct hxxx_helper *hh,
462 int(*parser)(struct hxxx_helper *,
463 const uint8_t*, size_t,uint8_t,bool*),
464 block_t *p_block, bool *p_config_changed)
466 if (p_config_changed != NULL)
468 int i_ret = parser(hh, p_block->p_buffer, p_block->i_buffer,
469 0, p_config_changed);
470 if (i_ret != VLC_SUCCESS)
472 block_Release(p_block);
473 return NULL;
476 return p_block;
479 static block_t *
480 helper_process_block_h264_annexb(struct hxxx_helper *hh, block_t *p_block,
481 bool *p_config_changed)
483 if (p_config_changed != NULL)
484 return helper_process_block_hxxx_annexb(hh, h264_helper_parse_nal,
485 p_block,p_config_changed);
486 return p_block;
489 static block_t *
490 helper_process_block_hevc_annexb(struct hxxx_helper *hh, block_t *p_block,
491 bool *p_config_changed)
493 if (p_config_changed != NULL)
494 return helper_process_block_hxxx_annexb(hh, hevc_helper_parse_nal,
495 p_block,p_config_changed);
496 return p_block;
499 static block_t *
500 helper_process_block_xvcc2annexb(struct hxxx_helper *hh, block_t *p_block,
501 bool *p_config_changed)
503 assert(helper_nal_length_valid(hh));
504 h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer,
505 hh->i_nal_length_size);
506 return helper_process_block_h264_annexb(hh, p_block, p_config_changed);
509 static block_t *
510 helper_process_block_h264_annexb2avcc(struct hxxx_helper *hh, block_t *p_block,
511 bool *p_config_changed)
513 p_block = helper_process_block_h264_annexb(hh, p_block, p_config_changed);
514 return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
517 static block_t *
518 helper_process_block_hevc_annexb2hvcc(struct hxxx_helper *hh, block_t *p_block,
519 bool *p_config_changed)
521 p_block = helper_process_block_hevc_annexb(hh, p_block, p_config_changed);
522 return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
525 static block_t *
526 helper_process_block_h264_avcc(struct hxxx_helper *hh, block_t *p_block,
527 bool *p_config_changed)
529 if (p_config_changed != NULL)
531 int i_ret = h264_helper_parse_nal(hh, p_block->p_buffer,
532 p_block->i_buffer,
533 hh->i_nal_length_size,
534 p_config_changed);
535 if (i_ret != VLC_SUCCESS)
537 block_Release(p_block);
538 return NULL;
541 return p_block;
544 static block_t *
545 helper_process_block_hevc_hvcc(struct hxxx_helper *hh, block_t *p_block,
546 bool *p_config_changed)
548 if (p_config_changed != NULL)
550 int i_ret = hevc_helper_parse_nal(hh, p_block->p_buffer,
551 p_block->i_buffer,
552 hh->i_nal_length_size,
553 p_config_changed);
554 if (i_ret != VLC_SUCCESS)
556 block_Release(p_block);
557 return NULL;
560 return p_block;
564 hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
565 size_t i_extra)
567 int i_ret;
568 switch (hh->i_codec)
570 case VLC_CODEC_H264:
571 i_ret = h264_helper_set_extra(hh, p_extra, i_extra);
572 break;
573 case VLC_CODEC_HEVC:
574 i_ret = hevc_helper_set_extra(hh, p_extra, i_extra);
575 break;
576 default:
577 vlc_assert_unreachable();
579 if (i_ret != VLC_SUCCESS)
580 return i_ret;
582 switch (hh->i_codec)
584 case VLC_CODEC_H264:
585 if (hh->b_is_xvcC)
587 if (hh->b_need_xvcC)
588 hh->pf_process_block = helper_process_block_h264_avcc;
589 else
590 hh->pf_process_block = helper_process_block_xvcc2annexb;
592 else /* AnnexB */
594 if (hh->b_need_xvcC)
595 hh->pf_process_block = helper_process_block_h264_annexb2avcc;
596 else
597 hh->pf_process_block = helper_process_block_h264_annexb;
599 break;
600 case VLC_CODEC_HEVC:
601 if (hh->b_is_xvcC)
603 if (hh->b_need_xvcC)
604 hh->pf_process_block = helper_process_block_hevc_hvcc;
605 else
606 hh->pf_process_block = helper_process_block_xvcc2annexb;
608 else /* AnnexB */
610 if (hh->b_need_xvcC)
611 hh->pf_process_block = helper_process_block_hevc_annexb2hvcc;
612 else
613 hh->pf_process_block = helper_process_block_hevc_annexb;
615 break;
616 default:
617 vlc_assert_unreachable();
619 return VLC_SUCCESS;;
622 static block_t *
623 hxxx_helper_get_annexb_config( const struct hxxx_helper_nal *pp_nal_lists[],
624 const size_t p_nal_counts[],
625 const size_t p_nal_maxs[],
626 size_t i_lists_size )
628 static const uint8_t annexb_startcode[] = { 0x00, 0x00, 0x00, 0x01 };
630 block_t *p_block_list = NULL, *p_current;
631 for (size_t i = 0; i < i_lists_size; ++i)
633 size_t i_nals_size = 0;
634 const struct hxxx_helper_nal *p_nal;
635 HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
637 i_nals_size += p_nal->b->i_buffer + sizeof annexb_startcode;
640 block_t *p_block = block_Alloc(i_nals_size);
641 if (p_block == NULL)
643 if (p_block_list != NULL)
644 block_Release(p_block_list);
645 return NULL;
648 p_block->i_buffer = 0;
649 HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
651 memcpy(&p_block->p_buffer[p_block->i_buffer], annexb_startcode,
652 sizeof annexb_startcode);
653 p_block->i_buffer += sizeof annexb_startcode;
654 memcpy(&p_block->p_buffer[p_block->i_buffer], p_nal->b->p_buffer,
655 p_nal->b->i_buffer);
656 p_block->i_buffer += p_nal->b->i_buffer;
658 if (p_block_list == NULL)
659 p_current = p_block_list = p_block;
660 else
662 p_current->p_next = p_block;
663 p_current = p_block;
667 return p_block_list;
670 block_t *
671 h264_helper_get_annexb_config(const struct hxxx_helper *hh)
673 if (hh->h264.i_sps_count == 0 || hh->h264.i_pps_count == 0)
674 return NULL;
676 const struct hxxx_helper_nal *pp_nal_lists[] = {
677 hh->h264.sps_list, hh->h264.pps_list };
678 const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count };
679 const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1 };
681 return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 2 );
684 block_t *
685 hevc_helper_get_annexb_config(const struct hxxx_helper *hh)
687 if (hh->hevc.i_vps_count == 0 || hh->hevc.i_sps_count == 0 ||
688 hh->hevc.i_pps_count == 0 )
689 return NULL;
691 const struct hxxx_helper_nal *pp_nal_lists[] = {
692 hh->hevc.vps_list, hh->hevc.sps_list, hh->hevc.pps_list };
693 const size_t p_nal_counts[] = { hh->hevc.i_vps_count, hh->hevc.i_sps_count,
694 hh->hevc.i_pps_count };
695 const size_t p_nal_maxs[] = { HEVC_VPS_ID_MAX+1, HEVC_SPS_ID_MAX+1, HEVC_PPS_ID_MAX+1 };
697 return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
700 block_t *
701 h264_helper_get_avcc_config(const struct hxxx_helper *hh)
703 const struct hxxx_helper_nal *p_nal;
704 size_t i = 0;
705 const uint8_t *pp_sps_bufs[hh->h264.i_sps_count];
706 size_t p_sps_sizes[hh->h264.i_sps_count];
707 HELPER_FOREACH_NAL(p_nal, hh->h264.sps_list, hh->h264.i_sps_count,
708 H264_SPS_ID_MAX+1)
710 pp_sps_bufs[i] = p_nal->b->p_buffer;
711 p_sps_sizes[i] = p_nal->b->i_buffer;
712 ++i;
715 i = 0;
716 const uint8_t *pp_pps_bufs[hh->h264.i_pps_count];
717 size_t p_pps_sizes[hh->h264.i_pps_count];
718 HELPER_FOREACH_NAL(p_nal, hh->h264.pps_list, hh->h264.i_pps_count,
719 H264_PPS_ID_MAX+1)
721 pp_pps_bufs[i] = p_nal->b->p_buffer;
722 p_pps_sizes[i] = p_nal->b->i_buffer;
723 ++i;
725 return h264_NAL_to_avcC(4, pp_sps_bufs, p_sps_sizes, hh->h264.i_sps_count,
726 pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count);
729 block_t *
730 hevc_helper_get_hvcc_config(const struct hxxx_helper *hh)
732 struct hevc_dcr_params params = {};
733 const struct hxxx_helper_nal *p_nal;
734 size_t i = 0;
736 HELPER_FOREACH_NAL(p_nal, hh->hevc.vps_list, hh->hevc.i_vps_count,
737 HEVC_VPS_ID_MAX+1)
739 params.p_vps[params.i_vps_count] = p_nal->b->p_buffer;
740 params.rgi_vps[params.i_vps_count++] = p_nal->b->i_buffer;
741 ++i;
744 HELPER_FOREACH_NAL(p_nal, hh->hevc.sps_list, hh->hevc.i_sps_count,
745 HEVC_SPS_ID_MAX+1)
747 params.p_sps[params.i_sps_count] = p_nal->b->p_buffer;
748 params.rgi_sps[params.i_sps_count++] = p_nal->b->i_buffer;
749 ++i;
752 HELPER_FOREACH_NAL(p_nal, hh->hevc.pps_list, hh->hevc.i_pps_count,
753 HEVC_PPS_ID_MAX+1)
755 params.p_pps[params.i_pps_count] = p_nal->b->p_buffer;
756 params.rgi_pps[params.i_pps_count++] = p_nal->b->i_buffer;
757 ++i;
760 size_t i_dcr;
761 uint8_t *p_dcr = hevc_create_dcr(&params, 4, true, &i_dcr);
762 if(p_dcr == NULL)
763 return NULL;
765 return block_heap_Alloc(p_dcr, i_dcr);
768 static const struct hxxx_helper_nal *
769 h264_helper_get_current_sps(const struct hxxx_helper *hh)
771 if (hh->h264.i_sps_count == 0)
772 return NULL;
774 const struct hxxx_helper_nal *hsps =
775 &hh->h264.sps_list[hh->h264.i_current_sps];
776 assert(hsps->b != NULL);
777 return hsps;
781 hxxx_helper_get_current_picture_size(const struct hxxx_helper *hh,
782 unsigned *p_w, unsigned *p_h,
783 unsigned *p_vw, unsigned *p_vh)
785 if(hh->i_codec == VLC_CODEC_H264)
787 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
788 if (hsps && h264_get_picture_size(hsps->h264_sps, p_w, p_h, p_vw, p_vh))
789 return VLC_SUCCESS;
791 else if(hh->i_codec == VLC_CODEC_HEVC)
793 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
794 if(hsps && hevc_get_picture_size(hsps->hevc_sps, p_w, p_h, p_vw, p_vh))
795 return VLC_SUCCESS;
797 return VLC_EGENERIC;
801 hxxx_helper_get_current_sar(const struct hxxx_helper *hh, int *p_num, int *p_den)
803 if(hh->i_codec == VLC_CODEC_H264)
805 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
806 if (hsps)
808 *p_num = hsps->h264_sps->vui.i_sar_num;
809 *p_den = hsps->h264_sps->vui.i_sar_den;
810 return VLC_SUCCESS;
813 else if(hh->i_codec == VLC_CODEC_HEVC)
815 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
816 unsigned num, den;
817 if(hsps && hevc_get_aspect_ratio(hsps->hevc_sps, &num, &den))
819 *p_num = num;
820 *p_den = den;
821 return VLC_SUCCESS;
824 return VLC_EGENERIC;
828 h264_helper_get_current_dpb_values(const struct hxxx_helper *hh,
829 uint8_t *p_depth, unsigned *p_delay)
831 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
832 if (hsps == NULL)
833 return VLC_EGENERIC;
834 return h264_get_dpb_values(hsps->h264_sps, p_depth, p_delay) ?
835 VLC_SUCCESS : VLC_EGENERIC;
839 hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh,
840 uint8_t *p_profile, uint8_t *p_level)
842 if(hh->i_codec == VLC_CODEC_H264)
844 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
845 if (hsps)
847 *p_profile = hsps->h264_sps->i_profile;
848 *p_level = hsps->h264_sps->i_level;
849 return VLC_SUCCESS;
852 else if(hh->i_codec == VLC_CODEC_HEVC)
854 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
855 if (hsps &&
856 hevc_get_sps_profile_tier_level(hsps->hevc_sps, p_profile, p_level))
857 return VLC_SUCCESS;
859 return VLC_EGENERIC;
863 hxxx_helper_get_colorimetry(const struct hxxx_helper *hh,
864 video_color_primaries_t *p_primaries,
865 video_transfer_func_t *p_transfer,
866 video_color_space_t *p_colorspace,
867 bool *p_full_range)
869 switch (hh->i_codec)
871 case VLC_CODEC_H264:
873 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
874 if (hsps == NULL)
875 return VLC_EGENERIC;
876 return h264_get_colorimetry(hsps->h264_sps, p_primaries, p_transfer,
877 p_colorspace, p_full_range)
878 == true ? VLC_SUCCESS : VLC_EGENERIC;
880 case VLC_CODEC_HEVC:
882 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
883 if (hsps == NULL)
884 return VLC_EGENERIC;
886 return hevc_get_colorimetry(hsps->hevc_sps, p_primaries, p_transfer,
887 p_colorspace, p_full_range)
888 == true ? VLC_SUCCESS : VLC_EGENERIC;
890 default:
891 vlc_assert_unreachable();