URL
https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk
Subversion Repositories bluespec-h264
[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [sei.c] - Rev 100
Compare with Previous | Blame | View Log
/*! ************************************************************************ * \file sei.c * * \brief * Functions to implement SEI messages * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Dong Tian <tian@cs.tut.fi> * - Karsten Suehring <suehring@hhi.de> ************************************************************************ */ #include "contributors.h" #include <stdlib.h> #include <assert.h> #include <string.h> #include "global.h" #include "memalloc.h" #include "sei.h" #include "vlc.h" #include "header.h" #include "mbuffer.h" #include "parset.h" extern int UsedBits; extern seq_parameter_set_rbsp_t SeqParSet[MAXSPS]; // #define PRINT_BUFFERING_PERIOD_INFO // uncomment to print buffering period SEI info // #define PRINT_PCITURE_TIMING_INFO // uncomment to print picture timing SEI info // #define WRITE_MAP_IMAGE // uncomment to write spare picture map // #define PRINT_SUBSEQUENCE_INFO // uncomment to print sub-sequence SEI info // #define PRINT_SUBSEQUENCE_LAYER_CHAR // uncomment to print sub-sequence layer characteristics SEI info // #define PRINT_SUBSEQUENCE_CHAR // uncomment to print sub-sequence characteristics SEI info // #define PRINT_SCENE_INFORMATION // uncomment to print scene information SEI info // #define PRINT_PAN_SCAN_RECT // uncomment to print pan-scan rectangle SEI info // #define PRINT_RECOVERY_POINT // uncomment to print random access point SEI info // #define PRINT_FILLER_PAYLOAD_INFO // uncomment to print filler payload SEI info // #define PRINT_DEC_REF_PIC_MARKING // uncomment to print decoded picture buffer management repetition SEI info // #define PRINT_RESERVED_INFO // uncomment to print reserved SEI info // #define PRINT_USER_DATA_UNREGISTERED_INFO // uncomment to print unregistered user data SEI info // #define PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO // uncomment to print ITU-T T.35 user data SEI info // #define PRINT_FULL_FRAME_FREEZE_INFO // uncomment to print full-frame freeze SEI info // #define PRINT_FULL_FRAME_FREEZE_RELEASE_INFO // uncomment to print full-frame freeze release SEI info // #define PRINT_FULL_FRAME_SNAPSHOT_INFO // uncomment to print full-frame snapshot SEI info // #define PRINT_PROGRESSIVE_REFINEMENT_END_INFO // uncomment to print Progressive refinement segment start SEI info // #define PRINT_PROGRESSIVE_REFINEMENT_END_INFO // uncomment to print Progressive refinement segment end SEI info // #define PRINT_MOTION_CONST_SLICE_GROUP_SET_INFO // uncomment to print Motion-constrained slice group set SEI info // #define PRINT_FILM_GRAIN_CHARACTERISTICS_INFO // uncomment to print Film grain characteristics SEI info // #define PRINT_DEBLOCKING_FILTER_DISPLAY_PREFERENCE_INFO // uncomment to print deblocking filter display preference SEI info // #define PRINT_STEREO_VIDEO_INFO_INFO // uncomment to print stero video SEI info /*! ************************************************************************ * \brief * Interpret the SEI rbsp * \param msg * a pointer that point to the sei message. * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void InterpretSEIMessage(byte* msg, int size, ImageParameters *img) { int payload_type = 0; int payload_size = 0; int offset = 1; byte tmp_byte; do { // sei_message(); payload_type = 0; tmp_byte = msg[offset++]; while (tmp_byte == 0xFF) { payload_type += 255; tmp_byte = msg[offset++]; } payload_type += tmp_byte; // this is the last byte payload_size = 0; tmp_byte = msg[offset++]; while (tmp_byte == 0xFF) { payload_size += 255; tmp_byte = msg[offset++]; } payload_size += tmp_byte; // this is the last byte switch ( payload_type ) // sei_payload( type, size ); { case SEI_BUFFERING_PERIOD: interpret_buffering_period_info( msg+offset, payload_size, img ); break; case SEI_PIC_TIMING: interpret_picture_timing_info( msg+offset, payload_size, img ); break; case SEI_PAN_SCAN_RECT: interpret_pan_scan_rect_info( msg+offset, payload_size, img ); break; case SEI_FILLER_PAYLOAD: interpret_filler_payload_info( msg+offset, payload_size, img ); break; case SEI_USER_DATA_REGISTERED_ITU_T_T35: interpret_user_data_registered_itu_t_t35_info( msg+offset, payload_size, img ); break; case SEI_USER_DATA_UNREGISTERED: interpret_user_data_unregistered_info( msg+offset, payload_size, img ); break; case SEI_RECOVERY_POINT: interpret_recovery_point_info( msg+offset, payload_size, img ); break; case SEI_DEC_REF_PIC_MARKING_REPETITION: interpret_dec_ref_pic_marking_repetition_info( msg+offset, payload_size, img ); break; case SEI_SPARE_PIC: interpret_spare_pic( msg+offset, payload_size, img ); break; case SEI_SCENE_INFO: interpret_scene_information( msg+offset, payload_size, img ); break; case SEI_SUB_SEQ_INFO: interpret_subsequence_info( msg+offset, payload_size, img ); break; case SEI_SUB_SEQ_LAYER_CHARACTERISTICS: interpret_subsequence_layer_characteristics_info( msg+offset, payload_size, img ); break; case SEI_SUB_SEQ_CHARACTERISTICS: interpret_subsequence_characteristics_info( msg+offset, payload_size, img ); break; case SEI_FULL_FRAME_FREEZE: interpret_full_frame_freeze_info( msg+offset, payload_size, img ); break; case SEI_FULL_FRAME_FREEZE_RELEASE: interpret_full_frame_freeze_release_info( msg+offset, payload_size, img ); break; case SEI_FULL_FRAME_SNAPSHOT: interpret_full_frame_snapshot_info( msg+offset, payload_size, img ); break; case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START: interpret_progressive_refinement_end_info( msg+offset, payload_size, img ); break; case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END: interpret_progressive_refinement_end_info( msg+offset, payload_size, img ); break; case SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET: interpret_motion_constrained_slice_group_set_info( msg+offset, payload_size, img ); case SEI_FILM_GRAIN_CHARACTERISTICS: interpret_film_grain_characteristics_info ( msg+offset, payload_size, img ); break; case SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE: interpret_deblocking_filter_display_preference_info ( msg+offset, payload_size, img ); break; case SEI_STEREO_VIDEO_INFO: interpret_stereo_video_info_info ( msg+offset, payload_size, img ); break; default: interpret_reserved_info( msg+offset, payload_size, img ); break; } offset += payload_size; } while( msg[offset] != 0x80 ); // more_rbsp_data() msg[offset] != 0x80 // ignore the trailing bits rbsp_trailing_bits(); assert(msg[offset] == 0x80); // this is the trailing bits assert( offset+1 == size ); } /*! ************************************************************************ * \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 = 0; 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 symbol_size_in_bytes = img->pic_unit_bitsize_on_disk/8; int j, k, i0, j0, tmp, kk; char filename[20] = "map_dec.yuv"; FILE *fp; imgpel** 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); buf = malloc(sizeof(Bitstream)); 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_mem2Dpel(&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? img->max_imgpel_value : 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++) fwrite(&(Y[i][j]), symbol_size_in_bytes, 1, p_out); for (k=0; k < 2; k++) for (i=0; i < img->height/2; i++) for (j=0; j < img->width/2; j++) fwrite(&(img->dc_pred_value_chroma), symbol_size_in_bytes, 1, p_out); } fclose( fp ); free_mem2Dpel( Y ); } // end of writing map image #undef WRITE_MAP_IMAGE #endif free_mem3D( map, num_spare_pics ); free(buf); } /*! ************************************************************************ * \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; buf = malloc(sizeof(Bitstream)); 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 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 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; buf = malloc(sizeof(Bitstream)); 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 * 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 Filler payload 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_filler_payload_info( byte* payload, int size, ImageParameters *img ) { int payload_cnt = 0; while (payload_cnt<size) { if (payload[payload_cnt] == 0xFF) { payload_cnt++; } } #ifdef PRINT_FILLER_PAYLOAD_INFO printf("Filler payload SEI message\n"); if (payload_cnt==size) { printf("read %d bytes of filler payload\n", payload_cnt); } else { printf("error reading filler payload: not all bytes are 0xFF (%d of %d)\n", payload_cnt, size); } #endif #ifdef PRINT_FILLER_PAYLOAD_INFO #undef PRINT_FILLER_PAYLOAD_INFO #endif } /*! ************************************************************************ * \brief * Interpret the User data unregistered 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_user_data_unregistered_info( byte* payload, int size, ImageParameters *img ) { int offset = 0; byte payload_byte; #ifdef PRINT_USER_DATA_UNREGISTERED_INFO printf("User data unregistered SEI message\n"); printf("uuid_iso_11578 = 0x"); #endif assert (size>=16); for (offset = 0; offset < 16; offset++) { #ifdef PRINT_USER_DATA_UNREGISTERED_INFO printf("%02x",payload[offset]); #endif } #ifdef PRINT_USER_DATA_UNREGISTERED_INFO printf("\n"); #endif while (offset < size) { payload_byte = payload[offset]; offset ++; #ifdef PRINT_USER_DATA_UNREGISTERED_INFO printf("Unreg data payload_byte = %d\n", payload_byte); #endif } #ifdef PRINT_USER_DATA_UNREGISTERED_INFO #undef PRINT_USER_DATA_UNREGISTERED_INFO #endif } /*! ************************************************************************ * \brief * Interpret the User data registered by ITU-T T.35 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_user_data_registered_itu_t_t35_info( byte* payload, int size, ImageParameters *img ) { int offset = 0; byte itu_t_t35_country_code, itu_t_t35_country_code_extension_byte, payload_byte; itu_t_t35_country_code = payload[offset]; offset++; #ifdef PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO printf("User data registered by ITU-T T.35 SEI message\n"); printf(" itu_t_t35_country_code = %d \n", itu_t_t35_country_code); #endif if(itu_t_t35_country_code == 0xFF) { itu_t_t35_country_code_extension_byte = payload[offset]; offset++; #ifdef PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO printf(" ITU_T_T35_COUNTRY_CODE_EXTENSION_BYTE %d \n", itu_t_t35_country_code_extension_byte); #endif } while (offset < size) { payload_byte = payload[offset]; offset ++; #ifdef PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO printf("itu_t_t35 payload_byte = %d\n", payload_byte); #endif } #ifdef PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO #undef PRINT_USER_DATA_REGISTERED_ITU_T_T35_INFO #endif } /*! ************************************************************************ * \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_cancel_flag; int pan_scan_cnt_minus1, i; int pan_scan_rect_repetition_period; 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_cancel_flag = u_1("SEI: pan_scan_rect_cancel_flag", buf); if (!pan_scan_rect_cancel_flag) { pan_scan_cnt_minus1 = ue_v("SEI: pan_scan_cnt_minus1", buf); for (i = 0; i <= pan_scan_cnt_minus1; i++) { 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 %d/%d\n", i, pan_scan_cnt_minus1); 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 } pan_scan_rect_repetition_period = ue_v("SEI: pan_scan_rect_repetition_period", buf); } free (buf); #ifdef PRINT_PAN_SCAN_RECT #undef PRINT_PAN_SCAN_RECT #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_recovery_point_info( byte* payload, int size, ImageParameters *img ) { int recovery_frame_cnt, exact_match_flag, broken_link_flag, changing_slice_group_idc; Bitstream* buf; buf = malloc(sizeof(Bitstream)); 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); img->recovery_point = 1; img->recovery_frame_cnt = recovery_frame_cnt; #ifdef PRINT_RECOVERY_POINT printf("Recovery 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_RECOVERY_POINT #undef PRINT_RECOVERY_POINT #endif } /*! ************************************************************************ * \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; buf = malloc(sizeof(Bitstream)); 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; img->dec_ref_pic_marking_buffer=tmp_drpm->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 } /*! ************************************************************************ * \brief * Interpret the Full-frame freeze 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_freeze_info( byte* payload, int size, ImageParameters *img ) { #ifdef PRINT_FULL_FRAME_FREEZE_INFO printf("Full-frame freeze SEI message\n"); if (size) { printf("payload size of this message should be zero, but is %d bytes.\n", size); } #endif #ifdef PRINT_FULL_FRAME_FREEZE_INFO #undef PRINT_FULL_FRAME_FREEZE_INFO #endif } /*! ************************************************************************ * \brief * Interpret the Full-frame freeze release 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_freeze_release_info( byte* payload, int size, ImageParameters *img ) { #ifdef PRINT_FULL_FRAME_FREEZE_RELEASE_INFO printf("Full-frame freeze release SEI message\n"); if (size) { printf("payload size of this message should be zero, but is %d bytes.\n", size); } #endif #ifdef PRINT_FULL_FRAME_FREEZE_RELEASE_INFO #undef PRINT_FULL_FRAME_FREEZE_RELEASE_INFO #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; buf = malloc(sizeof(Bitstream)); 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 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; 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); 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 * 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 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; int sliceGroupSize; Bitstream* buf; buf = malloc(sizeof(Bitstream)); 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); sliceGroupSize = CeilLog2( num_slice_groups_minus1 + 1 ); #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 = u_v (sliceGroupSize, "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 film grain 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_film_grain_characteristics_info( byte* payload, int size, ImageParameters *img ) { int film_grain_characteristics_cancel_flag; int model_id, separate_colour_description_present_flag; int film_grain_bit_depth_luma_minus8, film_grain_bit_depth_chroma_minus8, film_grain_full_range_flag, film_grain_colour_primaries, film_grain_transfer_characteristics, film_grain_matrix_coefficients; int blending_mode_id, log2_scale_factor, comp_model_present_flag[3]; int num_intensity_intervals_minus1, num_model_values_minus1; int intensity_interval_lower_bound, intensity_interval_upper_bound; int comp_model_value; int film_grain_characteristics_repetition_period; int c, i, j; Bitstream* buf; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; film_grain_characteristics_cancel_flag = u_1("SEI: film_grain_characteristics_cancel_flag", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("film_grain_characteristics_cancel_flag = %d\n", film_grain_characteristics_cancel_flag); #endif if(!film_grain_characteristics_cancel_flag) { model_id = u_v(2, "SEI: model_id", buf); separate_colour_description_present_flag = u_1("SEI: separate_colour_description_present_flag", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("model_id = %d\n", model_id); printf("separate_colour_description_present_flag = %d\n", separate_colour_description_present_flag); #endif if (separate_colour_description_present_flag) { film_grain_bit_depth_luma_minus8 = u_v(3, "SEI: film_grain_bit_depth_luma_minus8", buf); film_grain_bit_depth_chroma_minus8 = u_v(3, "SEI: film_grain_bit_depth_chroma_minus8", buf); film_grain_full_range_flag = u_v(1, "SEI: film_grain_full_range_flag", buf); film_grain_colour_primaries = u_v(8, "SEI: film_grain_colour_primaries", buf); film_grain_transfer_characteristics = u_v(8, "SEI: film_grain_transfer_characteristics", buf); film_grain_matrix_coefficients = u_v(8, "SEI: film_grain_matrix_coefficients", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("film_grain_bit_depth_luma_minus8 = %d\n", film_grain_bit_depth_luma_minus8); printf("film_grain_bit_depth_chroma_minus8 = %d\n", film_grain_bit_depth_chroma_minus8); printf("film_grain_full_range_flag = %d\n", film_grain_full_range_flag); printf("film_grain_colour_primaries = %d\n", film_grain_colour_primaries); printf("film_grain_transfer_characteristics = %d\n", film_grain_transfer_characteristics); printf("film_grain_matrix_coefficients = %d\n", film_grain_matrix_coefficients); #endif } blending_mode_id = u_v(2, "SEI: blending_mode_id", buf); log2_scale_factor = u_v(4, "SEI: log2_scale_factor", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("blending_mode_id = %d\n", blending_mode_id); printf("log2_scale_factor = %d\n", log2_scale_factor); #endif for (c = 0; c < 3; c ++) { comp_model_present_flag[c] = u_1("SEI: comp_model_present_flag", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("comp_model_present_flag = %d\n", comp_model_present_flag[c]); #endif } for (c = 0; c < 3; c ++) if (comp_model_present_flag[c]) { num_intensity_intervals_minus1 = u_v(8, "SEI: num_intensity_intervals_minus1", buf); num_model_values_minus1 = u_v(3, "SEI: num_model_values_minus1", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("num_intensity_intervals_minus1 = %d\n", num_intensity_intervals_minus1); printf("num_model_values_minus1 = %d\n", num_model_values_minus1); #endif for (i = 0; i <= num_intensity_intervals_minus1; i ++) { intensity_interval_lower_bound = u_v(8, "SEI: intensity_interval_lower_bound", buf); intensity_interval_upper_bound = u_v(8, "SEI: intensity_interval_upper_bound", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("intensity_interval_lower_bound = %d\n", intensity_interval_lower_bound); printf("intensity_interval_upper_bound = %d\n", intensity_interval_upper_bound); #endif for (j = 0; j <= num_model_values_minus1; j++) { comp_model_value = se_v("SEI: comp_model_value", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("comp_model_value = %d\n", comp_model_value); #endif } } } film_grain_characteristics_repetition_period = ue_v("SEI: film_grain_characteristics_repetition_period", buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO printf("film_grain_characteristics_repetition_period = %d\n", film_grain_characteristics_repetition_period); #endif } free (buf); #ifdef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO #undef PRINT_FILM_GRAIN_CHARACTERISTICS_INFO #endif } /*! ************************************************************************ * \brief * Interpret the deblocking filter display preference 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_deblocking_filter_display_preference_info( byte* payload, int size, ImageParameters *img ) { int deblocking_display_preference_cancel_flag; int display_prior_to_deblocking_preferred_flag, dec_frame_buffering_constraint_flag, deblocking_display_preference_repetition_period; Bitstream* buf; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; deblocking_display_preference_cancel_flag = u_1("SEI: deblocking_display_preference_cancel_flag", buf); #ifdef PRINT_DEBLOCKING_FILTER_DISPLAY_PREFERENCE_INFO printf("deblocking_display_preference_cancel_flag = %d\n", deblocking_display_preference_cancel_flag); #endif if(!deblocking_display_preference_cancel_flag) { display_prior_to_deblocking_preferred_flag = u_1("SEI: display_prior_to_deblocking_preferred_flag", buf); dec_frame_buffering_constraint_flag = u_1("SEI: dec_frame_buffering_constraint_flag", buf); deblocking_display_preference_repetition_period = ue_v("SEI: deblocking_display_preference_repetition_period", buf); #ifdef PRINT_DEBLOCKING_FILTER_DISPLAY_PREFERENCE_INFO printf("display_prior_to_deblocking_preferred_flag = %d\n", display_prior_to_deblocking_preferred_flag); printf("dec_frame_buffering_constraint_flag = %d\n", dec_frame_buffering_constraint_flag); printf("deblocking_display_preference_repetition_period = %d\n", deblocking_display_preference_repetition_period); #endif } free (buf); #ifdef PRINT_DEBLOCKING_FILTER_DISPLAY_PREFERENCE_INFO #undef PRINT_DEBLOCKING_FILTER_DISPLAY_PREFERENCE_INFO #endif } /*! ************************************************************************ * \brief * Interpret the stereo video info 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_stereo_video_info_info( byte* payload, int size, ImageParameters *img ) { int field_views_flags; int top_field_is_left_view_flag, current_frame_is_left_view_flag, next_frame_is_second_view_flag; int left_view_self_contained_flag; int right_view_self_contained_flag; Bitstream* buf; buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; field_views_flags = u_1("SEI: field_views_flags", buf); #ifdef PRINT_STEREO_VIDEO_INFO_INFO printf("field_views_flags = %d\n", field_views_flags); #endif if (field_views_flags) { top_field_is_left_view_flag = u_1("SEI: top_field_is_left_view_flag", buf); #ifdef PRINT_STEREO_VIDEO_INFO_INFO printf("top_field_is_left_view_flag = %d\n", top_field_is_left_view_flag); #endif } else { current_frame_is_left_view_flag = u_1("SEI: current_frame_is_left_view_flag", buf); next_frame_is_second_view_flag = u_1("SEI: next_frame_is_second_view_flag", buf); #ifdef PRINT_STEREO_VIDEO_INFO_INFO printf("current_frame_is_left_view_flag = %d\n", current_frame_is_left_view_flag); printf("next_frame_is_second_view_flag = %d\n", next_frame_is_second_view_flag); #endif } left_view_self_contained_flag = u_1("SEI: left_view_self_contained_flag", buf); right_view_self_contained_flag = u_1("SEI: right_view_self_contained_flag", buf); #ifdef PRINT_STEREO_VIDEO_INFO_INFO printf("left_view_self_contained_flag = %d\n", left_view_self_contained_flag); printf("right_view_self_contained_flag = %d\n", right_view_self_contained_flag); #endif free (buf); #ifdef PRINT_STEREO_VIDEO_INFO_INFO #undef PRINT_STEREO_VIDEO_INFO_INFO #endif } /*! ************************************************************************ * \brief * Interpret the Reserved 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_reserved_info( byte* payload, int size, ImageParameters *img ) { int offset = 0; byte payload_byte; #ifdef PRINT_RESERVED_INFO printf("Reserved SEI message\n"); #endif while (offset < size) { payload_byte = payload[offset]; offset ++; #ifdef PRINT_RESERVED_INFO printf("reserved_sei_message_payload_byte = %d\n", payload_byte); #endif } #ifdef PRINT_RESERVED_INFO #undef PRINT_RESERVED_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]; activate_sps(sps); #ifdef PRINT_BUFFERING_PERIOD_INFO printf("Buffering period SEI message\n"); printf("seq_parameter_set_id = %d\n", seq_parameter_set_id); #endif // Note: NalHrdBpPresentFlag and CpbDpbDelaysPresentFlag can also be set "by some means not specified in this Recommendation | International Standard" if (sps->vui_parameters_present_flag) { if (sps->vui_seq_parameters.nal_hrd_parameters_present_flag) { for (k=0; k<sps->vui_seq_parameters.nal_hrd_parameters.cpb_cnt_minus1+1; k++) { initial_cpb_removal_delay = u_v(sps->vui_seq_parameters.nal_hrd_parameters.initial_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.initial_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_minus1+1; k++) { initial_cpb_removal_delay = u_v(sps->vui_seq_parameters.vcl_hrd_parameters.initial_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.initial_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 * 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; int cpb_removal_len = 24; int dpb_output_len = 24; Boolean CpbDpbDelaysPresentFlag; Bitstream* buf; if (NULL==active_sps) { fprintf (stderr, "Warning: no active SPS, timing SEI cannot be parsed\n"); return; } buf = malloc(sizeof(Bitstream)); buf->bitstream_length = size; buf->streamBuffer = payload; buf->frame_bitoffset = 0; UsedBits = 0; #ifdef PRINT_PCITURE_TIMING_INFO printf("Picture timing SEI message\n"); #endif // CpbDpbDelaysPresentFlag can also be set "by some means not specified in this Recommendation | International Standard" CpbDpbDelaysPresentFlag = (Boolean) (active_sps->vui_parameters_present_flag && ( (active_sps->vui_seq_parameters.nal_hrd_parameters_present_flag != 0) ||(active_sps->vui_seq_parameters.vcl_hrd_parameters_present_flag != 0))); if (CpbDpbDelaysPresentFlag ) { if (active_sps->vui_parameters_present_flag) { if (active_sps->vui_seq_parameters.nal_hrd_parameters_present_flag) { cpb_removal_len = active_sps->vui_seq_parameters.nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1; dpb_output_len = active_sps->vui_seq_parameters.nal_hrd_parameters.dpb_output_delay_length_minus1 + 1; } else if (active_sps->vui_seq_parameters.vcl_hrd_parameters_present_flag) { cpb_removal_len = active_sps->vui_seq_parameters.vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1; dpb_output_len = active_sps->vui_seq_parameters.vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1; } } if ((active_sps->vui_seq_parameters.nal_hrd_parameters_present_flag)|| (active_sps->vui_seq_parameters.vcl_hrd_parameters_present_flag)) { cpb_removal_delay = u_v(cpb_removal_len, "SEI: cpb_removal_delay" , buf); dpb_output_delay = u_v(dpb_output_len, "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 } } if (!active_sps->vui_parameters_present_flag) { picture_structure_present_flag = 0; } else { picture_structure_present_flag = active_sps->vui_seq_parameters.pic_struct_present_flag; } if (picture_structure_present_flag) { picture_structure = u_v(4, "SEI: pic_struct" , 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 } } } } { int time_offset_length; if (active_sps->vui_seq_parameters.vcl_hrd_parameters_present_flag) time_offset_length = active_sps->vui_seq_parameters.vcl_hrd_parameters.time_offset_length; else if (active_sps->vui_seq_parameters.nal_hrd_parameters_present_flag) time_offset_length = active_sps->vui_seq_parameters.nal_hrd_parameters.time_offset_length; else time_offset_length = 24; if (time_offset_length) time_offset = u_v(time_offset_length, "SEI: time_offset" , buf); // TODO interpretation is unsigned, need signed interpretation (i_v) else time_offset = 0; #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 }