1 /*--------------------------------------------------------------------------
2 Copyright (c) 2013-2014, The Linux Foundation. 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 The Linux Foundation 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 /*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33 *//** @file omx_vdec.cpp
34 This module contains the implementation of the OpenMAX core & component.
35
36 *//*========================================================================*/
37
38 //////////////////////////////////////////////////////////////////////////////
39 // Include Files
40 //////////////////////////////////////////////////////////////////////////////
41
42 #include <string.h>
43 #include <pthread.h>
44 #include <sys/prctl.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include "omx_vdec_hevc.h"
49 #include <fcntl.h>
50 #include <limits.h>
51 #include <media/msm_media_info.h>
52 #include <qdMetaData.h>
53
54 #ifndef _ANDROID_
55 #include <sys/ioctl.h>
56 #include <sys/mman.h>
57 #endif //_ANDROID_
58
59 #ifdef _ANDROID_
60 #include <cutils/properties.h>
61 #undef USE_EGL_IMAGE_GPU
62 #endif
63
64 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
65 #include <gralloc_priv.h>
66 #endif
67
68 #ifdef _ANDROID_
69 #include "DivXDrmDecrypt.h"
70 #endif //_ANDROID_
71
72 #ifdef USE_EGL_IMAGE_GPU
73 #include <EGL/egl.h>
74 #include <EGL/eglQCOM.h>
75 #define EGL_BUFFER_HANDLE_QCOM 0x4F00
76 #define EGL_BUFFER_OFFSET_QCOM 0x4F01
77 #endif
78
79 #ifdef INPUT_BUFFER_LOG
80 #define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0"
81 #define INPUT_BUFFER_FILE_NAME_LEN 30
82 FILE *inputBufferFile1;
83 char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0";
84 #endif
85 #ifdef OUTPUT_BUFFER_LOG
86 FILE *outputBufferFile1;
87 char outputfilename [] = "/data/output.yuv";
88 #endif
89 #ifdef OUTPUT_EXTRADATA_LOG
90 FILE *outputExtradataFile;
91 char ouputextradatafilename [] = "/data/extradata";
92 #endif
93
94 #ifdef VENUS_HEVC
95 #define DEVICE_NAME "/dev/video/venus_dec"
96 #else
97 #define DEVICE_NAME "/dev/video/q6_dec"
98 #endif
99
100 #define DEFAULT_FPS 30
101 #define MAX_INPUT_ERROR DEFAULT_FPS
102 #define MAX_SUPPORTED_FPS 120
103
104 #define VC1_SP_MP_START_CODE 0xC5000000
105 #define VC1_SP_MP_START_CODE_MASK 0xFF000000
106 #define VC1_AP_SEQ_START_CODE 0x0F010000
107 #define VC1_STRUCT_C_PROFILE_MASK 0xF0
108 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
109 #define VC1_SIMPLE_PROFILE 0
110 #define VC1_MAIN_PROFILE 1
111 #define VC1_ADVANCE_PROFILE 3
112 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
113 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2
114 #define VC1_STRUCT_C_LEN 4
115 #define VC1_STRUCT_C_POS 8
116 #define VC1_STRUCT_A_POS 12
117 #define VC1_STRUCT_B_POS 24
118 #define VC1_SEQ_LAYER_SIZE 36
119 #define POLL_TIMEOUT 0x7fffffff
120
121 #define MEM_DEVICE "/dev/ion"
122 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
123
124 #ifdef _ANDROID_
125 extern "C" {
126 #include<utils/Log.h>
127 }
128 #endif//_ANDROID_
129
130 #define SZ_4K 0x1000
131 #define SZ_1M 0x100000
132
133 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
134 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
135 #define EXTRADATA_IDX(__num_planes) (__num_planes - 1)
136
137 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA)
138
async_message_thread(void * input)139 void* async_message_thread (void *input)
140 {
141 OMX_BUFFERHEADERTYPE *buffer;
142 struct v4l2_plane plane[VIDEO_MAX_PLANES];
143 struct pollfd pfd;
144 struct v4l2_buffer v4l2_buf;
145 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
146 struct v4l2_event dqevent;
147 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
148 pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
149 pfd.fd = omx->drv_ctx.video_driver_fd;
150 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
151 DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
152 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
153 while (1) {
154 rc = poll(&pfd, 1, POLL_TIMEOUT);
155 if (!rc) {
156 DEBUG_PRINT_ERROR("Poll timedout");
157 break;
158 } else if (rc < 0) {
159 DEBUG_PRINT_ERROR("Error while polling: %d", rc);
160 break;
161 }
162 if ((pfd.revents & POLLIN) || (pfd.revents & POLLRDNORM)) {
163 struct vdec_msginfo vdec_msg;
164 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
165 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
166 v4l2_buf.length = omx->drv_ctx.num_planes;
167 v4l2_buf.m.planes = plane;
168 while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
169 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
170 vdec_msg.status_code=VDEC_S_SUCCESS;
171 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
172 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
173 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
174 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
175 (uint64_t)v4l2_buf.timestamp.tv_usec;
176 if (vdec_msg.msgdata.output_frame.len) {
177 vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
178 vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
179 vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
180 vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
181 }
182 if (omx->async_message_process(input,&vdec_msg) < 0) {
183 DEBUG_PRINT_HIGH("async_message_thread Exited");
184 break;
185 }
186 }
187 }
188 if ((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) {
189 struct vdec_msginfo vdec_msg;
190 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
191 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
192 v4l2_buf.length = 1;
193 v4l2_buf.m.planes = plane;
194 while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
195 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
196 vdec_msg.status_code=VDEC_S_SUCCESS;
197 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
198 if (omx->async_message_process(input,&vdec_msg) < 0) {
199 DEBUG_PRINT_HIGH("async_message_thread Exited");
200 break;
201 }
202 }
203 }
204 if (pfd.revents & POLLPRI) {
205 rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent);
206 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
207 struct vdec_msginfo vdec_msg;
208 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
209 vdec_msg.status_code=VDEC_S_SUCCESS;
210 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved");
211 if (omx->async_message_process(input,&vdec_msg) < 0) {
212 DEBUG_PRINT_HIGH("async_message_thread Exited");
213 break;
214 }
215 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT ) {
216 struct vdec_msginfo vdec_msg;
217 vdec_msg.msgcode=VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
218 vdec_msg.status_code=VDEC_S_SUCCESS;
219 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved");
220 if (omx->async_message_process(input,&vdec_msg) < 0) {
221 DEBUG_PRINT_HIGH("async_message_thread Exited");
222 break;
223 }
224 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
225 struct vdec_msginfo vdec_msg;
226 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
227 vdec_msg.status_code=VDEC_S_SUCCESS;
228 DEBUG_PRINT_HIGH("VIDC Flush Done Recieved");
229 if (omx->async_message_process(input,&vdec_msg) < 0) {
230 DEBUG_PRINT_HIGH("async_message_thread Exited");
231 break;
232 }
233 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
234 vdec_msg.status_code=VDEC_S_SUCCESS;
235 DEBUG_PRINT_HIGH("VIDC Flush Done Recieved");
236 if (omx->async_message_process(input,&vdec_msg) < 0) {
237 DEBUG_PRINT_HIGH("async_message_thread Exited");
238 break;
239 }
240 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
241 DEBUG_PRINT_HIGH("VIDC Close Done Recieved and async_message_thread Exited");
242 break;
243 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
244 struct vdec_msginfo vdec_msg;
245 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
246 vdec_msg.status_code=VDEC_S_SUCCESS;
247 DEBUG_PRINT_HIGH("SYS Error Recieved");
248 if (omx->async_message_process(input,&vdec_msg) < 0) {
249 DEBUG_PRINT_HIGH("async_message_thread Exited");
250 break;
251 }
252 } else {
253 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
254 continue;
255 }
256 }
257 }
258 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
259 return NULL;
260 }
261
message_thread(void * input)262 void* message_thread(void *input)
263 {
264 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
265 unsigned char id;
266 int n;
267 if (omx == NULL) {
268 DEBUG_PRINT_ERROR("message thread null pointer rxd");
269 return NULL;
270 }
271
272 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
273 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
274 while (1) {
275
276 n = read(omx->m_pipe_in, &id, 1);
277
278 if (0 == n) {
279 break;
280 }
281
282 if (1 == n) {
283 omx->process_event_cb(omx, id);
284 }
285 if ((n < 0) && (errno != EINTR)) {
286 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
287 break;
288 }
289 }
290 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
291 return NULL;
292 }
293
post_message(omx_vdec * omx,unsigned char id)294 void post_message(omx_vdec *omx, unsigned char id)
295 {
296 int ret_value;
297
298 if (omx == NULL) {
299 DEBUG_PRINT_ERROR("message thread null pointer rxd");
300 return;
301 }
302 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
303 ret_value = write(omx->m_pipe_out, &id, 1);
304 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
305 }
306
307 // omx_cmd_queue destructor
~omx_cmd_queue()308 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
309 {
310 // Nothing to do
311 }
312
313 // omx cmd queue constructor
omx_cmd_queue()314 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
315 {
316 memset(m_q,0,sizeof(m_q));
317 }
318
319 // omx cmd queue insert
insert_entry(unsigned p1,unsigned p2,unsigned id)320 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
321 {
322 bool ret = true;
323 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
324 m_q[m_write].id = id;
325 m_q[m_write].param1 = p1;
326 m_q[m_write].param2 = p2;
327 m_write++;
328 m_size ++;
329 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
330 m_write = 0;
331 }
332 } else {
333 ret = false;
334 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
335 }
336 return ret;
337 }
338
339 // omx cmd queue pop
pop_entry(unsigned * p1,unsigned * p2,unsigned * id)340 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
341 {
342 bool ret = true;
343 if (m_size > 0) {
344 *id = m_q[m_read].id;
345 *p1 = m_q[m_read].param1;
346 *p2 = m_q[m_read].param2;
347 // Move the read pointer ahead
348 ++m_read;
349 --m_size;
350 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
351 m_read = 0;
352 }
353 } else {
354 ret = false;
355 }
356 return ret;
357 }
358
359 // Retrieve the first mesg type in the queue
get_q_msg_type()360 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
361 {
362 return m_q[m_read].id;
363 }
364
365 #ifdef _ANDROID_
ts_arr_list()366 omx_vdec::ts_arr_list::ts_arr_list()
367 {
368 //initialize timestamps array
369 memset(m_ts_arr_list, 0, sizeof(m_ts_arr_list) );
370 }
~ts_arr_list()371 omx_vdec::ts_arr_list::~ts_arr_list()
372 {
373 //free m_ts_arr_list?
374 }
375
insert_ts(OMX_TICKS ts)376 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
377 {
378 bool ret = true;
379 bool duplicate_ts = false;
380 int idx = 0;
381
382 //insert at the first available empty location
383 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
384 if (!m_ts_arr_list[idx].valid) {
385 //found invalid or empty entry, save timestamp
386 m_ts_arr_list[idx].valid = true;
387 m_ts_arr_list[idx].timestamp = ts;
388 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
389 ts, idx);
390 break;
391 }
392 }
393
394 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
395 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
396 ret = false;
397 }
398 return ret;
399 }
400
pop_min_ts(OMX_TICKS & ts)401 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
402 {
403 bool ret = true;
404 int min_idx = -1;
405 OMX_TICKS min_ts = 0;
406 int idx = 0;
407
408 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
409
410 if (m_ts_arr_list[idx].valid) {
411 //found valid entry, save index
412 if (min_idx < 0) {
413 //first valid entry
414 min_ts = m_ts_arr_list[idx].timestamp;
415 min_idx = idx;
416 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
417 min_ts = m_ts_arr_list[idx].timestamp;
418 min_idx = idx;
419 }
420 }
421
422 }
423
424 if (min_idx < 0) {
425 //no valid entries found
426 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
427 ts = 0;
428 ret = false;
429 } else {
430 ts = m_ts_arr_list[min_idx].timestamp;
431 m_ts_arr_list[min_idx].valid = false;
432 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
433 ts, min_idx);
434 }
435
436 return ret;
437
438 }
439
440
reset_ts_list()441 bool omx_vdec::ts_arr_list::reset_ts_list()
442 {
443 bool ret = true;
444 int idx = 0;
445
446 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
447 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
448 m_ts_arr_list[idx].valid = false;
449 }
450 return ret;
451 }
452 #endif
453
454 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)455 void *get_omx_component_factory_fn(void)
456 {
457 return (new omx_vdec);
458 }
459
460 #ifdef _ANDROID_
461 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,ion_user_handle_t handle,int ionMapfd)462 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
463 ion_user_handle_t handle, int ionMapfd)
464 {
465 // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
466 }
467 #else
VideoHeap(int fd,size_t size,void * base)468 VideoHeap::VideoHeap(int fd, size_t size, void* base)
469 {
470 // dup file descriptor, map once, use pmem
471 init(dup(fd), base, size, 0 , MEM_DEVICE);
472 }
473 #endif
474 #endif // _ANDROID_
475 /* ======================================================================
476 FUNCTION
477 omx_vdec::omx_vdec
478
479 DESCRIPTION
480 Constructor
481
482 PARAMETERS
483 None
484
485 RETURN VALUE
486 None.
487 ========================================================================== */
omx_vdec()488 omx_vdec::omx_vdec(): m_error_propogated(false),
489 m_state(OMX_StateInvalid),
490 m_app_data(NULL),
491 m_inp_mem_ptr(NULL),
492 m_out_mem_ptr(NULL),
493 m_inp_err_count(0),
494 input_flush_progress (false),
495 output_flush_progress (false),
496 input_use_buffer (false),
497 output_use_buffer (false),
498 ouput_egl_buffers(false),
499 m_use_output_pmem(OMX_FALSE),
500 m_out_mem_region_smi(OMX_FALSE),
501 m_out_pvt_entry_pmem(OMX_FALSE),
502 pending_input_buffers(0),
503 pending_output_buffers(0),
504 m_out_bm_count(0),
505 m_inp_bm_count(0),
506 m_inp_bPopulated(OMX_FALSE),
507 m_out_bPopulated(OMX_FALSE),
508 m_flags(0),
509 #ifdef _ANDROID_
510 m_heap_ptr(NULL),
511 #endif
512 m_inp_bEnabled(OMX_TRUE),
513 m_out_bEnabled(OMX_TRUE),
514 m_in_alloc_cnt(0),
515 m_platform_list(NULL),
516 m_platform_entry(NULL),
517 m_pmem_info(NULL),
518 arbitrary_bytes (true),
519 psource_frame (NULL),
520 pdest_frame (NULL),
521 m_inp_heap_ptr (NULL),
522 m_phdr_pmem_ptr(NULL),
523 m_heap_inp_bm_count (0),
524 codec_type_parse ((codec_type)0),
525 first_frame_meta (true),
526 frame_count (0),
527 nal_count (0),
528 nal_length(0),
529 look_ahead_nal (false),
530 first_frame(0),
531 first_buffer(NULL),
532 first_frame_size (0),
533 m_device_file_ptr(NULL),
534 m_vc1_profile((vc1_profile_type)0),
535 h264_last_au_ts(LLONG_MAX),
536 h264_last_au_flags(0),
537 prev_ts(LLONG_MAX),
538 rst_prev_ts(true),
539 frm_int(0),
540 in_reconfig(false),
541 m_display_id(NULL),
542 h264_parser(NULL),
543 client_extradata(0),
544 #ifdef _ANDROID_
545 m_enable_android_native_buffers(OMX_FALSE),
546 m_use_android_native_buffers(OMX_FALSE),
547 iDivXDrmDecrypt(NULL),
548 #endif
549 m_desc_buffer_ptr(NULL),
550 secure_mode(false)
551 {
552 /* Assumption is that , to begin with , we have all the frames with decoder */
553 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
554 #ifdef _ANDROID_
555 char property_value[PROPERTY_VALUE_MAX] = {0};
556 property_get("vidc.debug.level", property_value, "1");
557 debug_level = atoi(property_value);
558 property_value[0] = '\0';
559
560 property_get("vidc.dec.debug.perf", property_value, "0");
561 perf_flag = atoi(property_value);
562 if (perf_flag) {
563 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
564 dec_time.start();
565 proc_frms = latency = 0;
566 }
567 property_value[0] = '\0';
568 property_get("vidc.dec.debug.ts", property_value, "0");
569 m_debug_timestamp = atoi(property_value);
570 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
571 if (m_debug_timestamp) {
572 time_stamp_dts.set_timestamp_reorder_mode(true);
573 time_stamp_dts.enable_debug_print(true);
574 }
575
576 property_value[0] = '\0';
577 property_get("vidc.dec.debug.concealedmb", property_value, "0");
578 m_debug_concealedmb = atoi(property_value);
579 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
580
581 #endif
582 memset(&m_cmp,0,sizeof(m_cmp));
583 memset(&m_cb,0,sizeof(m_cb));
584 memset (&drv_ctx,0,sizeof(drv_ctx));
585 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
586 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
587 memset(m_demux_offsets, 0, sizeof(m_demux_offsets) );
588 m_demux_entries = 0;
589 #ifdef _ANDROID_ICS_
590 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
591 #endif
592 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
593 drv_ctx.timestamp_adjust = false;
594 drv_ctx.video_driver_fd = -1;
595 m_vendor_config.pData = NULL;
596 pthread_mutex_init(&m_lock, NULL);
597 pthread_mutex_init(&c_lock, NULL);
598 sem_init(&m_cmd_lock,0,0);
599 streaming[CAPTURE_PORT] =
600 streaming[OUTPUT_PORT] = false;
601 #ifdef _ANDROID_
602 char extradata_value[PROPERTY_VALUE_MAX] = {0};
603 property_get("vidc.dec.debug.extradata", extradata_value, "0");
604 m_debug_extradata = atoi(extradata_value);
605 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
606 #endif
607 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
608 client_buffers.set_vdec_client(this);
609 }
610
611 static const int event_type[] = {
612 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
613 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
614 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
615 V4L2_EVENT_MSM_VIDC_CLOSE_DONE,
616 V4L2_EVENT_MSM_VIDC_SYS_ERROR
617 };
618
subscribe_to_events(int fd)619 static OMX_ERRORTYPE subscribe_to_events(int fd)
620 {
621 OMX_ERRORTYPE eRet = OMX_ErrorNone;
622 struct v4l2_event_subscription sub;
623 int array_sz = sizeof(event_type)/sizeof(int);
624 int i,rc;
625 if (fd < 0) {
626 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
627 return OMX_ErrorBadParameter;
628 }
629
630 for (i = 0; i < array_sz; ++i) {
631 memset(&sub, 0, sizeof(sub));
632 sub.type = event_type[i];
633 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
634 if (rc) {
635 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
636 break;
637 }
638 }
639 if (i < array_sz) {
640 for (--i; i >=0 ; i--) {
641 memset(&sub, 0, sizeof(sub));
642 sub.type = event_type[i];
643 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
644 if (rc)
645 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
646 }
647 eRet = OMX_ErrorNotImplemented;
648 }
649 return eRet;
650 }
651
652
unsubscribe_to_events(int fd)653 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
654 {
655 OMX_ERRORTYPE eRet = OMX_ErrorNone;
656 struct v4l2_event_subscription sub;
657 int array_sz = sizeof(event_type)/sizeof(int);
658 int i,rc;
659 if (fd < 0) {
660 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
661 return OMX_ErrorBadParameter;
662 }
663
664 for (i = 0; i < array_sz; ++i) {
665 memset(&sub, 0, sizeof(sub));
666 sub.type = event_type[i];
667 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
668 if (rc) {
669 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
670 break;
671 }
672 }
673 return eRet;
674 }
675
676 /* ======================================================================
677 FUNCTION
678 omx_vdec::~omx_vdec
679
680 DESCRIPTION
681 Destructor
682
683 PARAMETERS
684 None
685
686 RETURN VALUE
687 None.
688 ========================================================================== */
~omx_vdec()689 omx_vdec::~omx_vdec()
690 {
691 m_pmem_info = NULL;
692 struct v4l2_decoder_cmd dec;
693 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
694 if (m_pipe_in) close(m_pipe_in);
695 if (m_pipe_out) close(m_pipe_out);
696 m_pipe_in = -1;
697 m_pipe_out = -1;
698 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
699 pthread_join(msg_thread_id,NULL);
700 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
701 dec.cmd = V4L2_DEC_CMD_STOP;
702 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
703 DEBUG_PRINT_ERROR("STOP Command failed");
704 }
705 pthread_join(async_thread_id,NULL);
706 unsubscribe_to_events(drv_ctx.video_driver_fd);
707 close(drv_ctx.video_driver_fd);
708 pthread_mutex_destroy(&m_lock);
709 pthread_mutex_destroy(&c_lock);
710 sem_destroy(&m_cmd_lock);
711 if (perf_flag) {
712 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
713 dec_time.end();
714 }
715 DEBUG_PRINT_HIGH("Exit OMX vdec Destructor");
716 }
717
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)718 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
719 {
720 struct v4l2_requestbuffers bufreq;
721 int rc = 0;
722 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
723 bufreq.memory = V4L2_MEMORY_USERPTR;
724 bufreq.count = 0;
725 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
726 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
727 }
728 return rc;
729 }
730
731 /* ======================================================================
732 FUNCTION
733 omx_vdec::OMXCntrlProcessMsgCb
734
735 DESCRIPTION
736 IL Client callbacks are generated through this routine. The decoder
737 provides the thread context for this routine.
738
739 PARAMETERS
740 ctxt -- Context information related to the self.
741 id -- Event identifier. This could be any of the following:
742 1. Command completion event
743 2. Buffer done callback event
744 3. Frame done callback event
745
746 RETURN VALUE
747 None.
748
749 ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)750 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
751 {
752 signed int p1; // Parameter - 1
753 signed int p2; // Parameter - 2
754 unsigned int ident;
755 unsigned int qsize=0; // qsize
756 omx_vdec *pThis = (omx_vdec *) ctxt;
757
758 if (!pThis) {
759 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
760 __func__);
761 return;
762 }
763
764 // Protect the shared queue data structure
765 do {
766 /*Read the message id's from the queue*/
767 pthread_mutex_lock(&pThis->m_lock);
768 qsize = pThis->m_cmd_q.m_size;
769 if (qsize) {
770 pThis->m_cmd_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
771 }
772
773 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
774 qsize = pThis->m_ftb_q.m_size;
775 if (qsize) {
776 pThis->m_ftb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
777 }
778 }
779
780 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
781 qsize = pThis->m_etb_q.m_size;
782 if (qsize) {
783 pThis->m_etb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
784 }
785 }
786 pthread_mutex_unlock(&pThis->m_lock);
787
788 /*process message if we have one*/
789 if (qsize > 0) {
790 id = ident;
791 switch (id) {
792 case OMX_COMPONENT_GENERATE_EVENT:
793 if (pThis->m_cb.EventHandler) {
794 switch (p1) {
795 case OMX_CommandStateSet:
796 pThis->m_state = (OMX_STATETYPE) p2;
797 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
798 pThis->m_state);
799 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
800 OMX_EventCmdComplete, p1, p2, NULL);
801 break;
802
803 case OMX_EventError:
804 if (p2 == OMX_StateInvalid) {
805 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
806 pThis->m_state = (OMX_STATETYPE) p2;
807 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
808 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
809 } else if (p2 == OMX_ErrorHardware) {
810 pThis->omx_report_error();
811 } else {
812 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
813 OMX_EventError, p2, (OMX_U32)NULL, NULL );
814 }
815 break;
816
817 case OMX_CommandPortDisable:
818 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%d]", p2);
819 if (BITMASK_PRESENT(&pThis->m_flags,
820 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
821 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
822 break;
823 }
824 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) {
825 OMX_ERRORTYPE eRet = OMX_ErrorNone;
826 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
827 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
828 DEBUG_PRINT_HIGH("Failed to release output buffers");
829 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
830 pThis->in_reconfig = false;
831 if (eRet != OMX_ErrorNone) {
832 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
833 pThis->omx_report_error();
834 break;
835 }
836 }
837 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
838 OMX_EventCmdComplete, p1, p2, NULL );
839 break;
840 case OMX_CommandPortEnable:
841 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%d]", p2);
842 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
843 OMX_EventCmdComplete, p1, p2, NULL );
844 break;
845
846 default:
847 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
848 OMX_EventCmdComplete, p1, p2, NULL );
849 break;
850
851 }
852 } else {
853 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
854 }
855 break;
856 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
857 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
858 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
859 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
860 pThis->omx_report_error ();
861 }
862 break;
863 case OMX_COMPONENT_GENERATE_ETB:
864 if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
865 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
866 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
867 pThis->omx_report_error ();
868 }
869 break;
870
871 case OMX_COMPONENT_GENERATE_FTB:
872 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
873 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
874 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
875 pThis->omx_report_error ();
876 }
877 break;
878
879 case OMX_COMPONENT_GENERATE_COMMAND:
880 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
881 (OMX_U32)p2,(OMX_PTR)NULL);
882 break;
883
884 case OMX_COMPONENT_GENERATE_EBD:
885
886 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
887 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
888 pThis->omx_report_error ();
889 } else {
890 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
891 pThis->m_inp_err_count++;
892 pThis->time_stamp_dts.remove_time_stamp(
893 ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp,
894 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
895 ?true:false);
896 } else {
897 pThis->m_inp_err_count = 0;
898 }
899 if ( pThis->empty_buffer_done(&pThis->m_cmp,
900 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
901 DEBUG_PRINT_ERROR("empty_buffer_done failure");
902 pThis->omx_report_error ();
903 }
904 if (pThis->m_inp_err_count >= MAX_INPUT_ERROR) {
905 DEBUG_PRINT_ERROR("Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR);
906 pThis->omx_report_error ();
907 }
908 }
909 break;
910 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED:
911 {
912 int64_t *timestamp = (int64_t *)p1;
913 if (p1) {
914 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
915 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
916 ?true:false);
917 free(timestamp);
918 }
919 }
920 break;
921 case OMX_COMPONENT_GENERATE_FBD:
922 if (p2 != VDEC_S_SUCCESS) {
923 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
924 pThis->omx_report_error ();
925 } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
926 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
927 DEBUG_PRINT_ERROR("fill_buffer_done failure");
928 pThis->omx_report_error ();
929 }
930 break;
931
932 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
933 DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
934 if (!pThis->input_flush_progress) {
935 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
936 } else {
937 pThis->execute_input_flush();
938 if (pThis->m_cb.EventHandler) {
939 if (p2 != VDEC_S_SUCCESS) {
940 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
941 pThis->omx_report_error ();
942 } else {
943 /*Check if we need generate event for Flush done*/
944 if (BITMASK_PRESENT(&pThis->m_flags,
945 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
946 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
947 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
948 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
949 OMX_EventCmdComplete,OMX_CommandFlush,
950 OMX_CORE_INPUT_PORT_INDEX,NULL );
951 }
952 if (BITMASK_PRESENT(&pThis->m_flags,
953 OMX_COMPONENT_IDLE_PENDING)) {
954 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
955 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
956 pThis->omx_report_error ();
957 } else {
958 pThis->streaming[OUTPUT_PORT] = false;
959 }
960 if (!pThis->output_flush_progress) {
961 DEBUG_PRINT_LOW("Input flush done hence issue stop");
962 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
963 OMX_COMPONENT_GENERATE_STOP_DONE);
964 }
965 }
966 }
967 } else {
968 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
969 }
970 }
971 break;
972
973 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
974 DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
975 if (!pThis->output_flush_progress) {
976 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
977 } else {
978 pThis->execute_output_flush();
979 if (pThis->m_cb.EventHandler) {
980 if (p2 != VDEC_S_SUCCESS) {
981 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
982 pThis->omx_report_error ();
983 } else {
984 /*Check if we need generate event for Flush done*/
985 if (BITMASK_PRESENT(&pThis->m_flags,
986 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
987 DEBUG_PRINT_LOW("Notify Output Flush done");
988 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
989 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
990 OMX_EventCmdComplete,OMX_CommandFlush,
991 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
992 }
993 if (BITMASK_PRESENT(&pThis->m_flags,
994 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
995 DEBUG_PRINT_LOW("Internal flush complete");
996 BITMASK_CLEAR (&pThis->m_flags,
997 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
998 if (BITMASK_PRESENT(&pThis->m_flags,
999 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1000 pThis->post_event(OMX_CommandPortDisable,
1001 OMX_CORE_OUTPUT_PORT_INDEX,
1002 OMX_COMPONENT_GENERATE_EVENT);
1003 BITMASK_CLEAR (&pThis->m_flags,
1004 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1005
1006 }
1007 }
1008
1009 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1010 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1011 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1012 pThis->omx_report_error ();
1013 break;
1014 }
1015 pThis->streaming[CAPTURE_PORT] = false;
1016 if (!pThis->input_flush_progress) {
1017 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1018 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1019 OMX_COMPONENT_GENERATE_STOP_DONE);
1020 }
1021 }
1022 }
1023 } else {
1024 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1025 }
1026 }
1027 break;
1028
1029 case OMX_COMPONENT_GENERATE_START_DONE:
1030 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1031
1032 if (pThis->m_cb.EventHandler) {
1033 if (p2 != VDEC_S_SUCCESS) {
1034 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1035 pThis->omx_report_error ();
1036 } else {
1037 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1038 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1039 DEBUG_PRINT_LOW("Move to executing");
1040 // Send the callback now
1041 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1042 pThis->m_state = OMX_StateExecuting;
1043 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1044 OMX_EventCmdComplete,OMX_CommandStateSet,
1045 OMX_StateExecuting, NULL);
1046 } else if (BITMASK_PRESENT(&pThis->m_flags,
1047 OMX_COMPONENT_PAUSE_PENDING)) {
1048 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1049 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1050 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1051 pThis->omx_report_error ();
1052 }
1053 }
1054 }
1055 } else {
1056 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1057 }
1058 break;
1059
1060 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1061 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1062 if (pThis->m_cb.EventHandler) {
1063 if (p2 != VDEC_S_SUCCESS) {
1064 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1065 pThis->omx_report_error ();
1066 } else {
1067 pThis->complete_pending_buffer_done_cbs();
1068 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1069 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1070 //Send the callback now
1071 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1072 pThis->m_state = OMX_StatePause;
1073 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1074 OMX_EventCmdComplete,OMX_CommandStateSet,
1075 OMX_StatePause, NULL);
1076 }
1077 }
1078 } else {
1079 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1080 }
1081
1082 break;
1083
1084 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1085 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1086 if (pThis->m_cb.EventHandler) {
1087 if (p2 != VDEC_S_SUCCESS) {
1088 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1089 pThis->omx_report_error ();
1090 } else {
1091 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1092 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1093 // Send the callback now
1094 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1095 pThis->m_state = OMX_StateExecuting;
1096 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1097 OMX_EventCmdComplete,OMX_CommandStateSet,
1098 OMX_StateExecuting,NULL);
1099 }
1100 }
1101 } else {
1102 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1103 }
1104
1105 break;
1106
1107 case OMX_COMPONENT_GENERATE_STOP_DONE:
1108 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1109 if (pThis->m_cb.EventHandler) {
1110 if (p2 != VDEC_S_SUCCESS) {
1111 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1112 pThis->omx_report_error ();
1113 } else {
1114 pThis->complete_pending_buffer_done_cbs();
1115 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1116 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1117 // Send the callback now
1118 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1119 pThis->m_state = OMX_StateIdle;
1120 DEBUG_PRINT_LOW("Move to Idle State");
1121 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1122 OMX_EventCmdComplete,OMX_CommandStateSet,
1123 OMX_StateIdle,NULL);
1124 }
1125 }
1126 } else {
1127 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1128 }
1129
1130 break;
1131
1132 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1133 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG");
1134
1135 if (p2 == OMX_IndexParamPortDefinition) {
1136 pThis->in_reconfig = true;
1137 }
1138 if (pThis->m_cb.EventHandler) {
1139 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1140 OMX_EventPortSettingsChanged, p1, p2, NULL );
1141 } else {
1142 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1143 }
1144
1145 if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) {
1146 OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1;
1147 OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged;
1148 if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
1149 format = OMX_InterlaceInterleaveFrameTopFieldFirst;
1150 else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
1151 format = OMX_InterlaceInterleaveFrameBottomFieldFirst;
1152 else //unsupported interlace format; raise a error
1153 event = OMX_EventError;
1154 if (pThis->m_cb.EventHandler) {
1155 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1156 event, format, 0, NULL );
1157 } else {
1158 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1159 }
1160 }
1161 break;
1162
1163 case OMX_COMPONENT_GENERATE_EOS_DONE:
1164 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1165 if (pThis->m_cb.EventHandler) {
1166 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1167 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1168 } else {
1169 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1170 }
1171 pThis->prev_ts = LLONG_MAX;
1172 pThis->rst_prev_ts = true;
1173 break;
1174
1175 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1176 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1177 pThis->omx_report_error ();
1178 break;
1179 case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG:
1180 {
1181 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG");
1182 if (pThis->m_cb.EventHandler) {
1183 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1184 (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
1185 } else {
1186 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1187 }
1188 }
1189 default:
1190 break;
1191 }
1192 }
1193 pthread_mutex_lock(&pThis->m_lock);
1194 qsize = pThis->m_cmd_q.m_size;
1195 if (pThis->m_state != OMX_StatePause)
1196 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1197 pthread_mutex_unlock(&pThis->m_lock);
1198 } while (qsize>0);
1199
1200 }
1201
update_resolution(int width,int height)1202 void omx_vdec::update_resolution(int width, int height)
1203 {
1204 drv_ctx.video_resolution.frame_height = height;
1205 drv_ctx.video_resolution.frame_width = width;
1206 drv_ctx.video_resolution.scan_lines = height;
1207 drv_ctx.video_resolution.stride = width;
1208 rectangle.nLeft = 0;
1209 rectangle.nTop = 0;
1210 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1211 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1212 }
1213
1214 /* ======================================================================
1215 FUNCTION
1216 omx_vdec::ComponentInit
1217
1218 DESCRIPTION
1219 Initialize the component.
1220
1221 PARAMETERS
1222 ctxt -- Context information related to the self.
1223 id -- Event identifier. This could be any of the following:
1224 1. Command completion event
1225 2. Buffer done callback event
1226 3. Frame done callback event
1227
1228 RETURN VALUE
1229 None.
1230
1231 ========================================================================== */
component_init(OMX_STRING role)1232 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1233 {
1234
1235 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1236 struct v4l2_fmtdesc fdesc;
1237 struct v4l2_format fmt;
1238 struct v4l2_requestbuffers bufreq;
1239 struct v4l2_control control;
1240 unsigned int alignment = 0,buffer_size = 0;
1241 int fds[2];
1242 int r,ret=0;
1243 bool codec_ambiguous = false;
1244 OMX_STRING device_name = (OMX_STRING)DEVICE_NAME;
1245 DEBUG_PRINT_LOW("Opening device %s", device_name);
1246 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1247
1248 DEBUG_PRINT_HIGH("omx_vdec::component_init(): Open device %s returned fd %d, errno %d",
1249 device_name, drv_ctx.video_driver_fd, errno);
1250
1251 if (drv_ctx.video_driver_fd == 0) {
1252 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1253 }
1254
1255 if (drv_ctx.video_driver_fd < 0) {
1256 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
1257 return OMX_ErrorInsufficientResources;
1258 }
1259 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1260 drv_ctx.frame_rate.fps_denominator = 1;
1261
1262 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
1263 if (ret < 0) {
1264 close(drv_ctx.video_driver_fd);
1265 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
1266 return OMX_ErrorInsufficientResources;
1267 }
1268
1269 #ifdef INPUT_BUFFER_LOG
1270 strcpy(inputfilename, INPUT_BUFFER_FILE_NAME);
1271 #endif
1272 #ifdef OUTPUT_BUFFER_LOG
1273 outputBufferFile1 = fopen (outputfilename, "ab");
1274 #endif
1275 #ifdef OUTPUT_EXTRADATA_LOG
1276 outputExtradataFile = fopen (ouputextradatafilename, "ab");
1277 #endif
1278
1279 // Copy the role information which provides the decoder kind
1280 strlcpy(drv_ctx.kind,role,128);
1281
1282 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
1283 OMX_MAX_STRINGNAME_SIZE)) {
1284 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
1285 OMX_MAX_STRINGNAME_SIZE);
1286 drv_ctx.timestamp_adjust = true;
1287 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
1288 eCompressionFormat = OMX_VIDEO_CodingMPEG4;
1289 output_capability=V4L2_PIX_FMT_MPEG4;
1290 /*Initialize Start Code for MPEG4*/
1291 codec_type_parse = CODEC_TYPE_MPEG4;
1292 m_frame_parser.init_start_codes (codec_type_parse);
1293 #ifdef INPUT_BUFFER_LOG
1294 strcat(inputfilename, "m4v");
1295 #endif
1296 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
1297 OMX_MAX_STRINGNAME_SIZE)) {
1298 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
1299 OMX_MAX_STRINGNAME_SIZE);
1300 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
1301 output_capability = V4L2_PIX_FMT_MPEG2;
1302 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
1303 /*Initialize Start Code for MPEG2*/
1304 codec_type_parse = CODEC_TYPE_MPEG2;
1305 m_frame_parser.init_start_codes (codec_type_parse);
1306 #ifdef INPUT_BUFFER_LOG
1307 strcat(inputfilename, "mpg");
1308 #endif
1309 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
1310 OMX_MAX_STRINGNAME_SIZE)) {
1311 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
1312 DEBUG_PRINT_LOW("H263 Decoder selected");
1313 drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
1314 eCompressionFormat = OMX_VIDEO_CodingH263;
1315 output_capability = V4L2_PIX_FMT_H263;
1316 codec_type_parse = CODEC_TYPE_H263;
1317 m_frame_parser.init_start_codes (codec_type_parse);
1318 #ifdef INPUT_BUFFER_LOG
1319 strcat(inputfilename, "263");
1320 #endif
1321 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
1322 OMX_MAX_STRINGNAME_SIZE)) {
1323 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1324 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
1325 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
1326 output_capability = V4L2_PIX_FMT_DIVX_311;
1327 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1328 codec_type_parse = CODEC_TYPE_DIVX;
1329 m_frame_parser.init_start_codes (codec_type_parse);
1330
1331 eRet = createDivxDrmContext();
1332 if (eRet != OMX_ErrorNone) {
1333 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1334 return eRet;
1335 }
1336 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
1337 OMX_MAX_STRINGNAME_SIZE)) {
1338 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1339 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
1340 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
1341 output_capability = V4L2_PIX_FMT_DIVX;
1342 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1343 codec_type_parse = CODEC_TYPE_DIVX;
1344 codec_ambiguous = true;
1345 m_frame_parser.init_start_codes (codec_type_parse);
1346
1347 eRet = createDivxDrmContext();
1348 if (eRet != OMX_ErrorNone) {
1349 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1350 return eRet;
1351 }
1352 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
1353 OMX_MAX_STRINGNAME_SIZE)) {
1354 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1355 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
1356 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
1357 output_capability = V4L2_PIX_FMT_DIVX;
1358 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1359 codec_type_parse = CODEC_TYPE_DIVX;
1360 codec_ambiguous = true;
1361 m_frame_parser.init_start_codes (codec_type_parse);
1362
1363 eRet = createDivxDrmContext();
1364 if (eRet != OMX_ErrorNone) {
1365 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1366 return eRet;
1367 }
1368
1369 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
1370 OMX_MAX_STRINGNAME_SIZE)) {
1371 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
1372 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
1373 output_capability=V4L2_PIX_FMT_H264;
1374 eCompressionFormat = OMX_VIDEO_CodingAVC;
1375 codec_type_parse = CODEC_TYPE_H264;
1376 m_frame_parser.init_start_codes (codec_type_parse);
1377 m_frame_parser.init_nal_length(nal_length);
1378 #ifdef INPUT_BUFFER_LOG
1379 strcat(inputfilename, "264");
1380 #endif
1381 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
1382 OMX_MAX_STRINGNAME_SIZE)) {
1383 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
1384 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
1385 output_capability=V4L2_PIX_FMT_HEVC;
1386 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
1387 codec_type_parse = CODEC_TYPE_HEVC;
1388 m_frame_parser.init_start_codes (codec_type_parse);
1389 m_frame_parser.init_nal_length(nal_length);
1390 #ifdef INPUT_BUFFER_LOG
1391 strcat(inputfilename, "265");
1392 #endif
1393 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
1394 OMX_MAX_STRINGNAME_SIZE)) {
1395 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1396 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
1397 eCompressionFormat = OMX_VIDEO_CodingWMV;
1398 codec_type_parse = CODEC_TYPE_VC1;
1399 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
1400 m_frame_parser.init_start_codes (codec_type_parse);
1401 #ifdef INPUT_BUFFER_LOG
1402 strcat(inputfilename, "vc1");
1403 #endif
1404 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
1405 OMX_MAX_STRINGNAME_SIZE)) {
1406 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1407 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
1408 eCompressionFormat = OMX_VIDEO_CodingWMV;
1409 codec_type_parse = CODEC_TYPE_VC1;
1410 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
1411 m_frame_parser.init_start_codes (codec_type_parse);
1412 #ifdef INPUT_BUFFER_LOG
1413 strcat(inputfilename, "vc1");
1414 #endif
1415 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",\
1416 OMX_MAX_STRINGNAME_SIZE)) {
1417 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
1418 output_capability=V4L2_PIX_FMT_VP8;
1419 eCompressionFormat = OMX_VIDEO_CodingVP8;
1420 codec_type_parse = CODEC_TYPE_VP8;
1421 arbitrary_bytes = false;
1422 } else {
1423 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
1424 eRet = OMX_ErrorInvalidComponentName;
1425 }
1426 #ifdef INPUT_BUFFER_LOG
1427 inputBufferFile1 = fopen (inputfilename, "ab");
1428 #endif
1429 if (eRet == OMX_ErrorNone) {
1430
1431 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
1432 OMX_COLOR_FORMATTYPE dest_color_format = (OMX_COLOR_FORMATTYPE)
1433 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
1434 if (!client_buffers.set_color_format(dest_color_format)) {
1435 DEBUG_PRINT_ERROR("Setting color format failed");
1436 eRet = OMX_ErrorInsufficientResources;
1437 }
1438
1439 capture_capability= V4L2_PIX_FMT_NV12;
1440 ret = subscribe_to_events(drv_ctx.video_driver_fd);
1441 if (ret) {
1442 DEBUG_PRINT_ERROR("Subscribe Event Failed");
1443 return OMX_ErrorInsufficientResources;
1444 }
1445
1446 struct v4l2_capability cap;
1447 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
1448 if (ret) {
1449 DEBUG_PRINT_ERROR("Failed to query capabilities");
1450 /*TODO: How to handle this case */
1451 } else {
1452 DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1453 " version = %d, capabilities = %x", cap.driver, cap.card,
1454 cap.bus_info, cap.version, cap.capabilities);
1455 }
1456 ret=0;
1457 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1458 fdesc.index=0;
1459 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1460 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1461 fdesc.pixelformat, fdesc.flags);
1462 fdesc.index++;
1463 }
1464 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1465 fdesc.index=0;
1466 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1467
1468 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1469 fdesc.pixelformat, fdesc.flags);
1470 fdesc.index++;
1471 }
1472 update_resolution(320, 240);
1473 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1474 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1475 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1476 fmt.fmt.pix_mp.pixelformat = output_capability;
1477 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1478 if (ret) {
1479 /*TODO: How to handle this case */
1480 DEBUG_PRINT_ERROR("Failed to set format on output port");
1481 }
1482 DEBUG_PRINT_HIGH("Set Format was successful");
1483 if (codec_ambiguous) {
1484 if (output_capability == V4L2_PIX_FMT_DIVX) {
1485 struct v4l2_control divx_ctrl;
1486
1487 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
1488 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
1489 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
1490 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
1491 } else {
1492 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
1493 }
1494
1495 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
1496 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
1497 if (ret) {
1498 DEBUG_PRINT_ERROR("Failed to set divx version");
1499 }
1500 } else {
1501 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
1502 }
1503 }
1504
1505 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1506 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1507 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1508 fmt.fmt.pix_mp.pixelformat = capture_capability;
1509 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1510 if (ret) {
1511 /*TODO: How to handle this case */
1512 DEBUG_PRINT_ERROR("Failed to set format on capture port");
1513 }
1514 DEBUG_PRINT_HIGH("Set Format was successful");
1515 if (secure_mode) {
1516 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1517 control.value = 1;
1518 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
1519 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
1520 if (ret) {
1521 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
1522 close(drv_ctx.video_driver_fd);
1523 return OMX_ErrorInsufficientResources;
1524 }
1525 }
1526
1527 /*Get the Buffer requirements for input and output ports*/
1528 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
1529 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
1530 if (secure_mode) {
1531 drv_ctx.op_buf.alignment=SZ_1M;
1532 drv_ctx.ip_buf.alignment=SZ_1M;
1533 } else {
1534 drv_ctx.op_buf.alignment=SZ_4K;
1535 drv_ctx.ip_buf.alignment=SZ_4K;
1536 }
1537 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
1538 drv_ctx.extradata = 0;
1539 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
1540 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
1541 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
1542 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1543 drv_ctx.idr_only_decoding = 0;
1544
1545 m_state = OMX_StateLoaded;
1546 #ifdef DEFAULT_EXTRADATA
1547 if (eRet == OMX_ErrorNone && !secure_mode)
1548 enable_extradata(DEFAULT_EXTRADATA, true, true);
1549 #endif
1550 eRet=get_buffer_req(&drv_ctx.ip_buf);
1551 DEBUG_PRINT_HIGH("Input Buffer Size =%d",drv_ctx.ip_buf.buffer_size);
1552 get_buffer_req(&drv_ctx.op_buf);
1553 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
1554 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC) {
1555 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
1556 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
1557 h264_scratch.nFilledLen = 0;
1558 h264_scratch.nOffset = 0;
1559
1560 if (h264_scratch.pBuffer == NULL) {
1561 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
1562 return OMX_ErrorInsufficientResources;
1563 }
1564 }
1565
1566 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
1567 if (m_frame_parser.mutils == NULL) {
1568 m_frame_parser.mutils = new H264_Utils();
1569
1570 if (m_frame_parser.mutils == NULL) {
1571 DEBUG_PRINT_ERROR("parser utils Allocation failed ");
1572 eRet = OMX_ErrorInsufficientResources;
1573 } else {
1574 m_frame_parser.mutils->initialize_frame_checking_environment();
1575 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
1576 }
1577 }
1578
1579 h264_parser = new h264_stream_parser();
1580 if (!h264_parser) {
1581 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
1582 eRet = OMX_ErrorInsufficientResources;
1583 }
1584 }
1585
1586 if (pipe(fds)) {
1587 DEBUG_PRINT_ERROR("pipe creation failed");
1588 eRet = OMX_ErrorInsufficientResources;
1589 } else {
1590 int temp1[2];
1591 if (fds[0] == 0 || fds[1] == 0) {
1592 if (pipe (temp1)) {
1593 DEBUG_PRINT_ERROR("pipe creation failed");
1594 return OMX_ErrorInsufficientResources;
1595 }
1596 //close (fds[0]);
1597 //close (fds[1]);
1598 fds[0] = temp1 [0];
1599 fds[1] = temp1 [1];
1600 }
1601 m_pipe_in = fds[0];
1602 m_pipe_out = fds[1];
1603 r = pthread_create(&msg_thread_id,0,message_thread,this);
1604
1605 if (r < 0) {
1606 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
1607 eRet = OMX_ErrorInsufficientResources;
1608 }
1609 }
1610 }
1611
1612 if (eRet != OMX_ErrorNone) {
1613 DEBUG_PRINT_ERROR("Component Init Failed");
1614 DEBUG_PRINT_HIGH("Calling VDEC_IOCTL_STOP_NEXT_MSG");
1615 (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
1616 NULL);
1617 DEBUG_PRINT_HIGH("Calling close() on Video Driver");
1618 close (drv_ctx.video_driver_fd);
1619 drv_ctx.video_driver_fd = -1;
1620 } else {
1621 DEBUG_PRINT_HIGH("omx_vdec::component_init() success");
1622 }
1623 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
1624 return eRet;
1625 }
1626
1627 /* ======================================================================
1628 FUNCTION
1629 omx_vdec::GetComponentVersion
1630
1631 DESCRIPTION
1632 Returns the component version.
1633
1634 PARAMETERS
1635 TBD.
1636
1637 RETURN VALUE
1638 OMX_ErrorNone.
1639
1640 ========================================================================== */
get_component_version(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STRING componentName,OMX_OUT OMX_VERSIONTYPE * componentVersion,OMX_OUT OMX_VERSIONTYPE * specVersion,OMX_OUT OMX_UUIDTYPE * componentUUID)1641 OMX_ERRORTYPE omx_vdec::get_component_version
1642 (
1643 OMX_IN OMX_HANDLETYPE hComp,
1644 OMX_OUT OMX_STRING componentName,
1645 OMX_OUT OMX_VERSIONTYPE* componentVersion,
1646 OMX_OUT OMX_VERSIONTYPE* specVersion,
1647 OMX_OUT OMX_UUIDTYPE* componentUUID
1648 )
1649 {
1650 if (m_state == OMX_StateInvalid) {
1651 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
1652 return OMX_ErrorInvalidState;
1653 }
1654 /* TBD -- Return the proper version */
1655 if (specVersion) {
1656 specVersion->nVersion = OMX_SPEC_VERSION;
1657 }
1658 return OMX_ErrorNone;
1659 }
1660 /* ======================================================================
1661 FUNCTION
1662 omx_vdec::SendCommand
1663
1664 DESCRIPTION
1665 Returns zero if all the buffers released..
1666
1667 PARAMETERS
1668 None.
1669
1670 RETURN VALUE
1671 true/false
1672
1673 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1674 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
1675 OMX_IN OMX_COMMANDTYPE cmd,
1676 OMX_IN OMX_U32 param1,
1677 OMX_IN OMX_PTR cmdData
1678 )
1679 {
1680 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
1681 if (m_state == OMX_StateInvalid) {
1682 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
1683 return OMX_ErrorInvalidState;
1684 }
1685 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
1686 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
1687 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
1688 "to invalid port: %lu", param1);
1689 return OMX_ErrorBadPortIndex;
1690 }
1691 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
1692 sem_wait(&m_cmd_lock);
1693 DEBUG_PRINT_LOW("send_command: Command Processed");
1694 return OMX_ErrorNone;
1695 }
1696
1697 /* ======================================================================
1698 FUNCTION
1699 omx_vdec::SendCommand
1700
1701 DESCRIPTION
1702 Returns zero if all the buffers released..
1703
1704 PARAMETERS
1705 None.
1706
1707 RETURN VALUE
1708 true/false
1709
1710 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1711 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
1712 OMX_IN OMX_COMMANDTYPE cmd,
1713 OMX_IN OMX_U32 param1,
1714 OMX_IN OMX_PTR cmdData
1715 )
1716 {
1717 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1718 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
1719 int bFlag = 1,sem_posted = 0,ret=0;
1720
1721 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
1722 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
1723 m_state, eState);
1724
1725 if (cmd == OMX_CommandStateSet) {
1726 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
1727 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
1728 /***************************/
1729 /* Current State is Loaded */
1730 /***************************/
1731 if (m_state == OMX_StateLoaded) {
1732 if (eState == OMX_StateIdle) {
1733 //if all buffers are allocated or all ports disabled
1734 if (allocate_done() ||
1735 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
1736 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
1737 } else {
1738 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
1739 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
1740 // Skip the event notification
1741 bFlag = 0;
1742 }
1743 }
1744 /* Requesting transition from Loaded to Loaded */
1745 else if (eState == OMX_StateLoaded) {
1746 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
1747 post_event(OMX_EventError,OMX_ErrorSameState,\
1748 OMX_COMPONENT_GENERATE_EVENT);
1749 eRet = OMX_ErrorSameState;
1750 }
1751 /* Requesting transition from Loaded to WaitForResources */
1752 else if (eState == OMX_StateWaitForResources) {
1753 /* Since error is None , we will post an event
1754 at the end of this function definition */
1755 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
1756 }
1757 /* Requesting transition from Loaded to Executing */
1758 else if (eState == OMX_StateExecuting) {
1759 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
1760 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1761 OMX_COMPONENT_GENERATE_EVENT);
1762 eRet = OMX_ErrorIncorrectStateTransition;
1763 }
1764 /* Requesting transition from Loaded to Pause */
1765 else if (eState == OMX_StatePause) {
1766 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
1767 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1768 OMX_COMPONENT_GENERATE_EVENT);
1769 eRet = OMX_ErrorIncorrectStateTransition;
1770 }
1771 /* Requesting transition from Loaded to Invalid */
1772 else if (eState == OMX_StateInvalid) {
1773 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
1774 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1775 eRet = OMX_ErrorInvalidState;
1776 } else {
1777 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
1778 eState);
1779 eRet = OMX_ErrorBadParameter;
1780 }
1781 }
1782
1783 /***************************/
1784 /* Current State is IDLE */
1785 /***************************/
1786 else if (m_state == OMX_StateIdle) {
1787 if (eState == OMX_StateLoaded) {
1788 if (release_done()) {
1789 /*
1790 Since error is None , we will post an event at the end
1791 of this function definition
1792 */
1793 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
1794 } else {
1795 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
1796 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
1797 // Skip the event notification
1798 bFlag = 0;
1799 }
1800 }
1801 /* Requesting transition from Idle to Executing */
1802 else if (eState == OMX_StateExecuting) {
1803 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
1804 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
1805 bFlag = 1;
1806 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
1807 m_state=OMX_StateExecuting;
1808 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
1809 }
1810 /* Requesting transition from Idle to Idle */
1811 else if (eState == OMX_StateIdle) {
1812 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
1813 post_event(OMX_EventError,OMX_ErrorSameState,\
1814 OMX_COMPONENT_GENERATE_EVENT);
1815 eRet = OMX_ErrorSameState;
1816 }
1817 /* Requesting transition from Idle to WaitForResources */
1818 else if (eState == OMX_StateWaitForResources) {
1819 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
1820 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1821 OMX_COMPONENT_GENERATE_EVENT);
1822 eRet = OMX_ErrorIncorrectStateTransition;
1823 }
1824 /* Requesting transition from Idle to Pause */
1825 else if (eState == OMX_StatePause) {
1826 /*To pause the Video core we need to start the driver*/
1827 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
1828 NULL) < */0) {
1829 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
1830 omx_report_error ();
1831 eRet = OMX_ErrorHardware;
1832 } else {
1833 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
1834 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
1835 bFlag = 0;
1836 }
1837 }
1838 /* Requesting transition from Idle to Invalid */
1839 else if (eState == OMX_StateInvalid) {
1840 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
1841 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1842 eRet = OMX_ErrorInvalidState;
1843 } else {
1844 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
1845 eRet = OMX_ErrorBadParameter;
1846 }
1847 }
1848
1849 /******************************/
1850 /* Current State is Executing */
1851 /******************************/
1852 else if (m_state == OMX_StateExecuting) {
1853 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
1854 /* Requesting transition from Executing to Idle */
1855 if (eState == OMX_StateIdle) {
1856 /* Since error is None , we will post an event
1857 at the end of this function definition
1858 */
1859 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
1860 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
1861 if (!sem_posted) {
1862 sem_posted = 1;
1863 sem_post (&m_cmd_lock);
1864 execute_omx_flush(OMX_ALL);
1865 }
1866 bFlag = 0;
1867 }
1868 /* Requesting transition from Executing to Paused */
1869 else if (eState == OMX_StatePause) {
1870 DEBUG_PRINT_LOW("PAUSE Command Issued");
1871 m_state = OMX_StatePause;
1872 bFlag = 1;
1873 }
1874 /* Requesting transition from Executing to Loaded */
1875 else if (eState == OMX_StateLoaded) {
1876 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
1877 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1878 OMX_COMPONENT_GENERATE_EVENT);
1879 eRet = OMX_ErrorIncorrectStateTransition;
1880 }
1881 /* Requesting transition from Executing to WaitForResources */
1882 else if (eState == OMX_StateWaitForResources) {
1883 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
1884 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1885 OMX_COMPONENT_GENERATE_EVENT);
1886 eRet = OMX_ErrorIncorrectStateTransition;
1887 }
1888 /* Requesting transition from Executing to Executing */
1889 else if (eState == OMX_StateExecuting) {
1890 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
1891 post_event(OMX_EventError,OMX_ErrorSameState,\
1892 OMX_COMPONENT_GENERATE_EVENT);
1893 eRet = OMX_ErrorSameState;
1894 }
1895 /* Requesting transition from Executing to Invalid */
1896 else if (eState == OMX_StateInvalid) {
1897 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
1898 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1899 eRet = OMX_ErrorInvalidState;
1900 } else {
1901 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
1902 eRet = OMX_ErrorBadParameter;
1903 }
1904 }
1905 /***************************/
1906 /* Current State is Pause */
1907 /***************************/
1908 else if (m_state == OMX_StatePause) {
1909 /* Requesting transition from Pause to Executing */
1910 if (eState == OMX_StateExecuting) {
1911 DEBUG_PRINT_LOW("Pause --> Executing");
1912 m_state = OMX_StateExecuting;
1913 bFlag = 1;
1914 }
1915 /* Requesting transition from Pause to Idle */
1916 else if (eState == OMX_StateIdle) {
1917 /* Since error is None , we will post an event
1918 at the end of this function definition */
1919 DEBUG_PRINT_LOW("Pause --> Idle");
1920 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
1921 if (!sem_posted) {
1922 sem_posted = 1;
1923 sem_post (&m_cmd_lock);
1924 execute_omx_flush(OMX_ALL);
1925 }
1926 bFlag = 0;
1927 }
1928 /* Requesting transition from Pause to loaded */
1929 else if (eState == OMX_StateLoaded) {
1930 DEBUG_PRINT_ERROR("Pause --> loaded");
1931 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1932 OMX_COMPONENT_GENERATE_EVENT);
1933 eRet = OMX_ErrorIncorrectStateTransition;
1934 }
1935 /* Requesting transition from Pause to WaitForResources */
1936 else if (eState == OMX_StateWaitForResources) {
1937 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
1938 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1939 OMX_COMPONENT_GENERATE_EVENT);
1940 eRet = OMX_ErrorIncorrectStateTransition;
1941 }
1942 /* Requesting transition from Pause to Pause */
1943 else if (eState == OMX_StatePause) {
1944 DEBUG_PRINT_ERROR("Pause --> Pause");
1945 post_event(OMX_EventError,OMX_ErrorSameState,\
1946 OMX_COMPONENT_GENERATE_EVENT);
1947 eRet = OMX_ErrorSameState;
1948 }
1949 /* Requesting transition from Pause to Invalid */
1950 else if (eState == OMX_StateInvalid) {
1951 DEBUG_PRINT_ERROR("Pause --> Invalid");
1952 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1953 eRet = OMX_ErrorInvalidState;
1954 } else {
1955 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
1956 eRet = OMX_ErrorBadParameter;
1957 }
1958 }
1959 /***************************/
1960 /* Current State is WaitForResources */
1961 /***************************/
1962 else if (m_state == OMX_StateWaitForResources) {
1963 /* Requesting transition from WaitForResources to Loaded */
1964 if (eState == OMX_StateLoaded) {
1965 /* Since error is None , we will post an event
1966 at the end of this function definition */
1967 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
1968 }
1969 /* Requesting transition from WaitForResources to WaitForResources */
1970 else if (eState == OMX_StateWaitForResources) {
1971 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
1972 post_event(OMX_EventError,OMX_ErrorSameState,
1973 OMX_COMPONENT_GENERATE_EVENT);
1974 eRet = OMX_ErrorSameState;
1975 }
1976 /* Requesting transition from WaitForResources to Executing */
1977 else if (eState == OMX_StateExecuting) {
1978 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
1979 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1980 OMX_COMPONENT_GENERATE_EVENT);
1981 eRet = OMX_ErrorIncorrectStateTransition;
1982 }
1983 /* Requesting transition from WaitForResources to Pause */
1984 else if (eState == OMX_StatePause) {
1985 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
1986 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1987 OMX_COMPONENT_GENERATE_EVENT);
1988 eRet = OMX_ErrorIncorrectStateTransition;
1989 }
1990 /* Requesting transition from WaitForResources to Invalid */
1991 else if (eState == OMX_StateInvalid) {
1992 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
1993 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1994 eRet = OMX_ErrorInvalidState;
1995 }
1996 /* Requesting transition from WaitForResources to Loaded -
1997 is NOT tested by Khronos TS */
1998
1999 } else {
2000 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2001 eRet = OMX_ErrorBadParameter;
2002 }
2003 }
2004 /********************************/
2005 /* Current State is Invalid */
2006 /*******************************/
2007 else if (m_state == OMX_StateInvalid) {
2008 /* State Transition from Invalid to any state */
2009 if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
2010 eState == OMX_StateIdle || eState == OMX_StateExecuting ||
2011 eState == OMX_StatePause || eState == OMX_StateInvalid) {
2012 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2013 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2014 OMX_COMPONENT_GENERATE_EVENT);
2015 eRet = OMX_ErrorInvalidState;
2016 }
2017 } else if (cmd == OMX_CommandFlush) {
2018 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2019 "with param1: %lu", param1);
2020 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2021 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2022 }
2023 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2024 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2025 }
2026 if (!sem_posted) {
2027 sem_posted = 1;
2028 DEBUG_PRINT_LOW("Set the Semaphore");
2029 sem_post (&m_cmd_lock);
2030 execute_omx_flush(param1);
2031 }
2032 bFlag = 0;
2033 } else if ( cmd == OMX_CommandPortEnable) {
2034 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2035 "with param1: %lu", param1);
2036 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2037 m_inp_bEnabled = OMX_TRUE;
2038
2039 if ( (m_state == OMX_StateLoaded &&
2040 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2041 || allocate_input_done()) {
2042 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2043 OMX_COMPONENT_GENERATE_EVENT);
2044 } else {
2045 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2046 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2047 // Skip the event notification
2048 bFlag = 0;
2049 }
2050 }
2051 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2052 DEBUG_PRINT_LOW("Enable output Port command recieved");
2053 m_out_bEnabled = OMX_TRUE;
2054
2055 if ( (m_state == OMX_StateLoaded &&
2056 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2057 || (allocate_output_done())) {
2058 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2059 OMX_COMPONENT_GENERATE_EVENT);
2060
2061 } else {
2062 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2063 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2064 // Skip the event notification
2065 bFlag = 0;
2066 }
2067 }
2068 } else if (cmd == OMX_CommandPortDisable) {
2069 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
2070 "with param1: %lu", param1);
2071 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2072 m_inp_bEnabled = OMX_FALSE;
2073 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2074 && release_input_done()) {
2075 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2076 OMX_COMPONENT_GENERATE_EVENT);
2077 } else {
2078 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2079 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2080 if (!sem_posted) {
2081 sem_posted = 1;
2082 sem_post (&m_cmd_lock);
2083 }
2084 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2085 }
2086
2087 // Skip the event notification
2088 bFlag = 0;
2089 }
2090 }
2091 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2092 m_out_bEnabled = OMX_FALSE;
2093 DEBUG_PRINT_LOW("Disable output Port command recieved");
2094 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2095 && release_output_done()) {
2096 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2097 OMX_COMPONENT_GENERATE_EVENT);
2098 } else {
2099 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2100 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2101 if (!sem_posted) {
2102 sem_posted = 1;
2103 sem_post (&m_cmd_lock);
2104 }
2105 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2106 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2107 }
2108 // Skip the event notification
2109 bFlag = 0;
2110
2111 }
2112 }
2113 } else {
2114 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
2115 eRet = OMX_ErrorNotImplemented;
2116 }
2117 if (eRet == OMX_ErrorNone && bFlag) {
2118 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2119 }
2120 if (!sem_posted) {
2121 sem_post(&m_cmd_lock);
2122 }
2123
2124 return eRet;
2125 }
2126
2127 /* ======================================================================
2128 FUNCTION
2129 omx_vdec::ExecuteOmxFlush
2130
2131 DESCRIPTION
2132 Executes the OMX flush.
2133
2134 PARAMETERS
2135 flushtype - input flush(1)/output flush(0)/ both.
2136
2137 RETURN VALUE
2138 true/false
2139
2140 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)2141 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
2142 {
2143 bool bRet = false;
2144 struct v4l2_plane plane;
2145 struct v4l2_buffer v4l2_buf;
2146 struct v4l2_decoder_cmd dec;
2147 DEBUG_PRINT_LOW("in %s", __func__);
2148 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
2149 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
2150 switch (flushType) {
2151 case OMX_CORE_INPUT_PORT_INDEX:
2152 input_flush_progress = true;
2153 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT;
2154 break;
2155 case OMX_CORE_OUTPUT_PORT_INDEX:
2156 output_flush_progress = true;
2157 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2158 break;
2159 default:
2160 input_flush_progress = true;
2161 output_flush_progress = true;
2162 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT |
2163 V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2164 }
2165
2166 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
2167 DEBUG_PRINT_ERROR("Flush Port (%lu) Failed ", flushType);
2168 bRet = false;
2169 }
2170
2171 return bRet;
2172 }
2173 /*=========================================================================
2174 FUNCTION : execute_output_flush
2175
2176 DESCRIPTION
2177 Executes the OMX flush at OUTPUT PORT.
2178
2179 PARAMETERS
2180 None.
2181
2182 RETURN VALUE
2183 true/false
2184 ==========================================================================*/
execute_output_flush()2185 bool omx_vdec::execute_output_flush()
2186 {
2187 unsigned p1 = 0; // Parameter - 1
2188 unsigned p2 = 0; // Parameter - 2
2189 unsigned ident = 0;
2190 bool bRet = true;
2191
2192 /*Generate FBD for all Buffers in the FTBq*/
2193 pthread_mutex_lock(&m_lock);
2194 DEBUG_PRINT_LOW("Initiate Output Flush");
2195 while (m_ftb_q.m_size) {
2196 DEBUG_PRINT_LOW("Buffer queue size %d pending buf cnt %d",
2197 m_ftb_q.m_size,pending_output_buffers);
2198 m_ftb_q.pop_entry(&p1,&p2,&ident);
2199 DEBUG_PRINT_LOW("ID(%x) P1(%x) P2(%x)", ident, p1, p2);
2200 if (ident == m_fill_output_msg ) {
2201 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2202 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
2203 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2204 }
2205 }
2206 pthread_mutex_unlock(&m_lock);
2207 output_flush_progress = false;
2208
2209 if (arbitrary_bytes) {
2210 prev_ts = LLONG_MAX;
2211 rst_prev_ts = true;
2212 }
2213 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
2214 return bRet;
2215 }
2216 /*=========================================================================
2217 FUNCTION : execute_input_flush
2218
2219 DESCRIPTION
2220 Executes the OMX flush at INPUT PORT.
2221
2222 PARAMETERS
2223 None.
2224
2225 RETURN VALUE
2226 true/false
2227 ==========================================================================*/
execute_input_flush()2228 bool omx_vdec::execute_input_flush()
2229 {
2230 unsigned i =0;
2231 unsigned p1 = 0; // Parameter - 1
2232 unsigned p2 = 0; // Parameter - 2
2233 unsigned ident = 0;
2234 bool bRet = true;
2235
2236 /*Generate EBD for all Buffers in the ETBq*/
2237 DEBUG_PRINT_LOW("Initiate Input Flush");
2238
2239 pthread_mutex_lock(&m_lock);
2240 DEBUG_PRINT_LOW("Check if the Queue is empty");
2241 while (m_etb_q.m_size) {
2242 m_etb_q.pop_entry(&p1,&p2,&ident);
2243
2244 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2245 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
2246 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2247 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
2248 pending_input_buffers++;
2249 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
2250 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
2251 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2252 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
2253 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
2254 (OMX_BUFFERHEADERTYPE *)p1);
2255 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2256 }
2257 }
2258 time_stamp_dts.flush_timestamp();
2259 /*Check if Heap Buffers are to be flushed*/
2260 if (arbitrary_bytes && !(codec_config_flag)) {
2261 DEBUG_PRINT_LOW("Reset all the variables before flusing");
2262 h264_scratch.nFilledLen = 0;
2263 nal_count = 0;
2264 look_ahead_nal = false;
2265 frame_count = 0;
2266 h264_last_au_ts = LLONG_MAX;
2267 h264_last_au_flags = 0;
2268 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
2269 m_demux_entries = 0;
2270 DEBUG_PRINT_LOW("Initialize parser");
2271 if (m_frame_parser.mutils) {
2272 m_frame_parser.mutils->initialize_frame_checking_environment();
2273 }
2274
2275 while (m_input_pending_q.m_size) {
2276 m_input_pending_q.pop_entry(&p1,&p2,&ident);
2277 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
2278 }
2279
2280 if (psource_frame) {
2281 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
2282 psource_frame = NULL;
2283 }
2284
2285 if (pdest_frame) {
2286 pdest_frame->nFilledLen = 0;
2287 m_input_free_q.insert_entry((unsigned) pdest_frame, (unsigned int)NULL,
2288 (unsigned int)NULL);
2289 pdest_frame = NULL;
2290 }
2291 m_frame_parser.flush();
2292 } else if (codec_config_flag) {
2293 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
2294 "is not sent to the driver yet");
2295 }
2296 pthread_mutex_unlock(&m_lock);
2297 input_flush_progress = false;
2298 if (!arbitrary_bytes) {
2299 prev_ts = LLONG_MAX;
2300 rst_prev_ts = true;
2301 }
2302 #ifdef _ANDROID_
2303 if (m_debug_timestamp) {
2304 m_timestamp_list.reset_ts_list();
2305 }
2306 #endif
2307 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
2308 return bRet;
2309 }
2310
2311
2312 /* ======================================================================
2313 FUNCTION
2314 omx_vdec::SendCommandEvent
2315
2316 DESCRIPTION
2317 Send the event to decoder pipe. This is needed to generate the callbacks
2318 in decoder thread context.
2319
2320 PARAMETERS
2321 None.
2322
2323 RETURN VALUE
2324 true/false
2325
2326 ========================================================================== */
post_event(unsigned int p1,unsigned int p2,unsigned int id)2327 bool omx_vdec::post_event(unsigned int p1,
2328 unsigned int p2,
2329 unsigned int id)
2330 {
2331 bool bRet = false;
2332
2333
2334 pthread_mutex_lock(&m_lock);
2335
2336 if (id == m_fill_output_msg ||
2337 id == OMX_COMPONENT_GENERATE_FBD) {
2338 m_ftb_q.insert_entry(p1,p2,id);
2339 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
2340 id == OMX_COMPONENT_GENERATE_EBD ||
2341 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2342 m_etb_q.insert_entry(p1,p2,id);
2343 } else {
2344 m_cmd_q.insert_entry(p1,p2,id);
2345 }
2346
2347 bRet = true;
2348 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
2349 post_message(this, id);
2350
2351 pthread_mutex_unlock(&m_lock);
2352
2353 return bRet;
2354 }
2355
get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)2356 OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
2357 {
2358 OMX_ERRORTYPE eRet = OMX_ErrorNoMore;
2359 if (!profileLevelType)
2360 return OMX_ErrorBadParameter;
2361
2362 if (profileLevelType->nPortIndex == 0) {
2363 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2364 if (profileLevelType->nProfileIndex == 0) {
2365 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
2366 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2367
2368 } else if (profileLevelType->nProfileIndex == 1) {
2369 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
2370 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2371 } else if (profileLevelType->nProfileIndex == 2) {
2372 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
2373 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2374 } else {
2375 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
2376 profileLevelType->nProfileIndex);
2377 eRet = OMX_ErrorNoMore;
2378 }
2379 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2380 // TODO
2381 {
2382 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d",
2383 profileLevelType->nProfileIndex);
2384 eRet = OMX_ErrorNoMore;
2385 }
2386 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
2387 if (profileLevelType->nProfileIndex == 0) {
2388 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
2389 profileLevelType->eLevel = OMX_VIDEO_H263Level70;
2390 } else {
2391 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2392 eRet = OMX_ErrorNoMore;
2393 }
2394 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2395 if (profileLevelType->nProfileIndex == 0) {
2396 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2397 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2398 } else if (profileLevelType->nProfileIndex == 1) {
2399 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2400 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2401 } else {
2402 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2403 eRet = OMX_ErrorNoMore;
2404 }
2405 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
2406 eRet = OMX_ErrorNoMore;
2407 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2408 if (profileLevelType->nProfileIndex == 0) {
2409 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
2410 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2411 } else if (profileLevelType->nProfileIndex == 1) {
2412 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
2413 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2414 } else {
2415 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu", profileLevelType->nProfileIndex);
2416 eRet = OMX_ErrorNoMore;
2417 }
2418 }
2419 } else {
2420 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %lu", profileLevelType->nPortIndex);
2421 eRet = OMX_ErrorBadPortIndex;
2422 }
2423 return eRet;
2424 }
2425
2426 /* ======================================================================
2427 FUNCTION
2428 omx_vdec::GetParameter
2429
2430 DESCRIPTION
2431 OMX Get Parameter method implementation
2432
2433 PARAMETERS
2434 <TBD>.
2435
2436 RETURN VALUE
2437 Error None if successful.
2438
2439 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)2440 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
2441 OMX_IN OMX_INDEXTYPE paramIndex,
2442 OMX_INOUT OMX_PTR paramData)
2443 {
2444 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2445
2446 DEBUG_PRINT_LOW("get_parameter:");
2447 if (m_state == OMX_StateInvalid) {
2448 DEBUG_PRINT_ERROR("Get Param in Invalid State");
2449 return OMX_ErrorInvalidState;
2450 }
2451 if (paramData == NULL) {
2452 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
2453 return OMX_ErrorBadParameter;
2454 }
2455 switch ((unsigned long)paramIndex) {
2456 case OMX_IndexParamPortDefinition:
2457 {
2458 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
2459 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2460 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
2461 eRet = update_portdef(portDefn);
2462 if (eRet == OMX_ErrorNone)
2463 m_port_def = *portDefn;
2464 break;
2465 }
2466 case OMX_IndexParamVideoInit:
2467 {
2468 OMX_PORT_PARAM_TYPE *portParamType =
2469 (OMX_PORT_PARAM_TYPE *) paramData;
2470 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
2471
2472 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2473 portParamType->nSize = sizeof(portParamType);
2474 portParamType->nPorts = 2;
2475 portParamType->nStartPortNumber = 0;
2476 break;
2477 }
2478 case OMX_IndexParamVideoPortFormat:
2479 {
2480 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2481 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2482 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
2483
2484 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
2485 portFmt->nSize = sizeof(portFmt);
2486
2487 if (0 == portFmt->nPortIndex) {
2488 if (0 == portFmt->nIndex) {
2489 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
2490 portFmt->eCompressionFormat = eCompressionFormat;
2491 } else {
2492 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
2493 " NoMore compression formats");
2494 eRet = OMX_ErrorNoMore;
2495 }
2496 } else if (1 == portFmt->nPortIndex) {
2497 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
2498
2499 if (0 == portFmt->nIndex)
2500 portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
2501 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2502 else if (1 == portFmt->nIndex)
2503 portFmt->eColorFormat = OMX_COLOR_FormatYUV420Planar;
2504 else {
2505 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
2506 " NoMore Color formats");
2507 eRet = OMX_ErrorNoMore;
2508 }
2509 DEBUG_PRINT_LOW("returning %d", portFmt->eColorFormat);
2510 } else {
2511 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
2512 (int)portFmt->nPortIndex);
2513 eRet = OMX_ErrorBadPortIndex;
2514 }
2515 break;
2516 }
2517 /*Component should support this port definition*/
2518 case OMX_IndexParamAudioInit:
2519 {
2520 OMX_PORT_PARAM_TYPE *audioPortParamType =
2521 (OMX_PORT_PARAM_TYPE *) paramData;
2522 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
2523 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2524 audioPortParamType->nSize = sizeof(audioPortParamType);
2525 audioPortParamType->nPorts = 0;
2526 audioPortParamType->nStartPortNumber = 0;
2527 break;
2528 }
2529 /*Component should support this port definition*/
2530 case OMX_IndexParamImageInit:
2531 {
2532 OMX_PORT_PARAM_TYPE *imagePortParamType =
2533 (OMX_PORT_PARAM_TYPE *) paramData;
2534 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
2535 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2536 imagePortParamType->nSize = sizeof(imagePortParamType);
2537 imagePortParamType->nPorts = 0;
2538 imagePortParamType->nStartPortNumber = 0;
2539 break;
2540
2541 }
2542 /*Component should support this port definition*/
2543 case OMX_IndexParamOtherInit:
2544 {
2545 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
2546 paramIndex);
2547 eRet =OMX_ErrorUnsupportedIndex;
2548 break;
2549 }
2550 case OMX_IndexParamStandardComponentRole:
2551 {
2552 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2553 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2554 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
2555 comp_role->nSize = sizeof(*comp_role);
2556
2557 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
2558 paramIndex);
2559 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
2560 OMX_MAX_STRINGNAME_SIZE);
2561 break;
2562 }
2563 /* Added for parameter test */
2564 case OMX_IndexParamPriorityMgmt:
2565 {
2566
2567 OMX_PRIORITYMGMTTYPE *priorityMgmType =
2568 (OMX_PRIORITYMGMTTYPE *) paramData;
2569 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
2570 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
2571 priorityMgmType->nSize = sizeof(priorityMgmType);
2572
2573 break;
2574 }
2575 /* Added for parameter test */
2576 case OMX_IndexParamCompBufferSupplier:
2577 {
2578 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
2579 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
2580 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
2581
2582 bufferSupplierType->nSize = sizeof(bufferSupplierType);
2583 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
2584 if (0 == bufferSupplierType->nPortIndex)
2585 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2586 else if (1 == bufferSupplierType->nPortIndex)
2587 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2588 else
2589 eRet = OMX_ErrorBadPortIndex;
2590
2591
2592 break;
2593 }
2594 case OMX_IndexParamVideoAvc:
2595 {
2596 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
2597 paramIndex);
2598 break;
2599 }
2600 case OMX_IndexParamVideoH263:
2601 {
2602 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
2603 paramIndex);
2604 break;
2605 }
2606 case OMX_IndexParamVideoMpeg4:
2607 {
2608 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
2609 paramIndex);
2610 break;
2611 }
2612 case OMX_IndexParamVideoMpeg2:
2613 {
2614 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
2615 paramIndex);
2616 break;
2617 }
2618 case OMX_IndexParamVideoProfileLevelQuerySupported:
2619 {
2620 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
2621 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
2622 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
2623 eRet = get_supported_profile_level_for_1080p(profileLevelType);
2624 break;
2625 }
2626 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
2627 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
2628 {
2629 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
2630 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
2631 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
2632
2633 if (secure_mode) {
2634 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
2635 GRALLOC_USAGE_PRIVATE_UNCACHED);
2636 } else {
2637 #ifdef _HEVC_USE_ADSP_HEAP_
2638 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2639 #else
2640 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2641 #endif
2642 DEBUG_PRINT_HIGH("nativeBuffersUsage->nUsage %x", (unsigned int)nativeBuffersUsage->nUsage);
2643 }
2644 } else {
2645 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
2646 eRet = OMX_ErrorBadParameter;
2647 }
2648 }
2649 break;
2650 #endif
2651
2652 default:
2653 {
2654 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
2655 eRet =OMX_ErrorUnsupportedIndex;
2656 }
2657
2658 }
2659
2660 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
2661 drv_ctx.video_resolution.frame_width,
2662 drv_ctx.video_resolution.frame_height,
2663 drv_ctx.video_resolution.stride,
2664 drv_ctx.video_resolution.scan_lines);
2665
2666 return eRet;
2667 }
2668
2669 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)2670 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
2671 {
2672 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
2673 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2674 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
2675
2676 if ((params == NULL) ||
2677 (params->nativeBuffer == NULL) ||
2678 (params->nativeBuffer->handle == NULL) ||
2679 !m_enable_android_native_buffers)
2680 return OMX_ErrorBadParameter;
2681 m_use_android_native_buffers = OMX_TRUE;
2682 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
2683 private_handle_t *handle = (private_handle_t *)nBuf->handle;
2684 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
2685 OMX_U8 *buffer = NULL;
2686 if (!secure_mode) {
2687 buffer = (OMX_U8*)mmap(0, handle->size,
2688 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
2689 if (buffer == MAP_FAILED) {
2690 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
2691 return OMX_ErrorInsufficientResources;
2692 }
2693 }
2694 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
2695 } else {
2696 eRet = OMX_ErrorBadParameter;
2697 }
2698 return eRet;
2699 }
2700 #endif
2701 /* ======================================================================
2702 FUNCTION
2703 omx_vdec::Setparameter
2704
2705 DESCRIPTION
2706 OMX Set Parameter method implementation.
2707
2708 PARAMETERS
2709 <TBD>.
2710
2711 RETURN VALUE
2712 OMX Error None if successful.
2713
2714 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)2715 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
2716 OMX_IN OMX_INDEXTYPE paramIndex,
2717 OMX_IN OMX_PTR paramData)
2718 {
2719 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2720 int ret=0;
2721 struct v4l2_format fmt;
2722 if (m_state == OMX_StateInvalid) {
2723 DEBUG_PRINT_ERROR("Set Param in Invalid State");
2724 return OMX_ErrorInvalidState;
2725 }
2726 if (paramData == NULL) {
2727 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
2728 return OMX_ErrorBadParameter;
2729 }
2730 if ((m_state != OMX_StateLoaded) &&
2731 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
2732 (m_out_bEnabled == OMX_TRUE) &&
2733 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
2734 (m_inp_bEnabled == OMX_TRUE)) {
2735 DEBUG_PRINT_ERROR("Set Param in Invalid State");
2736 return OMX_ErrorIncorrectStateOperation;
2737 }
2738 switch ((unsigned long)paramIndex) {
2739 case OMX_IndexParamPortDefinition:
2740 {
2741 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2742 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2743 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
2744 //been called.
2745 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
2746 (int)portDefn->format.video.nFrameHeight,
2747 (int)portDefn->format.video.nFrameWidth);
2748 if (OMX_DirOutput == portDefn->eDir) {
2749 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
2750 m_display_id = portDefn->format.video.pNativeWindow;
2751 unsigned int buffer_size;
2752 if (!client_buffers.get_buffer_req(buffer_size)) {
2753 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
2754 eRet = OMX_ErrorBadParameter;
2755 } else {
2756 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
2757 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) {
2758 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
2759 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
2760 eRet = set_buffer_req(&drv_ctx.op_buf);
2761 if (eRet == OMX_ErrorNone)
2762 m_port_def = *portDefn;
2763 } else {
2764 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%lu: %lu)",
2765 drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size,
2766 portDefn->nBufferCountActual, portDefn->nBufferSize);
2767 eRet = OMX_ErrorBadParameter;
2768 }
2769 }
2770 } else if (OMX_DirInput == portDefn->eDir) {
2771 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
2772 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
2773 // Frame rate only should be set if this is a "known value" or to
2774 // activate ts prediction logic (arbitrary mode only) sending input
2775 // timestamps with max value (LLONG_MAX).
2776 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %lu",
2777 portDefn->format.video.xFramerate >> 16);
2778 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
2779 drv_ctx.frame_rate.fps_denominator);
2780 if (!drv_ctx.frame_rate.fps_numerator) {
2781 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
2782 drv_ctx.frame_rate.fps_numerator = 30;
2783 }
2784 if (drv_ctx.frame_rate.fps_denominator)
2785 drv_ctx.frame_rate.fps_numerator = (int)
2786 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
2787 drv_ctx.frame_rate.fps_denominator = 1;
2788 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
2789 drv_ctx.frame_rate.fps_numerator;
2790 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
2791 frm_int, drv_ctx.frame_rate.fps_numerator /
2792 (float)drv_ctx.frame_rate.fps_denominator);
2793 }
2794 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
2795 if (drv_ctx.video_resolution.frame_height !=
2796 portDefn->format.video.nFrameHeight ||
2797 drv_ctx.video_resolution.frame_width !=
2798 portDefn->format.video.nFrameWidth) {
2799 DEBUG_PRINT_LOW("SetParam IP: WxH(%d x %d)",
2800 portDefn->format.video.nFrameWidth,
2801 portDefn->format.video.nFrameHeight);
2802 if (portDefn->format.video.nFrameHeight != 0x0 &&
2803 portDefn->format.video.nFrameWidth != 0x0) {
2804 update_resolution(portDefn->format.video.nFrameWidth,
2805 portDefn->format.video.nFrameHeight);
2806 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2807 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2808 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2809 fmt.fmt.pix_mp.pixelformat = output_capability;
2810 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
2811 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2812 if (ret) {
2813 DEBUG_PRINT_ERROR("Set Resolution failed");
2814 eRet = OMX_ErrorUnsupportedSetting;
2815 } else
2816 eRet = get_buffer_req(&drv_ctx.op_buf);
2817 }
2818 } else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
2819 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
2820 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
2821 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
2822 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
2823 (~(buffer_prop->alignment - 1));
2824 eRet = set_buffer_req(buffer_prop);
2825 } else {
2826 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%lu: %lu)",
2827 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size,
2828 portDefn->nBufferCountActual, portDefn->nBufferSize);
2829 eRet = OMX_ErrorBadParameter;
2830 }
2831 } else if (portDefn->eDir == OMX_DirMax) {
2832 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
2833 (int)portDefn->nPortIndex);
2834 eRet = OMX_ErrorBadPortIndex;
2835 }
2836 }
2837 break;
2838 case OMX_IndexParamVideoPortFormat:
2839 {
2840 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2841 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2842 int ret=0;
2843 struct v4l2_format fmt;
2844 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d",
2845 portFmt->eColorFormat);
2846
2847 if (1 == portFmt->nPortIndex) {
2848 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2849 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2850 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2851 fmt.fmt.pix_mp.pixelformat = capture_capability;
2852 enum vdec_output_fromat op_format;
2853 if ((portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
2854 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) ||
2855 (portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar))
2856 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
2857 else if (portFmt->eColorFormat ==
2858 (OMX_COLOR_FORMATTYPE)
2859 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka)
2860 op_format = VDEC_YUV_FORMAT_TILE_4x2;
2861 else
2862 eRet = OMX_ErrorBadParameter;
2863
2864 if (eRet == OMX_ErrorNone) {
2865 drv_ctx.output_format = op_format;
2866 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2867 if (ret) {
2868 DEBUG_PRINT_ERROR("Set output format failed");
2869 eRet = OMX_ErrorUnsupportedSetting;
2870 /*TODO: How to handle this case */
2871 } else {
2872 eRet = get_buffer_req(&drv_ctx.op_buf);
2873 }
2874 }
2875 if (eRet == OMX_ErrorNone) {
2876 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
2877 DEBUG_PRINT_ERROR("Set color format failed");
2878 eRet = OMX_ErrorBadParameter;
2879 }
2880 }
2881 }
2882 }
2883 break;
2884
2885 case OMX_QcomIndexPortDefn:
2886 {
2887 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
2888 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
2889 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d",
2890 portFmt->nFramePackingFormat);
2891
2892 /* Input port */
2893 if (portFmt->nPortIndex == 0) {
2894 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
2895 if (secure_mode) {
2896 arbitrary_bytes = false;
2897 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session");
2898 eRet = OMX_ErrorUnsupportedSetting;
2899 } else {
2900 arbitrary_bytes = true;
2901 }
2902 } else if (portFmt->nFramePackingFormat ==
2903 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
2904 arbitrary_bytes = false;
2905 } else {
2906 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %lu",
2907 portFmt->nFramePackingFormat);
2908 eRet = OMX_ErrorUnsupportedSetting;
2909 }
2910 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
2911 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
2912 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
2913 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
2914 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
2915 m_out_mem_region_smi = OMX_TRUE;
2916 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
2917 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
2918 m_use_output_pmem = OMX_TRUE;
2919 }
2920 }
2921 }
2922 }
2923 break;
2924
2925 case OMX_IndexParamStandardComponentRole:
2926 {
2927 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2928 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2929 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
2930 comp_role->cRole);
2931
2932 if ((m_state == OMX_StateLoaded)&&
2933 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
2934 DEBUG_PRINT_LOW("Set Parameter called in valid state");
2935 } else {
2936 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
2937 return OMX_ErrorIncorrectStateOperation;
2938 }
2939
2940 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2941 if (!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2942 strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2943 } else {
2944 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2945 eRet =OMX_ErrorUnsupportedSetting;
2946 }
2947 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2948 if (!strncmp((char*)comp_role->cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
2949 strlcpy((char*)m_cRole,"video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2950 } else {
2951 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2952 eRet =OMX_ErrorUnsupportedSetting;
2953 }
2954 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2955 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2956 strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
2957 } else {
2958 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2959 eRet = OMX_ErrorUnsupportedSetting;
2960 }
2961 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
2962 if (!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
2963 strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2964 } else {
2965 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2966 eRet =OMX_ErrorUnsupportedSetting;
2967 }
2968 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2969 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2970 strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
2971 } else {
2972 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2973 eRet = OMX_ErrorUnsupportedSetting;
2974 }
2975 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
2976 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
2977 ) {
2978 if (!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) {
2979 strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2980 } else {
2981 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2982 eRet =OMX_ErrorUnsupportedSetting;
2983 }
2984 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
2985 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
2986 ) {
2987 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) {
2988 strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2989 } else {
2990 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2991 eRet =OMX_ErrorUnsupportedSetting;
2992 }
2993 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
2994 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
2995 (!strncmp((const char*)comp_role->cRole,"video_decoder.vpx",OMX_MAX_STRINGNAME_SIZE))) {
2996 strlcpy((char*)m_cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2997 } else {
2998 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
2999 eRet = OMX_ErrorUnsupportedSetting;
3000 }
3001 } else {
3002 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
3003 eRet = OMX_ErrorInvalidComponentName;
3004 }
3005 break;
3006 }
3007
3008 case OMX_IndexParamPriorityMgmt:
3009 {
3010 if (m_state != OMX_StateLoaded) {
3011 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
3012 return OMX_ErrorIncorrectStateOperation;
3013 }
3014 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
3015 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d",
3016 priorityMgmtype->nGroupID);
3017
3018 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d",
3019 priorityMgmtype->nGroupPriority);
3020
3021 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
3022 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
3023
3024 break;
3025 }
3026
3027 case OMX_IndexParamCompBufferSupplier:
3028 {
3029 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3030 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
3031 bufferSupplierType->eBufferSupplier);
3032 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
3033 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
3034
3035 else
3036
3037 eRet = OMX_ErrorBadPortIndex;
3038
3039 break;
3040
3041 }
3042 case OMX_IndexParamVideoAvc:
3043 {
3044 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
3045 paramIndex);
3046 break;
3047 }
3048 case OMX_IndexParamVideoH263:
3049 {
3050 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
3051 paramIndex);
3052 break;
3053 }
3054 case OMX_IndexParamVideoMpeg4:
3055 {
3056 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
3057 paramIndex);
3058 break;
3059 }
3060 case OMX_IndexParamVideoMpeg2:
3061 {
3062 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
3063 paramIndex);
3064 break;
3065 }
3066 case OMX_QcomIndexParamVideoDecoderPictureOrder:
3067 {
3068 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
3069 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
3070 struct v4l2_control control;
3071 int pic_order,rc=0;
3072 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
3073 pictureOrder->eOutputPictureOrder);
3074 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
3075 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
3076 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
3077 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3078 time_stamp_dts.set_timestamp_reorder_mode(false);
3079 } else
3080 eRet = OMX_ErrorBadParameter;
3081 if (eRet == OMX_ErrorNone) {
3082 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3083 control.value = pic_order;
3084 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3085 if (rc) {
3086 DEBUG_PRINT_ERROR("Set picture order failed");
3087 eRet = OMX_ErrorUnsupportedSetting;
3088 }
3089 }
3090 break;
3091 }
3092 case OMX_QcomIndexParamConcealMBMapExtraData:
3093 if (!secure_mode)
3094 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
3095 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3096 else {
3097 DEBUG_PRINT_ERROR("secure mode setting not supported");
3098 eRet = OMX_ErrorUnsupportedSetting;
3099 }
3100 break;
3101 case OMX_QcomIndexParamFrameInfoExtraData:
3102 {
3103 if (!secure_mode)
3104 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
3105 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3106 else {
3107 DEBUG_PRINT_ERROR("secure mode setting not supported");
3108 eRet = OMX_ErrorUnsupportedSetting;
3109 }
3110 break;
3111 }
3112 case OMX_QcomIndexParamInterlaceExtraData:
3113 if (!secure_mode)
3114 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
3115 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3116 else {
3117 DEBUG_PRINT_ERROR("secure mode setting not supported");
3118 eRet = OMX_ErrorUnsupportedSetting;
3119 }
3120 break;
3121 case OMX_QcomIndexParamH264TimeInfo:
3122 if (!secure_mode)
3123 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
3124 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3125 else {
3126 DEBUG_PRINT_ERROR("secure mode setting not supported");
3127 eRet = OMX_ErrorUnsupportedSetting;
3128 }
3129 break;
3130 case OMX_QcomIndexParamVideoDivx:
3131 {
3132 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
3133 }
3134 break;
3135 case OMX_QcomIndexPlatformPvt:
3136 {
3137 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
3138 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
3139 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3140 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
3141 eRet = OMX_ErrorUnsupportedSetting;
3142 } else {
3143 m_out_pvt_entry_pmem = OMX_TRUE;
3144 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
3145 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
3146 m_use_output_pmem = OMX_TRUE;
3147 }
3148 }
3149
3150 }
3151 break;
3152 case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
3153 {
3154 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
3155 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
3156 struct v4l2_control control;
3157 int rc;
3158 drv_ctx.idr_only_decoding = 1;
3159 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3160 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3161 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3162 if (rc) {
3163 DEBUG_PRINT_ERROR("Set picture order failed");
3164 eRet = OMX_ErrorUnsupportedSetting;
3165 } else {
3166 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
3167 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
3168 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3169 if (rc) {
3170 DEBUG_PRINT_ERROR("Sync frame setting failed");
3171 eRet = OMX_ErrorUnsupportedSetting;
3172 }
3173 }
3174 }
3175 break;
3176
3177 case OMX_QcomIndexParamIndexExtraDataType:
3178 {
3179 if (!secure_mode) {
3180 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
3181 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
3182 (extradataIndexType->bEnabled == OMX_TRUE) &&
3183 (extradataIndexType->nPortIndex == 1)) {
3184 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
3185 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
3186
3187 }
3188 }
3189 }
3190 break;
3191 case OMX_QcomIndexParamEnableSmoothStreaming:
3192 {
3193 struct v4l2_control control;
3194 struct v4l2_format fmt;
3195 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3196 control.value = 1;
3197 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3198 if (rc < 0) {
3199 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3200 eRet = OMX_ErrorHardware;
3201 }
3202 }
3203 break;
3204 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3205 /* Need to allow following two set_parameters even in Idle
3206 * state. This is ANDROID architecture which is not in sync
3207 * with openmax standard. */
3208 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
3209 {
3210 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
3211 if (enableNativeBuffers) {
3212 m_enable_android_native_buffers = enableNativeBuffers->enable;
3213 }
3214 }
3215 break;
3216 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
3217 {
3218 eRet = use_android_native_buffer(hComp, paramData);
3219 }
3220 break;
3221 #endif
3222 case OMX_QcomIndexParamEnableTimeStampReorder:
3223 {
3224 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
3225 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
3226 if (reorder->bEnable == OMX_TRUE) {
3227 frm_int =0;
3228 time_stamp_dts.set_timestamp_reorder_mode(true);
3229 } else
3230 time_stamp_dts.set_timestamp_reorder_mode(false);
3231 } else {
3232 time_stamp_dts.set_timestamp_reorder_mode(false);
3233 if (reorder->bEnable == OMX_TRUE) {
3234 eRet = OMX_ErrorUnsupportedSetting;
3235 }
3236 }
3237 }
3238 break;
3239 default:
3240 {
3241 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
3242 eRet = OMX_ErrorUnsupportedIndex;
3243 }
3244 }
3245 return eRet;
3246 }
3247
3248 /* ======================================================================
3249 FUNCTION
3250 omx_vdec::GetConfig
3251
3252 DESCRIPTION
3253 OMX Get Config Method implementation.
3254
3255 PARAMETERS
3256 <TBD>.
3257
3258 RETURN VALUE
3259 OMX Error None if successful.
3260
3261 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)3262 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
3263 OMX_IN OMX_INDEXTYPE configIndex,
3264 OMX_INOUT OMX_PTR configData)
3265 {
3266 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3267
3268 if (m_state == OMX_StateInvalid) {
3269 DEBUG_PRINT_ERROR("Get Config in Invalid State");
3270 return OMX_ErrorInvalidState;
3271 }
3272
3273 switch ((unsigned long)configIndex) {
3274 case OMX_QcomIndexConfigInterlaced:
3275 {
3276 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
3277 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
3278 if (configFmt->nPortIndex == 1) {
3279 if (configFmt->nIndex == 0) {
3280 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
3281 } else if (configFmt->nIndex == 1) {
3282 configFmt->eInterlaceType =
3283 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
3284 } else if (configFmt->nIndex == 2) {
3285 configFmt->eInterlaceType =
3286 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
3287 } else {
3288 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
3289 " NoMore Interlaced formats");
3290 eRet = OMX_ErrorNoMore;
3291 }
3292
3293 } else {
3294 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
3295 (int)configFmt->nPortIndex);
3296 eRet = OMX_ErrorBadPortIndex;
3297 }
3298 break;
3299 }
3300 case OMX_QcomIndexQueryNumberOfVideoDecInstance:
3301 {
3302 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
3303 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
3304 decoderinstances->nNumOfInstances = 16;
3305 /*TODO: How to handle this case */
3306 break;
3307 }
3308 case OMX_QcomIndexConfigVideoFramePackingArrangement:
3309 {
3310 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
3311 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
3312 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
3313 h264_parser->get_frame_pack_data(configFmt);
3314 } else {
3315 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
3316 }
3317 break;
3318 }
3319 case OMX_IndexConfigCommonOutputCrop:
3320 {
3321 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
3322 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
3323 break;
3324 }
3325 default:
3326 {
3327 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
3328 eRet = OMX_ErrorBadParameter;
3329 }
3330
3331 }
3332
3333 return eRet;
3334 }
3335
3336 /* ======================================================================
3337 FUNCTION
3338 omx_vdec::SetConfig
3339
3340 DESCRIPTION
3341 OMX Set Config method implementation
3342
3343 PARAMETERS
3344 <TBD>.
3345
3346 RETURN VALUE
3347 OMX Error None if successful.
3348 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)3349 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
3350 OMX_IN OMX_INDEXTYPE configIndex,
3351 OMX_IN OMX_PTR configData)
3352 {
3353 if (m_state == OMX_StateInvalid) {
3354 DEBUG_PRINT_ERROR("Get Config in Invalid State");
3355 return OMX_ErrorInvalidState;
3356 }
3357
3358 OMX_ERRORTYPE ret = OMX_ErrorNone;
3359 OMX_VIDEO_CONFIG_NALSIZE *pNal;
3360
3361 DEBUG_PRINT_LOW("Set Config Called");
3362
3363 if (m_state == OMX_StateExecuting) {
3364 DEBUG_PRINT_ERROR("set_config:Ignore in Exe state");
3365 return ret;
3366 }
3367
3368 if (configIndex == (OMX_INDEXTYPE)OMX_IndexVendorVideoExtraData) {
3369 OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData;
3370 DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called");
3371 if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc")) {
3372 DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData AVC");
3373 OMX_U32 extra_size;
3374 // Parsing done here for the AVC atom is definitely not generic
3375 // Currently this piece of code is working, but certainly
3376 // not tested with all .mp4 files.
3377 // Incase of failure, we might need to revisit this
3378 // for a generic piece of code.
3379
3380 // Retrieve size of NAL length field
3381 // byte #4 contains the size of NAL lenght field
3382 nal_length = (config->pData[4] & 0x03) + 1;
3383
3384 extra_size = 0;
3385 if (nal_length > 2) {
3386 /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
3387 extra_size = (nal_length - 2) * 2;
3388 }
3389
3390 // SPS starts from byte #6
3391 OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
3392 OMX_U8 *pDestBuf;
3393 m_vendor_config.nPortIndex = config->nPortIndex;
3394
3395 // minus 6 --> SPS starts from byte #6
3396 // minus 1 --> picture param set byte to be ignored from avcatom
3397 m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size;
3398 m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize);
3399 OMX_U32 len;
3400 OMX_U8 index = 0;
3401 // case where SPS+PPS is sent as part of set_config
3402 pDestBuf = m_vendor_config.pData;
3403
3404 DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]",
3405 m_vendor_config.nPortIndex,
3406 m_vendor_config.nDataSize,
3407 m_vendor_config.pData);
3408 while (index < 2) {
3409 uint8 *psize;
3410 len = *pSrcBuf;
3411 len = len << 8;
3412 len |= *(pSrcBuf + 1);
3413 psize = (uint8 *) & len;
3414 memcpy(pDestBuf + nal_length, pSrcBuf + 2,len);
3415 for (unsigned int i = 0; i < nal_length; i++) {
3416 pDestBuf[i] = psize[nal_length - 1 - i];
3417 }
3418 //memcpy(pDestBuf,pSrcBuf,(len+2));
3419 pDestBuf += len + nal_length;
3420 pSrcBuf += len + 2;
3421 index++;
3422 pSrcBuf++; // skip picture param set
3423 len = 0;
3424 }
3425 } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") ||
3426 !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) {
3427 m_vendor_config.nPortIndex = config->nPortIndex;
3428 m_vendor_config.nDataSize = config->nDataSize;
3429 m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize));
3430 memcpy(m_vendor_config.pData, config->pData,config->nDataSize);
3431 } else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) {
3432 if (m_vendor_config.pData) {
3433 free(m_vendor_config.pData);
3434 m_vendor_config.pData = NULL;
3435 m_vendor_config.nDataSize = 0;
3436 }
3437
3438 if (((*((OMX_U32 *) config->pData)) &
3439 VC1_SP_MP_START_CODE_MASK) ==
3440 VC1_SP_MP_START_CODE) {
3441 DEBUG_PRINT_LOW("set_config - VC1 simple/main profile");
3442 m_vendor_config.nPortIndex = config->nPortIndex;
3443 m_vendor_config.nDataSize = config->nDataSize;
3444 m_vendor_config.pData =
3445 (OMX_U8 *) malloc(config->nDataSize);
3446 memcpy(m_vendor_config.pData, config->pData,
3447 config->nDataSize);
3448 m_vc1_profile = VC1_SP_MP_RCV;
3449 } else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) {
3450 DEBUG_PRINT_LOW("set_config - VC1 Advance profile");
3451 m_vendor_config.nPortIndex = config->nPortIndex;
3452 m_vendor_config.nDataSize = config->nDataSize;
3453 m_vendor_config.pData =
3454 (OMX_U8 *) malloc((config->nDataSize));
3455 memcpy(m_vendor_config.pData, config->pData,
3456 config->nDataSize);
3457 m_vc1_profile = VC1_AP;
3458 } else if ((config->nDataSize == VC1_STRUCT_C_LEN)) {
3459 DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only");
3460 m_vendor_config.nPortIndex = config->nPortIndex;
3461 m_vendor_config.nDataSize = config->nDataSize;
3462 m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
3463 memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
3464 m_vc1_profile = VC1_SP_MP_RCV;
3465 } else {
3466 DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile");
3467 }
3468 }
3469 return ret;
3470 } else if (configIndex == OMX_IndexConfigVideoNalSize) {
3471
3472 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
3473 nal_length = pNal->nNaluBytes;
3474 m_frame_parser.init_nal_length(nal_length);
3475 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d",nal_length);
3476 return ret;
3477 }
3478
3479 return OMX_ErrorNotImplemented;
3480 }
3481
3482 /* ======================================================================
3483 FUNCTION
3484 omx_vdec::GetExtensionIndex
3485
3486 DESCRIPTION
3487 OMX GetExtensionIndex method implementaion. <TBD>
3488
3489 PARAMETERS
3490 <TBD>.
3491
3492 RETURN VALUE
3493 OMX Error None if everything successful.
3494
3495 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)3496 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
3497 OMX_IN OMX_STRING paramName,
3498 OMX_OUT OMX_INDEXTYPE* indexType)
3499 {
3500 if (m_state == OMX_StateInvalid) {
3501 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
3502 return OMX_ErrorInvalidState;
3503 } else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) {
3504 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
3505 } else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) {
3506 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
3507 }
3508 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3509 else if (!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
3510 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
3511 } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
3512 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
3513 } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
3514 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
3515 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
3516 } else if (!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
3517 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
3518 }
3519 #endif
3520 else {
3521 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
3522 return OMX_ErrorNotImplemented;
3523 }
3524 return OMX_ErrorNone;
3525 }
3526
3527 /* ======================================================================
3528 FUNCTION
3529 omx_vdec::GetState
3530
3531 DESCRIPTION
3532 Returns the state information back to the caller.<TBD>
3533
3534 PARAMETERS
3535 <TBD>.
3536
3537 RETURN VALUE
3538 Error None if everything is successful.
3539 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)3540 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
3541 OMX_OUT OMX_STATETYPE* state)
3542 {
3543 *state = m_state;
3544 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
3545 return OMX_ErrorNone;
3546 }
3547
3548 /* ======================================================================
3549 FUNCTION
3550 omx_vdec::ComponentTunnelRequest
3551
3552 DESCRIPTION
3553 OMX Component Tunnel Request method implementation. <TBD>
3554
3555 PARAMETERS
3556 None.
3557
3558 RETURN VALUE
3559 OMX Error None if everything successful.
3560
3561 ========================================================================== */
component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_HANDLETYPE peerComponent,OMX_IN OMX_U32 peerPort,OMX_INOUT OMX_TUNNELSETUPTYPE * tunnelSetup)3562 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
3563 OMX_IN OMX_U32 port,
3564 OMX_IN OMX_HANDLETYPE peerComponent,
3565 OMX_IN OMX_U32 peerPort,
3566 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
3567 {
3568 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
3569 return OMX_ErrorNotImplemented;
3570 }
3571
3572 /* ======================================================================
3573 FUNCTION
3574 omx_vdec::UseOutputBuffer
3575
3576 DESCRIPTION
3577 Helper function for Use buffer in the input pin
3578
3579 PARAMETERS
3580 None.
3581
3582 RETURN VALUE
3583 true/false
3584
3585 ========================================================================== */
allocate_extradata()3586 OMX_ERRORTYPE omx_vdec::allocate_extradata()
3587 {
3588 #ifdef USE_ION
3589 if (drv_ctx.extradata_info.buffer_size) {
3590 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
3591 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
3592 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3593 free_ion_memory(&drv_ctx.extradata_info.ion);
3594 }
3595 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
3596 DEBUG_PRINT_HIGH("allocate extradata memory size %d", drv_ctx.extradata_info.size);
3597 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
3598 drv_ctx.extradata_info.size, 4096,
3599 &drv_ctx.extradata_info.ion.ion_alloc_data,
3600 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
3601 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
3602 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
3603 return OMX_ErrorInsufficientResources;
3604 }
3605 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
3606 drv_ctx.extradata_info.size,
3607 PROT_READ|PROT_WRITE, MAP_SHARED,
3608 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
3609 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
3610 DEBUG_PRINT_ERROR("Failed to map extradata memory");
3611 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3612 free_ion_memory(&drv_ctx.extradata_info.ion);
3613 return OMX_ErrorInsufficientResources;
3614 }
3615 memset(drv_ctx.extradata_info.uaddr, 0, drv_ctx.extradata_info.size);
3616 }
3617 #endif
3618 return OMX_ErrorNone;
3619 }
3620
free_extradata()3621 void omx_vdec::free_extradata()
3622 {
3623 #ifdef USE_ION
3624 if (drv_ctx.extradata_info.uaddr) {
3625 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
3626 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
3627 free_ion_memory(&drv_ctx.extradata_info.ion);
3628 }
3629 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
3630 #endif
3631 }
3632
use_output_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)3633 OMX_ERRORTYPE omx_vdec::use_output_buffer(
3634 OMX_IN OMX_HANDLETYPE hComp,
3635 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3636 OMX_IN OMX_U32 port,
3637 OMX_IN OMX_PTR appData,
3638 OMX_IN OMX_U32 bytes,
3639 OMX_IN OMX_U8* buffer)
3640 {
3641 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3642 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
3643 unsigned i= 0; // Temporary counter
3644 struct vdec_setbuffer_cmd setbuffers;
3645 OMX_PTR privateAppData = NULL;
3646 private_handle_t *handle = NULL;
3647 OMX_U8 *buff = buffer;
3648 struct v4l2_buffer buf;
3649 struct v4l2_plane plane[VIDEO_MAX_PLANES];
3650 int extra_idx = 0;
3651
3652 if (!m_out_mem_ptr) {
3653 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
3654 eRet = allocate_output_headers();
3655 if (eRet == OMX_ErrorNone)
3656 eRet = allocate_extradata();
3657 }
3658
3659 if (eRet == OMX_ErrorNone) {
3660 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
3661 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
3662 break;
3663 }
3664 }
3665 }
3666
3667 if (i >= drv_ctx.op_buf.actualcount) {
3668 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
3669 eRet = OMX_ErrorInsufficientResources;
3670 }
3671
3672 if (eRet == OMX_ErrorNone) {
3673 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
3674 if (m_enable_android_native_buffers) {
3675 if (m_use_android_native_buffers) {
3676 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
3677 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3678 handle = (private_handle_t *)nBuf->handle;
3679 privateAppData = params->pAppPrivate;
3680 } else {
3681 handle = (private_handle_t *)buff;
3682 privateAppData = appData;
3683 }
3684
3685 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
3686 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
3687 " expected %u, got %lu",
3688 drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size);
3689 return OMX_ErrorBadParameter;
3690 }
3691
3692 drv_ctx.op_buf.buffer_size = (OMX_U32)handle->size;
3693 if (!m_use_android_native_buffers) {
3694 if (!secure_mode) {
3695 buff = (OMX_U8*)mmap(0, handle->size,
3696 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3697 if (buff == MAP_FAILED) {
3698 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3699 return OMX_ErrorInsufficientResources;
3700 }
3701 }
3702 }
3703 #if defined(_ANDROID_ICS_)
3704 native_buffer[i].nativehandle = handle;
3705 native_buffer[i].privatehandle = handle;
3706 #endif
3707 if (!handle) {
3708 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
3709 return OMX_ErrorBadParameter;
3710 }
3711 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
3712 drv_ctx.ptr_outputbuffer[i].offset = 0;
3713 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3714 drv_ctx.ptr_outputbuffer[i].mmaped_size =
3715 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3716 } else
3717 #endif
3718
3719 if (!ouput_egl_buffers && !m_use_output_pmem) {
3720 #ifdef USE_ION
3721 DEBUG_PRINT_HIGH("allocate output buffer memory size %d", drv_ctx.op_buf.buffer_size);
3722 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
3723 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
3724 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
3725 &drv_ctx.op_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0);
3726 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
3727 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
3728 return OMX_ErrorInsufficientResources;
3729 }
3730 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3731 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
3732 #else
3733 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3734 open (MEM_DEVICE,O_RDWR);
3735
3736 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3737 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
3738 return OMX_ErrorInsufficientResources;
3739 }
3740
3741 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
3742 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
3743 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3744 open (MEM_DEVICE,O_RDWR);
3745 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3746 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
3747 return OMX_ErrorInsufficientResources;
3748 }
3749 }
3750
3751 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
3752 drv_ctx.op_buf.buffer_size,
3753 drv_ctx.op_buf.alignment)) {
3754 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
3755 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3756 return OMX_ErrorInsufficientResources;
3757 }
3758 #endif
3759 if (!secure_mode) {
3760 drv_ctx.ptr_outputbuffer[i].bufferaddr =
3761 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
3762 PROT_READ|PROT_WRITE, MAP_SHARED,
3763 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
3764 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
3765 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3766 #ifdef USE_ION
3767 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
3768 #endif
3769 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
3770 return OMX_ErrorInsufficientResources;
3771 }
3772 }
3773 drv_ctx.ptr_outputbuffer[i].offset = 0;
3774 privateAppData = appData;
3775 } else {
3776
3777 DEBUG_PRINT_HIGH("Use_op_buf: out_pmem=%d",m_use_output_pmem);
3778 if (!appData || !bytes ) {
3779 if (!secure_mode && !buffer) {
3780 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
3781 return OMX_ErrorBadParameter;
3782 }
3783 }
3784
3785 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
3786 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
3787 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
3788 if (!pmem_list->entryList || !pmem_list->entryList->entry ||
3789 !pmem_list->nEntries ||
3790 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3791 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
3792 return OMX_ErrorBadParameter;
3793 }
3794 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
3795 pmem_list->entryList->entry;
3796 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x",
3797 pmem_info->pmem_fd);
3798 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
3799 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
3800 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3801 drv_ctx.ptr_outputbuffer[i].mmaped_size =
3802 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3803 privateAppData = appData;
3804 }
3805 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
3806 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
3807
3808 *bufferHdr = (m_out_mem_ptr + i );
3809 if (secure_mode)
3810 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
3811 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
3812 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
3813 sizeof (vdec_bufferpayload));
3814
3815 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
3816 drv_ctx.ptr_outputbuffer[i].bufferaddr,
3817 drv_ctx.ptr_outputbuffer[i].pmem_fd );
3818
3819 buf.index = i;
3820 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3821 buf.memory = V4L2_MEMORY_USERPTR;
3822 plane[0].length = drv_ctx.op_buf.buffer_size;
3823 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
3824 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
3825 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
3826 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
3827 plane[0].data_offset = 0;
3828 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
3829 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
3830 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
3831 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
3832 #ifdef USE_ION
3833 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
3834 #endif
3835 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
3836 plane[extra_idx].data_offset = 0;
3837 } else if (extra_idx >= VIDEO_MAX_PLANES) {
3838 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
3839 return OMX_ErrorBadParameter;
3840 }
3841 buf.m.planes = plane;
3842 buf.length = drv_ctx.num_planes;
3843
3844 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
3845
3846 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
3847 DEBUG_PRINT_ERROR("Failed to prepare bufs");
3848 /*TODO: How to handle this case */
3849 return OMX_ErrorInsufficientResources;
3850 }
3851
3852 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
3853 enum v4l2_buf_type buf_type;
3854 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3855 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
3856 return OMX_ErrorInsufficientResources;
3857 } else {
3858 streaming[CAPTURE_PORT] = true;
3859 DEBUG_PRINT_LOW("STREAMON Successful");
3860 }
3861 }
3862
3863 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
3864 if (m_enable_android_native_buffers) {
3865 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
3866 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
3867 } else {
3868 (*bufferHdr)->pBuffer = buff;
3869 }
3870 (*bufferHdr)->pAppPrivate = privateAppData;
3871 BITMASK_SET(&m_out_bm_count,i);
3872 }
3873 return eRet;
3874 }
3875
3876 /* ======================================================================
3877 FUNCTION
3878 omx_vdec::use_input_heap_buffers
3879
3880 DESCRIPTION
3881 OMX Use Buffer Heap allocation method implementation.
3882
3883 PARAMETERS
3884 <TBD>.
3885
3886 RETURN VALUE
3887 OMX Error None , if everything successful.
3888
3889 ========================================================================== */
use_input_heap_buffers(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)3890 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
3891 OMX_IN OMX_HANDLETYPE hComp,
3892 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3893 OMX_IN OMX_U32 port,
3894 OMX_IN OMX_PTR appData,
3895 OMX_IN OMX_U32 bytes,
3896 OMX_IN OMX_U8* buffer)
3897 {
3898 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
3899 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3900 if (!m_inp_heap_ptr)
3901 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
3902 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
3903 drv_ctx.ip_buf.actualcount);
3904 if (!m_phdr_pmem_ptr)
3905 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
3906 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
3907 drv_ctx.ip_buf.actualcount);
3908 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
3909 DEBUG_PRINT_ERROR("Insufficent memory");
3910 eRet = OMX_ErrorInsufficientResources;
3911 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
3912 input_use_buffer = true;
3913 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
3914 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
3915 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
3916 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
3917 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
3918 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
3919 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
3920 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
3921 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
3922 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt],
3923 (unsigned)NULL, (unsigned)NULL)) {
3924 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
3925 return OMX_ErrorInsufficientResources;
3926 }
3927 m_in_alloc_cnt++;
3928 } else {
3929 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
3930 eRet = OMX_ErrorInsufficientResources;
3931 }
3932 return eRet;
3933 }
3934
3935 /* ======================================================================
3936 FUNCTION
3937 omx_vdec::UseBuffer
3938
3939 DESCRIPTION
3940 OMX Use Buffer method implementation.
3941
3942 PARAMETERS
3943 <TBD>.
3944
3945 RETURN VALUE
3946 OMX Error None , if everything successful.
3947
3948 ========================================================================== */
use_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)3949 OMX_ERRORTYPE omx_vdec::use_buffer(
3950 OMX_IN OMX_HANDLETYPE hComp,
3951 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3952 OMX_IN OMX_U32 port,
3953 OMX_IN OMX_PTR appData,
3954 OMX_IN OMX_U32 bytes,
3955 OMX_IN OMX_U8* buffer)
3956 {
3957 OMX_ERRORTYPE error = OMX_ErrorNone;
3958 struct vdec_setbuffer_cmd setbuffers;
3959
3960 if (bufferHdr == NULL || bytes == 0) {
3961 if (!secure_mode && buffer == NULL) {
3962 DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer);
3963 return OMX_ErrorBadParameter;
3964 }
3965 }
3966 if (m_state == OMX_StateInvalid) {
3967 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
3968 return OMX_ErrorInvalidState;
3969 }
3970 if (port == OMX_CORE_INPUT_PORT_INDEX)
3971 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
3972 else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
3973 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
3974 else {
3975 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
3976 error = OMX_ErrorBadPortIndex;
3977 }
3978 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error);
3979 if (error == OMX_ErrorNone) {
3980 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
3981 // Send the callback now
3982 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
3983 post_event(OMX_CommandStateSet,OMX_StateIdle,
3984 OMX_COMPONENT_GENERATE_EVENT);
3985 }
3986 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
3987 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
3988 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
3989 post_event(OMX_CommandPortEnable,
3990 OMX_CORE_INPUT_PORT_INDEX,
3991 OMX_COMPONENT_GENERATE_EVENT);
3992 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
3993 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
3994 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3995 post_event(OMX_CommandPortEnable,
3996 OMX_CORE_OUTPUT_PORT_INDEX,
3997 OMX_COMPONENT_GENERATE_EVENT);
3998 }
3999 }
4000 return error;
4001 }
4002
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)4003 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
4004 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
4005 {
4006 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
4007 if (m_inp_heap_ptr[bufferindex].pBuffer)
4008 free(m_inp_heap_ptr[bufferindex].pBuffer);
4009 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
4010 }
4011 if (pmem_bufferHdr)
4012 free_input_buffer(pmem_bufferHdr);
4013 return OMX_ErrorNone;
4014 }
4015
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4016 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4017 {
4018 unsigned int index = 0;
4019 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
4020 return OMX_ErrorBadParameter;
4021 }
4022
4023 index = bufferHdr - m_inp_mem_ptr;
4024 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
4025
4026 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
4027 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
4028 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) {
4029 struct vdec_setbuffer_cmd setbuffers;
4030 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
4031 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
4032 sizeof (vdec_bufferpayload));
4033 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
4034 drv_ctx.ptr_inputbuffer[index].pmem_fd);
4035 DEBUG_PRINT_LOW("unmap the input buffer size=%d address = %d",
4036 drv_ctx.ptr_inputbuffer[index].mmaped_size,
4037 drv_ctx.ptr_inputbuffer[index].bufferaddr);
4038 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
4039 drv_ctx.ptr_inputbuffer[index].mmaped_size);
4040 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
4041 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
4042 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
4043 free(m_desc_buffer_ptr[index].buf_addr);
4044 m_desc_buffer_ptr[index].buf_addr = NULL;
4045 m_desc_buffer_ptr[index].desc_data_size = 0;
4046 }
4047 #ifdef USE_ION
4048 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
4049 #endif
4050 }
4051 }
4052
4053 return OMX_ErrorNone;
4054 }
4055
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4056 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4057 {
4058 unsigned int index = 0;
4059
4060 if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
4061 return OMX_ErrorBadParameter;
4062 }
4063
4064 index = bufferHdr - m_out_mem_ptr;
4065 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
4066
4067 if (index < drv_ctx.op_buf.actualcount
4068 && drv_ctx.ptr_outputbuffer) {
4069 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %x", index,
4070 drv_ctx.ptr_outputbuffer[index].bufferaddr);
4071
4072 struct vdec_setbuffer_cmd setbuffers;
4073 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
4074 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
4075 sizeof (vdec_bufferpayload));
4076 #ifdef _ANDROID_
4077 if (m_enable_android_native_buffers) {
4078 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
4079 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
4080 drv_ctx.ptr_outputbuffer[index].mmaped_size);
4081 }
4082 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
4083 } else {
4084 #endif
4085 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
4086 DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
4087 drv_ctx.ptr_outputbuffer[0].pmem_fd);
4088 DEBUG_PRINT_LOW("unmap the ouput buffer size=%d address = %d",
4089 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
4090 drv_ctx.ptr_outputbuffer[0].bufferaddr);
4091 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
4092 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
4093 close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
4094 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
4095 #ifdef USE_ION
4096 free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
4097 #endif
4098 }
4099 #ifdef _ANDROID_
4100 }
4101 #endif
4102 if (release_output_done()) {
4103 free_extradata();
4104 }
4105 }
4106
4107 return OMX_ErrorNone;
4108
4109 }
4110
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)4111 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
4112 OMX_BUFFERHEADERTYPE **bufferHdr,
4113 OMX_U32 port,
4114 OMX_PTR appData,
4115 OMX_U32 bytes)
4116 {
4117 OMX_BUFFERHEADERTYPE *input = NULL;
4118 unsigned char *buf_addr = NULL;
4119 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4120 unsigned i = 0;
4121
4122 /* Sanity Check*/
4123 if (bufferHdr == NULL) {
4124 return OMX_ErrorBadParameter;
4125 }
4126
4127 if (m_inp_heap_ptr == NULL) {
4128 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
4129 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4130 drv_ctx.ip_buf.actualcount);
4131 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
4132 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4133 drv_ctx.ip_buf.actualcount);
4134
4135 if (m_inp_heap_ptr == NULL) {
4136 DEBUG_PRINT_ERROR("m_inp_heap_ptr Allocation failed ");
4137 return OMX_ErrorInsufficientResources;
4138 }
4139 }
4140
4141 /*Find a Free index*/
4142 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
4143 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
4144 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
4145 break;
4146 }
4147 }
4148
4149 if (i < drv_ctx.ip_buf.actualcount) {
4150 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
4151
4152 if (buf_addr == NULL) {
4153 return OMX_ErrorInsufficientResources;
4154 }
4155
4156 *bufferHdr = (m_inp_heap_ptr + i);
4157 input = *bufferHdr;
4158 BITMASK_SET(&m_heap_inp_bm_count,i);
4159
4160 input->pBuffer = (OMX_U8 *)buf_addr;
4161 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4162 input->nVersion.nVersion = OMX_SPEC_VERSION;
4163 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4164 input->pAppPrivate = appData;
4165 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4166 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
4167 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
4168 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
4169 /*Add the Buffers to freeq*/
4170 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[i],
4171 (unsigned)NULL, (unsigned)NULL)) {
4172 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
4173 return OMX_ErrorInsufficientResources;
4174 }
4175 } else {
4176 return OMX_ErrorBadParameter;
4177 }
4178
4179 return eRet;
4180
4181 }
4182
4183
4184 /* ======================================================================
4185 FUNCTION
4186 omx_vdec::AllocateInputBuffer
4187
4188 DESCRIPTION
4189 Helper function for allocate buffer in the input pin
4190
4191 PARAMETERS
4192 None.
4193
4194 RETURN VALUE
4195 true/false
4196
4197 ========================================================================== */
allocate_input_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes)4198 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
4199 OMX_IN OMX_HANDLETYPE hComp,
4200 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4201 OMX_IN OMX_U32 port,
4202 OMX_IN OMX_PTR appData,
4203 OMX_IN OMX_U32 bytes)
4204 {
4205
4206 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4207 struct vdec_setbuffer_cmd setbuffers;
4208 OMX_BUFFERHEADERTYPE *input = NULL;
4209 unsigned i = 0;
4210 unsigned char *buf_addr = NULL;
4211 int pmem_fd = -1;
4212
4213 if (bytes != drv_ctx.ip_buf.buffer_size) {
4214 DEBUG_PRINT_LOW("Requested Size is wrong %d epected is %d",
4215 bytes, drv_ctx.ip_buf.buffer_size);
4216 return OMX_ErrorBadParameter;
4217 }
4218
4219 if (!m_inp_mem_ptr) {
4220 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
4221 drv_ctx.ip_buf.actualcount,
4222 drv_ctx.ip_buf.buffer_size);
4223
4224 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4225 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4226
4227 if (m_inp_mem_ptr == NULL) {
4228 return OMX_ErrorInsufficientResources;
4229 }
4230
4231 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
4232 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
4233
4234 if (drv_ctx.ptr_inputbuffer == NULL) {
4235 return OMX_ErrorInsufficientResources;
4236 }
4237 #ifdef USE_ION
4238 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
4239 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
4240
4241 if (drv_ctx.ip_buf_ion_info == NULL) {
4242 return OMX_ErrorInsufficientResources;
4243 }
4244 #endif
4245
4246 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
4247 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
4248 #ifdef USE_ION
4249 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
4250 #endif
4251 }
4252 }
4253
4254 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
4255 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
4256 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
4257 break;
4258 }
4259 }
4260
4261 if (i < drv_ctx.ip_buf.actualcount) {
4262 struct v4l2_buffer buf;
4263 struct v4l2_plane plane;
4264 int rc;
4265
4266 #ifdef USE_ION
4267 DEBUG_PRINT_HIGH("Allocate input Buffer size %d", drv_ctx.ip_buf.buffer_size);
4268 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
4269 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
4270 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
4271 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0);
4272 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
4273 return OMX_ErrorInsufficientResources;
4274 }
4275 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
4276 #else
4277 pmem_fd = open (MEM_DEVICE,O_RDWR);
4278
4279 if (pmem_fd < 0) {
4280 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
4281 return OMX_ErrorInsufficientResources;
4282 }
4283
4284 if (pmem_fd == 0) {
4285 pmem_fd = open (MEM_DEVICE,O_RDWR);
4286
4287 if (pmem_fd < 0) {
4288 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
4289 return OMX_ErrorInsufficientResources;
4290 }
4291 }
4292
4293 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
4294 drv_ctx.ip_buf.alignment)) {
4295 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
4296 close(pmem_fd);
4297 return OMX_ErrorInsufficientResources;
4298 }
4299 #endif
4300 if (!secure_mode) {
4301 buf_addr = (unsigned char *)mmap(NULL,
4302 drv_ctx.ip_buf.buffer_size,
4303 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
4304
4305 if (buf_addr == MAP_FAILED) {
4306 close(pmem_fd);
4307 #ifdef USE_ION
4308 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
4309 #endif
4310 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
4311 return OMX_ErrorInsufficientResources;
4312 }
4313 }
4314 *bufferHdr = (m_inp_mem_ptr + i);
4315 if (secure_mode)
4316 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
4317 else
4318 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
4319 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
4320 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4321 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
4322 drv_ctx.ptr_inputbuffer [i].offset = 0;
4323
4324
4325 buf.index = i;
4326 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4327 buf.memory = V4L2_MEMORY_USERPTR;
4328 plane.bytesused = 0;
4329 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
4330 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
4331 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
4332 plane.reserved[1] = 0;
4333 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
4334 buf.m.planes = &plane;
4335 buf.length = 1;
4336
4337 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_inputbuffer[i]);
4338
4339 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4340
4341 if (rc) {
4342 DEBUG_PRINT_ERROR("Failed to prepare bufs");
4343 /*TODO: How to handle this case */
4344 return OMX_ErrorInsufficientResources;
4345 }
4346
4347 input = *bufferHdr;
4348 BITMASK_SET(&m_inp_bm_count,i);
4349 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
4350 if (secure_mode)
4351 input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd;
4352 else
4353 input->pBuffer = (OMX_U8 *)buf_addr;
4354 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4355 input->nVersion.nVersion = OMX_SPEC_VERSION;
4356 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4357 input->pAppPrivate = appData;
4358 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4359 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
4360
4361 if (drv_ctx.disable_dmx) {
4362 eRet = allocate_desc_buffer(i);
4363 }
4364 } else {
4365 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
4366 eRet = OMX_ErrorInsufficientResources;
4367 }
4368 return eRet;
4369 }
4370
4371
4372 /* ======================================================================
4373 FUNCTION
4374 omx_vdec::AllocateOutputBuffer
4375
4376 DESCRIPTION
4377 Helper fn for AllocateBuffer in the output pin
4378
4379 PARAMETERS
4380 <TBD>.
4381
4382 RETURN VALUE
4383 OMX Error None if everything went well.
4384
4385 ========================================================================== */
allocate_output_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes)4386 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
4387 OMX_IN OMX_HANDLETYPE hComp,
4388 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4389 OMX_IN OMX_U32 port,
4390 OMX_IN OMX_PTR appData,
4391 OMX_IN OMX_U32 bytes)
4392 {
4393 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4394 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
4395 unsigned i= 0; // Temporary counter
4396 struct vdec_setbuffer_cmd setbuffers;
4397 int extra_idx = 0;
4398 #ifdef USE_ION
4399 int ion_device_fd =-1;
4400 struct ion_allocation_data ion_alloc_data;
4401 struct ion_fd_data fd_ion_data;
4402 #endif
4403 if (!m_out_mem_ptr) {
4404 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%d)",
4405 drv_ctx.op_buf.actualcount,
4406 drv_ctx.op_buf.buffer_size);
4407 int nBufHdrSize = 0;
4408 int nPlatformEntrySize = 0;
4409 int nPlatformListSize = 0;
4410 int nPMEMInfoSize = 0;
4411 int pmem_fd = -1;
4412 unsigned char *pmem_baseaddress = NULL;
4413
4414 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
4415 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
4416 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
4417
4418 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
4419 drv_ctx.op_buf.actualcount);
4420 nBufHdrSize = drv_ctx.op_buf.actualcount *
4421 sizeof(OMX_BUFFERHEADERTYPE);
4422
4423 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
4424 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
4425 nPlatformListSize = drv_ctx.op_buf.actualcount *
4426 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
4427 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
4428 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
4429
4430 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize,
4431 sizeof(OMX_BUFFERHEADERTYPE),
4432 nPMEMInfoSize,
4433 nPlatformListSize);
4434 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
4435 drv_ctx.op_buf.actualcount);
4436 #ifdef USE_ION
4437 DEBUG_PRINT_HIGH("allocate outputBuffer size %d",drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount);
4438 ion_device_fd = alloc_map_ion_memory(
4439 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
4440 drv_ctx.op_buf.alignment,
4441 &ion_alloc_data, &fd_ion_data, secure_mode ? ION_SECURE : 0);
4442 if (ion_device_fd < 0) {
4443 return OMX_ErrorInsufficientResources;
4444 }
4445 pmem_fd = fd_ion_data.fd;
4446 #else
4447 pmem_fd = open (MEM_DEVICE,O_RDWR);
4448
4449 if (pmem_fd < 0) {
4450 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
4451 drv_ctx.op_buf.buffer_size);
4452 return OMX_ErrorInsufficientResources;
4453 }
4454
4455 if (pmem_fd == 0) {
4456 pmem_fd = open (MEM_DEVICE,O_RDWR);
4457
4458 if (pmem_fd < 0) {
4459 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
4460 drv_ctx.op_buf.buffer_size);
4461 return OMX_ErrorInsufficientResources;
4462 }
4463 }
4464
4465 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
4466 drv_ctx.op_buf.actualcount,
4467 drv_ctx.op_buf.alignment)) {
4468 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
4469 close(pmem_fd);
4470 return OMX_ErrorInsufficientResources;
4471 }
4472 #endif
4473 if (!secure_mode) {
4474 pmem_baseaddress = (unsigned char *)mmap(NULL,
4475 (drv_ctx.op_buf.buffer_size *
4476 drv_ctx.op_buf.actualcount),
4477 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
4478 if (pmem_baseaddress == MAP_FAILED) {
4479 DEBUG_PRINT_ERROR("MMAP failed for Size %d",
4480 drv_ctx.op_buf.buffer_size);
4481 close(pmem_fd);
4482 #ifdef USE_ION
4483 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
4484 #endif
4485 return OMX_ErrorInsufficientResources;
4486 }
4487 }
4488 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
4489 // Alloc mem for platform specific info
4490 char *pPtr=NULL;
4491 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
4492 nPMEMInfoSize,1);
4493 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
4494 calloc (sizeof(struct vdec_bufferpayload),
4495 drv_ctx.op_buf.actualcount);
4496 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
4497 calloc (sizeof (struct vdec_output_frameinfo),
4498 drv_ctx.op_buf.actualcount);
4499 #ifdef USE_ION
4500 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
4501 calloc (sizeof(struct vdec_ion),
4502 drv_ctx.op_buf.actualcount);
4503 #endif
4504
4505 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
4506 && drv_ctx.ptr_respbuffer) {
4507 drv_ctx.ptr_outputbuffer[0].mmaped_size =
4508 (drv_ctx.op_buf.buffer_size *
4509 drv_ctx.op_buf.actualcount);
4510 bufHdr = m_out_mem_ptr;
4511 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
4512 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
4513 (((char *) m_platform_list) + nPlatformListSize);
4514 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4515 (((char *) m_platform_entry) + nPlatformEntrySize);
4516 pPlatformList = m_platform_list;
4517 pPlatformEntry = m_platform_entry;
4518 pPMEMInfo = m_pmem_info;
4519
4520 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
4521
4522 // Settting the entire storage nicely
4523 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
4524 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
4525 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
4526 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4527 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
4528 // Set the values when we determine the right HxW param
4529 bufHdr->nAllocLen = bytes;
4530 bufHdr->nFilledLen = 0;
4531 bufHdr->pAppPrivate = appData;
4532 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
4533 // Platform specific PMEM Information
4534 // Initialize the Platform Entry
4535 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
4536 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
4537 pPlatformEntry->entry = pPMEMInfo;
4538 // Initialize the Platform List
4539 pPlatformList->nEntries = 1;
4540 pPlatformList->entryList = pPlatformEntry;
4541 // Keep pBuffer NULL till vdec is opened
4542 bufHdr->pBuffer = NULL;
4543 bufHdr->nOffset = 0;
4544
4545 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
4546 pPMEMInfo->pmem_fd = 0;
4547 bufHdr->pPlatformPrivate = pPlatformList;
4548
4549 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
4550 m_pmem_info[i].pmem_fd = pmem_fd;
4551 #ifdef USE_ION
4552 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
4553 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
4554 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
4555 #endif
4556
4557 /*Create a mapping between buffers*/
4558 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
4559 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
4560 &drv_ctx.ptr_outputbuffer[i];
4561 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
4562 drv_ctx.ptr_outputbuffer[i].bufferaddr =
4563 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
4564
4565 DEBUG_PRINT_LOW("pmem_fd = %d offset = %d address = %p",
4566 pmem_fd, drv_ctx.ptr_outputbuffer[i].offset,
4567 drv_ctx.ptr_outputbuffer[i].bufferaddr);
4568 // Move the buffer and buffer header pointers
4569 bufHdr++;
4570 pPMEMInfo++;
4571 pPlatformEntry++;
4572 pPlatformList++;
4573 }
4574 } else {
4575 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
4576 m_out_mem_ptr, pPtr);
4577 if (m_out_mem_ptr) {
4578 free(m_out_mem_ptr);
4579 m_out_mem_ptr = NULL;
4580 }
4581 if (pPtr) {
4582 free(pPtr);
4583 pPtr = NULL;
4584 }
4585 if (drv_ctx.ptr_outputbuffer) {
4586 free(drv_ctx.ptr_outputbuffer);
4587 drv_ctx.ptr_outputbuffer = NULL;
4588 }
4589 if (drv_ctx.ptr_respbuffer) {
4590 free(drv_ctx.ptr_respbuffer);
4591 drv_ctx.ptr_respbuffer = NULL;
4592 }
4593 #ifdef USE_ION
4594 if (drv_ctx.op_buf_ion_info) {
4595 DEBUG_PRINT_LOW("Free o/p ion context");
4596 free(drv_ctx.op_buf_ion_info);
4597 drv_ctx.op_buf_ion_info = NULL;
4598 }
4599 #endif
4600 eRet = OMX_ErrorInsufficientResources;
4601 }
4602 if (eRet == OMX_ErrorNone)
4603 eRet = allocate_extradata();
4604 }
4605
4606 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
4607 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
4608 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
4609 break;
4610 }
4611 }
4612
4613 if (eRet == OMX_ErrorNone) {
4614 if (i < drv_ctx.op_buf.actualcount) {
4615 struct v4l2_buffer buf;
4616 struct v4l2_plane plane[VIDEO_MAX_PLANES];
4617 int rc;
4618 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
4619
4620 drv_ctx.ptr_outputbuffer[i].buffer_len =
4621 drv_ctx.op_buf.buffer_size;
4622
4623 *bufferHdr = (m_out_mem_ptr + i );
4624 if (secure_mode) {
4625 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
4626 }
4627 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
4628
4629 buf.index = i;
4630 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4631 buf.memory = V4L2_MEMORY_USERPTR;
4632 plane[0].length = drv_ctx.op_buf.buffer_size;
4633 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
4634 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
4635 #ifdef USE_ION
4636 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
4637 #endif
4638 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
4639 plane[0].data_offset = 0;
4640 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
4641 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4642 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
4643 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
4644 #ifdef USE_ION
4645 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
4646 #endif
4647 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
4648 plane[extra_idx].data_offset = 0;
4649 } else if (extra_idx >= VIDEO_MAX_PLANES) {
4650 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
4651 return OMX_ErrorBadParameter;
4652 }
4653 buf.m.planes = plane;
4654 buf.length = drv_ctx.num_planes;
4655 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
4656 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4657 if (rc) {
4658 /*TODO: How to handle this case */
4659 return OMX_ErrorInsufficientResources;
4660 }
4661
4662 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
4663 enum v4l2_buf_type buf_type;
4664 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4665 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
4666 if (rc) {
4667 return OMX_ErrorInsufficientResources;
4668 } else {
4669 streaming[CAPTURE_PORT] = true;
4670 DEBUG_PRINT_LOW("STREAMON Successful");
4671 }
4672 }
4673
4674 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
4675 (*bufferHdr)->pAppPrivate = appData;
4676 BITMASK_SET(&m_out_bm_count,i);
4677 } else {
4678 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
4679 eRet = OMX_ErrorInsufficientResources;
4680 }
4681 }
4682
4683 return eRet;
4684 }
4685
4686
4687 // AllocateBuffer -- API Call
4688 /* ======================================================================
4689 FUNCTION
4690 omx_vdec::AllocateBuffer
4691
4692 DESCRIPTION
4693 Returns zero if all the buffers released..
4694
4695 PARAMETERS
4696 None.
4697
4698 RETURN VALUE
4699 true/false
4700
4701 ========================================================================== */
allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes)4702 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
4703 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4704 OMX_IN OMX_U32 port,
4705 OMX_IN OMX_PTR appData,
4706 OMX_IN OMX_U32 bytes)
4707 {
4708 unsigned i = 0;
4709 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
4710
4711 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
4712 if (m_state == OMX_StateInvalid) {
4713 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
4714 return OMX_ErrorInvalidState;
4715 }
4716
4717 if (port == OMX_CORE_INPUT_PORT_INDEX) {
4718 if (arbitrary_bytes) {
4719 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
4720 } else {
4721 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
4722 }
4723 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4724 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
4725 appData,bytes);
4726 } else {
4727 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
4728 eRet = OMX_ErrorBadPortIndex;
4729 }
4730 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
4731 if (eRet == OMX_ErrorNone) {
4732 if (allocate_done()) {
4733 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
4734 // Send the callback now
4735 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4736 post_event(OMX_CommandStateSet,OMX_StateIdle,
4737 OMX_COMPONENT_GENERATE_EVENT);
4738 }
4739 }
4740 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
4741 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
4742 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4743 post_event(OMX_CommandPortEnable,
4744 OMX_CORE_INPUT_PORT_INDEX,
4745 OMX_COMPONENT_GENERATE_EVENT);
4746 }
4747 }
4748 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
4749 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
4750 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4751 post_event(OMX_CommandPortEnable,
4752 OMX_CORE_OUTPUT_PORT_INDEX,
4753 OMX_COMPONENT_GENERATE_EVENT);
4754 }
4755 }
4756 }
4757 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
4758 return eRet;
4759 }
4760
4761 // Free Buffer - API call
4762 /* ======================================================================
4763 FUNCTION
4764 omx_vdec::FreeBuffer
4765
4766 DESCRIPTION
4767
4768 PARAMETERS
4769 None.
4770
4771 RETURN VALUE
4772 true/false
4773
4774 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4775 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
4776 OMX_IN OMX_U32 port,
4777 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4778 {
4779 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4780 unsigned int nPortIndex;
4781 DEBUG_PRINT_LOW("In for decoder free_buffer");
4782
4783 if (m_state == OMX_StateIdle &&
4784 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4785 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
4786 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
4787 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
4788 DEBUG_PRINT_LOW("Free Buffer while port %d disabled", port);
4789 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
4790 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
4791 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
4792 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
4793 DEBUG_PRINT_LOW("Free Buffer while port %d enable pending", port);
4794 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
4795 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
4796 post_event(OMX_EventError,
4797 OMX_ErrorPortUnpopulated,
4798 OMX_COMPONENT_GENERATE_EVENT);
4799
4800 return OMX_ErrorIncorrectStateOperation;
4801 } else if (m_state != OMX_StateInvalid) {
4802 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
4803 post_event(OMX_EventError,
4804 OMX_ErrorPortUnpopulated,
4805 OMX_COMPONENT_GENERATE_EVENT);
4806 }
4807
4808 if (port == OMX_CORE_INPUT_PORT_INDEX) {
4809 /*Check if arbitrary bytes*/
4810 if (!arbitrary_bytes && !input_use_buffer)
4811 nPortIndex = buffer - m_inp_mem_ptr;
4812 else
4813 nPortIndex = buffer - m_inp_heap_ptr;
4814
4815 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
4816 if (nPortIndex < drv_ctx.ip_buf.actualcount) {
4817 // Clear the bit associated with it.
4818 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
4819 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
4820 if (input_use_buffer == true) {
4821
4822 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
4823 if (m_phdr_pmem_ptr)
4824 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
4825 } else {
4826 if (arbitrary_bytes) {
4827 if (m_phdr_pmem_ptr)
4828 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
4829 else
4830 free_input_buffer(nPortIndex,NULL);
4831 } else
4832 free_input_buffer(buffer);
4833 }
4834 m_inp_bPopulated = OMX_FALSE;
4835 /*Free the Buffer Header*/
4836 if (release_input_done()) {
4837 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
4838 free_input_buffer_header();
4839 }
4840 } else {
4841 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
4842 eRet = OMX_ErrorBadPortIndex;
4843 }
4844
4845 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
4846 && release_input_done()) {
4847 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4848 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
4849 post_event(OMX_CommandPortDisable,
4850 OMX_CORE_INPUT_PORT_INDEX,
4851 OMX_COMPONENT_GENERATE_EVENT);
4852 }
4853 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
4854 // check if the buffer is valid
4855 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
4856 if (nPortIndex < drv_ctx.op_buf.actualcount) {
4857 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
4858 // Clear the bit associated with it.
4859 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
4860 m_out_bPopulated = OMX_FALSE;
4861 client_buffers.free_output_buffer (buffer);
4862
4863 if (release_output_done()) {
4864 free_output_buffer_header();
4865 }
4866 } else {
4867 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
4868 eRet = OMX_ErrorBadPortIndex;
4869 }
4870 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
4871 && release_output_done()) {
4872 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
4873
4874 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
4875 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
4876 #ifdef _ANDROID_ICS_
4877 if (m_enable_android_native_buffers) {
4878 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
4879 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
4880 }
4881 #endif
4882
4883 post_event(OMX_CommandPortDisable,
4884 OMX_CORE_OUTPUT_PORT_INDEX,
4885 OMX_COMPONENT_GENERATE_EVENT);
4886 }
4887 } else {
4888 eRet = OMX_ErrorBadPortIndex;
4889 }
4890 if ((eRet == OMX_ErrorNone) &&
4891 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
4892 if (release_done()) {
4893 // Send the callback now
4894 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
4895 post_event(OMX_CommandStateSet, OMX_StateLoaded,
4896 OMX_COMPONENT_GENERATE_EVENT);
4897 }
4898 }
4899 return eRet;
4900 }
4901
4902
4903 /* ======================================================================
4904 FUNCTION
4905 omx_vdec::EmptyThisBuffer
4906
4907 DESCRIPTION
4908 This routine is used to push the encoded video frames to
4909 the video decoder.
4910
4911 PARAMETERS
4912 None.
4913
4914 RETURN VALUE
4915 OMX Error None if everything went successful.
4916
4917 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)4918 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
4919 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
4920 {
4921 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
4922 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
4923
4924 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
4925 codec_config_flag = true;
4926 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
4927 }
4928 if (m_state == OMX_StateInvalid) {
4929 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
4930 return OMX_ErrorInvalidState;
4931 }
4932
4933 if (buffer == NULL) {
4934 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
4935 return OMX_ErrorBadParameter;
4936 }
4937
4938 if (!m_inp_bEnabled) {
4939 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
4940 return OMX_ErrorIncorrectStateOperation;
4941 }
4942
4943 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4944 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %lu", buffer->nInputPortIndex);
4945 return OMX_ErrorBadPortIndex;
4946 }
4947
4948 #ifdef _ANDROID_
4949 if (iDivXDrmDecrypt) {
4950 OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer);
4951 if (drmErr != OMX_ErrorNone) {
4952 // this error can be ignored
4953 DEBUG_PRINT_LOW("ERROR:iDivXDrmDecrypt->Decrypt %d", drmErr);
4954 }
4955 }
4956 #endif //_ANDROID_
4957 if (perf_flag) {
4958 if (!latency) {
4959 dec_time.stop();
4960 latency = dec_time.processing_time_us();
4961 dec_time.start();
4962 }
4963 }
4964
4965 if (arbitrary_bytes) {
4966 nBufferIndex = buffer - m_inp_heap_ptr;
4967 } else {
4968 if (input_use_buffer == true) {
4969 nBufferIndex = buffer - m_inp_heap_ptr;
4970 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
4971 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
4972 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
4973 buffer = &m_inp_mem_ptr[nBufferIndex];
4974 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d",
4975 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen);
4976 } else {
4977 nBufferIndex = buffer - m_inp_mem_ptr;
4978 }
4979 }
4980
4981 if (nBufferIndex > drv_ctx.ip_buf.actualcount ) {
4982 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
4983 return OMX_ErrorBadParameter;
4984 }
4985
4986 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)",
4987 buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen);
4988 if (arbitrary_bytes) {
4989 post_event ((unsigned)hComp,(unsigned)buffer,
4990 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
4991 } else {
4992 if (!(client_extradata & OMX_TIMEINFO_EXTRADATA))
4993 set_frame_rate(buffer->nTimeStamp);
4994 post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
4995 }
4996 return OMX_ErrorNone;
4997 }
4998
4999 /* ======================================================================
5000 FUNCTION
5001 omx_vdec::empty_this_buffer_proxy
5002
5003 DESCRIPTION
5004 This routine is used to push the encoded video frames to
5005 the video decoder.
5006
5007 PARAMETERS
5008 None.
5009
5010 RETURN VALUE
5011 OMX Error None if everything went successful.
5012
5013 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5014 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
5015 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5016 {
5017 int push_cnt = 0,i=0;
5018 unsigned nPortIndex = 0;
5019 OMX_ERRORTYPE ret = OMX_ErrorNone;
5020 struct vdec_input_frameinfo frameinfo;
5021 struct vdec_bufferpayload *temp_buffer;
5022 struct vdec_seqheader seq_header;
5023 bool port_setting_changed = true;
5024 bool not_coded_vop = false;
5025
5026 /*Should we generate a Aync error event*/
5027 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
5028 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
5029 return OMX_ErrorBadParameter;
5030 }
5031
5032 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
5033
5034 if (nPortIndex > drv_ctx.ip_buf.actualcount) {
5035 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
5036 nPortIndex);
5037 return OMX_ErrorBadParameter;
5038 }
5039
5040 pending_input_buffers++;
5041
5042 /* return zero length and not an EOS buffer */
5043 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
5044 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
5045 DEBUG_PRINT_HIGH("return zero legth buffer");
5046 post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5047 OMX_COMPONENT_GENERATE_EBD);
5048 return OMX_ErrorNone;
5049 }
5050
5051
5052 if (codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX) {
5053 mp4StreamType psBits;
5054 psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset);
5055 psBits.numBytes = buffer->nFilledLen;
5056 mp4_headerparser.parseHeader(&psBits);
5057 not_coded_vop = mp4_headerparser.is_notcodec_vop(
5058 (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5059 if (not_coded_vop) {
5060 DEBUG_PRINT_HIGH("Found Not coded vop len %lu frame number %u",
5061 buffer->nFilledLen,frame_count);
5062 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5063 DEBUG_PRINT_HIGH("Eos and Not coded Vop set len to zero");
5064 not_coded_vop = false;
5065 buffer->nFilledLen = 0;
5066 }
5067 }
5068 }
5069
5070 if (input_flush_progress == true
5071
5072 || not_coded_vop
5073
5074 ) {
5075 DEBUG_PRINT_LOW("Flush in progress return buffer ");
5076 post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5077 OMX_COMPONENT_GENERATE_EBD);
5078 return OMX_ErrorNone;
5079 }
5080
5081 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
5082
5083 if ((temp_buffer - drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount) {
5084 return OMX_ErrorBadParameter;
5085 }
5086
5087 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5088 /*for use buffer we need to memcpy the data*/
5089 temp_buffer->buffer_len = buffer->nFilledLen;
5090
5091 if (input_use_buffer) {
5092 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
5093 if (arbitrary_bytes) {
5094 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5095 } else {
5096 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
5097 buffer->nFilledLen);
5098 }
5099 } else {
5100 return OMX_ErrorBadParameter;
5101 }
5102
5103 }
5104
5105 frameinfo.bufferaddr = temp_buffer->bufferaddr;
5106 frameinfo.client_data = (void *) buffer;
5107 frameinfo.datalen = temp_buffer->buffer_len;
5108 frameinfo.flags = 0;
5109 frameinfo.offset = buffer->nOffset;
5110 frameinfo.pmem_fd = temp_buffer->pmem_fd;
5111 frameinfo.pmem_offset = temp_buffer->offset;
5112 frameinfo.timestamp = buffer->nTimeStamp;
5113 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
5114 DEBUG_PRINT_LOW("ETB: dmx enabled");
5115 if (m_demux_entries == 0) {
5116 extract_demux_addr_offsets(buffer);
5117 }
5118
5119 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries);
5120 handle_demux_data(buffer);
5121 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
5122 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
5123 } else {
5124 frameinfo.desc_addr = NULL;
5125 frameinfo.desc_size = 0;
5126 }
5127 if (!arbitrary_bytes) {
5128 frameinfo.flags |= buffer->nFlags;
5129 }
5130
5131 #ifdef _ANDROID_
5132 if (m_debug_timestamp) {
5133 if (arbitrary_bytes) {
5134 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5135 m_timestamp_list.insert_ts(buffer->nTimeStamp);
5136 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
5137 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5138 m_timestamp_list.insert_ts(buffer->nTimeStamp);
5139 }
5140 }
5141 #endif
5142
5143 #ifdef INPUT_BUFFER_LOG
5144 if (inputBufferFile1) {
5145 fwrite((const char *)temp_buffer->bufferaddr,
5146 temp_buffer->buffer_len,1,inputBufferFile1);
5147 }
5148 #endif
5149
5150 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
5151 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5152 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5153 }
5154
5155 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5156 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
5157 frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
5158 h264_scratch.nFilledLen = 0;
5159 nal_count = 0;
5160 look_ahead_nal = false;
5161 frame_count = 0;
5162 if (m_frame_parser.mutils)
5163 m_frame_parser.mutils->initialize_frame_checking_environment();
5164 m_frame_parser.flush();
5165 h264_last_au_ts = LLONG_MAX;
5166 h264_last_au_flags = 0;
5167 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
5168 m_demux_entries = 0;
5169 }
5170 struct v4l2_buffer buf;
5171 struct v4l2_plane plane;
5172 memset( (void *)&buf, 0, sizeof(buf));
5173 memset( (void *)&plane, 0, sizeof(plane));
5174 int rc;
5175 unsigned long print_count;
5176 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
5177 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
5178 DEBUG_PRINT_HIGH("INPUT EOS reached") ;
5179 }
5180 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5181 buf.index = nPortIndex;
5182 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5183 buf.memory = V4L2_MEMORY_USERPTR;
5184 plane.bytesused = temp_buffer->buffer_len;
5185 plane.length = drv_ctx.ip_buf.buffer_size;
5186 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
5187 (unsigned long)temp_buffer->offset;
5188 plane.reserved[0] = temp_buffer->pmem_fd;
5189 plane.reserved[1] = temp_buffer->offset;
5190 plane.data_offset = 0;
5191 buf.m.planes = &plane;
5192 buf.length = 1;
5193 if (frameinfo.timestamp >= LLONG_MAX) {
5194 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
5195 }
5196 //assumption is that timestamp is in milliseconds
5197 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
5198 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
5199 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
5200
5201 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5202 if (rc) {
5203 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
5204 return OMX_ErrorHardware;
5205 }
5206 codec_config_flag = false;
5207 DEBUG_PRINT_LOW("%s: codec_config cleared", __FUNCTION__);
5208
5209 if (!streaming[OUTPUT_PORT]) {
5210 enum v4l2_buf_type buf_type;
5211 int ret,r;
5212
5213 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5214 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
5215 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5216 if (!ret) {
5217 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
5218 streaming[OUTPUT_PORT] = true;
5219 } else {
5220 /*TODO: How to handle this case */
5221 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
5222 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
5223 post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5224 OMX_COMPONENT_GENERATE_EBD);
5225 return OMX_ErrorBadParameter;
5226 }
5227 }
5228 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)",
5229 frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen);
5230 time_stamp_dts.insert_timestamp(buffer);
5231
5232 return ret;
5233 }
5234
5235 /* ======================================================================
5236 FUNCTION
5237 omx_vdec::FillThisBuffer
5238
5239 DESCRIPTION
5240 IL client uses this method to release the frame buffer
5241 after displaying them.
5242
5243 PARAMETERS
5244 None.
5245
5246 RETURN VALUE
5247 true/false
5248
5249 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5250 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
5251 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5252 {
5253 unsigned nPortIndex = buffer - client_buffers.get_il_buf_hdr();
5254
5255 if (m_state == OMX_StateInvalid) {
5256 DEBUG_PRINT_ERROR("FTB in Invalid State");
5257 return OMX_ErrorInvalidState;
5258 }
5259
5260 if (!m_out_bEnabled) {
5261 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
5262 return OMX_ErrorIncorrectStateOperation;
5263 }
5264
5265 if (buffer == NULL ||
5266 (nPortIndex >= drv_ctx.op_buf.actualcount)) {
5267 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
5268 nPortIndex, drv_ctx.op_buf.actualcount);
5269 return OMX_ErrorBadParameter;
5270 }
5271
5272 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
5273 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %lu", buffer->nOutputPortIndex);
5274 return OMX_ErrorBadPortIndex;
5275 }
5276
5277 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5278 post_event((unsigned) hComp, (unsigned)buffer, m_fill_output_msg);
5279 return OMX_ErrorNone;
5280 }
5281 /* ======================================================================
5282 FUNCTION
5283 omx_vdec::fill_this_buffer_proxy
5284
5285 DESCRIPTION
5286 IL client uses this method to release the frame buffer
5287 after displaying them.
5288
5289 PARAMETERS
5290 None.
5291
5292 RETURN VALUE
5293 true/false
5294
5295 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)5296 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
5297 OMX_IN OMX_HANDLETYPE hComp,
5298 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
5299 {
5300 OMX_ERRORTYPE nRet = OMX_ErrorNone;
5301 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
5302 unsigned nPortIndex = 0;
5303 struct vdec_fillbuffer_cmd fillbuffer;
5304 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
5305 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
5306
5307 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
5308
5309 if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) {
5310 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
5311 nPortIndex, drv_ctx.op_buf.actualcount);
5312 return OMX_ErrorBadParameter;
5313 }
5314
5315 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
5316 bufferAdd, bufferAdd->pBuffer);
5317 /*Return back the output buffer to client*/
5318 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
5319 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
5320 buffer->nFilledLen = 0;
5321 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5322 return OMX_ErrorNone;
5323 }
5324 pending_output_buffers++;
5325 buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
5326 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
5327 if (ptr_respbuffer) {
5328 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
5329 }
5330
5331 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
5332 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
5333 buffer->nFilledLen = 0;
5334 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5335 pending_output_buffers--;
5336 return OMX_ErrorBadParameter;
5337 }
5338
5339 int rc = 0;
5340 struct v4l2_buffer buf;
5341 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5342 memset( (void *)&buf, 0, sizeof(buf));
5343 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
5344 int extra_idx = 0;
5345
5346 buf.index = nPortIndex;
5347 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5348 buf.memory = V4L2_MEMORY_USERPTR;
5349 plane[0].bytesused = buffer->nFilledLen;
5350 plane[0].length = drv_ctx.op_buf.buffer_size;
5351 plane[0].m.userptr =
5352 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
5353 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
5354 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
5355 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
5356 plane[0].data_offset = 0;
5357 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5358 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5359 plane[extra_idx].bytesused = 0;
5360 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5361 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
5362 #ifdef USE_ION
5363 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5364 #endif
5365 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
5366 plane[extra_idx].data_offset = 0;
5367 } else if (extra_idx >= VIDEO_MAX_PLANES) {
5368 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d", extra_idx);
5369 return OMX_ErrorBadParameter;
5370 }
5371 buf.m.planes = plane;
5372 buf.length = drv_ctx.num_planes;
5373 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5374 if (rc) {
5375 /*TODO: How to handle this case */
5376 DEBUG_PRINT_ERROR("Failed to qbuf to driver");
5377 }
5378 return OMX_ErrorNone;
5379 }
5380
5381 /* ======================================================================
5382 FUNCTION
5383 omx_vdec::SetCallbacks
5384
5385 DESCRIPTION
5386 Set the callbacks.
5387
5388 PARAMETERS
5389 None.
5390
5391 RETURN VALUE
5392 OMX Error None if everything successful.
5393
5394 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)5395 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
5396 OMX_IN OMX_CALLBACKTYPE* callbacks,
5397 OMX_IN OMX_PTR appData)
5398 {
5399
5400 m_cb = *callbacks;
5401 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
5402 m_cb.EventHandler,m_cb.FillBufferDone);
5403 m_app_data = appData;
5404 return OMX_ErrorNotImplemented;
5405 }
5406
5407 /* ======================================================================
5408 FUNCTION
5409 omx_vdec::ComponentDeInit
5410
5411 DESCRIPTION
5412 Destroys the component and release memory allocated to the heap.
5413
5414 PARAMETERS
5415 <TBD>.
5416
5417 RETURN VALUE
5418 OMX Error None if everything successful.
5419
5420 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)5421 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
5422 {
5423 #ifdef _ANDROID_
5424 if (iDivXDrmDecrypt) {
5425 delete iDivXDrmDecrypt;
5426 iDivXDrmDecrypt=NULL;
5427 }
5428 #endif //_ANDROID_
5429
5430 unsigned i = 0;
5431 if (OMX_StateLoaded != m_state) {
5432 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
5433 m_state);
5434 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
5435 } else {
5436 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
5437 }
5438
5439 /*Check if the output buffers have to be cleaned up*/
5440 if (m_out_mem_ptr) {
5441 DEBUG_PRINT_LOW("Freeing the Output Memory");
5442 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
5443 free_output_buffer (&m_out_mem_ptr[i]);
5444 }
5445 #ifdef _ANDROID_ICS_
5446 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5447 #endif
5448 }
5449
5450 /*Check if the input buffers have to be cleaned up*/
5451 if (m_inp_mem_ptr || m_inp_heap_ptr) {
5452 DEBUG_PRINT_LOW("Freeing the Input Memory");
5453 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
5454 if (m_inp_mem_ptr)
5455 free_input_buffer (i,&m_inp_mem_ptr[i]);
5456 else
5457 free_input_buffer (i,NULL);
5458 }
5459 }
5460 free_input_buffer_header();
5461 free_output_buffer_header();
5462 if (h264_scratch.pBuffer) {
5463 free(h264_scratch.pBuffer);
5464 h264_scratch.pBuffer = NULL;
5465 }
5466
5467 if (h264_parser) {
5468 delete h264_parser;
5469 h264_parser = NULL;
5470 }
5471
5472 if (m_platform_list) {
5473 free(m_platform_list);
5474 m_platform_list = NULL;
5475 }
5476 if (m_vendor_config.pData) {
5477 free(m_vendor_config.pData);
5478 m_vendor_config.pData = NULL;
5479 }
5480
5481 // Reset counters in mesg queues
5482 m_ftb_q.m_size=0;
5483 m_cmd_q.m_size=0;
5484 m_etb_q.m_size=0;
5485 m_ftb_q.m_read = m_ftb_q.m_write =0;
5486 m_cmd_q.m_read = m_cmd_q.m_write =0;
5487 m_etb_q.m_read = m_etb_q.m_write =0;
5488 #ifdef _ANDROID_
5489 if (m_debug_timestamp) {
5490 m_timestamp_list.reset_ts_list();
5491 }
5492 #endif
5493
5494 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
5495 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
5496 // NULL);
5497 DEBUG_PRINT_HIGH("Close the driver instance");
5498
5499 #ifdef INPUT_BUFFER_LOG
5500 fclose (inputBufferFile1);
5501 #endif
5502 #ifdef OUTPUT_BUFFER_LOG
5503 if (outputBufferFile1)
5504 fclose (outputBufferFile1);
5505 #endif
5506 #ifdef OUTPUT_EXTRADATA_LOG
5507 fclose (outputExtradataFile);
5508 #endif
5509 DEBUG_PRINT_HIGH("omx_vdec::component_deinit() complete");
5510 return OMX_ErrorNone;
5511 }
5512
5513 /* ======================================================================
5514 FUNCTION
5515 omx_vdec::UseEGLImage
5516
5517 DESCRIPTION
5518 OMX Use EGL Image method implementation <TBD>.
5519
5520 PARAMETERS
5521 <TBD>.
5522
5523 RETURN VALUE
5524 Not Implemented error.
5525
5526 ========================================================================== */
use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN void * eglImage)5527 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
5528 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5529 OMX_IN OMX_U32 port,
5530 OMX_IN OMX_PTR appData,
5531 OMX_IN void* eglImage)
5532 {
5533 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
5534 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
5535 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
5536
5537 #ifdef USE_EGL_IMAGE_GPU
5538 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
5539 EGLint fd = -1, offset = 0,pmemPtr = 0;
5540 #else
5541 int fd = -1, offset = 0;
5542 #endif
5543 DEBUG_PRINT_HIGH("use EGL image support for decoder");
5544 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
5545 DEBUG_PRINT_ERROR("");
5546 }
5547 #ifdef USE_EGL_IMAGE_GPU
5548 if (m_display_id == NULL) {
5549 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
5550 return OMX_ErrorInsufficientResources;
5551 }
5552 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
5553 eglGetProcAddress("eglQueryImageKHR");
5554 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd);
5555 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset);
5556 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr);
5557 #else //with OMX test app
5558 struct temp_egl {
5559 int pmem_fd;
5560 int offset;
5561 };
5562 struct temp_egl *temp_egl_id = NULL;
5563 void * pmemPtr = (void *) eglImage;
5564 temp_egl_id = (struct temp_egl *)eglImage;
5565 if (temp_egl_id != NULL) {
5566 fd = temp_egl_id->pmem_fd;
5567 offset = temp_egl_id->offset;
5568 }
5569 #endif
5570 if (fd < 0) {
5571 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
5572 return OMX_ErrorInsufficientResources;
5573 }
5574 pmem_info.pmem_fd = (OMX_U32) fd;
5575 pmem_info.offset = (OMX_U32) offset;
5576 pmem_entry.entry = (void *) &pmem_info;
5577 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
5578 pmem_list.entryList = &pmem_entry;
5579 pmem_list.nEntries = 1;
5580 ouput_egl_buffers = true;
5581 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
5582 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
5583 (OMX_U8 *)pmemPtr)) {
5584 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
5585 return OMX_ErrorInsufficientResources;
5586 }
5587 return OMX_ErrorNone;
5588 }
5589
5590 /* ======================================================================
5591 FUNCTION
5592 omx_vdec::ComponentRoleEnum
5593
5594 DESCRIPTION
5595 OMX Component Role Enum method implementation.
5596
5597 PARAMETERS
5598 <TBD>.
5599
5600 RETURN VALUE
5601 OMX Error None if everything is successful.
5602 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)5603 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
5604 OMX_OUT OMX_U8* role,
5605 OMX_IN OMX_U32 index)
5606 {
5607 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5608
5609 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
5610 if ((0 == index) && role) {
5611 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
5612 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5613 } else {
5614 eRet = OMX_ErrorNoMore;
5615 }
5616 }
5617 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
5618 if ((0 == index) && role) {
5619 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
5620 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5621 } else {
5622 eRet = OMX_ErrorNoMore;
5623 }
5624 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
5625 if ((0 == index) && role) {
5626 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
5627 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5628 } else {
5629 DEBUG_PRINT_LOW("No more roles");
5630 eRet = OMX_ErrorNoMore;
5631 }
5632 }
5633
5634 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
5635 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) ) {
5636 if ((0 == index) && role) {
5637 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
5638 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5639 } else {
5640 DEBUG_PRINT_LOW("No more roles");
5641 eRet = OMX_ErrorNoMore;
5642 }
5643 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
5644 if ((0 == index) && role) {
5645 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
5646 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5647 } else {
5648 DEBUG_PRINT_LOW("No more roles");
5649 eRet = OMX_ErrorNoMore;
5650 }
5651 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",OMX_MAX_STRINGNAME_SIZE)) {
5652 if ((0 == index) && role) {
5653 strlcpy((char *)role, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
5654 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5655 } else {
5656 DEBUG_PRINT_LOW("No more roles");
5657 eRet = OMX_ErrorNoMore;
5658 }
5659 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
5660 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
5661 ) {
5662 if ((0 == index) && role) {
5663 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
5664 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5665 } else {
5666 DEBUG_PRINT_LOW("No more roles");
5667 eRet = OMX_ErrorNoMore;
5668 }
5669 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
5670 if ((0 == index) && role) {
5671 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
5672 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
5673 } else {
5674 DEBUG_PRINT_LOW("No more roles");
5675 eRet = OMX_ErrorNoMore;
5676 }
5677 } else {
5678 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
5679 eRet = OMX_ErrorInvalidComponentName;
5680 }
5681 return eRet;
5682 }
5683
5684
5685
5686
5687 /* ======================================================================
5688 FUNCTION
5689 omx_vdec::AllocateDone
5690
5691 DESCRIPTION
5692 Checks if entire buffer pool is allocated by IL Client or not.
5693 Need this to move to IDLE state.
5694
5695 PARAMETERS
5696 None.
5697
5698 RETURN VALUE
5699 true/false.
5700
5701 ========================================================================== */
allocate_done(void)5702 bool omx_vdec::allocate_done(void)
5703 {
5704 bool bRet = false;
5705 bool bRet_In = false;
5706 bool bRet_Out = false;
5707
5708 bRet_In = allocate_input_done();
5709 bRet_Out = allocate_output_done();
5710
5711 if (bRet_In && bRet_Out) {
5712 bRet = true;
5713 }
5714
5715 return bRet;
5716 }
5717 /* ======================================================================
5718 FUNCTION
5719 omx_vdec::AllocateInputDone
5720
5721 DESCRIPTION
5722 Checks if I/P buffer pool is allocated by IL Client or not.
5723
5724 PARAMETERS
5725 None.
5726
5727 RETURN VALUE
5728 true/false.
5729
5730 ========================================================================== */
allocate_input_done(void)5731 bool omx_vdec::allocate_input_done(void)
5732 {
5733 bool bRet = false;
5734 unsigned i=0;
5735
5736 if (m_inp_mem_ptr == NULL) {
5737 return bRet;
5738 }
5739 if (m_inp_mem_ptr ) {
5740 for (; i<drv_ctx.ip_buf.actualcount; i++) {
5741 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
5742 break;
5743 }
5744 }
5745 }
5746 if (i == drv_ctx.ip_buf.actualcount) {
5747 bRet = true;
5748 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
5749 }
5750 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
5751 m_inp_bPopulated = OMX_TRUE;
5752 }
5753 return bRet;
5754 }
5755 /* ======================================================================
5756 FUNCTION
5757 omx_vdec::AllocateOutputDone
5758
5759 DESCRIPTION
5760 Checks if entire O/P buffer pool is allocated by IL Client or not.
5761
5762 PARAMETERS
5763 None.
5764
5765 RETURN VALUE
5766 true/false.
5767
5768 ========================================================================== */
allocate_output_done(void)5769 bool omx_vdec::allocate_output_done(void)
5770 {
5771 bool bRet = false;
5772 unsigned j=0;
5773
5774 if (m_out_mem_ptr == NULL) {
5775 return bRet;
5776 }
5777
5778 if (m_out_mem_ptr) {
5779 for (; j < drv_ctx.op_buf.actualcount; j++) {
5780 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
5781 break;
5782 }
5783 }
5784 }
5785
5786 if (j == drv_ctx.op_buf.actualcount) {
5787 bRet = true;
5788 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
5789 if (m_out_bEnabled)
5790 m_out_bPopulated = OMX_TRUE;
5791 }
5792
5793 return bRet;
5794 }
5795
5796 /* ======================================================================
5797 FUNCTION
5798 omx_vdec::ReleaseDone
5799
5800 DESCRIPTION
5801 Checks if IL client has released all the buffers.
5802
5803 PARAMETERS
5804 None.
5805
5806 RETURN VALUE
5807 true/false
5808
5809 ========================================================================== */
release_done(void)5810 bool omx_vdec::release_done(void)
5811 {
5812 bool bRet = false;
5813
5814 if (release_input_done()) {
5815 if (release_output_done()) {
5816 bRet = true;
5817 }
5818 }
5819 return bRet;
5820 }
5821
5822
5823 /* ======================================================================
5824 FUNCTION
5825 omx_vdec::ReleaseOutputDone
5826
5827 DESCRIPTION
5828 Checks if IL client has released all the buffers.
5829
5830 PARAMETERS
5831 None.
5832
5833 RETURN VALUE
5834 true/false
5835
5836 ========================================================================== */
release_output_done(void)5837 bool omx_vdec::release_output_done(void)
5838 {
5839 bool bRet = false;
5840 unsigned i=0,j=0;
5841
5842 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_inp_mem_ptr);
5843 if (m_out_mem_ptr) {
5844 for (; j < drv_ctx.op_buf.actualcount ; j++) {
5845 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
5846 break;
5847 }
5848 }
5849 if (j == drv_ctx.op_buf.actualcount) {
5850 m_out_bm_count = 0;
5851 bRet = true;
5852 }
5853 } else {
5854 m_out_bm_count = 0;
5855 bRet = true;
5856 }
5857 return bRet;
5858 }
5859 /* ======================================================================
5860 FUNCTION
5861 omx_vdec::ReleaseInputDone
5862
5863 DESCRIPTION
5864 Checks if IL client has released all the buffers.
5865
5866 PARAMETERS
5867 None.
5868
5869 RETURN VALUE
5870 true/false
5871
5872 ========================================================================== */
release_input_done(void)5873 bool omx_vdec::release_input_done(void)
5874 {
5875 bool bRet = false;
5876 unsigned i=0,j=0;
5877
5878 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
5879 if (m_inp_mem_ptr) {
5880 for (; j<drv_ctx.ip_buf.actualcount; j++) {
5881 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
5882 break;
5883 }
5884 }
5885 if (j==drv_ctx.ip_buf.actualcount) {
5886 bRet = true;
5887 }
5888 } else {
5889 bRet = true;
5890 }
5891 return bRet;
5892 }
5893
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)5894 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
5895 OMX_BUFFERHEADERTYPE * buffer)
5896 {
5897 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
5898 if (!buffer || (buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount) {
5899 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
5900 return OMX_ErrorBadParameter;
5901 } else if (output_flush_progress) {
5902 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
5903 buffer->nFilledLen = 0;
5904 buffer->nTimeStamp = 0;
5905 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
5906 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5907 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
5908 }
5909
5910 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
5911 buffer, buffer->pBuffer);
5912 pending_output_buffers --;
5913
5914 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5915 DEBUG_PRINT_HIGH("Output EOS has been reached");
5916 if (!output_flush_progress)
5917 post_event((unsigned)NULL, (unsigned)NULL,
5918 OMX_COMPONENT_GENERATE_EOS_DONE);
5919
5920 if (psource_frame) {
5921 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
5922 psource_frame = NULL;
5923 }
5924 if (pdest_frame) {
5925 pdest_frame->nFilledLen = 0;
5926 m_input_free_q.insert_entry((unsigned) pdest_frame,(unsigned)NULL,
5927 (unsigned)NULL);
5928 pdest_frame = NULL;
5929 }
5930 }
5931
5932 DEBUG_PRINT_LOW("In fill Buffer done call address %p ",buffer);
5933 #ifdef OUTPUT_BUFFER_LOG
5934 if (outputBufferFile1 && buffer->nFilledLen) {
5935 int buf_index = buffer - m_out_mem_ptr;
5936 int stride = drv_ctx.video_resolution.stride;
5937 int scanlines = drv_ctx.video_resolution.scan_lines;
5938 char *temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
5939 int i;
5940 int bytes_written = 0;
5941 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
5942 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, outputBufferFile1);
5943 temp += stride;
5944 }
5945 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
5946 int stride_c = stride;
5947 for (i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
5948 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, outputBufferFile1);
5949 temp += stride_c;
5950 }
5951 }
5952 #endif
5953
5954 /* For use buffer we need to copy the data */
5955 if (!output_flush_progress) {
5956 time_stamp_dts.get_next_timestamp(buffer,
5957 (drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
5958 ?true:false);
5959 if (m_debug_timestamp) {
5960 {
5961 OMX_TICKS expected_ts = 0;
5962 m_timestamp_list.pop_min_ts(expected_ts);
5963 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
5964 buffer->nTimeStamp, expected_ts);
5965
5966 if (buffer->nTimeStamp != expected_ts) {
5967 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
5968 }
5969 }
5970 }
5971 }
5972 if (m_cb.FillBufferDone) {
5973 if (buffer->nFilledLen > 0) {
5974 handle_extradata(buffer);
5975 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
5976 // Keep min timestamp interval to handle corrupted bit stream scenario
5977 set_frame_rate(buffer->nTimeStamp);
5978 else if (arbitrary_bytes)
5979 adjust_timestamp(buffer->nTimeStamp);
5980 if (perf_flag) {
5981 if (!proc_frms) {
5982 dec_time.stop();
5983 latency = dec_time.processing_time_us() - latency;
5984 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
5985 dec_time.start();
5986 fps_metrics.start();
5987 }
5988 proc_frms++;
5989 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
5990 OMX_U64 proc_time = 0;
5991 fps_metrics.stop();
5992 proc_time = fps_metrics.processing_time_us();
5993 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)",
5994 proc_frms, (float)proc_time / 1e6,
5995 (float)(1e6 * proc_frms) / proc_time);
5996 proc_frms = 0;
5997 }
5998 }
5999
6000 #ifdef OUTPUT_EXTRADATA_LOG
6001 if (outputExtradataFile) {
6002
6003 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
6004 p_extra = (OMX_OTHER_EXTRADATATYPE *)
6005 ((unsigned)(buffer->pBuffer + buffer->nOffset +
6006 buffer->nFilledLen + 3)&(~3));
6007 while (p_extra &&
6008 (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) ) {
6009 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType);
6010 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
6011 if (p_extra->eType == OMX_ExtraDataNone) {
6012 break;
6013 }
6014 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
6015 }
6016 }
6017 #endif
6018 }
6019 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
6020 prev_ts = LLONG_MAX;
6021 rst_prev_ts = true;
6022 }
6023
6024 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6025 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
6026 buffer->pPlatformPrivate)->entryList->entry;
6027 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd);
6028 OMX_BUFFERHEADERTYPE *il_buffer;
6029 il_buffer = client_buffers.get_il_buf_hdr(buffer);
6030 if (il_buffer)
6031 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
6032 else {
6033 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
6034 return OMX_ErrorBadParameter;
6035 }
6036 DEBUG_PRINT_LOW("After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd);
6037 } else {
6038 return OMX_ErrorBadParameter;
6039 }
6040
6041 return OMX_ErrorNone;
6042 }
6043
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6044 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
6045 OMX_BUFFERHEADERTYPE* buffer)
6046 {
6047
6048 if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount)) {
6049 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
6050 return OMX_ErrorBadParameter;
6051 }
6052
6053 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
6054 buffer, buffer->pBuffer);
6055 pending_input_buffers--;
6056
6057 if (arbitrary_bytes) {
6058 if (pdest_frame == NULL && input_flush_progress == false) {
6059 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
6060 pdest_frame = buffer;
6061 buffer->nFilledLen = 0;
6062 buffer->nTimeStamp = LLONG_MAX;
6063 push_input_buffer (hComp);
6064 } else {
6065 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
6066 buffer->nFilledLen = 0;
6067 if (!m_input_free_q.insert_entry((unsigned)buffer,
6068 (unsigned)NULL, (unsigned)NULL)) {
6069 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
6070 }
6071 }
6072 } else if (m_cb.EmptyBufferDone) {
6073 buffer->nFilledLen = 0;
6074 if (input_use_buffer == true) {
6075 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
6076 }
6077 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
6078 }
6079 return OMX_ErrorNone;
6080 }
6081
async_message_process(void * context,void * message)6082 int omx_vdec::async_message_process (void *context, void* message)
6083 {
6084 omx_vdec* omx = NULL;
6085 struct vdec_msginfo *vdec_msg = NULL;
6086 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
6087 struct v4l2_buffer *v4l2_buf_ptr = NULL;
6088 struct vdec_output_frameinfo *output_respbuf = NULL;
6089 int rc=1;
6090 if (context == NULL || message == NULL) {
6091 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
6092 return -1;
6093 }
6094 vdec_msg = (struct vdec_msginfo *)message;
6095
6096 omx = reinterpret_cast<omx_vdec*>(context);
6097
6098 switch (vdec_msg->msgcode) {
6099
6100 case VDEC_MSG_EVT_HW_ERROR:
6101 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6102 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6103 break;
6104
6105 case VDEC_MSG_RESP_START_DONE:
6106 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6107 OMX_COMPONENT_GENERATE_START_DONE);
6108 break;
6109
6110 case VDEC_MSG_RESP_STOP_DONE:
6111 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6112 OMX_COMPONENT_GENERATE_STOP_DONE);
6113 break;
6114
6115 case VDEC_MSG_RESP_RESUME_DONE:
6116 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6117 OMX_COMPONENT_GENERATE_RESUME_DONE);
6118 break;
6119
6120 case VDEC_MSG_RESP_PAUSE_DONE:
6121 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6122 OMX_COMPONENT_GENERATE_PAUSE_DONE);
6123 break;
6124
6125 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
6126 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6127 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
6128 break;
6129 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
6130 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6131 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
6132 break;
6133 case VDEC_MSG_RESP_INPUT_FLUSHED:
6134 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
6135
6136 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
6137 vdec_msg->msgdata.input_frame_clientdata; */
6138
6139 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
6140 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index;
6141 if (omxhdr == NULL ||
6142 ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) ) {
6143 omxhdr = NULL;
6144 vdec_msg->status_code = VDEC_S_EFATAL;
6145 }
6146
6147 omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
6148 OMX_COMPONENT_GENERATE_EBD);
6149 break;
6150 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
6151 int64_t *timestamp;
6152 timestamp = (int64_t *) malloc(sizeof(int64_t));
6153 if (timestamp) {
6154 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
6155 omx->post_event ((unsigned int)timestamp, vdec_msg->status_code,
6156 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
6157 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
6158 vdec_msg->msgdata.output_frame.time_stamp);
6159 }
6160 break;
6161 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
6162 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
6163
6164 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
6165 omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index;
6166 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)",
6167 omxhdr, vdec_msg->msgdata.output_frame.time_stamp,
6168 vdec_msg->msgdata.output_frame.pic_type);
6169
6170 if (omxhdr && omxhdr->pOutputPortPrivate &&
6171 ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) &&
6172 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
6173 - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount)) {
6174 if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
6175 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
6176 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
6177 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
6178 omxhdr->nFlags = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nFlags;
6179
6180 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
6181 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
6182 //rc = -1;
6183 }
6184 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
6185 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6186 }
6187 vdec_msg->msgdata.output_frame.bufferaddr =
6188 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
6189 if (omxhdr->nFilledLen && (((unsigned)omx->rectangle.nLeft !=
6190 vdec_msg->msgdata.output_frame.framesize.left)
6191 || ((unsigned)omx->rectangle.nTop != vdec_msg->msgdata.output_frame.framesize.top)
6192 || (omx->rectangle.nWidth != vdec_msg->msgdata.output_frame.framesize.right)
6193 || (omx->rectangle.nHeight != vdec_msg->msgdata.output_frame.framesize.bottom))) {
6194 omx->rectangle.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
6195 omx->rectangle.nTop = vdec_msg->msgdata.output_frame.framesize.top;
6196 omx->rectangle.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
6197 omx->rectangle.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
6198 DEBUG_PRINT_HIGH("Crop information has changed");
6199 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexConfigCommonOutputCrop,
6200 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6201 }
6202 output_respbuf = (struct vdec_output_frameinfo *)\
6203 omxhdr->pOutputPortPrivate;
6204 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
6205 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
6206 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
6207 output_respbuf->pic_type = PICTURE_TYPE_I;
6208 }
6209 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
6210 output_respbuf->pic_type = PICTURE_TYPE_P;
6211 }
6212 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
6213 output_respbuf->pic_type = PICTURE_TYPE_B;
6214 }
6215
6216 if (omx->output_use_buffer)
6217 memcpy ( omxhdr->pBuffer, (void *)
6218 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
6219 (unsigned long)vdec_msg->msgdata.output_frame.offset),
6220 vdec_msg->msgdata.output_frame.len);
6221 } else
6222 omxhdr->nFilledLen = 0;
6223 omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code,
6224 OMX_COMPONENT_GENERATE_FBD);
6225 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS)
6226 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
6227 OMX_COMPONENT_GENERATE_EOS_DONE);
6228 else
6229 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
6230 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6231 break;
6232 case VDEC_MSG_EVT_CONFIG_CHANGED:
6233 DEBUG_PRINT_HIGH("Port settings changed");
6234 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
6235 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6236 break;
6237 case VDEC_MSG_EVT_INFO_CONFIG_CHANGED:
6238 {
6239 DEBUG_PRINT_HIGH("Port settings changed info");
6240 // get_buffer_req and populate port defn structure
6241 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6242 struct v4l2_format fmt;
6243 int ret;
6244 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6245 ret = ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
6246 omx->update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
6247 omx->drv_ctx.video_resolution.stride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
6248 omx->drv_ctx.video_resolution.scan_lines = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
6249 omx->m_port_def.nPortIndex = 1;
6250 eRet = omx->update_portdef(&(omx->m_port_def));
6251 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
6252 OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG);
6253 break;
6254 }
6255 default:
6256 break;
6257 }
6258 return rc;
6259 }
6260
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6261 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
6262 OMX_HANDLETYPE hComp,
6263 OMX_BUFFERHEADERTYPE *buffer
6264 )
6265 {
6266 unsigned address,p2,id;
6267 DEBUG_PRINT_LOW("Empty this arbitrary");
6268
6269 if (buffer == NULL) {
6270 return OMX_ErrorBadParameter;
6271 }
6272 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6273 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %d, timestamp %u",
6274 buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp);
6275
6276 /* return zero length and not an EOS buffer */
6277 /* return buffer if input flush in progress */
6278 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
6279 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
6280 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
6281 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
6282 return OMX_ErrorNone;
6283 }
6284
6285 if (psource_frame == NULL) {
6286 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp);
6287 psource_frame = buffer;
6288 DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
6289 push_input_buffer (hComp);
6290 } else {
6291 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
6292 if (!m_input_pending_q.insert_entry((unsigned)buffer, (unsigned)NULL,
6293 (unsigned)NULL)) {
6294 return OMX_ErrorBadParameter;
6295 }
6296 }
6297
6298
6299 return OMX_ErrorNone;
6300 }
6301
push_input_buffer(OMX_HANDLETYPE hComp)6302 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
6303 {
6304 unsigned address,p2,id;
6305 OMX_ERRORTYPE ret = OMX_ErrorNone;
6306
6307 if (pdest_frame == NULL || psource_frame == NULL) {
6308 /*Check if we have a destination buffer*/
6309 if (pdest_frame == NULL) {
6310 DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
6311 if (m_input_free_q.m_size) {
6312 m_input_free_q.pop_entry(&address,&p2,&id);
6313 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
6314 pdest_frame->nFilledLen = 0;
6315 pdest_frame->nTimeStamp = LLONG_MAX;
6316 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
6317 }
6318 }
6319
6320 /*Check if we have a destination buffer*/
6321 if (psource_frame == NULL) {
6322 DEBUG_PRINT_LOW("Get a source buffer from the queue");
6323 if (m_input_pending_q.m_size) {
6324 m_input_pending_q.pop_entry(&address,&p2,&id);
6325 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
6326 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame,
6327 psource_frame->nTimeStamp);
6328 DEBUG_PRINT_LOW("Next source Buffer flag %d length %d",
6329 psource_frame->nFlags,psource_frame->nFilledLen);
6330
6331 }
6332 }
6333
6334 }
6335
6336 while ((pdest_frame != NULL) && (psource_frame != NULL)) {
6337 switch (codec_type_parse) {
6338 case CODEC_TYPE_MPEG4:
6339 case CODEC_TYPE_H263:
6340 case CODEC_TYPE_MPEG2:
6341 ret = push_input_sc_codec(hComp);
6342 break;
6343 case CODEC_TYPE_H264:
6344 ret = push_input_h264(hComp);
6345 break;
6346 case CODEC_TYPE_HEVC:
6347 ret = push_input_hevc(hComp);
6348 break;
6349 case CODEC_TYPE_VC1:
6350 ret = push_input_vc1(hComp);
6351 break;
6352 default:
6353 break;
6354 }
6355 if (ret != OMX_ErrorNone) {
6356 DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
6357 omx_report_error ();
6358 break;
6359 }
6360 }
6361
6362 return ret;
6363 }
6364
push_input_sc_codec(OMX_HANDLETYPE hComp)6365 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
6366 {
6367 OMX_U32 partial_frame = 1;
6368 OMX_BOOL generate_ebd = OMX_TRUE;
6369 unsigned address,p2,id;
6370
6371 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %d",
6372 psource_frame,psource_frame->nTimeStamp);
6373 if (m_frame_parser.parse_sc_frame(psource_frame,
6374 pdest_frame,&partial_frame) == -1) {
6375 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6376 return OMX_ErrorBadParameter;
6377 }
6378
6379 if (partial_frame == 0) {
6380 DEBUG_PRINT_LOW("Frame size %d source %p frame count %d",
6381 pdest_frame->nFilledLen,psource_frame,frame_count);
6382
6383
6384 DEBUG_PRINT_LOW("TimeStamp updated %d",pdest_frame->nTimeStamp);
6385 /*First Parsed buffer will have only header Hence skip*/
6386 if (frame_count == 0) {
6387 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
6388
6389 if (codec_type_parse == CODEC_TYPE_MPEG4 ||
6390 codec_type_parse == CODEC_TYPE_DIVX) {
6391 mp4StreamType psBits;
6392 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
6393 psBits.numBytes = pdest_frame->nFilledLen;
6394 mp4_headerparser.parseHeader(&psBits);
6395 }
6396
6397 frame_count++;
6398 } else {
6399 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6400 if (pdest_frame->nFilledLen) {
6401 /*Push the frame to the Decoder*/
6402 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6403 return OMX_ErrorBadParameter;
6404 }
6405 frame_count++;
6406 pdest_frame = NULL;
6407
6408 if (m_input_free_q.m_size) {
6409 m_input_free_q.pop_entry(&address,&p2,&id);
6410 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6411 pdest_frame->nFilledLen = 0;
6412 }
6413 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
6414 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
6415 m_input_free_q.insert_entry((unsigned) pdest_frame, (unsigned)NULL,
6416 (unsigned)NULL);
6417 pdest_frame = NULL;
6418 }
6419 }
6420 } else {
6421 DEBUG_PRINT_LOW("Not a Complete Frame %d",pdest_frame->nFilledLen);
6422 /*Check if Destination Buffer is full*/
6423 if (pdest_frame->nAllocLen ==
6424 pdest_frame->nFilledLen + pdest_frame->nOffset) {
6425 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
6426 return OMX_ErrorStreamCorrupt;
6427 }
6428 }
6429
6430 if (psource_frame->nFilledLen == 0) {
6431 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6432 if (pdest_frame) {
6433 pdest_frame->nFlags |= psource_frame->nFlags;
6434 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x",
6435 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6436 DEBUG_PRINT_LOW("Found a frame size = %d number = %d",
6437 pdest_frame->nFilledLen,frame_count++);
6438 /*Push the frame to the Decoder*/
6439 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6440 return OMX_ErrorBadParameter;
6441 }
6442 frame_count++;
6443 pdest_frame = NULL;
6444 } else {
6445 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
6446 generate_ebd = OMX_FALSE;
6447 }
6448 }
6449 if (generate_ebd) {
6450 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
6451 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6452 psource_frame = NULL;
6453
6454 if (m_input_pending_q.m_size) {
6455 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
6456 m_input_pending_q.pop_entry(&address,&p2,&id);
6457 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6458 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame,
6459 psource_frame->nTimeStamp);
6460 DEBUG_PRINT_LOW("Next source Buffer flag %d length %d",
6461 psource_frame->nFlags,psource_frame->nFilledLen);
6462 }
6463 }
6464 }
6465 return OMX_ErrorNone;
6466 }
6467
push_input_h264(OMX_HANDLETYPE hComp)6468 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
6469 {
6470 OMX_U32 partial_frame = 1;
6471 unsigned address,p2,id;
6472 OMX_BOOL isNewFrame = OMX_FALSE;
6473 OMX_BOOL generate_ebd = OMX_TRUE;
6474
6475 if (h264_scratch.pBuffer == NULL) {
6476 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
6477 return OMX_ErrorBadParameter;
6478 }
6479 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %d "
6480 "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal);
6481 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
6482 if (h264_scratch.nFilledLen && look_ahead_nal) {
6483 look_ahead_nal = false;
6484 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6485 h264_scratch.nFilledLen) {
6486 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6487 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6488 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6489 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
6490 h264_scratch.nFilledLen = 0;
6491 } else {
6492 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
6493 return OMX_ErrorBadParameter;
6494 }
6495 }
6496 if (nal_length == 0) {
6497 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
6498 if (m_frame_parser.parse_sc_frame(psource_frame,
6499 &h264_scratch,&partial_frame) == -1) {
6500 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6501 return OMX_ErrorBadParameter;
6502 }
6503 } else {
6504 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
6505 if (m_frame_parser.parse_h264_nallength(psource_frame,
6506 &h264_scratch,&partial_frame) == -1) {
6507 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
6508 return OMX_ErrorBadParameter;
6509 }
6510 }
6511
6512 if (partial_frame == 0) {
6513 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
6514 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
6515 nal_count++;
6516 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
6517 h264_scratch.nFlags = psource_frame->nFlags;
6518 } else {
6519 DEBUG_PRINT_LOW("Parsed New NAL Length = %d",h264_scratch.nFilledLen);
6520 if (h264_scratch.nFilledLen) {
6521 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
6522 NALU_TYPE_SPS);
6523 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6524 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
6525 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6526 h264_scratch.nFilledLen, NALU_TYPE_SEI);
6527 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6528 // If timeinfo is present frame info from SEI is already processed
6529 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6530 h264_scratch.nFilledLen, NALU_TYPE_SEI);
6531 #endif
6532 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
6533 nal_count++;
6534 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
6535 pdest_frame->nTimeStamp = h264_last_au_ts;
6536 pdest_frame->nFlags = h264_last_au_flags;
6537 #ifdef PANSCAN_HDLR
6538 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6539 h264_parser->update_panscan_data(h264_last_au_ts);
6540 #endif
6541 }
6542 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
6543 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
6544 h264_last_au_ts = h264_scratch.nTimeStamp;
6545 h264_last_au_flags = h264_scratch.nFlags;
6546 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6547 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
6548 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
6549 if (!VALID_TS(h264_last_au_ts))
6550 h264_last_au_ts = ts_in_sei;
6551 }
6552 #endif
6553 } else
6554 h264_last_au_ts = LLONG_MAX;
6555 }
6556
6557 if (!isNewFrame) {
6558 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6559 h264_scratch.nFilledLen) {
6560 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %d",
6561 h264_scratch.nFilledLen);
6562 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6563 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6564 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6565 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
6566 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6567 h264_scratch.nFilledLen = 0;
6568 } else {
6569 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
6570 return OMX_ErrorBadParameter;
6571 }
6572 } else {
6573 look_ahead_nal = true;
6574 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x",
6575 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6576 DEBUG_PRINT_LOW("Found a frame size = %d number = %d",
6577 pdest_frame->nFilledLen,frame_count++);
6578
6579 if (pdest_frame->nFilledLen == 0) {
6580 DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
6581 look_ahead_nal = false;
6582 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6583 h264_scratch.nFilledLen) {
6584 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6585 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6586 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6587 h264_scratch.nFilledLen = 0;
6588 } else {
6589 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
6590 return OMX_ErrorBadParameter;
6591 }
6592 } else {
6593 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
6594 DEBUG_PRINT_LOW("Reset the EOS Flag");
6595 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6596 }
6597 /*Push the frame to the Decoder*/
6598 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6599 return OMX_ErrorBadParameter;
6600 }
6601 //frame_count++;
6602 pdest_frame = NULL;
6603 if (m_input_free_q.m_size) {
6604 m_input_free_q.pop_entry(&address,&p2,&id);
6605 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6606 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
6607 pdest_frame->nFilledLen = 0;
6608 pdest_frame->nFlags = 0;
6609 pdest_frame->nTimeStamp = LLONG_MAX;
6610 }
6611 }
6612 }
6613 }
6614 } else {
6615 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
6616 /*Check if Destination Buffer is full*/
6617 if (h264_scratch.nAllocLen ==
6618 h264_scratch.nFilledLen + h264_scratch.nOffset) {
6619 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
6620 return OMX_ErrorStreamCorrupt;
6621 }
6622 }
6623
6624 if (!psource_frame->nFilledLen) {
6625 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
6626
6627 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6628 if (pdest_frame) {
6629 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
6630 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6631 h264_scratch.nFilledLen) {
6632 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6633 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6634 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6635 h264_scratch.nFilledLen = 0;
6636 } else {
6637 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
6638 return OMX_ErrorBadParameter;
6639 }
6640 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
6641 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
6642
6643 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%d TimeStamp = %x",
6644 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6645 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
6646 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6647 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
6648 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
6649 if (!VALID_TS(pdest_frame->nTimeStamp))
6650 pdest_frame->nTimeStamp = ts_in_sei;
6651 }
6652 #endif
6653 /*Push the frame to the Decoder*/
6654 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6655 return OMX_ErrorBadParameter;
6656 }
6657 frame_count++;
6658 pdest_frame = NULL;
6659 } else {
6660 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %d",
6661 pdest_frame,h264_scratch.nFilledLen);
6662 generate_ebd = OMX_FALSE;
6663 }
6664 }
6665 }
6666 if (generate_ebd && !psource_frame->nFilledLen) {
6667 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6668 psource_frame = NULL;
6669 if (m_input_pending_q.m_size) {
6670 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
6671 m_input_pending_q.pop_entry(&address,&p2,&id);
6672 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6673 DEBUG_PRINT_LOW("Next source Buffer flag %d src length %d",
6674 psource_frame->nFlags,psource_frame->nFilledLen);
6675 }
6676 }
6677 return OMX_ErrorNone;
6678 }
6679
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)6680 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
6681 {
6682 OMX_ERRORTYPE rc = OMX_ErrorNone;
6683 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
6684 memcpy ((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
6685 if (pDst->nTimeStamp == LLONG_MAX) {
6686 pDst->nTimeStamp = pSrc->nTimeStamp;
6687 DEBUG_PRINT_LOW("Assign Dst nTimeStamp=%lld", pDst->nTimeStamp);
6688 }
6689 pDst->nFilledLen += pSrc->nFilledLen;
6690 pSrc->nFilledLen = 0;
6691 } else {
6692 DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
6693 rc = OMX_ErrorBadParameter;
6694 }
6695 return rc;
6696 }
6697
push_input_hevc(OMX_HANDLETYPE hComp)6698 OMX_ERRORTYPE omx_vdec::push_input_hevc (OMX_HANDLETYPE hComp)
6699 {
6700 OMX_U32 partial_frame = 1;
6701 unsigned address,p2,id;
6702 OMX_BOOL isNewFrame = OMX_FALSE;
6703 OMX_BOOL generate_ebd = OMX_TRUE;
6704 OMX_ERRORTYPE rc = OMX_ErrorNone;
6705
6706 if (h264_scratch.pBuffer == NULL) {
6707 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
6708 return OMX_ErrorBadParameter;
6709 }
6710
6711
6712 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %d has look_ahead_nal %d pdest_frame nFilledLen %d nTimeStamp %lld",
6713 h264_scratch.nFilledLen, look_ahead_nal, pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
6714
6715 if (h264_scratch.nFilledLen && look_ahead_nal) {
6716 look_ahead_nal = false;
6717
6718 // copy the lookahead buffer in the scratch
6719 rc = copy_buffer(pdest_frame, &h264_scratch);
6720 if (rc != OMX_ErrorNone) {
6721 return rc;
6722 }
6723 }
6724 if (nal_length == 0) {
6725 if (m_frame_parser.parse_sc_frame(psource_frame,
6726 &h264_scratch,&partial_frame) == -1) {
6727 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
6728 return OMX_ErrorBadParameter;
6729 }
6730 } else {
6731 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
6732 if (m_frame_parser.parse_h264_nallength(psource_frame,
6733 &h264_scratch,&partial_frame) == -1) {
6734 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
6735 return OMX_ErrorBadParameter;
6736 }
6737 }
6738
6739 if (partial_frame == 0) {
6740 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
6741 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
6742 nal_count++;
6743 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
6744 h264_scratch.nFlags = psource_frame->nFlags;
6745 } else {
6746 DEBUG_PRINT_LOW("Parsed New NAL Length = %d",h264_scratch.nFilledLen);
6747 if (h264_scratch.nFilledLen) {
6748 mHEVCutils.isNewFrame(&h264_scratch, 0, isNewFrame);
6749 nal_count++;
6750 }
6751
6752 if (!isNewFrame) {
6753 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %d nTimestamp %lld, pdest_frame nFilledLen %d nTimestamp %lld",
6754 h264_scratch.nFilledLen, h264_scratch.nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
6755 rc = copy_buffer(pdest_frame, &h264_scratch);
6756 if ( rc != OMX_ErrorNone) {
6757 return rc;
6758 }
6759 } else {
6760 look_ahead_nal = true;
6761 if (pdest_frame->nFilledLen == 0) {
6762 look_ahead_nal = false;
6763 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
6764 rc = copy_buffer(pdest_frame, &h264_scratch);
6765 if ( rc != OMX_ErrorNone ) {
6766 return OMX_ErrorBadParameter;
6767 }
6768 } else {
6769 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
6770 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6771 }
6772
6773 DEBUG_PRINT_LOW("FrameDetecetd # %d pdest_frame nFilledLen %d nTimeStamp %lld, look_ahead_nal in h264_scratch nFilledLen %d nTimeStamp %lld",
6774 frame_count++, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
6775 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6776 return OMX_ErrorBadParameter;
6777 }
6778 pdest_frame = NULL;
6779 if (m_input_free_q.m_size) {
6780 m_input_free_q.pop_entry(&address,&p2,&id);
6781 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6782 DEBUG_PRINT_LOW("pop the next pdest_buffer %p",pdest_frame);
6783 pdest_frame->nFilledLen = 0;
6784 pdest_frame->nFlags = 0;
6785 pdest_frame->nTimeStamp = LLONG_MAX;
6786 }
6787 }
6788 }
6789 }
6790 } else {
6791 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %d nTimeStamp %lld, pdest_frame nFilledLen %d nTimeStamp %lld, h264_scratch nFilledLen %d nTimeStamp %lld",
6792 psource_frame->nFilledLen, psource_frame->nTimeStamp, pdest_frame->nFilledLen, pdest_frame->nTimeStamp, h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
6793
6794 /*Check if Destination Buffer is full*/
6795 if (h264_scratch.nAllocLen ==
6796 h264_scratch.nFilledLen + h264_scratch.nOffset) {
6797 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
6798 return OMX_ErrorStreamCorrupt;
6799 }
6800 }
6801
6802 if (!psource_frame->nFilledLen) {
6803 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
6804
6805 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
6806 if (pdest_frame) {
6807 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
6808 rc = copy_buffer(pdest_frame, &h264_scratch);
6809 if ( rc != OMX_ErrorNone ) {
6810 return rc;
6811 }
6812 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
6813 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
6814
6815 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%d TimeStamp = %lld",
6816 frame_count, pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6817
6818 /*Push the frame to the Decoder*/
6819 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
6820 return OMX_ErrorBadParameter;
6821 }
6822 frame_count++;
6823 pdest_frame = NULL;
6824 } else {
6825 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %d",
6826 pdest_frame,h264_scratch.nFilledLen);
6827 generate_ebd = OMX_FALSE;
6828 }
6829 }
6830 }
6831 if (generate_ebd && !psource_frame->nFilledLen) {
6832 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6833 psource_frame = NULL;
6834 if (m_input_pending_q.m_size) {
6835 m_input_pending_q.pop_entry(&address,&p2,&id);
6836 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6837 DEBUG_PRINT_LOW("Next source Buffer flag %d nFilledLen %d, nTimeStamp %lld",
6838 psource_frame->nFlags,psource_frame->nFilledLen, psource_frame->nTimeStamp);
6839 }
6840 }
6841 return OMX_ErrorNone;
6842 }
6843
push_input_vc1(OMX_HANDLETYPE hComp)6844 OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
6845 {
6846 OMX_U8 *buf, *pdest;
6847 OMX_U32 partial_frame = 1;
6848 OMX_U32 buf_len, dest_len;
6849
6850 if (first_frame == 0) {
6851 first_frame = 1;
6852 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
6853 if (!m_vendor_config.pData) {
6854 DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
6855 buf = psource_frame->pBuffer;
6856 buf_len = psource_frame->nFilledLen;
6857
6858 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
6859 VC1_SP_MP_START_CODE) {
6860 m_vc1_profile = VC1_SP_MP_RCV;
6861 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
6862 m_vc1_profile = VC1_AP;
6863 } else {
6864 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
6865 return OMX_ErrorStreamCorrupt;
6866 }
6867 } else {
6868 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
6869 pdest_frame->nOffset;
6870 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
6871 pdest_frame->nOffset);
6872
6873 if (dest_len < m_vendor_config.nDataSize) {
6874 DEBUG_PRINT_ERROR("Destination buffer full");
6875 return OMX_ErrorBadParameter;
6876 } else {
6877 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
6878 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
6879 }
6880 }
6881 }
6882
6883 switch (m_vc1_profile) {
6884 case VC1_AP:
6885 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
6886 if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
6887 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
6888 return OMX_ErrorBadParameter;
6889 }
6890 break;
6891
6892 case VC1_SP_MP_RCV:
6893 default:
6894 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
6895 return OMX_ErrorBadParameter;
6896 }
6897 return OMX_ErrorNone;
6898 }
6899
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)6900 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
6901 OMX_U32 alignment)
6902 {
6903 struct pmem_allocation allocation;
6904 allocation.size = buffer_size;
6905 allocation.align = clip2(alignment);
6906 if (allocation.align < 4096) {
6907 allocation.align = 4096;
6908 }
6909 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
6910 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
6911 allocation.align, allocation.size);
6912 return false;
6913 }
6914 return true;
6915 }
6916 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,OMX_U32 alignment,struct ion_allocation_data * alloc_data,struct ion_fd_data * fd_data,int flag)6917 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
6918 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
6919 struct ion_fd_data *fd_data, int flag)
6920 {
6921 int fd = -EINVAL;
6922 int rc = -EINVAL;
6923 int ion_dev_flag;
6924 struct vdec_ion ion_buf_info;
6925 if (!alloc_data || buffer_size <= 0 || !fd_data) {
6926 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
6927 return -EINVAL;
6928 }
6929 ion_dev_flag = O_RDONLY;
6930 fd = open (MEM_DEVICE, ion_dev_flag);
6931 if (fd < 0) {
6932 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
6933 return fd;
6934 }
6935 alloc_data->flags = 0;
6936 if (!secure_mode && (flag & ION_FLAG_CACHED)) {
6937 alloc_data->flags |= ION_FLAG_CACHED;
6938 }
6939 alloc_data->len = buffer_size;
6940 alloc_data->align = clip2(alignment);
6941 if (alloc_data->align < 4096) {
6942 alloc_data->align = 4096;
6943 }
6944 if ((secure_mode) && (flag & ION_SECURE))
6945 alloc_data->flags |= ION_SECURE;
6946
6947 #ifdef _HEVC_USE_ADSP_HEAP_
6948 alloc_data->heap_id_mask = ION_HEAP(ION_ADSP_HEAP_ID);
6949 #else
6950 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
6951 #endif
6952 if (secure_mode) {
6953 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
6954 }
6955 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
6956 if (rc || !alloc_data->handle) {
6957 DEBUG_PRINT_ERROR("ION ALLOC memory failed ");
6958 alloc_data->handle = NULL;
6959 close(fd);
6960 fd = -ENOMEM;
6961 return fd;
6962 }
6963 fd_data->handle = alloc_data->handle;
6964 rc = ioctl(fd,ION_IOC_MAP,fd_data);
6965 if (rc) {
6966 DEBUG_PRINT_ERROR("ION MAP failed ");
6967 ion_buf_info.ion_alloc_data = *alloc_data;
6968 ion_buf_info.ion_device_fd = fd;
6969 ion_buf_info.fd_ion_data = *fd_data;
6970 free_ion_memory(&ion_buf_info);
6971 fd_data->fd =-1;
6972 fd = -ENOMEM;
6973 }
6974
6975 return fd;
6976 }
6977
free_ion_memory(struct vdec_ion * buf_ion_info)6978 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
6979 {
6980
6981 if (!buf_ion_info) {
6982 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
6983 return;
6984 }
6985 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
6986 &buf_ion_info->ion_alloc_data.handle)) {
6987 DEBUG_PRINT_ERROR("ION: free failed" );
6988 }
6989 close(buf_ion_info->ion_device_fd);
6990 buf_ion_info->ion_device_fd = -1;
6991 buf_ion_info->ion_alloc_data.handle = NULL;
6992 buf_ion_info->fd_ion_data.fd = -1;
6993 }
6994 #endif
free_output_buffer_header()6995 void omx_vdec::free_output_buffer_header()
6996 {
6997 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
6998 output_use_buffer = false;
6999 ouput_egl_buffers = false;
7000
7001 if (m_out_mem_ptr) {
7002 free (m_out_mem_ptr);
7003 m_out_mem_ptr = NULL;
7004 }
7005
7006 if (m_platform_list) {
7007 free(m_platform_list);
7008 m_platform_list = NULL;
7009 }
7010
7011 if (drv_ctx.ptr_respbuffer) {
7012 free (drv_ctx.ptr_respbuffer);
7013 drv_ctx.ptr_respbuffer = NULL;
7014 }
7015 if (drv_ctx.ptr_outputbuffer) {
7016 free (drv_ctx.ptr_outputbuffer);
7017 drv_ctx.ptr_outputbuffer = NULL;
7018 }
7019 #ifdef USE_ION
7020 if (drv_ctx.op_buf_ion_info) {
7021 DEBUG_PRINT_LOW("Free o/p ion context");
7022 free(drv_ctx.op_buf_ion_info);
7023 drv_ctx.op_buf_ion_info = NULL;
7024 }
7025 #endif
7026 }
7027
free_input_buffer_header()7028 void omx_vdec::free_input_buffer_header()
7029 {
7030 input_use_buffer = false;
7031 if (arbitrary_bytes) {
7032 if (m_frame_parser.mutils) {
7033 DEBUG_PRINT_LOW("Free utils parser");
7034 delete (m_frame_parser.mutils);
7035 m_frame_parser.mutils = NULL;
7036 }
7037
7038 if (m_inp_heap_ptr) {
7039 DEBUG_PRINT_LOW("Free input Heap Pointer");
7040 free (m_inp_heap_ptr);
7041 m_inp_heap_ptr = NULL;
7042 }
7043
7044 if (m_phdr_pmem_ptr) {
7045 DEBUG_PRINT_LOW("Free input pmem header Pointer");
7046 free (m_phdr_pmem_ptr);
7047 m_phdr_pmem_ptr = NULL;
7048 }
7049 }
7050 if (m_inp_mem_ptr) {
7051 DEBUG_PRINT_LOW("Free input pmem Pointer area");
7052 free (m_inp_mem_ptr);
7053 m_inp_mem_ptr = NULL;
7054 }
7055 if (drv_ctx.ptr_inputbuffer) {
7056 DEBUG_PRINT_LOW("Free Driver Context pointer");
7057 free (drv_ctx.ptr_inputbuffer);
7058 drv_ctx.ptr_inputbuffer = NULL;
7059 }
7060 #ifdef USE_ION
7061 if (drv_ctx.ip_buf_ion_info) {
7062 DEBUG_PRINT_LOW("Free ion context");
7063 free(drv_ctx.ip_buf_ion_info);
7064 drv_ctx.ip_buf_ion_info = NULL;
7065 }
7066 #endif
7067 }
7068
stream_off(OMX_U32 port)7069 int omx_vdec::stream_off(OMX_U32 port)
7070 {
7071 enum v4l2_buf_type btype;
7072 int rc = 0;
7073 enum v4l2_ports v4l2_port = OUTPUT_PORT;
7074
7075 if (port == OMX_CORE_INPUT_PORT_INDEX) {
7076 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7077 v4l2_port = OUTPUT_PORT;
7078 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7079 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7080 v4l2_port = CAPTURE_PORT;
7081 } else if (port == OMX_ALL) {
7082 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
7083 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
7084
7085 if (!rc_input)
7086 return rc_input;
7087 else
7088 return rc_output;
7089 }
7090
7091 if (!streaming[v4l2_port]) {
7092 // already streamed off, warn and move on
7093 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
7094 " which is already streamed off", v4l2_port);
7095 return 0;
7096 }
7097
7098 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
7099
7100 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
7101 if (rc) {
7102 /*TODO: How to handle this case */
7103 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
7104 } else {
7105 streaming[v4l2_port] = false;
7106 }
7107
7108 return rc;
7109 }
7110
get_buffer_req(vdec_allocatorproperty * buffer_prop)7111 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
7112 {
7113 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7114 struct v4l2_requestbuffers bufreq;
7115 unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
7116 struct v4l2_format fmt;
7117 int ret = 0;
7118
7119 bufreq.memory = V4L2_MEMORY_USERPTR;
7120 bufreq.count = 1;
7121 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7122 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7123 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7124 fmt.fmt.pix_mp.pixelformat = output_capability;
7125 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7126 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7127 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7128 fmt.fmt.pix_mp.pixelformat = capture_capability;
7129 } else {
7130 eRet = OMX_ErrorBadParameter;
7131 }
7132 if (eRet==OMX_ErrorNone) {
7133 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7134 }
7135 if (ret) {
7136 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7137 /*TODO: How to handle this case */
7138 eRet = OMX_ErrorInsufficientResources;
7139 return eRet;
7140 } else {
7141 buffer_prop->actualcount = bufreq.count;
7142 buffer_prop->mincount = bufreq.count;
7143 DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
7144 }
7145 DEBUG_PRINT_HIGH("GetBufReq: ActCnt(%d) Size(%d), BufType(%d)",
7146 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type);
7147
7148 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7149 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7150
7151 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7152
7153 update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
7154 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
7155 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
7156 DEBUG_PRINT_HIGH("Buffer Size (plane[0].sizeimage) = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
7157
7158 if (ret) {
7159 /*TODO: How to handle this case */
7160 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7161 eRet = OMX_ErrorInsufficientResources;
7162 } else {
7163 int extra_idx = 0;
7164 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
7165 buf_size = buffer_prop->buffer_size;
7166 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7167 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7168 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
7169 } else if (extra_idx >= VIDEO_MAX_PLANES) {
7170 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
7171 return OMX_ErrorBadParameter;
7172 }
7173 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
7174 DEBUG_PRINT_HIGH("Frame info extra data enabled!");
7175 client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
7176 }
7177 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
7178 client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE;
7179 }
7180 if (client_extradata & OMX_PORTDEF_EXTRADATA) {
7181 client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE;
7182 DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d",
7183 client_extra_data_size);
7184 }
7185 if (client_extra_data_size) {
7186 client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
7187 buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
7188 }
7189 drv_ctx.extradata_info.size = buffer_prop->actualcount * extra_data_size;
7190 drv_ctx.extradata_info.count = buffer_prop->actualcount;
7191 drv_ctx.extradata_info.buffer_size = extra_data_size;
7192 buf_size += client_extra_data_size;
7193 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7194 DEBUG_PRINT_HIGH("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d) BufType(%d)",
7195 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size, buffer_prop->buffer_type);
7196 if (in_reconfig) // BufReq will be set to driver when port is disabled
7197 buffer_prop->buffer_size = buf_size;
7198 else if (buf_size != buffer_prop->buffer_size) {
7199 buffer_prop->buffer_size = buf_size;
7200 eRet = set_buffer_req(buffer_prop);
7201 }
7202 }
7203 DEBUG_PRINT_HIGH("GetBufReq OUT: ActCnt(%d) Size(%d), BufType(%d)",
7204 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type);
7205 return eRet;
7206 }
7207
set_buffer_req(vdec_allocatorproperty * buffer_prop)7208 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
7209 {
7210 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7211 unsigned buf_size = 0;
7212 struct v4l2_format fmt;
7213 struct v4l2_requestbuffers bufreq;
7214 int ret;
7215 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)",
7216 buffer_prop->actualcount, buffer_prop->buffer_size);
7217 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7218 if (buf_size != buffer_prop->buffer_size) {
7219 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
7220 buffer_prop->buffer_size, buf_size);
7221 eRet = OMX_ErrorBadParameter;
7222 } else {
7223 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7224 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7225
7226 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7227 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7228 fmt.fmt.pix_mp.pixelformat = output_capability;
7229 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7230 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7231 fmt.fmt.pix_mp.pixelformat = capture_capability;
7232 } else {
7233 eRet = OMX_ErrorBadParameter;
7234 }
7235
7236 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
7237 if (ret) {
7238 /*TODO: How to handle this case */
7239 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
7240 eRet = OMX_ErrorInsufficientResources;
7241 }
7242
7243 bufreq.memory = V4L2_MEMORY_USERPTR;
7244 bufreq.count = buffer_prop->actualcount;
7245 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
7246 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7247 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7248 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7249 } else {
7250 eRet = OMX_ErrorBadParameter;
7251 }
7252
7253 if (eRet==OMX_ErrorNone) {
7254 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7255 }
7256
7257 if (ret) {
7258 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
7259 /*TODO: How to handle this case */
7260 eRet = OMX_ErrorInsufficientResources;
7261 } else if (bufreq.count < buffer_prop->actualcount) {
7262 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
7263 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
7264 buffer_prop->actualcount, bufreq.count);
7265 eRet = OMX_ErrorInsufficientResources;
7266 } else {
7267 if (!client_buffers.update_buffer_req()) {
7268 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
7269 eRet = OMX_ErrorInsufficientResources;
7270 }
7271 }
7272 }
7273 if (!eRet && buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
7274 // need to update extradata buffers also
7275 drv_ctx.extradata_info.size = buffer_prop->actualcount * drv_ctx.extradata_info.buffer_size;
7276 drv_ctx.extradata_info.count = buffer_prop->actualcount;
7277 }
7278 return eRet;
7279 }
7280
update_picture_resolution()7281 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
7282 {
7283 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7284 return eRet;
7285 }
7286
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)7287 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
7288 {
7289 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7290 if (!portDefn) {
7291 return OMX_ErrorBadParameter;
7292 }
7293 DEBUG_PRINT_LOW("omx_vdec::update_portdef");
7294 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
7295 portDefn->nSize = sizeof(portDefn);
7296 portDefn->eDomain = OMX_PortDomainVideo;
7297 if (drv_ctx.frame_rate.fps_denominator > 0)
7298 portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator /
7299 drv_ctx.frame_rate.fps_denominator;
7300 else {
7301 DEBUG_PRINT_ERROR("Error: Divide by zero");
7302 return OMX_ErrorBadParameter;
7303 }
7304 if (0 == portDefn->nPortIndex) {
7305 portDefn->eDir = OMX_DirInput;
7306 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
7307 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
7308 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
7309 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
7310 portDefn->format.video.eCompressionFormat = eCompressionFormat;
7311 portDefn->bEnabled = m_inp_bEnabled;
7312 portDefn->bPopulated = m_inp_bPopulated;
7313 } else if (1 == portDefn->nPortIndex) {
7314 unsigned int buf_size = 0;
7315 if (!client_buffers.update_buffer_req()) {
7316 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
7317 return OMX_ErrorHardware;
7318 }
7319 if (!client_buffers.get_buffer_req(buf_size)) {
7320 DEBUG_PRINT_ERROR("update buffer requirements");
7321 return OMX_ErrorHardware;
7322 }
7323 portDefn->nBufferSize = buf_size;
7324 portDefn->eDir = OMX_DirOutput;
7325 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
7326 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
7327 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7328 portDefn->bEnabled = m_out_bEnabled;
7329 portDefn->bPopulated = m_out_bPopulated;
7330 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
7331 DEBUG_PRINT_ERROR("Error in getting color format");
7332 return OMX_ErrorHardware;
7333 }
7334 } else {
7335 portDefn->eDir = OMX_DirMax;
7336 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
7337 (int)portDefn->nPortIndex);
7338 eRet = OMX_ErrorBadPortIndex;
7339 }
7340 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
7341 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
7342 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
7343 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
7344 DEBUG_PRINT_HIGH("update_portdef Width = %lu Height = %lu Stride = %ld"
7345 " SliceHeight = %lu", portDefn->format.video.nFrameWidth,
7346 portDefn->format.video.nFrameHeight,
7347 portDefn->format.video.nStride,
7348 portDefn->format.video.nSliceHeight);
7349 return eRet;
7350
7351 }
7352
allocate_output_headers()7353 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
7354 {
7355 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7356 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
7357 unsigned i= 0;
7358
7359 if (!m_out_mem_ptr) {
7360 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
7361 int nBufHdrSize = 0;
7362 int nPlatformEntrySize = 0;
7363 int nPlatformListSize = 0;
7364 int nPMEMInfoSize = 0;
7365 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
7366 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
7367 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
7368
7369 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
7370 drv_ctx.op_buf.actualcount);
7371 nBufHdrSize = drv_ctx.op_buf.actualcount *
7372 sizeof(OMX_BUFFERHEADERTYPE);
7373
7374 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
7375 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
7376 nPlatformListSize = drv_ctx.op_buf.actualcount *
7377 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
7378 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
7379 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
7380
7381 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize,
7382 sizeof(OMX_BUFFERHEADERTYPE),
7383 nPMEMInfoSize,
7384 nPlatformListSize);
7385 DEBUG_PRINT_LOW("PE %d bmSize %d",nPlatformEntrySize,
7386 m_out_bm_count);
7387 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
7388 // Alloc mem for platform specific info
7389 char *pPtr=NULL;
7390 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7391 nPMEMInfoSize,1);
7392 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
7393 calloc (sizeof(struct vdec_bufferpayload),
7394 drv_ctx.op_buf.actualcount);
7395 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
7396 calloc (sizeof (struct vdec_output_frameinfo),
7397 drv_ctx.op_buf.actualcount);
7398 #ifdef USE_ION
7399 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
7400 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
7401 #endif
7402
7403 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
7404 && drv_ctx.ptr_respbuffer) {
7405 bufHdr = m_out_mem_ptr;
7406 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7407 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7408 (((char *) m_platform_list) + nPlatformListSize);
7409 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7410 (((char *) m_platform_entry) + nPlatformEntrySize);
7411 pPlatformList = m_platform_list;
7412 pPlatformEntry = m_platform_entry;
7413 pPMEMInfo = m_pmem_info;
7414
7415 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
7416
7417 // Settting the entire storage nicely
7418 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
7419 m_out_mem_ptr,pPlatformEntry);
7420 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
7421 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
7422 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
7423 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
7424 // Set the values when we determine the right HxW param
7425 bufHdr->nAllocLen = 0;
7426 bufHdr->nFilledLen = 0;
7427 bufHdr->pAppPrivate = NULL;
7428 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7429 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7430 pPlatformEntry->entry = pPMEMInfo;
7431 // Initialize the Platform List
7432 pPlatformList->nEntries = 1;
7433 pPlatformList->entryList = pPlatformEntry;
7434 // Keep pBuffer NULL till vdec is opened
7435 bufHdr->pBuffer = NULL;
7436 pPMEMInfo->offset = 0;
7437 pPMEMInfo->pmem_fd = 0;
7438 bufHdr->pPlatformPrivate = pPlatformList;
7439 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
7440 #ifdef USE_ION
7441 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
7442 #endif
7443 /*Create a mapping between buffers*/
7444 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7445 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
7446 &drv_ctx.ptr_outputbuffer[i];
7447 // Move the buffer and buffer header pointers
7448 bufHdr++;
7449 pPMEMInfo++;
7450 pPlatformEntry++;
7451 pPlatformList++;
7452 }
7453 } else {
7454 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
7455 m_out_mem_ptr, pPtr);
7456 if (m_out_mem_ptr) {
7457 free(m_out_mem_ptr);
7458 m_out_mem_ptr = NULL;
7459 }
7460 if (pPtr) {
7461 free(pPtr);
7462 pPtr = NULL;
7463 }
7464 if (drv_ctx.ptr_outputbuffer) {
7465 free(drv_ctx.ptr_outputbuffer);
7466 drv_ctx.ptr_outputbuffer = NULL;
7467 }
7468 if (drv_ctx.ptr_respbuffer) {
7469 free(drv_ctx.ptr_respbuffer);
7470 drv_ctx.ptr_respbuffer = NULL;
7471 }
7472 #ifdef USE_ION
7473 if (drv_ctx.op_buf_ion_info) {
7474 DEBUG_PRINT_LOW("Free o/p ion context");
7475 free(drv_ctx.op_buf_ion_info);
7476 drv_ctx.op_buf_ion_info = NULL;
7477 }
7478 #endif
7479 eRet = OMX_ErrorInsufficientResources;
7480 }
7481 } else {
7482 eRet = OMX_ErrorInsufficientResources;
7483 }
7484 return eRet;
7485 }
7486
complete_pending_buffer_done_cbs()7487 void omx_vdec::complete_pending_buffer_done_cbs()
7488 {
7489 unsigned p1;
7490 unsigned p2;
7491 unsigned ident;
7492 omx_cmd_queue tmp_q, pending_bd_q;
7493 pthread_mutex_lock(&m_lock);
7494 // pop all pending GENERATE FDB from ftb queue
7495 while (m_ftb_q.m_size) {
7496 m_ftb_q.pop_entry(&p1,&p2,&ident);
7497 if (ident == OMX_COMPONENT_GENERATE_FBD) {
7498 pending_bd_q.insert_entry(p1,p2,ident);
7499 } else {
7500 tmp_q.insert_entry(p1,p2,ident);
7501 }
7502 }
7503 //return all non GENERATE FDB to ftb queue
7504 while (tmp_q.m_size) {
7505 tmp_q.pop_entry(&p1,&p2,&ident);
7506 m_ftb_q.insert_entry(p1,p2,ident);
7507 }
7508 // pop all pending GENERATE EDB from etb queue
7509 while (m_etb_q.m_size) {
7510 m_etb_q.pop_entry(&p1,&p2,&ident);
7511 if (ident == OMX_COMPONENT_GENERATE_EBD) {
7512 pending_bd_q.insert_entry(p1,p2,ident);
7513 } else {
7514 tmp_q.insert_entry(p1,p2,ident);
7515 }
7516 }
7517 //return all non GENERATE FDB to etb queue
7518 while (tmp_q.m_size) {
7519 tmp_q.pop_entry(&p1,&p2,&ident);
7520 m_etb_q.insert_entry(p1,p2,ident);
7521 }
7522 pthread_mutex_unlock(&m_lock);
7523 // process all pending buffer dones
7524 while (pending_bd_q.m_size) {
7525 pending_bd_q.pop_entry(&p1,&p2,&ident);
7526 switch (ident) {
7527 case OMX_COMPONENT_GENERATE_EBD:
7528 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
7529 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
7530 omx_report_error ();
7531 }
7532 break;
7533
7534 case OMX_COMPONENT_GENERATE_FBD:
7535 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
7536 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
7537 omx_report_error ();
7538 }
7539 break;
7540 }
7541 }
7542 }
7543
set_frame_rate(OMX_S64 act_timestamp)7544 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
7545 {
7546 OMX_U32 new_frame_interval = 0;
7547 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
7548 && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000)) {
7549 new_frame_interval = (act_timestamp > prev_ts)?
7550 act_timestamp - prev_ts :
7551 prev_ts - act_timestamp;
7552 if (new_frame_interval < frm_int || frm_int == 0) {
7553 frm_int = new_frame_interval;
7554 if (frm_int) {
7555 drv_ctx.frame_rate.fps_numerator = 1e6;
7556 drv_ctx.frame_rate.fps_denominator = frm_int;
7557 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
7558 frm_int, drv_ctx.frame_rate.fps_numerator /
7559 (float)drv_ctx.frame_rate.fps_denominator);
7560 }
7561 }
7562 }
7563 prev_ts = act_timestamp;
7564 }
7565
adjust_timestamp(OMX_S64 & act_timestamp)7566 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
7567 {
7568 if (rst_prev_ts && VALID_TS(act_timestamp)) {
7569 prev_ts = act_timestamp;
7570 rst_prev_ts = false;
7571 } else if (VALID_TS(prev_ts)) {
7572 bool codec_cond = (drv_ctx.timestamp_adjust)?
7573 (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)?
7574 (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)):
7575 (!VALID_TS(act_timestamp) || act_timestamp == prev_ts);
7576 if (frm_int > 0 && codec_cond) {
7577 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
7578 act_timestamp = prev_ts + frm_int;
7579 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
7580 prev_ts = act_timestamp;
7581 } else
7582 set_frame_rate(act_timestamp);
7583 } else if (frm_int > 0) // In this case the frame rate was set along
7584 { // with the port definition, start ts with 0
7585 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
7586 rst_prev_ts = true;
7587 }
7588 }
7589
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)7590 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
7591 {
7592 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
7593 OMX_U32 num_conceal_MB = 0;
7594 OMX_U32 frame_rate = 0;
7595 int consumed_len = 0;
7596 OMX_U32 num_MB_in_frame;
7597 OMX_U32 recovery_sei_flags = 1;
7598 int buf_index = p_buf_hdr - m_out_mem_ptr;
7599 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
7600 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
7601 p_buf_hdr->nOffset;
7602 if (!drv_ctx.extradata_info.uaddr) {
7603 return;
7604 }
7605 p_extra = (OMX_OTHER_EXTRADATATYPE *)
7606 ((unsigned)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
7607 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
7608 if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))
7609 p_extra = NULL;
7610 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
7611 if (data) {
7612 while ((consumed_len < drv_ctx.extradata_info.buffer_size)
7613 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
7614 if ((consumed_len + data->nSize) > drv_ctx.extradata_info.buffer_size) {
7615 DEBUG_PRINT_LOW("Invalid extra data size");
7616 break;
7617 }
7618 switch ((unsigned long)data->eType) {
7619 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
7620 struct msm_vidc_interlace_payload *payload;
7621 payload = (struct msm_vidc_interlace_payload *)data->data;
7622 if (payload->format != MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
7623 int enable = 1;
7624 OMX_U32 mbaff = 0;
7625 mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
7626 if ((payload->format == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !mbaff)
7627 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
7628 else
7629 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
7630 if (m_enable_android_native_buffers)
7631 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
7632 PP_PARAM_INTERLACED, (void*)&enable);
7633 }
7634 if (!secure_mode && (client_extradata & OMX_INTERLACE_EXTRADATA)) {
7635 append_interlace_extradata(p_extra, payload->format);
7636 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7637 }
7638 break;
7639 case MSM_VIDC_EXTRADATA_FRAME_RATE:
7640 struct msm_vidc_framerate_payload *frame_rate_payload;
7641 frame_rate_payload = (struct msm_vidc_framerate_payload *)data->data;
7642 frame_rate = frame_rate_payload->frame_rate;
7643 break;
7644 case MSM_VIDC_EXTRADATA_TIMESTAMP:
7645 struct msm_vidc_ts_payload *time_stamp_payload;
7646 time_stamp_payload = (struct msm_vidc_ts_payload *)data->data;
7647 p_buf_hdr->nTimeStamp = time_stamp_payload->timestamp_lo;
7648 p_buf_hdr->nTimeStamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
7649 break;
7650 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
7651 struct msm_vidc_concealmb_payload *conceal_mb_payload;
7652 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)data->data;
7653 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
7654 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
7655 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
7656 break;
7657 case MSM_VIDC_EXTRADATA_ASPECT_RATIO:
7658 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
7659 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)data->data;
7660 ((struct vdec_output_frameinfo *)
7661 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
7662 ((struct vdec_output_frameinfo *)
7663 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
7664 break;
7665 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
7666 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
7667 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)data->data;
7668 recovery_sei_flags = recovery_sei_payload->flags;
7669 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
7670 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
7671 DEBUG_PRINT_HIGH("Extradata: OMX_BUFFERFLAG_DATACORRUPT Received");
7672 }
7673 break;
7674 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
7675 panscan_payload = (struct msm_vidc_panscan_window_payload *)data->data;
7676 break;
7677 default:
7678 goto unrecognized_extradata;
7679 }
7680 consumed_len += data->nSize;
7681 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
7682 }
7683 if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
7684 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
7685 append_frame_info_extradata(p_extra,
7686 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
7687 panscan_payload,&((struct vdec_output_frameinfo *)
7688 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
7689 }
7690 }
7691 unrecognized_extradata:
7692 if (!secure_mode && client_extradata)
7693 append_terminator_extradata(p_extra);
7694 return;
7695 }
7696
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)7697 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
7698 bool is_internal, bool enable)
7699 {
7700 OMX_ERRORTYPE ret = OMX_ErrorNone;
7701 struct v4l2_control control;
7702 if (m_state != OMX_StateLoaded) {
7703 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
7704 return OMX_ErrorIncorrectStateOperation;
7705 }
7706 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%lu] requested[%lu] enable[%d], is_internal: %d",
7707 client_extradata, requested_extradata, enable, is_internal);
7708
7709 if (!is_internal) {
7710 if (enable)
7711 client_extradata |= requested_extradata;
7712 else
7713 client_extradata = client_extradata & ~requested_extradata;
7714 }
7715
7716 if (enable) {
7717 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
7718 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7719 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
7720 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7721 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
7722 " Quality of interlaced clips might be impacted.");
7723 }
7724 } else if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
7725 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7726 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
7727 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7728 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
7729 }
7730 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7731 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
7732 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7733 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
7734 }
7735 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7736 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
7737 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7738 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
7739 }
7740 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7741 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
7742 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7743 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
7744 }
7745 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7746 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
7747 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7748 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
7749 }
7750 } else if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
7751 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
7752 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
7753 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
7754 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
7755 }
7756 }
7757 }
7758 ret = get_buffer_req(&drv_ctx.op_buf);
7759 return ret;
7760 }
7761
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)7762 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7763 {
7764 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
7765 OMX_U8 *data_ptr = extra->data, data = 0;
7766 while (byte_count < extra->nDataSize) {
7767 data = *data_ptr;
7768 while (data) {
7769 num_MB += (data&0x01);
7770 data >>= 1;
7771 }
7772 data_ptr++;
7773 byte_count++;
7774 }
7775 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
7776 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
7777 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
7778 }
7779
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)7780 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7781 {
7782 if (!m_debug_extradata)
7783 return;
7784
7785 DEBUG_PRINT_HIGH(
7786 "============== Extra Data ==============\n"
7787 " Size: %lu \n"
7788 " Version: %lu \n"
7789 " PortIndex: %lu \n"
7790 " Type: %x \n"
7791 " DataSize: %lu",
7792 extra->nSize, extra->nVersion.nVersion,
7793 extra->nPortIndex, extra->eType, extra->nDataSize);
7794
7795 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
7796 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data;
7797 DEBUG_PRINT_HIGH(
7798 "------ Interlace Format ------\n"
7799 " Size: %lu \n"
7800 " Version: %lu \n"
7801 " PortIndex: %lu \n"
7802 " Is Interlace Format: %d \n"
7803 " Interlace Formats: %lu \n"
7804 "=========== End of Interlace ===========",
7805 intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex,
7806 intfmt->bInterlaceFormat, intfmt->nInterlaceFormats);
7807 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
7808 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
7809
7810 DEBUG_PRINT_HIGH(
7811 "-------- Frame Format --------\n"
7812 " Picture Type: %d \n"
7813 " Interlace Type: %d \n"
7814 " Pan Scan Total Frame Num: %lu \n"
7815 " Concealed Macro Blocks: %lu \n"
7816 " frame rate: %lu \n"
7817 " Aspect Ratio X: %lu \n"
7818 " Aspect Ratio Y: %lu",
7819 fminfo->ePicType,
7820 fminfo->interlaceType,
7821 fminfo->panScan.numWindows,
7822 fminfo->nConcealedMacroblocks,
7823 fminfo->nFrameRate,
7824 fminfo->aspectRatio.aspectRatioX,
7825 fminfo->aspectRatio.aspectRatioY);
7826
7827 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
7828 DEBUG_PRINT_HIGH(
7829 "------------------------------\n"
7830 " Pan Scan Frame Num: %lu \n"
7831 " Rectangle x: %ld \n"
7832 " Rectangle y: %ld \n"
7833 " Rectangle dx: %ld \n"
7834 " Rectangle dy: %ld",
7835 i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y,
7836 fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy);
7837 }
7838
7839 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
7840 } else if (extra->eType == OMX_ExtraDataNone) {
7841 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
7842 } else {
7843 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
7844 }
7845 }
7846
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)7847 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
7848 OMX_U32 interlaced_format_type)
7849 {
7850 OMX_STREAMINTERLACEFORMAT *interlace_format;
7851 OMX_U32 mbaff = 0;
7852 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
7853 return;
7854 }
7855 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
7856 extra->nVersion.nVersion = OMX_SPEC_VERSION;
7857 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7858 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
7859 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
7860 interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data;
7861 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
7862 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
7863 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7864 mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
7865 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !mbaff) {
7866 interlace_format->bInterlaceFormat = OMX_FALSE;
7867 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
7868 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
7869 } else {
7870 interlace_format->bInterlaceFormat = OMX_TRUE;
7871 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
7872 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
7873 }
7874 print_debug_extradata(extra);
7875 }
7876
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)7877 void omx_vdec::fill_aspect_ratio_info(
7878 struct vdec_aspectratioinfo *aspect_ratio_info,
7879 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
7880 {
7881 m_extradata = frame_info;
7882 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
7883 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
7884 DEBUG_PRINT_LOW("aspectRatioX %d aspectRatioX %d", m_extradata->aspectRatio.aspectRatioX,
7885 m_extradata->aspectRatio.aspectRatioY);
7886 }
7887
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 picture_type,OMX_U32 frame_rate,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)7888 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
7889 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
7890 struct msm_vidc_panscan_window_payload *panscan_payload,
7891 struct vdec_aspectratioinfo *aspect_ratio_info)
7892 {
7893 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
7894 struct msm_vidc_panscan_window *panscan_window;
7895 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
7896 return;
7897 }
7898 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
7899 extra->nVersion.nVersion = OMX_SPEC_VERSION;
7900 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7901 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
7902 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
7903 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
7904 switch (picture_type) {
7905 case PICTURE_TYPE_I:
7906 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
7907 break;
7908 case PICTURE_TYPE_P:
7909 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
7910 break;
7911 case PICTURE_TYPE_B:
7912 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
7913 break;
7914 default:
7915 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
7916 }
7917 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
7918 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
7919 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
7920 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
7921 else
7922 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
7923 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
7924 frame_info->nConcealedMacroblocks = num_conceal_mb;
7925 frame_info->nFrameRate = frame_rate;
7926 frame_info->panScan.numWindows = 0;
7927 if (panscan_payload) {
7928 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
7929 panscan_window = &panscan_payload->wnd[0];
7930 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
7931 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
7932 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
7933 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
7934 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
7935 panscan_window++;
7936 }
7937 }
7938 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
7939 print_debug_extradata(extra);
7940 }
7941
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)7942 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7943 {
7944 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
7945 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
7946 extra->nVersion.nVersion = OMX_SPEC_VERSION;
7947 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7948 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
7949 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
7950 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data;
7951 *portDefn = m_port_def;
7952 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u"
7953 "sliceheight = %u",portDefn->format.video.nFrameHeight,
7954 portDefn->format.video.nFrameWidth,
7955 portDefn->format.video.nStride,
7956 portDefn->format.video.nSliceHeight);
7957 }
7958
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)7959 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
7960 {
7961 if (!client_extradata) {
7962 return;
7963 }
7964 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
7965 extra->nVersion.nVersion = OMX_SPEC_VERSION;
7966 extra->eType = OMX_ExtraDataNone;
7967 extra->nDataSize = 0;
7968 extra->data[0] = 0;
7969
7970 print_debug_extradata(extra);
7971 }
7972
allocate_desc_buffer(OMX_U32 index)7973 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
7974 {
7975 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7976 if (index >= drv_ctx.ip_buf.actualcount) {
7977 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
7978 return OMX_ErrorInsufficientResources;
7979 }
7980 if (m_desc_buffer_ptr == NULL) {
7981 m_desc_buffer_ptr = (desc_buffer_hdr*) \
7982 calloc( (sizeof(desc_buffer_hdr)),
7983 drv_ctx.ip_buf.actualcount);
7984 if (m_desc_buffer_ptr == NULL) {
7985 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
7986 return OMX_ErrorInsufficientResources;
7987 }
7988 }
7989
7990 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
7991 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
7992 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
7993 return OMX_ErrorInsufficientResources;
7994 }
7995
7996 return eRet;
7997 }
7998
insert_demux_addr_offset(OMX_U32 address_offset)7999 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
8000 {
8001 DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries);
8002 if (m_demux_entries < 8192) {
8003 m_demux_offsets[m_demux_entries++] = address_offset;
8004 }
8005 return;
8006 }
8007
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)8008 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
8009 {
8010 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
8011 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
8012 OMX_U32 index = 0;
8013
8014 m_demux_entries = 0;
8015
8016 while (index < bytes_to_parse) {
8017 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8018 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
8019 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8020 (buf[index+2] == 0x01)) ) {
8021 //Found start code, insert address offset
8022 insert_demux_addr_offset(index);
8023 if (buf[index+2] == 0x01) // 3 byte start code
8024 index += 3;
8025 else //4 byte start code
8026 index += 4;
8027 } else
8028 index++;
8029 }
8030 DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries);
8031 return;
8032 }
8033
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)8034 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
8035 {
8036 //fix this, handle 3 byte start code, vc1 terminator entry
8037 OMX_U8 *p_demux_data = NULL;
8038 OMX_U32 desc_data = 0;
8039 OMX_U32 start_addr = 0;
8040 OMX_U32 nal_size = 0;
8041 OMX_U32 suffix_byte = 0;
8042 OMX_U32 demux_index = 0;
8043 OMX_U32 buffer_index = 0;
8044
8045 if (m_desc_buffer_ptr == NULL) {
8046 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
8047 return OMX_ErrorBadParameter;
8048 }
8049
8050 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
8051 if (buffer_index > drv_ctx.ip_buf.actualcount) {
8052 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%lu)", buffer_index);
8053 return OMX_ErrorBadParameter;
8054 }
8055
8056 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
8057
8058 if ( ((OMX_U8*)p_demux_data == NULL) ||
8059 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
8060 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
8061 return OMX_ErrorBadParameter;
8062 } else {
8063 for (; demux_index < m_demux_entries; demux_index++) {
8064 desc_data = 0;
8065 start_addr = m_demux_offsets[demux_index];
8066 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
8067 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
8068 } else {
8069 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
8070 }
8071 if (demux_index < (m_demux_entries - 1)) {
8072 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
8073 } else {
8074 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
8075 }
8076 DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)",
8077 start_addr,
8078 suffix_byte,
8079 nal_size,
8080 demux_index);
8081 desc_data = (start_addr >> 3) << 1;
8082 desc_data |= (start_addr & 7) << 21;
8083 desc_data |= suffix_byte << 24;
8084
8085 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8086 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
8087 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8088 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8089
8090 p_demux_data += 16;
8091 }
8092 if (codec_type_parse == CODEC_TYPE_VC1) {
8093 DEBUG_PRINT_LOW("VC1 terminator entry");
8094 desc_data = 0;
8095 desc_data = 0x82 << 24;
8096 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8097 memset(p_demux_data + 4, 0, sizeof(OMX_U32));
8098 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8099 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8100 p_demux_data += 16;
8101 m_demux_entries++;
8102 }
8103 //Add zero word to indicate end of descriptors
8104 memset(p_demux_data, 0, sizeof(OMX_U32));
8105
8106 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
8107 DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size);
8108 }
8109 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
8110 m_demux_entries = 0;
8111 DEBUG_PRINT_LOW("Demux table complete!");
8112 return OMX_ErrorNone;
8113 }
8114
createDivxDrmContext()8115 OMX_ERRORTYPE omx_vdec::createDivxDrmContext()
8116 {
8117 OMX_ERRORTYPE err = OMX_ErrorNone;
8118 iDivXDrmDecrypt = DivXDrmDecrypt::Create();
8119 if (iDivXDrmDecrypt) {
8120 OMX_ERRORTYPE err = iDivXDrmDecrypt->Init();
8121 if (err!=OMX_ErrorNone) {
8122 DEBUG_PRINT_ERROR("ERROR :iDivXDrmDecrypt->Init %d", err);
8123 delete iDivXDrmDecrypt;
8124 iDivXDrmDecrypt = NULL;
8125 }
8126 } else {
8127 DEBUG_PRINT_ERROR("Unable to Create DIVX DRM");
8128 err = OMX_ErrorUndefined;
8129 }
8130 return err;
8131 }
8132
allocate_color_convert_buf()8133 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
8134 {
8135 enabled = false;
8136 omx = NULL;
8137 init_members();
8138 ColorFormat = OMX_COLOR_FormatMax;
8139 }
8140
set_vdec_client(void * client)8141 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
8142 {
8143 omx = reinterpret_cast<omx_vdec*>(client);
8144 }
8145
init_members()8146 void omx_vdec::allocate_color_convert_buf::init_members()
8147 {
8148 allocated_count = 0;
8149 buffer_size_req = 0;
8150 buffer_alignment_req = 0;
8151 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
8152 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
8153 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
8154 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
8155 #ifdef USE_ION
8156 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
8157 #endif
8158 for (int i = 0; i < MAX_COUNT; i++)
8159 pmem_fd[i] = -1;
8160 }
8161
~allocate_color_convert_buf()8162 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
8163 {
8164 c2d.destroy();
8165 }
8166
update_buffer_req()8167 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
8168 {
8169 bool status = true;
8170 unsigned int src_size = 0, destination_size = 0;
8171 OMX_COLOR_FORMATTYPE drv_color_format;
8172 if (!omx) {
8173 DEBUG_PRINT_ERROR("Invalid client in color convert");
8174 return false;
8175 }
8176 if (!enabled) {
8177 DEBUG_PRINT_HIGH("No color conversion required");
8178 return status;
8179 }
8180 pthread_mutex_lock(&omx->c_lock);
8181 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
8182 ColorFormat != OMX_COLOR_FormatYUV420Planar) {
8183 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
8184 status = false;
8185 goto fail_update_buf_req;
8186 }
8187 c2d.close();
8188 status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
8189 omx->drv_ctx.video_resolution.frame_width,
8190 NV12_128m,YCbCr420P);
8191 if (status) {
8192 status = c2d.get_buffer_size(C2D_INPUT,src_size);
8193 if (status)
8194 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
8195 }
8196 if (status) {
8197 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
8198 !destination_size) {
8199 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
8200 "driver size %d destination size %d",
8201 src_size,omx->drv_ctx.op_buf.buffer_size,destination_size);
8202 status = false;
8203 c2d.close();
8204 buffer_size_req = 0;
8205 } else {
8206 buffer_size_req = destination_size;
8207 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
8208 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
8209 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
8210 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
8211 }
8212 }
8213 fail_update_buf_req:
8214 pthread_mutex_unlock(&omx->c_lock);
8215 return status;
8216 }
8217
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)8218 bool omx_vdec::allocate_color_convert_buf::set_color_format(
8219 OMX_COLOR_FORMATTYPE dest_color_format)
8220 {
8221 bool status = true;
8222 OMX_COLOR_FORMATTYPE drv_color_format;
8223 if (!omx) {
8224 DEBUG_PRINT_ERROR("Invalid client in color convert");
8225 return false;
8226 }
8227 pthread_mutex_lock(&omx->c_lock);
8228 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
8229 drv_color_format = (OMX_COLOR_FORMATTYPE)
8230 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
8231 else {
8232 DEBUG_PRINT_ERROR("Incorrect color format");
8233 status = false;
8234 }
8235 if (status && (drv_color_format != dest_color_format)) {
8236 DEBUG_PRINT_LOW("Enabling C2D");
8237 if (dest_color_format != OMX_COLOR_FormatYUV420Planar) {
8238 DEBUG_PRINT_ERROR("Unsupported color format for c2d");
8239 status = false;
8240 } else {
8241 ColorFormat = OMX_COLOR_FormatYUV420Planar;
8242 if (enabled)
8243 c2d.destroy();
8244 enabled = false;
8245 if (!c2d.init()) {
8246 DEBUG_PRINT_ERROR("open failed for c2d");
8247 status = false;
8248 } else
8249 enabled = true;
8250 }
8251 } else {
8252 if (enabled)
8253 c2d.destroy();
8254 enabled = false;
8255 }
8256 pthread_mutex_unlock(&omx->c_lock);
8257 return status;
8258 }
8259
get_il_buf_hdr()8260 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
8261 {
8262 if (!omx) {
8263 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8264 return NULL;
8265 }
8266 if (!enabled)
8267 return omx->m_out_mem_ptr;
8268 return m_out_mem_ptr_client;
8269 }
8270
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)8271 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
8272 (OMX_BUFFERHEADERTYPE *bufadd)
8273 {
8274 if (!omx) {
8275 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8276 return NULL;
8277 }
8278 if (!enabled)
8279 return bufadd;
8280
8281 unsigned index = 0;
8282 index = bufadd - omx->m_out_mem_ptr;
8283 if (index < omx->drv_ctx.op_buf.actualcount) {
8284 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
8285 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
8286 bool status;
8287 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
8288 pthread_mutex_lock(&omx->c_lock);
8289 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
8290 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer,pmem_fd[index],
8291 pmem_baseaddress[index], pmem_baseaddress[index]);
8292 pthread_mutex_unlock(&omx->c_lock);
8293 m_out_mem_ptr_client[index].nFilledLen = buffer_size_req;
8294 if (!status) {
8295 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
8296 m_out_mem_ptr_client[index].nFilledLen = 0;
8297 return &m_out_mem_ptr_client[index];
8298 }
8299 } else
8300 m_out_mem_ptr_client[index].nFilledLen = 0;
8301 return &m_out_mem_ptr_client[index];
8302 }
8303 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
8304 return NULL;
8305 }
8306
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)8307 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
8308 (OMX_BUFFERHEADERTYPE *bufadd)
8309 {
8310 if (!omx) {
8311 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
8312 return NULL;
8313 }
8314 if (!enabled)
8315 return bufadd;
8316 unsigned index = 0;
8317 index = bufadd - m_out_mem_ptr_client;
8318 if (index < omx->drv_ctx.op_buf.actualcount) {
8319 return &omx->m_out_mem_ptr[index];
8320 }
8321 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
8322 return NULL;
8323 }
get_buffer_req(unsigned int & buffer_size)8324 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
8325 (unsigned int &buffer_size)
8326 {
8327 bool status = true;
8328 pthread_mutex_lock(&omx->c_lock);
8329 if (!enabled)
8330 buffer_size = omx->drv_ctx.op_buf.buffer_size;
8331 else {
8332 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
8333 DEBUG_PRINT_ERROR("Get buffer size failed");
8334 status = false;
8335 goto fail_get_buffer_size;
8336 }
8337 }
8338 if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
8339 buffer_size = omx->drv_ctx.op_buf.buffer_size;
8340 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
8341 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
8342 fail_get_buffer_size:
8343 pthread_mutex_unlock(&omx->c_lock);
8344 return status;
8345 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)8346 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
8347 OMX_BUFFERHEADERTYPE *bufhdr)
8348 {
8349 unsigned int index = 0;
8350
8351 if (!enabled)
8352 return omx->free_output_buffer(bufhdr);
8353 if (enabled && omx->is_component_secure())
8354 return OMX_ErrorNone;
8355 if (!allocated_count || !bufhdr) {
8356 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
8357 return OMX_ErrorBadParameter;
8358 }
8359 index = bufhdr - m_out_mem_ptr_client;
8360 if (index >= omx->drv_ctx.op_buf.actualcount) {
8361 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
8362 return OMX_ErrorBadParameter;
8363 }
8364 if (pmem_fd[index] > 0) {
8365 munmap(pmem_baseaddress[index], buffer_size_req);
8366 close(pmem_fd[index]);
8367 }
8368 pmem_fd[index] = -1;
8369 #ifdef USE_ION
8370 omx->free_ion_memory(&op_buf_ion_info[index]);
8371 #endif
8372 m_heap_ptr[index].video_heap_ptr = NULL;
8373 if (allocated_count > 0)
8374 allocated_count--;
8375 else
8376 allocated_count = 0;
8377 if (!allocated_count) {
8378 pthread_mutex_lock(&omx->c_lock);
8379 c2d.close();
8380 init_members();
8381 pthread_mutex_unlock(&omx->c_lock);
8382 }
8383 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
8384 }
8385
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)8386 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
8387 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
8388 {
8389 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8390 if (!enabled) {
8391 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
8392 return eRet;
8393 }
8394 if (enabled && omx->is_component_secure()) {
8395 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
8396 omx->is_component_secure());
8397 return OMX_ErrorUnsupportedSetting;
8398 }
8399 if (!bufferHdr || bytes > buffer_size_req) {
8400 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
8401 DEBUG_PRINT_ERROR("color_convert buffer_size_req %d bytes %lu",
8402 buffer_size_req,bytes);
8403 return OMX_ErrorBadParameter;
8404 }
8405 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
8406 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
8407 return OMX_ErrorInsufficientResources;
8408 }
8409 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
8410 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
8411 port,appData,omx->drv_ctx.op_buf.buffer_size);
8412 if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
8413 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
8414 return eRet;
8415 }
8416 if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
8417 omx->drv_ctx.op_buf.actualcount) {
8418 DEBUG_PRINT_ERROR("Invalid header index %d",
8419 (temp_bufferHdr - omx->m_out_mem_ptr));
8420 return OMX_ErrorUndefined;
8421 }
8422 unsigned int i = allocated_count;
8423 #ifdef USE_ION
8424 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
8425 buffer_size_req,buffer_alignment_req,
8426 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
8427 0);
8428 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
8429 if (op_buf_ion_info[i].ion_device_fd < 0) {
8430 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
8431 return OMX_ErrorInsufficientResources;
8432 }
8433 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
8434 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
8435
8436 if (pmem_baseaddress[i] == MAP_FAILED) {
8437 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
8438 close(pmem_fd[i]);
8439 omx->free_ion_memory(&op_buf_ion_info[i]);
8440 return OMX_ErrorInsufficientResources;
8441 }
8442 m_heap_ptr[i].video_heap_ptr = new VideoHeap (
8443 op_buf_ion_info[i].ion_device_fd,buffer_size_req,
8444 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
8445 #endif
8446 m_pmem_info_client[i].pmem_fd = (OMX_U32)m_heap_ptr[i].video_heap_ptr.get();
8447 m_pmem_info_client[i].offset = 0;
8448 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
8449 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8450 m_platform_list_client[i].nEntries = 1;
8451 m_platform_list_client[i].entryList = &m_platform_entry_client[i];
8452 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
8453 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
8454 m_out_mem_ptr_client[i].nFilledLen = 0;
8455 m_out_mem_ptr_client[i].nFlags = 0;
8456 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8457 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
8458 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
8459 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
8460 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
8461 m_out_mem_ptr_client[i].pAppPrivate = appData;
8462 *bufferHdr = &m_out_mem_ptr_client[i];
8463 DEBUG_PRINT_ERROR("IL client buffer header %p", *bufferHdr);
8464 allocated_count++;
8465 return eRet;
8466 }
8467
is_component_secure()8468 bool omx_vdec::is_component_secure()
8469 {
8470 return secure_mode;
8471 }
8472
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)8473 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
8474 {
8475 bool status = true;
8476 if (!enabled) {
8477 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
8478 dest_color_format = (OMX_COLOR_FORMATTYPE)
8479 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
8480 else
8481 status = false;
8482 } else {
8483 if (ColorFormat != OMX_COLOR_FormatYUV420Planar) {
8484 status = false;
8485 } else
8486 dest_color_format = OMX_COLOR_FormatYUV420Planar;
8487 }
8488 return status;
8489 }
8490