JM ldecod分析: 分帧处理
JM ldecod分析: 分帧处理
接上节获取slice获取slice,现在根据不同的帧类型进行处理,此过程是解码的主要工作。
为了可以进行解码,帧stream中总是sps pps在前,第一步是分析SPS 和 PPS.
SPS 处理
//! DataPartition
typedef struct datapartition_dec
{Bitstream *bitstream;DecodingEnvironment de_cabac;int (*readSyntaxElement)(struct macroblock_dec *currMB, struct syntaxelement_dec *, struct datapartition_dec *);/*!< virtual function;actual method depends on chosen data partition andentropy coding method */
} DataPartition;
在解码slice之前,必须要先读到sps和pps,并且首先要读到sps。
case NALU_TYPE_SPS://printf ("Found NALU_TYPE_SPS\n");ProcessSPS(p_Vid, nalu);break;
void ProcessSPS (VideoParameters *p_Vid, NALU_t *nalu)
{ DataPartition *dp = AllocPartition(1);seq_parameter_set_rbsp_t *sps = AllocSPS();memcpy (dp->bitstream->streamBuffer, &nalu->buf[1], nalu->len-1);dp->bitstream->code_len = dp->bitstream->bitstream_length = RBSPtoSODB (dp->bitstream->streamBuffer, nalu->len-1);dp->bitstream->ei_flag = 0;dp->bitstream->read_len = dp->bitstream->frame_bitoffset = 0;InterpretSPS (p_Vid, dp, sps);
#if (MVC_EXTENSION_ENABLE)get_max_dec_frame_buf_size(sps);
#endifif (sps->Valid){if (p_Vid->active_sps){if (sps->seq_parameter_set_id == p_Vid->active_sps->seq_parameter_set_id){if (!sps_is_equal(sps, p_Vid->active_sps)){if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs) //?{// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_sps=NULL;}}}// SPSConsistencyCheck (pps);MakeSPSavailable (p_Vid, sps->seq_parameter_set_id, sps);
#if (MVC_EXTENSION_ENABLE)if (p_Vid->profile_idc < (int) sps->profile_idc){p_Vid->profile_idc = sps->profile_idc;}
#elsep_Vid->profile_idc = sps->profile_idc;
#endifp_Vid->separate_colour_plane_flag = sps->separate_colour_plane_flag;if( p_Vid->separate_colour_plane_flag ){p_Vid->ChromaArrayType = 0;}else{p_Vid->ChromaArrayType = sps->chroma_format_idc;}}FreePartition (dp, 1);FreeSPS (sps);
}
InterpretSPS() 是processSPS的关键 (sps内容参见 sps 组成 )
// fill sps with content of pint InterpretSPS (VideoParameters *p_Vid, DataPartition *p, seq_parameter_set_rbsp_t *sps)
{unsigned i;unsigned n_ScalingList;int reserved_zero;Bitstream *s = p->bitstream;assert (p != NULL);assert (p->bitstream != NULL);assert (p->bitstream->streamBuffer != 0);assert (sps != NULL);p_Dec->UsedBits = 0;sps->profile_idc = read_u_v (8, "SPS: profile_idc" , s, &p_Dec->UsedBits);if ((sps->profile_idc!=BASELINE ) &&(sps->profile_idc!=MAIN ) &&(sps->profile_idc!=EXTENDED ) &&(sps->profile_idc!=FREXT_HP ) &&(sps->profile_idc!=FREXT_Hi10P ) &&(sps->profile_idc!=FREXT_Hi422 ) &&(sps->profile_idc!=FREXT_Hi444 ) &&(sps->profile_idc!=FREXT_CAVLC444 )
#if (MVC_EXTENSION_ENABLE)&& (sps->profile_idc!=MVC_HIGH)&& (sps->profile_idc!=STEREO_HIGH)
#endif){printf("Invalid Profile IDC (%d) encountered. \n", sps->profile_idc);return p_Dec->UsedBits;}sps->constrained_set0_flag = read_u_1 ( "SPS: constrained_set0_flag" , s, &p_Dec->UsedBits);sps->constrained_set1_flag = read_u_1 ( "SPS: constrained_set1_flag" , s, &p_Dec->UsedBits);sps->constrained_set2_flag = read_u_1 ( "SPS: constrained_set2_flag" , s, &p_Dec->UsedBits);sps->constrained_set3_flag = read_u_1 ( "SPS: constrained_set3_flag" , s, &p_Dec->UsedBits);
#if (MVC_EXTENSION_ENABLE)sps->constrained_set4_flag = read_u_1 ( "SPS: constrained_set4_flag" , s, &p_Dec->UsedBits);sps->constrained_set5_flag = read_u_1 ( "SPS: constrained_set5_flag" , s, &p_Dec->UsedBits);reserved_zero = read_u_v (2, "SPS: reserved_zero_2bits" , s, &p_Dec->UsedBits);
#elsereserved_zero = read_u_v (4, "SPS: reserved_zero_4bits" , s, &p_Dec->UsedBits);
#endif//assert (reserved_zero==0);if (reserved_zero != 0){printf("Warning, reserved_zero flag not equal to 0. Possibly new constrained_setX flag introduced.\n");}sps->level_idc = read_u_v (8, "SPS: level_idc" , s, &p_Dec->UsedBits);sps->seq_parameter_set_id = read_ue_v ("SPS: seq_parameter_set_id" , s, &p_Dec->UsedBits);// Fidelity Range Extensions stuffsps->chroma_format_idc = 1;sps->bit_depth_luma_minus8 = 0;sps->bit_depth_chroma_minus8 = 0;sps->lossless_qpprime_flag = 0;sps->separate_colour_plane_flag = 0;if((sps->profile_idc==FREXT_HP ) ||(sps->profile_idc==FREXT_Hi10P) ||(sps->profile_idc==FREXT_Hi422) ||(sps->profile_idc==FREXT_Hi444) ||(sps->profile_idc==FREXT_CAVLC444)
#if (MVC_EXTENSION_ENABLE)|| (sps->profile_idc==MVC_HIGH)|| (sps->profile_idc==STEREO_HIGH)
#endif){sps->chroma_format_idc = read_ue_v ("SPS: chroma_format_idc" , s, &p_Dec->UsedBits);if(sps->chroma_format_idc == YUV444){sps->separate_colour_plane_flag = read_u_1 ("SPS: separate_colour_plane_flag" , s, &p_Dec->UsedBits);}sps->bit_depth_luma_minus8 = read_ue_v ("SPS: bit_depth_luma_minus8" , s, &p_Dec->UsedBits);sps->bit_depth_chroma_minus8 = read_ue_v ("SPS: bit_depth_chroma_minus8" , s, &p_Dec->UsedBits);//checking;if((sps->bit_depth_luma_minus8+8 > sizeof(imgpel)*8) || (sps->bit_depth_chroma_minus8+8> sizeof(imgpel)*8))error ("Source picture has higher bit depth than imgpel data type. \nPlease recompile with larger data type for imgpel.", 500);sps->lossless_qpprime_flag = read_u_1 ("SPS: lossless_qpprime_y_zero_flag" , s, &p_Dec->UsedBits);sps->seq_scaling_matrix_present_flag = read_u_1 ( "SPS: seq_scaling_matrix_present_flag" , s, &p_Dec->UsedBits);if(sps->seq_scaling_matrix_present_flag){n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;for(i=0; i<n_ScalingList; i++){sps->seq_scaling_list_present_flag[i] = read_u_1 ( "SPS: seq_scaling_list_present_flag" , s, &p_Dec->UsedBits);if(sps->seq_scaling_list_present_flag[i]){if(i<6)Scaling_List(sps->ScalingList4x4[i], 16, &sps->UseDefaultScalingMatrix4x4Flag[i], s);elseScaling_List(sps->ScalingList8x8[i-6], 64, &sps->UseDefaultScalingMatrix8x8Flag[i-6], s);}}}}sps->log2_max_frame_num_minus4 = read_ue_v ("SPS: log2_max_frame_num_minus4" , s, &p_Dec->UsedBits);sps->pic_order_cnt_type = read_ue_v ("SPS: pic_order_cnt_type" , s, &p_Dec->UsedBits);if (sps->pic_order_cnt_type == 0)sps->log2_max_pic_order_cnt_lsb_minus4 = read_ue_v ("SPS: log2_max_pic_order_cnt_lsb_minus4" , s, &p_Dec->UsedBits);else if (sps->pic_order_cnt_type == 1){sps->delta_pic_order_always_zero_flag = read_u_1 ("SPS: delta_pic_order_always_zero_flag" , s, &p_Dec->UsedBits);sps->offset_for_non_ref_pic = read_se_v ("SPS: offset_for_non_ref_pic" , s, &p_Dec->UsedBits);sps->offset_for_top_to_bottom_field = read_se_v ("SPS: offset_for_top_to_bottom_field" , s, &p_Dec->UsedBits);sps->num_ref_frames_in_pic_order_cnt_cycle = read_ue_v ("SPS: num_ref_frames_in_pic_order_cnt_cycle" , s, &p_Dec->UsedBits);for(i=0; i<sps->num_ref_frames_in_pic_order_cnt_cycle; i++)sps->offset_for_ref_frame[i] = read_se_v ("SPS: offset_for_ref_frame[i]" , s, &p_Dec->UsedBits);}sps->num_ref_frames = read_ue_v ("SPS: num_ref_frames" , s, &p_Dec->UsedBits);sps->gaps_in_frame_num_value_allowed_flag = read_u_1 ("SPS: gaps_in_frame_num_value_allowed_flag" , s, &p_Dec->UsedBits);sps->pic_width_in_mbs_minus1 = read_ue_v ("SPS: pic_width_in_mbs_minus1" , s, &p_Dec->UsedBits);sps->pic_height_in_map_units_minus1 = read_ue_v ("SPS: pic_height_in_map_units_minus1" , s, &p_Dec->UsedBits);sps->frame_mbs_only_flag = read_u_1 ("SPS: frame_mbs_only_flag" , s, &p_Dec->UsedBits);if (!sps->frame_mbs_only_flag){sps->mb_adaptive_frame_field_flag = read_u_1 ("SPS: mb_adaptive_frame_field_flag" , s, &p_Dec->UsedBits);}//printf("interlace flags %d %d\n", sps->frame_mbs_only_flag, sps->mb_adaptive_frame_field_flag);sps->direct_8x8_inference_flag = read_u_1 ("SPS: direct_8x8_inference_flag" , s, &p_Dec->UsedBits);sps->frame_cropping_flag = read_u_1 ("SPS: frame_cropping_flag" , s, &p_Dec->UsedBits);if (sps->frame_cropping_flag){sps->frame_crop_left_offset = read_ue_v ("SPS: frame_crop_left_offset" , s, &p_Dec->UsedBits);sps->frame_crop_right_offset = read_ue_v ("SPS: frame_crop_right_offset" , s, &p_Dec->UsedBits);sps->frame_crop_top_offset = read_ue_v ("SPS: frame_crop_top_offset" , s, &p_Dec->UsedBits);sps->frame_crop_bottom_offset = read_ue_v ("SPS: frame_crop_bottom_offset" , s, &p_Dec->UsedBits);}sps->vui_parameters_present_flag = (Boolean) read_u_1 ("SPS: vui_parameters_present_flag" , s, &p_Dec->UsedBits);InitVUI(sps);ReadVUI(p, sps);sps->Valid = TRUE;return p_Dec->UsedBits;
}
当seq_scaling_list_present_flag 为1时,放大系数以下面的函数的过程来从sps中获取。一般情况下seq_scaling_list_present_flag都为0,即使用默认的放大系数。
// syntax for scaling list matrix values
void Scaling_List(int *scalingList, int sizeOfScalingList, Boolean *UseDefaultScalingMatrix, Bitstream *s)
{int j, scanj;int delta_scale, lastScale, nextScale;lastScale = 8;nextScale = 8;for(j=0; j<sizeOfScalingList; j++){scanj = (sizeOfScalingList==16) ? ZZ_SCAN[j]:ZZ_SCAN8[j];if(nextScale!=0){delta_scale = read_se_v ( " : delta_sl " , s, &p_Dec->UsedBits);nextScale = (lastScale + delta_scale + 256) % 256;*UseDefaultScalingMatrix = (Boolean) (scanj==0 && nextScale==0);}scalingList[scanj] = (nextScale==0) ? lastScale:nextScale;lastScale = scalingList[scanj];}
}
PPS 处理
ProcessSPS(p_Vid, nalu);
void ProcessPPS (VideoParameters *p_Vid, NALU_t *nalu){DataPartition *dp = AllocPartition(1);pic_parameter_set_rbsp_t *pps = AllocPPS();//讲nalu中的数据拷贝到bitstreammemcpy (dp->bitstream->streamBuffer, &nalu->buf[1], nalu->len-1);dp->bitstream->code_len = dp->bitstream->bitstream_length = RBSPtoSODB (dp->bitstream->streamBuffer, nalu->len-1);dp->bitstream->ei_flag = 0;dp->bitstream->read_len = dp->bitstream->frame_bitoffset = 0;InterpretPPS (p_Vid, dp, pps);// PPSConsistencyCheck (pps);if (p_Vid->active_pps){if (pps->pic_parameter_set_id == p_Vid->active_pps->pic_parameter_set_id){if(!pps_is_equal(pps, p_Vid->active_pps)){//copy to next PPS;memcpy(p_Vid->pNextPPS, p_Vid->active_pps, sizeof (pic_parameter_set_rbsp_t));{if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_pps = NULL;}}}}MakePPSavailable (p_Vid, pps->pic_parameter_set_id, pps);FreePartition (dp, 1);FreePPS (pps);}
slice 和IDR
根据读到的nalu,填充slice。
case NALU_TYPE_SLICE:case NALU_TYPE_IDR:if (p_Vid->recovery_point || nalu->nal_unit_type == NALU_TYPE_IDR){if (p_Vid->recovery_point_found == 0){if (nalu->nal_unit_type != NALU_TYPE_IDR){printf("Warning: Decoding does not start with an IDR picture.\n");p_Vid->non_conforming_stream = 1;}elsep_Vid->non_conforming_stream = 0;}p_Vid->recovery_point_found = 1;}if (p_Vid->recovery_point_found == 0)break;currSlice->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR);currSlice->nal_reference_idc = nalu->nal_reference_idc;currSlice->dp_mode = PAR_DP_1;currSlice->max_part_nr = 1;
#if (MVC_EXTENSION_ENABLE)if (currSlice->svc_extension_flag != 0){currStream = currSlice->partArr[0].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;fast_memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);}
#else datapartion 在malloc_slice中分配,nr 为3,bitstream同时也在此时分配,下边填充bitstreamcurrStream = currSlice->partArr[0].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);
#endif#if (MVC_EXTENSION_ENABLE)if(currSlice->svc_extension_flag == 0){ //MVC//if(is_MVC_profile(p_Vid->active_sps->profile_idc))//{currSlice->view_id = currSlice->NaluHeaderMVCExt.view_id;currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;//}}else if(currSlice->svc_extension_flag == -1) //SVC and the normal AVC;{if(p_Vid->active_subset_sps == NULL){currSlice->view_id = GetBaseViewId(p_Vid, &p_Vid->active_subset_sps);if(currSlice->NaluHeaderMVCExt.iPrefixNALU >0){assert(currSlice->view_id == currSlice->NaluHeaderMVCExt.view_id);currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;}else{currSlice->inter_view_flag = 1;currSlice->anchor_pic_flag = currSlice->idr_flag;}}else{assert(p_Vid->active_subset_sps->num_views_minus1 >=0);// prefix NALU availableif(currSlice->NaluHeaderMVCExt.iPrefixNALU >0){currSlice->view_id = currSlice->NaluHeaderMVCExt.view_id;currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;}else{ //no prefix NALU;currSlice->view_id = p_Vid->active_subset_sps->view_id[0];currSlice->inter_view_flag = 1;currSlice->anchor_pic_flag = currSlice->idr_flag;}}}currSlice->layer_id = currSlice->view_id = GetVOIdx( p_Vid, currSlice->view_id );
#endif// Some syntax of the Slice Header depends on the parameter set, which depends on// the parameter set ID of the SLice header. Hence, read the pic_parameter_set_id// of the slice header first, then setup the active parameter sets, and then read// the rest of the slice headerBitsUsedByHeader = FirstPartOfSliceHeader(currSlice);UseParameterSet (currSlice);currSlice->active_sps = p_Vid->active_sps;currSlice->active_pps = p_Vid->active_pps;currSlice->Transform8x8Mode = p_Vid->active_pps->transform_8x8_mode_flag;currSlice->chroma444_not_separate = (p_Vid->active_sps->chroma_format_idc==YUV444)&&((p_Vid->separate_colour_plane_flag == 0));BitsUsedByHeader += RestOfSliceHeader (currSlice);
#if (MVC_EXTENSION_ENABLE)if(currSlice->view_id >=0){currSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->view_id];}
#endifassign_quant_params (currSlice); // if primary slice is replaced with redundant slice, set the correct image typeif(currSlice->redundant_pic_cnt && p_Vid->Is_primary_correct==0 && p_Vid->Is_redundant_correct){p_Vid->dec_picture->slice_type = p_Vid->type;}if(is_new_picture(p_Vid->dec_picture, currSlice, p_Vid->old_slice)){if(p_Vid->iSliceNumOfCurrPic==0)init_picture(p_Vid, currSlice, p_Inp);current_header = SOP;//check zero_byte if it is also the first NAL unit in the access unitCheckZeroByteVCL(p_Vid, nalu);}elsecurrent_header = SOS;setup_slice_methods(currSlice);// From here on, p_Vid->active_sps, p_Vid->active_pps and the slice header are validif (currSlice->mb_aff_frame_flag)currSlice->current_mb_nr = currSlice->start_mb_nr << 1;elsecurrSlice->current_mb_nr = currSlice->start_mb_nr;if (p_Vid->active_pps->entropy_coding_mode_flag){int ByteStartPosition = currStream->frame_bitoffset/8;if (currStream->frame_bitoffset%8 != 0){++ByteStartPosition;}arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len);}// printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS");//FreeNALU(nalu);p_Vid->recovery_point = 0;return current_header;break;case NALU_TYPE_DPA:if (p_Vid->recovery_point_found == 0)break;// read DP_AcurrSlice->dpB_NotPresent =1; currSlice->dpC_NotPresent =1; currSlice->idr_flag = FALSE;currSlice->nal_reference_idc = nalu->nal_reference_idc;currSlice->dp_mode = PAR_DP_3;currSlice->max_part_nr = 3;currSlice->ei_flag = 0;
#if MVC_EXTENSION_ENABLEcurrSlice->p_Dpb = p_Vid->p_Dpb_layer[0];
#endifcurrStream = currSlice->partArr[0].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);
#if MVC_EXTENSION_ENABLEcurrSlice->view_id = GetBaseViewId(p_Vid, &p_Vid->active_subset_sps);currSlice->inter_view_flag = 1;currSlice->layer_id = currSlice->view_id = GetVOIdx( p_Vid, currSlice->view_id );currSlice->anchor_pic_flag = currSlice->idr_flag;
#endifBitsUsedByHeader = FirstPartOfSliceHeader(currSlice);UseParameterSet (currSlice);currSlice->active_sps = p_Vid->active_sps;currSlice->active_pps = p_Vid->active_pps;currSlice->Transform8x8Mode = p_Vid->active_pps->transform_8x8_mode_flag;currSlice->chroma444_not_separate = (p_Vid->active_sps->chroma_format_idc==YUV444)&&((p_Vid->separate_colour_plane_flag == 0));BitsUsedByHeader += RestOfSliceHeader (currSlice);
#if MVC_EXTENSION_ENABLEcurrSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->view_id];
#endifassign_quant_params (currSlice); 当该slice是一副新图像,一般情况下一个slice都是一副新图像。if(is_new_picture(p_Vid->dec_picture, currSlice, p_Vid->old_slice)){ 当slice是第一个slice时if(p_Vid->iSliceNumOfCurrPic==0)init_picture(p_Vid, currSlice, p_Inp);current_header = SOP;//check zero_byte if it is also the first NAL unit in the access unitCheckZeroByteVCL(p_Vid, nalu);}elsecurrent_header = SOS;setup_slice_methods(currSlice);// From here on, p_Vid->active_sps, p_Vid->active_pps and the slice header are validif (currSlice->mb_aff_frame_flag)currSlice->current_mb_nr = currSlice->start_mb_nr << 1;elsecurrSlice->current_mb_nr = currSlice->start_mb_nr;// Now I need to read the slice ID, which depends on the value of// redundant_pic_cnt_present_flagslice_id_a = read_ue_v("NALU: DP_A slice_id", currStream, &p_Dec->UsedBits);if (p_Vid->active_pps->entropy_coding_mode_flag)error ("received data partition with CABAC, this is not allowed", 500);// continue with reading next DPif (0 == read_next_nalu(p_Vid, nalu))return current_header;if ( NALU_TYPE_DPB == nalu->nal_unit_type){// we got a DPBcurrStream = currSlice->partArr[1].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);slice_id_b = read_ue_v("NALU: DP_B slice_id", currStream, &p_Dec->UsedBits);currSlice->dpB_NotPresent = 0; if ((slice_id_b != slice_id_a) || (nalu->lost_packets)){printf ("Waning: got a data partition B which does not match DP_A (DP loss!)\n");currSlice->dpB_NotPresent =1; currSlice->dpC_NotPresent =1; }else{if (p_Vid->active_pps->redundant_pic_cnt_present_flag)read_ue_v("NALU: DP_B redundant_pic_cnt", currStream, &p_Dec->UsedBits);// we're finished with DP_B, so let's continue with next DPif (0 == read_next_nalu(p_Vid, nalu))return current_header;}}else{currSlice->dpB_NotPresent =1; }// check if we got DP_Cif ( NALU_TYPE_DPC == nalu->nal_unit_type){currStream = currSlice->partArr[2].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);currSlice->dpC_NotPresent = 0;slice_id_c = read_ue_v("NALU: DP_C slice_id", currStream, &p_Dec->UsedBits);if ((slice_id_c != slice_id_a)|| (nalu->lost_packets)){printf ("Warning: got a data partition C which does not match DP_A(DP loss!)\n");//currSlice->dpB_NotPresent =1;currSlice->dpC_NotPresent =1;}if (p_Vid->active_pps->redundant_pic_cnt_present_flag)read_ue_v("NALU:SLICE_C redudand_pic_cnt", currStream, &p_Dec->UsedBits);}else{currSlice->dpC_NotPresent =1;pending_nalu = nalu;}// check if we read anything else than the expected partitionsif ((nalu->nal_unit_type != NALU_TYPE_DPB) && (nalu->nal_unit_type != NALU_TYPE_DPC) && (!currSlice->dpC_NotPresent)){// we have a NALI that we can't process here, so restart processinggoto process_nalu;// yes, "goto" should not be used, but it's really the best way here before we restructure the decoding loop// (which should be taken care of anyway)}//FreeNALU(nalu);return current_header;break;
/*!************************************************************************* \brief* Initializes the parameters for a new picture*************************************************************************/
static void init_picture(VideoParameters *p_Vid, Slice *currSlice, InputParameters *p_Inp)
{int i;int nplane;StorablePicture *dec_picture = NULL;seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps;DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;p_Vid->PicHeightInMbs = p_Vid->FrameHeightInMbs / ( 1 + currSlice->field_pic_flag );p_Vid->PicSizeInMbs = p_Vid->PicWidthInMbs * p_Vid->PicHeightInMbs;p_Vid->FrameSizeInMbs = p_Vid->PicWidthInMbs * p_Vid->FrameHeightInMbs;p_Vid->bFrameInit = 1;if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->dpb_layer_id = currSlice->layer_id;//set buffers;setup_buffers(p_Vid, currSlice->layer_id);if (p_Vid->recovery_point)p_Vid->recovery_frame_num = (currSlice->frame_num + p_Vid->recovery_frame_cnt) % p_Vid->max_frame_num;if (currSlice->idr_flag)p_Vid->recovery_frame_num = currSlice->frame_num;if (p_Vid->recovery_point == 0 &&currSlice->frame_num != p_Vid->pre_frame_num &&currSlice->frame_num != (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num){if (active_sps->gaps_in_frame_num_value_allowed_flag == 0){// picture error concealmentif(p_Inp->conceal_mode !=0){if((currSlice->frame_num) < ((p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num)){/* Conceal lost IDR frames and any frames immediatelyfollowing the IDR. Use frame copy for these sincelists cannot be formed correctly for motion copy*/p_Vid->conceal_mode = 1;p_Vid->IDR_concealment_flag = 1;conceal_lost_frames(p_Dpb, currSlice);//reset to original concealment mode for future dropsp_Vid->conceal_mode = p_Inp->conceal_mode;}else{//reset to original concealment mode for future dropsp_Vid->conceal_mode = p_Inp->conceal_mode;p_Vid->IDR_concealment_flag = 0;conceal_lost_frames(p_Dpb, currSlice);}}else{ /* Advanced Error Concealment would be called here to combat unintentional loss of pictures. */error("An unintentional loss of pictures occurs! Exit\n", 100);}}if(p_Vid->conceal_mode == 0)fill_frame_num_gap(p_Vid, currSlice);}if(currSlice->nal_reference_idc){p_Vid->pre_frame_num = currSlice->frame_num;}//p_Vid->num_dec_mb = 0;//calculate POCdecode_poc(p_Vid, currSlice);if (p_Vid->recovery_frame_num == (int) currSlice->frame_num && p_Vid->recovery_poc == 0x7fffffff)p_Vid->recovery_poc = currSlice->framepoc;if(currSlice->nal_reference_idc)p_Vid->last_ref_pic_poc = currSlice->framepoc;// dumppoc (p_Vid);if (currSlice->structure==FRAME ||currSlice->structure==TOP_FIELD){gettime (&(p_Vid->start_time)); // start time}dec_picture = p_Vid->dec_picture = alloc_storable_picture (p_Vid, currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);dec_picture->top_poc=currSlice->toppoc;dec_picture->bottom_poc=currSlice->bottompoc;dec_picture->frame_poc=currSlice->framepoc;dec_picture->qp = currSlice->qp;dec_picture->slice_qp_delta = currSlice->slice_qp_delta;dec_picture->chroma_qp_offset[0] = p_Vid->active_pps->chroma_qp_index_offset;dec_picture->chroma_qp_offset[1] = p_Vid->active_pps->second_chroma_qp_index_offset;dec_picture->iCodingType = currSlice->structure==FRAME? (currSlice->mb_aff_frame_flag? FRAME_MB_PAIR_CODING:FRAME_CODING): FIELD_CODING; //currSlice->slice_type;dec_picture->layer_id = currSlice->layer_id;
#if (MVC_EXTENSION_ENABLE)dec_picture->view_id = currSlice->view_id;dec_picture->inter_view_flag = currSlice->inter_view_flag;dec_picture->anchor_pic_flag = currSlice->anchor_pic_flag;if (dec_picture->view_id == 1){if((p_Vid->profile_idc == MVC_HIGH) || (p_Vid->profile_idc == STEREO_HIGH))init_mvc_picture(currSlice);}
#endif// reset all variables of the error concealment instance before decoding of every frame.// here the third parameter should, if perfectly, be equal to the number of slices per frame.// using little value is ok, the code will allocate more memory if the slice number is larger
#if (DISABLE_ERC == 0)ercReset(p_Vid->erc_errorVar, p_Vid->PicSizeInMbs, p_Vid->PicSizeInMbs, dec_picture->size_x);
#endifp_Vid->erc_mvperMB = 0;switch (currSlice->structure ){case TOP_FIELD:{dec_picture->poc = currSlice->toppoc;p_Vid->number *= 2;break;}case BOTTOM_FIELD:{dec_picture->poc = currSlice->bottompoc;p_Vid->number = p_Vid->number * 2 + 1;break;}case FRAME:{dec_picture->poc = currSlice->framepoc;break;}default:error("p_Vid->structure not initialized", 235);}//p_Vid->current_slice_nr=0;if (p_Vid->type > SI_SLICE){set_ec_flag(p_Vid, SE_PTYPE);p_Vid->type = P_SLICE; // concealed element}// CAVLC initif (p_Vid->active_pps->entropy_coding_mode_flag == (Boolean) CAVLC){memset(p_Vid->nz_coeff[0][0][0], -1, p_Vid->PicSizeInMbs * 48 *sizeof(byte)); // 3 * 4 * 4}// Set the slice_nr member of each MB to -1, to ensure correct when packet loss occurs// TO set Macroblock Map (mark all MBs as 'have to be concealed')if( (p_Vid->separate_colour_plane_flag != 0) ){for( nplane=0; nplane<MAX_PLANE; ++nplane ){ Macroblock *currMB = p_Vid->mb_data_JV[nplane];char *intra_block = p_Vid->intra_block_JV[nplane];for(i=0; i<(int)p_Vid->PicSizeInMbs; ++i){reset_mbs(currMB++);}fast_memset(p_Vid->ipredmode_JV[nplane][0], DC_PRED, 16 * p_Vid->FrameHeightInMbs * p_Vid->PicWidthInMbs * sizeof(char));if(p_Vid->active_pps->constrained_intra_pred_flag){for (i=0; i<(int)p_Vid->PicSizeInMbs; ++i){intra_block[i] = 1;}}}}else{#if 0 //defined(OPENMP)
#pragma omp parallel forfor(i=0; i<(int)p_Vid->PicSizeInMbs; ++i)reset_mbs(&p_Vid->mb_data[i]);
#elseMacroblock *currMB = p_Vid->mb_data;for(i=0; i<(int)p_Vid->PicSizeInMbs; ++i)reset_mbs(currMB++);
#endifif(p_Vid->active_pps->constrained_intra_pred_flag){for (i=0; i<(int)p_Vid->PicSizeInMbs; ++i){p_Vid->intra_block[i] = 1;}}fast_memset(p_Vid->ipredmode[0], DC_PRED, 16 * p_Vid->FrameHeightInMbs * p_Vid->PicWidthInMbs * sizeof(char));} dec_picture->slice_type = p_Vid->type;dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0);dec_picture->idr_flag = currSlice->idr_flag;dec_picture->no_output_of_prior_pics_flag = currSlice->no_output_of_prior_pics_flag;dec_picture->long_term_reference_flag = currSlice->long_term_reference_flag;dec_picture->adaptive_ref_pic_buffering_flag = currSlice->adaptive_ref_pic_buffering_flag;dec_picture->dec_ref_pic_marking_buffer = currSlice->dec_ref_pic_marking_buffer;currSlice->dec_ref_pic_marking_buffer = NULL;dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag;dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs;p_Vid->get_mb_block_pos = dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal;p_Vid->getNeighbour = dec_picture->mb_aff_frame_flag ? getAffNeighbour : getNonAffNeighbour;dec_picture->pic_num = currSlice->frame_num;dec_picture->frame_num = currSlice->frame_num;dec_picture->recovery_frame = (unsigned int) ((int) currSlice->frame_num == p_Vid->recovery_frame_num);dec_picture->coded_frame = (currSlice->structure==FRAME);dec_picture->chroma_format_idc = active_sps->chroma_format_idc;dec_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag;dec_picture->frame_cropping_flag = active_sps->frame_cropping_flag;if (dec_picture->frame_cropping_flag){dec_picture->frame_crop_left_offset = active_sps->frame_crop_left_offset;dec_picture->frame_crop_right_offset = active_sps->frame_crop_right_offset;dec_picture->frame_crop_top_offset = active_sps->frame_crop_top_offset;dec_picture->frame_crop_bottom_offset = active_sps->frame_crop_bottom_offset;}#if (ENABLE_OUTPUT_TONEMAPPING)// store the necessary tone mapping sei into StorablePicture structureif (p_Vid->seiToneMapping->seiHasTone_mapping){int coded_data_bit_max = (1 << p_Vid->seiToneMapping->coded_data_bit_depth);dec_picture->seiHasTone_mapping = 1;dec_picture->tone_mapping_model_id = p_Vid->seiToneMapping->model_id;dec_picture->tonemapped_bit_depth = p_Vid->seiToneMapping->sei_bit_depth;dec_picture->tone_mapping_lut = malloc(coded_data_bit_max * sizeof(int));if (NULL == dec_picture->tone_mapping_lut){no_mem_exit("init_picture: tone_mapping_lut");}memcpy(dec_picture->tone_mapping_lut, p_Vid->seiToneMapping->lut, sizeof(imgpel) * coded_data_bit_max);update_tone_mapping_sei(p_Vid->seiToneMapping);}elsedec_picture->seiHasTone_mapping = 0;
#endifif( (p_Vid->separate_colour_plane_flag != 0) ){p_Vid->dec_picture_JV[0] = p_Vid->dec_picture;p_Vid->dec_picture_JV[1] = alloc_storable_picture (p_Vid, (PictureStructure) currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);copy_dec_picture_JV( p_Vid, p_Vid->dec_picture_JV[1], p_Vid->dec_picture_JV[0] );p_Vid->dec_picture_JV[2] = alloc_storable_picture (p_Vid, (PictureStructure) currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);copy_dec_picture_JV( p_Vid, p_Vid->dec_picture_JV[2], p_Vid->dec_picture_JV[0] );}
}
slice header 处理
- 当该nalu为IDR和普通slice 时,这里就是一个刷新点。然后开始读取slice header,由于sliceheader字段依赖图像参数集,这里的读取sliceheader分为两部分。
FirstPartOfSliceHeader(currSlice) 获取sliceheader字段中不依赖图像参数集的部分
sliceheader字段描述
/*!************************************************************************* \brief* read the first part of the header (only the pic_parameter_set_id)* \return* Length of the first part of the slice header (in bits)*************************************************************************/
int FirstPartOfSliceHeader(Slice *currSlice)
{VideoParameters *p_Vid = currSlice->p_Vid;byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER];DataPartition *partition = &(currSlice->partArr[dP_nr]);Bitstream *currStream = partition->bitstream;int tmp;p_Dec->UsedBits= partition->bitstream->frame_bitoffset; // was hardcoded to 31 for previous start-code. This is better.// Get first_mb_in_slicecurrSlice->start_mb_nr = read_ue_v ("SH: first_mb_in_slice", currStream, &p_Dec->UsedBits);tmp = read_ue_v ("SH: slice_type", currStream, &p_Dec->UsedBits);if (tmp > 4) tmp -= 5;p_Vid->type = currSlice->slice_type = (SliceType) tmp;currSlice->pic_parameter_set_id = read_ue_v ("SH: pic_parameter_set_id", currStream, &p_Dec->UsedBits);if( p_Vid->separate_colour_plane_flag )currSlice->colour_plane_id = read_u_v (2, "SH: colour_plane_id", currStream, &p_Dec->UsedBits);elsecurrSlice->colour_plane_id = PLANE_Y;return p_Dec->UsedBits;
}
slice_type 为1~5,上面代码中会有映射
typedef enum
{P_SLICE = 0,B_SLICE = 1,I_SLICE = 2,SP_SLICE = 3,SI_SLICE = 4,NUM_SLICE_TYPES = 5
} SliceType;
UseParameterSet (Slice *currSlice)
在读到其他帧之前一定要先读到sps 和pps 才能够进行解码。下边是激活sps 和pps,并根据读到的pps的熵编码类型设置读取函数。
void UseParameterSet (Slice *currSlice)
{VideoParameters *p_Vid = currSlice->p_Vid;int PicParsetId = currSlice->pic_parameter_set_id; pic_parameter_set_rbsp_t *pps = &p_Vid->PicParSet[PicParsetId];seq_parameter_set_rbsp_t *sps = &p_Vid->SeqParSet[pps->seq_parameter_set_id];int i;if (pps->Valid != TRUE)printf ("Trying to use an invalid (uninitialized) Picture Parameter Set with ID %d, expect the unexpected...\n", PicParsetId);
#if (MVC_EXTENSION_ENABLE)if (currSlice->svc_extension_flag == -1){if (sps->Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);}else{// Set SPS to the subset SPS parametersp_Vid->active_subset_sps = p_Vid->SubsetSeqParSet + pps->seq_parameter_set_id;sps = &(p_Vid->active_subset_sps->sps);if (p_Vid->SubsetSeqParSet[pps->seq_parameter_set_id].Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Subset Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);}
#elseif (sps->Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);
#endif// In theory, and with a well-designed software, the lines above// are everything necessary. In practice, we need to patch many values// in p_Vid-> (but no more in p_Inp-> -- these have been taken care of)// Set Sequence Parameter Stuff first// printf ("Using Picture Parameter set %d and associated Sequence Parameter Set %d\n", PicParsetId, pps->seq_parameter_set_id);if ((int) sps->pic_order_cnt_type < 0 || sps->pic_order_cnt_type > 2) // != 1{printf ("invalid sps->pic_order_cnt_type = %d\n", (int) sps->pic_order_cnt_type);error ("pic_order_cnt_type != 1", -1000);}if (sps->pic_order_cnt_type == 1){if(sps->num_ref_frames_in_pic_order_cnt_cycle >= MAXnum_ref_frames_in_pic_order_cnt_cycle){error("num_ref_frames_in_pic_order_cnt_cycle too large",-1011);}}p_Vid->dpb_layer_id = currSlice->layer_id;activate_sps(p_Vid, sps);activate_pps(p_Vid, pps);// currSlice->dp_mode is set by read_new_slice (NALU first byte available there)if (pps->entropy_coding_mode_flag == (Boolean) CAVLC){currSlice->nal_startcode_follows = uvlc_startcode_follows;for (i=0; i<3; i++){currSlice->partArr[i].readSyntaxElement = readSyntaxElement_UVLC; }}else{currSlice->nal_startcode_follows = cabac_startcode_follows;for (i=0; i<3; i++){currSlice->partArr[i].readSyntaxElement = readSyntaxElement_CABAC;}}p_Vid->type = currSlice->slice_type;
activate_sps() & activate_pps()
/*!************************************************************************* \brief* Activate Sequence Parameter Sets**************************************************************************/
void activate_sps (VideoParameters *p_Vid, seq_parameter_set_rbsp_t *sps)
{InputParameters *p_Inp = p_Vid->p_Inp;
激活sps时,p_Vid中activate_sps是NULLif (p_Vid->active_sps != sps){if (p_Vid->dec_picture){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_sps = sps;if(p_Vid->dpb_layer_id==0 && is_BL_profile(sps->profile_idc) && !p_Vid->p_Dpb_layer[0]->init_done){将sps中的相关参数加入到解码参数结构中set_coding_par(sps, p_Vid->p_EncodePar[0]);setup_layer_info( p_Vid, sps, p_Vid->p_LayerPar[0]);}else if(p_Vid->dpb_layer_id==1 && is_EL_profile(sps->profile_idc) && !p_Vid->p_Dpb_layer[1]->init_done){set_coding_par(sps, p_Vid->p_EncodePar[1]);setup_layer_info(p_Vid, sps, p_Vid->p_LayerPar[1]);}//to be removed in future;set_global_coding_par(p_Vid, p_Vid->p_EncodePar[p_Vid->dpb_layer_id]);
//end;#if (MVC_EXTENSION_ENABLE)//init_frext(p_Vid);if (/*p_Vid->last_pic_width_in_mbs_minus1 != p_Vid->active_sps->pic_width_in_mbs_minus1|| p_Vid->last_pic_height_in_map_units_minus1 != p_Vid->active_sps->pic_height_in_map_units_minus1|| p_Vid->last_max_dec_frame_buffering != GetMaxDecFrameBuffering(p_Vid)|| */(p_Vid->last_profile_idc != p_Vid->active_sps->profile_idc && is_BL_profile(p_Vid->active_sps->profile_idc) && !p_Vid->p_Dpb_layer[0]->init_done /*&& is_BL_profile(p_Vid->last_profile_idc)*/)){//init_frext(p_Vid);init_global_buffers(p_Vid, 0);if (!p_Vid->no_output_of_prior_pics_flag){flush_dpb(p_Vid->p_Dpb_layer[0]);flush_dpb(p_Vid->p_Dpb_layer[1]);}init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);}else if(p_Vid->last_profile_idc != p_Vid->active_sps->profile_idc && (is_MVC_profile(p_Vid->last_profile_idc) || is_MVC_profile(p_Vid->active_sps->profile_idc))&& (!p_Vid->p_Dpb_layer[1]->init_done)){assert(p_Vid->p_Dpb_layer[0]->init_done);//init_frext(p_Vid);if(p_Vid->p_Dpb_layer[0]->init_done){free_dpb(p_Vid->p_Dpb_layer[0]);init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);}init_global_buffers(p_Vid, 1);// for now lets re_init both buffers. Later, we should only re_init appropriate one// Note that we seem to be doing this for every frame which seems not good.//re_init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#if MVC_EXTENSION_ENABLEinit_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#endif//p_Vid->last_profile_idc = p_Vid->active_sps->profile_idc;}//p_Vid->p_Dpb_layer[0]->num_ref_frames = p_Vid->active_sps->num_ref_frames;//p_Vid->p_Dpb_layer[1]->num_ref_frames = p_Vid->active_sps->num_ref_frames;p_Vid->last_pic_width_in_mbs_minus1 = p_Vid->active_sps->pic_width_in_mbs_minus1; p_Vid->last_pic_height_in_map_units_minus1 = p_Vid->active_sps->pic_height_in_map_units_minus1;p_Vid->last_max_dec_frame_buffering = GetMaxDecFrameBuffering(p_Vid);p_Vid->last_profile_idc = p_Vid->active_sps->profile_idc;#else//init_frext(p_Vid);init_global_buffers(p_Vid, 0);if (!p_Vid->no_output_of_prior_pics_flag){flush_dpb(p_Vid->p_Dpb_layer[0]);}init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0);// for now lets init both buffers. Later, we should only re_init appropriate one//init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);// obviously this is not needed her but just adding it for completeness//init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#endif#if (DISABLE_ERC == 0)ercInit(p_Vid, p_Vid->width, p_Vid->height, 1);if(p_Vid->dec_picture){ercReset(p_Vid->erc_errorVar, p_Vid->PicSizeInMbs, p_Vid->PicSizeInMbs, p_Vid->dec_picture->size_x);p_Vid->erc_mvperMB = 0;}
#endif}reset_format_info(sps, p_Vid, &p_Inp->source, &p_Inp->output);
}
在激活sps时,有init_global_buffers()
int init_global_buffers(VideoParameters *p_Vid, int layer_id)
{int memory_size=0;int i;CodingParameters *cps = p_Vid->p_EncodePar[layer_id];BlockPos* PicPos;if (p_Vid->global_init_done[layer_id]){free_layer_buffers(p_Vid, layer_id);}// allocate memory for reference frame in find_snrmemory_size += get_mem2Dpel(&cps->imgY_ref, cps->height, cps->width);if (cps->yuv_format != YUV400){memory_size += get_mem3Dpel(&cps->imgUV_ref, 2, cps->height_cr, cps->width_cr);}elsecps->imgUV_ref = NULL;// allocate memory in structure p_Vidif( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){if(((cps->mb_data_JV[i]) = (Macroblock *) calloc(cps->FrameSizeInMbs, sizeof(Macroblock))) == NULL)no_mem_exit("init_global_buffers: cps->mb_data_JV");}cps->mb_data = NULL;}else{if(((cps->mb_data) = (Macroblock *) calloc(cps->FrameSizeInMbs, sizeof(Macroblock))) == NULL)no_mem_exit("init_global_buffers: cps->mb_data");}if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){if(((cps->intra_block_JV[i]) = (char*) calloc(cps->FrameSizeInMbs, sizeof(char))) == NULL)no_mem_exit("init_global_buffers: cps->intra_block_JV");}cps->intra_block = NULL;}else{if(((cps->intra_block) = (char*) calloc(cps->FrameSizeInMbs, sizeof(char))) == NULL)no_mem_exit("init_global_buffers: cps->intra_block");}//memory_size += get_mem2Dint(&PicPos,p_Vid->FrameSizeInMbs + 1,2); //! Helper array to access macroblock positions. We add 1 to also consider last MB.if(((cps->PicPos) = (BlockPos*) calloc(cps->FrameSizeInMbs + 1, sizeof(BlockPos))) == NULL)no_mem_exit("init_global_buffers: PicPos");PicPos = cps->PicPos;for (i = 0; i < (int) cps->FrameSizeInMbs + 1;++i){PicPos[i].x = (short) (i % cps->PicWidthInMbs);PicPos[i].y = (short) (i / cps->PicWidthInMbs);}if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){get_mem2D(&(cps->ipredmode_JV[i]), 4*cps->FrameHeightInMbs, 4*cps->PicWidthInMbs);}cps->ipredmode = NULL;}elsememory_size += get_mem2D(&(cps->ipredmode), 4*cps->FrameHeightInMbs, 4*cps->PicWidthInMbs);// CAVLC memmemory_size += get_mem4D(&(cps->nz_coeff), cps->FrameSizeInMbs, 3, BLOCK_SIZE, BLOCK_SIZE);if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){get_mem2Dint(&(cps->siblock_JV[i]), cps->FrameHeightInMbs, cps->PicWidthInMbs);if(cps->siblock_JV[i]== NULL)no_mem_exit("init_global_buffers: p_Vid->siblock_JV");}cps->siblock = NULL;}else{memory_size += get_mem2Dint(&(cps->siblock), cps->FrameHeightInMbs, cps->PicWidthInMbs);}init_qp_process(cps);cps->oldFrameSizeInMbs = cps->FrameSizeInMbs;if(layer_id == 0 )init_output(cps, ((cps->pic_unit_bitsize_on_disk+7) >> 3));elsecps->img2buf = p_Vid->p_EncodePar[0]->img2buf;p_Vid->global_init_done[layer_id] = 1;return (memory_size);
}
qp 到反向量化矩阵是一个映射关系,由一个表定义。qp/6 和qp%6的值决定了矩阵中的相应位置上的值。CodingParameters中的qp_per_matrix 是qp/6的值的数组,qp_rem_matrix是qp%6的数组,便于直接通过qp获取到这两个值。init_qp_process 的工作就是初始化这两个数组。
void init_qp_process(CodingParameters *cps)
{int bitdepth_qp_scale = imax(cps->bitdepth_luma_qp_scale, cps->bitdepth_chroma_qp_scale);int i;// We should allocate memory outside of this process since maybe we will have a change of SPS // and we may need to recreate these. Currently should only support same bitdepthif (cps->qp_per_matrix == NULL)if ((cps->qp_per_matrix = (int*)malloc((MAX_QP + 1 + bitdepth_qp_scale)*sizeof(int))) == NULL)no_mem_exit("init_qp_process: cps->qp_per_matrix");if (cps->qp_rem_matrix == NULL)if ((cps->qp_rem_matrix = (int*)malloc((MAX_QP + 1 + bitdepth_qp_scale)*sizeof(int))) == NULL)no_mem_exit("init_qp_process: cps->qp_rem_matrix");for (i = 0; i < MAX_QP + bitdepth_qp_scale + 1; i++){cps->qp_per_matrix[i] = i / 6;cps->qp_rem_matrix[i] = i % 6;}
}
static void set_coding_par(seq_parameter_set_rbsp_t *sps, CodingParameters *cps)
{// maximum vertical motion vector range in luma quarter pixel unitscps->profile_idc = sps->profile_idc;cps->lossless_qpprime_flag = sps->lossless_qpprime_flag;if (sps->level_idc <= 10){cps->max_vmv_r = 64 * 4;}else if (sps->level_idc <= 20){cps->max_vmv_r = 128 * 4;}else if (sps->level_idc <= 30){cps->max_vmv_r = 256 * 4;}else{cps->max_vmv_r = 512 * 4; // 512 pixels in quarter pixels}// Fidelity Range Extensions stuff (part 1)cps->bitdepth_chroma = 0;cps->width_cr = 0;cps->height_cr = 0;亮度bit深度cps->bitdepth_luma = (short) (sps->bit_depth_luma_minus8 + 8);cps->bitdepth_scale[0] = 1 << sps->bit_depth_luma_minus8;if (sps->chroma_format_idc != YUV400){有色度分量时cps->bitdepth_chroma = (short) (sps->bit_depth_chroma_minus8 + 8);cps->bitdepth_scale[1] = 1 << sps->bit_depth_chroma_minus8;}
最大帧号cps->max_frame_num = 1<<(sps->log2_max_frame_num_minus4+4);cps->PicWidthInMbs = (sps->pic_width_in_mbs_minus1 +1);cps->PicHeightInMapUnits = (sps->pic_height_in_map_units_minus1 +1);cps->FrameHeightInMbs = ( 2 - sps->frame_mbs_only_flag ) * cps->PicHeightInMapUnits;cps->FrameSizeInMbs = cps->PicWidthInMbs * cps->FrameHeightInMbs;
输入原始图像格式cps->yuv_format=sps->chroma_format_idc;色彩通道是否分离[source参数描述](https://blog.csdn.net/dongkun152/article/details/118912591?spm=1001.2014.3001.5501)cps->separate_colour_plane_flag = sps->separate_colour_plane_flag;if( cps->separate_colour_plane_flag ){cps->ChromaArrayType = 0;}else{cps->ChromaArrayType = sps->chroma_format_idc;}
宏块尺寸默认16*16cps->width = cps->PicWidthInMbs * MB_BLOCK_SIZE;cps->height = cps->FrameHeightInMbs * MB_BLOCK_SIZE; cps->iLumaPadX = MCBUF_LUMA_PAD_X;cps->iLumaPadY = MCBUF_LUMA_PAD_Y;cps->iChromaPadX = MCBUF_CHROMA_PAD_X;cps->iChromaPadY = MCBUF_CHROMA_PAD_Y;if (sps->chroma_format_idc == YUV420){YUV420时 色度是亮度的一半cps->width_cr = (cps->width >> 1);cps->height_cr = (cps->height >> 1);}else if (sps->chroma_format_idc == YUV422){cps->width_cr = (cps->width >> 1);cps->height_cr = cps->height;cps->iChromaPadY = MCBUF_CHROMA_PAD_Y*2;}else if (sps->chroma_format_idc == YUV444){//YUV444cps->width_cr = cps->width;cps->height_cr = cps->height;cps->iChromaPadX = cps->iLumaPadX;cps->iChromaPadY = cps->iLumaPadY;}//pel bitdepth initcps->bitdepth_luma_qp_scale = 6 * (cps->bitdepth_luma - 8);if(cps->bitdepth_luma > cps->bitdepth_chroma || sps->chroma_format_idc == YUV400)cps->pic_unit_bitsize_on_disk = (cps->bitdepth_luma > 8)? 16:8;elsecps->pic_unit_bitsize_on_disk = (cps->bitdepth_chroma > 8)? 16:8;cps->dc_pred_value_comp[0] = 1<<(cps->bitdepth_luma - 1);cps->max_pel_value_comp[0] = (1<<cps->bitdepth_luma) - 1;宏块只存16*16cps->mb_size[0][0] = cps->mb_size[0][1] = MB_BLOCK_SIZE;if (sps->chroma_format_idc != YUV400){//for chrominance partcps->bitdepth_chroma_qp_scale = 6 * (cps->bitdepth_chroma - 8);cps->dc_pred_value_comp[1] = (1 << (cps->bitdepth_chroma - 1));cps->dc_pred_value_comp[2] = cps->dc_pred_value_comp[1];cps->max_pel_value_comp[1] = (1 << cps->bitdepth_chroma) - 1;cps->max_pel_value_comp[2] = (1 << cps->bitdepth_chroma) - 1;cps->num_blk8x8_uv = (1 << sps->chroma_format_idc) & (~(0x1));cps->num_uv_blocks = (cps->num_blk8x8_uv >> 1);cps->num_cdc_coeff = (cps->num_blk8x8_uv << 1);cps->mb_size[1][0] = cps->mb_size[2][0] = cps->mb_cr_size_x = (sps->chroma_format_idc==YUV420 || sps->chroma_format_idc==YUV422)? 8 : 16;cps->mb_size[1][1] = cps->mb_size[2][1] = cps->mb_cr_size_y = (sps->chroma_format_idc==YUV444 || sps->chroma_format_idc==YUV422)? 16 : 8;cps->subpel_x = cps->mb_cr_size_x == 8 ? 7 : 3;cps->subpel_y = cps->mb_cr_size_y == 8 ? 7 : 3;cps->shiftpel_x = cps->mb_cr_size_x == 8 ? 3 : 2;cps->shiftpel_y = cps->mb_cr_size_y == 8 ? 3 : 2;cps->total_scale = cps->shiftpel_x + cps->shiftpel_y;}else{cps->bitdepth_chroma_qp_scale = 0;cps->max_pel_value_comp[1] = 0;cps->max_pel_value_comp[2] = 0;cps->num_blk8x8_uv = 0;cps->num_uv_blocks = 0;cps->num_cdc_coeff = 0;cps->mb_size[1][0] = cps->mb_size[2][0] = cps->mb_cr_size_x = 0;cps->mb_size[1][1] = cps->mb_size[2][1] = cps->mb_cr_size_y = 0;cps->subpel_x = 0;cps->subpel_y = 0;cps->shiftpel_x = 0;cps->shiftpel_y = 0;cps->total_scale = 0;}cps->mb_cr_size = cps->mb_cr_size_x * cps->mb_cr_size_y;cps->mb_size_blk[0][0] = cps->mb_size_blk[0][1] = cps->mb_size[0][0] >> 2;cps->mb_size_blk[1][0] = cps->mb_size_blk[2][0] = cps->mb_size[1][0] >> 2;cps->mb_size_blk[1][1] = cps->mb_size_blk[2][1] = cps->mb_size[1][1] >> 2;cps->mb_size_shift[0][0] = cps->mb_size_shift[0][1] = CeilLog2_sf (cps->mb_size[0][0]);cps->mb_size_shift[1][0] = cps->mb_size_shift[2][0] = CeilLog2_sf (cps->mb_size[1][0]);cps->mb_size_shift[1][1] = cps->mb_size_shift[2][1] = CeilLog2_sf (cps->mb_size[1][1]);cps->rgb_output = (sps->vui_seq_parameters.matrix_coefficients==0);
}
分配量化参数
/*!************************************************************************* \brief* For mapping the q-matrix to the active id and calculate quantisation values** \param currSlice* Slice pointer* \param pps* Picture parameter set* \param sps* Sequence parameter set**************************************************************************/
void assign_quant_params(Slice *currSlice)
{seq_parameter_set_rbsp_t* sps = currSlice->active_sps;pic_parameter_set_rbsp_t* pps = currSlice->active_pps;int i;int n_ScalingList;
当sps和pps中放大系数矩阵都不存在时,使用的默认的参数if(!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag){for(i=0; i<12; i++)currSlice->qmatrix[i] = (i < 6) ? quant_org : quant8_org;}else{n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;if(sps->seq_scaling_matrix_present_flag) // check sps first{for(i=0; i<n_ScalingList; i++){if(i<6){if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A{if(i==0)currSlice->qmatrix[i] = quant_intra_default;else if(i==3)currSlice->qmatrix[i] = quant_inter_default;elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-1];}else{if(sps->UseDefaultScalingMatrix4x4Flag[i])currSlice->qmatrix[i] = (i<3) ? quant_intra_default : quant_inter_default;elsecurrSlice->qmatrix[i] = sps->ScalingList4x4[i];}}else{if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A{if(i==6)currSlice->qmatrix[i] = quant8_intra_default;else if(i==7)currSlice->qmatrix[i] = quant8_inter_default;elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-2];}else{if(sps->UseDefaultScalingMatrix8x8Flag[i-6])currSlice->qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;elsecurrSlice->qmatrix[i] = sps->ScalingList8x8[i-6];}}}}if(pps->pic_scaling_matrix_present_flag) // then check pps{for(i=0; i<n_ScalingList; i++){if(i<6){if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B{if (i==0){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant_intra_default;}else if (i==3){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant_inter_default;}elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-1];}else{if(pps->UseDefaultScalingMatrix4x4Flag[i])currSlice->qmatrix[i] = (i<3) ? quant_intra_default:quant_inter_default;elsecurrSlice->qmatrix[i] = pps->ScalingList4x4[i];}}else{if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B{if (i==6){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant8_intra_default;}else if(i==7){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant8_inter_default;}else currSlice->qmatrix[i] = currSlice->qmatrix[i-2];}else{if(pps->UseDefaultScalingMatrix8x8Flag[i-6])currSlice->qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;elsecurrSlice->qmatrix[i] = pps->ScalingList8x8[i-6];}}}}}
计算实际使用的4x4量化参数CalculateQuant4x4Param(currSlice);if(pps->transform_8x8_mode_flag)CalculateQuant8x8Param(currSlice);
}
计算量化参数就是在 dequant_coef反量化系数矩阵每个元素上乘以默认放大矩阵的每个元素。
/*!************************************************************************* \brief* For calculating the quantisation values at frame level**************************************************************************/
void CalculateQuant4x4Param(Slice *currSlice)
{int k;const int (*p_dequant_coef)[4][4] = dequant_coef;int (*InvLevelScale4x4_Intra_0)[4][4] = currSlice->InvLevelScale4x4_Intra[0];int (*InvLevelScale4x4_Intra_1)[4][4] = currSlice->InvLevelScale4x4_Intra[1];int (*InvLevelScale4x4_Intra_2)[4][4] = currSlice->InvLevelScale4x4_Intra[2];int (*InvLevelScale4x4_Inter_0)[4][4] = currSlice->InvLevelScale4x4_Inter[0];int (*InvLevelScale4x4_Inter_1)[4][4] = currSlice->InvLevelScale4x4_Inter[1];int (*InvLevelScale4x4_Inter_2)[4][4] = currSlice->InvLevelScale4x4_Inter[2];for(k=0; k<6; k++){set_dequant4x4(*InvLevelScale4x4_Intra_0++, *p_dequant_coef , currSlice->qmatrix[0]);set_dequant4x4(*InvLevelScale4x4_Intra_1++, *p_dequant_coef , currSlice->qmatrix[1]);set_dequant4x4(*InvLevelScale4x4_Intra_2++, *p_dequant_coef , currSlice->qmatrix[2]);set_dequant4x4(*InvLevelScale4x4_Inter_0++, *p_dequant_coef , currSlice->qmatrix[3]);set_dequant4x4(*InvLevelScale4x4_Inter_1++, *p_dequant_coef , currSlice->qmatrix[4]);set_dequant4x4(*InvLevelScale4x4_Inter_2++, *p_dequant_coef++, currSlice->qmatrix[5]);}
}static void set_dequant4x4(int (*InvLevelScale4x4)[4], const int (*dequant)[4], int *qmatrix)
{int j;for(j=0; j<4; j++){*(*InvLevelScale4x4 ) = *(*dequant ) * *qmatrix++;*(*InvLevelScale4x4 + 1) = *(*dequant + 1) * *qmatrix++;*(*InvLevelScale4x4 + 2) = *(*dequant + 2) * *qmatrix++;*(*InvLevelScale4x4++ + 3) = *(*dequant++ + 3) * *qmatrix++;}
}
反量化关于QP的函数矩阵如下
参考变换和量化
//! Dequantization coefficients
static const int dequant_coef[6][4][4] = {{{ 10, 13, 10, 13},{ 13, 16, 13, 16},{ 10, 13, 10, 13},{ 13, 16, 13, 16}},{{ 11, 14, 11, 14},{ 14, 18, 14, 18},{ 11, 14, 11, 14},{ 14, 18, 14, 18}},{{ 13, 16, 13, 16},{ 16, 20, 16, 20},{ 13, 16, 13, 16},{ 16, 20, 16, 20}},{{ 14, 18, 14, 18},{ 18, 23, 18, 23},{ 14, 18, 14, 18},{ 18, 23, 18, 23}},{{ 16, 20, 16, 20},{ 20, 25, 20, 25},{ 16, 20, 16, 20},{ 20, 25, 20, 25}},{{ 18, 23, 18, 23},{ 23, 29, 23, 29},{ 18, 23, 18, 23},{ 23, 29, 23, 29}}
};
slice_data 处理
开始读取slice_data, setup_slice_methods()根据不同的slice type 设置回调函数。
/*!************************************************************************* \brief* Set mode interpretation based on slice type*************************************************************************/
void setup_slice_methods(Slice *currSlice)
{setup_read_macroblock (currSlice);switch (currSlice->slice_type){case P_SLICE: currSlice->interpret_mb_mode = interpret_mb_mode_P;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_p_slice;currSlice->decode_one_component = decode_one_component_p_slice;currSlice->update_direct_mv_info = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists = currSlice->view_id ? init_lists_p_slice_mvc : init_lists_p_slice;
#elsecurrSlice->init_lists = init_lists_p_slice;
#endifbreak;case SP_SLICE:currSlice->interpret_mb_mode = interpret_mb_mode_P;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_p_slice;currSlice->decode_one_component = decode_one_component_sp_slice;currSlice->update_direct_mv_info = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists = currSlice->view_id ? init_lists_p_slice_mvc : init_lists_p_slice;
#elsecurrSlice->init_lists = init_lists_p_slice;
#endifbreak;case B_SLICE:currSlice->interpret_mb_mode = interpret_mb_mode_B;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_b_slice;currSlice->decode_one_component = decode_one_component_b_slice;update_direct_types(currSlice);
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists = currSlice->view_id ? init_lists_b_slice_mvc : init_lists_b_slice;
#elsecurrSlice->init_lists = init_lists_b_slice;
#endifbreak;case I_SLICE: currSlice->interpret_mb_mode = interpret_mb_mode_I;currSlice->read_motion_info_from_NAL = NULL;currSlice->decode_one_component = decode_one_component_i_slice;currSlice->update_direct_mv_info = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists = currSlice->view_id ? init_lists_i_slice_mvc : init_lists_i_slice;
#elsecurrSlice->init_lists = init_lists_i_slice;
#endifbreak;case SI_SLICE: currSlice->interpret_mb_mode = interpret_mb_mode_SI;currSlice->read_motion_info_from_NAL = NULL;currSlice->decode_one_component = decode_one_component_i_slice;currSlice->update_direct_mv_info = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists = currSlice->view_id ? init_lists_i_slice_mvc : init_lists_i_slice;
#elsecurrSlice->init_lists = init_lists_i_slice;
#endifbreak;default:printf("Unsupported slice type\n");break;}set_intra_prediction_modes(currSlice);if ( currSlice->p_Vid->active_sps->chroma_format_idc==YUV444 && (currSlice->p_Vid->separate_colour_plane_flag == 0) )currSlice->read_coeff_4x4_CAVLC = read_coeff_4x4_CAVLC_444;elsecurrSlice->read_coeff_4x4_CAVLC = read_coeff_4x4_CAVLC;switch(currSlice->p_Vid->active_pps->entropy_coding_mode_flag){case CABAC:set_read_CBP_and_coeffs_cabac(currSlice);break;case CAVLC:set_read_CBP_and_coeffs_cavlc(currSlice);break;default:printf("Unsupported entropy coding mode\n");break;}
}
void set_intra_prediction_modes(Slice *currSlice)
{ if (currSlice->mb_aff_frame_flag){currSlice->intra_pred_4x4 = intra_pred_4x4_mbaff;currSlice->intra_pred_8x8 = intra_pred_8x8_mbaff;currSlice->intra_pred_16x16 = intra_pred_16x16_mbaff; currSlice->intra_pred_chroma = intra_pred_chroma_mbaff;}else{currSlice->intra_pred_4x4 = intra_pred_4x4_normal; currSlice->intra_pred_8x8 = intra_pred_8x8_normal;currSlice->intra_pred_16x16 = intra_pred_16x16_normal;currSlice->intra_pred_chroma = intra_pred_chroma; }
}
void set_read_CBP_and_coeffs_cabac(Slice *currSlice)
{switch (currSlice->p_Vid->active_sps->chroma_format_idc){case YUV444:if (currSlice->p_Vid->separate_colour_plane_flag == 0){currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_444;}else{currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_400;}break;case YUV422:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_422;break;case YUV420:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_420;break;case YUV400:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_400;break;default:assert (1);currSlice->read_CBP_and_coeffs_from_NAL = NULL;break;}
}
JM ldecod分析: 分帧处理相关推荐
- 基于MATLAB的语音信号的时域特性分析(一)——分帧、窗函数
语音信号是一个非稳态的.时变的信号.但在"短时间"范围内可以认为语音信号是稳态的.时不变的.这个短时间一般值10~30ms.由于有这个特性,故常把语音信号称为"准稳态 ...
- 关于语音分帧时有重叠部分的原因分析
在用Matlab进行语音分析时,通常会用读入的数据进行分帧处理.在分帧中,往往设置在相邻两帧之间有一部分重叠. 其原因是:语音信号是时变的,在短时范围内特征变化较小,所以做为稳态来处理:但超出这短时范 ...
- 语音信号分析(语音分帧)
语音分帧 不管是进行什么参数分析以及采用什么分析方法,都需要一些预先的处理,如语音信号的数字化.语音信号的端点检测.预加重.加窗和分帧等,这些也是不可忽视的语音信号分析的关键技术.贯穿于语音分析全过程 ...
- 音频处理四:(音频的分帧)
程序设计四:音频的分帧 一:需求分析 为了分析读人数据,通常进行分帧处理.在分帧中,往往设置在相邻两帧之间有一部分重叠.其原因是:语音信号是时变的,在短时范围内特征变化较小,所以作为稳态来处理;但超出 ...
- 语音信号处理基础(五)——语音分帧与加窗
文章目录 原理 1.加窗 2.分帧 一般而言语音处理的目的有两种: 一种是对语音信号进行分析,提取特征参数,用于后续处理: 提取的特征参数主要有语音的短时能量和平均幅度.短时平均过零率.短时自相关函数 ...
- 语音信号处理中怎么理解分帧?
那么一帧有多长呢?帧长要满足两个条件: 从宏观上看,它必须足够短来保证帧内信号是平稳的. 前面说过,口型的变化是导致信号不平稳的原因,所以在一帧的期间内口型不能有明显变化,即一帧的长度应当小于一个音素 ...
- 已开源!Flutter 基于分帧渲染的流畅度优化组件 Keframe
大家好,这里是承香墨影! 今天给大家推荐一个,Flutter 中利用分帧渲染优化流程度的开源库,刚开源,还热乎着.这次开源可真波折,看着 @Nayuta 前前后后在公司内部流程走了一个多月吧,太艰难了 ...
- matlab语音分帧加窗,语音信号的加窗处理
平稳的随机过程是研究语音信号的主要手段,但是语音信号本身并不是平衡的. 一,语音信号不平稳 语音信号在产生过程中与环境和发声器官的联系很紧密,与各种运动都是相关的,信号本身是不平移的信号.主要是由于发 ...
- python对语音信号读取、分帧、加窗
python对语音信号读取.分帧.加窗 一.读入音频信号 语音信号有三个重要的参数:声道数.取样频率和量化位数. 声道数:单声道或者双声道 采样频率:一秒钟对声音采样的次数,例如10000HZ代表一秒 ...
最新文章
- 全国自考微型计算机原理及其应用,2010年10月全国自考微型计算机原理及应用试题...
- hdu4081 最小树+DFS或者次小树的变形
- 不动产登记证书曝光 一个“改变”必须注意(图)
- ES-PHP向ES批量添加文档报No alive nodes found in your cluster
- .NET Core系列 : 2 、project.json 这葫芦里卖的什么药
- 编写高性能 Web 应用程序的 10 个技巧 (转)
- vb.net 窗体接收键盘事件_(十五)C#WinFrom自定义控件系列-键盘(二)
- Oracle杂谈二 SQL*PLUS命令的使用大全
- Eclipse Egit 安装
- Android图片的三级缓存整理
- 蓝桥杯题目练习 水题 [蓝桥杯2019初赛]矩形切割
- 基于STM32战舰开发板的内部温度传感器实验
- 如今表情包的天下,曾经可是颜文字和Emoji的啊...
- Python每日一练(23)-基于百度 AI 识别抓取的表情包
- 多目标进化算法详细讲解及代码实现(样例:MOEA/D、NSGA-Ⅱ求解多目标(柔性)作业车间调度问题)
- 概率统计Python计算:贝叶斯公式
- 【数字IC/FPGA】仲裁器进阶--Round Robin Arbiter
- 如何高效地使用ERP管理系统
- 卡罗拉 (COROLLA) - 油箱盖
- LMS自适应滤波matlab仿真