blob: b9ebc9dcadec59f7de5f219eea62fb5a9ebc2092 [file] [log] [blame]
Shalaj Jain273b3e02012-06-22 19:08:03 -07001/*--------------------------------------------------------------------------
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}
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530219
220OMX_S32 extra_data_handler::parse_ltrinfo(
221 OMX_BUFFERHEADERTYPE *pBufHdr, OMX_OTHER_EXTRADATATYPE *pExtra)
222{
223 OMX_U32 *pLTR;
224 pExtra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoLTRInfo;
225 pLTR = (OMX_U32* )pExtra + 5;
226 DEBUG_PRINT_HIGH("ExtraData LTR ID %d", *pLTR, 0, 0);
227 return 0;
228}
Shalaj Jain273b3e02012-06-22 19:08:03 -0700229/*======================================================================
230 Slice Information will be available as below (each line is of 4 bytes)
231 | number of slices |
232 | 1st slice offset |
233 | 1st slice size |
234 | .. |
235 | Nth slice offset |
236 | Nth slice size |
237======================================================================*/
238OMX_S32 extra_data_handler::parse_sliceinfo(
239 OMX_BUFFERHEADERTYPE *pBufHdr, OMX_OTHER_EXTRADATATYPE *pExtra)
240{
241 OMX_U32 slice_offset = 0, slice_size = 0, total_size = 0;
242 OMX_U8 *pBuffer = (OMX_U8 *)pBufHdr->pBuffer;
243 OMX_U32 *data = (OMX_U32 *)pExtra->data;
244 OMX_U32 num_slices = *data;
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530245 DEBUG_PRINT_LOW("number of slices = %d", num_slices);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700246 if ((4 + num_slices * 8) != (OMX_U32)pExtra->nDataSize) {
247 DEBUG_PRINT_ERROR("unknown error in slice info extradata");
248 return -1;
249 }
250 for (int i = 0; i < num_slices; i++) {
251 slice_offset = (OMX_U32)(*(data + (i*2 + 1)));
252 if ((*(pBuffer + slice_offset + 0) != 0x00) ||
253 (*(pBuffer + slice_offset + 1) != 0x00) ||
254 (*(pBuffer + slice_offset + 2) != 0x00) ||
255 (*(pBuffer + slice_offset + 3) != H264_START_CODE)) {
256 DEBUG_PRINT_ERROR("found 0x%x instead of start code at offset[%d] "
257 "for slice[%d]", (OMX_U32)(*(OMX_U32 *)(pBuffer + slice_offset)),
258 slice_offset, i);
259 return -1;
260 }
261 if (slice_offset != total_size) {
262 DEBUG_PRINT_ERROR("offset of slice number %d is not correct "
263 "or previous slice size is not correct", i);
264 return -1;
265 }
266 slice_size = (OMX_U32)(*(data + (i*2 + 2)));
267 total_size += slice_size;
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530268 DEBUG_PRINT_LOW("slice number %d offset/size = %d/%d",
Shalaj Jain273b3e02012-06-22 19:08:03 -0700269 i, slice_offset, slice_size);
270 }
271 if (pBufHdr->nFilledLen != total_size) {
272 DEBUG_PRINT_ERROR("frame_size[%d] is not equal to "
273 "total slices size[%d]", pBufHdr->nFilledLen, total_size);
274 return -1;
275 }
276 return 0;
277}
278
279OMX_U32 extra_data_handler::parse_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr)
280{
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530281 DEBUG_PRINT_LOW("In %s() flags: 0x%x", __func__,buf_hdr->nFlags);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700282
283 if (buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530284
285 OMX_OTHER_EXTRADATATYPE *extra_data = (OMX_OTHER_EXTRADATATYPE *)
286 ((unsigned)(buf_hdr->pBuffer + buf_hdr->nOffset +
287 buf_hdr->nFilledLen + 3)&(~3));
288
289 while(extra_data &&
290 ((OMX_U32)extra_data > (OMX_U32)buf_hdr->pBuffer) &&
291 ((OMX_U32)extra_data < (OMX_U32)buf_hdr->pBuffer + buf_hdr->nAllocLen)) {
292
293 DEBUG_PRINT_LOW("extradata(0x%x): nSize = 0x%x, eType = 0x%x,"
294 " nDataSize = 0x%x", (unsigned)extra_data, extra_data->nSize,
295 extra_data->eType, extra_data->nDataSize);
296
297 if ((extra_data->eType == VDEC_EXTRADATA_NONE) ||
298 (extra_data->eType == VEN_EXTRADATA_NONE)) {
299 DEBUG_PRINT_LOW("No more extradata available");
300 extra_data->eType = OMX_ExtraDataNone;
301 break;
302 }
303 else if (extra_data->eType == VDEC_EXTRADATA_SEI) {
304 DEBUG_PRINT_LOW("Extradata SEI of size %d found, "
305 "parsing it", extra_data->nDataSize);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700306 parse_sei(extra_data->data, extra_data->nDataSize);
307 }
308 else if (extra_data->eType == VEN_EXTRADATA_QCOMFILLER) {
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530309 DEBUG_PRINT_LOW("Extradata Qcom Filler found, skip %d bytes",
Shalaj Jain273b3e02012-06-22 19:08:03 -0700310 extra_data->nSize);
311 }
312 else if (extra_data->eType == VEN_EXTRADATA_SLICEINFO) {
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530313 DEBUG_PRINT_LOW("Extradata SliceInfo of size %d found, "
Shalaj Jain273b3e02012-06-22 19:08:03 -0700314 "parsing it", extra_data->nDataSize);
315 parse_sliceinfo(buf_hdr, extra_data);
316 }
Maheshwar Ajja1c976422012-10-20 16:58:10 +0530317#ifndef _MSM8974_
318 else if (extra_data->eType == VEN_EXTRADATA_LTRINFO) {
319 DEBUG_PRINT_LOW("Extradata LTRInfo of size %d found, "
320 "parsing it", extra_data->nDataSize);
321 parse_ltrinfo(buf_hdr, extra_data);
322 }
323#endif
324 else {
325 DEBUG_PRINT_ERROR("Unknown extradata(0x%x) found, nSize = 0x%x, "
326 "eType = 0x%x, nDataSize = 0x%x", (unsigned)extra_data,
327 extra_data->nSize, extra_data->eType, extra_data->nDataSize);
328 buf_hdr->nFlags &= ~(OMX_BUFFERFLAG_EXTRADATA);
329 break;
330 }
Shalaj Jain273b3e02012-06-22 19:08:03 -0700331 extra_data = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) extra_data) +
332 extra_data->nSize);
333 }
334 }
335 return 1;
336}
337
338OMX_U32 extra_data_handler::get_frame_pack_data(
339 OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack)
340{
341 DEBUG_PRINT_LOW("\n%s:%d get frame data", __func__, __LINE__);
342 memcpy(&frame_pack->id,&frame_packing_arrangement.id,
343 FRAME_PACK_SIZE*sizeof(OMX_U32));
344 return 1;
345}
346
347OMX_U32 extra_data_handler::set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT
348 *frame_pack)
349{
350 DEBUG_PRINT_LOW("\n%s:%d set frame data", __func__, __LINE__);
351 memcpy(&frame_packing_arrangement.id, &frame_pack->id,
352 FRAME_PACK_SIZE*sizeof(OMX_U32));
353 pack_sei = true;
354 sei_payload_type = SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT;
355 return 1;
356}
357
358OMX_U32 extra_data_handler::e_u(OMX_U32 symbol, OMX_U32 num_bits)
359{
360 OMX_U32 rem_bits = num_bits, shift;
361
362 DEBUG_PRINT_LOW("\n%s bin : %x/%d", __func__, symbol, num_bits);
363
364 while(rem_bits >= bit_ptr) {
365 shift = rem_bits - bit_ptr;
366 rbsp_buf[byte_ptr] |= (symbol >> shift);
367 symbol = (symbol << (32 - shift)) >> (32 - shift);
368 rem_bits -= bit_ptr;
369 DEBUG_PRINT_LOW("\n%sstream byte/rem_bits %x/%d", __func__,
370 rbsp_buf[byte_ptr], rem_bits);
371 byte_ptr ++;
372 bit_ptr = 8;
373 }
374
375 if(rem_bits) {
376 shift = bit_ptr - rem_bits;
377 rbsp_buf[byte_ptr] |= (symbol << shift);
378 bit_ptr -= rem_bits;
379 DEBUG_PRINT_LOW("\n%s 2 stream byte/rem_bits %x", __func__,
380 rbsp_buf[byte_ptr], rem_bits);
381 if(bit_ptr == 0) {
382 bit_ptr = 8;
383 byte_ptr++;
384 }
385 }
386 return 1;
387}
388
389OMX_U32 extra_data_handler::e_ue(OMX_U32 symbol)
390{
391 OMX_U32 i, sym_len, sufix_len, info;
392 OMX_U32 nn =(symbol + 1) >> 1;
393
394 DEBUG_PRINT_LOW("\n%s bin : %x", __func__, symbol);
395
396 for(i=0; i < 33 && nn != 0; i++)
397 nn >>= 1;
398
399 sym_len = ((i << 1) + 1);
400 info = symbol + 1 - (1 << i);
401 sufix_len = (1 << (sym_len >>1));
402 info = sufix_len | (info & (sufix_len - 1));
403 e_u(info, sym_len);
404 return 1;
405}
406
407OMX_U32 extra_data_handler::create_frame_pack()
408{
409 e_ue(frame_packing_arrangement.id);
410 e_u(frame_packing_arrangement.cancel_flag, 1);
411 if(!frame_packing_arrangement.cancel_flag) {
412 e_u(frame_packing_arrangement.type, 7);
413 e_u(frame_packing_arrangement.quincunx_sampling_flag, 1);
414 e_u(frame_packing_arrangement.content_interpretation_type, 6);
415 e_u(frame_packing_arrangement.spatial_flipping_flag, 1);
416 e_u(frame_packing_arrangement.frame0_flipped_flag, 1);
417 e_u(frame_packing_arrangement.field_views_flag, 1);
418 e_u(frame_packing_arrangement.current_frame_is_frame0_flag, 1);
419 e_u(frame_packing_arrangement.frame0_self_contained_flag, 1);
420 e_u(frame_packing_arrangement.frame1_self_contained_flag, 1);
421 if(!frame_packing_arrangement.quincunx_sampling_flag &&
422 frame_packing_arrangement.type != 5) {
423 e_u(frame_packing_arrangement.frame0_grid_position_x, 4);
424 e_u(frame_packing_arrangement.frame0_grid_position_y, 4);
425 e_u(frame_packing_arrangement.frame1_grid_position_x, 4);
426 e_u(frame_packing_arrangement.frame1_grid_position_y, 4);
427 }
428 e_u(frame_packing_arrangement.reserved_byte, 8);
429 e_ue(frame_packing_arrangement.repetition_period);
430 }
431 e_u(frame_packing_arrangement.extension_flag, 1);
432 return 1;
433}
434
435OMX_S32 extra_data_handler::create_rbsp(OMX_U8 *buf, OMX_U32 nalu_type)
436{
437 OMX_U32 i, j = 7;
438 for(i = 0;i < 3;i++)
439 *buf++ = 0x00;
440 *buf++ = H264_START_CODE;
441 *buf++ = nalu_type;
442 *buf++ = (sei_payload_type & 0x000000FF);
443 *buf++ = byte_ptr - 1; //payload will contain 1 byte of rbsp_trailing_bits
444 //that shouldn't be taken into account
445
446 for(i = 0;i < byte_ptr ;i += 2) {
447 *buf++ = rbsp_buf[i];
448 j++;
449 if(i+1 < byte_ptr) {
450 *buf++ = rbsp_buf[i+1];
451 j++;
452 if(!(rbsp_buf[i] + rbsp_buf[i+1])) {
453 *buf++ = H264_EMULATION_BYTE;
454 j++;
455 }
456 }
457 }
458
459 DEBUG_PRINT_LOW("\n%s rbsp length %d", __func__, j);
460 return j;
461}
462
463OMX_U32 extra_data_handler::create_sei(OMX_U8 *buffer)
464{
465 OMX_U32 i, ret_val = 0;
466
467 byte_ptr = 0;
468 bit_ptr = 8;
469
470 if(sei_payload_type == SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT) {
471 create_frame_pack();
472
473 if(bit_ptr != 8) {
474 e_u(1,1);
475 if(bit_ptr != 8)
476 e_u(0,bit_ptr);
477 }
478
479 //Payload will have been byte aligned by now,
480 //insert the rbsp trailing bits
481 e_u(1, 1);
482 e_u(0, 7);
483
484 ret_val = create_rbsp(buffer, NAL_TYPE_SEI);
485 }
486
487 pack_sei = false;
488 sei_payload_type = -1;
489
490 return ret_val;
491}
492
493OMX_U32 extra_data_handler::create_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr)
494{
495 OMX_U8 *buffer = (OMX_U8 *) ((unsigned)(buf_hdr->pBuffer +
496 buf_hdr->nOffset + buf_hdr->nFilledLen));
497 OMX_U32 msg_size;
498
Shalaj Jain273b3e02012-06-22 19:08:03 -0700499 if(buf_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
500 DEBUG_PRINT_LOW("\n%s:%d create extra data with config", __func__,
501 __LINE__);
502 if(pack_sei) {
503 msg_size = create_sei(buffer);
504 if( msg_size > 0)
505 buf_hdr->nFilledLen += msg_size;
506 }
507 }
Shalaj Jain273b3e02012-06-22 19:08:03 -0700508 return 1;
509}
510