@ -1004,6 +1004,125 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
}
}
static int h264_init_ps ( H264Context * h , const H264SliceContext * sl , int first_slice )
{
const SPS * sps ;
int needs_reinit = 0 , must_reinit , ret ;
if ( first_slice ) {
av_buffer_unref ( & h - > ps . pps_ref ) ;
h - > ps . pps = NULL ;
h - > ps . pps_ref = av_buffer_ref ( h - > ps . pps_list [ sl - > pps_id ] ) ;
if ( ! h - > ps . pps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . pps = ( const PPS * ) h - > ps . pps_ref - > data ;
}
if ( h - > ps . sps ! = ( const SPS * ) h - > ps . sps_list [ h - > ps . pps - > sps_id ] - > data ) {
av_buffer_unref ( & h - > ps . sps_ref ) ;
h - > ps . sps = NULL ;
h - > ps . sps_ref = av_buffer_ref ( h - > ps . sps_list [ h - > ps . pps - > sps_id ] ) ;
if ( ! h - > ps . sps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . sps = ( const SPS * ) h - > ps . sps_ref - > data ;
if ( h - > mb_width ! = h - > ps . sps - > mb_width | |
h - > mb_height ! = h - > ps . sps - > mb_height * ( 2 - h - > ps . sps - > frame_mbs_only_flag ) | |
h - > cur_bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > cur_chroma_format_idc ! = h - > ps . sps - > chroma_format_idc
)
needs_reinit = 1 ;
if ( h - > bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > chroma_format_idc ! = h - > ps . sps - > chroma_format_idc )
needs_reinit = 1 ;
}
sps = h - > ps . sps ;
must_reinit = ( h - > context_initialized & &
( 16 * sps - > mb_width ! = h - > avctx - > coded_width
| | 16 * sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ! = h - > avctx - > coded_height
| | h - > cur_bit_depth_luma ! = sps - > bit_depth_luma
| | h - > cur_chroma_format_idc ! = sps - > chroma_format_idc
| | h - > mb_width ! = sps - > mb_width
| | h - > mb_height ! = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag )
) ) ;
if ( h - > avctx - > pix_fmt = = AV_PIX_FMT_NONE
| | ( non_j_pixfmt ( h - > avctx - > pix_fmt ) ! = non_j_pixfmt ( get_pixel_format ( h , 0 ) ) ) )
must_reinit = 1 ;
if ( first_slice & & av_cmp_q ( sps - > sar , h - > avctx - > sample_aspect_ratio ) )
must_reinit = 1 ;
if ( ! h - > setup_finished ) {
h - > avctx - > profile = ff_h264_get_profile ( sps ) ;
h - > avctx - > level = sps - > level_idc ;
h - > avctx - > refs = sps - > ref_frame_count ;
h - > mb_width = sps - > mb_width ;
h - > mb_height = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ;
h - > mb_num = h - > mb_width * h - > mb_height ;
h - > mb_stride = h - > mb_width + 1 ;
h - > b_stride = h - > mb_width * 4 ;
h - > chroma_y_shift = sps - > chroma_format_idc < = 1 ; // 400 uses yuv420p
h - > width = 16 * h - > mb_width ;
h - > height = 16 * h - > mb_height ;
ret = init_dimensions ( h ) ;
if ( ret < 0 )
return ret ;
if ( sps - > video_signal_type_present_flag ) {
h - > avctx - > color_range = sps - > full_range > 0 ? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG ;
if ( sps - > colour_description_present_flag ) {
if ( h - > avctx - > colorspace ! = sps - > colorspace )
needs_reinit = 1 ;
h - > avctx - > color_primaries = sps - > color_primaries ;
h - > avctx - > color_trc = sps - > color_trc ;
h - > avctx - > colorspace = sps - > colorspace ;
}
}
}
if ( ! h - > context_initialized | | must_reinit | | needs_reinit ) {
int flush_changes = h - > context_initialized ;
h - > context_initialized = 0 ;
if ( sl ! = h - > slice_ctx ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" changing width %d -> %d / height %d -> %d on "
" slice %d \n " ,
h - > width , h - > avctx - > coded_width ,
h - > height , h - > avctx - > coded_height ,
h - > current_slice + 1 ) ;
return AVERROR_INVALIDDATA ;
}
av_assert1 ( first_slice ) ;
if ( flush_changes )
ff_h264_flush_change ( h ) ;
if ( ( ret = get_pixel_format ( h , 1 ) ) < 0 )
return ret ;
h - > avctx - > pix_fmt = ret ;
av_log ( h - > avctx , AV_LOG_VERBOSE , " Reinit context to %dx%d, "
" pix_fmt: %s \n " , h - > width , h - > height , av_get_pix_fmt_name ( h - > avctx - > pix_fmt ) ) ;
if ( ( ret = h264_slice_header_init ( h ) ) < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" h264_slice_header_init() failed \n " ) ;
return ret ;
}
}
return 0 ;
}
/* This function is called right after decoding the slice header for a first
* slice in a field ( or a frame ) . It decides whether we are decoding a new frame
* or a second field in a pair and does the necessary setup .
@ -1011,10 +1130,12 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
static int h264_field_start ( H264Context * h , const H264SliceContext * sl )
{
int i ;
const SPS * sps = h - > ps . sps ;
const SPS * sps ;
int last_pic_structure , last_pic_droppable , ret ;
sps = h - > ps . sps ;
last_pic_droppable = h - > droppable ;
last_pic_structure = h - > picture_structure ;
h - > droppable = ( h - > nal_ref_idc = = 0 ) ;
@ -1205,11 +1326,8 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
{
const SPS * sps ;
const PPS * pps ;
unsigned int pps_id ;
int ret ;
unsigned int slice_type , tmp , i ;
int must_reinit ;
int needs_reinit = 0 ;
int field_pic_flag , bottom_field_flag ;
int first_slice = sl = = h - > slice_ctx & & ! h - > current_slice ;
int frame_num , droppable , picture_structure ;
@ -1299,152 +1417,45 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
}
}
pps_id = get_ue_golomb ( & sl - > gb ) ;
if ( pps_id > = MAX_PPS_COUNT ) {
av_log ( h - > avctx , AV_LOG_ERROR , " pps_id %u out of range \n " , pps_id ) ;
sl - > pps_id = get_ue_golomb ( & sl - > gb ) ;
if ( sl - > pps_id > = MAX_PPS_COUNT ) {
av_log ( h - > avctx , AV_LOG_ERROR , " pps_id %u out of range \n " , sl - > pps_id ) ;
return AVERROR_INVALIDDATA ;
}
if ( ! h - > ps . pps_list [ pps_id ] ) {
if ( ! h - > ps . pps_list [ sl - > pps_id ] ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" non-existing PPS %u referenced \n " ,
pps_id ) ;
sl - > pps_id ) ;
return AVERROR_INVALIDDATA ;
}
pps = ( const PPS * ) h - > ps . pps_list [ pps_id ] - > data ;
pps = ( const PPS * ) h - > ps . pps_list [ sl - > pps_id ] - > data ;
if ( ! h - > ps . sps_list [ pps - > sps_id ] ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" non-existing SPS %u referenced \n " ,
pps - > sps_id ) ;
" non-existing SPS %u referenced \n " , pps - > sps_id ) ;
return AVERROR_INVALIDDATA ;
}
if ( first_slice ) {
av_buffer_unref ( & h - > ps . pps_ref ) ;
h - > ps . pps = NULL ;
h - > ps . pps_ref = av_buffer_ref ( h - > ps . pps_list [ pps_id ] ) ;
if ( ! h - > ps . pps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . pps = ( const PPS * ) h - > ps . pps_ref - > data ;
} else {
if ( ! first_slice ) {
if ( h - > ps . pps - > sps_id ! = pps - > sps_id | |
h - > ps . pps - > transform_8x8_mode ! = pps - > transform_8x8_mode /*||
( h - > setup_finished & & h - > ps . pps ! = pps ) */ ) {
av_log ( h - > avctx , AV_LOG_ERROR , " PPS changed between slices \n " ) ;
return AVERROR_INVALIDDATA ;
}
}
if ( h - > ps . sps ! = ( const SPS * ) h - > ps . sps_list [ h - > ps . pps - > sps_id ] - > data ) {
if ( ! first_slice ) {
if ( h - > ps . sps ! = ( const SPS * ) h - > ps . sps_list [ h - > ps . pps - > sps_id ] - > data ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" SPS changed in the middle of the frame \n " ) ;
return AVERROR_INVALIDDATA ;
}
av_buffer_unref ( & h - > ps . sps_ref ) ;
h - > ps . sps = NULL ;
h - > ps . sps_ref = av_buffer_ref ( h - > ps . sps_list [ h - > ps . pps - > sps_id ] ) ;
if ( ! h - > ps . sps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . sps = ( const SPS * ) h - > ps . sps_ref - > data ;
if ( h - > mb_width ! = h - > ps . sps - > mb_width | |
h - > mb_height ! = h - > ps . sps - > mb_height * ( 2 - h - > ps . sps - > frame_mbs_only_flag ) | |
h - > cur_bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > cur_chroma_format_idc ! = h - > ps . sps - > chroma_format_idc
)
needs_reinit = 1 ;
if ( h - > bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > chroma_format_idc ! = h - > ps . sps - > chroma_format_idc )
needs_reinit = 1 ;
}
pps = h - > ps . pps ;
sps = h - > ps . sps ;
must_reinit = ( h - > context_initialized & &
( 16 * sps - > mb_width ! = h - > avctx - > coded_width
| | 16 * sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ! = h - > avctx - > coded_height
| | h - > cur_bit_depth_luma ! = sps - > bit_depth_luma
| | h - > cur_chroma_format_idc ! = sps - > chroma_format_idc
| | h - > mb_width ! = sps - > mb_width
| | h - > mb_height ! = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag )
) ) ;
if ( h - > avctx - > pix_fmt = = AV_PIX_FMT_NONE
| | ( non_j_pixfmt ( h - > avctx - > pix_fmt ) ! = non_j_pixfmt ( get_pixel_format ( h , 0 ) ) ) )
must_reinit = 1 ;
if ( first_slice & & av_cmp_q ( sps - > sar , h - > avctx - > sample_aspect_ratio ) )
must_reinit = 1 ;
if ( ! h - > setup_finished ) {
h - > avctx - > profile = ff_h264_get_profile ( sps ) ;
h - > avctx - > level = sps - > level_idc ;
h - > avctx - > refs = sps - > ref_frame_count ;
h - > mb_width = sps - > mb_width ;
h - > mb_height = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ;
h - > mb_num = h - > mb_width * h - > mb_height ;
h - > mb_stride = h - > mb_width + 1 ;
h - > b_stride = h - > mb_width * 4 ;
h - > chroma_y_shift = sps - > chroma_format_idc < = 1 ; // 400 uses yuv420p
h - > width = 16 * h - > mb_width ;
h - > height = 16 * h - > mb_height ;
ret = init_dimensions ( h ) ;
if ( ret < 0 )
return ret ;
if ( sps - > video_signal_type_present_flag ) {
h - > avctx - > color_range = sps - > full_range > 0 ? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG ;
if ( sps - > colour_description_present_flag ) {
if ( h - > avctx - > colorspace ! = sps - > colorspace )
needs_reinit = 1 ;
h - > avctx - > color_primaries = sps - > color_primaries ;
h - > avctx - > color_trc = sps - > color_trc ;
h - > avctx - > colorspace = sps - > colorspace ;
}
}
}
if ( ! h - > context_initialized | | must_reinit | | needs_reinit ) {
int flush_changes = h - > context_initialized ;
h - > context_initialized = 0 ;
if ( sl ! = h - > slice_ctx ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" changing width %d -> %d / height %d -> %d on "
" slice %d \n " ,
h - > width , h - > avctx - > coded_width ,
h - > height , h - > avctx - > coded_height ,
h - > current_slice + 1 ) ;
return AVERROR_INVALIDDATA ;
}
av_assert1 ( first_slice ) ;
if ( flush_changes )
ff_h264_flush_change ( h ) ;
if ( ( ret = get_pixel_format ( h , 1 ) ) < 0 )
return ret ;
h - > avctx - > pix_fmt = ret ;
av_log ( h - > avctx , AV_LOG_VERBOSE , " Reinit context to %dx%d, "
" pix_fmt: %s \n " , h - > width , h - > height , av_get_pix_fmt_name ( h - > avctx - > pix_fmt ) ) ;
// TODO: should probably be moved to h264_field_start()
ret = h264_init_ps ( h , sl , first_slice ) ;
if ( ret < 0 )
return ret ;
if ( ( ret = h264_slice_header_init ( h ) ) < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" h264_slice_header_init() failed \n " ) ;
return ret ;
}
}
sps = ( const SPS * ) h - > ps . sps_list [ pps - > sps_id ] - > data ;
frame_num = get_bits ( & sl - > gb , sps - > log2_max_frame_num ) ;
if ( ! first_slice ) {