From ece0487e183ead1e5b6ab13104b27d427b41269c Mon Sep 17 00:00:00 2001 From: Yusuke Nakamura Date: Wed, 10 Sep 2014 04:57:09 +0900 Subject: [PATCH] nalu: Make a common function to find the start code. Fix possible infinite loop when whole stream is filled with 0. --- cli/importer.c | 32 ++++++++------------------------ codecs/h264.c | 4 +++- codecs/hevc.c | 4 +++- codecs/nalu.h | 23 +++++++++++++++++++++++ lsmash.h | 2 +- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/cli/importer.c b/cli/importer.c index e71608b..7bbd9af 100644 --- a/cli/importer.c +++ b/cli/importer.c @@ -3356,17 +3356,9 @@ static int h264_importer_probe( importer_t *importer ) if( !h264_imp ) return -1; lsmash_bs_t *bs = h264_imp->bs; - uint64_t first_sc_head_pos = 0; - while( 1 ) - { - /* The first NALU of an AU in decoding order shall have long start code (0x00000001). */ - if( 0x00000001 == lsmash_bs_show_be32( bs, first_sc_head_pos ) ) - break; - /* Invalid if encountered any value of non-zero before the first start code. */ - if( lsmash_bs_show_byte( bs, first_sc_head_pos ) ) - goto fail; - ++first_sc_head_pos; - } + uint64_t first_sc_head_pos = nalu_find_first_start_code( bs ); + if( first_sc_head_pos == UINT64_MAX ) + goto fail; /* OK. It seems the stream has a long start code of H.264. */ importer->info = h264_imp; h264_info_t *info = &h264_imp->info; @@ -3377,8 +3369,8 @@ static int h264_importer_probe( importer_t *importer ) /* Go back to the start code of the first NALU. */ h264_imp->status = IMPORTER_OK; lsmash_bs_read_seek( bs, first_sc_head_pos, SEEK_SET ); - info->prev_nalu_type = H264_NALU_TYPE_UNSPECIFIED0; h264_imp->sc_head_pos = first_sc_head_pos; + info->prev_nalu_type = H264_NALU_TYPE_UNSPECIFIED0; uint8_t *temp_au = info->picture.au; uint8_t *temp_incomplete_au = info->picture.incomplete_au; memset( &info->picture, 0, sizeof(h264_picture_info_t) ); @@ -4011,17 +4003,9 @@ static int hevc_importer_probe( importer_t *importer ) if( !hevc_imp ) return -1; lsmash_bs_t *bs = hevc_imp->bs; - uint64_t first_sc_head_pos = 0; - while( 1 ) - { - /* The first NALU of an AU in decoding order shall have long start code (0x00000001). */ - if( 0x00000001 == lsmash_bs_show_be32( bs, first_sc_head_pos ) ) - break; - /* Invalid if encountered any value of non-zero before the first start code. */ - if( lsmash_bs_show_byte( bs, first_sc_head_pos ) ) - goto fail; - ++first_sc_head_pos; - } + uint64_t first_sc_head_pos = nalu_find_first_start_code( bs ); + if( first_sc_head_pos == UINT64_MAX ) + goto fail; /* OK. It seems the stream has a long start code of HEVC. */ importer->info = hevc_imp; hevc_info_t *info = &hevc_imp->info; @@ -4032,8 +4016,8 @@ static int hevc_importer_probe( importer_t *importer ) /* Go back to the start code of the first NALU. */ hevc_imp->status = IMPORTER_OK; lsmash_bs_read_seek( bs, first_sc_head_pos, SEEK_SET ); - info->prev_nalu_type = HEVC_NALU_TYPE_UNKNOWN; hevc_imp->sc_head_pos = first_sc_head_pos; + info->prev_nalu_type = HEVC_NALU_TYPE_UNKNOWN; uint8_t *temp_au = info->au.data; uint8_t *temp_incomplete_au = info->au.incomplete_data; memset( &info->au, 0, sizeof(hevc_access_unit_t) ); diff --git a/codecs/h264.c b/codecs/h264.c index 9f39ae4..3d34143 100644 --- a/codecs/h264.c +++ b/codecs/h264.c @@ -2212,11 +2212,13 @@ int lsmash_setup_h264_specific_parameters_from_access_unit lsmash_bs_t *bs = &(lsmash_bs_t){ 0 }; if( lsmash_bs_set_empty_stream( bs, data, data_length ) < 0 ) return -1; + uint64_t sc_head_pos = nalu_find_first_start_code( bs ); + if( sc_head_pos == UINT64_MAX ) + return -1; if( h264_setup_parser( info, 1 ) < 0 ) return h264_parse_failed( info ); h264_stream_buffer_t *sb = &info->buffer; h264_slice_info_t *slice = &info->slice; - uint64_t sc_head_pos = 0; while( 1 ) { h264_nalu_header_t nuh; diff --git a/codecs/hevc.c b/codecs/hevc.c index f0f066e..6f74d28 100644 --- a/codecs/hevc.c +++ b/codecs/hevc.c @@ -2687,11 +2687,13 @@ int lsmash_setup_hevc_specific_parameters_from_access_unit lsmash_bs_t *bs = &(lsmash_bs_t){ 0 }; if( lsmash_bs_set_empty_stream( bs, data, data_length ) < 0 ) return -1; + uint64_t sc_head_pos = nalu_find_first_start_code( bs ); + if( sc_head_pos == UINT64_MAX ) + return -1; if( hevc_setup_parser( info, 1 ) < 0 ) return hevc_parse_failed( info ); hevc_stream_buffer_t *sb = &info->buffer; hevc_slice_info_t *slice = &info->slice; - uint64_t sc_head_pos = 0; while( 1 ) { hevc_nalu_header_t nuh; diff --git a/codecs/nalu.h b/codecs/nalu.h index 8455e63..2eb79de 100644 --- a/codecs/nalu.h +++ b/codecs/nalu.h @@ -227,3 +227,26 @@ static inline int nalu_check_next_short_start_code { return ((buf_pos + 2) < buf_end) && !buf_pos[0] && !buf_pos[1] && (buf_pos[2] == 0x01); } + +/* Return the offset from the beginning of stream if a start code is found. + * Return UINT64_MAX otherwise. */ +static inline uint64_t nalu_find_first_start_code +( + lsmash_bs_t *bs +) +{ + uint64_t first_sc_head_pos = 0; + while( 1 ) + { + if( lsmash_bs_is_end( bs, first_sc_head_pos + NALU_LONG_START_CODE_LENGTH ) ) + return UINT64_MAX; + /* Invalid if encountered any value of non-zero before the first start code. */ + if( lsmash_bs_show_byte( bs, first_sc_head_pos ) ) + return UINT64_MAX; + /* The first NALU of an AU in decoding order shall have long start code (0x00000001). */ + if( 0x00000001 == lsmash_bs_show_be32( bs, first_sc_head_pos ) ) + break; + ++first_sc_head_pos; + } + return first_sc_head_pos; +} diff --git a/lsmash.h b/lsmash.h index ef71cfa..0293692 100644 --- a/lsmash.h +++ b/lsmash.h @@ -35,7 +35,7 @@ ****************************************************************************/ #define LSMASH_VERSION_MAJOR 1 #define LSMASH_VERSION_MINOR 13 -#define LSMASH_VERSION_MICRO 20 +#define LSMASH_VERSION_MICRO 21 #define LSMASH_VERSION_INT( a, b, c ) (((a) << 16) | ((b) << 8) | (c)) -- 2.11.4.GIT