[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