1/*-------------------------------------------------------------------------- 2Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. 3 4Redistribution and use in source and binary forms, with or without 5modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the name of Code Aurora nor 12 the names of its contributors may be used to endorse or promote 13 products derived from this software without specific prior written 14 permission. 15 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27--------------------------------------------------------------------------*/ 28 29#include "extra_data_handler.h" 30 31extra_data_handler::extra_data_handler() 32{ 33 rbsp_buf = (OMX_U8 *) calloc(1,100); 34 memset(&frame_packing_arrangement,0,sizeof(frame_packing_arrangement)); 35 frame_packing_arrangement.cancel_flag = 1; 36 pack_sei = false; 37 sei_payload_type = -1; 38} 39 40extra_data_handler::~extra_data_handler() 41{ 42 if(rbsp_buf) { 43 free(rbsp_buf); 44 rbsp_buf = NULL; 45 } 46} 47 48OMX_U32 extra_data_handler::d_u(OMX_U32 num_bits) 49{ 50 OMX_U32 rem_bits = num_bits, bins = 0, shift = 0; 51 52 while(rem_bits >= bit_ptr) { 53 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, 54 byte_ptr, rbsp_buf[byte_ptr]); 55 bins <<= shift; 56 shift = (8-bit_ptr); 57 bins |= ((rbsp_buf[byte_ptr] << shift) & 0xFF) >> shift; 58 rem_bits -= bit_ptr; 59 bit_ptr = 8; 60 byte_ptr ++; 61 } 62 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, 63 byte_ptr, rbsp_buf[byte_ptr]); 64 65 if (rem_bits) { 66 bins <<= rem_bits; 67 bins |= ((rbsp_buf[byte_ptr] << (8-bit_ptr)) & 0xFF) >> (8-rem_bits); 68 bit_ptr -= rem_bits; 69 if (bit_ptr == 0) { 70 bit_ptr = 8; 71 byte_ptr++; 72 } 73 } 74 DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, 75 byte_ptr, rbsp_buf[byte_ptr]); 76 77 DEBUG_PRINT_LOW("\nIn %s() bin/num_bits : %x/%d", __func__, bins, num_bits); 78 return bins; 79} 80 81OMX_U32 extra_data_handler::d_ue() 82{ 83 OMX_S32 lead_zeros = -1; 84 OMX_U32 symbol, bit; 85 do{ 86 bit = d_u(1); 87 lead_zeros++; 88 }while (!bit); 89 90 symbol = ((1 << lead_zeros) - 1) + d_u(lead_zeros); 91 92 DEBUG_PRINT_LOW("\nIn %s() symbol : %d", __func__,symbol); 93 return symbol; 94} 95 96OMX_U32 extra_data_handler::parse_frame_pack(OMX_U32 payload_size) 97{ 98 frame_packing_arrangement.id = d_ue(); 99 frame_packing_arrangement.cancel_flag = d_u(1); 100 if(!frame_packing_arrangement.cancel_flag) { 101 frame_packing_arrangement.type = d_u(7); 102 frame_packing_arrangement.quincunx_sampling_flag = d_u(1); 103 frame_packing_arrangement.content_interpretation_type = d_u(6); 104 frame_packing_arrangement.spatial_flipping_flag = d_u(1); 105 frame_packing_arrangement.frame0_flipped_flag = d_u(1); 106 frame_packing_arrangement.field_views_flag = d_u(1); 107 frame_packing_arrangement.current_frame_is_frame0_flag = d_u(1); 108 frame_packing_arrangement.frame0_self_contained_flag = d_u(1); 109 frame_packing_arrangement.frame1_self_contained_flag = d_u(1); 110 111 if(!frame_packing_arrangement.quincunx_sampling_flag && 112 frame_packing_arrangement.type != 5) { 113 frame_packing_arrangement.frame0_grid_position_x = d_u(4); 114 frame_packing_arrangement.frame0_grid_position_y = d_u(4); 115 frame_packing_arrangement.frame1_grid_position_x = d_u(4); 116 frame_packing_arrangement.frame1_grid_position_y = d_u(4); 117 } 118 frame_packing_arrangement.reserved_byte = d_u(8); 119 frame_packing_arrangement.repetition_period = d_ue(); 120 } 121 frame_packing_arrangement.extension_flag = d_u(1); 122 123 return 1; 124} 125 126OMX_S32 extra_data_handler::parse_rbsp(OMX_U8 *buf, OMX_U32 len) 127{ 128 OMX_U32 i = 3, j=0, startcode; 129 OMX_U32 nal_unit_type, nal_ref_idc, forbidden_zero_bit; 130 131 bit_ptr = 8; 132 byte_ptr = 0; 133 134 startcode = buf[0] << 16 | buf[1] <<8 | buf[2]; 135 136 if (!startcode) { 137 startcode |= buf[i++]; 138 } 139 if(startcode != H264_START_CODE) { 140 DEBUG_PRINT_ERROR("\nERROR: In %s() Start code not found", __func__); 141 return -1; 142 } 143 forbidden_zero_bit = (buf[i] & 0x80) >>7; 144 if(forbidden_zero_bit) { 145 DEBUG_PRINT_ERROR("\nERROR: In %s() Non-zero forbidden bit", __func__); 146 return -1; 147 } 148 nal_ref_idc = (buf[i] & 0x60) >>5; 149 DEBUG_PRINT_LOW("\nIn %s() nal_ref_idc ; %d", __func__, nal_ref_idc); 150 151 nal_unit_type = (buf[i++] & 0x1F); 152 153 while(i<len) { 154 if(!(buf[i] + buf[i+1]) && (buf[i+2] == H264_EMULATION_BYTE) && 155 (i+2 < len)) { 156 rbsp_buf[j++] = buf[i++]; 157 rbsp_buf[j++] = buf[i++]; 158 i++; 159 } else 160 rbsp_buf[j++] = buf[i++]; 161 } 162 return nal_unit_type; 163} 164OMX_S32 extra_data_handler::parse_sei(OMX_U8 *buffer, OMX_U32 buffer_length) 165{ 166 OMX_U32 nal_unit_type, payload_type = 0, payload_size = 0; 167 OMX_U32 marker = 0, pad = 0xFF; 168 169 nal_unit_type = parse_rbsp(buffer, buffer_length); 170 171 if (nal_unit_type != NAL_TYPE_SEI) { 172 DEBUG_PRINT_ERROR("\nERROR: In %s() - Non SEI NAL ", __func__); 173 return -1; 174 } else { 175 176 while(rbsp_buf[byte_ptr] == 0xFF) 177 payload_type += rbsp_buf[byte_ptr++]; 178 payload_type += rbsp_buf[byte_ptr++]; 179 180 DEBUG_PRINT_LOW("\nIn %s() payload_type : %u", __func__, payload_type); 181 182 while(rbsp_buf[byte_ptr] == 0xFF) 183 payload_size += rbsp_buf[byte_ptr++]; 184 payload_size += rbsp_buf[byte_ptr++]; 185 186 DEBUG_PRINT_LOW("\nIn %s() payload_size : %u", __func__, payload_size); 187 188 switch(payload_type) { 189 case SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT: 190 DEBUG_PRINT_LOW("\nIn %s() Frame Packing SEI ", __func__); 191 parse_frame_pack(payload_size); 192 break; 193 default: 194 DEBUG_PRINT_LOW("\nINFO: In %s() Not Supported SEI NAL ", __func__); 195 break; 196 } 197 } 198 if(bit_ptr != 8) { 199 marker = d_u(1); 200 if(marker) { 201 if(bit_ptr != 8) { 202 pad = d_u(bit_ptr); 203 if(pad) { 204 DEBUG_PRINT_ERROR("\nERROR: In %s() padding Bits Error in SEI", 205 __func__); 206 return -1; 207 } 208 } 209 } else { 210 DEBUG_PRINT_ERROR("\nERROR: In %s() Marker Bit Error in SEI", 211 __func__); 212 return -1; 213 } 214 } 215 DEBUG_PRINT_LOW("\nIn %s() payload_size : %u/%u", __func__, 216 payload_size, byte_ptr); 217 return 1; 218} 219/*====================================================================== 220 Slice Information will be available as below (each line is of 4 bytes) 221 | number of slices | 222 | 1st slice offset | 223 | 1st slice size | 224 | .. | 225 | Nth slice offset | 226 | Nth slice size | 227======================================================================*/ 228OMX_S32 extra_data_handler::parse_sliceinfo( 229 OMX_BUFFERHEADERTYPE *pBufHdr, OMX_OTHER_EXTRADATATYPE *pExtra) 230{ 231 OMX_U32 slice_offset = 0, slice_size = 0, total_size = 0; 232 OMX_U8 *pBuffer = (OMX_U8 *)pBufHdr->pBuffer; 233 OMX_U32 *data = (OMX_U32 *)pExtra->data; 234 OMX_U32 num_slices = *data; 235 DEBUG_PRINT_HIGH("number of slices = %d", num_slices); 236 if ((4 + num_slices * 8) != (OMX_U32)pExtra->nDataSize) { 237 DEBUG_PRINT_ERROR("unknown error in slice info extradata"); 238 return -1; 239 } 240 for (int i = 0; i < num_slices; i++) { 241 slice_offset = (OMX_U32)(*(data + (i*2 + 1))); 242 if ((*(pBuffer + slice_offset + 0) != 0x00) || 243 (*(pBuffer + slice_offset + 1) != 0x00) || 244 (*(pBuffer + slice_offset + 2) != 0x00) || 245 (*(pBuffer + slice_offset + 3) != H264_START_CODE)) { 246 DEBUG_PRINT_ERROR("found 0x%x instead of start code at offset[%d] " 247 "for slice[%d]", (OMX_U32)(*(OMX_U32 *)(pBuffer + slice_offset)), 248 slice_offset, i); 249 return -1; 250 } 251 if (slice_offset != total_size) { 252 DEBUG_PRINT_ERROR("offset of slice number %d is not correct " 253 "or previous slice size is not correct", i); 254 return -1; 255 } 256 slice_size = (OMX_U32)(*(data + (i*2 + 2))); 257 total_size += slice_size; 258 DEBUG_PRINT_HIGH("slice number %d offset/size = %d/%d", 259 i, slice_offset, slice_size); 260 } 261 if (pBufHdr->nFilledLen != total_size) { 262 DEBUG_PRINT_ERROR("frame_size[%d] is not equal to " 263 "total slices size[%d]", pBufHdr->nFilledLen, total_size); 264 return -1; 265 } 266 return 0; 267} 268 269OMX_U32 extra_data_handler::parse_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr) 270{ 271 OMX_OTHER_EXTRADATATYPE *extra_data = (OMX_OTHER_EXTRADATATYPE *) 272 ((unsigned)(buf_hdr->pBuffer + buf_hdr->nOffset + 273 buf_hdr->nFilledLen + 3)&(~3)); 274 275 DEBUG_PRINT_LOW("\nIn %s() symbol : %u", __func__,buf_hdr->nFlags); 276 277 if (buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) { 278 while(extra_data && (OMX_U8*)extra_data < (buf_hdr->pBuffer + 279 buf_hdr->nAllocLen) && extra_data->eType != VDEC_EXTRADATA_NONE) { 280 DEBUG_PRINT_LOW("\nExtra data type(%x) Extra data size(%u)", 281 extra_data->eType, extra_data->nDataSize); 282 if (extra_data->eType == VDEC_EXTRADATA_SEI) { 283 parse_sei(extra_data->data, extra_data->nDataSize); 284 } 285 else if (extra_data->eType == VEN_EXTRADATA_QCOMFILLER) { 286 DEBUG_PRINT_HIGH("Extradata Qcom Filler found, skip %d bytes", 287 extra_data->nSize); 288 } 289 else if (extra_data->eType == VEN_EXTRADATA_SLICEINFO) { 290 DEBUG_PRINT_HIGH("Extradata SliceInfo of size %d found, " 291 "parsing it", extra_data->nDataSize); 292 parse_sliceinfo(buf_hdr, extra_data); 293 } 294 extra_data = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) extra_data) + 295 extra_data->nSize); 296 } 297 } 298 return 1; 299} 300 301OMX_U32 extra_data_handler::get_frame_pack_data( 302 OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack) 303{ 304 DEBUG_PRINT_LOW("\n%s:%d get frame data", __func__, __LINE__); 305 memcpy(&frame_pack->id,&frame_packing_arrangement.id, 306 FRAME_PACK_SIZE*sizeof(OMX_U32)); 307 return 1; 308} 309 310OMX_U32 extra_data_handler::set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT 311 *frame_pack) 312{ 313 DEBUG_PRINT_LOW("\n%s:%d set frame data", __func__, __LINE__); 314 memcpy(&frame_packing_arrangement.id, &frame_pack->id, 315 FRAME_PACK_SIZE*sizeof(OMX_U32)); 316 pack_sei = true; 317 sei_payload_type = SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT; 318 return 1; 319} 320 321OMX_U32 extra_data_handler::e_u(OMX_U32 symbol, OMX_U32 num_bits) 322{ 323 OMX_U32 rem_bits = num_bits, shift; 324 325 DEBUG_PRINT_LOW("\n%s bin : %x/%d", __func__, symbol, num_bits); 326 327 while(rem_bits >= bit_ptr) { 328 shift = rem_bits - bit_ptr; 329 rbsp_buf[byte_ptr] |= (symbol >> shift); 330 symbol = (symbol << (32 - shift)) >> (32 - shift); 331 rem_bits -= bit_ptr; 332 DEBUG_PRINT_LOW("\n%sstream byte/rem_bits %x/%d", __func__, 333 rbsp_buf[byte_ptr], rem_bits); 334 byte_ptr ++; 335 bit_ptr = 8; 336 } 337 338 if(rem_bits) { 339 shift = bit_ptr - rem_bits; 340 rbsp_buf[byte_ptr] |= (symbol << shift); 341 bit_ptr -= rem_bits; 342 DEBUG_PRINT_LOW("\n%s 2 stream byte/rem_bits %x", __func__, 343 rbsp_buf[byte_ptr], rem_bits); 344 if(bit_ptr == 0) { 345 bit_ptr = 8; 346 byte_ptr++; 347 } 348 } 349 return 1; 350} 351 352OMX_U32 extra_data_handler::e_ue(OMX_U32 symbol) 353{ 354 OMX_U32 i, sym_len, sufix_len, info; 355 OMX_U32 nn =(symbol + 1) >> 1; 356 357 DEBUG_PRINT_LOW("\n%s bin : %x", __func__, symbol); 358 359 for(i=0; i < 33 && nn != 0; i++) 360 nn >>= 1; 361 362 sym_len = ((i << 1) + 1); 363 info = symbol + 1 - (1 << i); 364 sufix_len = (1 << (sym_len >>1)); 365 info = sufix_len | (info & (sufix_len - 1)); 366 e_u(info, sym_len); 367 return 1; 368} 369 370OMX_U32 extra_data_handler::create_frame_pack() 371{ 372 e_ue(frame_packing_arrangement.id); 373 e_u(frame_packing_arrangement.cancel_flag, 1); 374 if(!frame_packing_arrangement.cancel_flag) { 375 e_u(frame_packing_arrangement.type, 7); 376 e_u(frame_packing_arrangement.quincunx_sampling_flag, 1); 377 e_u(frame_packing_arrangement.content_interpretation_type, 6); 378 e_u(frame_packing_arrangement.spatial_flipping_flag, 1); 379 e_u(frame_packing_arrangement.frame0_flipped_flag, 1); 380 e_u(frame_packing_arrangement.field_views_flag, 1); 381 e_u(frame_packing_arrangement.current_frame_is_frame0_flag, 1); 382 e_u(frame_packing_arrangement.frame0_self_contained_flag, 1); 383 e_u(frame_packing_arrangement.frame1_self_contained_flag, 1); 384 if(!frame_packing_arrangement.quincunx_sampling_flag && 385 frame_packing_arrangement.type != 5) { 386 e_u(frame_packing_arrangement.frame0_grid_position_x, 4); 387 e_u(frame_packing_arrangement.frame0_grid_position_y, 4); 388 e_u(frame_packing_arrangement.frame1_grid_position_x, 4); 389 e_u(frame_packing_arrangement.frame1_grid_position_y, 4); 390 } 391 e_u(frame_packing_arrangement.reserved_byte, 8); 392 e_ue(frame_packing_arrangement.repetition_period); 393 } 394 e_u(frame_packing_arrangement.extension_flag, 1); 395 return 1; 396} 397 398OMX_S32 extra_data_handler::create_rbsp(OMX_U8 *buf, OMX_U32 nalu_type) 399{ 400 OMX_U32 i, j = 7; 401 for(i = 0;i < 3;i++) 402 *buf++ = 0x00; 403 *buf++ = H264_START_CODE; 404 *buf++ = nalu_type; 405 *buf++ = (sei_payload_type & 0x000000FF); 406 *buf++ = byte_ptr - 1; //payload will contain 1 byte of rbsp_trailing_bits 407 //that shouldn't be taken into account 408 409 for(i = 0;i < byte_ptr ;i += 2) { 410 *buf++ = rbsp_buf[i]; 411 j++; 412 if(i+1 < byte_ptr) { 413 *buf++ = rbsp_buf[i+1]; 414 j++; 415 if(!(rbsp_buf[i] + rbsp_buf[i+1])) { 416 *buf++ = H264_EMULATION_BYTE; 417 j++; 418 } 419 } 420 } 421 422 DEBUG_PRINT_LOW("\n%s rbsp length %d", __func__, j); 423 return j; 424} 425 426OMX_U32 extra_data_handler::create_sei(OMX_U8 *buffer) 427{ 428 OMX_U32 i, ret_val = 0; 429 430 byte_ptr = 0; 431 bit_ptr = 8; 432 433 if(sei_payload_type == SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT) { 434 create_frame_pack(); 435 436 if(bit_ptr != 8) { 437 e_u(1,1); 438 if(bit_ptr != 8) 439 e_u(0,bit_ptr); 440 } 441 442 //Payload will have been byte aligned by now, 443 //insert the rbsp trailing bits 444 e_u(1, 1); 445 e_u(0, 7); 446 447 ret_val = create_rbsp(buffer, NAL_TYPE_SEI); 448 } 449 450 pack_sei = false; 451 sei_payload_type = -1; 452 453 return ret_val; 454} 455 456OMX_U32 extra_data_handler::create_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr) 457{ 458 OMX_U8 *buffer = (OMX_U8 *) ((unsigned)(buf_hdr->pBuffer + 459 buf_hdr->nOffset + buf_hdr->nFilledLen)); 460 OMX_U32 msg_size; 461 462 DEBUG_PRINT_LOW("\n filled_len/orig_len %d/%d", buf_hdr->nFilledLen, 463 buf_hdr->nAllocLen); 464 465 if(buf_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 466 DEBUG_PRINT_LOW("\n%s:%d create extra data with config", __func__, 467 __LINE__); 468 if(pack_sei) { 469 msg_size = create_sei(buffer); 470 if( msg_size > 0) 471 buf_hdr->nFilledLen += msg_size; 472 } 473 } 474 DEBUG_PRINT_LOW("\n filled_len/orig_len %d/%d", buf_hdr->nFilledLen, 475 buf_hdr->nAllocLen); 476 return 1; 477} 478 479