1 #include "viddec_mp4_visualobject.h" 2 3 static inline uint8_t mp4_pvt_isValid_verID(uint8_t id) 4 { 5 uint8_t ret=true; 6 switch(id) 7 { 8 case 1: 9 case 2: 10 case 4: 11 case 5: 12 { 13 break; 14 } 15 default: 16 { 17 ret = false; 18 break; 19 } 20 } 21 return ret; 22 } // mp4_pvt_isValid_verID 23 24 static mp4_Status_t mp4_Parse_video_signal_type(void *parent, mp4_VideoSignalType_t *vidSignal) 25 { 26 uint32_t data=0; 27 int32_t getbits=0; 28 mp4_Status_t ret = MP4_STATUS_PARSE_ERROR; 29 30 /* Set default values defined in spec first */ 31 vidSignal->video_format = 5; 32 vidSignal->video_range = 0; 33 vidSignal->colour_primaries = 1; 34 vidSignal->transfer_characteristics = 1; 35 vidSignal->matrix_coefficients = 1; 36 do 37 { 38 getbits = viddec_pm_get_bits(parent, &data, 1); 39 BREAK_GETBITS_FAIL(getbits, ret); 40 vidSignal->is_video_signal_type = (data > 0); 41 if(vidSignal->is_video_signal_type) 42 { 43 getbits = viddec_pm_get_bits(parent, &data, 5); 44 BREAK_GETBITS_FAIL(getbits, ret); 45 vidSignal->is_colour_description = data & 0x1; 46 vidSignal->video_range = ((data & 0x2) > 0); 47 data = data >> 2; 48 vidSignal->video_format = data & 0x7; 49 if(vidSignal->is_colour_description) 50 { 51 getbits = viddec_pm_get_bits(parent, &data, 24); 52 BREAK_GETBITS_FAIL(getbits, ret); 53 vidSignal->colour_primaries = (data >> 16) & 0xFF; 54 vidSignal->transfer_characteristics = (data >> 8) & 0xFF; 55 vidSignal->matrix_coefficients = data & 0xFF; 56 } 57 } 58 ret = MP4_STATUS_OK; 59 }while(0); 60 61 return ret; 62 } // mp4_Parse_video_signal_type 63 64 void mp4_set_hdr_bitstream_error(viddec_mp4_parser_t *parser, uint8_t hdr_flag, mp4_Status_t parse_status) 65 { 66 //DEB("Entering mp4_set_hdr_bitstream_error: bs_err: 0x%x, hdr: %d, parse_status: %d\n", 67 // parser->bitstream_error, hdr_flag, parse_status); 68 69 if(hdr_flag) 70 { 71 if(parse_status & MP4_STATUS_NOTSUPPORT) 72 parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP; 73 if(parse_status & MP4_STATUS_PARSE_ERROR) 74 parser->bitstream_error |= MP4_BS_ERROR_HDR_PARSE; 75 if(parse_status & MP4_STATUS_REQD_DATA_ERROR) 76 parser->bitstream_error |= MP4_BS_ERROR_HDR_NONDEC; 77 parser->bitstream_error &= MP4_HDR_ERROR_MASK; 78 } 79 else 80 { 81 if(parse_status & MP4_STATUS_NOTSUPPORT) 82 parser->bitstream_error |= MP4_BS_ERROR_FRM_UNSUP; 83 if(parse_status & MP4_STATUS_PARSE_ERROR) 84 parser->bitstream_error |= MP4_BS_ERROR_FRM_PARSE; 85 if(parse_status & MP4_STATUS_REQD_DATA_ERROR) 86 parser->bitstream_error |= MP4_BS_ERROR_FRM_NONDEC; 87 } 88 89 //DEB("Exiting mp4_set_hdr_bitstream_error: bs_err: 0x%x\n", parser->bitstream_error); 90 91 return; 92 } // mp4_set_hdr_bitstream_error 93 94 mp4_Status_t mp4_Parse_VisualSequence(void *parent, viddec_mp4_parser_t *parser) 95 { 96 uint32_t data=0; 97 int32_t getbits=0; 98 mp4_Status_t ret = MP4_STATUS_PARSE_ERROR; 99 100 getbits = viddec_pm_get_bits(parent, &data, 8); 101 if(getbits != -1) 102 { 103 parser->info.profile_and_level_indication = data & 0xFF; 104 // If present, check for validity 105 switch(parser->info.profile_and_level_indication) 106 { 107 case MP4_SIMPLE_PROFILE_LEVEL_0: 108 case MP4_SIMPLE_PROFILE_LEVEL_1: 109 case MP4_SIMPLE_PROFILE_LEVEL_2: 110 case MP4_SIMPLE_PROFILE_LEVEL_3: 111 case MP4_SIMPLE_PROFILE_LEVEL_4a: 112 case MP4_SIMPLE_PROFILE_LEVEL_5: 113 case MP4_SIMPLE_PROFILE_LEVEL_6: 114 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_0: 115 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_1: 116 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_2: 117 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3: 118 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_4: 119 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_5: 120 case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3B: 121 parser->bitstream_error = MP4_BS_ERROR_NONE; 122 ret = MP4_STATUS_OK; 123 break; 124 default: 125 parser->bitstream_error = MP4_BS_ERROR_HDR_UNSUP | MP4_BS_ERROR_HDR_NONDEC; 126 break; 127 } 128 } 129 else 130 { 131 parser->bitstream_error = MP4_BS_ERROR_HDR_PARSE | MP4_BS_ERROR_HDR_NONDEC; 132 } 133 134 return ret; 135 } // mp4_Parse_VisualSequence 136 137 mp4_Status_t mp4_Parse_VisualObject(void *parent, viddec_mp4_parser_t *parser) 138 { 139 mp4_Info_t *pInfo = &(parser->info); 140 mp4_VisualObject_t *visObj = &(pInfo->VisualObject); 141 uint32_t data=0; 142 int32_t getbits=0; 143 mp4_Status_t ret = MP4_STATUS_PARSE_ERROR; 144 145 do 146 { 147 getbits = viddec_pm_get_bits(parent, &data, 1); 148 BREAK_GETBITS_FAIL(getbits, ret); 149 visObj->is_visual_object_identifier = (data > 0); 150 151 visObj->visual_object_verid = 1; /* Default value as per spec */ 152 if (visObj->is_visual_object_identifier) 153 { 154 viddec_pm_get_bits(parent, &data, 7); 155 visObj->visual_object_priority = data & 0x7; 156 data = data >> 3; 157 if(mp4_pvt_isValid_verID(data & 0xF)) 158 { 159 visObj->visual_object_verid = data & 0xF; 160 } 161 else 162 { 163 DEB("Warning: Unsupported visual_object_verid\n"); 164 parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP; 165 // Continue parsing as it is not a required field for decoder 166 } 167 } 168 169 getbits = viddec_pm_get_bits(parent, &data, 4); 170 BREAK_GETBITS_FAIL(getbits, ret); 171 visObj->visual_object_type = data; 172 if (visObj->visual_object_type != MP4_VISUAL_OBJECT_TYPE_VIDEO) 173 { 174 /* VIDEO is the only supported type */ 175 DEB("Error: Unsupported object: visual_object_type != video ID\n"); 176 parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP; 177 break; 178 } 179 180 /* Not required to check for visual_object_type as we already handle it above */ 181 ret = mp4_Parse_video_signal_type(parent, &(visObj->VideoSignalType)); 182 183 // No need to check for user data or visual object layer because they have a different start code 184 // and will not be part of this header 185 186 } while(0); 187 188 mp4_set_hdr_bitstream_error(parser, true, ret); 189 190 // POPULATE WORKLOAD ITEM 191 { 192 viddec_workload_item_t wi; 193 mp4_VideoSignalType_t *vst = &(visObj->VideoSignalType); 194 195 wi.vwi_type = VIDDEC_WORKLOAD_MPEG4_VISUAL_SEQ_OBJ; 196 197 wi.mp4_vs_vo.vs_item = 0; 198 wi.mp4_vs_vo.video_signal_type = 0; 199 wi.mp4_vs_vo.color_desc = 0; 200 201 viddec_fw_mp4_vs_set_profile_and_level_indication(&wi.mp4_vs_vo, pInfo->profile_and_level_indication); 202 203 viddec_fw_mp4_vo_set_video_signal_type(&wi.mp4_vs_vo, vst->is_video_signal_type); 204 if(vst->is_video_signal_type) 205 { 206 viddec_fw_mp4_vo_set_video_range(&wi.mp4_vs_vo, vst->video_range); 207 viddec_fw_mp4_vo_set_video_format(&wi.mp4_vs_vo, vst->video_format); 208 viddec_fw_mp4_vo_set_colour_description(&wi.mp4_vs_vo, vst->is_colour_description); 209 if(vst->is_colour_description) 210 { 211 viddec_fw_mp4_vo_set_transfer_char(&wi.mp4_vs_vo, vst->transfer_characteristics); 212 viddec_fw_mp4_vo_set_color_primaries(&wi.mp4_vs_vo, vst->colour_primaries); 213 } 214 } 215 216 ret = viddec_pm_append_workitem(parent, &wi); 217 if(ret == 1) 218 ret = MP4_STATUS_OK; 219 } 220 221 return ret; 222 } // mp4_Parse_VisualObject 223 224 mp4_Status_t mp4_Parse_UserData(void *parent, viddec_mp4_parser_t *parser) 225 { 226 mp4_Status_t ret = MP4_STATUS_PARSE_ERROR; 227 uint32_t user_data; 228 viddec_workload_item_t wi; 229 230 DEB("ParseUser-prev_sc: 0x%x\n", parser->prev_sc); 231 232 /* find the scope based on start code sc */ 233 switch(parser->prev_sc) { 234 case MP4_SC_VISUAL_OBJECT_SEQUENCE: 235 wi.vwi_type = VIDDEC_WORKLOAD_SEQ_USER_DATA; 236 break; 237 case MP4_SC_VISUAL_OBJECT: 238 wi.vwi_type = VIDDEC_WORKLOAD_VISUAL_OBJ_USER_DATA; 239 break; 240 case MP4_SC_GROUP_OF_VOP: 241 wi.vwi_type = VIDDEC_WORKLOAD_GOP_USER_DATA; 242 break; 243 case MP4_SC_VIDEO_OBJECT_LAYER_MIN: 244 wi.vwi_type = VIDDEC_WORKLOAD_VIDEO_OBJ_USER_DATA; 245 break; 246 default: 247 wi.vwi_type = VIDDEC_WORKLOAD_INVALID; //ERROR - should not happen 248 break; 249 } 250 251 /* Read 1 byte of user data and store it in workitem for the current stream level (VS/VO/VOL/GVOP). 252 Keep adding data payloads till it reaches size 11. When it is 11, the maximum user data payload size, 253 append the workitem. This loop is repeated till all user data is extracted and appended. */ 254 wi.user_data.size = 0; 255 while(viddec_pm_get_bits(parent, &user_data, 8) != -1) 256 { 257 /* Store the valid byte in data payload */ 258 wi.user_data.data_payload[wi.user_data.size] = user_data; 259 wi.user_data.size++; 260 261 /* When size exceeds payload size, append workitem and continue */ 262 if (wi.user_data.size >= 11) 263 { 264 viddec_pm_setup_userdata(&wi); 265 ret = viddec_pm_append_workitem(parent, &wi); 266 wi.user_data.size = 0; 267 } 268 } 269 /* If size is not 0, append remaining user data. */ 270 if (wi.user_data.size > 0) 271 { 272 int i; 273 for(i=wi.user_data.size;i<11;i++) 274 { 275 wi.user_data.data_payload[i] = 0; 276 } 277 viddec_pm_setup_userdata(&wi); 278 ret = viddec_pm_append_workitem(parent, &wi); 279 wi.user_data.size = 0; 280 } 281 282 if(ret == 1) 283 ret = MP4_STATUS_OK; 284 285 return ret; 286 } // mp4_Parse_UserData 287 288