[vlc-commits] [Git][videolan/vlc][master] 9 commits: hxxx_helper: remove direct calls to process_block

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Wed Jan 5 11:19:06 UTC 2022



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
7c7516d5 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: remove direct calls to process_block

- - - - -
1bb32e8f by Francois Cartegnie at 2022-01-05T10:40:01+00:00
codec: mediacodec: fix potential NULL deref

- - - - -
926bf504 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
codec: nvdec: fix extradata leak

- - - - -
db160a58 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
test: add hxxx_helper

- - - - -
2313a098 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: refactor & simplify

also removes extradata requirement to set pf_process_block

- - - - -
0e3f3d5d by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: replace ambigous xvcC/AnnexB parameter

- - - - -
b89e4fc1 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: replace config_changed with getter

- - - - -
a0c259ea by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: simplify extradata getters

- - - - -
bce57ed7 by Francois Cartegnie at 2022-01-05T10:40:01+00:00
hxxx_helper: add hxxx_helper_has_config

- - - - -


8 changed files:

- modules/codec/hxxx_helper.c
- modules/codec/hxxx_helper.h
- modules/codec/hxxx_helper_testdec.c
- modules/codec/omxil/mediacodec.c
- modules/codec/videotoolbox.c
- modules/hw/nvdec/nvdec.c
- test/Makefile.am
- + test/modules/codec/hxxx_helper.c


Changes:

=====================================
modules/codec/hxxx_helper.c
=====================================
@@ -34,14 +34,19 @@
 
 void
 hxxx_helper_init(struct hxxx_helper *hh, vlc_object_t *p_obj,
-                 vlc_fourcc_t i_codec, bool b_need_xvcC)
+                 vlc_fourcc_t i_codec, uint8_t i_input_length_size,
+                 uint8_t i_output_length_size)
 {
     assert(i_codec == VLC_CODEC_H264 || i_codec == VLC_CODEC_HEVC);
+    /* we don't support prefix conversion */
+    if(i_input_length_size && i_output_length_size)
+        i_output_length_size = i_input_length_size;
 
     memset(hh, 0, sizeof(struct hxxx_helper));
     hh->p_obj = p_obj;
     hh->i_codec = i_codec;
-    hh->b_need_xvcC = b_need_xvcC;
+    hh->i_input_nal_length_size = i_input_length_size;
+    hh->i_output_nal_length_size = i_output_length_size;
 }
 
 #define RELEASE_NALS(list, max, release) \
@@ -147,10 +152,10 @@ helper_search_nal(const struct hxxx_helper_nal *p_nal_list, size_t i_nal_count,
 }
 
 static inline bool
-helper_nal_length_valid(struct hxxx_helper *hh)
+helper_nal_length_valid(uint8_t i_nal_length_size)
 {
-    return hh->i_nal_length_size == 1 || hh->i_nal_length_size == 2
-        || hh->i_nal_length_size == 4;
+    return i_nal_length_size == 1 || i_nal_length_size == 2
+        || i_nal_length_size == 4;
 }
 
 static void
@@ -170,7 +175,7 @@ helper_load_sei(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal)
 
 #define LOAD_xPS(list, count, id, max, xpstype, xpsdecode, xpsrelease) \
     if (helper_search_nal(list, count, max+1, p_nal, i_nal) != NULL)\
-        continue;\
+        return VLC_SUCCESS;\
     xpstype *p_xps = xpsdecode(p_nal, i_nal, true);\
     if (!p_xps)\
         return VLC_EGENERIC;\
@@ -187,92 +192,81 @@ helper_load_sei(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal)
         count++;\
 \
     hnal->xps = p_xps;\
-    *p_config_changed = true
+    hh->i_config_version++
 
 static int
-h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
-                      uint8_t i_nal_length_size, bool *p_config_changed)
+h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal)
 {
-    const uint8_t *p_nal;
-    size_t i_nal;
-    hxxx_iterator_ctx_t it;
-    hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
-    *p_config_changed = false;
-
-    while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
-                               : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
-    {
-        if (i_nal < 2)
-            continue;
+    if (i_nal < 2)
+        return VLC_EGENERIC;
 
-        const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
+    const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
 
-        if (i_nal_type == H264_NAL_SPS)
-        {
-            LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count,
-                     p_xps->i_id, H264_SPS_ID_MAX,
-                     h264_sequence_parameter_set_t,
-                     h264_decode_sps,
-                     h264_release_sps);
-            hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id;
-            msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps);
-        }
-        else if (i_nal_type == H264_NAL_PPS)
-        {
-            LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count,
-                     p_xps->i_id, H264_PPS_ID_MAX,
-                     h264_picture_parameter_set_t,
-                     h264_decode_pps,
-                     h264_release_pps);
-            msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
-        }
-        else if(i_nal_type == H264_NAL_SPS_EXT)
-        {
-            LOAD_xPS(hh->h264.spsext_list, hh->h264.i_spsext_count,
-                     p_xps->i_sps_id, H264_SPSEXT_ID_MAX,
-                     h264_sequence_parameter_set_extension_t,
-                     h264_decode_sps_extension,
-                     h264_release_sps_extension);
-            msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", ((h264_sequence_parameter_set_extension_t*)p_xps)->i_sps_id);
-        }
-        else if (i_nal_type <= H264_NAL_SLICE_IDR
-              && i_nal_type != H264_NAL_UNKNOWN)
+    if (i_nal_type == H264_NAL_SPS)
+    {
+        LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count,
+                 p_xps->i_id, H264_SPS_ID_MAX,
+                 h264_sequence_parameter_set_t,
+                 h264_decode_sps,
+                 h264_release_sps);
+        hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id;
+        msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps);
+    }
+    else if (i_nal_type == H264_NAL_PPS)
+    {
+        LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count,
+                 p_xps->i_id, H264_PPS_ID_MAX,
+                 h264_picture_parameter_set_t,
+                 h264_decode_pps,
+                 h264_release_pps);
+        msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
+    }
+    else if(i_nal_type == H264_NAL_SPS_EXT)
+    {
+        LOAD_xPS(hh->h264.spsext_list, hh->h264.i_spsext_count,
+                 p_xps->i_sps_id, H264_SPSEXT_ID_MAX,
+                 h264_sequence_parameter_set_extension_t,
+                 h264_decode_sps_extension,
+                 h264_release_sps_extension);
+        msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", ((h264_sequence_parameter_set_extension_t*)p_xps)->i_sps_id);
+    }
+    else if (i_nal_type <= H264_NAL_SLICE_IDR
+             && i_nal_type != H264_NAL_UNKNOWN)
+    {
+        if (hh->h264.i_sps_count > 1)
         {
-            if (hh->h264.i_sps_count > 1)
-            {
-                /* There is more than one SPS. Get the PPS id of the current
+            /* There is more than one SPS. Get the PPS id of the current
                  * SLICE in order to get the current SPS id */
 
-                /* Get the PPS id from the slice: inspirated from
+            /* Get the PPS id from the slice: inspirated from
                  * h264_decode_slice() */
-                bs_t s;
-                bs_init(&s, p_nal, i_nal);
-                bs_skip(&s, 8);
-                bs_read_ue(&s);
-                bs_read_ue(&s);
-                unsigned i_pps_id = bs_read_ue(&s);
-                if (i_pps_id > H264_PPS_ID_MAX)
-                    return VLC_EGENERIC;
-
-                struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
-                if (hpps->b == NULL)
-                    return VLC_EGENERIC;
-
-                struct hxxx_helper_nal *hsps =
+            bs_t s;
+            bs_init(&s, p_nal, i_nal);
+            bs_skip(&s, 8);
+            bs_read_ue(&s);
+            bs_read_ue(&s);
+            unsigned i_pps_id = bs_read_ue(&s);
+            if (i_pps_id > H264_PPS_ID_MAX)
+                return VLC_EGENERIC;
+
+            struct hxxx_helper_nal *hpps = &hh->h264.pps_list[i_pps_id];
+            if (hpps->b == NULL)
+                return VLC_EGENERIC;
+
+            struct hxxx_helper_nal *hsps =
                     &hh->h264.sps_list[hpps->h264_pps->i_sps_id];
-                if (hsps->b == NULL)
-                    return VLC_EGENERIC;
-
-                assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id);
-                if (hsps->h264_sps->i_id != hh->h264.i_current_sps)
-                {
-                    hh->h264.i_current_sps = hsps->h264_sps->i_id;
-                    *p_config_changed = true;
-                }
+            if (hsps->b == NULL)
+                return VLC_EGENERIC;
+
+            assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id);
+            if (hsps->h264_sps->i_id != hh->h264.i_current_sps)
+            {
+                hh->h264.i_current_sps = hsps->h264_sps->i_id;
+                hh->i_config_version++;
             }
-            break; /* No need to parse further NAL */
         }
     }
