/***************************************************************************** * Open *****************************************************************************/ static int Open(vlc_object_t *p_this) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC) return VLC_EGENERIC; p_dec->p_sys = p_sys = calloc(1, sizeof(decoder_sys_t)); if (!p_dec->p_sys) return VLC_ENOMEM; INITQ(pre); INITQ(frame); INITQ(post); packetizer_Init(&p_dec->p_sys->packetizer, p_hevc_startcode, sizeof(p_hevc_startcode), startcode_FindAnnexB, p_hevc_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec); /* Copy properties */ es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in); p_dec->fmt_out.b_packetized = true; /* Set callbacks */ const uint8_t *p_extra = p_dec->fmt_in.p_extra; const size_t i_extra = p_dec->fmt_in.i_extra; /* Check if we have hvcC as extradata */ if(hevc_ishvcC(p_extra, i_extra)) { p_dec->pf_packetize = PacketizeHVC1; /* Clear hvcC/HVC1 extra, to be replaced with AnnexB */ free(p_dec->fmt_out.p_extra); p_dec->fmt_out.i_extra = 0; size_t i_new_extra = 0; p_dec->fmt_out.p_extra = hevc_hvcC_to_AnnexB_NAL(p_extra, i_extra, &i_new_extra, &p_sys->i_nal_length_size); if(p_dec->fmt_out.p_extra) p_dec->fmt_out.i_extra = i_new_extra; } else { p_dec->pf_packetize = PacketizeAnnexB; } p_dec->pf_flush = PacketizeFlush; if(p_dec->fmt_out.i_extra) { /* Feed with AnnexB VPS/SPS/PPS/SEI extradata */ packetizer_Header(&p_sys->packetizer, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra); } return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_VC1 ) return VLC_EGENERIC; p_dec->pf_packetize = Packetize; /* Create the output format */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->p_sys = p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) ); // sunqueen modify if( unlikely( !p_sys ) ) return VLC_ENOMEM; packetizer_Init( &p_sys->packetizer, p_vc1_startcode, sizeof(p_vc1_startcode), NULL, 0, 4, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_sequence_header = false; p_sys->sh.p_sh = NULL; p_sys->b_entry_point = false; p_sys->ep.p_ep = NULL; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->b_frame = false; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; p_sys->i_interpolated_dts = VLC_TS_INVALID; p_sys->b_check_startcode = p_dec->fmt_in.b_packetized; if( p_dec->fmt_out.i_extra > 0 ) { uint8_t *p_extra = (uint8_t *)p_dec->fmt_out.p_extra; // sunqueen modify /* With (some) ASF the first byte has to be stripped */ if( p_extra[0] != 0x00 ) { memcpy( &p_extra[0], &p_extra[1], p_dec->fmt_out.i_extra - 1 ); p_dec->fmt_out.i_extra--; } /* */ if( p_dec->fmt_out.i_extra > 0 ) packetizer_Header( &p_sys->packetizer, (const uint8_t *)p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); // sunqueen modify } return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; int i; if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 ) return VLC_EGENERIC; if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1') && p_dec->fmt_in.i_extra < 7 ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { return VLC_ENOMEM; } packetizer_Init( &p_sys->packetizer, p_h264_startcode, sizeof(p_h264_startcode), p_h264_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_slice = false; p_sys->p_frame = NULL; p_sys->b_frame_sps = false; p_sys->b_frame_pps = false; p_sys->b_header= false; p_sys->b_sps = false; p_sys->b_pps = false; for( i = 0; i < SPS_MAX; i++ ) p_sys->pp_sps[i] = NULL; for( i = 0; i < PPS_MAX; i++ ) p_sys->pp_pps[i] = NULL; p_sys->i_recovery_frames = -1; p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_idr_pic_id = -1; p_sys->slice.i_frame_num = -1; p_sys->slice.i_frame_type = 0; p_sys->slice.i_pic_parameter_set_id = -1; p_sys->slice.i_field_pic_flag = 0; p_sys->slice.i_bottom_field_flag = -1; p_sys->slice.i_pic_order_cnt_lsb = -1; p_sys->slice.i_delta_pic_order_cnt_bottom = -1; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_H264; if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4]; int i_sps, i_pps; bool b_dummy; int i; /* Parse avcC */ p_sys->i_avcC_length_size = 1 + ((*p++)&0x03); /* Read SPS */ i_sps = (*p++)&0x1f; for( i = 0; i < i_sps; i++ ) { uint16_t i_length = GetWBE( p ); p += 2; if( i_length > (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p ) { return VLC_EGENERIC; } block_t *p_sps = CreateAnnexbNAL( p_dec, p, i_length ); if( !p_sps ) return VLC_EGENERIC; ParseNALBlock( p_dec, &b_dummy, p_sps ); p += i_length; } /* Read PPS */ i_pps = *p++; for( i = 0; i < i_pps; i++ ) { uint16_t i_length = GetWBE( p ); p += 2; if( i_length > (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p ) { return VLC_EGENERIC; } block_t *p_pps = CreateAnnexbNAL( p_dec, p, i_length ); if( !p_pps ) return VLC_EGENERIC; ParseNALBlock( p_dec, &b_dummy, p_pps ); p += i_length; } msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d", p_sys->i_avcC_length_size, i_sps, i_pps ); if( !p_sys->b_sps || !p_sys->b_pps ) return VLC_EGENERIC; /* FIXME: FFMPEG isn't happy at all if you leave this */ if( p_dec->fmt_out.i_extra > 0 ) free( p_dec->fmt_out.p_extra ); p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = NULL; /* Set the new extradata */ for( i = 0; i < SPS_MAX; i++ ) { if( p_sys->pp_sps[i] ) p_dec->fmt_out.i_extra += p_sys->pp_sps[i]->i_buffer; } for( i = 0; i < PPS_MAX; i++ ) { if( p_sys->pp_pps[i] ) p_dec->fmt_out.i_extra += p_sys->pp_pps[i]->i_buffer; } p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); if( p_dec->fmt_out.p_extra ) { uint8_t *p_dst = p_dec->fmt_out.p_extra; for( i = 0; i < SPS_MAX; i++ ) { if( p_sys->pp_sps[i] ) { memcpy( p_dst, p_sys->pp_sps[i]->p_buffer, p_sys->pp_sps[i]->i_buffer ); p_dst += p_sys->pp_sps[i]->i_buffer; } } for( i = 0; i < PPS_MAX; i++ ) { if( p_sys->pp_pps[i] ) { memcpy( p_dst, p_sys->pp_pps[i]->p_buffer, p_sys->pp_pps[i]->i_buffer ); p_dst += p_sys->pp_pps[i]->i_buffer; } } p_sys->b_header = true; } else { p_dec->fmt_out.i_extra = 0; } /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; /* TODO CC ? */ } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; p_dec->pf_get_cc = GetCc; /* */ p_sys->i_cc_pts = VLC_TS_INVALID; p_sys->i_cc_dts = VLC_TS_INVALID; p_sys->i_cc_flags = 0; cc_Init( &p_sys->cc ); cc_Init( &p_sys->cc_next ); /* */ if( p_dec->fmt_in.i_extra > 0 ) packetizer_Header( &p_sys->packetizer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); } return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; int i; const bool b_avc = (p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' )); if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 ) return VLC_EGENERIC; if( b_avc && p_dec->fmt_in.i_extra < 7 ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { return VLC_ENOMEM; } p_sys->p_ccs = cc_storage_new(); if( unlikely(!p_sys->p_ccs) ) { free( p_dec->p_sys ); return VLC_ENOMEM; } packetizer_Init( &p_sys->packetizer, p_h264_startcode, sizeof(p_h264_startcode), startcode_FindAnnexB, p_h264_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_slice = false; p_sys->p_frame = NULL; p_sys->pp_frame_last = &p_sys->p_frame; p_sys->b_frame_sps = false; p_sys->b_frame_pps = false; p_sys->b_header= false; p_sys->b_sps = false; p_sys->b_pps = false; for( i = 0; i <= H264_SPS_ID_MAX; i++ ) p_sys->pp_sps[i] = NULL; for( i = 0; i <= H264_PPS_ID_MAX; i++ ) p_sys->pp_pps[i] = NULL; p_sys->i_recovery_frames = -1; p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_idr_pic_id = -1; p_sys->slice.i_frame_num = -1; p_sys->slice.i_frame_type = 0; p_sys->slice.i_pic_parameter_set_id = -1; p_sys->slice.i_field_pic_flag = 0; p_sys->slice.i_bottom_field_flag = -1; p_sys->slice.i_pic_order_cnt_lsb = -1; p_sys->slice.i_delta_pic_order_cnt_bottom = -1; p_sys->b_timing_info_present_flag = false; p_sys->b_pic_struct_present_flag = false; p_sys->b_cpb_dpb_delays_present_flag = false; p_sys->i_cpb_removal_delay_length_minus1 = 0; p_sys->i_dpb_output_delay_length_minus1 = 0; p_sys->b_even_frame = false; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->i_prev_dts = VLC_TS_INVALID; p_sys->i_prev_pts = VLC_TS_INVALID; p_sys->i_dpb_output_delay = 0; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_H264; p_dec->fmt_out.b_packetized = true; if( b_avc ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ if( h264_isavcC( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) ) { free( p_dec->fmt_out.p_extra ); size_t i_size; p_dec->fmt_out.p_extra = h264_avcC_to_AnnexB_NAL( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_size, &p_sys->i_avcC_length_size ); p_dec->fmt_out.i_extra = i_size; p_sys->b_header = !!p_dec->fmt_out.i_extra; if(!p_dec->fmt_out.p_extra) { msg_Err( p_dec, "Invalid AVC extradata"); Close( p_this ); return VLC_EGENERIC; } } else { msg_Err( p_dec, "Invalid or missing AVC extradata"); Close( p_this ); return VLC_EGENERIC; } /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; } /* */ if( p_dec->fmt_out.i_extra > 0 ) { packetizer_Header( &p_sys->packetizer, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); } if( b_avc ) { if( !p_sys->b_sps || !p_sys->b_pps ) { msg_Err( p_dec, "Invalid or missing SPS %d or PPS %d in AVC extradata", p_sys->b_sps, p_sys->b_pps ); Close( p_this ); return VLC_EGENERIC; } msg_Dbg( p_dec, "Packetizer fed with AVC, nal length size=%d", p_sys->i_avcC_length_size ); } /* CC are the same for H264/AVC in T35 sections (ETSI TS 101 154) */ p_dec->pf_get_cc = GetCc; p_dec->pf_flush = PacketizeFlush; return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; int i; const bool b_avc = (p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' )); if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 ) return VLC_EGENERIC; if( b_avc && p_dec->fmt_in.i_extra < 7 ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { return VLC_ENOMEM; } p_sys->p_ccs = cc_storage_new(); if( unlikely(!p_sys->p_ccs) ) { free( p_dec->p_sys ); return VLC_ENOMEM; } packetizer_Init( &p_sys->packetizer, p_h264_startcode, sizeof(p_h264_startcode), startcode_FindAnnexB, p_h264_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_slice = false; p_sys->p_frame = NULL; p_sys->pp_frame_last = &p_sys->p_frame; p_sys->p_sei = NULL; p_sys->pp_sei_last = &p_sys->p_sei; p_sys->b_new_sps = false; p_sys->b_new_pps = false; for( i = 0; i <= H264_SPS_ID_MAX; i++ ) { p_sys->sps[i].p_sps = NULL; p_sys->sps[i].p_block = NULL; } p_sys->p_active_sps = NULL; for( i = 0; i <= H264_PPS_ID_MAX; i++ ) { p_sys->pps[i].p_pps = NULL; p_sys->pps[i].p_block = NULL; } p_sys->p_active_pps = NULL; p_sys->i_recovery_frame_cnt = UINT_MAX; h264_slice_init( &p_sys->slice ); p_sys->i_next_block_flags = 0; p_sys->b_recovered = false; p_sys->i_recoveryfnum = UINT_MAX; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->i_dpb_output_delay = 0; /* POC */ h264_poc_context_init( &p_sys->pocctx ); p_sys->prevdatedpoc.pts = VLC_TS_INVALID; date_Init( &p_sys->dts, 30000 * 2, 1001 ); date_Set( &p_sys->dts, VLC_TS_INVALID ); /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_H264; p_dec->fmt_out.b_packetized = true; if( p_dec->fmt_in.video.i_frame_rate_base && p_dec->fmt_in.video.i_frame_rate && p_dec->fmt_in.video.i_frame_rate <= UINT_MAX / 2 ) { date_Change( &p_sys->dts, p_dec->fmt_in.video.i_frame_rate * 2, p_dec->fmt_in.video.i_frame_rate_base ); } if( b_avc ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ if( h264_isavcC( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) ) { free( p_dec->fmt_out.p_extra ); size_t i_size; p_dec->fmt_out.p_extra = h264_avcC_to_AnnexB_NAL( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra, &i_size, &p_sys->i_avcC_length_size ); p_dec->fmt_out.i_extra = i_size; p_sys->b_recovered = !!p_dec->fmt_out.i_extra; if(!p_dec->fmt_out.p_extra) { msg_Err( p_dec, "Invalid AVC extradata"); Close( p_this ); return VLC_EGENERIC; } } else { msg_Err( p_dec, "Invalid or missing AVC extradata"); Close( p_this ); return VLC_EGENERIC; } /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; } /* */ if( p_dec->fmt_out.i_extra > 0 ) { packetizer_Header( &p_sys->packetizer, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); } if( b_avc ) { /* FIXME: that's not correct for every AVC */ if( !p_sys->b_new_pps || !p_sys->b_new_sps ) { msg_Err( p_dec, "Invalid or missing SPS %d or PPS %d in AVC extradata", p_sys->b_new_sps, p_sys->b_new_pps ); Close( p_this ); return VLC_EGENERIC; } msg_Dbg( p_dec, "Packetizer fed with AVC, nal length size=%d", p_sys->i_avcC_length_size ); } /* CC are the same for H264/AVC in T35 sections (ETSI TS 101 154) */ p_dec->pf_get_cc = GetCc; p_dec->pf_flush = PacketizeFlush; return VLC_SUCCESS; }