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