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