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
extra_data_handler()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
~extra_data_handler()40 extra_data_handler::~extra_data_handler()
41 {
42 if(rbsp_buf) {
43 free(rbsp_buf);
44 rbsp_buf = NULL;
45 }
46 }
47
d_u(OMX_U32 num_bits)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
d_ue()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
parse_frame_pack(OMX_U32 payload_size)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
parse_rbsp(OMX_U8 * buf,OMX_U32 len)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 }
parse_sei(OMX_U8 * buffer,OMX_U32 buffer_length)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 ======================================================================*/
parse_sliceinfo(OMX_BUFFERHEADERTYPE * pBufHdr,OMX_OTHER_EXTRADATATYPE * pExtra)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
parse_extra_data(OMX_BUFFERHEADERTYPE * buf_hdr)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
get_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT * frame_pack)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
set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT * frame_pack)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
e_u(OMX_U32 symbol,OMX_U32 num_bits)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
e_ue(OMX_U32 symbol)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
create_frame_pack()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
create_rbsp(OMX_U8 * buf,OMX_U32 nalu_type)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
create_sei(OMX_U8 * buffer)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
create_extra_data(OMX_BUFFERHEADERTYPE * buf_hdr)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