diff options
Diffstat (limited to 'Src/h264dec/ldecod/src/sei.c')
-rw-r--r-- | Src/h264dec/ldecod/src/sei.c | 2132 |
1 files changed, 2132 insertions, 0 deletions
diff --git a/Src/h264dec/ldecod/src/sei.c b/Src/h264dec/ldecod/src/sei.c new file mode 100644 index 00000000..faa4f8ec --- /dev/null +++ b/Src/h264dec/ldecod/src/sei.c @@ -0,0 +1,2132 @@ +/*! + ************************************************************************ + * \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 <math.h> +#include "global.h" +#include "memalloc.h" +#include "sei.h" +#include "vlc.h" +#include "header.h" +#include "mbuffer.h" +#include "parset.h" + + +// #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 +// #define PRINT_TONE_MAPPING // uncomment to print tone-mapping SEI info +// #define PRINT_POST_FILTER_HINT_INFO // uncomment to print post-filter hint 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void InterpretSEIMessage(byte* msg, int size, VideoParameters *p_Vid) +{ + 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, p_Vid ); + break; + case SEI_PIC_TIMING: + interpret_picture_timing_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_PAN_SCAN_RECT: + interpret_pan_scan_rect_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_FILLER_PAYLOAD: + interpret_filler_payload_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_USER_DATA_REGISTERED_ITU_T_T35: + interpret_user_data_registered_itu_t_t35_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_USER_DATA_UNREGISTERED: + interpret_user_data_unregistered_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_RECOVERY_POINT: + interpret_recovery_point_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_DEC_REF_PIC_MARKING_REPETITION: + interpret_dec_ref_pic_marking_repetition_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_SPARE_PIC: + interpret_spare_pic( msg+offset, payload_size, p_Vid ); + break; + case SEI_SCENE_INFO: + interpret_scene_information( msg+offset, payload_size, p_Vid ); + break; + case SEI_SUB_SEQ_INFO: + interpret_subsequence_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_SUB_SEQ_LAYER_CHARACTERISTICS: + interpret_subsequence_layer_characteristics_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_SUB_SEQ_CHARACTERISTICS: + interpret_subsequence_characteristics_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_FULL_FRAME_FREEZE: + interpret_full_frame_freeze_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_FULL_FRAME_FREEZE_RELEASE: + interpret_full_frame_freeze_release_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_FULL_FRAME_SNAPSHOT: + interpret_full_frame_snapshot_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START: + interpret_progressive_refinement_start_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END: + interpret_progressive_refinement_end_info( msg+offset, payload_size, p_Vid ); + break; + case SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET: + interpret_motion_constrained_slice_group_set_info( msg+offset, payload_size, p_Vid ); + case SEI_FILM_GRAIN_CHARACTERISTICS: + interpret_film_grain_characteristics_info ( msg+offset, payload_size, p_Vid ); + break; + case SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE: + interpret_deblocking_filter_display_preference_info ( msg+offset, payload_size, p_Vid ); + break; + case SEI_STEREO_VIDEO_INFO: + interpret_stereo_video_info_info ( msg+offset, payload_size, p_Vid ); + break; + case SEI_TONE_MAPPING: + interpret_tone_mapping( msg+offset, payload_size, p_Vid ); + break; + case SEI_POST_FILTER_HINTS: + interpret_post_filter_hints_info ( msg+offset, payload_size, p_Vid ); + default: + interpret_reserved_info( msg+offset, payload_size, p_Vid ); + 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 p_Vid +* the image pointer +* +************************************************************************ +*/ +void interpret_spare_pic( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 = p_Vid->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 + + + + assert( payload!=NULL); + assert( p_Vid!=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, p_Vid->height >> 4, p_Vid->width >> 4); + + 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<p_Vid->height >> 4; y++) + for (x=0; x<p_Vid->width >> 4; x++) + map[i][y][x] = 0; + break; + case 1: // The map is not compressed + for (y=0; y<p_Vid->height >> 4; y++) + for (x=0; x<p_Vid->width >> 4; x++) + { + map[i][y][x] = (byte) 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 = ( (p_Vid->width >> 4) - 1 ) / 2; + y = ( (p_Vid->height >> 4) - 1 ) / 2; + left = right = x; + top = bottom = y; + directx = 0; + directy = 1; + + for (m=0; m<p_Vid->height >> 4; m++) + for (n=0; n<p_Vid->width >> 4; n++) + { + + if (no_bit0<0) + { + no_bit0 = ue_v("SEI: zero_run_length", buf); + } + if (no_bit0>0) + map[i][y][x] = (byte) bit0; + else + map[i][y][x] = (byte) 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 == (p_Vid->width >> 4) - 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 == (p_Vid->height >> 4) - 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 != p_Vid->number ) + { + old_pn = p_Vid->number; + get_mem2Dpel(&Y, p_Vid->height, p_Vid->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 < p_Vid->height >> 4; i++) + for (j=0; j < p_Vid->width >> 4; j++) + { + tmp=map[kk][i][j]==0? p_Vid->max_pel_value_comp[0] : 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 < p_Vid->height; i++) + for (j=0; j < p_Vid->width; j++) + fwrite(&(Y[i][j]), symbol_size_in_bytes, 1, p_out); + + for (k=0; k < 2; k++) + for (i=0; i < p_Vid->height>>1; i++) + for (j=0; j < p_Vid->width>>1; j++) + fwrite(&(p_Vid->dc_pred_value_comp[1]), 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 ); + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_subsequence_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_subsequence_layer_characteristics_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_subsequence_characteristics_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_scene_information( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_filler_payload_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_user_data_unregistered_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_user_data_registered_itu_t_t35_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_pan_scan_rect_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_recovery_point_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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); + + p_Vid->recovery_point = 1; + p_Vid->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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_dec_ref_pic_marking_repetition_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + int original_idr_flag, original_frame_num; + int original_field_pic_flag, original_bottom_field_flag; + + 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; + + original_idr_flag = u_1 ( "SEI: original_idr_flag" , buf); + original_frame_num = ue_v( "SEI: original_frame_num" , buf); + + if ( !p_Vid->active_sps->frame_mbs_only_flag ) + { + original_field_pic_flag = u_1 ( "SEI: original_field_pic_flag", buf); + if ( original_field_pic_flag ) + { + original_bottom_field_flag = u_1 ( "SEI: original_bottom_field_flag", 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); + if ( active_sps->frame_mbs_only_flag ) + { + printf("original_field_pic_flag = %d\n", original_field_pic_flag); + if ( original_field_pic_flag ) + { + printf("original_bottom_field_flag = %d\n", original_bottom_field_flag); + } + } +#endif + + // we need to save everything that is probably overwritten in dec_ref_pic_marking() + old_drpm = p_Vid->dec_ref_pic_marking_buffer; + old_idr_flag = p_Vid->idr_flag; + + old_no_output_of_prior_pics_flag = p_Vid->no_output_of_prior_pics_flag; + old_long_term_reference_flag = p_Vid->long_term_reference_flag; + old_adaptive_ref_pic_buffering_flag = p_Vid->adaptive_ref_pic_buffering_flag; + + // set new initial values + p_Vid->idr_flag = original_idr_flag; + p_Vid->dec_ref_pic_marking_buffer = NULL; + + dec_ref_pic_marking(p_Vid, buf); + + // print out decoded values +#ifdef PRINT_DEC_REF_PIC_MARKING + if (p_Vid->idr_flag) + { + printf("no_output_of_prior_pics_flag = %d\n", p_Vid->no_output_of_prior_pics_flag); + printf("long_term_reference_flag = %d\n", p_Vid->long_term_reference_flag); + } + else + { + printf("adaptive_ref_pic_buffering_flag = %d\n", p_Vid->adaptive_ref_pic_buffering_flag); + if (p_Vid->adaptive_ref_pic_buffering_flag) + { + tmp_drpm=p_Vid->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 (p_Vid->dec_ref_pic_marking_buffer) + { + tmp_drpm=p_Vid->dec_ref_pic_marking_buffer; + + p_Vid->dec_ref_pic_marking_buffer=tmp_drpm->Next; + free (tmp_drpm); + } + + // restore old values in p_Vid + p_Vid->dec_ref_pic_marking_buffer = old_drpm; + p_Vid->idr_flag = old_idr_flag; + p_Vid->no_output_of_prior_pics_flag = old_no_output_of_prior_pics_flag; + p_Vid->long_term_reference_flag = old_long_term_reference_flag; + p_Vid->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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_full_frame_freeze_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + int full_frame_freeze_repetition_period; + Bitstream* buf; + + buf = malloc(sizeof(Bitstream)); + buf->bitstream_length = size; + buf->streamBuffer = payload; + buf->frame_bitoffset = 0; + + full_frame_freeze_repetition_period = ue_v( "SEI: full_frame_freeze_repetition_period" , buf); + +#ifdef PRINT_FULL_FRAME_FREEZE_INFO + printf("full_frame_freeze_repetition_period = %d\n", full_frame_freeze_repetition_period); +#endif + + free (buf); +#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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_full_frame_freeze_release_info( byte* payload, int size, VideoParameters *p_Vid ) +{ +#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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_full_frame_snapshot_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + int snapshot_id; + + Bitstream* buf; + + buf = malloc(sizeof(Bitstream)); + buf->bitstream_length = size; + buf->streamBuffer = payload; + buf->frame_bitoffset = 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_progressive_refinement_start_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_progressive_refinement_end_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + int progressive_refinement_id; + + Bitstream* buf; + + buf = malloc(sizeof(Bitstream)); + buf->bitstream_length = size; + buf->streamBuffer = payload; + buf->frame_bitoffset = 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_motion_constrained_slice_group_set_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_film_grain_characteristics_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_deblocking_filter_display_preference_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_stereo_video_info_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_reserved_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_buffering_period_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + 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; + + seq_parameter_set_id = ue_v("SEI: seq_parameter_set_id" , buf); + + sps = &p_Vid->SeqParSet[seq_parameter_set_id]; + + activate_sps(p_Vid, 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 p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_picture_timing_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + + seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps; + + 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; + + +#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 = i_v(time_offset_length, "SEI: time_offset" , buf); + 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 +} + +/*! + ************************************************************************ + * \brief + * Interpret the HDR tone-mapping SEI message (JVT-T060) + * \param payload + * a pointer that point to the sei payload + * \param size + * the size of the sei message + * \param p_Vid + * the image pointer + * + ************************************************************************ + */ +typedef struct +{ + unsigned int tone_map_id; + unsigned char tone_map_cancel_flag; + unsigned int tone_map_repetition_period; + unsigned char coded_data_bit_depth; + unsigned char sei_bit_depth; + unsigned int model_id; + // variables for model 0 + int min_value; + int max_value; + // variables for model 1 + int sigmoid_midpoint; + int sigmoid_width; + // variables for model 2 + int start_of_coded_interval[1<<MAX_SEI_BIT_DEPTH]; + // variables for model 3 + int num_pivots; + int coded_pivot_value[MAX_NUM_PIVOTS]; + int sei_pivot_value[MAX_NUM_PIVOTS]; +} tone_mapping_struct_tmp; + +void interpret_tone_mapping( byte* payload, int size, VideoParameters *p_Vid ) +{ + tone_mapping_struct_tmp seiToneMappingTmp; + Bitstream* buf; + int i = 0, max_coded_num, max_output_num; + + memset (&seiToneMappingTmp, 0, sizeof (tone_mapping_struct_tmp)); + + buf = malloc(sizeof(Bitstream)); + buf->bitstream_length = size; + buf->streamBuffer = payload; + buf->frame_bitoffset = 0; + + seiToneMappingTmp.tone_map_id = ue_v("SEI: tone_map_id", buf); + seiToneMappingTmp.tone_map_cancel_flag = (unsigned char) u_1("SEI: tone_map_cancel_flag", buf); + +#ifdef PRINT_TONE_MAPPING + printf("Tone-mapping SEI message\n"); + printf("tone_map_id = %d\n", seiToneMappingTmp.tone_map_id); + + if (seiToneMappingTmp.tone_map_id != 0) + printf("WARNING! Tone_map_id != 0, print the SEI message info only. The tone mapping is actually applied only when Tone_map_id==0\n\n"); + printf("tone_map_cancel_flag = %d\n", seiToneMappingTmp.tone_map_cancel_flag); +#endif + + if (!seiToneMappingTmp.tone_map_cancel_flag) + { + seiToneMappingTmp.tone_map_repetition_period = ue_v( "SEI: tone_map_repetition_period", buf); + seiToneMappingTmp.coded_data_bit_depth = (unsigned char)u_v (8,"SEI: coded_data_bit_depth" , buf); + seiToneMappingTmp.sei_bit_depth = (unsigned char)u_v (8,"SEI: sei_bit_depth" , buf); + + seiToneMappingTmp.model_id = ue_v( "SEI: model_id" , buf); + +#ifdef PRINT_TONE_MAPPING + printf("tone_map_repetition_period = %d\n", seiToneMappingTmp.tone_map_repetition_period); + printf("coded_data_bit_depth = %d\n", seiToneMappingTmp.coded_data_bit_depth); + printf("sei_bit_depth = %d\n", seiToneMappingTmp.sei_bit_depth); + printf("model_id = %d\n", seiToneMappingTmp.model_id); +#endif + + max_coded_num = 1<<seiToneMappingTmp.coded_data_bit_depth; + max_output_num = 1<<seiToneMappingTmp.sei_bit_depth; + + if (seiToneMappingTmp.model_id == 0) + { // linear mapping with clipping + seiToneMappingTmp.min_value = u_v (32,"SEI: min_value", buf); + seiToneMappingTmp.max_value = u_v (32,"SEI: min_value", buf); +#ifdef PRINT_TONE_MAPPING + printf("min_value = %d, max_value = %d\n", seiToneMappingTmp.min_value, seiToneMappingTmp.max_value); +#endif + } + else if (seiToneMappingTmp.model_id == 1) + { // sigmoidal mapping + seiToneMappingTmp.sigmoid_midpoint = u_v (32,"SEI: sigmoid_midpoint", buf); + seiToneMappingTmp.sigmoid_width = u_v (32,"SEI: sigmoid_width", buf); +#ifdef PRINT_TONE_MAPPING + printf("sigmoid_midpoint = %d, sigmoid_width = %d\n", seiToneMappingTmp.sigmoid_midpoint, seiToneMappingTmp.sigmoid_width); +#endif + } + else if (seiToneMappingTmp.model_id == 2) + { // user defined table mapping + for (i=0; i<max_output_num; i++) + { + seiToneMappingTmp.start_of_coded_interval[i] = u_v((((seiToneMappingTmp.coded_data_bit_depth+7)>>3)<<3), "SEI: start_of_coded_interval" , buf); +#ifdef PRINT_TONE_MAPPING // too long to print + //printf("start_of_coded_interval[%d] = %d\n", i, seiToneMappingTmp.start_of_coded_interval[i]); +#endif + } + } + else if (seiToneMappingTmp.model_id == 3) + { // piece-wise linear mapping + seiToneMappingTmp.num_pivots = u_v (16,"SEI: num_pivots", buf); +#ifdef PRINT_TONE_MAPPING + printf("num_pivots = %d\n", seiToneMappingTmp.num_pivots); +#endif + seiToneMappingTmp.coded_pivot_value[0] = 0; + seiToneMappingTmp.sei_pivot_value[0] = 0; + seiToneMappingTmp.coded_pivot_value[seiToneMappingTmp.num_pivots+1] = max_coded_num-1; + seiToneMappingTmp.sei_pivot_value[seiToneMappingTmp.num_pivots+1] = max_output_num-1; + + for (i=1; i < seiToneMappingTmp.num_pivots+1; i++) + { + seiToneMappingTmp.coded_pivot_value[i] = u_v( (((seiToneMappingTmp.coded_data_bit_depth+7)>>3)<<3), "SEI: coded_pivot_value", buf); + seiToneMappingTmp.sei_pivot_value[i] = u_v( (((seiToneMappingTmp.sei_bit_depth+7)>>3)<<3), "SEI: sei_pivot_value", buf); +#ifdef PRINT_TONE_MAPPING + printf("coded_pivot_value[%d] = %d, sei_pivot_value[%d] = %d\n", i, seiToneMappingTmp.coded_pivot_value[i], i, seiToneMappingTmp.sei_pivot_value[i]); +#endif + } + } + +#if (ENABLE_OUTPUT_TONEMAPPING) + // Currently, only when the map_id == 0, the tone-mapping is actually applied. + if (seiToneMappingTmp.tone_map_id== 0) + { + int j; + p_Vid->seiToneMapping->seiHasTone_mapping = TRUE; + p_Vid->seiToneMapping->tone_map_repetition_period = seiToneMappingTmp.tone_map_repetition_period; + p_Vid->seiToneMapping->coded_data_bit_depth = seiToneMappingTmp.coded_data_bit_depth; + p_Vid->seiToneMapping->sei_bit_depth = seiToneMappingTmp.sei_bit_depth; + p_Vid->seiToneMapping->model_id = seiToneMappingTmp.model_id; + p_Vid->seiToneMapping->count = 0; + + // generate the look up table of tone mapping + switch(seiToneMappingTmp.model_id) + { + case 0: // linear mapping with clipping + for (i=0; i<=seiToneMappingTmp.min_value; i++) + p_Vid->seiToneMapping->lut[i] = 0; + + for (i=seiToneMappingTmp.min_value+1; i < seiToneMappingTmp.max_value; i++) + p_Vid->seiToneMapping->lut[i] = (imgpel) ((i-seiToneMappingTmp.min_value) * (max_output_num-1)/(seiToneMappingTmp.max_value- seiToneMappingTmp.min_value)); + + for (i=seiToneMappingTmp.max_value; i<max_coded_num; i++) + p_Vid->seiToneMapping->lut[i] =(imgpel) (max_output_num - 1); + break; + case 1: // sigmoid mapping + + for (i=0; i < max_coded_num; i++) + { +#if 0 + int j = (int)(1 + exp( -6*(double)(i-seiToneMappingTmp.sigmoid_midpoint)/seiToneMappingTmp.sigmoid_width)); + p_Vid->seiToneMapping->lut[i] = ((max_output_num-1)+(j>>1)) / j; +#else + double tmp = 1.0 + exp( -6*(double)(i-seiToneMappingTmp.sigmoid_midpoint)/seiToneMappingTmp.sigmoid_width); + p_Vid->seiToneMapping->lut[i] = (imgpel)( (double)(max_output_num-1)/ tmp + 0.5); +#endif + } + break; + case 2: // user defined table + if (0 < max_output_num-1) + { + for (j=0; j<max_output_num-1; j++) + { + for (i=seiToneMappingTmp.start_of_coded_interval[j]; i<seiToneMappingTmp.start_of_coded_interval[j+1]; i++) + { + p_Vid->seiToneMapping->lut[i] = (imgpel) j; + } + } + p_Vid->seiToneMapping->lut[i] = (imgpel) (max_output_num - 1); + } + break; + case 3: // piecewise linear mapping + for (j=0; j<seiToneMappingTmp.num_pivots+1; j++) + { +#if 0 + slope = ((seiToneMappingTmp.sei_pivot_value[j+1] - seiToneMappingTmp.sei_pivot_value[j])<<16)/(seiToneMappingTmp.coded_pivot_value[j+1]-seiToneMappingTmp.coded_pivot_value[j]); + for (i=seiToneMappingTmp.coded_pivot_value[j]; i <= seiToneMappingTmp.coded_pivot_value[j+1]; i++) + { + p_Vid->seiToneMapping->lut[i] = seiToneMappingTmp.sei_pivot_value[j] + (( (i - seiToneMappingTmp.coded_pivot_value[j]) * slope)>>16); + } +#else + double slope = (double)(seiToneMappingTmp.sei_pivot_value[j+1] - seiToneMappingTmp.sei_pivot_value[j])/(seiToneMappingTmp.coded_pivot_value[j+1]-seiToneMappingTmp.coded_pivot_value[j]); + for (i=seiToneMappingTmp.coded_pivot_value[j]; i <= seiToneMappingTmp.coded_pivot_value[j+1]; i++) + { + p_Vid->seiToneMapping->lut[i] = (imgpel) (seiToneMappingTmp.sei_pivot_value[j] + (int)(( (i - seiToneMappingTmp.coded_pivot_value[j]) * slope))); + } +#endif + } + break; + + default: + break; + } // end switch + } +#endif + } // end !tone_map_cancel_flag + free (buf); +} + +#if (ENABLE_OUTPUT_TONEMAPPING) +// tone map using the look-up-table generated according to SEI tone mapping message +void tone_map (imgpel** imgX, imgpel* lut, int size_x, int size_y) +{ + int i, j; + + for(i=0;i<size_y;i++) + { + for(j=0;j<size_x;j++) + { + imgX[i][j] = (imgpel)lut[imgX[i][j]]; + } + } +} + +void init_tone_mapping_sei(ToneMappingSEI *seiToneMapping) +{ + seiToneMapping->seiHasTone_mapping = FALSE; + seiToneMapping->count = 0; +} + +void update_tone_mapping_sei(ToneMappingSEI *seiToneMapping) +{ + + if(seiToneMapping->tone_map_repetition_period == 0) + { + seiToneMapping->seiHasTone_mapping = FALSE; + seiToneMapping->count = 0; + } + else if (seiToneMapping->tone_map_repetition_period>1) + { + seiToneMapping->count++; + if (seiToneMapping->count>=seiToneMapping->tone_map_repetition_period) + { + seiToneMapping->seiHasTone_mapping = FALSE; + seiToneMapping->count = 0; + } + } +} +#endif + +/*! + ************************************************************************ + * \brief + * Interpret the post filter hints SEI message (JVT-U035) + * \param payload + * a pointer that point to the sei payload + * \param size + * the size of the sei message + * \param p_Vid + * the image pointer + * + ************************************************************************ + */ +void interpret_post_filter_hints_info( byte* payload, int size, VideoParameters *p_Vid ) +{ + Bitstream* buf; + unsigned int filter_hint_size_y, filter_hint_size_x, filter_hint_type, color_component, cx, cy, additional_extension_flag; + int ***filter_hint; + + buf = malloc(sizeof(Bitstream)); + buf->bitstream_length = size; + buf->streamBuffer = payload; + buf->frame_bitoffset = 0; + + filter_hint_size_y = ue_v("SEI: filter_hint_size_y", buf); // interpret post-filter hint SEI here + filter_hint_size_x = ue_v("SEI: filter_hint_size_x", buf); // interpret post-filter hint SEI here + filter_hint_type = u_v(2, "SEI: filter_hint_type", buf); // interpret post-filter hint SEI here + + get_mem3Dint (&filter_hint, 3, filter_hint_size_y, filter_hint_size_x); + + for (color_component = 0; color_component < 3; color_component ++) + for (cy = 0; cy < filter_hint_size_y; cy ++) + for (cx = 0; cx < filter_hint_size_x; cx ++) + filter_hint[color_component][cy][cx] = se_v("SEI: filter_hint", buf); // interpret post-filter hint SEI here + + additional_extension_flag = u_1("SEI: additional_extension_flag", buf); // interpret post-filter hint SEI here + +#ifdef PRINT_POST_FILTER_HINT_INFO + printf(" Post-filter hint SEI message\n"); + printf(" post_filter_hint_size_y %d \n", filter_hint_size_y); + printf(" post_filter_hint_size_x %d \n", filter_hint_size_x); + printf(" post_filter_hint_type %d \n", filter_hint_type); + for (color_component = 0; color_component < 3; color_component ++) + for (cy = 0; cy < filter_hint_size_y; cy ++) + for (cx = 0; cx < filter_hint_size_x; cx ++) + printf(" post_filter_hint[%d][%d][%d] %d \n", color_component, cy, cx, filter_hint[color_component][cy][cx]); + + printf(" additional_extension_flag %d \n", additional_extension_flag); + +#undef PRINT_POST_FILTER_HINT_INFO +#endif + + free_mem3Dint (filter_hint); + free( buf ); +} |