/*! ************************************************************************ * \brief * Interpret the Progressive refinement segment start SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_progressive_refinement_start_info( byte* payload, int size, ImageParameters *img ) { int progressive_refinement_id, num_refinement_steps_minus1; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; progressive_refinement_id = ue_v("SEI: progressive_refinement_id" , buf); num_refinement_steps_minus1 = ue_v("SEI: num_refinement_steps_minus1", buf); #ifdef PRINT_PROGRESSIVE_REFINEMENT_START_INFO printf("Progressive refinement segment start SEI message\n"); printf("progressive_refinement_id = %d\n", progressive_refinement_id); printf("num_refinement_steps_minus1 = %d\n", num_refinement_steps_minus1); #endif free (buf); #ifdef PRINT_PROGRESSIVE_REFINEMENT_START_INFO #undef PRINT_PROGRESSIVE_REFINEMENT_START_INFO #endif }
/*! ************************************************************************ * \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_slice currSlice->start_mb_nr = ue_v ("SH: first_mb_in_slice", currStream); tmp = ue_v ("SH: slice_type", currStream); if (tmp > 4) tmp -= 5; p_Vid->type = currSlice->slice_type = (SliceType) tmp; currSlice->pic_parameter_set_id = ue_v ("SH: pic_parameter_set_id", currStream); if( p_Vid->separate_colour_plane_flag ) currSlice->colour_plane_id = u_v (2, "SH: colour_plane_id", currStream); else currSlice->colour_plane_id = PLANE_Y; return p_Dec->UsedBits; }
/*! ************************************************************************ * \brief * Interpret the Scene information SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_scene_information( byte* payload, int size, ImageParameters *img ) { Bitstream* buf; int scene_id, scene_transition_type, second_scene_id; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; scene_id = ue_v("SEI: scene_id" , buf); scene_transition_type = ue_v("SEI: scene_transition_type", buf); if ( scene_transition_type > 3 ) { second_scene_id = ue_v("SEI: scene_transition_type", buf);; } #ifdef PRINT_SCENE_INFORMATION printf("Scene information SEI message\n"); printf("scene_transition_type = %d\n", scene_transition_type); printf("scene_id = %d\n", scene_id); if ( scene_transition_type > 3 ) { printf("second_scene_id = %d\n", second_scene_id); } #endif free( buf ); #ifdef PRINT_SCENE_INFORMATION #undef PRINT_SCENE_INFORMATION #endif }
/*! ************************************************************************ * \brief * Interpret the Motion-constrained slice group set SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_motion_constrained_slice_group_set_info( byte* payload, int size, ImageParameters *img ) { int num_slice_groups_minus1, slice_group_id, exact_match_flag, pan_scan_rect_flag, pan_scan_rect_id; int i; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; num_slice_groups_minus1 = ue_v("SEI: num_slice_groups_minus1" , buf); #ifdef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO printf("Motion-constrained slice group set SEI message\n"); printf("num_slice_groups_minus1 = %d\n", num_slice_groups_minus1); #endif for (i=0; i<=num_slice_groups_minus1;i++) { slice_group_id = ue_v("SEI: slice_group_id" , buf); #ifdef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO printf("slice_group_id = %d\n", slice_group_id); #endif } exact_match_flag = u_1("SEI: exact_match_flag" , buf); pan_scan_rect_flag = u_1("SEI: pan_scan_rect_flag" , buf); #ifdef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO printf("exact_match_flag = %d\n", exact_match_flag); printf("pan_scan_rect_flag = %d\n", pan_scan_rect_flag); #endif if (pan_scan_rect_flag) { pan_scan_rect_id = ue_v("SEI: pan_scan_rect_id" , buf); #ifdef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO printf("pan_scan_rect_id = %d\n", pan_scan_rect_id); #endif } free (buf); #ifdef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO #undef PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO #endif }
/*! ************************************************************************ * \brief * Interpret the Sub-sequence layer characteristics SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_subsequence_layer_characteristics_info( byte* payload, int size, ImageParameters *img ) { Bitstream* buf; long num_sub_layers, accurate_statistics_flag, average_bit_rate, average_frame_rate; int i; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; num_sub_layers = 1 + ue_v("SEI: num_sub_layers_minus1", buf); #ifdef PRINT_SUBSEQUENCE_LAYER_CHAR printf("Sub-sequence layer characteristics SEI message\n"); printf("num_sub_layers_minus1 = %d\n", num_sub_layers - 1); #endif for (i=0; i<num_sub_layers; i++) { accurate_statistics_flag = u_1( "SEI: accurate_statistics_flag", buf); average_bit_rate = u_v(16,"SEI: average_bit_rate" , buf); average_frame_rate = u_v(16,"SEI: average_frame_rate" , buf); #ifdef PRINT_SUBSEQUENCE_LAYER_CHAR printf("layer %d: accurate_statistics_flag = %ld \n", i, accurate_statistics_flag); printf("layer %d: average_bit_rate = %ld \n", i, average_bit_rate); printf("layer %d: average_frame_rate = %ld \n", i, average_frame_rate); #endif } free (buf); }
/*! ************************************************************************ * \brief * Interpret the Pan scan rectangle SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_pan_scan_rect_info( byte* payload, int size, ImageParameters *img ) { int pan_scan_rect_id, pan_scan_rect_left_offset, pan_scan_rect_right_offset; int pan_scan_rect_top_offset, pan_scan_rect_bottom_offset; Bitstream* buf; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; pan_scan_rect_id = ue_v("SEI: pan_scan_rect_id", buf); pan_scan_rect_left_offset = se_v("SEI: pan_scan_rect_left_offset" , buf); pan_scan_rect_right_offset = se_v("SEI: pan_scan_rect_right_offset" , buf); pan_scan_rect_top_offset = se_v("SEI: pan_scan_rect_top_offset" , buf); pan_scan_rect_bottom_offset = se_v("SEI: pan_scan_rect_bottom_offset", buf); #ifdef PRINT_PAN_SCAN_RECT printf("Pan scan rectangle SEI message\n"); printf("pan_scan_rect_id = %d\n", pan_scan_rect_id); printf("pan_scan_rect_left_offset = %d\n", pan_scan_rect_left_offset); printf("pan_scan_rect_right_offset = %d\n", pan_scan_rect_right_offset); printf("pan_scan_rect_top_offset = %d\n", pan_scan_rect_top_offset); printf("pan_scan_rect_bottom_offset = %d\n", pan_scan_rect_bottom_offset); #endif free (buf); #ifdef PRINT_PAN_SCAN_RECT #undef PRINT_PAN_SCAN_RECT #endif }
/*! ************************************************************************ * \brief * Interpret the Full-frame snapshot SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_full_frame_snapshot_info( byte* payload, int size, ImageParameters *img ) { int snapshot_id; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; snapshot_id = ue_v("SEI: snapshot_id", buf); #ifdef PRINT_FULL_FRAME_SNAPSHOT_INFO printf("Full-frame snapshot SEI message\n"); printf("snapshot_id = %d\n", snapshot_id); #endif free (buf); #ifdef PRINT_FULL_FRAME_SNAPSHOT_INFO #undef PRINT_FULL_FRAME_SNAPSHOT_INFO #endif }
/*! ************************************************************************ * \brief * Interpret the Random access point SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_random_access_info( byte* payload, int size, ImageParameters *img ) { int recovery_frame_cnt, exact_match_flag, broken_link_flag, changing_slice_group_idc; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; recovery_frame_cnt = ue_v( "SEI: recovery_frame_cnt" , buf); exact_match_flag = u_1 ( "SEI: exact_match_flag" , buf); broken_link_flag = u_1 ( "SEI: broken_link_flag" , buf); changing_slice_group_idc = u_v ( 2, "SEI: changing_slice_group_idc", buf); #ifdef PRINT_RANDOM_ACCESS printf("Random access point SEI message\n"); printf("recovery_frame_cnt = %d\n", recovery_frame_cnt); printf("exact_match_flag = %d\n", exact_match_flag); printf("broken_link_flag = %d\n", broken_link_flag); printf("changing_slice_group_idc = %d\n", changing_slice_group_idc); #endif free (buf); #ifdef PRINT_RANDOM_ACCESS #undef PRINT_RANDOM_ACCESS #endif }
/*! ************************************************************************ * \brief * Interpret the Sub-sequence information SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_subsequence_info( byte* payload, int size, ImageParameters *img ) { Bitstream* buf; int sub_seq_layer_num, sub_seq_id, first_ref_pic_flag, leading_non_ref_pic_flag, last_pic_flag, sub_seq_frame_num_flag, sub_seq_frame_num; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; sub_seq_layer_num = ue_v("SEI: sub_seq_layer_num" , buf); sub_seq_id = ue_v("SEI: sub_seq_id" , buf); first_ref_pic_flag = u_1 ("SEI: first_ref_pic_flag" , buf); leading_non_ref_pic_flag = u_1 ("SEI: leading_non_ref_pic_flag", buf); last_pic_flag = u_1 ("SEI: last_pic_flag" , buf); sub_seq_frame_num_flag = u_1 ("SEI: sub_seq_frame_num_flag" , buf); if (sub_seq_frame_num_flag) { sub_seq_frame_num = ue_v("SEI: sub_seq_frame_num" , buf); } #ifdef PRINT_SUBSEQUENCE_INFO printf("Sub-sequence information SEI message\n"); printf("sub_seq_layer_num = %d\n", sub_seq_layer_num ); printf("sub_seq_id = %d\n", sub_seq_id); printf("first_ref_pic_flag = %d\n", first_ref_pic_flag); printf("leading_non_ref_pic_flag = %d\n", leading_non_ref_pic_flag); printf("last_pic_flag = %d\n", last_pic_flag); printf("sub_seq_frame_num_flag = %d\n", sub_seq_frame_num_flag); if (sub_seq_frame_num_flag) { printf("sub_seq_frame_num = %d\n", sub_seq_frame_num); } #endif free(buf); #ifdef PRINT_SUBSEQUENCE_INFO #undef PRINT_SUBSEQUENCE_INFO #endif }
/*! ************************************************************************ * \brief * Interpret the Buffering period SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_buffering_period_info( byte* payload, int size, ImageParameters *img ) { int seq_parameter_set_id, initial_cpb_removal_delay, initial_cpb_removal_delay_offset; unsigned int k; Bitstream* buf; seq_parameter_set_rbsp_t *sps; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; seq_parameter_set_id = ue_v("SEI: seq_parameter_set_id" , buf); sps = &SeqParSet[seq_parameter_set_id]; #ifdef PRINT_BUFFERING_PERIOD_INFO printf("Buffering period SEI message\n"); printf("seq_parameter_set_id = %d\n", seq_parameter_set_id); #endif if (sps->vui_seq_parameters.nal_hrd_parameters_present_flag) { for (k=0; k<sps->vui_seq_parameters.nal_hrd_parameters.cpb_cnt; k++) { initial_cpb_removal_delay = u_v(sps->vui_seq_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1+1, "SEI: initial_cpb_removal_delay" , buf); initial_cpb_removal_delay_offset = u_v(sps->vui_seq_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1+1, "SEI: initial_cpb_removal_delay_offset" , buf); #ifdef PRINT_BUFFERING_PERIOD_INFO printf("nal initial_cpb_removal_delay[%d] = %d\n", k, initial_cpb_removal_delay); printf("nal initial_cpb_removal_delay_offset[%d] = %d\n", k, initial_cpb_removal_delay_offset); #endif } } if (sps->vui_seq_parameters.vcl_hrd_parameters_present_flag) { for (k=0; k<sps->vui_seq_parameters.vcl_hrd_parameters.cpb_cnt; k++) { initial_cpb_removal_delay = u_v(sps->vui_seq_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1+1, "SEI: initial_cpb_removal_delay" , buf); initial_cpb_removal_delay_offset = u_v(sps->vui_seq_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1+1, "SEI: initial_cpb_removal_delay_offset" , buf); #ifdef PRINT_BUFFERING_PERIOD_INFO printf("vcl initial_cpb_removal_delay[%d] = %d\n", k, initial_cpb_removal_delay); printf("vcl initial_cpb_removal_delay_offset[%d] = %d\n", k, initial_cpb_removal_delay_offset); #endif } } free (buf); #ifdef PRINT_BUFFERING_PERIOD_INFO #undef PRINT_BUFFERING_PERIOD_INFO #endif }
/*! ************************************************************************ * \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 = img->currentSlice; int dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER]; DataPartition *partition = &(currSlice->partArr[dP_nr]); Bitstream *currStream = partition->bitstream; int tmp; UsedBits= partition->bitstream->frame_bitoffset; // was hardcoded to 31 for previous start-code. This is better. // Get first_mb_in_slice currSlice->start_mb_nr = ue_v ("SH: first_mb_in_slice", currStream); tmp = ue_v ("SH: slice_type", currStream); if (tmp>4) tmp -=5; img->type = currSlice->picture_type = (SliceType) tmp; currSlice->pic_parameter_set_id = ue_v ("SH: pic_parameter_set_id", currStream); return UsedBits; }
/*! ************************************************************************ * \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) *----------------------------------------------------------------------- * Function Argument List Changed [Removing Global Variables] * Input parameters added are * - h264_decoder* dec_params * * <*****@*****.**> ************************************************************************ */ int FirstPartOfSliceHeader( h264_decoder* dec_params) { Slice *currSlice = dec_params->img->currentSlice; //int dP_nr = assignSE2partition[PAR_DP_1][SE_HEADER]; //int dP_nr = 0; DataPartition *partition = &(currSlice->partArr[0]); Bitstream *currStream = partition->bitstream; int tmp; dec_params->UsedBits= partition->bitstream->frame_bitoffset; // was hardcoded to 31 for previous start-code. This is better. // Get first_mb_in_slice currSlice->start_mb_nr = ue_v ("SH: first_mb_in_slice", currStream,dec_params); tmp = ue_v ("SH: slice_type", currStream,dec_params); if (tmp>4) tmp -=5; dec_params->img->type = currSlice->picture_type = (SliceType) tmp; currSlice->pic_parameter_set_id = ue_v ("SH: pic_parameter_set_id", currStream,dec_params); return dec_params->UsedBits; }
static void ref_pic_list_reordering( h264_decoder* dec_params ) { Slice *currSlice = dec_params->img->currentSlice; //int dP_nr = assignSE2partition[PAR_DP_1][SE_HEADER]; //int dP_nr = 0; DataPartition *partition = &(currSlice->partArr[0]); Bitstream *currStream = partition->bitstream; int i, val; alloc_ref_pic_list_reordering_buffer( currSlice, dec_params ); if (dec_params->img->type!=I_SLICE) { val = currSlice->ref_pic_list_reordering_flag_l0 = u_1 ("SH: ref_pic_list_reordering_flag_l0", currStream,dec_params); if (val) { i=0; do { val = currSlice->remapping_of_pic_nums_idc_l0[i] = ue_v("SH: remapping_of_pic_nums_idc_l0", currStream,dec_params); if (val==0 || val==1) { currSlice->abs_diff_pic_num_minus1_l0[i] = ue_v("SH: abs_diff_pic_num_minus1_l0", currStream,dec_params); } else { if (val==2) { currSlice->long_term_pic_idx_l0[i] = ue_v("SH: long_term_pic_idx_l0", currStream,dec_params); } } i++; // assert (i>dec_params->img->num_ref_idx_l0_active); } while (val != 3); } } if (dec_params->img->type==B_SLICE) { val = currSlice->ref_pic_list_reordering_flag_l1 = u_1 ("SH: ref_pic_list_reordering_flag_l1", currStream,dec_params); if (val) { i=0; do { val = currSlice->remapping_of_pic_nums_idc_l1[i] = ue_v("SH: remapping_of_pic_nums_idc_l1", currStream,dec_params); if (val==0 || val==1) { currSlice->abs_diff_pic_num_minus1_l1[i] = ue_v("SH: abs_diff_pic_num_minus1_l1", currStream,dec_params); } else { if (val==2) { currSlice->long_term_pic_idx_l1[i] = ue_v("SH: long_term_pic_idx_l1", currStream,dec_params); } } i++; // assert (i>dec_params->img->num_ref_idx_l1_active); } while (val != 3); } } }
/*! ******************************************************************************************** * \brief * Write a slice header ******************************************************************************************** */ int SliceHeader(int first_mb_in_slice) { //ue_v(img.current_mb_nr); ue_v(first_mb_in_slice); ue_v(get_picture_type ()); ue_v(0); //assert (img.frame_num < 1<<(LOG2_MAX_FRAME_NUM_MINUS4+4)); // check that it fits u_v (LOG2_MAX_FRAME_NUM_MINUS4 + 4, img.frame_num); //added by eskim as what jjs said for another decoder to decode result stream, such as JM11 and GOM player if(img.number == 0) ue_v (0); img.pic_order_cnt_lsb = (img.framepoc & 0xff); u_v (LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4+4, img.pic_order_cnt_lsb); // ist there any sense in the following assignments ??? if (img.type == P_SLICE) { // num_ref_idx_active_override_flag here always 1 u_1 (1); ue_v (img.num_ref_idx_l0_active-1); } ref_pic_list_reordering(); if (img.nal_reference_idc) dec_ref_pic_marking(); // we transmit zero in the pps, so here the real QP se_v((img.qp - 26)); if (input.LFSendParameters) { ue_v(input.LFDisableIdc); // Turn loop filter on/off on slice basis if (input.LFDisableIdc!=1) { se_v (input.LFAlphaC0Offset / 2); se_v (input.LFBetaOffset / 2); } } //MSG(SLICE_HEADER); return 0; }
/*! ************************************************************************ * \brief * Interpret the Progressive refinement segment end SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_progressive_refinement_end_info( byte* payload, int size, ImageParameters *img ) { int progressive_refinement_id; Bitstream* buf; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; progressive_refinement_id = ue_v("SEI: progressive_refinement_id" , buf); #ifdef PRINT_PROGRESSIVE_REFINEMENT_END_INFO printf("Progressive refinement segment end SEI message\n"); printf("progressive_refinement_id = %d\n", progressive_refinement_id); #endif free (buf); #ifdef PRINT_PROGRESSIVE_REFINEMENT_END_INFO #undef PRINT_PROGRESSIVE_REFINEMENT_END_INFO #endif }
/*! ************************************************************************ * \brief * Interpret the Sub-sequence characteristics SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_subsequence_characteristics_info( byte* payload, int size, ImageParameters *img ) { Bitstream* buf; int i; int sub_seq_layer_num, sub_seq_id, duration_flag, average_rate_flag, accurate_statistics_flag; unsigned long sub_seq_duration, average_bit_rate, average_frame_rate; int num_referenced_subseqs, ref_sub_seq_layer_num, ref_sub_seq_id, ref_sub_seq_direction; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; sub_seq_layer_num = ue_v("SEI: sub_seq_layer_num", buf); sub_seq_id = ue_v("SEI: sub_seq_id", buf); duration_flag = u_1 ("SEI: duration_flag", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("Sub-sequence characteristics SEI message\n"); printf("sub_seq_layer_num = %d\n", sub_seq_layer_num ); printf("sub_seq_id = %d\n", sub_seq_id); printf("duration_flag = %d\n", duration_flag); #endif if ( duration_flag ) { sub_seq_duration = u_v (32, "SEI: duration_flag", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("sub_seq_duration = %ld\n", sub_seq_duration); #endif } average_rate_flag = u_1 ("SEI: average_rate_flag", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("average_rate_flag = %d\n", average_rate_flag); #endif if ( average_rate_flag ) { accurate_statistics_flag = u_1 ( "SEI: accurate_statistics_flag", buf); average_bit_rate = u_v (16, "SEI: average_bit_rate", buf); average_frame_rate = u_v (16, "SEI: average_frame_rate", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("accurate_statistics_flag = %d\n", accurate_statistics_flag); printf("average_bit_rate = %ld\n", average_bit_rate); printf("average_frame_rate = %ld\n", average_frame_rate); #endif } num_referenced_subseqs = ue_v("SEI: num_referenced_subseqs", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("num_referenced_subseqs = %d\n", num_referenced_subseqs); #endif for (i=0; i<num_referenced_subseqs; i++) { ref_sub_seq_layer_num = ue_v("SEI: ref_sub_seq_layer_num", buf); ref_sub_seq_id = ue_v("SEI: ref_sub_seq_id", buf); ref_sub_seq_direction = u_1 ("SEI: ref_sub_seq_direction", buf); #ifdef PRINT_SUBSEQUENCE_CHAR printf("ref_sub_seq_layer_num = %d\n", ref_sub_seq_layer_num); printf("ref_sub_seq_id = %d\n", ref_sub_seq_id); printf("ref_sub_seq_direction = %d\n", ref_sub_seq_direction); #endif } free( buf ); #ifdef PRINT_SUBSEQUENCE_CHAR #undef PRINT_SUBSEQUENCE_CHAR #endif }
/*! ************************************************************************ * \brief * read the scond part of the header (without the pic_parameter_set_id * \return * Length of the second part of the Slice header in bits ************************************************************************ */ int RestOfSliceHeader(Slice *currSlice) { VideoParameters *p_Vid = currSlice->p_Vid; InputParameters *p_Inp = currSlice->p_Inp; seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps; byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER]; DataPartition *partition = &(currSlice->partArr[dP_nr]); Bitstream *currStream = partition->bitstream; int val, len; currSlice->frame_num = u_v (active_sps->log2_max_frame_num_minus4 + 4, "SH: frame_num", currStream); /* Tian Dong: frame_num gap processing, if found */ if(currSlice->idr_flag) //if (p_Vid->idr_flag) { p_Vid->pre_frame_num = currSlice->frame_num; // picture error concealment p_Vid->last_ref_pic_poc = 0; assert(currSlice->frame_num == 0); } if (active_sps->frame_mbs_only_flag) { p_Vid->structure = FRAME; currSlice->field_pic_flag=0; } else { // field_pic_flag u(1) currSlice->field_pic_flag = u_1("SH: field_pic_flag", currStream); if (currSlice->field_pic_flag) { // bottom_field_flag u(1) currSlice->bottom_field_flag = (byte) u_1("SH: bottom_field_flag", currStream); p_Vid->structure = currSlice->bottom_field_flag ? BOTTOM_FIELD : TOP_FIELD; } else { p_Vid->structure = FRAME; currSlice->bottom_field_flag = FALSE; } } currSlice->structure = (PictureStructure) p_Vid->structure; currSlice->mb_aff_frame_flag = (active_sps->mb_adaptive_frame_field_flag && (currSlice->field_pic_flag==0)); //currSlice->mb_aff_frame_flag = p_Vid->mb_aff_frame_flag; if (p_Vid->structure == FRAME ) assert (currSlice->field_pic_flag == 0); if (p_Vid->structure == TOP_FIELD ) assert (currSlice->field_pic_flag == 1 && (currSlice->bottom_field_flag == FALSE)); if (p_Vid->structure == BOTTOM_FIELD) assert (currSlice->field_pic_flag == 1 && (currSlice->bottom_field_flag == TRUE )); if (currSlice->idr_flag) { currSlice->idr_pic_id = ue_v("SH: idr_pic_id", currStream); } if (active_sps->pic_order_cnt_type == 0) { currSlice->pic_order_cnt_lsb = u_v(active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4, "SH: pic_order_cnt_lsb", currStream); if( p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 && !currSlice->field_pic_flag ) currSlice->delta_pic_order_cnt_bottom = se_v("SH: delta_pic_order_cnt_bottom", currStream); else currSlice->delta_pic_order_cnt_bottom = 0; } if( active_sps->pic_order_cnt_type == 1) { if ( !active_sps->delta_pic_order_always_zero_flag ) { currSlice->delta_pic_order_cnt[ 0 ] = se_v("SH: delta_pic_order_cnt[0]", currStream); if( p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 && !currSlice->field_pic_flag ) currSlice->delta_pic_order_cnt[ 1 ] = se_v("SH: delta_pic_order_cnt[1]", currStream); else currSlice->delta_pic_order_cnt[ 1 ] = 0; // set to zero if not in stream } else { currSlice->delta_pic_order_cnt[ 0 ] = 0; currSlice->delta_pic_order_cnt[ 1 ] = 0; } } //! redundant_pic_cnt is missing here if (p_Vid->active_pps->redundant_pic_cnt_present_flag) { currSlice->redundant_pic_cnt = ue_v ("SH: redundant_pic_cnt", currStream); } if(currSlice->slice_type == B_SLICE) { currSlice->direct_spatial_mv_pred_flag = u_1 ("SH: direct_spatial_mv_pred_flag", currStream); } currSlice->num_ref_idx_active[LIST_0] = p_Vid->active_pps->num_ref_idx_l0_active_minus1 + 1; currSlice->num_ref_idx_active[LIST_1] = p_Vid->active_pps->num_ref_idx_l1_active_minus1 + 1; if(p_Vid->type==P_SLICE || p_Vid->type == SP_SLICE || p_Vid->type==B_SLICE) { val = u_1 ("SH: num_ref_idx_override_flag", currStream); if (val) { currSlice->num_ref_idx_active[LIST_0] = 1 + ue_v ("SH: num_ref_idx_l0_active_minus1", currStream); if(p_Vid->type==B_SLICE) { currSlice->num_ref_idx_active[LIST_1] = 1 + ue_v ("SH: num_ref_idx_l1_active_minus1", currStream); } } } if (currSlice->slice_type!=B_SLICE) { currSlice->num_ref_idx_active[LIST_1] = 0; } #if (MVC_EXTENSION_ENABLE) if (currSlice->svc_extension_flag == 0 || currSlice->svc_extension_flag == 1) ref_pic_list_mvc_modification(currSlice); else ref_pic_list_reordering(currSlice); #else ref_pic_list_reordering(currSlice); #endif currSlice->weighted_pred_flag = (unsigned short) ((currSlice->slice_type == P_SLICE || currSlice->slice_type == SP_SLICE) ? p_Vid->active_pps->weighted_pred_flag : (currSlice->slice_type == B_SLICE && p_Vid->active_pps->weighted_bipred_idc == 1)); currSlice->weighted_bipred_idc = (unsigned short) (currSlice->slice_type == B_SLICE && p_Vid->active_pps->weighted_bipred_idc > 0); if ((p_Vid->active_pps->weighted_pred_flag&&(p_Vid->type==P_SLICE|| p_Vid->type == SP_SLICE))|| (p_Vid->active_pps->weighted_bipred_idc==1 && (p_Vid->type==B_SLICE))) { pred_weight_table(currSlice); } if (currSlice->nal_reference_idc) dec_ref_pic_marking(p_Vid, currStream, currSlice); if (p_Vid->active_pps->entropy_coding_mode_flag && p_Vid->type!=I_SLICE && p_Vid->type!=SI_SLICE) { currSlice->model_number = ue_v("SH: cabac_init_idc", currStream); } else { currSlice->model_number = 0; } currSlice->slice_qp_delta = val = se_v("SH: slice_qp_delta", currStream); //currSlice->qp = p_Vid->qp = 26 + p_Vid->active_pps->pic_init_qp_minus26 + val; currSlice->qp = 26 + p_Vid->active_pps->pic_init_qp_minus26 + val; if ((currSlice->qp < -p_Vid->bitdepth_luma_qp_scale) || (currSlice->qp > 51)) error ("slice_qp_delta makes slice_qp_y out of range", 500); if(p_Vid->type==SP_SLICE || p_Vid->type == SI_SLICE) { if(p_Vid->type==SP_SLICE) { currSlice->sp_switch = u_1 ("SH: sp_for_switch_flag", currStream); } currSlice->slice_qs_delta = val = se_v("SH: slice_qs_delta", currStream); currSlice->qs = 26 + p_Vid->active_pps->pic_init_qs_minus26 + val; if ((currSlice->qs < 0) || (currSlice->qs > 51)) error ("slice_qs_delta makes slice_qs_y out of range", 500); } if ( !HI_INTRA_ONLY_PROFILE || (HI_INTRA_ONLY_PROFILE && (p_Inp->intra_profile_deblocking == 1) )) //then read flags and parameters from bistream { if (p_Vid->active_pps->deblocking_filter_control_present_flag) { currSlice->DFDisableIdc = (short) ue_v ("SH: disable_deblocking_filter_idc", currStream); if (currSlice->DFDisableIdc!=1) { currSlice->DFAlphaC0Offset = (short) (2 * se_v("SH: slice_alpha_c0_offset_div2", currStream)); currSlice->DFBetaOffset = (short) (2 * se_v("SH: slice_beta_offset_div2", currStream)); } else { currSlice->DFAlphaC0Offset = currSlice->DFBetaOffset = 0; } } else { currSlice->DFDisableIdc = currSlice->DFAlphaC0Offset = currSlice->DFBetaOffset = 0; } } else //By default the Loop Filter is Off { //444_TEMP_NOTE: change made below. 08/07/07 //still need to parse the SEs (read flags and parameters from bistream) but will ignore if (p_Vid->active_pps->deblocking_filter_control_present_flag) { currSlice->DFDisableIdc = (short) ue_v ("SH: disable_deblocking_filter_idc", currStream); if (currSlice->DFDisableIdc!=1) { currSlice->DFAlphaC0Offset = (short) (2 * se_v("SH: slice_alpha_c0_offset_div2", currStream)); currSlice->DFBetaOffset = (short) (2 * se_v("SH: slice_beta_offset_div2", currStream)); } }//444_TEMP_NOTE. the end of change. 08/07/07 //Ignore the SEs, by default the Loop Filter is Off currSlice->DFDisableIdc =1; currSlice->DFAlphaC0Offset = currSlice->DFBetaOffset = 0; } if (p_Vid->active_pps->num_slice_groups_minus1>0 && p_Vid->active_pps->slice_group_map_type>=3 && p_Vid->active_pps->slice_group_map_type<=5) { len = (active_sps->pic_height_in_map_units_minus1+1)*(active_sps->pic_width_in_mbs_minus1+1)/ (p_Vid->active_pps->slice_group_change_rate_minus1+1); if (((active_sps->pic_height_in_map_units_minus1+1)*(active_sps->pic_width_in_mbs_minus1+1))% (p_Vid->active_pps->slice_group_change_rate_minus1+1)) len +=1; len = CeilLog2(len+1); currSlice->slice_group_change_cycle = u_v (len, "SH: slice_group_change_cycle", currStream); } 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; return p_Dec->UsedBits; }
/*! ************************************************************************ * \brief * Interpret the spare picture SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_spare_pic( byte* payload, int size, ImageParameters *img ) { int i,x,y; Bitstream* buf; int bit0, bit1, bitc, no_bit0; int target_frame_num; int num_spare_pics; int delta_spare_frame_num, CandidateSpareFrameNum, SpareFrameNum = 0; int ref_area_indicator; int m, n, left, right, top, bottom,directx, directy; byte ***map; #ifdef WRITE_MAP_IMAGE int j, k, i0, j0, tmp, kk; char filename[20] = "map_dec.yuv"; FILE *fp; byte** Y; static int old_pn=-1; static int first = 1; printf("Spare picture SEI message\n"); #endif UsedBits = 0; assert( payload!=NULL); assert( img!=NULL); #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; target_frame_num = ue_v("SEI: target_frame_num", buf); #ifdef WRITE_MAP_IMAGE printf( "target_frame_num is %d\n", target_frame_num ); #endif num_spare_pics = 1 + ue_v("SEI: num_spare_pics_minus1", buf); #ifdef WRITE_MAP_IMAGE printf( "num_spare_pics is %d\n", num_spare_pics ); #endif get_mem3D(&map, num_spare_pics, img->height/16, img->width/16); for (i=0; i<num_spare_pics; i++) { if (i==0) { CandidateSpareFrameNum = target_frame_num - 1; if ( CandidateSpareFrameNum < 0 ) CandidateSpareFrameNum = MAX_FN - 1; } else CandidateSpareFrameNum = SpareFrameNum; delta_spare_frame_num = ue_v("SEI: delta_spare_frame_num", buf); SpareFrameNum = CandidateSpareFrameNum - delta_spare_frame_num; if( SpareFrameNum < 0 ) SpareFrameNum = MAX_FN + SpareFrameNum; ref_area_indicator = ue_v("SEI: ref_area_indicator", buf); switch ( ref_area_indicator ) { case 0: // The whole frame can serve as spare picture for (y=0; y<img->height/16; y++) for (x=0; x<img->width/16; x++) map[i][y][x] = 0; break; case 1: // The map is not compressed for (y=0; y<img->height/16; y++) for (x=0; x<img->width/16; x++) { map[i][y][x] = u_1("SEI: ref_mb_indicator", buf); } break; case 2: // The map is compressed //!KS: could not check this function, description is unclear (as stated in Ed. Note) bit0 = 0; bit1 = 1; bitc = bit0; no_bit0 = -1; x = ( img->width/16 - 1 ) / 2; y = ( img->height/16 - 1 ) / 2; left = right = x; top = bottom = y; directx = 0; directy = 1; for (m=0; m<img->height/16; m++) for (n=0; n<img->width/16; n++) { if (no_bit0<0) { no_bit0 = ue_v("SEI: zero_run_length", buf); } if (no_bit0>0) map[i][y][x] = bit0; else map[i][y][x] = bit1; no_bit0--; // go to the next mb: if ( directx == -1 && directy == 0 ) { if (x > left) x--; else if (x == 0) { y = bottom + 1; bottom++; directx = 1; directy = 0; } else if (x == left) { x--; left--; directx = 0; directy = 1; } } else if ( directx == 1 && directy == 0 ) { if (x < right) x++; else if (x == img->width/16 - 1) { y = top - 1; top--; directx = -1; directy = 0; } else if (x == right) { x++; right++; directx = 0; directy = -1; } } else if ( directx == 0 && directy == -1 ) { if ( y > top) y--; else if (y == 0) { x = left - 1; left--; directx = 0; directy = 1; } else if (y == top) { y--; top--; directx = -1; directy = 0; } } else if ( directx == 0 && directy == 1 ) { if (y < bottom) y++; else if (y == img->height/16 - 1) { x = right+1; right++; directx = 0; directy = -1; } else if (y == bottom) { y++; bottom++; directx = 1; directy = 0; } } } break; default: printf( "Wrong ref_area_indicator %d!\n", ref_area_indicator ); exit(0); break; } } // end of num_spare_pics #ifdef WRITE_MAP_IMAGE // begin to write map seq if ( old_pn != img->number ) { old_pn = img->number; get_mem2D(&Y, img->height, img->width); if (first) { fp = fopen( filename, "wb" ); first = 0; } else fp = fopen( filename, "ab" ); assert( fp != NULL ); for (kk=0; kk<num_spare_pics; kk++) { for (i=0; i < img->height/16; i++) for (j=0; j < img->width/16; j++) { tmp=map[kk][i][j]==0? 255 : 0; for (i0=0; i0<16; i0++) for (j0=0; j0<16; j0++) Y[i*16+i0][j*16+j0]=tmp; } // write the map image for (i=0; i < img->height; i++) for (j=0; j < img->width; j++) fputc(Y[i][j], fp); for (k=0; k < 2; k++) for (i=0; i < img->height/2; i++) for (j=0; j < img->width/2; j++) fputc(128, fp); } fclose( fp ); free_mem2D( Y ); } // end of writing map image #undef WRITE_MAP_IMAGE #endif free_mem3D( map, num_spare_pics ); free(buf); }
static void pred_weight_table( h264_decoder* dec_params) { Slice *currSlice = dec_params->img->currentSlice; DataPartition *partition = &(currSlice->partArr[0]); Bitstream *currStream = partition->bitstream; int luma_weight_flag_l0, luma_weight_flag_l1, chroma_weight_flag_l0, chroma_weight_flag_l1; int i,j; dec_params->img->luma_log2_weight_denom = ue_v ("SH: luma_log2_weight_denom", currStream,dec_params); dec_params->img->wp_round_luma = dec_params->img->luma_log2_weight_denom ? 1<<(dec_params->img->luma_log2_weight_denom - 1): 0; dec_params->img->chroma_log2_weight_denom = ue_v ("SH: chroma_log2_weight_denom", currStream,dec_params); dec_params->img->wp_round_chroma = dec_params->img->chroma_log2_weight_denom ? 1<<(dec_params->img->chroma_log2_weight_denom - 1): 0; reset_wp_params(dec_params->img); for (i=0; i<dec_params->img->num_ref_idx_l0_active; i++) { luma_weight_flag_l0 = u_1("SH: luma_weight_flag_l0", currStream,dec_params); if (luma_weight_flag_l0) { dec_params->img->apply_weights_luma = 1; dec_params->img->wp_weight[0][i][0] = se_v ("SH: luma_weight_l0", currStream,dec_params); dec_params->img->wp_offset[0][i][0] = se_v ("SH: luma_offset_l0", currStream,dec_params); } else { dec_params->img->wp_weight[0][i][0] = 1<<dec_params->img->luma_log2_weight_denom; dec_params->img->wp_offset[0][i][0] = 0; } //if (dec_params->active_sps->chroma_format_idc != 0) { chroma_weight_flag_l0 = u_1 ("SH: chroma_weight_flag_l0", currStream,dec_params); for (j=1; j<3; j++) { if (chroma_weight_flag_l0) { dec_params->img->wp_weight[0][i][j] = se_v("SH: chroma_weight_l0", currStream,dec_params); dec_params->img->wp_offset[0][i][j] = se_v("SH: chroma_offset_l0", currStream,dec_params); dec_params->img->apply_weights_chr = 1; } else { dec_params->img->wp_weight[0][i][j] = 1<<dec_params->img->chroma_log2_weight_denom; dec_params->img->wp_offset[0][i][j] = 0; } } } } if ((dec_params->img->type == B_SLICE) && dec_params->active_pps->weighted_bipred_idc == 1) { for (i=0; i<dec_params->img->num_ref_idx_l1_active; i++) { luma_weight_flag_l1 = u_1("SH: luma_weight_flag_l1", currStream,dec_params); if (luma_weight_flag_l1) { dec_params->img->wp_weight[1][i][0] = se_v ("SH: luma_weight_l1", currStream,dec_params); dec_params->img->wp_offset[1][i][0] = se_v ("SH: luma_offset_l1", currStream,dec_params); dec_params->img->apply_weights_luma =1; } else { dec_params->img->wp_weight[1][i][0] = 1<<dec_params->img->luma_log2_weight_denom; dec_params->img->wp_offset[1][i][0] = 0; } //if (dec_params->active_sps->chroma_format_idc != 0) { chroma_weight_flag_l1 = u_1 ("SH: chroma_weight_flag_l1", currStream,dec_params); for (j=1; j<3; j++) { if (chroma_weight_flag_l1) { dec_params->img->wp_weight[1][i][j] = se_v("SH: chroma_weight_l1", currStream,dec_params); dec_params->img->wp_offset[1][i][j] = se_v("SH: chroma_offset_l1", currStream,dec_params); dec_params->img->apply_weights_chr = 1; } else { dec_params->img->wp_weight[1][i][j] = 1<<dec_params->img->chroma_log2_weight_denom; dec_params->img->wp_offset[1][i][j] = 0; } } } } } }
//++ 参见标准7.3.2.2、7.4.2.2节 int GeneratePic_parameter_set_rbsp (pic_parameter_set_rbsp_t *pps, char *rbsp) { DataPartition *partition; int len = 0, LenInBytes; unsigned i; unsigned NumberBitsPerSliceGroupId; assert (rbsp != NULL); // In order to use the entropy coding functions from golomb.c we need // to allocate a partition structure. It will be freed later in this // function if ((partition=calloc(1,sizeof(DataPartition)))==NULL) no_mem_exit("PicParameterSet:partition"); if ((partition->bitstream=calloc(1, sizeof(Bitstream)))==NULL) no_mem_exit("PicParameterSet:bitstream"); // .. and use the rbsp provided (or allocated above) for the data partition->bitstream->streamBuffer = rbsp; partition->bitstream->bits_to_go = 8; //sw paff pps->pic_order_present_flag = img->pic_order_present_flag; len+=ue_v ("PPS: pic_parameter_set_id", pps->pic_parameter_set_id, partition); len+=ue_v ("PPS: seq_parameter_set_id", pps->seq_parameter_set_id, partition); len+=u_1 ("PPS: entropy_coding_mode_flag", pps->entropy_coding_mode_flag, partition); len+=u_1 ("PPS: pic_order_present_flag", pps->pic_order_present_flag, partition); len+=ue_v ("PPS: num_slice_groups_minus1", pps->num_slice_groups_minus1, partition); // FMO stuff if(pps->num_slice_groups_minus1 > 0 ) { len+=ue_v ("PPS: slice_group_map_type", pps->slice_group_map_type, partition); if (pps->slice_group_map_type == 0) for (i=0; i<=pps->num_slice_groups_minus1; i++) len+=ue_v ("PPS: run_length_minus1[i]", pps->run_length_minus1[i], partition); else if (pps->slice_group_map_type==2) for (i=0; i<pps->num_slice_groups_minus1; i++) { len+=ue_v ("PPS: top_left[i]", pps->top_left[i], partition); len+=ue_v ("PPS: bottom_right[i]", pps->bottom_right[i], partition); } else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 || pps->slice_group_map_type == 5) { len+=u_1 ("PPS: slice_group_change_direction_flag", pps->slice_group_change_direction_flag, partition); len+=ue_v ("PPS: slice_group_change_rate_minus1", pps->slice_group_change_rate_minus1, partition); } else if (pps->slice_group_map_type == 6) { if (pps->num_slice_groups_minus1>=4) NumberBitsPerSliceGroupId=3; else if (pps->num_slice_groups_minus1>=2) NumberBitsPerSliceGroupId=2; else if (pps->num_slice_groups_minus1>=1) NumberBitsPerSliceGroupId=1; else NumberBitsPerSliceGroupId=0; len+=ue_v ("PPS: pic_size_in_map_units_minus1", pps->pic_size_in_map_units_minus1, partition); for(i=0; i<=pps->pic_size_in_map_units_minus1; i++) len+= u_v (NumberBitsPerSliceGroupId, "PPS: >slice_group_id[i]", pps->slice_group_id[i], partition); } } // End of FMO stuff len+=ue_v ("PPS: num_ref_idx_l0_active_minus1", pps->num_ref_idx_l0_active_minus1, partition); len+=ue_v ("PPS: num_ref_idx_l1_active_minus1", pps->num_ref_idx_l1_active_minus1, partition); len+=u_1 ("PPS: weighted_pred_flag", pps->weighted_pred_flag, partition); len+=u_v (2, "PPS: weighted_bipred_idc", pps->weighted_bipred_idc, partition); len+=se_v ("PPS: pic_init_qp_minus26", pps->pic_init_qp_minus26, partition); len+=se_v ("PPS: pic_init_qs_minus26", pps->pic_init_qs_minus26, partition); len+=se_v ("PPS: chroma_qp_index_offset", pps->chroma_qp_index_offset, partition); len+=u_1 ("PPS: deblocking_filter_control_present_flag", pps->deblocking_filter_control_present_flag, partition); len+=u_1 ("PPS: constrained_intra_pred_flag", pps->constrained_intra_pred_flag, partition); len+=u_1 ("PPS: redundant_pic_cnt_present_flag", pps->redundant_pic_cnt_present_flag, partition); SODBtoRBSP(partition->bitstream); // copies the last couple of bits into the byte buffer LenInBytes=partition->bitstream->byte_pos; // Get rid of the helper structures free (partition->bitstream); free (partition); return LenInBytes; }
/*! ************************************************************************ * \brief * Interpret the Picture timing SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_picture_timing_info( byte* payload, int size, ImageParameters *img ) { int cpb_removal_delay, dpb_output_delay, picture_structure_present_flag, picture_structure; int clock_time_stamp_flag; int ct_type, nuit_field_based_flag, counting_type, full_timestamp_flag, discontinuity_flag, cnt_dropped_flag, nframes; int seconds_value, minutes_value, hours_value, seconds_flag, minutes_flag, hours_flag, time_offset; int NumClockTs = 0; int i; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; assert (NULL!=active_sps); #ifdef PRINT_PCITURE_TIMING_INFO printf("Picture timing SEI message\n"); #endif if ((active_sps->vui_seq_parameters.nal_hrd_parameters_present_flag)|| (active_sps->vui_seq_parameters.vcl_hrd_parameters_present_flag)) { cpb_removal_delay = ue_v("SEI: cpb_removal_delay" , buf); dpb_output_delay = ue_v("SEI: dpb_output_delay" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("cpb_removal_delay = %d\n",cpb_removal_delay); printf("dpb_output_delay = %d\n",dpb_output_delay); #endif } picture_structure_present_flag = u_1("SEI: picture_structure_present_flag" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("picture_structure_present_flag = %d\n",picture_structure_present_flag); #endif if (picture_structure_present_flag) { picture_structure = u_v(3, "SEI: picture_structure" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("picture_structure = %d\n",picture_structure); #endif switch (picture_structure) { case 0: case 1: case 2: NumClockTs = 1; break; case 3: case 4: case 7: NumClockTs = 2; break; case 5: case 6: case 8: NumClockTs = 3; break; default: error("reserved picture_structure used (can't determine NumClockTs)", 500); } for (i=0; i<NumClockTs; i++) { clock_time_stamp_flag = u_1("SEI: clock_time_stamp_flag" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("clock_time_stamp_flag = %d\n",clock_time_stamp_flag); #endif if (clock_time_stamp_flag) { ct_type = u_v(2, "SEI: ct_type" , buf); nuit_field_based_flag = u_1( "SEI: nuit_field_based_flag" , buf); counting_type = u_v(5, "SEI: counting_type" , buf); full_timestamp_flag = u_1( "SEI: full_timestamp_flag" , buf); discontinuity_flag = u_1( "SEI: discontinuity_flag" , buf); cnt_dropped_flag = u_1( "SEI: cnt_dropped_flag" , buf); nframes = u_v(8, "SEI: nframes" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("ct_type = %d\n",ct_type); printf("nuit_field_based_flag = %d\n",nuit_field_based_flag); printf("full_timestamp_flag = %d\n",full_timestamp_flag); printf("discontinuity_flag = %d\n",discontinuity_flag); printf("cnt_dropped_flag = %d\n",cnt_dropped_flag); printf("nframes = %d\n",nframes); #endif if (full_timestamp_flag) { seconds_value = u_v(6, "SEI: seconds_value" , buf); minutes_value = u_v(6, "SEI: minutes_value" , buf); hours_value = u_v(5, "SEI: hours_value" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("seconds_value = %d\n",seconds_value); printf("minutes_value = %d\n",minutes_value); printf("hours_value = %d\n",hours_value); #endif } else { seconds_flag = u_1( "SEI: seconds_flag" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("seconds_flag = %d\n",seconds_flag); #endif if (seconds_flag) { seconds_value = u_v(6, "SEI: seconds_value" , buf); minutes_flag = u_1( "SEI: minutes_flag" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("seconds_value = %d\n",seconds_value); printf("minutes_flag = %d\n",minutes_flag); #endif if(minutes_flag) { minutes_value = u_v(6, "SEI: minutes_value" , buf); hours_flag = u_1( "SEI: hours_flag" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("minutes_value = %d\n",minutes_value); printf("hours_flag = %d\n",hours_flag); #endif if(hours_flag) { hours_value = u_v(5, "SEI: hours_value" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("hours_value = %d\n",hours_value); #endif } } } } if(active_sps->vui_seq_parameters.nal_hrd_parameters.time_offset_length) //!KS which HRD params shall be used? { time_offset=0; // time_offset = i_v(active_sps->vui_seq_parameters.nal_hrd_parameters.time_offset_length, "SEI: time_offset" , buf); #ifdef PRINT_PCITURE_TIMING_INFO printf("time_offset = %d\n",time_offset); #endif } } } } free (buf); #ifdef PRINT_PCITURE_TIMING_INFO #undef PRINT_PCITURE_TIMING_INFO #endif }
void I_Picture_Header(char *buf,int startcodepos, int length) { currStream->frame_bitoffset = currStream->read_len = (startcodepos+1)*8; currStream->code_len = currStream->bitstream_length = length; memcpy (currStream->streamBuffer, buf, length); bbv_delay = u_v(16,"bbv delay"); time_code_flag = u_v(1,"time_code_flag"); if (time_code_flag) time_code =u_v(24,"time_code"); marker_bit =u_v(1,"marker_bit"); picture_distance = u_v(8,"picture_distance"); if(low_delay) { bbv_check_times = ue_v("bbv check times"); } progressive_frame = u_v(1,"progressive_frame"); if (!progressive_frame) { img->picture_structure = u_v(1,"picture_structure"); }else { img->picture_structure = 1; } top_field_first = u_v(1,"top_field_first"); repeat_first_field = u_v(1,"repeat_first_field"); fixed_picture_qp = u_v(1,"fixed_picture_qp"); picture_qp = u_v(6,"picture_qp"); if(progressive_frame==0) { if(img->picture_structure == 0) { skip_mode_flag =u_v(1,"skip mode flag"); } } u_v(4,"reserved bits"); loop_filter_disable = u_v(1,"loop_filter_disable"); if (!loop_filter_disable) { loop_filter_parameter_flag = u_v(1,"loop_filter_parameter_flag"); if (loop_filter_parameter_flag) { alpha_offset = se_v("alpha_offset"); beta_offset = se_v("beta_offset"); } else { alpha_offset = 0; beta_offset = 0; } } img->qp = picture_qp; img->pic_distance = picture_distance; img->type = I_IMG; }
/*! ************************************************************************ * \brief * Reads new slice from bit_stream ************************************************************************ */ int read_new_slice() { NALU_t *nalu = AllocNALU(MAX_CODED_FRAME_SIZE); int current_header; int ret; int BitsUsedByHeader; Slice *currSlice = img->currentSlice; Bitstream *currStream; int newframe; int slice_id_a, slice_id_b, slice_id_c; int redundant_pic_cnt_a, redundant_pic_cnt_b, redundant_pic_cnt_c; long ftell_position, expected_slice_type; // int i; expected_slice_type = NALU_TYPE_DPA; while (1) { ftell_position = ftell(bits); if (input->FileFormat == PAR_OF_ANNEXB) ret=GetAnnexbNALU (nalu); else ret=GetRTPNALU (nalu); NALUtoRBSP(nalu); // printf ("nalu->len %d\n", nalu->len); if (ret < 0) printf ("Error while getting the NALU in file format %s, exit\n", input->FileFormat==PAR_OF_ANNEXB?"Annex B":"RTP"); if (ret == 0) { // printf ("read_new_slice: returning %s\n", "EOS"); if(expected_slice_type != NALU_TYPE_DPA) { /* oops... we found the next slice, go back! */ fseek(bits, ftell_position, SEEK_SET); FreeNALU(nalu); return current_header; } else return EOS; } // Got a NALU if (nalu->forbidden_bit) { printf ("Found NALU w/ forbidden_bit set, bit error? Let's try...\n"); } switch (nalu->nal_unit_type) { case NALU_TYPE_SLICE: case NALU_TYPE_IDR: img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR); img->nal_reference_idc = nalu->nal_reference_idc; img->disposable_flag = (nalu->nal_reference_idc == NALU_PRIORITY_DISPOSABLE); currSlice->dp_mode = PAR_DP_1; currSlice->max_part_nr = 1; currSlice->ei_flag = 0; currStream = 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); // 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 header BitsUsedByHeader = FirstPartOfSliceHeader(); UseParameterSet (currSlice->pic_parameter_set_id); BitsUsedByHeader+= RestOfSliceHeader (); FmoInit (active_pps, active_sps); init_lists(img->type, img->currentSlice->structure); reorder_lists (img->type, img->currentSlice); /* if (img->frame_num==1) // write a reference list { count ++; if (count==1) for (i=0; i<listXsize[0]; i++) write_picture(listX[0][i], p_out2); } */ if (img->MbaffFrameFlag) { init_mbaff_lists(); } if (img->currentSlice->structure!=0) { img->height /=2 ; img->height_cr /=2; } // From here on, active_sps, active_pps and the slice header are valid img->current_mb_nr = currSlice->start_mb_nr; if (img->tr_old != img->ThisPOC) { newframe=1; img->tr_old = img->ThisPOC; } else newframe = 0; if (newframe) current_header = SOP; else current_header = SOS; if(img->structure != img->structure_old) newframe |= 1; img->structure_old = img->structure; //! new stuff StW if(newframe || g_new_frame) { current_header = SOP; g_new_frame=0; } else current_header = SOS; if (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, img->type); } // printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS"); FreeNALU(nalu); return current_header; break; case NALU_TYPE_DPA: //! The state machine here should follow the same ideas as the old readSliceRTP() //! basically: //! work on DPA (as above) //! read and process all following SEI/SPS/PPS/PD/Filler NALUs //! if next video NALU is dpB, //! then read and check whether it belongs to DPA, if yes, use it //! else //! ; // nothing //! read and process all following SEI/SPS/PPS/PD/Filler NALUs //! if next video NALU is dpC //! then read and check whether it belongs to DPA (and DPB, if present), if yes, use it, done //! else //! use the DPA (and the DPB if present) /* LC: inserting the code related to DP processing, mainly copying some of the parts related to NALU_TYPE_SLICE, NALU_TYPE_IDR. */ if(expected_slice_type != NALU_TYPE_DPA) { /* oops... we found the next slice, go back! */ fseek(bits, ftell_position, SEEK_SET); FreeNALU(nalu); return current_header; } img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR); img->nal_reference_idc = nalu->nal_reference_idc; img->disposable_flag = (nalu->nal_reference_idc == NALU_PRIORITY_DISPOSABLE); currSlice->dp_mode = PAR_DP_3; currSlice->max_part_nr = 3; currSlice->ei_flag = 0; currStream = 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); BitsUsedByHeader = FirstPartOfSliceHeader(); UseParameterSet (currSlice->pic_parameter_set_id); BitsUsedByHeader += RestOfSliceHeader (); FmoInit (active_pps, active_sps); init_lists(img->type, img->currentSlice->structure); reorder_lists (img->type, img->currentSlice); if (img->MbaffFrameFlag) { init_mbaff_lists(); } if (img->currentSlice->structure!=0) { img->height /=2 ; img->height_cr /=2; } // From here on, active_sps, active_pps and the slice header are valid img->current_mb_nr = currSlice->start_mb_nr; if (img->tr_old != img->ThisPOC) { newframe=1; img->tr_old = img->ThisPOC; } else newframe = 0; if (newframe) current_header = SOP; else current_header = SOS; if(img->structure != img->structure_old) newframe |= 1; img->structure_old = img->structure; //! new stuff StW if(newframe || g_new_frame) { current_header = SOP; g_new_frame=0; } else current_header = SOS; /* LC: Now I need to read the slice ID, which depends on the value of redundant_pic_cnt_present_flag (pag.49). */ slice_id_a = ue_v("NALU:SLICE_A slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_a = ue_v("NALU:SLICE_A redudand_pic_cnt", currStream); else redundant_pic_cnt_a = 0; if (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, img->type); } // printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS"); break; case NALU_TYPE_DPB: /* LC: inserting the code related to DP processing */ currStream = 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 = ue_v("NALU:SLICE_B slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_b = ue_v("NALU:SLICE_B redudand_pic_cnt", currStream); else redundant_pic_cnt_b = 0; /* LC: Initializing CABAC for the current data stream. */ if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset % 8 != 0) ByteStartPosition++; arideco_start_decoding (&currSlice->partArr[1].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } /* LC: resilience code to be inserted */ /* FreeNALU(nalu); */ /* return current_header; */ break; case NALU_TYPE_DPC: /* LC: inserting the code related to DP processing */ 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); slice_id_c = ue_v("NALU:SLICE_C slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_c = ue_v("NALU:SLICE_C redudand_pic_cnt", currStream); else redundant_pic_cnt_c = 0; /* LC: Initializing CABAC for the current data stream. */ if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset % 8 != 0) ByteStartPosition++; arideco_start_decoding (&currSlice->partArr[2].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } /* LC: resilience code to be inserted */ FreeNALU(nalu); return current_header; break; case NALU_TYPE_SEI: printf ("read_new_slice: Found NALU_TYPE_SEI, len %d\n", nalu->len); InterpretSEIMessage(nalu->buf,nalu->len,img); break; case NALU_TYPE_PPS: ProcessPPS(nalu); break; case NALU_TYPE_SPS: ProcessSPS(nalu); break; case NALU_TYPE_PD: // printf ("read_new_slice: Found 'Access Unit Delimiter' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_EOSEQ: // printf ("read_new_slice: Found 'End of Sequence' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_EOSTREAM: // printf ("read_new_slice: Found 'End of Stream' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_FILL: printf ("read_new_slice: Found NALU_TYPE_FILL, len %d\n", nalu->len); printf ("Skipping these filling bits, proceeding w/ next NALU\n"); break; default: printf ("Found NALU type %d, len %d undefined, ignore NALU, moving on\n", nalu->nal_unit_type, nalu->len); } } FreeNALU(nalu); return current_header; }
//++ 参见标准7.3.2.1、7.4.2.1节 int GenerateSeq_parameter_set_rbsp (seq_parameter_set_rbsp_t *sps, char *rbsp) { DataPartition *partition; int len = 0, LenInBytes; unsigned i; assert (rbsp != NULL); // In order to use the entropy coding functions from golomb.c we need // to allocate a partition structure. It will be freed later in this // function if ((partition=calloc(1,sizeof(DataPartition)))==NULL) no_mem_exit("SeqParameterSet:partition"); if ((partition->bitstream=calloc(1, sizeof(Bitstream)))==NULL) no_mem_exit("SeqParameterSet:bitstream"); // .. and use the rbsp provided (or allocated above) for the data partition->bitstream->streamBuffer = rbsp; partition->bitstream->bits_to_go = 8; len+=u_v (8, "SPS: profile_idc", sps->profile_idc, partition); len+=u_1 ("SPS: constrained_set0_flag", sps->constrained_set0_flag, partition); len+=u_1 ("SPS: constrained_set1_flag", sps->constrained_set1_flag, partition); len+=u_1 ("SPS: constrained_set2_flag", sps->constrained_set2_flag, partition); len+=u_v (5, "SPS: reserved_zero", 0, partition); len+=u_v (8, "SPS: level_idc", sps->level_idc, partition); len+=ue_v ("SPS: seq_parameter_set_id", sps->seq_parameter_set_id, partition); len+=ue_v ("SPS: log2_max_frame_num_minus4", sps->log2_max_frame_num_minus4, partition); len+=ue_v ("SPS: pic_order_cnt_type", sps->pic_order_cnt_type, partition); // POC200301 if (sps->pic_order_cnt_type == 0) len+=ue_v ("SPS: log2_max_pic_order_cnt_lsb_minus4", sps->log2_max_pic_order_cnt_lsb_minus4, partition); else if (sps->pic_order_cnt_type == 1) { len+=u_1 ("SPS: delta_pic_order_always_zero_flag", sps->delta_pic_order_always_zero_flag, partition); len+=se_v ("SPS: offset_for_non_ref_pic", sps->offset_for_non_ref_pic, partition); len+=se_v ("SPS: offset_for_top_to_bottom_field", sps->offset_for_top_to_bottom_field, partition); len+=ue_v ("SPS: num_ref_frames_in_pic_order_cnt_cycle", sps->num_ref_frames_in_pic_order_cnt_cycle, partition); for (i=0; i<sps->num_ref_frames_in_pic_order_cnt_cycle; i++) len+=se_v ("SPS: offset_for_ref_frame", sps->offset_for_ref_frame[i], partition); } len+=ue_v ("SPS: num_ref_frames", sps->num_ref_frames, partition); len+=u_1 ("SPS: gaps_in_frame_num_value_allowed_flag", sps->gaps_in_frame_num_value_allowed_flag, partition); len+=ue_v ("SPS: pic_width_in_mbs_minus1", sps->pic_width_in_mbs_minus1, partition); len+=ue_v ("SPS: pic_height_in_map_units_minus1", sps->pic_height_in_map_units_minus1, partition); len+=u_1 ("SPS: frame_mbs_only_flag", sps->frame_mbs_only_flag, partition); if (!sps->frame_mbs_only_flag) { len+=u_1 ("SPS: mb_adaptive_frame_field_flag", sps->mb_adaptive_frame_field_flag, partition); } len+=u_1 ("SPS: direct_8x8_inference_flag", sps->direct_8x8_inference_flag, partition); len+=u_1 ("SPS: frame_cropping_flag", sps->frame_cropping_flag, partition); if (sps->frame_cropping_flag) { len+=ue_v ("SPS: frame_cropping_rect_left_offset", sps->frame_cropping_rect_left_offset, partition); len+=ue_v ("SPS: frame_cropping_rect_right_offset", sps->frame_cropping_rect_right_offset, partition); len+=ue_v ("SPS: frame_cropping_rect_top_offset", sps->frame_cropping_rect_top_offset, partition); len+=ue_v ("SPS: frame_cropping_rect_bottom_offset", sps->frame_cropping_rect_bottom_offset, partition); } len+=u_1 ("SPS: vui_parameters_present_flag", sps->vui_parameters_present_flag, partition); if (sps->vui_parameters_present_flag) len+=GenerateVUISequenceParameters(); // currently a dummy, asserting SODBtoRBSP(partition->bitstream); // copies the last couple of bits into the byte buffer LenInBytes=partition->bitstream->byte_pos; free (partition->bitstream); free (partition); return LenInBytes; }
/* ************************************************************************* * Function:pb picture header * Input: * Output: * Return: * Attention: ************************************************************************* */ void PB_Picture_Header(char *buf,int startcodepos, int length) { currStream->frame_bitoffset = currStream->read_len = (startcodepos+1)*8; currStream->code_len = currStream->bitstream_length = length; memcpy (currStream->streamBuffer, buf, length); bbv_delay = u_v(16,"bbv delay"); picture_coding_type = u_v(2,"picture_coding_type"); picture_distance = u_v(8,"picture_distance"); if(low_delay) { bbv_check_times = ue_v("bbv check times"); } progressive_frame = u_v(1,"progressive_frame"); if (!progressive_frame) { img->picture_structure = u_v(1,"picture_structure"); if (!img->picture_structure) img->advanced_pred_mode_disable = u_v(1,"advanced_pred_mode_disable"); }else img->picture_structure = 1; top_field_first = u_v(1,"top_field_first"); repeat_first_field = u_v(1,"repeat_first_field"); fixed_picture_qp = u_v(1,"fixed_picture_qp"); picture_qp = u_v(6,"picture_qp"); if (!(picture_coding_type==2 && img->picture_structure==1)) { picture_reference_flag = u_v(1,"picture_reference_flag"); } img->no_forward_reference = u_v(1, "no_forward_reference_flag"); u_v(3,"reserved bits"); skip_mode_flag = u_v(1,"skip_mode_flag"); loop_filter_disable = u_v(1,"loop_filter_disable"); if (!loop_filter_disable) { loop_filter_parameter_flag = u_v(1,"loop_filter_parameter_flag"); if (loop_filter_parameter_flag) { alpha_offset = se_v("alpha_offset"); beta_offset = se_v("beta_offset"); } else // 20071009 { alpha_offset = 0; beta_offset = 0; } } img->qp = picture_qp; if(picture_coding_type==1) { img->type = P_IMG; vec_flag = 0; } else { img->type = B_IMG; } img->pic_distance = picture_distance; }
/*! ************************************************************************ * \brief * read the memory control operations ************************************************************************ */ void dec_ref_pic_marking(VideoParameters *p_Vid, Bitstream *currStream, Slice *pSlice) { int val; DecRefPicMarking_t *tmp_drpm,*tmp_drpm2; // free old buffer content while (pSlice->dec_ref_pic_marking_buffer) { tmp_drpm=pSlice->dec_ref_pic_marking_buffer; pSlice->dec_ref_pic_marking_buffer=tmp_drpm->Next; free (tmp_drpm); } if (pSlice->idr_flag) { pSlice->no_output_of_prior_pics_flag = u_1("SH: no_output_of_prior_pics_flag", currStream); p_Vid->no_output_of_prior_pics_flag = pSlice->no_output_of_prior_pics_flag; pSlice->long_term_reference_flag = u_1("SH: long_term_reference_flag", currStream); } else { pSlice->adaptive_ref_pic_buffering_flag = u_1("SH: adaptive_ref_pic_buffering_flag", currStream); if (pSlice->adaptive_ref_pic_buffering_flag) { // read Memory Management Control Operation do { tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)); tmp_drpm->Next=NULL; val = tmp_drpm->memory_management_control_operation = ue_v("SH: memory_management_control_operation", currStream); if ((val==1)||(val==3)) { tmp_drpm->difference_of_pic_nums_minus1 = ue_v("SH: difference_of_pic_nums_minus1", currStream); } if (val==2) { tmp_drpm->long_term_pic_num = ue_v("SH: long_term_pic_num", currStream); } if ((val==3)||(val==6)) { tmp_drpm->long_term_frame_idx = ue_v("SH: long_term_frame_idx", currStream); } if (val==4) { tmp_drpm->max_long_term_frame_idx_plus1 = ue_v("SH: max_long_term_pic_idx_plus1", currStream); } // add command if (pSlice->dec_ref_pic_marking_buffer==NULL) { pSlice->dec_ref_pic_marking_buffer=tmp_drpm; } else { tmp_drpm2=pSlice->dec_ref_pic_marking_buffer; while (tmp_drpm2->Next!=NULL) tmp_drpm2=tmp_drpm2->Next; tmp_drpm2->Next=tmp_drpm; } } while (val != 0); } } }
/*! ************************************************************************ * \brief * read the weighted prediction tables ************************************************************************ */ static void pred_weight_table(Slice *currSlice) { VideoParameters *p_Vid = currSlice->p_Vid; seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps; byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER]; DataPartition *partition = &(currSlice->partArr[dP_nr]); Bitstream *currStream = partition->bitstream; int luma_weight_flag_l0, luma_weight_flag_l1, chroma_weight_flag_l0, chroma_weight_flag_l1; int i,j; currSlice->luma_log2_weight_denom = (unsigned short) ue_v ("SH: luma_log2_weight_denom", currStream); currSlice->wp_round_luma = currSlice->luma_log2_weight_denom ? 1<<(currSlice->luma_log2_weight_denom - 1): 0; if ( 0 != active_sps->chroma_format_idc) { currSlice->chroma_log2_weight_denom = (unsigned short) ue_v ("SH: chroma_log2_weight_denom", currStream); currSlice->wp_round_chroma = currSlice->chroma_log2_weight_denom ? 1<<(currSlice->chroma_log2_weight_denom - 1): 0; } reset_wp_params(currSlice); for (i=0; i<currSlice->num_ref_idx_active[LIST_0]; i++) { luma_weight_flag_l0 = u_1("SH: luma_weight_flag_l0", currStream); if (luma_weight_flag_l0) { currSlice->wp_weight[0][i][0] = se_v ("SH: luma_weight_l0", currStream); currSlice->wp_offset[0][i][0] = se_v ("SH: luma_offset_l0", currStream); currSlice->wp_offset[0][i][0] = currSlice->wp_offset[0][i][0]<<(p_Vid->bitdepth_luma - 8); } else { currSlice->wp_weight[0][i][0] = 1 << currSlice->luma_log2_weight_denom; currSlice->wp_offset[0][i][0] = 0; } if (active_sps->chroma_format_idc != 0) { chroma_weight_flag_l0 = u_1 ("SH: chroma_weight_flag_l0", currStream); for (j=1; j<3; j++) { if (chroma_weight_flag_l0) { currSlice->wp_weight[0][i][j] = se_v("SH: chroma_weight_l0", currStream); currSlice->wp_offset[0][i][j] = se_v("SH: chroma_offset_l0", currStream); currSlice->wp_offset[0][i][j] = currSlice->wp_offset[0][i][j]<<(p_Vid->bitdepth_chroma-8); } else { currSlice->wp_weight[0][i][j] = 1<<currSlice->chroma_log2_weight_denom; currSlice->wp_offset[0][i][j] = 0; } } } } if ((p_Vid->type == B_SLICE) && p_Vid->active_pps->weighted_bipred_idc == 1) { for (i=0; i<currSlice->num_ref_idx_active[LIST_1]; i++) { luma_weight_flag_l1 = u_1("SH: luma_weight_flag_l1", currStream); if (luma_weight_flag_l1) { currSlice->wp_weight[1][i][0] = se_v ("SH: luma_weight_l1", currStream); currSlice->wp_offset[1][i][0] = se_v ("SH: luma_offset_l1", currStream); currSlice->wp_offset[1][i][0] = currSlice->wp_offset[1][i][0]<<(p_Vid->bitdepth_luma-8); } else { currSlice->wp_weight[1][i][0] = 1<<currSlice->luma_log2_weight_denom; currSlice->wp_offset[1][i][0] = 0; } if (active_sps->chroma_format_idc != 0) { chroma_weight_flag_l1 = u_1 ("SH: chroma_weight_flag_l1", currStream); for (j=1; j<3; j++) { if (chroma_weight_flag_l1) { currSlice->wp_weight[1][i][j] = se_v("SH: chroma_weight_l1", currStream); currSlice->wp_offset[1][i][j] = se_v("SH: chroma_offset_l1", currStream); currSlice->wp_offset[1][i][j] = currSlice->wp_offset[1][i][j]<<(p_Vid->bitdepth_chroma-8); } else { currSlice->wp_weight[1][i][j] = 1<<currSlice->chroma_log2_weight_denom; currSlice->wp_offset[1][i][j] = 0; } } } } } }
/*! ************************************************************************ * \brief * Interpret the Decoded Picture Buffer Management Repetition SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_dec_ref_pic_marking_repetition_info( byte* payload, int size, ImageParameters *img ) { int original_idr_flag, original_frame_num; DecRefPicMarking_t *tmp_drpm; DecRefPicMarking_t *old_drpm; int old_idr_flag , old_no_output_of_prior_pics_flag, old_long_term_reference_flag , old_adaptive_ref_pic_buffering_flag; Bitstream* buf; #ifdef ESLCPP buf = (Bitstream*)malloc(sizeof(Bitstream)); #else buf = malloc(sizeof(Bitstream)); #endif buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; original_idr_flag = u_1 ( "SEI: original_idr_flag" , buf); original_frame_num = ue_v( "SEI: original_frame_num" , buf); #ifdef PRINT_DEC_REF_PIC_MARKING printf("Decoded Picture Buffer Management Repetition SEI message\n"); printf("original_idr_flag = %d\n", original_idr_flag); printf("original_frame_num = %d\n", original_frame_num); #endif // we need to save everything that is probably overwritten in dec_ref_pic_marking() old_drpm = img->dec_ref_pic_marking_buffer; old_idr_flag = img->idr_flag; old_no_output_of_prior_pics_flag = img->no_output_of_prior_pics_flag; old_long_term_reference_flag = img->long_term_reference_flag; old_adaptive_ref_pic_buffering_flag = img->adaptive_ref_pic_buffering_flag; // set new initial values img->idr_flag = original_idr_flag; img->dec_ref_pic_marking_buffer = NULL; dec_ref_pic_marking(buf); // print out decoded values #ifdef PRINT_DEC_REF_PIC_MARKING if (img->idr_flag) { printf("no_output_of_prior_pics_flag = %d\n", img->no_output_of_prior_pics_flag); printf("long_term_reference_flag = %d\n", img->long_term_reference_flag); } else { printf("adaptive_ref_pic_buffering_flag = %d\n", img->adaptive_ref_pic_buffering_flag); if (img->adaptive_ref_pic_buffering_flag) { tmp_drpm=img->dec_ref_pic_marking_buffer; while (tmp_drpm != NULL) { printf("memory_management_control_operation = %d\n", tmp_drpm->memory_management_control_operation); if ((tmp_drpm->memory_management_control_operation==1)||(tmp_drpm->memory_management_control_operation==3)) { printf("difference_of_pic_nums_minus1 = %d\n", tmp_drpm->difference_of_pic_nums_minus1); } if (tmp_drpm->memory_management_control_operation==2) { printf("long_term_pic_num = %d\n", tmp_drpm->long_term_pic_num); } if ((tmp_drpm->memory_management_control_operation==3)||(tmp_drpm->memory_management_control_operation==6)) { printf("long_term_frame_idx = %d\n", tmp_drpm->long_term_frame_idx); } if (tmp_drpm->memory_management_control_operation==4) { printf("max_long_term_pic_idx_plus1 = %d\n", tmp_drpm->max_long_term_frame_idx_plus1); } tmp_drpm = tmp_drpm->Next; } } } #endif while (img->dec_ref_pic_marking_buffer) { tmp_drpm = img->dec_ref_pic_marking_buffer->Next; free (tmp_drpm); } // restore old values in img img->dec_ref_pic_marking_buffer = old_drpm; img->idr_flag = old_idr_flag; img->no_output_of_prior_pics_flag = old_no_output_of_prior_pics_flag; img->long_term_reference_flag = old_long_term_reference_flag; img->adaptive_ref_pic_buffering_flag = old_adaptive_ref_pic_buffering_flag; free (buf); #ifdef PRINT_DEC_REF_PIC_MARKING #undef PRINT_DEC_REF_PIC_MARKING #endif }
/* update video->mb_skip_run */ AVCDec_Status DecodeMB(AVCDecObject *decvid) { AVCDec_Status status; AVCCommonObj *video = decvid->common; AVCDecBitstream *stream = decvid->bitstream; AVCMacroblock *currMB = video->currMB; uint mb_type; int slice_type = video->slice_type; int temp; currMB->QPy = video->QPy; currMB->QPc = video->QPc; if (slice_type == AVC_P_SLICE) { if (video->mb_skip_run < 0) { ue_v(stream, (uint *)&(video->mb_skip_run)); } if (video->mb_skip_run == 0) { /* this will not handle the case where the slice ends with a mb_skip_run == 0 and no following MB data */ ue_v(stream, &mb_type); if (mb_type > 30) { return AVCDEC_FAIL; } InterpretMBModeP(currMB, mb_type); video->mb_skip_run = -1; } else { /* see subclause 7.4.4 for more details on how mb_field_decoding_flag is derived in case of skipped MB */ currMB->mb_intra = FALSE; currMB->mbMode = AVC_SKIP; currMB->MbPartWidth = currMB->MbPartHeight = 16; currMB->NumMbPart = 1; currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] = currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1; // currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] = currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth; currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] = currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight; oscl_memset(currMB->nz_coeff, 0, sizeof(uint8)*NUM_BLKS_IN_MB); currMB->CBP = 0; video->cbp4x4 = 0; /* for skipped MB, always look at the first entry in RefPicList */ currMB->RefIdx[0] = currMB->RefIdx[1] = currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx; InterMBPrediction(video); video->mb_skip_run--; return AVCDEC_SUCCESS; } } else { /* Then decode mode and MV */ ue_v(stream, &mb_type); if (mb_type > 25) { return AVCDEC_FAIL; } InterpretMBModeI(currMB, mb_type); } if (currMB->mbMode != AVC_I_PCM) { if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0) { status = sub_mb_pred(video, currMB, stream); } else { status = mb_pred(video, currMB, stream) ; } if (status != AVCDEC_SUCCESS) { return status; } if (currMB->mbMode != AVC_I16) { /* decode coded_block_pattern */ status = DecodeCBP(currMB, stream); if (status != AVCDEC_SUCCESS) { return status; } } if (currMB->CBP > 0 || currMB->mbMode == AVC_I16) { se_v(stream, &temp); if (temp) { temp += (video->QPy + 52); currMB->QPy = video->QPy = temp - 52 * (temp * 79 >> 12); if (currMB->QPy > 51 || currMB->QPy < 0) { video->QPy = AVC_CLIP3(0, 51, video->QPy); // return AVCDEC_FAIL; } video->QPy_div_6 = (video->QPy * 43) >> 8; video->QPy_mod_6 = video->QPy - 6 * video->QPy_div_6; currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, video->QPy + video->currPicParams->chroma_qp_index_offset)]; video->QPc_div_6 = (video->QPc * 43) >> 8; video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6; } } /* decode residue and inverse transform */ status = residual(decvid, currMB); if (status != AVCDEC_SUCCESS) { return status; } }
static void ref_pic_list_mvc_modification(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 i, val; alloc_ref_pic_list_reordering_buffer(currSlice); if ((p_Vid->type % 5) != I_SLICE && (p_Vid->type % 5) != SI_SLICE) { val = currSlice->ref_pic_list_reordering_flag[LIST_0] = u_1 ("SH: ref_pic_list_modification_flag_l0", currStream); if (val) { i=0; do { val = currSlice->reordering_of_pic_nums_idc[LIST_0][i] = ue_v("SH: modification_of_pic_nums_idc_l0", currStream); if (val==0 || val==1) { currSlice->abs_diff_pic_num_minus1[LIST_0][i] = ue_v("SH: abs_diff_pic_num_minus1_l0", currStream); } else { if (val==2) { currSlice->long_term_pic_idx[LIST_0][i] = ue_v("SH: long_term_pic_idx_l0", currStream); } else if (val==4 || val==5) { currSlice->abs_diff_view_idx_minus1[LIST_0][i] = ue_v("SH: abs_diff_view_idx_minus1_l0", currStream); } } i++; // assert (i>img->num_ref_idx_l0_active); } while (val != 3); } } if ((p_Vid->type % 5) == B_SLICE) { val = currSlice->ref_pic_list_reordering_flag[LIST_1] = u_1 ("SH: ref_pic_list_reordering_flag_l1", currStream); if (val) { i=0; do { val = currSlice->reordering_of_pic_nums_idc[LIST_1][i] = ue_v("SH: modification_of_pic_nums_idc_l1", currStream); if (val==0 || val==1) { currSlice->abs_diff_pic_num_minus1[LIST_1][i] = ue_v("SH: abs_diff_pic_num_minus1_l1", currStream); } else { if (val==2) { currSlice->long_term_pic_idx[LIST_1][i] = ue_v("SH: long_term_pic_idx_l1", currStream); } else if (val==4 || val==5) { currSlice->abs_diff_view_idx_minus1[LIST_1][i] = ue_v("SH: abs_diff_view_idx_minus1_l1", currStream); } } i++; // assert (i>img->num_ref_idx_l1_active); } while (val != 3); } } // set reference index of redundant slices. if(currSlice->redundant_pic_cnt && (p_Vid->type != I_SLICE) ) { currSlice->redundant_slice_ref_idx = currSlice->abs_diff_pic_num_minus1[LIST_0][0] + 1; } }