input: add an input_item_t arg to input_CreateFilename()
[vlc.git] / modules / codec / hxxx_helper.c
blobc8e4b0a1b92ad417886f98cf94b309b45ebc2273
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 hh->b_need_xvcC = b_need_xvcC;
47 #define RELEASE_NALS(list, max, release) \
48 for (size_t i = 0; i <= max; ++i) \
49 { \
50 hnal = &list[i]; \
51 if (hnal->b) \
52 { \
53 block_Release(hnal->b); \
54 release; \
55 } \
58 static void
59 helper_clear_sei(struct hxxx_helper *hh)
61 if (hh->i_codec != VLC_CODEC_HEVC)
62 return;
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;
75 void
76 hxxx_helper_clean(struct hxxx_helper *hh)
78 struct hxxx_helper_nal *hnal;
79 switch (hh->i_codec)
81 case VLC_CODEC_H264:
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));
87 break;
88 case VLC_CODEC_HEVC:
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));
95 helper_clear_sei(hh);
96 memset(&hh->hevc, 0, sizeof(hh->hevc));
97 break;
98 default:
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)
107 static int
108 helper_dup_buf(struct hxxx_helper_nal *p_nal,
109 const uint8_t *p_nal_buf, size_t i_nal_buf)
111 if (!p_nal->b)
113 p_nal->b = block_Alloc(i_nal_buf);
114 if (!p_nal->b)
115 return VLC_ENOMEM;
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);
120 if (b == NULL)
121 return VLC_ENOMEM;
122 p_nal->b = b;
124 memcpy(p_nal->b->p_buffer, p_nal_buf, i_nal_buf);
125 p_nal->b->i_buffer = i_nal_buf;
126 return VLC_SUCCESS;
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)
133 size_t i_nal_nb = 0;
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)
138 continue;
139 i_nal_nb++;
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)
142 return p_nal;
144 return NULL;
147 static inline bool
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;
154 static void
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)
158 return;
160 if(hh->hevc.i_sei_count == HXXX_HELPER_SEI_COUNT)
161 return;
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))
165 return;
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)\
171 continue;\
172 xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
173 if (!p_xps)\
174 return VLC_EGENERIC;\
176 struct hxxx_helper_nal *hnal = &list[id];\
177 if (helper_dup_buf(hnal, p_nal, i_nal))\
179 xpsrelease(p_xps);\
180 return VLC_EGENERIC;\
182 if (hnal->xps)\
183 xpsrelease(hnal->xps);\
184 else\
185 count++;\
187 hnal->xps = p_xps;\
188 *p_config_changed = true
190 static int
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;
195 size_t i_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))
203 if (i_nal < 2)
204 continue;
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,
213 h264_decode_sps,
214 h264_release_sps);
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,
223 h264_decode_pps,
224 h264_release_pps);
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() */
237 bs_t s;
238 bs_init(&s, p_nal, i_nal);
239 bs_skip(&s, 8);
240 bs_read_ue(&s);
241 bs_read_ue(&s);
242 unsigned i_pps_id = bs_read_ue(&s);
243 if (i_pps_id > H264_PPS_ID_MAX)
244 return VLC_EGENERIC;
246 struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
247 if (hpps->b == NULL)
248 return VLC_EGENERIC;
250 struct hxxx_helper_nal *hsps =
251 &hh->h264.sps_list[hpps->h264_pps->i_sps_id];
252 if (hsps->b == NULL)
253 return VLC_EGENERIC;
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 */
265 return VLC_SUCCESS;
268 static void
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;
279 static int
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;
284 size_t i_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)
293 continue;
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)
302 uint8_t i_id;
303 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
304 return VLC_EGENERIC;
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,
308 hevc_decode_vps,
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)
314 uint8_t i_id;
315 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
316 return VLC_EGENERIC;
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,
320 hevc_decode_sps,
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)
326 uint8_t i_id;
327 if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
328 return VLC_EGENERIC;
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,
332 hevc_decode_pps,
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() */
342 bs_t s;
343 bs_init(&s, p_nal, i_nal);
344 bs_skip(&s, 2);
345 unsigned i_id = bs_read_ue(&s);
346 if (i_id > HEVC_PPS_ID_MAX)
347 return VLC_EGENERIC;
349 struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
350 if (xps->b == NULL)
351 return VLC_EGENERIC;
353 const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
354 xps = &hh->hevc.sps_list[i_spsid];
355 if (xps->b == NULL)
356 return VLC_EGENERIC;
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);
377 return VLC_SUCCESS;
380 static int
381 helper_process_avcC_h264(struct hxxx_helper *hh, const uint8_t *p_buf,
382 size_t i_buf)
384 if (i_buf < H264_MIN_AVCC_SIZE)
385 return VLC_EGENERIC;
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);
393 p_buf++; i_buf--;
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)
399 return VLC_EGENERIC;
400 bool b_unused;
401 int i_ret = h264_helper_parse_nal(hh, p_buf, i_nal_size + 2, 2,
402 &b_unused);
403 if (i_ret != VLC_SUCCESS)
404 return i_ret;
405 p_buf += i_nal_size + 2;
406 i_buf -= i_nal_size + 2;
410 return VLC_SUCCESS;
413 static bool
414 hxxx_extra_isannexb(const void *p_extra, size_t i_extra)
416 return i_extra == 0
417 || (i_extra > 4 && memcmp(p_extra, annexb_startcode4, 4) == 0);
420 static int
421 h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
422 size_t i_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))
428 return VLC_EGENERIC;
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.
436 * -Thomas */
437 if (!hh->b_need_xvcC && hh->i_nal_length_size != 4)
439 msg_Dbg(hh->p_obj, "nal_length_size is too small");
440 return VLC_EGENERIC;
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;
448 bool unused;
449 return i_extra == 0 ? VLC_SUCCESS :
450 h264_helper_parse_nal(hh, p_extra, i_extra, 0, &unused);
452 else
453 return VLC_EGENERIC;
456 static int
457 helper_process_hvcC_hevc(struct hxxx_helper *hh, const uint8_t *p_buf,
458 size_t i_buf)
460 if (i_buf < HEVC_MIN_HVCC_SIZE)
461 return VLC_EGENERIC;
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++ )
468 if(i_buf < 3)
469 return VLC_EGENERIC;
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++ )
476 if(i_buf < 2)
477 return VLC_EGENERIC;
479 const uint16_t i_nalu_length = p_buf[0] << 8 | p_buf[1];
480 if(i_buf < (size_t)i_nalu_length + 2)
481 return VLC_EGENERIC;
483 bool foo;
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;
492 return VLC_SUCCESS;
495 static int
496 hevc_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
497 size_t i_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))
503 return VLC_EGENERIC;
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;
511 bool unused;
512 return i_extra == 0 ? VLC_SUCCESS :
513 hevc_helper_parse_nal(hh, p_extra, i_extra, 0, &unused);
515 else
516 return VLC_EGENERIC;
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);
532 return NULL;
535 return p_block;
538 static block_t *
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);
545 return p_block;
548 static block_t *
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);
555 return p_block;
558 static block_t *
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);
568 static block_t *
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;
576 static block_t *
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;
584 static block_t *
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,
591 p_block->i_buffer,
592 hh->i_nal_length_size,
593 p_config_changed);
594 if (i_ret != VLC_SUCCESS)
596 block_Release(p_block);
597 return NULL;
600 return p_block;
603 static block_t *
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,
610 p_block->i_buffer,
611 hh->i_nal_length_size,
612 p_config_changed);
613 if (i_ret != VLC_SUCCESS)
615 block_Release(p_block);
616 return NULL;
619 return p_block;
623 hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
624 size_t i_extra)
626 int i_ret;
627 switch (hh->i_codec)
629 case VLC_CODEC_H264:
630 i_ret = h264_helper_set_extra(hh, p_extra, i_extra);
631 break;
632 case VLC_CODEC_HEVC:
633 i_ret = hevc_helper_set_extra(hh, p_extra, i_extra);
634 break;
635 default:
636 vlc_assert_unreachable();
638 if (i_ret != VLC_SUCCESS)
639 return i_ret;
641 switch (hh->i_codec)
643 case VLC_CODEC_H264:
644 if (hh->b_is_xvcC)
646 if (hh->b_need_xvcC)
647 hh->pf_process_block = helper_process_block_h264_avcc;
648 else
649 hh->pf_process_block = helper_process_block_xvcc2annexb;
651 else /* AnnexB */
653 if (hh->b_need_xvcC)
654 hh->pf_process_block = helper_process_block_h264_annexb2avcc;
655 else
656 hh->pf_process_block = helper_process_block_h264_annexb;
658 break;
659 case VLC_CODEC_HEVC:
660 if (hh->b_is_xvcC)
662 if (hh->b_need_xvcC)
663 hh->pf_process_block = helper_process_block_hevc_hvcc;
664 else
665 hh->pf_process_block = helper_process_block_xvcc2annexb;
667 else /* AnnexB */
669 if (hh->b_need_xvcC)
670 hh->pf_process_block = helper_process_block_hevc_annexb2hvcc;
671 else
672 hh->pf_process_block = helper_process_block_hevc_annexb;
674 break;
675 default:
676 vlc_assert_unreachable();
678 return VLC_SUCCESS;;
681 static block_t *
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);
700 if (p_block == NULL)
702 if (p_block_list != NULL)
703 block_Release(p_block_list);
704 return NULL;
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,
714 p_nal->b->i_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;
719 else
721 p_current->p_next = p_block;
722 p_current = p_block;
726 return p_block_list;
729 block_t *
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)
733 return NULL;
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 );
743 block_t *
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 )
748 return NULL;
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 );
759 block_t *
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,
766 H264_SPS_ID_MAX+1)
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,
775 H264_PPS_ID_MAX+1)
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);
784 block_t *
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,
791 HEVC_VPS_ID_MAX+1)
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,
798 HEVC_SPS_ID_MAX+1)
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,
805 HEVC_PPS_ID_MAX+1)
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,
812 HEVC_DCR_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;
819 else
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;
826 size_t i_dcr;
827 uint8_t *p_dcr = hevc_create_dcr(&params, 4, true, &i_dcr);
828 if(p_dcr == NULL)
829 return NULL;
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)
838 return NULL;
840 const struct hxxx_helper_nal *hsps =
841 &hh->h264.sps_list[hh->h264.i_current_sps];
842 assert(hsps->b != NULL);
843 return hsps;
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))
855 return VLC_SUCCESS;
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))
861 return VLC_SUCCESS;
863 return VLC_EGENERIC;
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);
872 if (hsps)
874 *p_num = hsps->h264_sps->vui.i_sar_num;
875 *p_den = hsps->h264_sps->vui.i_sar_den;
876 return VLC_SUCCESS;
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];
882 unsigned num, den;
883 if(hsps && hsps->hevc_sps && hevc_get_aspect_ratio(hsps->hevc_sps, &num, &den))
885 *p_num = num;
886 *p_den = den;
887 return VLC_SUCCESS;
890 return VLC_EGENERIC;
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);
898 if (hsps == NULL)
899 return VLC_EGENERIC;
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);
911 if (hsps)
913 *p_profile = hsps->h264_sps->i_profile;
914 *p_level = hsps->h264_sps->i_level;
915 return VLC_SUCCESS;
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))
923 return VLC_SUCCESS;
925 return VLC_EGENERIC;
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)
932 switch (hh->i_codec)
934 case VLC_CODEC_H264:
936 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
937 if (hsps == NULL)
938 return VLC_EGENERIC;
939 return h264_get_chroma_luma(hsps->h264_sps, pi_chroma_format, pi_depth_luma,
940 pi_depth_chroma)
941 == true ? VLC_SUCCESS : VLC_EGENERIC;
943 case VLC_CODEC_HEVC:
945 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
946 if (hsps == NULL || hsps->hevc_sps == NULL)
947 return VLC_EGENERIC;
949 return hevc_get_chroma_luma(hsps->hevc_sps, pi_chroma_format, pi_depth_luma,
950 pi_depth_chroma)
951 == true ? VLC_SUCCESS : VLC_EGENERIC;
953 default:
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,
964 bool *p_full_range)
966 switch (hh->i_codec)
968 case VLC_CODEC_H264:
970 const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
971 if (hsps == NULL)
972 return VLC_EGENERIC;
973 return h264_get_colorimetry(hsps->h264_sps, p_primaries, p_transfer,
974 p_colorspace, p_full_range)
975 == true ? VLC_SUCCESS : VLC_EGENERIC;
977 case VLC_CODEC_HEVC:
979 const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
980 if (hsps == NULL || hsps->hevc_sps == NULL)
981 return VLC_EGENERIC;
983 return hevc_get_colorimetry(hsps->hevc_sps, p_primaries, p_transfer,
984 p_colorspace, p_full_range)
985 == true ? VLC_SUCCESS : VLC_EGENERIC;
987 default:
988 vlc_assert_unreachable();