+
     return VLC_SUCCESS;
 }
 
@@ -288,103 +282,95 @@ helper_check_sei_au(struct hxxx_helper *hh, uint8_t i_nal_type)
 }
 
 static int
-hevc_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf,
-                      uint8_t i_nal_length_size, bool *p_config_changed)
+hevc_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal)
 {
-    const uint8_t *p_nal;
-    size_t i_nal;
-    hxxx_iterator_ctx_t it;
-    hxxx_iterator_init(&it, p_buf, i_buf, i_nal_length_size);
-    *p_config_changed = false;
+    if (i_nal < 2)
+        return VLC_EGENERIC;
 
-    while ((i_nal_length_size) ? hxxx_iterate_next(&it, &p_nal, &i_nal)
-                               : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
-    {
-        if (i_nal < 2 || hevc_getNALLayer(p_nal) > 0)
-            continue;
+    if(hevc_getNALLayer(p_nal) > 0)
+        return VLC_SUCCESS;
 
-        const uint8_t i_nal_type = hevc_getNALType(p_nal);
+    const uint8_t i_nal_type = hevc_getNALType(p_nal);
 
-        /* we need to clear sei not belonging to this access unit */
-        helper_check_sei_au(hh, i_nal_type);
+    /* we need to clear sei not belonging to this access unit */
+    helper_check_sei_au(hh, i_nal_type);
 
-        if (i_nal_type == HEVC_NAL_VPS)
+    if (i_nal_type == HEVC_NAL_VPS)
+    {
+        uint8_t i_id;
+        if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+            return VLC_EGENERIC;
+        LOAD_xPS(hh->hevc.vps_list, hh->hevc.i_vps_count,
+                 i_id, HEVC_VPS_ID_MAX,
+                 hevc_video_parameter_set_t,
+                 hevc_decode_vps,
+                 hevc_rbsp_release_vps);
+        msg_Dbg(hh->p_obj, "new VPS parsed: %u", i_id);
+    }
+    else if (i_nal_type == HEVC_NAL_SPS)
+    {
+        uint8_t i_id;
+        if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+            return VLC_EGENERIC;
+        LOAD_xPS(hh->hevc.sps_list, hh->hevc.i_sps_count,
+                 i_id, HEVC_SPS_ID_MAX,
+                 hevc_sequence_parameter_set_t,
+                 hevc_decode_sps,
+                 hevc_rbsp_release_sps);
+        msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id);
+    }
+    else if (i_nal_type == HEVC_NAL_PPS)
+    {
+        uint8_t i_id;
+        if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+            return VLC_EGENERIC;
+        LOAD_xPS(hh->hevc.pps_list, hh->hevc.i_pps_count,
+                 i_id, HEVC_PPS_ID_MAX,
+                 hevc_picture_parameter_set_t,
+                 hevc_decode_pps,
+                 hevc_rbsp_release_pps);
+        msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id);
+    }
+    else if (i_nal_type <= HEVC_NAL_IRAP_VCL23)
+    {
+        if (hh->hevc.i_sps_count > 1 || hh->hevc.i_vps_count > 1)
         {
-            uint8_t i_id;
-            if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+            /* Get the PPS id from the slice: inspirated from
+                 * h264_decode_slice() */
+            bs_t s;
+            bs_init(&s, p_nal, i_nal);
+            bs_skip(&s, 2);
+            unsigned i_id = bs_read_ue(&s);
+            if (i_id > HEVC_PPS_ID_MAX)
                 return VLC_EGENERIC;
-            LOAD_xPS(hh->hevc.vps_list, hh->hevc.i_vps_count,
-                     i_id, HEVC_VPS_ID_MAX,
-                     hevc_video_parameter_set_t,
-                     hevc_decode_vps,
-                     hevc_rbsp_release_vps);
-            msg_Dbg(hh->p_obj, "new VPS parsed: %u", i_id);
-        }
-        else if (i_nal_type == HEVC_NAL_SPS)
-        {
-            uint8_t i_id;
-            if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+
+            struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
+            if (xps->b == NULL)
                 return VLC_EGENERIC;
-            LOAD_xPS(hh->hevc.sps_list, hh->hevc.i_sps_count,
-                     i_id, HEVC_SPS_ID_MAX,
-                     hevc_sequence_parameter_set_t,
-                     hevc_decode_sps,
-                     hevc_rbsp_release_sps);
-            msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id);
-        }
-        else if (i_nal_type == HEVC_NAL_PPS)
-        {
-            uint8_t i_id;
-            if( !hevc_get_xps_id(p_nal, i_nal, &i_id) )
+
+            const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
+            xps = &hh->hevc.sps_list[i_spsid];
+            if (xps->b == NULL)
                 return VLC_EGENERIC;
-            LOAD_xPS(hh->hevc.pps_list, hh->hevc.i_pps_count,
-                     i_id, HEVC_PPS_ID_MAX,
-                     hevc_picture_parameter_set_t,
-                     hevc_decode_pps,
-                     hevc_rbsp_release_pps);
-            msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id);
-        }
-        else if (i_nal_type <= HEVC_NAL_IRAP_VCL23)
-        {
-            if (hh->hevc.i_sps_count > 1 || hh->hevc.i_vps_count > 1)
-            {
-                /* Get the PPS id from the slice: inspirated from
-                 * h264_decode_slice() */
-                bs_t s;
-                bs_init(&s, p_nal, i_nal);
-                bs_skip(&s, 2);
-                unsigned i_id = bs_read_ue(&s);
-                if (i_id > HEVC_PPS_ID_MAX)
-                    return VLC_EGENERIC;
-
-                struct hxxx_helper_nal *xps = &hh->hevc.pps_list[i_id];
-                if (xps->b == NULL)
-                    return VLC_EGENERIC;
-
-                const uint8_t i_spsid = hevc_get_pps_sps_id(xps->hevc_pps);
-                xps = &hh->hevc.sps_list[i_spsid];
-                if (xps->b == NULL)
-                    return VLC_EGENERIC;
-
-                i_id = hevc_get_sps_vps_id(xps->hevc_sps);
-                xps = &hh->hevc.vps_list[i_id];
-
-                if (i_spsid != hh->hevc.i_current_sps ||
+
+            i_id = hevc_get_sps_vps_id(xps->hevc_sps);
+            xps = &hh->hevc.vps_list[i_id];
+
+            if (i_spsid != hh->hevc.i_current_sps ||
                     i_id != hh->hevc.i_current_vps)
-                {
-                    hh->hevc.i_current_sps = i_spsid;
-                    hh->hevc.i_current_vps = i_id;
-                    *p_config_changed = true;
-                }
+            {
+                hh->hevc.i_current_sps = i_spsid;
+                hh->hevc.i_current_vps = i_id;
+                hh->i_config_version++;
             }
-            break; /* No need to parse further NAL */
-        }
-        else if(i_nal_type == HEVC_NAL_PREF_SEI||
-                i_nal_type == HEVC_NAL_SUFF_SEI)
-        {
-            helper_load_sei(hh, p_nal, i_nal);
         }
     }
+    else if(i_nal_type == HEVC_NAL_PREF_SEI||
+            i_nal_type == HEVC_NAL_SUFF_SEI)
+    {
+        helper_load_sei(hh, p_nal, i_nal);
+    }
+
     return VLC_SUCCESS;
 }
 
