demux: mp4: avoid audio cuts on seek
[vlc.git] / modules / codec / hxxx_helper.c
blobc451d052cc2ad013080fe6af8acc906930d90662
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 free(hh->hevc.p_annexb_config_nal);
83 break;
84 default:
85 vlc_assert_unreachable();
89 #define HELPER_FOREACH_NAL(it, p_nal_list, i_nal_count, i_nal_max) \
90 for (size_t ii = 0, i_nal_nb = 0; i < i_nal_max && i_nal_count > i_nal_nb; ++ii) \
91 if (p_nal_list[ii].b != NULL && (it = &p_nal_list[ii]) && ++i_nal_nb)
93 static int
94 helper_dup_buf(struct hxxx_helper_nal *p_nal,
95 const uint8_t *p_nal_buf, size_t i_nal_buf)
97 if (!p_nal->b)
99 p_nal->b = block_Alloc(i_nal_buf);
100 if (!p_nal->b)
101 return VLC_ENOMEM;
103 else if (p_nal->b != NULL && i_nal_buf > p_nal->b->i_buffer)
105 block_t *b = block_TryRealloc(p_nal->b, 0, i_nal_buf);
106 if (b == NULL)
107 return VLC_ENOMEM;
108 p_nal->b = b;
110 memcpy(p_nal->b->p_buffer, p_nal_buf, i_nal_buf);
111 p_nal->b->i_buffer = i_nal_buf;
112 return VLC_SUCCESS;
115 static inline const struct hxxx_helper_nal *
116 helper_search_nal(const struct hxxx_helper_nal *p_nal_list, size_t i_nal_count,
117 size_t i_nal_max, const void *p_nal_buf, size_t i_nal_buf)
119 size_t i_nal_nb = 0;
120 for (size_t i = 0; i < i_nal_max && i_nal_count > i_nal_nb; ++i)
122 const struct hxxx_helper_nal *p_nal = &p_nal_list[i];
123 if (p_nal->b == NULL)
124 continue;
125 i_nal_nb++;
126 const int i_diff = i_nal_buf - p_nal->b->i_buffer;
127 if (i_diff == 0 && memcmp(p_nal_buf, p_nal->b->p_buffer, i_nal_buf) == 0)
128 return p_nal;
130 return NULL;
133 static inline bool
134 helper_nal_length_valid(struct hxxx_helper *hh)
136 return hh->i_nal_length_size == 1 || hh->i_nal_length_size == 2
137 || hh->i_nal_length_size == 4;
140 #define LOAD_xPS(list, count, id, max, xpstype, xpsdecode, xpsrelease) \
141 if (helper_search_nal(list, count, max+1, p_nal, i_nal) != NULL)\
142 continue;\
143 xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
144 if (!p_xps)\
145 return VLC_EGENERIC;\
147 struct hxxx_helper_nal *hnal = &list[id];\
148 if (helper_dup_buf(hnal, p_nal, i_nal))\
150 xpsrelease(p_xps);\
151 return VLC_EGENERIC;\
153 if (hnal->xps)\
154 xpsrelease(hnal->xps);\
155 else\
156 count++;\
158 hnal->xps = p_xps;\
159 *p_config_changed = true
161 static int
162 h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
163 uint8_t i_nal_length_size, bool *p_config_changed)
165 const uint8_t *p_nal;
166 size_t i_nal;
167 hxxx_iterator_ctx_t it;
168 hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
169 *p_config_changed = false;
171 while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
172 : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
174 if (i_nal < 2)
175 continue;
177 const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
179 if (i_nal_type == H264_NAL_SPS)
181 LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count,
182 p_xps->i_id, H264_SPS_ID_MAX,
183 h264_sequence_parameter_set_t,
184 h264_decode_sps,
185 h264_release_sps);
186 hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id;
187 msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps);
189 else if (i_nal_type == H264_NAL_PPS)
191 LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count,
192 p_xps->i_id, H264_PPS_ID_MAX,
193 h264_picture_parameter_set_t,
194 h264_decode_pps,
195 h264_release_pps);
196 msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
198 else if (i_nal_type <= H264_NAL_SLICE_IDR
199 && i_nal_type != H264_NAL_UNKNOWN)
201 if (hh->h264.i_sps_count > 1)
203 /* There is more than one SPS. Get the PPS id of the current
204 * SLICE in order to get the current SPS id */
206 /* Get the PPS id from the slice: inspirated from
207 * h264_decode_slice() */
208 bs_t s;
209 bs_init(&s, p_nal, i_nal);
210 bs_skip(&s, 8);
211 bs_read_ue(&s);
212 bs_read_ue(&s);
213 unsigned i_pps_id = bs_read_ue(&s);
214 if (i_pps_id > H264_PPS_ID_MAX)
215 return VLC_EGENERIC;
217 struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
218 if (hpps->b == NULL)
219 return VLC_EGENERIC;
221 struct hxxx_helper_nal *hsps =
222 &hh->h264.sps_list[hpps->h264_pps->i_sps_id];
223 if (hsps->b == NULL)
224 return VLC_EGENERIC;
226 assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id);
227 if (hsps->h264_sps->i_id != hh->h264.i_current_sps)
229 hh->h264.i_current_sps = hsps->h264_sps->i_id;
230 *p_config_changed = true;
233 break; /* No need to parse further NAL */
236 return VLC_SUCCESS;
239 static int
240 hevc_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
241 uint8_t i_nal_length_size, bool *p_config_changed)
243 const uint8_t *p_nal;
244 size_t i_nal;
245 hxxx_iterator_ctx_t it;
246 hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
247 *p_config_changed = false;
249 while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
250 : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
252 if (i_nal < 2 || hevc_getNALLayer(p_nal) > 0)
253 continue;
255 const uint8_t i_nal_type = hevc_getNALType(p_nal);
256 if (i_nal_type == HEVC_NAL_VPS)
258 uint8_t i_id;
259 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
260 return VLC_EGENERIC;
261 LOAD_xPS(hh->hevc.vps_list, hh->hevc.i_vps_count,
262 i_id, HEVC_VPS_ID_MAX,
263 hevc_video_parameter_set_t,
264 hevc_decode_vps,
265 hevc_rbsp_release_vps);
266 msg_Dbg(hh->p_obj, "new VPS parsed: %u", i_id);
268 else if (i_nal_type == HEVC_NAL_SPS)
270 uint8_t i_id;
271 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
272 return VLC_EGENERIC;
273 LOAD_xPS(hh->hevc.sps_list, hh->hevc.i_sps_count,
274 i_id, HEVC_SPS_ID_MAX,
275 hevc_sequence_parameter_set_t,
276 hevc_decode_sps,
277 hevc_rbsp_release_sps);
278 msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id);
280 else if (i_nal_type == HEVC_NAL_PPS)
282 uint8_t i_id;
283 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
284 return VLC_EGENERIC;
285 LOAD_xPS(hh->hevc.pps_list, hh->hevc.i_pps_count,
286 i_id, HEVC_PPS_ID_MAX,
287 hevc_picture_parameter_set_t,
288 hevc_decode_pps,
289 hevc_rbsp_release_pps);
290 msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id);
292 else if (i_nal_type <= HEVC_NAL_IRAP_VCL23)
294 if (hh->hevc.i_sps_count > 1 || hh->hevc.i_vps_count > 1)
296 /* Get the PPS id from the slice: inspirated from
297 * h264_decode_slice() */
298 bs_t s;
299 bs_init(&s, p_nal, i_nal);
300 bs_skip(&s, 2);
301 unsigned i_id = bs_read_ue(&s);
302 if (i_id > HEVC_PPS_ID_MAX)
303 return VLC_EGENERIC;
305 struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
306 if (xps->b == NULL)
307 return VLC_EGENERIC;
309 const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
310 xps = &hh->hevc.sps_list[i_spsid];
311 if (xps->b == NULL)
312 return VLC_EGENERIC;
314 i_id = hevc_get_sps_vps_id(xps->hevc_sps);
315 xps = &hh->hevc.vps_list[i_id];
317 if (i_spsid != hh->hevc.i_current_sps ||
318 i_id != hh->hevc.i_current_vps)
320 hh->hevc.i_current_sps = i_spsid;
321 hh->hevc.i_current_vps = i_id;
322 *p_config_changed = true;
325 break; /* No need to parse further NAL */
328 return VLC_SUCCESS;
331 static int
332 helper_process_avcC_h264(struct hxxx_helper *hh, const uint8_t *p_buf,
333 size_t i_buf)
335 if (i_buf < H264_MIN_AVCC_SIZE)
336 return VLC_EGENERIC;
338 p_buf += 5; i_buf -= 5;
340 for (unsigned int j = 0; j < 2 && i_buf > 0; j++)
342 /* First time is SPS, Second is PPS */
343 const unsigned int i_num_nal = p_buf[0] & (j == 0 ? 0x1f : 0xff);
344 p_buf++; i_buf--;
346 for (unsigned int i = 0; i < i_num_nal && i_buf >= 2; i++)
348 uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1];
349 if (i_nal_size > i_buf - 2)
350 return VLC_EGENERIC;
351 bool b_unused;
352 int i_ret = h264_helper_parse_nal(hh, p_buf, i_nal_size + 2, 2,
353 &b_unused);
354 if (i_ret != VLC_SUCCESS)
355 return i_ret;
356 p_buf += i_nal_size + 2;
357 i_buf -= i_nal_size + 2;
361 return VLC_SUCCESS;
364 static int
365 h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
366 size_t i_extra)
368 if (i_extra == 0)
370 /* AnnexB case */
371 hh->i_nal_length_size = 4;
372 return VLC_SUCCESS;
374 else if (h264_isavcC(p_extra, i_extra))
376 hh->i_nal_length_size = (((uint8_t*)p_extra)[4] & 0x03) + 1;
377 if (!helper_nal_length_valid(hh))
378 return VLC_EGENERIC;
379 hh->b_is_xvcC = true;
381 /* XXX h264_AVC_to_AnnexB() works only with a i_nal_length_size of 4.
382 * If nal_length_size is smaller than 4, fallback to SW decoding. I
383 * don't know if it's worth the effort to fix h264_AVC_to_AnnexB() for
384 * a smaller nal_length_size. Indeed, this case will happen only with
385 * very small resolutions, where hardware decoders are not that useful.
386 * -Thomas */
387 if (!hh->b_need_xvcC && hh->i_nal_length_size != 4)
389 msg_Dbg(hh->p_obj, "nal_length_size is too small");
390 return VLC_EGENERIC;
393 return helper_process_avcC_h264(hh, p_extra, i_extra);
395 else /* Can't handle extra that is not avcC */
396 return VLC_EGENERIC;
399 static int
400 hevc_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
401 size_t i_extra)
403 if (i_extra == 0)
405 /* AnnexB case */
406 hh->i_nal_length_size = 4;
407 return VLC_SUCCESS;
409 else if (hevc_ishvcC(p_extra, i_extra))
411 hh->i_nal_length_size = hevc_getNALLengthSize(p_extra);
412 if (!helper_nal_length_valid(hh))
413 return VLC_EGENERIC;
414 hh->b_is_xvcC = true;
416 if (hh->b_need_xvcC)
417 return VLC_SUCCESS;
419 size_t i_buf;
420 uint8_t *p_buf = hevc_hvcC_to_AnnexB_NAL(p_extra, i_extra, &i_buf,
421 NULL);
422 if (!p_buf)
424 msg_Dbg(hh->p_obj, "hevc_hvcC_to_AnnexB_NAL failed");
425 return VLC_EGENERIC;
428 hh->hevc.p_annexb_config_nal = p_buf;
429 hh->hevc.i_annexb_config_nal = i_buf;
430 return VLC_SUCCESS;
432 else /* Can't handle extra that is not avcC */
433 return VLC_EGENERIC;
436 static inline block_t *
437 helper_process_block_hxxx_annexb(struct hxxx_helper *hh,
438 int(*parser)(struct hxxx_helper *,
439 const uint8_t*, size_t,uint8_t,bool*),
440 block_t *p_block, bool *p_config_changed)
442 if (p_config_changed != NULL)
444 int i_ret = parser(hh, p_block->p_buffer, p_block->i_buffer,
445 0, p_config_changed);
446 if (i_ret != VLC_SUCCESS)
448 block_Release(p_block);
449 return NULL;
452 return p_block;
455 static block_t *
456 helper_process_block_h264_annexb(struct hxxx_helper *hh, block_t *p_block,
457 bool *p_config_changed)
459 if (p_config_changed != NULL)
460 return helper_process_block_hxxx_annexb(hh, h264_helper_parse_nal,
461 p_block,p_config_changed);
462 return p_block;
465 static block_t *
466 helper_process_block_hevc_annexb(struct hxxx_helper *hh, block_t *p_block,
467 bool *p_config_changed)
469 if (p_config_changed != NULL)
470 return helper_process_block_hxxx_annexb(hh, hevc_helper_parse_nal,
471 p_block,p_config_changed);
472 return p_block;
475 static block_t *
476 helper_process_block_xvcc2annexb(struct hxxx_helper *hh, block_t *p_block,
477 bool *p_config_changed)
479 assert(helper_nal_length_valid(hh));
480 h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer,
481 hh->i_nal_length_size);
482 return helper_process_block_h264_annexb(hh, p_block, p_config_changed);
485 static block_t *
486 helper_process_block_h264_annexb2avcc(struct hxxx_helper *hh, block_t *p_block,
487 bool *p_config_changed)
489 p_block = helper_process_block_h264_annexb(hh, p_block, p_config_changed);
490 return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
493 static block_t *
494 helper_process_block_hevc_annexb2hvcc(struct hxxx_helper *hh, block_t *p_block,
495 bool *p_config_changed)
497 p_block = helper_process_block_hevc_annexb(hh, p_block, p_config_changed);
498 return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
501 static block_t *
502 helper_process_block_h264_avcc(struct hxxx_helper *hh, block_t *p_block,
503 bool *p_config_changed)
505 if (p_config_changed != NULL)
507 int i_ret = h264_helper_parse_nal(hh, p_block->p_buffer,
508 p_block->i_buffer,
509 hh->i_nal_length_size,
510 p_config_changed);
511 if (i_ret != VLC_SUCCESS)
513 block_Release(p_block);
514 return NULL;
517 return p_block;
520 static block_t *
521 helper_process_block_hevc_hvcc(struct hxxx_helper *hh, block_t *p_block,
522 bool *p_config_changed)
524 if (p_config_changed != NULL)
526 int i_ret = hevc_helper_parse_nal(hh, p_block->p_buffer,
527 p_block->i_buffer,
528 hh->i_nal_length_size,
529 p_config_changed);
530 if (i_ret != VLC_SUCCESS)
532 block_Release(p_block);
533 return NULL;
536 return p_block;
540 hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
541 size_t i_extra)
543 int i_ret;
544 switch (hh->i_codec)
546 case VLC_CODEC_H264:
547 i_ret = h264_helper_set_extra(hh, p_extra, i_extra);
548 break;
549 case VLC_CODEC_HEVC:
550 i_ret = hevc_helper_set_extra(hh, p_extra, i_extra);
551 break;
552 default:
553 vlc_assert_unreachable();
555 if (i_ret != VLC_SUCCESS)
556 return i_ret;
558 switch (hh->i_codec)
560 case VLC_CODEC_H264:
561 if (hh->b_is_xvcC)
563 if (hh->b_need_xvcC)
564 hh->pf_process_block = helper_process_block_h264_avcc;
565 else
566 hh->pf_process_block = helper_process_block_xvcc2annexb;
568 else /* AnnexB */
570 if (hh->b_need_xvcC)
571 hh->pf_process_block = helper_process_block_h264_annexb2avcc;
572 else
573 hh->pf_process_block = helper_process_block_h264_annexb;
575 break;
576 case VLC_CODEC_HEVC:
577 if (hh->b_is_xvcC)
579 if (hh->b_need_xvcC)
580 hh->pf_process_block = helper_process_block_hevc_hvcc;
581 else
582 hh->pf_process_block = helper_process_block_xvcc2annexb;
584 else /* AnnexB */
586 if (hh->b_need_xvcC)
587 hh->pf_process_block = helper_process_block_hevc_annexb2hvcc;
588 else
589 hh->pf_process_block = helper_process_block_hevc_annexb;
591 break;
592 default:
593 vlc_assert_unreachable();
595 return VLC_SUCCESS;;
598 block_t *
599 h264_helper_get_annexb_config(const struct hxxx_helper *hh)
601 static const uint8_t annexb_startcode[] = { 0x00, 0x00, 0x00, 0x01 };
603 if (hh->h264.i_sps_count == 0 || hh->h264.i_pps_count == 0)
604 return NULL;
606 const struct hxxx_helper_nal *pp_nal_lists[] = {
607 hh->h264.sps_list, hh->h264.pps_list };
608 const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count };
609 const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1 };
611 block_t *p_block_list = NULL;
612 for (size_t i = 0; i < 2; ++i)
614 size_t i_nals_size = 0;
615 const struct hxxx_helper_nal *p_nal;
616 HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
618 i_nals_size += p_nal->b->i_buffer + sizeof annexb_startcode;
621 block_t *p_block = block_Alloc(i_nals_size);
622 if (p_block == NULL)
624 if (p_block_list != NULL)
625 block_Release(p_block_list);
626 return NULL;
629 p_block->i_buffer = 0;
630 HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
632 memcpy(&p_block->p_buffer[p_block->i_buffer], annexb_startcode,
633 sizeof annexb_startcode);
634 p_block->i_buffer += sizeof annexb_startcode;
635 memcpy(&p_block->p_buffer[p_block->i_buffer], p_nal->b->p_buffer,
636 p_nal->b->i_buffer);
637 p_block->i_buffer += p_nal->b->i_buffer;
639 if (p_block_list == NULL)
640 p_block_list = p_block;
641 else
642 p_block_list->p_next = p_block;
645 return p_block_list;
648 block_t *
649 h264_helper_get_avcc_config(const struct hxxx_helper *hh)
651 const struct hxxx_helper_nal *p_nal;
652 size_t i = 0;
653 const uint8_t *pp_sps_bufs[hh->h264.i_sps_count];
654 size_t p_sps_sizes[hh->h264.i_sps_count];
655 HELPER_FOREACH_NAL(p_nal, hh->h264.sps_list, hh->h264.i_sps_count,
656 H264_SPS_ID_MAX+1)
658 pp_sps_bufs[i] = p_nal->b->p_buffer;
659 p_sps_sizes[i] = p_nal->b->i_buffer;
660 ++i;
663 i = 0;
664 const uint8_t *pp_pps_bufs[hh->h264.i_pps_count];
665 size_t p_pps_sizes[hh->h264.i_pps_count];
666 HELPER_FOREACH_NAL(p_nal, hh->h264.pps_list, hh->h264.i_pps_count,
667 H264_PPS_ID_MAX+1)
669 pp_pps_bufs[i] = p_nal->b->p_buffer;
670 p_pps_sizes[i] = p_nal->b->i_buffer;
671 ++i;
673 return h264_NAL_to_avcC(4, pp_sps_bufs, p_sps_sizes, hh->h264.i_sps_count,
674 pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count);
677 static const struct hxxx_helper_nal *
678 h264_helper_get_current_sps(const struct hxxx_helper *hh)
680 if (hh->h264.i_sps_count == 0)
681 return NULL;
683 const struct hxxx_helper_nal *hsps =
684 &hh->h264.sps_list[hh->h264.i_current_sps];
685 assert(hsps->b != NULL);
686 return hsps;
690 hxxx_helper_get_current_picture_size(const struct hxxx_helper *hh,
691 unsigned *p_w, unsigned *p_h,
692 unsigned *p_vw, unsigned *p_vh)
694 if(hh->i_codec == VLC_CODEC_H264)
696 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
697 if (hsps && h264_get_picture_size(hsps->h264_sps, p_w, p_h, p_vw, p_vh))
698 return VLC_SUCCESS;
700 else if(hh->i_codec == VLC_CODEC_HEVC)
702 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
703 if(hsps && hevc_get_picture_size(hsps->hevc_sps, p_w, p_h, p_vw, p_vh))
704 return VLC_SUCCESS;
706 return VLC_EGENERIC;
710 hxxx_helper_get_current_sar(const struct hxxx_helper *hh, int *p_num, int *p_den)
712 if(hh->i_codec == VLC_CODEC_H264)
714 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
715 if (hsps)
717 *p_num = hsps->h264_sps->vui.i_sar_num;
718 *p_den = hsps->h264_sps->vui.i_sar_den;
719 return VLC_SUCCESS;
722 else if(hh->i_codec == VLC_CODEC_HEVC)
724 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
725 unsigned num, den;
726 if(hsps && hevc_get_aspect_ratio(hsps->hevc_sps, &num, &den))
728 *p_num = num;
729 *p_den = den;
730 return VLC_SUCCESS;
733 return VLC_EGENERIC;
737 h264_helper_get_current_dpb_values(const struct hxxx_helper *hh,
738 uint8_t *p_depth, unsigned *p_delay)
740 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
741 if (hsps == NULL)
742 return VLC_EGENERIC;
743 return h264_get_dpb_values(hsps->h264_sps, p_depth, p_delay) ?
744 VLC_SUCCESS : VLC_EGENERIC;
748 hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh,
749 uint8_t *p_profile, uint8_t *p_level)
751 if(hh->i_codec == VLC_CODEC_H264)
753 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
754 if (hsps)
756 *p_profile = hsps->h264_sps->i_profile;
757 *p_level = hsps->h264_sps->i_level;
758 return VLC_SUCCESS;
761 else if(hh->i_codec == VLC_CODEC_HEVC)
763 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
764 if (hsps &&
765 hevc_get_sps_profile_tier_level(hsps->hevc_sps, p_profile, p_level))
766 return VLC_SUCCESS;
768 return VLC_EGENERIC;
772 hxxx_helper_get_colorimetry(const struct hxxx_helper *hh,
773 video_color_primaries_t *p_primaries,
774 video_transfer_func_t *p_transfer,
775 video_color_space_t *p_colorspace,
776 bool *p_full_range)
778 switch (hh->i_codec)
780 case VLC_CODEC_H264:
782 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
783 if (hsps == NULL)
784 return VLC_EGENERIC;
785 return h264_get_colorimetry(hsps->h264_sps, p_primaries, p_transfer,
786 p_colorspace, p_full_range)
787 == true ? VLC_SUCCESS : VLC_EGENERIC;
789 case VLC_CODEC_HEVC:
790 /* FIXME */
791 return VLC_EGENERIC;
792 default:
793 vlc_assert_unreachable();