Home | History | Annotate | Download | only in src
      1 /*--------------------------------------------------------------------------
      2 Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, 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 
     16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 --------------------------------------------------------------------------*/
     28 
     29 #include "extra_data_handler.h"
     30 
     31 extra_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 
     40 extra_data_handler::~extra_data_handler()
     41 {
     42   if(rbsp_buf) {
     43     free(rbsp_buf);
     44     rbsp_buf = NULL;
     45   }
     46 }
     47 
     48 OMX_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 
     81 OMX_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 
     96 OMX_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 
    126 OMX_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 }
    164 OMX_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 ======================================================================*/
    228 OMX_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 
    269 OMX_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 
    301 OMX_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 
    310 OMX_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 
    321 OMX_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 
    352 OMX_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 
    370 OMX_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 
    398 OMX_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 
    426 OMX_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 
    456 OMX_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