@@ -408,9 +394,7 @@ helper_process_avcC_h264(struct hxxx_helper *hh, const uint8_t *p_buf,
             uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1];
             if (i_nal_size > i_buf - 2)
                 return VLC_EGENERIC;
-            bool b_unused;
-            int i_ret = h264_helper_parse_nal(hh, p_buf, i_nal_size + 2, 2,
-                                              &b_unused);
+            int i_ret = h264_helper_parse_nal(hh, p_buf + 2, i_nal_size);
             if (i_ret != VLC_SUCCESS)
                 return i_ret;
             p_buf += i_nal_size + 2;
@@ -434,10 +418,10 @@ h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
 {
     if (h264_isavcC(p_extra, i_extra))
     {
-        hh->i_nal_length_size = (((uint8_t*)p_extra)[4] & 0x03) + 1;
-        if (!helper_nal_length_valid(hh))
+        uint8_t i_nal_length_size = (((uint8_t*)p_extra)[4] & 0x03) + 1;
+        if (!helper_nal_length_valid(i_nal_length_size))
             return VLC_EGENERIC;
-        hh->b_is_xvcC = true;
+        hh->i_input_nal_length_size = i_nal_length_size;
 
         /* XXX h264_AVC_to_AnnexB() works only with a i_nal_length_size of 4.
          * If nal_length_size is smaller than 4, fallback to SW decoding. I
@@ -445,7 +429,7 @@ h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
          * a smaller nal_length_size. Indeed, this case will happen only with
          * very small resolutions, where hardware decoders are not that useful.
          * -Thomas */
-        if (!hh->b_need_xvcC && hh->i_nal_length_size != 4)
+        if (hh->i_output_nal_length_size == 0 && hh->i_input_nal_length_size != 4)
         {
             msg_Dbg(hh->p_obj, "nal_length_size is too small");
             return VLC_EGENERIC;
@@ -455,10 +439,9 @@ h264_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
     }
     else if (hxxx_extra_isannexb(p_extra, i_extra))
     {
-        hh->i_nal_length_size = 4;
-        bool unused;
+        hh->i_input_nal_length_size = 0;
         return i_extra == 0 ? VLC_SUCCESS :
-               h264_helper_parse_nal(hh, p_extra, i_extra, 0, &unused);
+               hxxx_helper_process_buffer(hh, p_extra, i_extra);
     }
     else
         return VLC_EGENERIC;
@@ -491,9 +474,7 @@ helper_process_hvcC_hevc(struct hxxx_helper *hh, const uint8_t *p_buf,
             if(i_buf < (size_t)i_nalu_length + 2)
                 return VLC_EGENERIC;
 
-            bool foo;
-            hevc_helper_parse_nal( hh, &p_buf[0],
-                                   i_nalu_length + 2, 2, &foo );
+            hevc_helper_parse_nal(hh, &p_buf[2], i_nalu_length);
 
             p_buf += i_nalu_length + 2;
             i_buf -= i_nalu_length + 2;
@@ -509,133 +490,81 @@ hevc_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
 {
     if (hevc_ishvcC(p_extra, i_extra))
     {
-        hh->i_nal_length_size = hevc_getNALLengthSize(p_extra);
-        if (!helper_nal_length_valid(hh))
+        uint8_t i_nal_length_size = hevc_getNALLengthSize(p_extra);
+        if (!helper_nal_length_valid(i_nal_length_size))
             return VLC_EGENERIC;
-        hh->b_is_xvcC = true;
+        hh->i_input_nal_length_size = i_nal_length_size;
 
         return helper_process_hvcC_hevc( hh, p_extra, i_extra );
     }
     else if (hxxx_extra_isannexb(p_extra, i_extra))
     {
-        hh->i_nal_length_size = 4;
-        bool unused;
+        hh->i_input_nal_length_size = 0;
         return i_extra == 0 ? VLC_SUCCESS :
-               hevc_helper_parse_nal(hh, p_extra, i_extra, 0, &unused);
+               hxxx_helper_process_buffer(hh, p_extra, i_extra);
     }
     else
         return VLC_EGENERIC;
 }
 
-static inline block_t *
-helper_process_block_hxxx_annexb(struct hxxx_helper *hh,
-                                 int(*parser)(struct hxxx_helper *,
-                                              const uint8_t*, size_t,uint8_t,bool*),
-                                 block_t *p_block, bool *p_config_changed)
+int hxxx_helper_process_nal(struct hxxx_helper *hh,
+                            const uint8_t *p_nal, size_t i_nal)
 {
-    if (p_config_changed != NULL)
-    {
-        int i_ret = parser(hh, p_block->p_buffer, p_block->i_buffer,
-                           0, p_config_changed);
-        if (i_ret != VLC_SUCCESS)
-        {
-            block_Release(p_block);
-            return NULL;
-        }
-    }
-    return p_block;
-}
-
-static block_t *
-helper_process_block_h264_annexb(struct hxxx_helper *hh, block_t *p_block,
-                                 bool *p_config_changed)
-{
-    if (p_config_changed != NULL)
-        return helper_process_block_hxxx_annexb(hh, h264_helper_parse_nal,
-                                                p_block,p_config_changed);
-    return p_block;
-}
-
-static block_t *
-helper_process_block_hevc_annexb(struct hxxx_helper *hh, block_t *p_block,
-                                 bool *p_config_changed)
-{
-    if (p_config_changed != NULL)
-        return helper_process_block_hxxx_annexb(hh, hevc_helper_parse_nal,
-                                                p_block,p_config_changed);
-    return p_block;
+    if(hh->i_codec == VLC_CODEC_H264)
+        return h264_helper_parse_nal(hh, p_nal, i_nal);
+    else
+        return hevc_helper_parse_nal(hh, p_nal, i_nal);
 }
 
-static block_t *
-helper_process_block_h264_xvcc2annexb(struct hxxx_helper *hh, block_t *p_block,
-                                 bool *p_config_changed)
+int
+hxxx_helper_process_buffer(struct hxxx_helper *hh,
+                           const uint8_t *p_buffer, size_t i_buffer)
 {
-    assert(helper_nal_length_valid(hh));
-    h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer,
-                       hh->i_nal_length_size);
-    return helper_process_block_h264_annexb(hh, p_block, p_config_changed);
-}
+    const uint8_t *p_nal;
+    size_t i_nal;
+    hxxx_iterator_ctx_t it;
+    hxxx_iterator_init(&it, p_buffer, i_buffer, hh->i_input_nal_length_size);
 
-static block_t *
-helper_process_block_hevc_xvcc2annexb(struct hxxx_helper *hh, block_t *p_block,
-                                 bool *p_config_changed)
-{
-    assert(helper_nal_length_valid(hh));
-    h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer,
-                       hh->i_nal_length_size);
-    return helper_process_block_hevc_annexb(hh, p_block, p_config_changed);
-}
+    if(hh->i_config_version_prev != hh->i_config_version)
+        hh->i_config_version_prev = hh->i_config_version;
 
-static block_t *
-helper_process_block_h264_annexb2avcc(struct hxxx_helper *hh, block_t *p_block,
-                                      bool *p_config_changed)
-{
-    p_block = helper_process_block_h264_annexb(hh, p_block, p_config_changed);
-    return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
-}
+    int i_ret = VLC_SUCCESS;
+    while (hh->i_input_nal_length_size ? hxxx_iterate_next(&it, &p_nal, &i_nal)
+                                       : hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
+    {
+        i_ret = hxxx_helper_process_nal(hh, p_nal, i_nal);
+        if(i_ret != VLC_SUCCESS)
+            break;
+    }
 
-static block_t *
-helper_process_block_hevc_annexb2hvcc(struct hxxx_helper *hh, block_t *p_block,
-                                      bool *p_config_changed)
-{
-    p_block = helper_process_block_hevc_annexb(hh, p_block, p_config_changed);
-    return p_block ? hxxx_AnnexB_to_xVC(p_block, hh->i_nal_length_size) : NULL;
+    return i_ret;
 }
 
-static block_t *
-helper_process_block_h264_avcc(struct hxxx_helper *hh, block_t *p_block,
-                               bool *p_config_changed)
+block_t *
+hxxx_helper_process_block(struct hxxx_helper *hh, block_t *p_block)
 {
-    if (p_config_changed != NULL)
+    int i_ret = hxxx_helper_process_buffer(hh, p_block->p_buffer, p_block->i_buffer);
+    if(i_ret != VLC_SUCCESS)
     {
-        int i_ret = h264_helper_parse_nal(hh, p_block->p_buffer,
-                                          p_block->i_buffer,
-                                          hh->i_nal_length_size,
-                                          p_config_changed);
-        if (i_ret != VLC_SUCCESS)
-        {
-            block_Release(p_block);
-            return NULL;
-        }
+        block_Release(p_block);
+        return NULL;
     }
-    return p_block;
-}
 
-static block_t *
-helper_process_block_hevc_hvcc(struct hxxx_helper *hh, block_t *p_block,
-                               bool *p_config_changed)
-{
-    if (p_config_changed != NULL)
+    if(p_block && hh->i_input_nal_length_size != hh->i_output_nal_length_size)
     {
-        int i_ret = hevc_helper_parse_nal(hh, p_block->p_buffer,
-                                          p_block->i_buffer,
-                                          hh->i_nal_length_size,
-                                          p_config_changed);
-        if (i_ret != VLC_SUCCESS)
+        if(unlikely(hh->i_input_nal_length_size && hh->i_output_nal_length_size))
         {
-            block_Release(p_block);
-            return NULL;
+            /* Should not happen */
+            assert(!hh->i_input_nal_length_size || !hh->i_output_nal_length_size);
+            return p_block;
+        }
+        else if(hh->i_output_nal_length_size)
+        {
+            assert(helper_nal_length_valid(hh->i_output_nal_length_size));
+            return hxxx_AnnexB_to_xVC(p_block, hh->i_output_nal_length_size);
         }
+        else
+            h264_AVC_to_AnnexB(p_block->p_buffer, p_block->i_buffer, hh->i_input_nal_length_size);
     }
     return p_block;
 }
@@ -644,59 +573,16 @@ int
 hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
                       size_t i_extra)
 {
-    int i_ret;
     switch (hh->i_codec)
     {
         case VLC_CODEC_H264:
-            i_ret = h264_helper_set_extra(hh, p_extra, i_extra);
-            break;
-        case VLC_CODEC_HEVC:
-            i_ret = hevc_helper_set_extra(hh, p_extra, i_extra);
-            break;
-        default:
-            vlc_assert_unreachable();
-    }
-    if (i_ret != VLC_SUCCESS)
-        return i_ret;
-
-    switch (hh->i_codec)
-    {
-        case VLC_CODEC_H264:
-            if (hh->b_is_xvcC)
-            {
-                if (hh->b_need_xvcC)
-                    hh->pf_process_block = helper_process_block_h264_avcc;
-                else
-                    hh->pf_process_block = helper_process_block_h264_xvcc2annexb;
-            }
-            else /* AnnexB */
-            {
-                if (hh->b_need_xvcC)
-                    hh->pf_process_block = helper_process_block_h264_annexb2avcc;
-                else
-                    hh->pf_process_block = helper_process_block_h264_annexb;
-            }
-            break;
+            return h264_helper_set_extra(hh, p_extra, i_extra);
         case VLC_CODEC_HEVC:
-            if (hh->b_is_xvcC)
-            {
-                if (hh->b_need_xvcC)
-                    hh->pf_process_block = helper_process_block_hevc_hvcc;
-                else
-                    hh->pf_process_block = helper_process_block_hevc_xvcc2annexb;
-            }
-            else /* AnnexB */
-            {
-                if (hh->b_need_xvcC)
-                    hh->pf_process_block = helper_process_block_hevc_annexb2hvcc;
-                else
-                    hh->pf_process_block = helper_process_block_hevc_annexb;
-            }
-            break;
+            return hevc_helper_set_extra(hh, p_extra, i_extra);
         default:
             vlc_assert_unreachable();
+            return VLC_EGENERIC;
     }
-    return VLC_SUCCESS;;
 }
 
 static block_t *
@@ -747,7 +633,27 @@ hxxx_helper_get_annexb_config( const struct hxxx_helper_nal *pp_nal_lists[],
     return p_block_list;
 }
 
-block_t *
+bool hxxx_helper_has_new_config(const struct hxxx_helper *hh)
+{
+    return hh->i_config_version != hh->i_config_version_prev;
+}
+
+bool hxxx_helper_has_config(const struct hxxx_helper *hh)
+{
+    if(hh->i_codec == VLC_CODEC_H264)
+    {
+        return hh->h264.i_sps_count &&
+               hh->h264.i_pps_count;
+    }
+    else
+    {
+        return hh->hevc.i_vps_count &&
+               hh->hevc.i_sps_count &&
+               hh->hevc.i_pps_count;
+    }
+}
+
+static block_t *
 h264_helper_get_annexb_config(const struct hxxx_helper *hh)
 {
     if (hh->h264.i_sps_count == 0 || hh->h264.i_pps_count == 0)
@@ -761,7 +667,7 @@ h264_helper_get_annexb_config(const struct hxxx_helper *hh)
     return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
 }
 
-block_t *
+static block_t *
 hevc_helper_get_annexb_config(const struct hxxx_helper *hh)
 {
     if (hh->hevc.i_vps_count == 0 || hh->hevc.i_sps_count == 0 ||
@@ -777,7 +683,7 @@ hevc_helper_get_annexb_config(const struct hxxx_helper *hh)
     return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
 }
 
-block_t *
+static block_t *
 h264_helper_get_avcc_config(const struct hxxx_helper *hh)
 {
     const struct hxxx_helper_nal *p_nal;
@@ -813,7 +719,7 @@ h264_helper_get_avcc_config(const struct hxxx_helper *hh)
                             pp_spsext_bufs, p_spsext_sizes, hh->h264.i_spsext_count);
 }
 
-block_t *
+static block_t *
 hevc_helper_get_hvcc_config(const struct hxxx_helper *hh)
 {
     struct hevc_dcr_params params = {};
@@ -863,6 +769,33 @@ hevc_helper_get_hvcc_config(const struct hxxx_helper *hh)
     return block_heap_Alloc(p_dcr, i_dcr);
 }
 
+block_t * hxxx_helper_get_extradata_chain(const struct hxxx_helper *hh)
+{
+    if(hh->i_codec == VLC_CODEC_H264)
+    {
+        return hh->i_output_nal_length_size ? h264_helper_get_avcc_config(hh)
+                                            : h264_helper_get_annexb_config(hh);
+    }
+    else
+    {
+        return hh->i_output_nal_length_size ? hevc_helper_get_hvcc_config(hh)
+                                            : hevc_helper_get_annexb_config(hh);
+    }
+}
+
+block_t * hxxx_helper_get_extradata_block(const struct hxxx_helper *hh)
+{
+    block_t *b = hxxx_helper_get_extradata_chain(hh);
+    if(b)
+    {
+        block_t *g = block_ChainGather(b);
+        if(g)
+            return g;
+        block_Release(b);
+    }
+    return NULL;
+}
+
 static const struct hxxx_helper_nal *
 h264_helper_get_current_sps(const struct hxxx_helper *hh)
 {


=====================================
modules/codec/hxxx_helper.h
=====================================
@@ -48,10 +48,10 @@ struct hxxx_helper
 {
     vlc_object_t *p_obj; /* for logs */
     vlc_fourcc_t i_codec;
-    bool b_need_xvcC; /* Need avcC or hvcC */
-
-    bool b_is_xvcC;
-    uint8_t i_nal_length_size;
+    uint8_t i_input_nal_length_size;
+    uint8_t i_output_nal_length_size;
+    uint8_t i_config_version_prev;
+    uint8_t i_config_version;
     union {
         struct {
             struct hxxx_helper_nal sps_list[H264_SPS_ID_MAX + 1];
@@ -76,26 +76,40 @@ struct hxxx_helper
             uint8_t i_previous_nal_type;
         } hevc;
     };
-
-    /* Process the block: do the AnnexB <-> xvcC conversion if needed. If
-     * p_config_changed is not NULL, parse nals to detect a SPS/PPS or a video
-     * size change. */
-    block_t * (*pf_process_block)(struct hxxx_helper *hh, block_t *p_block,
-                                  bool *p_config_changed);
 };
 
+/* Init:
+ * i_input_length_size set xvcC nal length or 0 for AnnexB (overriden by extradata)
+ * i_output_length_size set xvcC nal length or 0 for AnnexB */
 void hxxx_helper_init(struct hxxx_helper *hh, vlc_object_t *p_obj,
-                      vlc_fourcc_t i_codec, bool b_need_xvcC);
+                      vlc_fourcc_t i_codec, uint8_t i_input_length_size,
+                      uint8_t i_output_length_size);
+
 void hxxx_helper_clean(struct hxxx_helper *hh);
 
+/* Process raw NAL buffer:
+ * No framing prefix */
+int hxxx_helper_process_nal(struct hxxx_helper *hh, const uint8_t *, size_t);
+
+/* Process the buffer:*/
+int hxxx_helper_process_buffer(struct hxxx_helper *hh, const uint8_t *, size_t);
+
+/* Process the block:
+ * Does AnnexB <-> xvcC conversion if needed. */
+block_t * hxxx_helper_process_block(struct hxxx_helper *hh, block_t *p_block);
+
+/* Set Extra:
+ * Also changes/set the input to match xvcC nal_size of Annexb format */
 int hxxx_helper_set_extra(struct hxxx_helper *hh, const void *p_extra,
                           size_t i_extra);
 
-block_t *h264_helper_get_annexb_config(const struct hxxx_helper *hh);
-block_t *hevc_helper_get_annexb_config(const struct hxxx_helper *hh);
+/* returns if a configuration parameter has changed since last block/buffer
+ * processing */
+bool hxxx_helper_has_new_config(const struct hxxx_helper *hh);
+bool hxxx_helper_has_config(const struct hxxx_helper *hh);
 
-block_t *h264_helper_get_avcc_config(const struct hxxx_helper *hh);
-block_t *hevc_helper_get_hvcc_config(const struct hxxx_helper *hh);
+block_t * hxxx_helper_get_extradata_chain(const struct hxxx_helper *hh);
+block_t * hxxx_helper_get_extradata_block(const struct hxxx_helper *hh);
 
 int hxxx_helper_get_current_picture_size(const struct hxxx_helper *hh,
                                          unsigned *p_w, unsigned *p_h,


=====================================
modules/codec/hxxx_helper_testdec.c
=====================================
@@ -45,13 +45,12 @@ DecodeBlock(decoder_t *dec, block_t *block)
     if (block == NULL)
         return VLCDEC_SUCCESS;
 
-    bool config_changed;
-    block = sys->hh.pf_process_block(&sys->hh, block, &config_changed);
+    block = hxxx_helper_process_block(&sys->hh, block);
 
     if (block == NULL)
         return VLCDEC_SUCCESS;
 
-    if (config_changed)
+    if (hxxx_helper_has_new_config(&sys->hh))
     {
         int ret;
         video_color_primaries_t primaries;
@@ -127,8 +126,8 @@ OpenDecoder(vlc_object_t *this)
     if (sys == NULL)
         return VLC_EGENERIC;
 
-    hxxx_helper_init(&sys->hh, this, dec->fmt_in.i_codec,
-                     var_InheritBool(this, "hxxx-helper-testdec-xvcC"));
+    hxxx_helper_init(&sys->hh, this, dec->fmt_in.i_codec, 0,
+                     var_InheritBool(this, "hxxx-helper-testdec-xvcC") ? 4 : 0);
 
     int ret = hxxx_helper_set_extra(&sys->hh, dec->fmt_in.p_extra,
                                     dec->fmt_in.i_extra);


=====================================
modules/codec/omxil/mediacodec.c
=====================================
@@ -284,11 +284,11 @@ static int H264SetCSD(decoder_t *p_dec, bool *p_size_changed)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     struct hxxx_helper *hh = &p_sys->video.hh;
-    assert(hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0);
+    assert(hxxx_helper_has_config(hh));
 
-    block_t *p_spspps_blocks = h264_helper_get_annexb_config(hh);
+    block_t *p_spspps_blocks = hxxx_helper_get_extradata_chain(hh);
 
-    if (p_spspps_blocks != NULL)
+    if (p_spspps_blocks != NULL && p_spspps_blocks->p_next)
         CSDInit(p_sys, p_spspps_blocks, 2);
 
     HXXXInitSize(p_dec, p_size_changed);
@@ -302,20 +302,11 @@ static int HEVCSetCSD(decoder_t *p_dec, bool *p_size_changed)
     decoder_sys_t *p_sys = p_dec->p_sys;
     struct hxxx_helper *hh = &p_sys->video.hh;
 
-    assert(hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
-           hh->hevc.i_pps_count > 0 );
+    assert(hxxx_helper_has_config(hh));
 
-    block_t *p_xps_blocks = hevc_helper_get_annexb_config(hh);
-    if (p_xps_blocks != NULL)
-    {
-        block_t *p_monolith = block_ChainGather(p_xps_blocks);
-        if (p_monolith == NULL)
-        {
-            block_ChainRelease(p_xps_blocks);
-            return VLC_ENOMEM;
-        }
-        CSDInit(p_sys, p_monolith, 1);
-    }
+    block_t *p_xps = hxxx_helper_get_extradata_block(hh);
+    if (p_xps != NULL)
+        CSDInit(p_sys, p_xps, 1);
 
     HXXXInitSize(p_dec, p_size_changed);
     return VLC_SUCCESS;
@@ -329,14 +320,13 @@ static int ParseVideoExtraH264(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
     int i_ret = hxxx_helper_set_extra(hh, p_extra, i_extra);
     if (i_ret != VLC_SUCCESS)
         return i_ret;
-    assert(hh->pf_process_block != NULL);
 
     if (p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
         p_sys->b_adaptive = true;
 
     p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
 
-    if (hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0)
+    if (hxxx_helper_has_config(hh))
         return H264SetCSD(p_dec, NULL);
     return VLC_SUCCESS;
 }
@@ -349,15 +339,13 @@ static int ParseVideoExtraHEVC(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
     int i_ret = hxxx_helper_set_extra(hh, p_extra, i_extra);
     if (i_ret != VLC_SUCCESS)
         return i_ret;
-    assert(hh->pf_process_block != NULL);
 
     if (p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
         p_sys->b_adaptive = true;
 
     p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
 
-    if (hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
-        hh->hevc.i_pps_count > 0 )
+    if (hxxx_helper_has_config(hh))
         return HEVCSetCSD(p_dec, NULL);
     return VLC_SUCCESS;
 }
@@ -902,7 +890,7 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
         case VLC_CODEC_H264:
         case VLC_CODEC_HEVC:
             hxxx_helper_init(&p_sys->video.hh, VLC_OBJECT(p_dec),
-                             p_dec->fmt_in.i_codec, false);
+                             p_dec->fmt_in.i_codec, 0, 0);
             break;
         }
         p_sys->pf_on_new_block = Video_OnNewBlock;
@@ -1745,27 +1733,24 @@ static int VideoHXXX_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     struct hxxx_helper *hh = &p_sys->video.hh;
-    bool b_config_changed = false;
-    bool *p_config_changed = p_sys->b_adaptive ? NULL : &b_config_changed;
 
-    *pp_block = hh->pf_process_block(hh, *pp_block, p_config_changed);
+    *pp_block = hxxx_helper_process_block(hh, *pp_block);
     if (!*pp_block)
         return 0;
-    if (b_config_changed)
+    if (!p_sys->b_adaptive && hxxx_helper_has_new_config(hh))
     {
         bool b_size_changed;
         int i_ret;
         switch (p_dec->fmt_in.i_codec)
         {
         case VLC_CODEC_H264:
-            if (hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0)
+            if (hxxx_helper_has_config(hh))
                 i_ret = H264SetCSD(p_dec, &b_size_changed);
             else
                 i_ret = VLC_EGENERIC;
             break;
         case VLC_CODEC_HEVC:
-            if (hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
-                hh->hevc.i_pps_count > 0 )
+            if (hxxx_helper_has_config(hh))
                 i_ret = HEVCSetCSD(p_dec, &b_size_changed);
             else
                 i_ret = VLC_EGENERIC;


=====================================
modules/codec/videotoolbox.c
=====================================
@@ -249,7 +249,7 @@ static bool FillReorderInfoH264(decoder_t *p_dec, const block_t *p_block,
     decoder_sys_t *p_sys = p_dec->p_sys;
     hxxx_iterator_ctx_t itctx;
     hxxx_iterator_init(&itctx, p_block->p_buffer, p_block->i_buffer,
-                       p_sys->hh.i_nal_length_size);
+                       p_sys->hh.i_output_nal_length_size);
 
     const uint8_t *p_nal; size_t i_nal;
     struct
@@ -343,7 +343,9 @@ static bool FillReorderInfoH264(decoder_t *p_dec, const block_t *p_block,
 static block_t *ProcessBlockH264(decoder_t *p_dec, block_t *p_block, bool *pb_config_changed)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    return p_sys->hh.pf_process_block(&p_sys->hh, p_block, pb_config_changed);
+    p_block = hxxx_helper_process_block(&p_sys->hh, p_block);
+    *pb_config_changed = hxxx_helper_has_new_config(&p_sys->hh);
+    return p_block;
 }
 
 
@@ -352,7 +354,7 @@ static bool InitH264(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
     h264_poc_context_init(&p_sys->h264_pocctx);
     hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec),
-                     p_dec->fmt_in.i_codec, true);
+                     p_dec->fmt_in.i_codec, 0, 4);
     return hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra,
                                              p_dec->fmt_in.i_extra) == VLC_SUCCESS;
 }
@@ -368,17 +370,17 @@ static CFDictionaryRef CopyDecoderExtradataH264(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     CFDictionaryRef extradata = NULL;
-    if (p_dec->fmt_in.i_extra && p_sys->hh.b_is_xvcC)
+    if (p_dec->fmt_in.i_extra && p_sys->hh.i_input_nal_length_size)
     {
         /* copy DecoderConfiguration */
         extradata = ExtradataInfoCreate(CFSTR("avcC"),
                                         p_dec->fmt_in.p_extra,
                                         p_dec->fmt_in.i_extra);
     }
-    else if (p_sys->hh.h264.i_pps_count && p_sys->hh.h264.i_sps_count)
+    else if (hxxx_helper_has_config(&p_sys->hh))
     {
         /* build DecoderConfiguration from gathered */
-        block_t *p_avcC = h264_helper_get_avcc_config(&p_sys->hh);
+        block_t *p_avcC = hxxx_helper_get_extradata_block(&p_sys->hh);
         if (p_avcC)
         {
             extradata = ExtradataInfoCreate(CFSTR("avcC"),
@@ -440,8 +442,7 @@ static bool CodecSupportedH264(decoder_t *p_dec)
 static bool LateStartH264(decoder_t *p_dec)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    return (p_dec->fmt_in.i_extra == 0 &&
-            (!p_sys->hh.h264.i_pps_count || !p_sys->hh.h264.i_sps_count) );
+    return (p_dec->fmt_in.i_extra == 0 && !hxxx_helper_has_config(&p_sys->hh));
 }
 
 static bool ConfigureVoutH264(decoder_t *p_dec)
@@ -542,7 +543,7 @@ static bool InitHEVC(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
     hevc_poc_cxt_init(&p_sys->hevc_pocctx);
     hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec),
-                     p_dec->fmt_in.i_codec, true);
+                     p_dec->fmt_in.i_codec, 0, 4);
     return hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra,
                                              p_dec->fmt_in.i_extra) == VLC_SUCCESS;
 }
