270b490090b175c6b4a8db56390d61ed5da8ee49
[vlc.git] / modules / codec / hxxx_helper.c
1 /*****************************************************************************
2  * hxxx_helper.c: AnnexB / avcC helper for dumb decoders
3  *****************************************************************************
4  * Copyright (C) 2017 VLC authors and VideoLAN
5  *
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.
10  *
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.
15  *
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  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <stdint.h>
26 #include <assert.h>
27
28 #include <vlc_common.h>
29 #include <vlc_bits.h>
30
31 #include "hxxx_helper.h"
32 #include "../packetizer/hxxx_nal.h"
33 #include "../packetizer/h264_slice.h"
34
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)
38 {
39     assert(i_codec == VLC_CODEC_H264 || i_codec == VLC_CODEC_HEVC);
40
41     memset(hh, 0, sizeof(struct hxxx_helper));
42     hh->p_obj = p_obj;
43     hh->i_codec = i_codec;
44     switch (i_codec)
45     {
46         case VLC_CODEC_H264:
47             break;
48     }
49     hh->b_need_xvcC = b_need_xvcC;
50 }
51
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         } \
61     }
62
63 static void
64 helper_clear_sei(struct hxxx_helper *hh)
65 {
66     if (hh->i_codec != VLC_CODEC_HEVC)
67         return;
68
69     for (uint8_t i=0; i<hh->hevc.i_sei_count; i++)
70     {
71         if(hh->hevc.sei_list[i].b)
72         {
73             block_Release(hh->hevc.sei_list[i].b);
74             hh->hevc.sei_list[i].b = NULL;
75         }
76     }
77     hh->hevc.i_sei_count = 0;
78 }
79
80 void
81 hxxx_helper_clean(struct hxxx_helper *hh)
82 {
83     struct hxxx_helper_nal *hnal;
84     switch (hh->i_codec)
85     {
86         case VLC_CODEC_H264:
87             RELEASE_NALS(hh->h264.sps_list, H264_SPS_ID_MAX,
88                          h264_release_sps(hnal->h264_sps));
89             RELEASE_NALS(hh->h264.pps_list, H264_PPS_ID_MAX,
90                          h264_release_pps(hnal->h264_pps));
91             memset(&hh->h264, 0, sizeof(hh->h264));
92             break;
93         case VLC_CODEC_HEVC:
94             RELEASE_NALS(hh->hevc.vps_list, HEVC_VPS_ID_MAX,
95                          hevc_rbsp_release_vps(hnal->hevc_vps));
96             RELEASE_NALS(hh->hevc.sps_list, HEVC_SPS_ID_MAX,
97                          hevc_rbsp_release_sps(hnal->hevc_sps));
98             RELEASE_NALS(hh->hevc.pps_list, HEVC_PPS_ID_MAX,
99                          hevc_rbsp_release_pps(hnal->hevc_pps));
100             helper_clear_sei(hh);
101             memset(&hh->hevc, 0, sizeof(hh->hevc));
102             break;
103         default:
104             vlc_assert_unreachable();
105     }
106 }
107
108 #define HELPER_FOREACH_NAL(it, p_nal_list, i_nal_count, i_nal_max) \
109     for (size_t ii = 0, i_nal_found = 0; ii < i_nal_max && i_nal_count > i_nal_found; ++ii) \
110         if (p_nal_list[ii].b != NULL && (it = &p_nal_list[ii]) && ++i_nal_found)
111
112 static int
113 helper_dup_buf(struct hxxx_helper_nal *p_nal,
114                const uint8_t *p_nal_buf, size_t i_nal_buf)
115 {
116     if (!p_nal->b)
117     {
118         p_nal->b = block_Alloc(i_nal_buf);
119         if (!p_nal->b)
120             return VLC_ENOMEM;
121     }
122     else if (p_nal->b != NULL && i_nal_buf > p_nal->b->i_buffer)
123     {
124         block_t *b = block_TryRealloc(p_nal->b, 0, i_nal_buf);
125         if (b == NULL)
126             return VLC_ENOMEM;
127         p_nal->b = b;
128     }
129     memcpy(p_nal->b->p_buffer, p_nal_buf, i_nal_buf);
130     p_nal->b->i_buffer = i_nal_buf;
131     return VLC_SUCCESS;
132 }
133
134 static inline const struct hxxx_helper_nal *
135 helper_search_nal(const struct hxxx_helper_nal *p_nal_list, size_t i_nal_count,
136                   size_t i_nal_max, const void *p_nal_buf, size_t i_nal_buf)
137 {
138     size_t i_nal_nb = 0;
139     for (size_t i = 0; i < i_nal_max && i_nal_count > i_nal_nb; ++i)
140     {
141         const struct hxxx_helper_nal *p_nal = &p_nal_list[i];
142         if (p_nal->b == NULL)
143             continue;
144         i_nal_nb++;
145         const int i_diff = i_nal_buf - p_nal->b->i_buffer;
146         if (i_diff == 0 && memcmp(p_nal_buf, p_nal->b->p_buffer, i_nal_buf) == 0)
147             return p_nal;
148     }
149     return NULL;
150 }
151
152 static inline bool
153 helper_nal_length_valid(struct hxxx_helper *hh)
154 {
155     return hh->i_nal_length_size == 1 || hh->i_nal_length_size == 2
156         || hh->i_nal_length_size == 4;
157 }
158
159 static void
160 helper_load_sei(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal)
161 {
162     if(hh->i_codec != VLC_CODEC_HEVC)
163         return;
164
165     if(hh->hevc.i_sei_count == HXXX_HELPER_SEI_COUNT)
166         return;
167
168     struct hxxx_helper_nal *hnal = &hh->hevc.sei_list[hh->hevc.i_sei_count];
169     if (helper_dup_buf(hnal, p_nal, i_nal))
170         return;
171     hh->hevc.i_sei_count++;
172 }
173
174 #define LOAD_xPS(list, count, id, max, xpstype, xpsdecode, xpsrelease) \
175     if (helper_search_nal(list, count, max+1, p_nal, i_nal) != NULL)\
176         continue;\
177     xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
178     if (!p_xps)\
179         return VLC_EGENERIC;\
180 \
181     struct hxxx_helper_nal *hnal = &list[id];\
182     if (helper_dup_buf(hnal, p_nal, i_nal))\
183     {\
184         xpsrelease(p_xps);\
185         return VLC_EGENERIC;\
186     }\
187     if (hnal->xps)\
188         xpsrelease(hnal->xps);\
189     else\
190         count++;\
191 \
192     hnal->xps = p_xps;\
193     *p_config_changed = true
194
195 static int
196 h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
197                       uint8_t i_nal_length_size, bool *p_config_changed)
198 {
199     const uint8_t *p_nal;
200     size_t i_nal;
201     hxxx_iterator_ctx_t it;
202     hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
203     *p_config_changed = false;
204
205     while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
206                                : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
207     {
208         if (i_nal < 2)
209             continue;
210
211         const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
212
213         if (i_nal_type == H264_NAL_SPS)
214         {
215             LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count,
216                      p_xps->i_id, H264_SPS_ID_MAX,
217                      h264_sequence_parameter_set_t,
218                      h264_decode_sps,
219                      h264_release_sps);
220             hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id;
221             msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps);
222         }
223         else if (i_nal_type == H264_NAL_PPS)
224         {
225             LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count,
226                      p_xps->i_id, H264_PPS_ID_MAX,
227                      h264_picture_parameter_set_t,
228                      h264_decode_pps,
229                      h264_release_pps);
230             msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
231         }
232         else if (i_nal_type <= H264_NAL_SLICE_IDR
233               && i_nal_type != H264_NAL_UNKNOWN)
234         {
235             if (hh->h264.i_sps_count > 1)
236             {
237                 /* There is more than one SPS. Get the PPS id of the current
238                  * SLICE in order to get the current SPS id */
239
240                 /* Get the PPS id from the slice: inspirated from
241                  * h264_decode_slice() */
242                 bs_t s;
243                 bs_init(&s, p_nal, i_nal);
244                 bs_skip(&s, 8);
245                 bs_read_ue(&s);
246                 bs_read_ue(&s);
247                 unsigned i_pps_id = bs_read_ue(&s);
248                 if (i_pps_id > H264_PPS_ID_MAX)
249                     return VLC_EGENERIC;
250
251                 struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
252                 if (hpps->b == NULL)
253                     return VLC_EGENERIC;
254
255                 struct hxxx_helper_nal *hsps =
256                     &hh->h264.sps_list[hpps->h264_pps->i_sps_id];
257                 if (hsps->b == NULL)
258                     return VLC_EGENERIC;
259
260                 assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id);
261                 if (hsps->h264_sps->i_id != hh->h264.i_current_sps)
262                 {
263                     hh->h264.i_current_sps = hsps->h264_sps->i_id;
264                     *p_config_changed = true;
265                 }
266             }
267             break; /* No need to parse further NAL */
268         }
269     }
270     return VLC_SUCCESS;
271 }
272
273 static void
274 helper_check_sei_au(struct hxxx_helper *hh, uint8_t i_nal_type)
275 {
276     if ((i_nal_type <= HEVC_NAL_IRAP_VCL23 &&
277          hh->hevc.i_previous_nal_type != HEVC_NAL_PREF_SEI) ||
278         (i_nal_type == HEVC_NAL_PREF_SEI &&
279          hh->hevc.i_previous_nal_type != HEVC_NAL_PREF_SEI))
280         helper_clear_sei(hh);
281     hh->hevc.i_previous_nal_type = i_nal_type;
282 }
283
284 static int
285 hevc_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
286                       uint8_t i_nal_length_size, bool *p_config_changed)
287 {
288     const uint8_t *p_nal;
289     size_t i_nal;
290     hxxx_iterator_ctx_t it;
291     hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
292     *p_config_changed = false;
293
294     while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
295                                : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
296     {
297         if (i_nal < 2 || hevc_getNALLayer(p_nal) > 0)
298             continue;
299
300         const uint8_t i_nal_type = hevc_getNALType(p_nal);
301
302         /* we need to clear sei not belonging to this access unit */
303         helper_check_sei_au(hh, i_nal_type);
304
305         if (i_nal_type == HEVC_NAL_VPS)
306         {
307             uint8_t i_id;
308             if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
309                 return VLC_EGENERIC;
310             LOAD_xPS(hh->hevc.vps_list, hh->hevc.i_vps_count,
311                      i_id, HEVC_VPS_ID_MAX,
312                      hevc_video_parameter_set_t,
313                      hevc_decode_vps,
314                      hevc_rbsp_release_vps);
315             msg_Dbg(hh->p_obj, "new VPS parsed: %u", i_id);
316         }
317         else if (i_nal_type == HEVC_NAL_SPS)
318         {
319             uint8_t i_id;
320             if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
321                 return VLC_EGENERIC;
322             LOAD_xPS(hh->hevc.sps_list, hh->hevc.i_sps_count,
323                      i_id, HEVC_SPS_ID_MAX,
324                      hevc_sequence_parameter_set_t,
325                      hevc_decode_sps,
326                      hevc_rbsp_release_sps);
327             msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id);
328         }
329         else if (i_nal_type == HEVC_NAL_PPS)
330         {
331             uint8_t i_id;
332             if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
333                 return VLC_EGENERIC;
334             LOAD_xPS(hh->hevc.pps_list, hh->hevc.i_pps_count,
335                      i_id, HEVC_PPS_ID_MAX,
336                      hevc_picture_parameter_set_t,
337                      hevc_decode_pps,
338                      hevc_rbsp_release_pps);
339             msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id);
340         }
341         else if (i_nal_type <= HEVC_NAL_IRAP_VCL23)
342         {
343             if (hh->hevc.i_sps_count > 1 || hh->hevc.i_vps_count > 1)
344             {
345                 /* Get the PPS id from the slice: inspirated from
346                  * h264_decode_slice() */
347                 bs_t s;
348                 bs_init(&s, p_nal, i_nal);
349                 bs_skip(&s, 2);
350                 unsigned i_id = bs_read_ue(&s);
351                 if (i_id > HEVC_PPS_ID_MAX)
352                     return VLC_EGENERIC;
353
354                 struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
355                 if (xps->b == NULL)
356                     return VLC_EGENERIC;
357
358                 const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
359                 xps = &hh->hevc.sps_list[i_spsid];
360                 if (xps->b == NULL)
361                     return VLC_EGENERIC;
362
363                 i_id = hevc_get_sps_vps_id(xps->hevc_sps);
364                 xps = &hh->hevc.vps_list[i_id];
365
366                 if (i_spsid != hh->hevc.i_current_sps ||
367                     i_id != hh->hevc.i_current_vps)
368                 {
369                     hh->hevc.i_current_sps = i_spsid;
370                     hh->hevc.i_current_vps = i_id;
371                     *p_config_changed = true;
372                 }
373             }
374             break; /* No need to parse further NAL */
375         }
376         else if(i_nal_type == HEVC_NAL_PREF_SEI||
377                 i_nal_type == HEVC_NAL_SUFF_SEI)
378         {
379             helper_load_sei(hh, p_nal, i_nal);
380         }
381     }
382     return VLC_SUCCESS;
383 }
384
385 static int
386 helper_process_avcC_h264(struct hxxx_helper *hh, const uint8_t *p_buf,
387                          size_t i_buf)
388 {
389     if (i_buf < H264_MIN_AVCC_SIZE)
390         return VLC_EGENERIC;
391
392     p_buf += 5; i_buf -= 5;
393
394     for (unsigned int j = 0; j < 2 && i_buf > 0; j++)
395     {
396         /* First time is SPS, Second is PPS */
397         const unsigned int i_num_nal = p_buf[0] & (j == 0 ? 0x1f : 0xff);
398         p_buf++; i_buf--;
399
400         for (unsigned int i = 0; i < i_num_nal && i_buf >= 2; i++)
401         {
402             uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1];
403             if (i_nal_size > i_buf - 2)
404                 return VLC_EGENERIC;
405             bool b_unused;
406             int i_ret = h264_helper_parse_nal(hh, p_buf, i_nal_size + 2, 2,
407                                               &b_unused);
408             if (i_ret != VLC_SUCCESS)
409                 return i_ret;
410             p_buf += i_nal_size + 2;
411             i_buf -= i_nal_size + 2;
412         }
413     }
414
415     return VLC_SUCCESS;
416 }
417
418 static int
419 h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
420                       size_t i_extra)
421 {
422     if (i_extra == 0)
423     {
424         /* AnnexB case */
425         hh->i_nal_length_size = 4;
426         return VLC_SUCCESS;
427     }
428     else if (h264_isavcC(p_extra, i_extra))
429     {
430         hh->i_nal_length_size = (((uint8_t*)p_extra)[4] & 0x03) + 1;
431         if (!helper_nal_length_valid(hh))
432             return VLC_EGENERIC;
433         hh->b_is_xvcC = true;
434
435         /* XXX h264_AVC_to_AnnexB() works only with a i_nal_length_size of 4.
436          * If nal_length_size is smaller than 4, fallback to SW decoding. I
437          * don't know if it's worth the effort to fix h264_AVC_to_AnnexB() for
438          * a smaller nal_length_size. Indeed, this case will happen only with
439          * very small resolutions, where hardware decoders are not that useful.
440          * -Thomas */
441         if (!hh->b_need_xvcC && hh->i_nal_length_size != 4)
442         {
443             msg_Dbg(hh->p_obj, "nal_length_size is too small");
444             return VLC_EGENERIC;
445         }
446
447         return helper_process_avcC_h264(hh, p_extra, i_extra);
448     }
449     else /* Can't handle extra that is not avcC */
450         return VLC_EGENERIC;
451 }
452
453 static int
454 helper_process_hvcC_hevc(struct hxxx_helper *hh, const uint8_t *p_buf,
455                          size_t i_buf)
456 {
457     if (i_buf < HEVC_MIN_HVCC_SIZE)
458         return VLC_EGENERIC;
459
460     const uint8_t i_num_array = p_buf[22];
461     p_buf += 23; i_buf -= 23;
462
463     for( uint8_t i = 0; i < i_num_array; i++ )
464     {
465         if(i_buf < 3)
466             return VLC_EGENERIC;
467
468         const uint16_t i_num_nalu = p_buf[1] << 8 | p_buf[2];
469         p_buf += 3; i_buf -= 3;
470
471         for( uint16_t j = 0; j < i_num_nalu; j++ )
472         {
473             if(i_buf < 2)
474                 return VLC_EGENERIC;
475
476             const uint16_t i_nalu_length = p_buf[0] << 8 | p_buf[1];
477             if(i_buf < (size_t)i_nalu_length + 2)
478                 return VLC_EGENERIC;
479
480             bool foo;
481             hevc_helper_parse_nal( hh, &p_buf[0],
482                                    i_nalu_length + 2, 2, &foo );
483
484             p_buf += i_nalu_length + 2;
485             i_buf -= i_nalu_length + 2;
486         }
487     }
488
489     return VLC_SUCCESS;
490 }
491
492 static int
493 hevc_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
494                       size_t i_extra)
495 {
496     if (i_extra == 0)
497     {
498         /* AnnexB case */
499         hh->i_nal_length_size = 4;
500         return VLC_SUCCESS;
501     }
502     else if (hevc_ishvcC(p_extra, i_extra))
503     {
504         hh->i_nal_length_size = hevc_getNALLengthSize(p_extra);
505         if (!helper_nal_length_valid(hh))
506             return VLC_EGENERIC;
507         hh->b_is_xvcC = true;
508
509         return helper_process_hvcC_hevc( hh, p_extra, i_extra );
510     }
511     else /* Can't handle extra that is not hvcC */
512         return VLC_EGENERIC;
513 }
514
515 static inline block_t *
516 helper_process_block_hxxx_annexb(struct hxxx_helper *hh,
517                                  int(*parser)(struct hxxx_helper *,
518                                               const uint8_t*, size_t,uint8_t,bool*),
519                                  block_t *p_block, bool *p_config_changed)
520 {
521     if (p_config_changed != NULL)
522     {
523         int i_ret = parser(hh, p_block->p_buffer, p_block->i_buffer,
524                            0, p_config_changed);
525         if (i_ret != VLC_SUCCESS)
526         {
527             block_Release(p_block);
528             return NULL;
529         }
530     }
531     return p_block;
532 }
533
534 static block_t *
535 helper_process_block_h264_annexb(struct hxxx_helper *hh, block_t *p_block,
536                                  bool *p_config_changed)
537 {
538     if (p_config_changed != NULL)
539         return helper_process_block_hxxx_annexb(hh, h264_helper_parse_nal,
540                                                 p_block,p_config_changed);
541     return p_block;
542 }
543
544 static block_t *
545 helper_process_block_hevc_annexb(struct hxxx_helper *hh, block_t *p_block,
546                                  bool *p_config_changed)
547 {
548     if (p_config_changed != NULL)
549         return helper_process_block_hxxx_annexb(hh, hevc_helper_parse_nal,
550                                                 p_block,p_config_changed);
551     return p_block;
552 }
553
554 static block_t *
555 helper_process_block_xvcc2annexb(struct hxxx_helper *hh, block_t *p_block,
556                                  bool *p_config_changed)
557 {
558     assert(helper_nal_length_valid(hh));
559     h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer,
560                        hh->i_nal_length_size);
561     return helper_process_block_h264_annexb(hh, p_block, p_config_changed);
562 }
563
564 static block_t *
565 helper_process_block_h264_annexb2avcc(struct hxxx_helper *hh, block_t *p_block,
566                                       bool *p_config_changed)
567 {
568     p_block = helper_process_block_h264_annexb(hh, p_block, p_config_changed);
569     return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
570 }
571
572 static block_t *
573 helper_process_block_hevc_annexb2hvcc(struct hxxx_helper *hh, block_t *p_block,
574                                       bool *p_config_changed)
575 {
576     p_block = helper_process_block_hevc_annexb(hh, p_block, p_config_changed);
577     return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
578 }
579
580 static block_t *
581 helper_process_block_h264_avcc(struct hxxx_helper *hh, block_t *p_block,
582                                bool *p_config_changed)
583 {
584     if (p_config_changed != NULL)
585     {
586         int i_ret = h264_helper_parse_nal(hh, p_block->p_buffer,
587                                           p_block->i_buffer,
588                                           hh->i_nal_length_size,
589                                           p_config_changed);
590         if (i_ret != VLC_SUCCESS)
591         {
592             block_Release(p_block);
593             return NULL;
594         }
595     }
596     return p_block;
597 }
598
599 static block_t *
600 helper_process_block_hevc_hvcc(struct hxxx_helper *hh, block_t *p_block,
601                                bool *p_config_changed)
602 {
603     if (p_config_changed != NULL)
604     {
605         int i_ret = hevc_helper_parse_nal(hh, p_block->p_buffer,
606                                           p_block->i_buffer,
607                                           hh->i_nal_length_size,
608                                           p_config_changed);
609         if (i_ret != VLC_SUCCESS)
610         {
611             block_Release(p_block);
612             return NULL;
613         }
614     }
615     return p_block;
616 }
617
618 int
619 hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
620                       size_t i_extra)
621 {
622     int i_ret;
623     switch (hh->i_codec)
624     {
625         case VLC_CODEC_H264:
626             i_ret = h264_helper_set_extra(hh, p_extra, i_extra);
627             break;
628         case VLC_CODEC_HEVC:
629             i_ret = hevc_helper_set_extra(hh, p_extra, i_extra);
630             break;
631         default:
632             vlc_assert_unreachable();
633     }
634     if (i_ret != VLC_SUCCESS)
635         return i_ret;
636
637     switch (hh->i_codec)
638     {
639         case VLC_CODEC_H264:
640             if (hh->b_is_xvcC)
641             {
642                 if (hh->b_need_xvcC)
643                     hh->pf_process_block = helper_process_block_h264_avcc;
644                 else
645                     hh->pf_process_block = helper_process_block_xvcc2annexb;
646             }
647             else /* AnnexB */
648             {
649                 if (hh->b_need_xvcC)
650                     hh->pf_process_block = helper_process_block_h264_annexb2avcc;
651                 else
652                     hh->pf_process_block = helper_process_block_h264_annexb;
653             }
654             break;
655         case VLC_CODEC_HEVC:
656             if (hh->b_is_xvcC)
657             {
658                 if (hh->b_need_xvcC)
659                     hh->pf_process_block = helper_process_block_hevc_hvcc;
660                 else
661                     hh->pf_process_block = helper_process_block_xvcc2annexb;
662             }
663             else /* AnnexB */
664             {
665                 if (hh->b_need_xvcC)
666                     hh->pf_process_block = helper_process_block_hevc_annexb2hvcc;
667                 else
668                     hh->pf_process_block = helper_process_block_hevc_annexb;
669             }
670             break;
671         default:
672             vlc_assert_unreachable();
673     }
674     return VLC_SUCCESS;;
675 }
676
677 static block_t *
678 hxxx_helper_get_annexb_config( const struct hxxx_helper_nal *pp_nal_lists[],
679                                const size_t p_nal_counts[],
680                                const size_t p_nal_maxs[],
681                                size_t i_lists_size )
682 {
683     static const uint8_t annexb_startcode[] = { 0x00, 0x00, 0x00, 0x01 };
684
685     block_t *p_block_list = NULL, *p_current;
686     for (size_t i = 0; i < i_lists_size; ++i)
687     {
688         size_t i_nals_size = 0;
689         const struct hxxx_helper_nal *p_nal;
690         HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
691         {
692             i_nals_size += p_nal->b->i_buffer + sizeof annexb_startcode;
693         }
694
695         block_t *p_block = block_Alloc(i_nals_size);
696         if (p_block == NULL)
697         {
698             if (p_block_list != NULL)
699                 block_Release(p_block_list);
700             return NULL;
701         }
702
703         p_block->i_buffer = 0;
704         HELPER_FOREACH_NAL(p_nal, pp_nal_lists[i], p_nal_counts[i], p_nal_maxs[i])
705         {
706             memcpy(&p_block->p_buffer[p_block->i_buffer], annexb_startcode,
707                    sizeof annexb_startcode);
708             p_block->i_buffer += sizeof annexb_startcode;
709             memcpy(&p_block->p_buffer[p_block->i_buffer], p_nal->b->p_buffer,
710                    p_nal->b->i_buffer);
711             p_block->i_buffer += p_nal->b->i_buffer;
712         }
713         if (p_block_list == NULL)
714             p_current = p_block_list = p_block;
715         else
716         {
717             p_current->p_next = p_block;
718             p_current = p_block;
719         }
720     }
721
722     return p_block_list;
723 }
724
725 block_t *
726 h264_helper_get_annexb_config(const struct hxxx_helper *hh)
727 {
728     if (hh->h264.i_sps_count == 0 || hh->h264.i_pps_count == 0)
729         return NULL;
730
731     const struct hxxx_helper_nal *pp_nal_lists[] = {
732         hh->h264.sps_list, hh->h264.pps_list };
733     const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count };
734     const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1 };
735
736     return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 2 );
737 }
738
739 block_t *
740 hevc_helper_get_annexb_config(const struct hxxx_helper *hh)
741 {
742     if (hh->hevc.i_vps_count == 0 || hh->hevc.i_sps_count == 0 ||
743         hh->hevc.i_pps_count == 0 )
744         return NULL;
745
746     const struct hxxx_helper_nal *pp_nal_lists[] = {
747         hh->hevc.vps_list, hh->hevc.sps_list, hh->hevc.pps_list };
748     const size_t p_nal_counts[] = { hh->hevc.i_vps_count, hh->hevc.i_sps_count,
749                                     hh->hevc.i_pps_count };
750     const size_t p_nal_maxs[] = { HEVC_VPS_ID_MAX+1, HEVC_SPS_ID_MAX+1, HEVC_PPS_ID_MAX+1 };
751
752     return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
753 }
754
755 block_t *
756 h264_helper_get_avcc_config(const struct hxxx_helper *hh)
757 {
758     const struct hxxx_helper_nal *p_nal;
759     const uint8_t *pp_sps_bufs[hh->h264.i_sps_count];
760     size_t p_sps_sizes[hh->h264.i_sps_count];
761     HELPER_FOREACH_NAL(p_nal, hh->h264.sps_list, hh->h264.i_sps_count,
762                        H264_SPS_ID_MAX+1)
763     {
764         pp_sps_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
765         p_sps_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
766     }
767
768     const uint8_t *pp_pps_bufs[hh->h264.i_pps_count];
769     size_t p_pps_sizes[hh->h264.i_pps_count];
770     HELPER_FOREACH_NAL(p_nal, hh->h264.pps_list, hh->h264.i_pps_count,
771                        H264_PPS_ID_MAX+1)
772     {
773         pp_pps_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
774         p_pps_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
775     }
776     return h264_NAL_to_avcC(4, pp_sps_bufs, p_sps_sizes, hh->h264.i_sps_count,
777                             pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count);
778 }
779
780 block_t *
781 hevc_helper_get_hvcc_config(const struct hxxx_helper *hh)
782 {
783     struct hevc_dcr_params params = {};
784     const struct hxxx_helper_nal *p_nal;
785
786     HELPER_FOREACH_NAL(p_nal, hh->hevc.vps_list, hh->hevc.i_vps_count,
787                        HEVC_VPS_ID_MAX+1)
788     {
789         params.p_vps[params.i_vps_count] = p_nal->b->p_buffer;
790         params.rgi_vps[params.i_vps_count++] = p_nal->b->i_buffer;
791     }
792
793     HELPER_FOREACH_NAL(p_nal, hh->hevc.sps_list, hh->hevc.i_sps_count,
794                        HEVC_SPS_ID_MAX+1)
795     {
796         params.p_sps[params.i_sps_count] = p_nal->b->p_buffer;
797         params.rgi_sps[params.i_sps_count++] = p_nal->b->i_buffer;
798     }
799
800     HELPER_FOREACH_NAL(p_nal, hh->hevc.pps_list, hh->hevc.i_pps_count,
801                        HEVC_PPS_ID_MAX+1)
802     {
803         params.p_pps[params.i_pps_count] = p_nal->b->p_buffer;
804         params.rgi_pps[params.i_pps_count++] = p_nal->b->i_buffer;
805     }
806
807     HELPER_FOREACH_NAL(p_nal, hh->hevc.sei_list, hh->hevc.i_sei_count,
808                        HEVC_DCR_SEI_COUNT)
809     {
810         if (hevc_getNALType(p_nal->b->p_buffer) == HEVC_NAL_PREF_SEI)
811         {
812             params.p_seipref[params.i_seipref_count] = p_nal->b->p_buffer;
813             params.rgi_seipref[params.i_seipref_count++] = p_nal->b->i_buffer;
814         }
815         else
816         {
817             params.p_seisuff[params.i_seisuff_count] = p_nal->b->p_buffer;
818             params.rgi_seisuff[params.i_seisuff_count++] = p_nal->b->i_buffer;
819         }
820     }
821
822     size_t i_dcr;
823     uint8_t *p_dcr = hevc_create_dcr(&params, 4, true, &i_dcr);
824     if(p_dcr == NULL)
825         return NULL;
826
827     return block_heap_Alloc(p_dcr, i_dcr);
828 }
829
830 static const struct hxxx_helper_nal *
831 h264_helper_get_current_sps(const struct hxxx_helper *hh)
832 {
833     if (hh->h264.i_sps_count == 0)
834         return NULL;
835
836     const struct hxxx_helper_nal *hsps =
837         &hh->h264.sps_list[hh->h264.i_current_sps];
838     assert(hsps->b != NULL);
839     return hsps;
840 }
841
842 int
843 hxxx_helper_get_current_picture_size(const struct hxxx_helper *hh,
844                                      unsigned *p_w, unsigned *p_h,
845                                      unsigned *p_vw, unsigned *p_vh)
846 {
847     if(hh->i_codec == VLC_CODEC_H264)
848     {
849         const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
850         if (hsps && h264_get_picture_size(hsps->h264_sps, p_w, p_h, p_vw, p_vh))
851                return VLC_SUCCESS;
852     }
853     else if(hh->i_codec == VLC_CODEC_HEVC)
854     {
855         const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
856         if(hsps && hevc_get_picture_size(hsps->hevc_sps, p_w, p_h, p_vw, p_vh))
857             return VLC_SUCCESS;
858     }
859     return VLC_EGENERIC;
860 }
861
862 int
863 hxxx_helper_get_current_sar(const struct hxxx_helper *hh, int *p_num, int *p_den)
864 {
865     if(hh->i_codec == VLC_CODEC_H264)
866     {
867         const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
868         if (hsps)
869         {
870             *p_num = hsps->h264_sps->vui.i_sar_num;
871             *p_den = hsps->h264_sps->vui.i_sar_den;
872             return VLC_SUCCESS;
873         }
874     }
875     else if(hh->i_codec == VLC_CODEC_HEVC)
876     {
877         const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
878         unsigned num, den;
879         if(hsps && hevc_get_aspect_ratio(hsps->hevc_sps, &num, &den))
880         {
881             *p_num = num;
882             *p_den = den;
883             return VLC_SUCCESS;
884         }
885     }
886     return VLC_EGENERIC;
887 }
888
889 int
890 h264_helper_get_current_dpb_values(const struct hxxx_helper *hh,
891                                    uint8_t *p_depth, unsigned *p_delay)
892 {
893     const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
894     if (hsps == NULL)
895         return VLC_EGENERIC;
896     return h264_get_dpb_values(hsps->h264_sps, p_depth, p_delay) ?
897            VLC_SUCCESS : VLC_EGENERIC;
898 }
899
900 int
901 hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh,
902                                       uint8_t *p_profile, uint8_t *p_level)
903 {
904     if(hh->i_codec == VLC_CODEC_H264)
905     {
906         const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
907         if (hsps)
908         {
909             *p_profile = hsps->h264_sps->i_profile;
910             *p_level = hsps->h264_sps->i_level;
911             return VLC_SUCCESS;
912         }
913     }
914     else if(hh->i_codec == VLC_CODEC_HEVC)
915     {
916         const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
917         if (hsps &&
918             hevc_get_sps_profile_tier_level(hsps->hevc_sps, p_profile, p_level))
919             return VLC_SUCCESS;
920     }
921     return VLC_EGENERIC;
922 }
923
924 int
925 hxxx_helper_get_colorimetry(const struct hxxx_helper *hh,
926                             video_color_primaries_t *p_primaries,
927                             video_transfer_func_t *p_transfer,
928                             video_color_space_t *p_colorspace,
929                             bool *p_full_range)
930 {
931     switch (hh->i_codec)
932     {
933         case VLC_CODEC_H264:
934         {
935             const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh);
936             if (hsps == NULL)
937                 return VLC_EGENERIC;
938             return h264_get_colorimetry(hsps->h264_sps, p_primaries, p_transfer,
939                                         p_colorspace, p_full_range)
940                 == true ? VLC_SUCCESS : VLC_EGENERIC;
941         }
942         case VLC_CODEC_HEVC:
943         {
944             const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps];
945             if (hsps == NULL)
946                 return VLC_EGENERIC;
947
948             return hevc_get_colorimetry(hsps->hevc_sps, p_primaries, p_transfer,
949                                         p_colorspace, p_full_range)
950                 == true ? VLC_SUCCESS : VLC_EGENERIC;
951         }
952         default:
953             vlc_assert_unreachable();
954     }
955 }