@@ -600,7 +601,7 @@ static bool FillReorderInfoHEVC(decoder_t *p_dec, const block_t *p_block,
     decoder_sys_t *p_sys = p_dec->p_sys;
     hxxx_iterator_ctx_t itctx;
     hxxx_iterator_init(&itctx, p_block->p_buffer, p_block->i_buffer,
-                       p_sys->hh.i_nal_length_size);
+                       p_sys->hh.i_output_nal_length_size);
 
     const uint8_t *p_nal; size_t i_nal;
     struct
@@ -720,19 +721,17 @@ static CFDictionaryRef CopyDecoderExtradataHEVC(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     CFDictionaryRef extradata = NULL;
-    if (p_dec->fmt_in.i_extra && p_sys->hh.b_is_xvcC)
+    if (p_dec->fmt_in.i_extra && p_sys->hh.i_input_nal_length_size)
     {
         /* copy DecoderConfiguration */
         extradata = ExtradataInfoCreate(CFSTR("hvcC"),
                                         p_dec->fmt_in.p_extra,
                                         p_dec->fmt_in.i_extra);
     }
-    else if (p_sys->hh.hevc.i_pps_count &&
-             p_sys->hh.hevc.i_sps_count &&
-             p_sys->hh.hevc.i_vps_count)
+    else if (hxxx_helper_has_config(&p_sys->hh))
     {
         /* build DecoderConfiguration from gathered */
-        block_t *p_hvcC = hevc_helper_get_hvcc_config(&p_sys->hh);
+        block_t *p_hvcC = hxxx_helper_get_extradata_block(&p_sys->hh);
         if (p_hvcC)
         {
             extradata = ExtradataInfoCreate(CFSTR("hvcC"),
@@ -747,10 +746,7 @@ static CFDictionaryRef CopyDecoderExtradataHEVC(decoder_t *p_dec)
 static bool LateStartHEVC(decoder_t *p_dec)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    return (p_dec->fmt_in.i_extra == 0 &&
-            (!p_sys->hh.hevc.i_pps_count ||
-             !p_sys->hh.hevc.i_sps_count ||
-             !p_sys->hh.hevc.i_vps_count) );
+    return (p_dec->fmt_in.i_extra == 0 && !hxxx_helper_has_config(&p_sys->hh));
 }
 
 static bool CodecSupportedHEVC(decoder_t *p_dec)


=====================================
modules/hw/nvdec/nvdec.c
=====================================
@@ -609,22 +609,18 @@ static int CuvidPushBlock(decoder_t *p_dec, block_t *p_block)
 static block_t * HXXXProcessBlock(decoder_t *p_dec, block_t *p_block)
 {
     nvdec_ctx_t *p_sys = p_dec->p_sys;
-    if (p_sys->hh.b_is_xvcC && !p_sys->b_xps_pushed) {
-        block_t *p_xps_blocks;   // parameter set blocks (SPS/PPS/VPS)
-        if (p_dec->fmt_in.i_codec == VLC_CODEC_H264) {
-            p_xps_blocks = h264_helper_get_annexb_config(&p_sys->hh);
-        } else if (p_dec->fmt_in.i_codec == VLC_CODEC_HEVC) {
-            p_xps_blocks = hevc_helper_get_annexb_config(&p_sys->hh);
-        } else {
-            return NULL;
-        }
-        for (block_t *p_b = p_xps_blocks; p_b != NULL; p_b = p_b->p_next) {
-            CuvidPushRawBlock(p_dec, p_b->p_buffer, p_b->i_buffer);
+    if (p_sys->hh.i_input_nal_length_size && !p_sys->b_xps_pushed) {
+        // parameter set blocks (SPS/PPS/VPS)
+        block_t *p_xps = hxxx_helper_get_extradata_block(&p_sys->hh);
+        if(p_xps)
+        {
+            CuvidPushRawBlock(p_dec, p_xps->p_buffer, p_xps->i_buffer);
+            block_Release(p_xps);
+            p_sys->b_xps_pushed = true;
         }
-        p_sys->b_xps_pushed = true;
     }
 
-    return p_sys->hh.pf_process_block(&p_sys->hh, p_block, NULL);
+    return hxxx_helper_process_block(&p_sys->hh, p_block);
 }
 
 static block_t * ProcessVC1Block(decoder_t *p_dec, block_t *p_block)
@@ -761,7 +757,7 @@ static int OpenDecoder(vlc_object_t *p_this)
             p_sys->b_is_hxxx = true;
             p_sys->i_nb_surface = MAX_HXXX_SURFACES;
             hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec),
-                             p_dec->fmt_in.i_codec, false);
+                             p_dec->fmt_in.i_codec, 0, 0);
             result = hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra,
                                            p_dec->fmt_in.i_extra);
             if (result != VLC_SUCCESS) {


=====================================
test/Makefile.am
=====================================
@@ -40,6 +40,7 @@ check_PROGRAMS = \
 	test_modules_packetizer_h264 \
 	test_modules_packetizer_hevc \
 	test_modules_packetizer_mpegvideo \
+	test_modules_codec_hxxx_helper \
 	test_modules_keystore \
 	test_modules_demux_timestamps_filter \
 	test_modules_demux_ts_pes \
@@ -159,6 +160,13 @@ test_modules_demux_ts_pes_SOURCES = modules/demux/ts_pes.c \
 test_modules_playlist_m3u_SOURCES = modules/demux/playlist/m3u.c
 test_modules_playlist_m3u_LDADD = $(LIBVLCCORE) $(LIBVLC)
 
+test_modules_codec_hxxx_helper_SOURCES = modules/codec/hxxx_helper.c \
+                                      ../modules/codec/hxxx_helper.c \
+                                      ../modules/packetizer/hxxx_nal.c \
+                                      ../modules/packetizer/h264_slice.c \
+                                      ../modules/packetizer/h264_nal.c \
+                                      ../modules/packetizer/hevc_nal.c
+test_modules_codec_hxxx_helper_LDADD = $(LIBVLCCORE) $(LIBVLC)
 
 test_src_video_output_SOURCES = \
 	src/video_output/video_output.c \


=====================================
test/modules/codec/hxxx_helper.c
=====================================
@@ -0,0 +1,278 @@
+/*****************************************************************************
+ * hxxx_helper.c: hxxx_helper packetizer unit testing
+ *****************************************************************************
+ * Copyright (C) 2021 VideoLabs, VideoLAN and VLC Authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "../../libvlc/test.h"
+
+const char vlc_module_name[] = "hxxx_helper";
+
+#include "../../../modules/packetizer/hxxx_nal.h"
+#include "../../../modules/codec/hxxx_helper.h"
+
+const uint8_t test_samples_raw_h264_annexb[] = {
+  0x00, 0x00, 0x00, 0x01, 0x67, 0xf4, 0x00, 0x0a, 0x91, 0x9b, 0x2b, 0xd0,
+  0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x19, 0x07, 0x89, 0x12,
+  0xcb, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xec, 0x44, 0x84, 0x40, 0x00, 0x00,
+  0x01, 0x65, 0x88, 0x84, 0x00, 0x37, 0xff, 0xfe, 0xf5, 0xdb, 0xf3, 0x2c,
+  0xac, 0x66, 0x67, 0xff, 0x00, 0x00, 0x01, 0x41, 0x9a, 0x24, 0x6c, 0x46,
+  0xff, 0xfe, 0xc0 };
+
+const uint8_t test_extradata_raw_h264_annexb[] = {
+  0x00, 0x00, 0x00, 0x01, 0x67, 0xf4, 0x00, 0x0a, 0x91, 0x9b, 0x2b, 0xd0,
+  0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x19, 0x07, 0x89, 0x12,
+  0xcb, 0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xec, 0x44, 0x84, 0x40 };
+
+const uint8_t test_extradata_raw_h264_avc1[] = {
+  0x01, 0xf4, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x15, 0x67, 0xf4, 0x00, 0x0a,
+  0x91, 0x9b, 0x2b, 0xd0, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00,
+  0x19, 0x07, 0x89, 0x12, 0xcb, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xec, 0x44,
+  0x84, 0x40 };
+
+const uint8_t test_samples_raw_h264_avc1[] = {
+  0x00, 0x00, 0x00, 0x15, 0x67, 0xf4, 0x00, 0x0a, 0x91, 0x9b, 0x2b, 0xd0,
+  0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x19, 0x07, 0x89, 0x12,
+  0xcb, 0x00, 0x00, 0x00, 0x06, 0x68, 0xeb, 0xec, 0x44, 0x84, 0x40, 0x00,
+  0x00, 0x00, 0x0f, 0x65, 0x88, 0x84, 0x00, 0x37, 0xff, 0xfe, 0xf5, 0xdb,
+  0xf3, 0x2c, 0xac, 0x66, 0x67, 0xff, 0x00, 0x00, 0x00, 0x08, 0x41, 0x9a,
+  0x24, 0x6c, 0x46, 0xff, 0xfe, 0xc0 };
+
+const uint8_t test_samples_raw_h265_annexb[] = {
+  0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+  0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e,
+  0x95, 0x98, 0x09, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 0x00,
+  0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e, 0x90,
+  0x11, 0x08, 0xb2, 0xca, 0xcd, 0x57, 0x95, 0xcd, 0x40, 0x80, 0x80, 0x01,
+  0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x19, 0x08, 0x00,
+  0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0x18, 0x31, 0x08, 0x90, 0x00, 0x00,
+  0x01, 0x28, 0x01, 0xaf, 0x19, 0x80, 0xef, 0xef, 0xcb, 0x5f, 0xfe, 0x52,
+  0x0b, 0xfe, 0xbb, 0x6d, 0xfd, 0x0f, 0xf8 };
+
+const uint8_t test_samples_raw_h265_hvc1[] = {
+  0x00, 0x00, 0x00, 0x17, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+  0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e,
+  0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x29, 0x42, 0x01, 0x01, 0x04, 0x08,
+  0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e,
+  0x90, 0x11, 0x08, 0xb2, 0xca, 0xcd, 0x57, 0x95, 0xcd, 0x40, 0x80, 0x80,
+  0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x19, 0x08,
+  0x00, 0x00, 0x00, 0x08, 0x44, 0x01, 0xc1, 0x73, 0x18, 0x31, 0x08, 0x90,
+  0x00, 0x00, 0x00, 0x12, 0x28, 0x01, 0xaf, 0x19, 0x80, 0xef, 0xef, 0xcb,
+  0x5f, 0xfe, 0x52, 0x0b, 0xfe, 0xbb, 0x6d, 0xfd, 0x0f, 0xf8 };
+
+const uint8_t test_extradata_raw_h265_annexb[] = {
+  0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+  0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e,
+  0x95, 0x98, 0x09, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 0x00,
+  0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e, 0x90,
+  0x11, 0x08, 0xb2, 0xca, 0xcd, 0x57, 0x95, 0xcd, 0x40, 0x80, 0x80, 0x01,
+  0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x19, 0x08, 0x00,
+  0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0x18, 0x31, 0x08, 0x90 };
+
+const uint8_t test_extradata_raw_h265_hvc1[] = {
+  0x01, 0x04, 0x08, 0x00, 0x00, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x1e, 0xf0, 0x00, 0xfc, 0xff, 0xf8, 0xf8, 0x00, 0x00, 0x0f, 0x03, 0xa0,
+  0x00, 0x01, 0x00, 0x17, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+  0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e,
+  0x95, 0x98, 0x09, 0xa1, 0x00, 0x01, 0x00, 0x29, 0x42, 0x01, 0x01, 0x04,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x1e, 0x90, 0x11, 0x08, 0xb2, 0xca, 0xcd, 0x57, 0x95, 0xcd, 0x40, 0x80,
+  0x80, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x19,
+  0x08, 0xa2, 0x00, 0x01, 0x00, 0x08, 0x44, 0x01, 0xc1, 0x73, 0x18, 0x31,
+  0x08, 0x90 };
+
+static int compare_any(const uint8_t *p0, size_t s0, uint8_t prefix0,
+                       const uint8_t *p1, size_t s1, uint8_t prefix1)
+{
+    hxxx_iterator_ctx_t it0, it1;
+    hxxx_iterator_init(&it0, p0, s0, prefix0);
+    hxxx_iterator_init(&it1, p1, s1, prefix1);
+    const uint8_t *nal0 = NULL, *nal1 = NULL;
+    size_t nalsz0 = 0, nalsz1 = 0;
+    int b0, b1;
+    for(;;)
+    {
+        b0 = it0.i_nal_length_size ? hxxx_iterate_next(&it0, &nal0, &nalsz0)
+                                   : hxxx_annexb_iterate_next(&it0, &nal0, &nalsz0);
+        b1 = it1.i_nal_length_size ? hxxx_iterate_next(&it1, &nal1, &nalsz1)
+                                   : hxxx_annexb_iterate_next(&it1, &nal1, &nalsz1);
+        assert(b0 == b1);
+        if(b0 != b1)
+            return 1;
+        if(!b0)
+            break;
+        assert(nalsz0 == nalsz1);
+        assert(memcmp(nal0, nal1, nalsz0) == 0);
+    }
+    return 0;
+}
+
+static void dump_hex(const char *s, const uint8_t *p, size_t sz)
+{
+    fprintf(stderr, "%s:\t", s);
+    for(size_t i=0; i<sz; i++)
+        fprintf(stderr, "0x%2.2x, ", p[i]);
+    fprintf(stderr, "\n");
+}
+
+static int test_extrainit(vlc_fourcc_t codec,
+                          const uint8_t *p_annexb, size_t i_annexb,
+                          const uint8_t *p_xvc, size_t i_xvc)
+{
+    struct hxxx_helper hlpr;
+
+    fprintf(stderr,"AnnexB extra init\n");
+    hxxx_helper_init(&hlpr, NULL, codec, 0, 0);
+    hxxx_helper_set_extra(&hlpr, p_annexb, i_annexb);
+    assert(hlpr.i_input_nal_length_size == 0);
+    assert(hlpr.i_output_nal_length_size == 0);
+
+    block_t *b = hxxx_helper_get_extradata_block(&hlpr);
+    if(!b)
+        return 1;
+    assert(compare_any(b->p_buffer, b->i_buffer, 0, p_annexb, i_annexb, 0) == 0);
+    block_Release(b);
+    hxxx_helper_clean(&hlpr);
+
+    fprintf(stderr,"xVC1 extra init\n");
+    hxxx_helper_init(&hlpr, NULL, codec, 0, 0);
+    hxxx_helper_set_extra(&hlpr, p_xvc, i_xvc);
+    assert(hlpr.i_input_nal_length_size);
+    assert(hlpr.i_output_nal_length_size == 0);
+    b = hxxx_helper_get_extradata_block(&hlpr);
+    if(!b)
+        return 1;
+    assert(compare_any(b->p_buffer, b->i_buffer, 0, p_annexb, i_annexb, 0) == 0);
+    block_Release(b);
+
+    hxxx_helper_clean(&hlpr);
+
+    return 0;
+}
+
+static int test_any(struct hxxx_helper *hlpr,
+                    const uint8_t *p_in, size_t i_in,
+                    const uint8_t *p_out, size_t i_out,
+                    const uint8_t *p_extraout, size_t i_extraout)
+{
+    block_t *b = block_Alloc(i_in);
+    if(!b)
+        return 1;
+    memcpy(b->p_buffer, p_in, i_in);
+
+    dump_hex("in", b->p_buffer, b->i_buffer);
+
+    assert(!hxxx_helper_has_new_config(hlpr));
+    b = hxxx_helper_process_block(hlpr, b);
+    if(!b)
+        return 1;
+    assert(hxxx_helper_has_new_config(hlpr));
+
+    dump_hex("out", b->p_buffer, b->i_buffer);
+
+    if(compare_any(b->p_buffer, b->i_buffer, hlpr->i_output_nal_length_size,
+                   p_out, i_out, hlpr->i_output_nal_length_size))
+    {
+        block_Release(b);
+        return 1;
+    }
+
+    block_Release(b);
+
+    b = hxxx_helper_get_extradata_block(hlpr);
+    if(!b)
+        return 1;
+
+    dump_hex("extra", b->p_buffer, b->i_buffer);
+    if(hlpr->i_output_nal_length_size)
+    {
+        if(b->i_buffer != i_extraout || memcmp(b->p_buffer, p_extraout, i_extraout))
+        {
+            assert(b->i_buffer == i_extraout);
+            assert(!memcmp(b->p_buffer, p_extraout, i_extraout));
+            block_Release(b);
+            return 1;
+        }
+    }
+    else if(compare_any(b->p_buffer, b->i_buffer, 0, p_extraout, i_extraout, 0))
+    {
+        block_Release(b);
+        return 1;
+    }
+
+    return 0;
+}
+
+#define RUN_TEST(codec, source0, prefix0, source1, prefix1) \
+    do\
+    {\
+        struct hxxx_helper hlpr;\
+        hxxx_helper_init(&hlpr, NULL, codec, prefix0, prefix1);\
+        ret = test_any(&hlpr, \
+                       test_samples_raw_##source0, sizeof(test_samples_raw_##source0),\
+                       test_samples_raw_##source1, sizeof(test_samples_raw_##source1),\
+                       test_extradata_raw_##source1, sizeof(test_extradata_raw_##source1));\
+        hxxx_helper_clean(&hlpr);\
+        if(ret) return ret;\
+    } while(0)
+
+static int test_annexb()
+{
+    int ret;
+    fprintf(stderr,"H264\n");
+    fprintf(stderr,"AnnexB -> AnnexB\n");
+    RUN_TEST(VLC_CODEC_H264, h264_annexb, 0, h264_annexb, 0);
+    fprintf(stderr,"AVC1 -> AVC1\n");
+    RUN_TEST(VLC_CODEC_H264, h264_avc1, 4, h264_avc1, 4);
+    fprintf(stderr,"AVC1 -> AnnexB\n");
+    RUN_TEST(VLC_CODEC_H264, h264_avc1, 4, h264_annexb, 0);
+    fprintf(stderr,"AnnexB -> AVC1\n");
+    RUN_TEST(VLC_CODEC_H264, h264_annexb, 0, h264_avc1, 4);
+
+    ret = test_extrainit(VLC_CODEC_H264,
+                test_extradata_raw_h264_annexb, sizeof(test_extradata_raw_h264_annexb),
+                test_extradata_raw_h264_avc1, sizeof(test_extradata_raw_h264_avc1));
+    if(ret) return ret;
+
+    fprintf(stderr,"HEVC\n");
+    fprintf(stderr,"AnnexB -> AnnexB\n");
+    RUN_TEST(VLC_CODEC_HEVC, h265_annexb, 0, h265_annexb, 0);
+    fprintf(stderr,"HVC1 -> HVC1\n");
+    RUN_TEST(VLC_CODEC_HEVC, h265_hvc1, 4, h265_hvc1, 4);
+    fprintf(stderr,"HVC1 -> AnnexB\n");
+    RUN_TEST(VLC_CODEC_HEVC, h265_hvc1, 4, h265_annexb, 0);
+    fprintf(stderr,"AnnexB -> HVC1\n");
+    RUN_TEST(VLC_CODEC_HEVC, h265_annexb, 0, h265_hvc1, 4);
+
+    ret = test_extrainit(VLC_CODEC_HEVC,
+                test_extradata_raw_h265_annexb, sizeof(test_extradata_raw_h265_annexb),
+                test_extradata_raw_h265_hvc1, sizeof(test_extradata_raw_h265_hvc1));
+    if(ret) return ret;
+
+    return 0;
+}
+
+
+int main(void)
+{
+    test_init();
+
+    return test_annexb();
+}



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7dc44f2d20a42fd43c1545a09b8b7c0e00d1b28d...bce57ed795b288901d7b6f50d46fe74c667e6792

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7dc44f2d20a42fd43c1545a09b8b7c0e00d1b28d...bce57ed795b288901d7b6f50d46fe74c667e6792
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list