1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2016, 2018, 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 #define __STDC_FORMAT_MACROS
43 #include <inttypes.h>
44
45 #include <string.h>
46 #include <pthread.h>
47 #include <sys/prctl.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <errno.h>
51 #include "omx_vdec.h"
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <stdlib.h>
55 #include <media/hardware/HardwareAPI.h>
56 #include <media/msm_media_info.h>
57
58 #ifndef _ANDROID_
59 #include <sys/ioctl.h>
60 #include <sys/mman.h>
61 #endif //_ANDROID_
62
63 #ifdef _ANDROID_
64 #include <cutils/properties.h>
65 #undef USE_EGL_IMAGE_GPU
66 #endif
67
68 #include <qdMetaData.h>
69
70 #ifdef _ANDROID_
71 #include "DivXDrmDecrypt.h"
72 #endif //_ANDROID_
73
74 #ifdef ANDROID_JELLYBEAN_MR2
75 #include "QComOMXMetadata.h"
76 #endif
77
78 #ifdef USE_EGL_IMAGE_GPU
79 #include <EGL/egl.h>
80 #include <EGL/eglQCOM.h>
81 #define EGL_BUFFER_HANDLE 0x4F00
82 #define EGL_BUFFER_OFFSET 0x4F01
83 #endif
84
85 #define BUFFER_LOG_LOC "/data/misc/media"
86
87 #ifdef OUTPUT_EXTRADATA_LOG
88 FILE *outputExtradataFile;
89 char output_extradata_filename [] = "/data/misc/media/extradata";
90 #endif
91
92 #define DEFAULT_FPS 30
93 #define MAX_SUPPORTED_FPS 120
94 #define DEFAULT_WIDTH_ALIGNMENT 128
95 #define DEFAULT_HEIGHT_ALIGNMENT 32
96
97 #define VC1_SP_MP_START_CODE 0xC5000000
98 #define VC1_SP_MP_START_CODE_MASK 0xFF000000
99 #define VC1_AP_SEQ_START_CODE 0x0F010000
100 #define VC1_STRUCT_C_PROFILE_MASK 0xF0
101 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
102 #define VC1_SIMPLE_PROFILE 0
103 #define VC1_MAIN_PROFILE 1
104 #define VC1_ADVANCE_PROFILE 3
105 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
106 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2
107 #define VC1_STRUCT_C_LEN 4
108 #define VC1_STRUCT_C_POS 8
109 #define VC1_STRUCT_A_POS 12
110 #define VC1_STRUCT_B_POS 24
111 #define VC1_SEQ_LAYER_SIZE 36
112 #define POLL_TIMEOUT 0x7fffffff
113
114 #define MEM_DEVICE "/dev/ion"
115 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
116
117 #ifdef _ANDROID_
118 extern "C" {
119 #include<utils/Log.h>
120 }
121 #endif//_ANDROID_
122
123 #define SZ_4K 0x1000
124 #define SZ_1M 0x100000
125
126 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
127 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
128 #define EXTRADATA_IDX(__num_planes) (__num_planes - 1)
129 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
130
131 #ifndef DISABLE_EXTRADATA
132 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_VUI_DISPLAY_INFO_EXTRADATA)
133 #endif
134
135 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
136
137
138 static OMX_U32 maxSmoothStreamingWidth = 1920;
139 static OMX_U32 maxSmoothStreamingHeight = 1088;
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 memset(&vdec_msg, 0, sizeof(vdec_msg));
167 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
168 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
169 v4l2_buf.length = omx->drv_ctx.num_planes;
170 v4l2_buf.m.planes = plane;
171 while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
172 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
173 vdec_msg.status_code=VDEC_S_SUCCESS;
174 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
175 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
176 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
177 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
178 (uint64_t)v4l2_buf.timestamp.tv_usec;
179 if (vdec_msg.msgdata.output_frame.len) {
180 vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
181 vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
182 vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
183 vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
184 vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
185 vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
186 }
187 if (omx->async_message_process(input,&vdec_msg) < 0) {
188 DEBUG_PRINT_HIGH("async_message_thread Exited");
189 break;
190 }
191 }
192 }
193 if ((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) {
194 struct vdec_msginfo vdec_msg;
195 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
196 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
197 v4l2_buf.length = 1;
198 v4l2_buf.m.planes = plane;
199 while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
200 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
201 vdec_msg.status_code=VDEC_S_SUCCESS;
202 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
203 if (omx->async_message_process(input,&vdec_msg) < 0) {
204 DEBUG_PRINT_HIGH("async_message_thread Exited");
205 break;
206 }
207 }
208 }
209 if (pfd.revents & POLLPRI) {
210 rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent);
211 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
212 struct vdec_msginfo vdec_msg;
213 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
214 vdec_msg.status_code=VDEC_S_SUCCESS;
215 DEBUG_PRINT_HIGH("VIDC Port Reconfig recieved insufficient");
216 if (omx->async_message_process(input,&vdec_msg) < 0) {
217 DEBUG_PRINT_HIGH("async_message_thread Exited");
218 break;
219 }
220 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
221 struct vdec_msginfo vdec_msg;
222 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
223 vdec_msg.status_code=VDEC_S_SUCCESS;
224 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
225 if (omx->async_message_process(input,&vdec_msg) < 0) {
226 DEBUG_PRINT_HIGH("async_message_thread Exited");
227 break;
228 }
229 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
230 vdec_msg.status_code=VDEC_S_SUCCESS;
231 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
232 if (omx->async_message_process(input,&vdec_msg) < 0) {
233 DEBUG_PRINT_HIGH("async_message_thread Exited");
234 break;
235 }
236 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
237 DEBUG_PRINT_HIGH("VIDC Close Done Recieved and async_message_thread Exited");
238 break;
239 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
240 struct vdec_msginfo vdec_msg;
241 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
242 vdec_msg.status_code=VDEC_S_SUCCESS;
243 DEBUG_PRINT_ERROR("HW Overload received");
244 if (omx->async_message_process(input,&vdec_msg) < 0) {
245 DEBUG_PRINT_HIGH("async_message_thread Exited");
246 break;
247 }
248 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
249 struct vdec_msginfo vdec_msg;
250 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
251 vdec_msg.status_code=VDEC_S_SUCCESS;
252 DEBUG_PRINT_ERROR("HW Unsupported received");
253 if (omx->async_message_process(input,&vdec_msg) < 0) {
254 DEBUG_PRINT_HIGH("async_message_thread Exited");
255 break;
256 }
257 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
258 struct vdec_msginfo vdec_msg;
259 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
260 vdec_msg.status_code=VDEC_S_SUCCESS;
261 DEBUG_PRINT_HIGH("SYS Error Recieved");
262 if (omx->async_message_process(input,&vdec_msg) < 0) {
263 DEBUG_PRINT_HIGH("async_message_thread Exited");
264 break;
265 }
266 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
267 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
268
269 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
270 omx->buf_ref_remove(ptr[0], ptr[1]);
271 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
272 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
273 struct vdec_msginfo vdec_msg;
274
275 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
276
277 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
278 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
279 v4l2_buf.length = omx->drv_ctx.num_planes;
280 v4l2_buf.m.planes = plane;
281 v4l2_buf.index = ptr[5];
282 v4l2_buf.flags = 0;
283
284 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
285 vdec_msg.status_code=VDEC_S_SUCCESS;
286 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
287 vdec_msg.msgdata.output_frame.len = 0;
288 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
289 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
290 (uint64_t)ptr[4];
291 if (omx->async_message_process(input,&vdec_msg) < 0) {
292 DEBUG_PRINT_HIGH("async_message_thread Exitedn");
293 break;
294 }
295 }
296 else {
297 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
298 continue;
299 }
300 }
301 }
302 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
303 return NULL;
304 }
305
message_thread(void * input)306 void* message_thread(void *input)
307 {
308 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
309 unsigned char id;
310 int n;
311
312 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
313 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
314 while (1) {
315
316 n = read(omx->m_pipe_in, &id, 1);
317
318 if (0 == n) {
319 break;
320 }
321
322 if (1 == n) {
323 omx->process_event_cb(omx, id);
324 }
325 if ((n < 0) && (errno != EINTR)) {
326 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
327 break;
328 }
329 }
330 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
331 return 0;
332 }
333
post_message(omx_vdec * omx,unsigned char id)334 void post_message(omx_vdec *omx, unsigned char id)
335 {
336 int ret_value;
337 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
338 ret_value = write(omx->m_pipe_out, &id, 1);
339 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
340 }
341
342 // omx_cmd_queue destructor
~omx_cmd_queue()343 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
344 {
345 // Nothing to do
346 }
347
348 // omx cmd queue constructor
omx_cmd_queue()349 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
350 {
351 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
352 }
353
354 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)355 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
356 {
357 bool ret = true;
358 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
359 m_q[m_write].id = id;
360 m_q[m_write].param1 = p1;
361 m_q[m_write].param2 = p2;
362 m_write++;
363 m_size ++;
364 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
365 m_write = 0;
366 }
367 } else {
368 ret = false;
369 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
370 }
371 return ret;
372 }
373
374 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)375 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
376 {
377 bool ret = true;
378 if (m_size > 0) {
379 *id = m_q[m_read].id;
380 *p1 = m_q[m_read].param1;
381 *p2 = m_q[m_read].param2;
382 // Move the read pointer ahead
383 ++m_read;
384 --m_size;
385 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
386 m_read = 0;
387 }
388 } else {
389 ret = false;
390 }
391 return ret;
392 }
393
394 // Retrieve the first mesg type in the queue
get_q_msg_type()395 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
396 {
397 return m_q[m_read].id;
398 }
399
400 #ifdef _ANDROID_
ts_arr_list()401 omx_vdec::ts_arr_list::ts_arr_list()
402 {
403 //initialize timestamps array
404 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
405 }
~ts_arr_list()406 omx_vdec::ts_arr_list::~ts_arr_list()
407 {
408 //free m_ts_arr_list?
409 }
410
insert_ts(OMX_TICKS ts)411 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
412 {
413 bool ret = true;
414 bool duplicate_ts = false;
415 int idx = 0;
416
417 //insert at the first available empty location
418 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
419 if (!m_ts_arr_list[idx].valid) {
420 //found invalid or empty entry, save timestamp
421 m_ts_arr_list[idx].valid = true;
422 m_ts_arr_list[idx].timestamp = ts;
423 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
424 ts, idx);
425 break;
426 }
427 }
428
429 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
430 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
431 ret = false;
432 }
433 return ret;
434 }
435
pop_min_ts(OMX_TICKS & ts)436 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
437 {
438 bool ret = true;
439 int min_idx = -1;
440 OMX_TICKS min_ts = 0;
441 int idx = 0;
442
443 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
444
445 if (m_ts_arr_list[idx].valid) {
446 //found valid entry, save index
447 if (min_idx < 0) {
448 //first valid entry
449 min_ts = m_ts_arr_list[idx].timestamp;
450 min_idx = idx;
451 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
452 min_ts = m_ts_arr_list[idx].timestamp;
453 min_idx = idx;
454 }
455 }
456
457 }
458
459 if (min_idx < 0) {
460 //no valid entries found
461 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
462 ts = 0;
463 ret = false;
464 } else {
465 ts = m_ts_arr_list[min_idx].timestamp;
466 m_ts_arr_list[min_idx].valid = false;
467 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
468 ts, min_idx);
469 }
470
471 return ret;
472
473 }
474
475
reset_ts_list()476 bool omx_vdec::ts_arr_list::reset_ts_list()
477 {
478 bool ret = true;
479 int idx = 0;
480
481 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
482 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
483 m_ts_arr_list[idx].valid = false;
484 }
485 return ret;
486 }
487 #endif
488
489 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)490 void *get_omx_component_factory_fn(void)
491 {
492 return (new omx_vdec);
493 }
494
495 #ifdef _ANDROID_
496 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,ion_user_handle_t handle,int ionMapfd)497 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
498 ion_user_handle_t handle, int ionMapfd)
499 {
500 (void) devicefd;
501 (void) size;
502 (void) base;
503 (void) handle;
504 (void) ionMapfd;
505 // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
506 }
507 #else
VideoHeap(int fd,size_t size,void * base)508 VideoHeap::VideoHeap(int fd, size_t size, void* base)
509 {
510 // dup file descriptor, map once, use pmem
511 init(dup(fd), base, size, 0 , MEM_DEVICE);
512 }
513 #endif
514 #endif // _ANDROID_
515 /* ======================================================================
516 FUNCTION
517 omx_vdec::omx_vdec
518
519 DESCRIPTION
520 Constructor
521
522 PARAMETERS
523 None
524
525 RETURN VALUE
526 None.
527 ========================================================================== */
omx_vdec()528 omx_vdec::omx_vdec(): m_error_propogated(false),
529 m_state(OMX_StateInvalid),
530 m_app_data(NULL),
531 m_inp_mem_ptr(NULL),
532 m_out_mem_ptr(NULL),
533 input_flush_progress (false),
534 output_flush_progress (false),
535 input_use_buffer (false),
536 output_use_buffer (false),
537 ouput_egl_buffers(false),
538 m_use_output_pmem(OMX_FALSE),
539 m_out_mem_region_smi(OMX_FALSE),
540 m_out_pvt_entry_pmem(OMX_FALSE),
541 pending_input_buffers(0),
542 pending_output_buffers(0),
543 m_out_bm_count(0),
544 m_inp_bm_count(0),
545 m_inp_bPopulated(OMX_FALSE),
546 m_out_bPopulated(OMX_FALSE),
547 m_flags(0),
548 #ifdef _ANDROID_
549 m_heap_ptr(NULL),
550 #endif
551 m_inp_bEnabled(OMX_TRUE),
552 m_out_bEnabled(OMX_TRUE),
553 m_in_alloc_cnt(0),
554 m_platform_list(NULL),
555 m_platform_entry(NULL),
556 m_pmem_info(NULL),
557 h264_parser(NULL),
558 arbitrary_bytes (true),
559 psource_frame (NULL),
560 pdest_frame (NULL),
561 m_inp_heap_ptr (NULL),
562 m_phdr_pmem_ptr(NULL),
563 m_heap_inp_bm_count (0),
564 codec_type_parse ((codec_type)0),
565 first_frame_meta (true),
566 frame_count (0),
567 nal_count (0),
568 nal_length(0),
569 look_ahead_nal (false),
570 first_frame(0),
571 first_buffer(NULL),
572 first_frame_size (0),
573 m_device_file_ptr(NULL),
574 m_vc1_profile((vc1_profile_type)0),
575 h264_last_au_ts(LLONG_MAX),
576 h264_last_au_flags(0),
577 m_disp_hor_size(0),
578 m_disp_vert_size(0),
579 prev_ts(LLONG_MAX),
580 rst_prev_ts(true),
581 frm_int(0),
582 in_reconfig(false),
583 m_display_id(NULL),
584 client_extradata(0),
585 m_reject_avc_1080p_mp (0),
586 #ifdef _ANDROID_
587 m_enable_android_native_buffers(OMX_FALSE),
588 m_use_android_native_buffers(OMX_FALSE),
589 iDivXDrmDecrypt(NULL),
590 #endif
591 m_desc_buffer_ptr(NULL),
592 secure_mode(false),
593 allocate_native_handle(false),
594 m_other_extradata(NULL),
595 m_profile(0),
596 client_set_fps(false),
597 m_last_rendered_TS(-1),
598 m_queued_codec_config_count(0),
599 secure_scaling_to_non_secure_opb(false),
600 m_buffer_error(false)
601 {
602 /* Assumption is that , to begin with , we have all the frames with decoder */
603 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
604 memset(&m_debug,0,sizeof(m_debug));
605 #ifdef _ANDROID_
606 char property_value[PROPERTY_VALUE_MAX] = {0};
607 property_get("vidc.debug.level", property_value, "1");
608 debug_level = atoi(property_value);
609 property_value[0] = '\0';
610
611 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
612
613 property_get("vidc.dec.debug.perf", property_value, "0");
614 perf_flag = atoi(property_value);
615 if (perf_flag) {
616 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
617 dec_time.start();
618 proc_frms = latency = 0;
619 }
620 prev_n_filled_len = 0;
621 property_value[0] = '\0';
622 property_get("vidc.dec.debug.ts", property_value, "0");
623 m_debug_timestamp = atoi(property_value);
624 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
625 if (m_debug_timestamp) {
626 time_stamp_dts.set_timestamp_reorder_mode(true);
627 time_stamp_dts.enable_debug_print(true);
628 }
629
630 property_value[0] = '\0';
631 property_get("vidc.dec.debug.concealedmb", property_value, "0");
632 m_debug_concealedmb = atoi(property_value);
633 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
634
635 property_value[0] = '\0';
636 property_get("vidc.dec.profile.check", property_value, "0");
637 m_reject_avc_1080p_mp = atoi(property_value);
638 DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
639
640 property_value[0] = '\0';
641 property_get("vidc.dec.log.in", property_value, "0");
642 m_debug.in_buffer_log = atoi(property_value);
643
644 property_value[0] = '\0';
645 property_get("vidc.dec.log.out", property_value, "0");
646 m_debug.out_buffer_log = atoi(property_value);
647 sprintf(m_debug.log_loc, "%s", BUFFER_LOG_LOC);
648
649 property_value[0] = '\0';
650 property_get("vidc.log.loc", property_value, "");
651 if (*property_value)
652 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
653
654 property_value[0] = '\0';
655 property_get("vidc.dec.120fps.enabled", property_value, "0");
656
657 //if this feature is not enabled then reset this value -ve
658 if(atoi(property_value)) {
659 DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
660 m_last_rendered_TS = 0;
661 }
662
663 property_value[0] = '\0';
664 property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
665 m_disable_dynamic_buf_mode = atoi(property_value);
666 DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
667
668 #endif
669 memset(&m_cmp,0,sizeof(m_cmp));
670 memset(&m_cb,0,sizeof(m_cb));
671 memset (&drv_ctx,0,sizeof(drv_ctx));
672 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
673 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
674 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
675 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
676 m_demux_entries = 0;
677 msg_thread_id = 0;
678 async_thread_id = 0;
679 msg_thread_created = false;
680 async_thread_created = false;
681 #ifdef _ANDROID_ICS_
682 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
683 #endif
684 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
685
686 /* invalidate m_frame_pack_arrangement */
687 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
688 m_frame_pack_arrangement.cancel_flag = 1;
689
690 drv_ctx.timestamp_adjust = false;
691 drv_ctx.video_driver_fd = -1;
692 m_vendor_config.pData = NULL;
693 pthread_mutex_init(&m_lock, NULL);
694 pthread_mutex_init(&c_lock, NULL);
695 pthread_mutex_init(&buf_lock, NULL);
696 sem_init(&m_cmd_lock,0,0);
697 sem_init(&m_safe_flush, 0, 0);
698 streaming[CAPTURE_PORT] =
699 streaming[OUTPUT_PORT] = false;
700 #ifdef _ANDROID_
701 char extradata_value[PROPERTY_VALUE_MAX] = {0};
702 property_get("vidc.dec.debug.extradata", extradata_value, "0");
703 m_debug_extradata = atoi(extradata_value);
704 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
705 #endif
706 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
707 client_buffers.set_vdec_client(this);
708 dynamic_buf_mode = false;
709 out_dynamic_list = NULL;
710 is_down_scalar_enabled = false;
711 m_smoothstreaming_mode = false;
712 m_smoothstreaming_width = 0;
713 m_smoothstreaming_height = 0;
714 is_q6_platform = false;
715 }
716
717 static const int event_type[] = {
718 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
719 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
720 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
721 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
722 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
723 V4L2_EVENT_MSM_VIDC_CLOSE_DONE,
724 V4L2_EVENT_MSM_VIDC_SYS_ERROR,
725 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
726 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
727 };
728
subscribe_to_events(int fd)729 static OMX_ERRORTYPE subscribe_to_events(int fd)
730 {
731 OMX_ERRORTYPE eRet = OMX_ErrorNone;
732 struct v4l2_event_subscription sub;
733 int array_sz = sizeof(event_type)/sizeof(int);
734 int i,rc;
735 if (fd < 0) {
736 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
737 return OMX_ErrorBadParameter;
738 }
739
740 for (i = 0; i < array_sz; ++i) {
741 memset(&sub, 0, sizeof(sub));
742 sub.type = event_type[i];
743 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
744 if (rc) {
745 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
746 break;
747 }
748 }
749 if (i < array_sz) {
750 for (--i; i >=0 ; i--) {
751 memset(&sub, 0, sizeof(sub));
752 sub.type = event_type[i];
753 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
754 if (rc)
755 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
756 }
757 eRet = OMX_ErrorNotImplemented;
758 }
759 return eRet;
760 }
761
762
unsubscribe_to_events(int fd)763 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
764 {
765 OMX_ERRORTYPE eRet = OMX_ErrorNone;
766 struct v4l2_event_subscription sub;
767 int array_sz = sizeof(event_type)/sizeof(int);
768 int i,rc;
769 if (fd < 0) {
770 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
771 return OMX_ErrorBadParameter;
772 }
773
774 for (i = 0; i < array_sz; ++i) {
775 memset(&sub, 0, sizeof(sub));
776 sub.type = event_type[i];
777 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
778 if (rc) {
779 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
780 break;
781 }
782 }
783 return eRet;
784 }
785
786 /* ======================================================================
787 FUNCTION
788 omx_vdec::~omx_vdec
789
790 DESCRIPTION
791 Destructor
792
793 PARAMETERS
794 None
795
796 RETURN VALUE
797 None.
798 ========================================================================== */
~omx_vdec()799 omx_vdec::~omx_vdec()
800 {
801 m_pmem_info = NULL;
802 struct v4l2_decoder_cmd dec;
803 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
804 if (m_pipe_in) close(m_pipe_in);
805 if (m_pipe_out) close(m_pipe_out);
806 m_pipe_in = -1;
807 m_pipe_out = -1;
808 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
809 if (msg_thread_created)
810 pthread_join(msg_thread_id,NULL);
811 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
812 dec.cmd = V4L2_DEC_CMD_STOP;
813 if (drv_ctx.video_driver_fd >=0 ) {
814 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec))
815 DEBUG_PRINT_ERROR("STOP Command failed");
816 }
817 if (async_thread_created)
818 pthread_join(async_thread_id,NULL);
819 unsubscribe_to_events(drv_ctx.video_driver_fd);
820 close(drv_ctx.video_driver_fd);
821 pthread_mutex_destroy(&m_lock);
822 pthread_mutex_destroy(&c_lock);
823 pthread_mutex_destroy(&buf_lock);
824 sem_destroy(&m_cmd_lock);
825 if (perf_flag) {
826 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
827 dec_time.end();
828 }
829 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
830 }
831
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)832 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
833 {
834 struct v4l2_requestbuffers bufreq;
835 int rc = 0;
836 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
837 bufreq.memory = V4L2_MEMORY_USERPTR;
838 bufreq.count = 0;
839 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
840 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
841 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
842 bufreq.memory = V4L2_MEMORY_USERPTR;
843 bufreq.count = 0;
844 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
845 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
846 }
847 return rc;
848 }
849
850 /* ======================================================================
851 FUNCTION
852 omx_vdec::OMXCntrlProcessMsgCb
853
854 DESCRIPTION
855 IL Client callbacks are generated through this routine. The decoder
856 provides the thread context for this routine.
857
858 PARAMETERS
859 ctxt -- Context information related to the self.
860 id -- Event identifier. This could be any of the following:
861 1. Command completion event
862 2. Buffer done callback event
863 3. Frame done callback event
864
865 RETURN VALUE
866 None.
867
868 ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)869 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
870 {
871 unsigned long p1; // Parameter - 1
872 unsigned long p2; // Parameter - 2
873 unsigned long ident;
874 unsigned qsize=0; // qsize
875 omx_vdec *pThis = (omx_vdec *) ctxt;
876
877 if (!pThis) {
878 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
879 __func__);
880 return;
881 }
882
883 // Protect the shared queue data structure
884 do {
885 /*Read the message id's from the queue*/
886 pthread_mutex_lock(&pThis->m_lock);
887 qsize = pThis->m_cmd_q.m_size;
888 if (qsize) {
889 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
890 }
891
892 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
893 qsize = pThis->m_ftb_q.m_size;
894 if (qsize) {
895 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
896 }
897 }
898
899 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
900 qsize = pThis->m_etb_q.m_size;
901 if (qsize) {
902 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
903 }
904 }
905 pthread_mutex_unlock(&pThis->m_lock);
906
907 /*process message if we have one*/
908 if (qsize > 0) {
909 id = ident;
910 switch (id) {
911 case OMX_COMPONENT_GENERATE_EVENT:
912 if (pThis->m_cb.EventHandler) {
913 switch (p1) {
914 case OMX_CommandStateSet:
915 pThis->m_state = (OMX_STATETYPE) p2;
916 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
917 pThis->m_state);
918 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
919 OMX_EventCmdComplete, p1, p2, NULL);
920 break;
921
922 case OMX_EventError:
923 if (p2 == OMX_StateInvalid) {
924 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
925 pThis->m_state = (OMX_STATETYPE) p2;
926 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
927 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
928 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
929 pThis->omx_report_error();
930 } else {
931 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
932 OMX_EventError, p2, (OMX_U32)NULL, NULL );
933 }
934 break;
935
936 case OMX_CommandPortDisable:
937 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
938 if (BITMASK_PRESENT(&pThis->m_flags,
939 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
940 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
941 break;
942 }
943 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
944 OMX_ERRORTYPE eRet = OMX_ErrorNone;
945 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
946 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
947 DEBUG_PRINT_HIGH("Failed to release output buffers");
948 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
949 pThis->in_reconfig = false;
950 if (eRet != OMX_ErrorNone) {
951 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
952 pThis->omx_report_error();
953 break;
954 }
955 }
956 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
957 OMX_EventCmdComplete, p1, p2, NULL );
958 break;
959 case OMX_CommandPortEnable:
960 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
961 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
962 OMX_EventCmdComplete, p1, p2, NULL );
963 break;
964
965 default:
966 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
967 OMX_EventCmdComplete, p1, p2, NULL );
968 break;
969
970 }
971 } else {
972 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
973 }
974 break;
975 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
976 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
977 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
978 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
979 pThis->omx_report_error ();
980 }
981 break;
982 case OMX_COMPONENT_GENERATE_ETB: {
983 OMX_ERRORTYPE iret;
984 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
985 if (iret == OMX_ErrorInsufficientResources) {
986 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
987 pThis->omx_report_hw_overload ();
988 } else if (iret != OMX_ErrorNone) {
989 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
990 pThis->omx_report_error ();
991 }
992 }
993 break;
994
995 case OMX_COMPONENT_GENERATE_FTB:
996 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
997 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
998 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
999 pThis->omx_report_error ();
1000 }
1001 break;
1002
1003 case OMX_COMPONENT_GENERATE_COMMAND:
1004 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1005 (OMX_U32)p2,(OMX_PTR)NULL);
1006 break;
1007
1008 case OMX_COMPONENT_GENERATE_EBD:
1009
1010 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1011 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1012 pThis->omx_report_error ();
1013 } else {
1014 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1015 pThis->time_stamp_dts.remove_time_stamp(
1016 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1017 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1018 ?true:false);
1019 }
1020 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1021 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1022 DEBUG_PRINT_ERROR("empty_buffer_done failure");
1023 pThis->omx_report_error ();
1024 }
1025 }
1026 break;
1027 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1028 int64_t *timestamp = (int64_t *)(intptr_t)p1;
1029 if (p1) {
1030 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1031 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1032 ?true:false);
1033 free(timestamp);
1034 }
1035 }
1036 break;
1037 case OMX_COMPONENT_GENERATE_FBD:
1038 if (p2 != VDEC_S_SUCCESS) {
1039 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1040 pThis->omx_report_error ();
1041 } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1042 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1043 DEBUG_PRINT_ERROR("fill_buffer_done failure");
1044 pThis->omx_report_error ();
1045 }
1046 break;
1047
1048 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1049 DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1050 if (!pThis->input_flush_progress) {
1051 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1052 } else {
1053 pThis->execute_input_flush();
1054 if (pThis->m_cb.EventHandler) {
1055 if (p2 != VDEC_S_SUCCESS) {
1056 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1057 pThis->omx_report_error ();
1058 } else {
1059 /*Check if we need generate event for Flush done*/
1060 if (BITMASK_PRESENT(&pThis->m_flags,
1061 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
1062 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
1063 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
1064 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1065 OMX_EventCmdComplete,OMX_CommandFlush,
1066 OMX_CORE_INPUT_PORT_INDEX,NULL );
1067 }
1068 if (BITMASK_PRESENT(&pThis->m_flags,
1069 OMX_COMPONENT_IDLE_PENDING)) {
1070 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1071 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1072 pThis->omx_report_error ();
1073 } else {
1074 pThis->streaming[OUTPUT_PORT] = false;
1075 }
1076 if (!pThis->output_flush_progress) {
1077 DEBUG_PRINT_LOW("Input flush done hence issue stop");
1078 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1079 OMX_COMPONENT_GENERATE_STOP_DONE);
1080 }
1081 }
1082 }
1083 } else {
1084 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1085 }
1086 }
1087 break;
1088
1089 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1090 DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1091 if (!pThis->output_flush_progress) {
1092 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1093 } else {
1094 pThis->execute_output_flush();
1095 if (pThis->m_cb.EventHandler) {
1096 if (p2 != VDEC_S_SUCCESS) {
1097 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1098 pThis->omx_report_error ();
1099 } else {
1100 /*Check if we need generate event for Flush done*/
1101 if (BITMASK_PRESENT(&pThis->m_flags,
1102 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
1103 DEBUG_PRINT_LOW("Notify Output Flush done");
1104 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1105 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1106 OMX_EventCmdComplete,OMX_CommandFlush,
1107 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1108 }
1109 if (BITMASK_PRESENT(&pThis->m_flags,
1110 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1111 DEBUG_PRINT_LOW("Internal flush complete");
1112 BITMASK_CLEAR (&pThis->m_flags,
1113 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1114 if (BITMASK_PRESENT(&pThis->m_flags,
1115 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1116 pThis->post_event(OMX_CommandPortDisable,
1117 OMX_CORE_OUTPUT_PORT_INDEX,
1118 OMX_COMPONENT_GENERATE_EVENT);
1119 BITMASK_CLEAR (&pThis->m_flags,
1120 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1121 BITMASK_CLEAR (&pThis->m_flags,
1122 OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1123
1124 }
1125 }
1126
1127 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1128 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1129 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1130 pThis->omx_report_error ();
1131 break;
1132 }
1133 pThis->streaming[CAPTURE_PORT] = false;
1134 if (!pThis->input_flush_progress) {
1135 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1136 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1137 OMX_COMPONENT_GENERATE_STOP_DONE);
1138 }
1139 }
1140 }
1141 } else {
1142 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1143 }
1144 }
1145 break;
1146
1147 case OMX_COMPONENT_GENERATE_START_DONE:
1148 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1149
1150 if (pThis->m_cb.EventHandler) {
1151 if (p2 != VDEC_S_SUCCESS) {
1152 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1153 pThis->omx_report_error ();
1154 } else {
1155 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1156 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1157 DEBUG_PRINT_LOW("Move to executing");
1158 // Send the callback now
1159 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1160 pThis->m_state = OMX_StateExecuting;
1161 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1162 OMX_EventCmdComplete,OMX_CommandStateSet,
1163 OMX_StateExecuting, NULL);
1164 } else if (BITMASK_PRESENT(&pThis->m_flags,
1165 OMX_COMPONENT_PAUSE_PENDING)) {
1166 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1167 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1168 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1169 pThis->omx_report_error ();
1170 }
1171 }
1172 }
1173 } else {
1174 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1175 }
1176 break;
1177
1178 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1179 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1180 if (pThis->m_cb.EventHandler) {
1181 if (p2 != VDEC_S_SUCCESS) {
1182 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1183 pThis->omx_report_error ();
1184 } else {
1185 pThis->complete_pending_buffer_done_cbs();
1186 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1187 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1188 //Send the callback now
1189 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1190 pThis->m_state = OMX_StatePause;
1191 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1192 OMX_EventCmdComplete,OMX_CommandStateSet,
1193 OMX_StatePause, NULL);
1194 }
1195 }
1196 } else {
1197 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1198 }
1199
1200 break;
1201
1202 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1203 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1204 if (pThis->m_cb.EventHandler) {
1205 if (p2 != VDEC_S_SUCCESS) {
1206 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1207 pThis->omx_report_error ();
1208 } else {
1209 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1210 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1211 // Send the callback now
1212 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1213 pThis->m_state = OMX_StateExecuting;
1214 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1215 OMX_EventCmdComplete,OMX_CommandStateSet,
1216 OMX_StateExecuting,NULL);
1217 }
1218 }
1219 } else {
1220 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1221 }
1222
1223 break;
1224
1225 case OMX_COMPONENT_GENERATE_STOP_DONE:
1226 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1227 if (pThis->m_cb.EventHandler) {
1228 if (p2 != VDEC_S_SUCCESS) {
1229 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1230 pThis->omx_report_error ();
1231 } else {
1232 pThis->complete_pending_buffer_done_cbs();
1233 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1234 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1235 // Send the callback now
1236 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1237 pThis->m_state = OMX_StateIdle;
1238 DEBUG_PRINT_LOW("Move to Idle State");
1239 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1240 OMX_EventCmdComplete,OMX_CommandStateSet,
1241 OMX_StateIdle,NULL);
1242 }
1243 }
1244 } else {
1245 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1246 }
1247
1248 break;
1249
1250 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1251 if (p2 == OMX_IndexParamPortDefinition) {
1252 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1253 pThis->in_reconfig = true;
1254
1255 } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1256 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1257
1258 /* Check if resolution is changed in smooth streaming mode */
1259 if (pThis->m_smoothstreaming_mode &&
1260 (pThis->framesize.nWidth !=
1261 pThis->drv_ctx.video_resolution.frame_width) ||
1262 (pThis->framesize.nHeight !=
1263 pThis->drv_ctx.video_resolution.frame_height)) {
1264
1265 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1266 pThis->framesize.nWidth,
1267 pThis->framesize.nHeight,
1268 pThis->drv_ctx.video_resolution.frame_width,
1269 pThis->drv_ctx.video_resolution.frame_height);
1270
1271 /* Update new resolution */
1272 pThis->framesize.nWidth =
1273 pThis->drv_ctx.video_resolution.frame_width;
1274 pThis->framesize.nHeight =
1275 pThis->drv_ctx.video_resolution.frame_height;
1276
1277 /* Update C2D with new resolution */
1278 if (!pThis->client_buffers.update_buffer_req()) {
1279 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1280 }
1281 }
1282
1283 /* Update new crop information */
1284 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1285 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1286 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1287 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1288
1289 /* Validate the new crop information */
1290 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1291 pThis->drv_ctx.video_resolution.frame_width) {
1292
1293 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1294 pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1295 pThis->drv_ctx.video_resolution.frame_width);
1296 pThis->rectangle.nLeft = 0;
1297
1298 if (pThis->rectangle.nWidth >
1299 pThis->drv_ctx.video_resolution.frame_width) {
1300
1301 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1302 pThis->rectangle.nWidth,
1303 pThis->drv_ctx.video_resolution.frame_width);
1304 pThis->rectangle.nWidth =
1305 pThis->drv_ctx.video_resolution.frame_width;
1306 }
1307 }
1308 if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1309 pThis->drv_ctx.video_resolution.frame_height) {
1310
1311 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1312 pThis->rectangle.nTop, pThis->rectangle.nHeight,
1313 pThis->drv_ctx.video_resolution.frame_height);
1314 pThis->rectangle.nTop = 0;
1315
1316 if (pThis->rectangle.nHeight >
1317 pThis->drv_ctx.video_resolution.frame_height) {
1318
1319 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1320 pThis->rectangle.nHeight,
1321 pThis->drv_ctx.video_resolution.frame_height);
1322 pThis->rectangle.nHeight =
1323 pThis->drv_ctx.video_resolution.frame_height;
1324 }
1325 }
1326 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1327 pThis->rectangle.nLeft, pThis->rectangle.nTop,
1328 pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1329 } else {
1330 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1331 break;
1332 }
1333 if (pThis->m_cb.EventHandler) {
1334 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1335 OMX_EventPortSettingsChanged, p1, p2, NULL );
1336 } else {
1337 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1338 }
1339
1340 break;
1341
1342 case OMX_COMPONENT_GENERATE_EOS_DONE:
1343 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1344 if (pThis->m_cb.EventHandler) {
1345 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1346 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1347 } else {
1348 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1349 }
1350 pThis->prev_ts = LLONG_MAX;
1351 pThis->rst_prev_ts = true;
1352 break;
1353
1354 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1355 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1356 pThis->omx_report_error ();
1357 break;
1358
1359 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1360 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1361 pThis->omx_report_unsupported_setting();
1362 break;
1363
1364 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1365 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1366 pThis->omx_report_hw_overload();
1367 break;
1368
1369 default:
1370 break;
1371 }
1372 }
1373 pthread_mutex_lock(&pThis->m_lock);
1374 qsize = pThis->m_cmd_q.m_size;
1375 if (pThis->m_state != OMX_StatePause)
1376 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1377 pthread_mutex_unlock(&pThis->m_lock);
1378 } while (qsize>0);
1379
1380 }
1381
update_resolution(int width,int height,int stride,int scan_lines)1382 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1383 {
1384 int format_changed = 0;
1385 if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1386 (width != (int)drv_ctx.video_resolution.frame_width)) {
1387 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1388 width, drv_ctx.video_resolution.frame_width,
1389 height,drv_ctx.video_resolution.frame_height);
1390 format_changed = 1;
1391 }
1392 drv_ctx.video_resolution.frame_height = height;
1393 drv_ctx.video_resolution.frame_width = width;
1394 drv_ctx.video_resolution.scan_lines = scan_lines;
1395 drv_ctx.video_resolution.stride = stride;
1396 if(!is_down_scalar_enabled) {
1397 rectangle.nLeft = 0;
1398 rectangle.nTop = 0;
1399 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1400 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1401 }
1402 return format_changed;
1403 }
1404
is_video_session_supported()1405 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1406 {
1407 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1408 OMX_MAX_STRINGNAME_SIZE) &&
1409 (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1410 m_decoder_capability.max_width = 1280;
1411 m_decoder_capability.max_height = 720;
1412 DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1413 }
1414
1415 if ((drv_ctx.video_resolution.frame_width *
1416 drv_ctx.video_resolution.frame_height >
1417 m_decoder_capability.max_width *
1418 m_decoder_capability.max_height) ||
1419 (drv_ctx.video_resolution.frame_width*
1420 drv_ctx.video_resolution.frame_height <
1421 m_decoder_capability.min_width *
1422 m_decoder_capability.min_height)) {
1423 DEBUG_PRINT_ERROR(
1424 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1425 drv_ctx.video_resolution.frame_width,
1426 drv_ctx.video_resolution.frame_height,
1427 m_decoder_capability.min_width,
1428 m_decoder_capability.min_height,
1429 m_decoder_capability.max_width,
1430 m_decoder_capability.max_height);
1431 return OMX_ErrorUnsupportedSetting;
1432 }
1433 DEBUG_PRINT_HIGH("video session supported");
1434 return OMX_ErrorNone;
1435 }
1436
log_input_buffers(const char * buffer_addr,int buffer_len)1437 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1438 {
1439 if (m_debug.in_buffer_log && !m_debug.infile) {
1440 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1441 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.m4v",
1442 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1443 }
1444 else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1445 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this); }
1446 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
1447 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.263",
1448 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1449 }
1450 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1451 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1452 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.264",
1453 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1454 }
1455 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1456 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.265",
1457 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1458 }
1459 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
1460 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.vc1",
1461 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1462 }
1463 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
1464 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.vc1",
1465 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1466 }
1467 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1468 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.ivf",
1469 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1470 }
1471 else {
1472 sprintf(m_debug.infile_name, "%s/input_dec_%d_%d_%p.divx",
1473 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1474 }
1475 m_debug.infile = fopen (m_debug.infile_name, "ab");
1476 if (!m_debug.infile) {
1477 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1478 m_debug.infile_name[0] = '\0';
1479 return -1;
1480 }
1481 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1482 struct ivf_file_header {
1483 OMX_U8 signature[4]; //='DKIF';
1484 OMX_U8 version ; //= 0;
1485 OMX_U8 headersize ; //= 32;
1486 OMX_U32 FourCC;
1487 OMX_U8 width;
1488 OMX_U8 height;
1489 OMX_U32 rate;
1490 OMX_U32 scale;
1491 OMX_U32 length;
1492 OMX_U8 unused[4];
1493 } file_header;
1494
1495 memset((void *)&file_header,0,sizeof(file_header));
1496 file_header.signature[0] = 'D';
1497 file_header.signature[1] = 'K';
1498 file_header.signature[2] = 'I';
1499 file_header.signature[3] = 'F';
1500 file_header.version = 0;
1501 file_header.headersize = 32;
1502 file_header.FourCC = 0x30385056;
1503 fwrite((const char *)&file_header,
1504 sizeof(file_header),1,m_debug.infile);
1505 }
1506 }
1507 if (m_debug.infile && buffer_addr && buffer_len) {
1508 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1509 struct vp8_ivf_frame_header {
1510 OMX_U32 framesize;
1511 OMX_U32 timestamp_lo;
1512 OMX_U32 timestamp_hi;
1513 } vp8_frame_header;
1514 vp8_frame_header.framesize = buffer_len;
1515 /* Currently FW doesn't use timestamp values */
1516 vp8_frame_header.timestamp_lo = 0;
1517 vp8_frame_header.timestamp_hi = 0;
1518 fwrite((const char *)&vp8_frame_header,
1519 sizeof(vp8_frame_header),1,m_debug.infile);
1520 }
1521 fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1522 }
1523 return 0;
1524 }
1525
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1526 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
1527 if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
1528 sprintf(m_debug.outfile_name, "%s/output_%d_%d_%p.yuv",
1529 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1530 m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1531 if (!m_debug.outfile) {
1532 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1533 m_debug.outfile_name[0] = '\0';
1534 return -1;
1535 }
1536 }
1537 if (m_debug.outfile && buffer && buffer->nFilledLen) {
1538 int buf_index = buffer - m_out_mem_ptr;
1539 int stride = drv_ctx.video_resolution.stride;
1540 int scanlines = drv_ctx.video_resolution.scan_lines;
1541 if (m_smoothstreaming_mode) {
1542 stride = drv_ctx.video_resolution.frame_width;
1543 scanlines = drv_ctx.video_resolution.frame_height;
1544 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
1545 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
1546 }
1547 char *temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1548 unsigned i;
1549 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1550 drv_ctx.video_resolution.frame_width,
1551 drv_ctx.video_resolution.frame_height, stride, scanlines);
1552 int bytes_written = 0;
1553 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1554 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1555 temp += stride;
1556 }
1557 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
1558 int stride_c = stride;
1559 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1560 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1561 temp += stride_c;
1562 }
1563 }
1564 return 0;
1565 }
1566
1567 /* ======================================================================
1568 FUNCTION
1569 omx_vdec::ComponentInit
1570
1571 DESCRIPTION
1572 Initialize the component.
1573
1574 PARAMETERS
1575 ctxt -- Context information related to the self.
1576 id -- Event identifier. This could be any of the following:
1577 1. Command completion event
1578 2. Buffer done callback event
1579 3. Frame done callback event
1580
1581 RETURN VALUE
1582 None.
1583
1584 ========================================================================== */
component_init(OMX_STRING role)1585 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1586 {
1587
1588 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1589 struct v4l2_fmtdesc fdesc;
1590 struct v4l2_format fmt;
1591 struct v4l2_requestbuffers bufreq;
1592 struct v4l2_control control;
1593 struct v4l2_frmsizeenum frmsize;
1594 unsigned int alignment = 0,buffer_size = 0;
1595 int fds[2];
1596 int r,ret=0;
1597 bool codec_ambiguous = false;
1598 OMX_STRING device_name = (OMX_STRING)"/dev/video32";
1599 char property_value[PROPERTY_VALUE_MAX] = {0};
1600
1601 #ifdef _ANDROID_
1602 char platform_name[PROPERTY_VALUE_MAX];
1603 property_get("ro.board.platform", platform_name, "0");
1604 if (!strncmp(platform_name, "msm8610", 7)) {
1605 device_name = (OMX_STRING)"/dev/video/q6_dec";
1606 is_q6_platform = true;
1607 maxSmoothStreamingWidth = 1280;
1608 maxSmoothStreamingHeight = 720;
1609 }
1610 #endif
1611
1612 #ifdef _ANDROID_
1613 /*
1614 * turn off frame parsing for Android by default.
1615 * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
1616 */
1617 arbitrary_bytes = false;
1618 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
1619 if (atoi(property_value)) {
1620 DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
1621 arbitrary_bytes = true;
1622 }
1623 #endif
1624
1625 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
1626 OMX_MAX_STRINGNAME_SIZE)) {
1627 secure_mode = true;
1628 arbitrary_bytes = false;
1629 role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
1630 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
1631 OMX_MAX_STRINGNAME_SIZE)) {
1632 secure_mode = true;
1633 arbitrary_bytes = false;
1634 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
1635 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
1636 OMX_MAX_STRINGNAME_SIZE)) {
1637 secure_mode = true;
1638 arbitrary_bytes = false;
1639 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
1640 } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
1641 OMX_MAX_STRINGNAME_SIZE)) {
1642 secure_mode = true;
1643 arbitrary_bytes = false;
1644 role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
1645 } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
1646 OMX_MAX_STRINGNAME_SIZE)) {
1647 secure_mode = true;
1648 arbitrary_bytes = false;
1649 role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
1650 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
1651 OMX_MAX_STRINGNAME_SIZE)) {
1652 secure_mode = true;
1653 arbitrary_bytes = false;
1654 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
1655 }
1656
1657 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1658
1659 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
1660
1661 if (drv_ctx.video_driver_fd == 0) {
1662 DEBUG_PRINT_ERROR("omx_vdec_msm8974 :: Got fd as 0 for msm_vidc_dec, Opening again");
1663 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1664 close(0);
1665 }
1666
1667 if (drv_ctx.video_driver_fd < 0) {
1668 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
1669 return OMX_ErrorInsufficientResources;
1670 }
1671 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1672 drv_ctx.frame_rate.fps_denominator = 1;
1673
1674 ret = subscribe_to_events(drv_ctx.video_driver_fd);
1675 if (!ret) {
1676 async_thread_created = true;
1677 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
1678 }
1679 if (ret) {
1680 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
1681 async_thread_created = false;
1682 return OMX_ErrorInsufficientResources;
1683 }
1684
1685 #ifdef OUTPUT_EXTRADATA_LOG
1686 outputExtradataFile = fopen (output_extradata_filename, "ab");
1687 #endif
1688
1689 // Copy the role information which provides the decoder kind
1690 strlcpy(drv_ctx.kind,role,128);
1691
1692 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
1693 OMX_MAX_STRINGNAME_SIZE)) {
1694 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
1695 OMX_MAX_STRINGNAME_SIZE);
1696 drv_ctx.timestamp_adjust = true;
1697 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
1698 eCompressionFormat = OMX_VIDEO_CodingMPEG4;
1699 output_capability=V4L2_PIX_FMT_MPEG4;
1700 /*Initialize Start Code for MPEG4*/
1701 codec_type_parse = CODEC_TYPE_MPEG4;
1702 m_frame_parser.init_start_codes (codec_type_parse);
1703 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
1704 OMX_MAX_STRINGNAME_SIZE)) {
1705 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
1706 OMX_MAX_STRINGNAME_SIZE);
1707 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
1708 output_capability = V4L2_PIX_FMT_MPEG2;
1709 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
1710 /*Initialize Start Code for MPEG2*/
1711 codec_type_parse = CODEC_TYPE_MPEG2;
1712 m_frame_parser.init_start_codes (codec_type_parse);
1713 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
1714 OMX_MAX_STRINGNAME_SIZE)) {
1715 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
1716 DEBUG_PRINT_LOW("H263 Decoder selected");
1717 drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
1718 eCompressionFormat = OMX_VIDEO_CodingH263;
1719 output_capability = V4L2_PIX_FMT_H263;
1720 codec_type_parse = CODEC_TYPE_H263;
1721 m_frame_parser.init_start_codes (codec_type_parse);
1722 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
1723 OMX_MAX_STRINGNAME_SIZE)) {
1724 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1725 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
1726 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
1727 output_capability = V4L2_PIX_FMT_DIVX_311;
1728 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1729 codec_type_parse = CODEC_TYPE_DIVX;
1730 m_frame_parser.init_start_codes (codec_type_parse);
1731
1732 eRet = createDivxDrmContext();
1733 if (eRet != OMX_ErrorNone) {
1734 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1735 return eRet;
1736 }
1737 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
1738 OMX_MAX_STRINGNAME_SIZE)) {
1739 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1740 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
1741 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
1742 output_capability = V4L2_PIX_FMT_DIVX;
1743 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1744 codec_type_parse = CODEC_TYPE_DIVX;
1745 codec_ambiguous = true;
1746 m_frame_parser.init_start_codes (codec_type_parse);
1747
1748 eRet = createDivxDrmContext();
1749 if (eRet != OMX_ErrorNone) {
1750 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1751 return eRet;
1752 }
1753 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
1754 OMX_MAX_STRINGNAME_SIZE)) {
1755 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1756 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
1757 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
1758 output_capability = V4L2_PIX_FMT_DIVX;
1759 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1760 codec_type_parse = CODEC_TYPE_DIVX;
1761 codec_ambiguous = true;
1762 m_frame_parser.init_start_codes (codec_type_parse);
1763
1764 eRet = createDivxDrmContext();
1765 if (eRet != OMX_ErrorNone) {
1766 DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
1767 return eRet;
1768 }
1769
1770 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
1771 OMX_MAX_STRINGNAME_SIZE)) {
1772 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
1773 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
1774 output_capability=V4L2_PIX_FMT_H264;
1775 eCompressionFormat = OMX_VIDEO_CodingAVC;
1776 codec_type_parse = CODEC_TYPE_H264;
1777 m_frame_parser.init_start_codes (codec_type_parse);
1778 m_frame_parser.init_nal_length(nal_length);
1779 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
1780 OMX_MAX_STRINGNAME_SIZE)) {
1781 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
1782 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
1783 output_capability = V4L2_PIX_FMT_H264_MVC;
1784 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
1785 codec_type_parse = CODEC_TYPE_H264;
1786 m_frame_parser.init_start_codes(codec_type_parse);
1787 m_frame_parser.init_nal_length(nal_length);
1788 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
1789 OMX_MAX_STRINGNAME_SIZE)) {
1790 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
1791 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
1792 output_capability = V4L2_PIX_FMT_HEVC;
1793 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
1794 codec_type_parse = CODEC_TYPE_HEVC;
1795 m_frame_parser.init_start_codes(codec_type_parse);
1796 m_frame_parser.init_nal_length(nal_length);
1797 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
1798 OMX_MAX_STRINGNAME_SIZE)) {
1799 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1800 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
1801 eCompressionFormat = OMX_VIDEO_CodingWMV;
1802 codec_type_parse = CODEC_TYPE_VC1;
1803 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
1804 m_frame_parser.init_start_codes (codec_type_parse);
1805 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
1806 OMX_MAX_STRINGNAME_SIZE)) {
1807 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1808 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
1809 eCompressionFormat = OMX_VIDEO_CodingWMV;
1810 codec_type_parse = CODEC_TYPE_VC1;
1811 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
1812 m_frame_parser.init_start_codes (codec_type_parse);
1813 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
1814 OMX_MAX_STRINGNAME_SIZE)) {
1815 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
1816 output_capability=V4L2_PIX_FMT_VP8;
1817 eCompressionFormat = OMX_VIDEO_CodingVP8;
1818 codec_type_parse = CODEC_TYPE_VP8;
1819 arbitrary_bytes = false;
1820
1821 } else {
1822 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
1823 eRet = OMX_ErrorInvalidComponentName;
1824 }
1825 if (eRet == OMX_ErrorNone) {
1826 OMX_COLOR_FORMATTYPE dest_color_format;
1827 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
1828 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
1829 dest_color_format = (OMX_COLOR_FORMATTYPE)
1830 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
1831 else
1832 dest_color_format = (OMX_COLOR_FORMATTYPE)
1833 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
1834 if (!client_buffers.set_color_format(dest_color_format)) {
1835 DEBUG_PRINT_ERROR("Setting color format failed");
1836 eRet = OMX_ErrorInsufficientResources;
1837 }
1838
1839 capture_capability= V4L2_PIX_FMT_NV12;
1840
1841 struct v4l2_capability cap;
1842 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
1843 if (ret) {
1844 DEBUG_PRINT_ERROR("Failed to query capabilities");
1845 /*TODO: How to handle this case */
1846 } else {
1847 DEBUG_PRINT_INFO("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1848 " version = %d, capabilities = %x", cap.driver, cap.card,
1849 cap.bus_info, cap.version, cap.capabilities);
1850 }
1851 ret=0;
1852 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1853 fdesc.index=0;
1854 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1855 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1856 fdesc.pixelformat, fdesc.flags);
1857 fdesc.index++;
1858 }
1859 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1860 fdesc.index=0;
1861 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1862
1863 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
1864 fdesc.pixelformat, fdesc.flags);
1865 fdesc.index++;
1866 }
1867 update_resolution(320, 240, 320, 240);
1868 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1869 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1870 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1871 fmt.fmt.pix_mp.pixelformat = output_capability;
1872 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1873 if (ret) {
1874 /*TODO: How to handle this case */
1875 DEBUG_PRINT_ERROR("Failed to set format on output port");
1876 return OMX_ErrorInsufficientResources;
1877 }
1878 DEBUG_PRINT_HIGH("Set Format was successful");
1879 if (codec_ambiguous) {
1880 if (output_capability == V4L2_PIX_FMT_DIVX) {
1881 struct v4l2_control divx_ctrl;
1882
1883 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
1884 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
1885 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
1886 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
1887 } else {
1888 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
1889 }
1890
1891 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
1892 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
1893 if (ret) {
1894 DEBUG_PRINT_ERROR("Failed to set divx version");
1895 }
1896 } else {
1897 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
1898 }
1899 }
1900
1901 property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
1902 m_conceal_color= atoi(property_value);
1903 DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
1904 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
1905 control.value = m_conceal_color;
1906 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1907 if (ret) {
1908 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
1909 }
1910
1911 //Get the hardware capabilities
1912 memset((void *)&frmsize,0,sizeof(frmsize));
1913 frmsize.index = 0;
1914 frmsize.pixel_format = output_capability;
1915 ret = ioctl(drv_ctx.video_driver_fd,
1916 VIDIOC_ENUM_FRAMESIZES, &frmsize);
1917 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
1918 DEBUG_PRINT_ERROR("Failed to get framesizes");
1919 return OMX_ErrorHardware;
1920 }
1921
1922 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
1923 m_decoder_capability.min_width = frmsize.stepwise.min_width;
1924 m_decoder_capability.max_width = frmsize.stepwise.max_width;
1925 m_decoder_capability.min_height = frmsize.stepwise.min_height;
1926 m_decoder_capability.max_height = frmsize.stepwise.max_height;
1927 }
1928
1929 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1930 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1931 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1932 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1933 fmt.fmt.pix_mp.pixelformat = capture_capability;
1934 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1935 if (ret) {
1936 /*TODO: How to handle this case */
1937 DEBUG_PRINT_ERROR("Failed to set format on capture port");
1938 }
1939 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
1940 framesize.nWidth = drv_ctx.video_resolution.frame_width;
1941 framesize.nHeight = drv_ctx.video_resolution.frame_height;
1942
1943 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
1944 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1945 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1946
1947 DEBUG_PRINT_HIGH("Set Format was successful");
1948 if (secure_mode) {
1949 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
1950 control.value = 1;
1951 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
1952 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
1953 if (ret) {
1954 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
1955 return OMX_ErrorInsufficientResources;
1956 }
1957 }
1958 if (output_capability == V4L2_PIX_FMT_H264_MVC) {
1959 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
1960 control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
1961 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
1962 if (ret) {
1963 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
1964 return OMX_ErrorInsufficientResources;
1965 }
1966 }
1967
1968 /*Get the Buffer requirements for input and output ports*/
1969 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
1970 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
1971 if (secure_mode) {
1972 drv_ctx.op_buf.alignment=SZ_1M;
1973 drv_ctx.ip_buf.alignment=SZ_1M;
1974 } else {
1975 drv_ctx.op_buf.alignment=SZ_4K;
1976 drv_ctx.ip_buf.alignment=SZ_4K;
1977 }
1978 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
1979 drv_ctx.extradata = 0;
1980 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
1981 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
1982 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
1983 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1984 drv_ctx.idr_only_decoding = 0;
1985
1986 property_get("vidc.debug.turbo", property_value, "0");
1987 if (atoi(property_value)) {
1988 DEBUG_PRINT_HIGH("Turbo mode debug property enabled");
1989 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
1990 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
1991 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
1992 DEBUG_PRINT_ERROR("Failed to set turbo mode");
1993 }
1994 }
1995
1996 m_state = OMX_StateLoaded;
1997 #ifdef DEFAULT_EXTRADATA
1998 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) &&
1999 (eRet == OMX_ErrorNone)) {
2000 DEBUG_PRINT_INFO("Enabling default extradata for %s", drv_ctx.kind);
2001 enable_extradata(DEFAULT_EXTRADATA, true, true);
2002 }
2003 #endif
2004 eRet=get_buffer_req(&drv_ctx.ip_buf);
2005 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2006 get_buffer_req(&drv_ctx.op_buf);
2007 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2008 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2009 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2010 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2011 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2012 h264_scratch.nFilledLen = 0;
2013 h264_scratch.nOffset = 0;
2014
2015 if (h264_scratch.pBuffer == NULL) {
2016 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2017 return OMX_ErrorInsufficientResources;
2018 }
2019 }
2020 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2021 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2022 if (m_frame_parser.mutils == NULL) {
2023 m_frame_parser.mutils = new H264_Utils();
2024 if (m_frame_parser.mutils == NULL) {
2025 DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2026 eRet = OMX_ErrorInsufficientResources;
2027 } else {
2028 m_frame_parser.mutils->initialize_frame_checking_environment();
2029 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2030 }
2031 }
2032
2033 h264_parser = new h264_stream_parser();
2034 if (!h264_parser) {
2035 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2036 eRet = OMX_ErrorInsufficientResources;
2037 }
2038 }
2039
2040 if (pipe(fds)) {
2041 DEBUG_PRINT_ERROR("pipe creation failed");
2042 eRet = OMX_ErrorInsufficientResources;
2043 } else {
2044 int temp1[2];
2045 if (fds[0] == 0 || fds[1] == 0) {
2046 if (pipe (temp1)) {
2047 DEBUG_PRINT_ERROR("pipe creation failed");
2048 return OMX_ErrorInsufficientResources;
2049 }
2050 //close (fds[0]);
2051 //close (fds[1]);
2052 fds[0] = temp1 [0];
2053 fds[1] = temp1 [1];
2054 }
2055 m_pipe_in = fds[0];
2056 m_pipe_out = fds[1];
2057 msg_thread_created = true;
2058 r = pthread_create(&msg_thread_id,0,message_thread,this);
2059
2060 if (r < 0) {
2061 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
2062 msg_thread_created = false;
2063 eRet = OMX_ErrorInsufficientResources;
2064 }
2065 }
2066 }
2067
2068 if (eRet != OMX_ErrorNone) {
2069 DEBUG_PRINT_ERROR("Component Init Failed");
2070 } else {
2071 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2072 drv_ctx.video_driver_fd);
2073 }
2074 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2075 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
2076 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
2077
2078 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
2079 DEBUG_PRINT_ERROR("Failed to set Default Priority");
2080 eRet = OMX_ErrorUnsupportedSetting;
2081 }
2082 return eRet;
2083 }
2084
2085 /* ======================================================================
2086 FUNCTION
2087 omx_vdec::GetComponentVersion
2088
2089 DESCRIPTION
2090 Returns the component version.
2091
2092 PARAMETERS
2093 TBD.
2094
2095 RETURN VALUE
2096 OMX_ErrorNone.
2097
2098 ========================================================================== */
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)2099 OMX_ERRORTYPE omx_vdec::get_component_version
2100 (
2101 OMX_IN OMX_HANDLETYPE hComp,
2102 OMX_OUT OMX_STRING componentName,
2103 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2104 OMX_OUT OMX_VERSIONTYPE* specVersion,
2105 OMX_OUT OMX_UUIDTYPE* componentUUID
2106 )
2107 {
2108 (void) hComp;
2109 (void) componentName;
2110 (void) componentVersion;
2111 (void) componentUUID;
2112 if (m_state == OMX_StateInvalid) {
2113 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2114 return OMX_ErrorInvalidState;
2115 }
2116 /* TBD -- Return the proper version */
2117 if (specVersion) {
2118 specVersion->nVersion = OMX_SPEC_VERSION;
2119 }
2120 return OMX_ErrorNone;
2121 }
2122 /* ======================================================================
2123 FUNCTION
2124 omx_vdec::SendCommand
2125
2126 DESCRIPTION
2127 Returns zero if all the buffers released..
2128
2129 PARAMETERS
2130 None.
2131
2132 RETURN VALUE
2133 true/false
2134
2135 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2136 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2137 OMX_IN OMX_COMMANDTYPE cmd,
2138 OMX_IN OMX_U32 param1,
2139 OMX_IN OMX_PTR cmdData
2140 )
2141 {
2142 (void) hComp;
2143 (void) cmdData;
2144 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2145 if (m_state == OMX_StateInvalid) {
2146 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2147 return OMX_ErrorInvalidState;
2148 }
2149 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2150 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2151 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2152 "to invalid port: %u", (unsigned int)param1);
2153 return OMX_ErrorBadPortIndex;
2154 }
2155
2156 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2157 sem_wait(&m_cmd_lock);
2158 DEBUG_PRINT_LOW("send_command: Command Processed");
2159 return OMX_ErrorNone;
2160 }
2161
2162 /* ======================================================================
2163 FUNCTION
2164 omx_vdec::SendCommand
2165
2166 DESCRIPTION
2167 Returns zero if all the buffers released..
2168
2169 PARAMETERS
2170 None.
2171
2172 RETURN VALUE
2173 true/false
2174
2175 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2176 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2177 OMX_IN OMX_COMMANDTYPE cmd,
2178 OMX_IN OMX_U32 param1,
2179 OMX_IN OMX_PTR cmdData
2180 )
2181 {
2182 (void) hComp;
2183 (void) cmdData;
2184 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2185 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2186 int bFlag = 1,sem_posted = 0,ret=0;
2187
2188 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2189 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2190 m_state, eState);
2191
2192 if (cmd == OMX_CommandStateSet) {
2193 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2194 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2195 /***************************/
2196 /* Current State is Loaded */
2197 /***************************/
2198 if (m_state == OMX_StateLoaded) {
2199 if (eState == OMX_StateIdle) {
2200 //if all buffers are allocated or all ports disabled
2201 if (allocate_done() ||
2202 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2203 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2204 } else {
2205 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2206 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2207 // Skip the event notification
2208 bFlag = 0;
2209 }
2210 }
2211 /* Requesting transition from Loaded to Loaded */
2212 else if (eState == OMX_StateLoaded) {
2213 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2214 post_event(OMX_EventError,OMX_ErrorSameState,\
2215 OMX_COMPONENT_GENERATE_EVENT);
2216 eRet = OMX_ErrorSameState;
2217 }
2218 /* Requesting transition from Loaded to WaitForResources */
2219 else if (eState == OMX_StateWaitForResources) {
2220 /* Since error is None , we will post an event
2221 at the end of this function definition */
2222 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2223 }
2224 /* Requesting transition from Loaded to Executing */
2225 else if (eState == OMX_StateExecuting) {
2226 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2227 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2228 OMX_COMPONENT_GENERATE_EVENT);
2229 eRet = OMX_ErrorIncorrectStateTransition;
2230 }
2231 /* Requesting transition from Loaded to Pause */
2232 else if (eState == OMX_StatePause) {
2233 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2234 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2235 OMX_COMPONENT_GENERATE_EVENT);
2236 eRet = OMX_ErrorIncorrectStateTransition;
2237 }
2238 /* Requesting transition from Loaded to Invalid */
2239 else if (eState == OMX_StateInvalid) {
2240 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2241 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2242 eRet = OMX_ErrorInvalidState;
2243 } else {
2244 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2245 eState);
2246 eRet = OMX_ErrorBadParameter;
2247 }
2248 }
2249
2250 /***************************/
2251 /* Current State is IDLE */
2252 /***************************/
2253 else if (m_state == OMX_StateIdle) {
2254 if (eState == OMX_StateLoaded) {
2255 if (release_done()) {
2256 /*
2257 Since error is None , we will post an event at the end
2258 of this function definition
2259 */
2260 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2261 } else {
2262 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2263 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2264 // Skip the event notification
2265 bFlag = 0;
2266 }
2267 }
2268 /* Requesting transition from Idle to Executing */
2269 else if (eState == OMX_StateExecuting) {
2270 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2271 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2272 bFlag = 1;
2273 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2274 m_state=OMX_StateExecuting;
2275 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2276 }
2277 /* Requesting transition from Idle to Idle */
2278 else if (eState == OMX_StateIdle) {
2279 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2280 post_event(OMX_EventError,OMX_ErrorSameState,\
2281 OMX_COMPONENT_GENERATE_EVENT);
2282 eRet = OMX_ErrorSameState;
2283 }
2284 /* Requesting transition from Idle to WaitForResources */
2285 else if (eState == OMX_StateWaitForResources) {
2286 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2287 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2288 OMX_COMPONENT_GENERATE_EVENT);
2289 eRet = OMX_ErrorIncorrectStateTransition;
2290 }
2291 /* Requesting transition from Idle to Pause */
2292 else if (eState == OMX_StatePause) {
2293 /*To pause the Video core we need to start the driver*/
2294 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2295 NULL) < */0) {
2296 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2297 omx_report_error ();
2298 eRet = OMX_ErrorHardware;
2299 } else {
2300 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2301 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2302 bFlag = 0;
2303 }
2304 }
2305 /* Requesting transition from Idle to Invalid */
2306 else if (eState == OMX_StateInvalid) {
2307 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2308 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2309 eRet = OMX_ErrorInvalidState;
2310 } else {
2311 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2312 eRet = OMX_ErrorBadParameter;
2313 }
2314 }
2315
2316 /******************************/
2317 /* Current State is Executing */
2318 /******************************/
2319 else if (m_state == OMX_StateExecuting) {
2320 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2321 /* Requesting transition from Executing to Idle */
2322 if (eState == OMX_StateIdle) {
2323 /* Since error is None , we will post an event
2324 at the end of this function definition
2325 */
2326 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2327 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2328 if (!sem_posted) {
2329 sem_posted = 1;
2330 sem_post (&m_cmd_lock);
2331 execute_omx_flush(OMX_ALL);
2332 }
2333 bFlag = 0;
2334 }
2335 /* Requesting transition from Executing to Paused */
2336 else if (eState == OMX_StatePause) {
2337 DEBUG_PRINT_LOW("PAUSE Command Issued");
2338 m_state = OMX_StatePause;
2339 bFlag = 1;
2340 }
2341 /* Requesting transition from Executing to Loaded */
2342 else if (eState == OMX_StateLoaded) {
2343 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2344 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2345 OMX_COMPONENT_GENERATE_EVENT);
2346 eRet = OMX_ErrorIncorrectStateTransition;
2347 }
2348 /* Requesting transition from Executing to WaitForResources */
2349 else if (eState == OMX_StateWaitForResources) {
2350 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2351 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2352 OMX_COMPONENT_GENERATE_EVENT);
2353 eRet = OMX_ErrorIncorrectStateTransition;
2354 }
2355 /* Requesting transition from Executing to Executing */
2356 else if (eState == OMX_StateExecuting) {
2357 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2358 post_event(OMX_EventError,OMX_ErrorSameState,\
2359 OMX_COMPONENT_GENERATE_EVENT);
2360 eRet = OMX_ErrorSameState;
2361 }
2362 /* Requesting transition from Executing to Invalid */
2363 else if (eState == OMX_StateInvalid) {
2364 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2365 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2366 eRet = OMX_ErrorInvalidState;
2367 } else {
2368 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2369 eRet = OMX_ErrorBadParameter;
2370 }
2371 }
2372 /***************************/
2373 /* Current State is Pause */
2374 /***************************/
2375 else if (m_state == OMX_StatePause) {
2376 /* Requesting transition from Pause to Executing */
2377 if (eState == OMX_StateExecuting) {
2378 DEBUG_PRINT_LOW("Pause --> Executing");
2379 m_state = OMX_StateExecuting;
2380 bFlag = 1;
2381 }
2382 /* Requesting transition from Pause to Idle */
2383 else if (eState == OMX_StateIdle) {
2384 /* Since error is None , we will post an event
2385 at the end of this function definition */
2386 DEBUG_PRINT_LOW("Pause --> Idle");
2387 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2388 if (!sem_posted) {
2389 sem_posted = 1;
2390 sem_post (&m_cmd_lock);
2391 execute_omx_flush(OMX_ALL);
2392 }
2393 bFlag = 0;
2394 }
2395 /* Requesting transition from Pause to loaded */
2396 else if (eState == OMX_StateLoaded) {
2397 DEBUG_PRINT_ERROR("Pause --> loaded");
2398 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2399 OMX_COMPONENT_GENERATE_EVENT);
2400 eRet = OMX_ErrorIncorrectStateTransition;
2401 }
2402 /* Requesting transition from Pause to WaitForResources */
2403 else if (eState == OMX_StateWaitForResources) {
2404 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2405 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2406 OMX_COMPONENT_GENERATE_EVENT);
2407 eRet = OMX_ErrorIncorrectStateTransition;
2408 }
2409 /* Requesting transition from Pause to Pause */
2410 else if (eState == OMX_StatePause) {
2411 DEBUG_PRINT_ERROR("Pause --> Pause");
2412 post_event(OMX_EventError,OMX_ErrorSameState,\
2413 OMX_COMPONENT_GENERATE_EVENT);
2414 eRet = OMX_ErrorSameState;
2415 }
2416 /* Requesting transition from Pause to Invalid */
2417 else if (eState == OMX_StateInvalid) {
2418 DEBUG_PRINT_ERROR("Pause --> Invalid");
2419 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2420 eRet = OMX_ErrorInvalidState;
2421 } else {
2422 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2423 eRet = OMX_ErrorBadParameter;
2424 }
2425 }
2426 /***************************/
2427 /* Current State is WaitForResources */
2428 /***************************/
2429 else if (m_state == OMX_StateWaitForResources) {
2430 /* Requesting transition from WaitForResources to Loaded */
2431 if (eState == OMX_StateLoaded) {
2432 /* Since error is None , we will post an event
2433 at the end of this function definition */
2434 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2435 }
2436 /* Requesting transition from WaitForResources to WaitForResources */
2437 else if (eState == OMX_StateWaitForResources) {
2438 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2439 post_event(OMX_EventError,OMX_ErrorSameState,
2440 OMX_COMPONENT_GENERATE_EVENT);
2441 eRet = OMX_ErrorSameState;
2442 }
2443 /* Requesting transition from WaitForResources to Executing */
2444 else if (eState == OMX_StateExecuting) {
2445 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2446 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2447 OMX_COMPONENT_GENERATE_EVENT);
2448 eRet = OMX_ErrorIncorrectStateTransition;
2449 }
2450 /* Requesting transition from WaitForResources to Pause */
2451 else if (eState == OMX_StatePause) {
2452 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2453 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2454 OMX_COMPONENT_GENERATE_EVENT);
2455 eRet = OMX_ErrorIncorrectStateTransition;
2456 }
2457 /* Requesting transition from WaitForResources to Invalid */
2458 else if (eState == OMX_StateInvalid) {
2459 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2460 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2461 eRet = OMX_ErrorInvalidState;
2462 }
2463 /* Requesting transition from WaitForResources to Loaded -
2464 is NOT tested by Khronos TS */
2465
2466 } else {
2467 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2468 eRet = OMX_ErrorBadParameter;
2469 }
2470 }
2471 /********************************/
2472 /* Current State is Invalid */
2473 /*******************************/
2474 else if (m_state == OMX_StateInvalid) {
2475 /* State Transition from Invalid to any state */
2476 if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
2477 eState == OMX_StateIdle || eState == OMX_StateExecuting ||
2478 eState == OMX_StatePause || eState == OMX_StateInvalid) {
2479 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2480 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2481 OMX_COMPONENT_GENERATE_EVENT);
2482 eRet = OMX_ErrorInvalidState;
2483 }
2484 } else if (cmd == OMX_CommandFlush) {
2485 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2486 "with param1: %u", (unsigned int)param1);
2487 #ifdef _MSM8974_
2488 send_codec_config();
2489 #endif
2490 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2491 param1 == OMX_ALL)) {
2492 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2493 struct timespec ts;
2494
2495 clock_gettime(CLOCK_REALTIME, &ts);
2496 ts.tv_sec += 2;
2497 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2498 m_queued_codec_config_count);
2499 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2500 if (sem_timedwait(&m_safe_flush, &ts)) {
2501 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2502 }
2503 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2504 }
2505 }
2506
2507 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2508 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2509 }
2510 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2511 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2512 }
2513 if (!sem_posted) {
2514 sem_posted = 1;
2515 DEBUG_PRINT_LOW("Set the Semaphore");
2516 sem_post (&m_cmd_lock);
2517 execute_omx_flush(param1);
2518 }
2519 bFlag = 0;
2520 } else if ( cmd == OMX_CommandPortEnable) {
2521 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2522 "with param1: %u", (unsigned int)param1);
2523 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2524 m_inp_bEnabled = OMX_TRUE;
2525
2526 if ( (m_state == OMX_StateLoaded &&
2527 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2528 || allocate_input_done()) {
2529 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2530 OMX_COMPONENT_GENERATE_EVENT);
2531 } else {
2532 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2533 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2534 // Skip the event notification
2535 bFlag = 0;
2536 }
2537 }
2538 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2539 DEBUG_PRINT_LOW("Enable output Port command recieved");
2540 m_out_bEnabled = OMX_TRUE;
2541
2542 if ( (m_state == OMX_StateLoaded &&
2543 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2544 || (allocate_output_done())) {
2545 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2546 OMX_COMPONENT_GENERATE_EVENT);
2547
2548 } else {
2549 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2550 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2551 // Skip the event notification
2552 bFlag = 0;
2553 }
2554 }
2555 } else if (cmd == OMX_CommandPortDisable) {
2556 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
2557 "with param1: %u", (unsigned int)param1);
2558 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2559 codec_config_flag = false;
2560 m_inp_bEnabled = OMX_FALSE;
2561 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2562 && release_input_done()) {
2563 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2564 OMX_COMPONENT_GENERATE_EVENT);
2565 } else {
2566 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2567 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2568 if (!sem_posted) {
2569 sem_posted = 1;
2570 sem_post (&m_cmd_lock);
2571 }
2572 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2573 }
2574
2575 // Skip the event notification
2576 bFlag = 0;
2577 }
2578 }
2579 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
2580 m_out_bEnabled = OMX_FALSE;
2581 DEBUG_PRINT_LOW("Disable output Port command recieved");
2582 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2583 && release_output_done()) {
2584 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2585 OMX_COMPONENT_GENERATE_EVENT);
2586 } else {
2587 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2588 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
2589 if (!sem_posted) {
2590 sem_posted = 1;
2591 sem_post (&m_cmd_lock);
2592 }
2593 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2594 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2595 }
2596 // Skip the event notification
2597 bFlag = 0;
2598
2599 }
2600 }
2601 } else {
2602 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
2603 eRet = OMX_ErrorNotImplemented;
2604 }
2605 if (eRet == OMX_ErrorNone && bFlag) {
2606 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2607 }
2608 if (!sem_posted) {
2609 sem_post(&m_cmd_lock);
2610 }
2611
2612 return eRet;
2613 }
2614
2615 /* ======================================================================
2616 FUNCTION
2617 omx_vdec::ExecuteOmxFlush
2618
2619 DESCRIPTION
2620 Executes the OMX flush.
2621
2622 PARAMETERS
2623 flushtype - input flush(1)/output flush(0)/ both.
2624
2625 RETURN VALUE
2626 true/false
2627
2628 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)2629 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
2630 {
2631 bool bRet = false;
2632 struct v4l2_plane plane;
2633 struct v4l2_buffer v4l2_buf;
2634 struct v4l2_decoder_cmd dec;
2635 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
2636 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
2637 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
2638
2639 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
2640
2641 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
2642 output_flush_progress = true;
2643 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2644 } else {
2645 /* XXX: The driver/hardware does not support flushing of individual ports
2646 * in all states. So we pretty much need to flush both ports internally,
2647 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
2648 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
2649 * we automatically omit sending the FLUSH done for the "opposite" port. */
2650 input_flush_progress = true;
2651 output_flush_progress = true;
2652 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
2653 }
2654
2655 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
2656 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
2657 bRet = false;
2658 }
2659
2660 return bRet;
2661 }
2662 /*=========================================================================
2663 FUNCTION : execute_output_flush
2664
2665 DESCRIPTION
2666 Executes the OMX flush at OUTPUT PORT.
2667
2668 PARAMETERS
2669 None.
2670
2671 RETURN VALUE
2672 true/false
2673 ==========================================================================*/
execute_output_flush()2674 bool omx_vdec::execute_output_flush()
2675 {
2676 unsigned long p1 = 0; // Parameter - 1
2677 unsigned long p2 = 0; // Parameter - 2
2678 unsigned long ident = 0;
2679 bool bRet = true;
2680
2681 /*Generate FBD for all Buffers in the FTBq*/
2682 pthread_mutex_lock(&m_lock);
2683 DEBUG_PRINT_LOW("Initiate Output Flush");
2684
2685 //reset last render TS
2686 if(m_last_rendered_TS > 0) {
2687 m_last_rendered_TS = 0;
2688 }
2689
2690 while (m_ftb_q.m_size) {
2691 DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
2692 m_ftb_q.m_size,pending_output_buffers);
2693 m_ftb_q.pop_entry(&p1,&p2,&ident);
2694 DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
2695 if (ident == m_fill_output_msg ) {
2696 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
2697 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
2698 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
2699 }
2700 }
2701 pthread_mutex_unlock(&m_lock);
2702 output_flush_progress = false;
2703
2704 if (arbitrary_bytes) {
2705 prev_ts = LLONG_MAX;
2706 rst_prev_ts = true;
2707 }
2708 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
2709 return bRet;
2710 }
2711 /*=========================================================================
2712 FUNCTION : execute_input_flush
2713
2714 DESCRIPTION
2715 Executes the OMX flush at INPUT PORT.
2716
2717 PARAMETERS
2718 None.
2719
2720 RETURN VALUE
2721 true/false
2722 ==========================================================================*/
execute_input_flush()2723 bool omx_vdec::execute_input_flush()
2724 {
2725 unsigned i =0;
2726 unsigned long p1 = 0; // Parameter - 1
2727 unsigned long p2 = 0; // Parameter - 2
2728 unsigned long ident = 0;
2729 bool bRet = true;
2730
2731 /*Generate EBD for all Buffers in the ETBq*/
2732 DEBUG_PRINT_LOW("Initiate Input Flush");
2733
2734 pthread_mutex_lock(&m_lock);
2735 DEBUG_PRINT_LOW("Check if the Queue is empty");
2736 while (m_etb_q.m_size) {
2737 m_etb_q.pop_entry(&p1,&p2,&ident);
2738
2739 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2740 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
2741 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2742 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
2743 pending_input_buffers++;
2744 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
2745 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
2746 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2747 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
2748 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
2749 (OMX_BUFFERHEADERTYPE *)p1);
2750 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2751 }
2752 }
2753 time_stamp_dts.flush_timestamp();
2754 /*Check if Heap Buffers are to be flushed*/
2755 if (arbitrary_bytes && !(codec_config_flag)) {
2756 DEBUG_PRINT_LOW("Reset all the variables before flusing");
2757 h264_scratch.nFilledLen = 0;
2758 nal_count = 0;
2759 look_ahead_nal = false;
2760 frame_count = 0;
2761 h264_last_au_ts = LLONG_MAX;
2762 h264_last_au_flags = 0;
2763 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
2764 m_demux_entries = 0;
2765 DEBUG_PRINT_LOW("Initialize parser");
2766 if (m_frame_parser.mutils) {
2767 m_frame_parser.mutils->initialize_frame_checking_environment();
2768 }
2769
2770 while (m_input_pending_q.m_size) {
2771 m_input_pending_q.pop_entry(&p1,&p2,&ident);
2772 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
2773 }
2774
2775 if (psource_frame) {
2776 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
2777 psource_frame = NULL;
2778 }
2779
2780 if (pdest_frame) {
2781 pdest_frame->nFilledLen = 0;
2782 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
2783 (unsigned int)NULL);
2784 pdest_frame = NULL;
2785 }
2786 m_frame_parser.flush();
2787 } else if (codec_config_flag) {
2788 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
2789 "is not sent to the driver yet");
2790 }
2791 pthread_mutex_unlock(&m_lock);
2792 input_flush_progress = false;
2793 if (!arbitrary_bytes) {
2794 prev_ts = LLONG_MAX;
2795 rst_prev_ts = true;
2796 }
2797 #ifdef _ANDROID_
2798 if (m_debug_timestamp) {
2799 m_timestamp_list.reset_ts_list();
2800 }
2801 #endif
2802 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
2803 return bRet;
2804 }
2805
2806
2807 /* ======================================================================
2808 FUNCTION
2809 omx_vdec::SendCommandEvent
2810
2811 DESCRIPTION
2812 Send the event to decoder pipe. This is needed to generate the callbacks
2813 in decoder thread context.
2814
2815 PARAMETERS
2816 None.
2817
2818 RETURN VALUE
2819 true/false
2820
2821 ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)2822 bool omx_vdec::post_event(unsigned long p1,
2823 unsigned long p2,
2824 unsigned long id)
2825 {
2826 bool bRet = false;
2827
2828 /* Just drop messages typically generated by hardware (w/o client request),
2829 * if we've reported an error to client. */
2830 if (m_error_propogated) {
2831 switch (id) {
2832 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
2833 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
2834 DEBUG_PRINT_ERROR("Dropping message %lx "
2835 "since client expected to be in error state", id);
2836 return false;
2837 default:
2838 /* whatever */
2839 break;
2840 }
2841 }
2842
2843 pthread_mutex_lock(&m_lock);
2844
2845 if (id == m_fill_output_msg ||
2846 id == OMX_COMPONENT_GENERATE_FBD ||
2847 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG) {
2848 m_ftb_q.insert_entry(p1,p2,id);
2849 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
2850 id == OMX_COMPONENT_GENERATE_EBD ||
2851 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
2852 m_etb_q.insert_entry(p1,p2,id);
2853 } else {
2854 m_cmd_q.insert_entry(p1,p2,id);
2855 }
2856
2857 bRet = true;
2858 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
2859 post_message(this, id);
2860
2861 pthread_mutex_unlock(&m_lock);
2862
2863 return bRet;
2864 }
2865
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)2866 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
2867 {
2868 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2869 if (!profileLevelType)
2870 return OMX_ErrorBadParameter;
2871
2872 if (profileLevelType->nPortIndex == 0) {
2873 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
2874 if (profileLevelType->nProfileIndex == 0) {
2875 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
2876 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
2877
2878 } else if (profileLevelType->nProfileIndex == 1) {
2879 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
2880 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
2881 } else if (profileLevelType->nProfileIndex == 2) {
2882 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
2883 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
2884 } else {
2885 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2886 (unsigned int)profileLevelType->nProfileIndex);
2887 eRet = OMX_ErrorNoMore;
2888 }
2889 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2890 if (profileLevelType->nProfileIndex == 0) {
2891 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
2892 profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51;
2893 } else {
2894 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2895 (unsigned int)profileLevelType->nProfileIndex);
2896 eRet = OMX_ErrorNoMore;
2897 }
2898 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2899 if (profileLevelType->nProfileIndex == 0) {
2900 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
2901 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
2902 } else {
2903 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2904 (unsigned int)profileLevelType->nProfileIndex);
2905 eRet = OMX_ErrorNoMore;
2906 }
2907 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
2908 if (profileLevelType->nProfileIndex == 0) {
2909 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
2910 profileLevelType->eLevel = OMX_VIDEO_H263Level70;
2911 } else {
2912 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2913 (unsigned int)profileLevelType->nProfileIndex);
2914 eRet = OMX_ErrorNoMore;
2915 }
2916 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
2917 if (profileLevelType->nProfileIndex == 0) {
2918 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2919 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2920 } else if (profileLevelType->nProfileIndex == 1) {
2921 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2922 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2923 } else {
2924 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2925 (unsigned int)profileLevelType->nProfileIndex);
2926 eRet = OMX_ErrorNoMore;
2927 }
2928 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
2929 eRet = OMX_ErrorNoMore;
2930 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
2931 if (profileLevelType->nProfileIndex == 0) {
2932 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
2933 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2934 } else if (profileLevelType->nProfileIndex == 1) {
2935 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
2936 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2937 } else {
2938 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
2939 (unsigned int)profileLevelType->nProfileIndex);
2940 eRet = OMX_ErrorNoMore;
2941 }
2942 } else {
2943 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
2944 eRet = OMX_ErrorNoMore;
2945 }
2946 } else {
2947 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
2948 (unsigned int)profileLevelType->nPortIndex);
2949 eRet = OMX_ErrorBadPortIndex;
2950 }
2951 return eRet;
2952 }
2953
2954 /* ======================================================================
2955 FUNCTION
2956 omx_vdec::GetParameter
2957
2958 DESCRIPTION
2959 OMX Get Parameter method implementation
2960
2961 PARAMETERS
2962 <TBD>.
2963
2964 RETURN VALUE
2965 Error None if successful.
2966
2967 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)2968 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
2969 OMX_IN OMX_INDEXTYPE paramIndex,
2970 OMX_INOUT OMX_PTR paramData)
2971 {
2972 (void) hComp;
2973 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2974
2975 DEBUG_PRINT_LOW("get_parameter:");
2976 if (m_state == OMX_StateInvalid) {
2977 DEBUG_PRINT_ERROR("Get Param in Invalid State");
2978 return OMX_ErrorInvalidState;
2979 }
2980 if (paramData == NULL) {
2981 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
2982 return OMX_ErrorBadParameter;
2983 }
2984 switch ((unsigned long)paramIndex) {
2985 case OMX_IndexParamPortDefinition: {
2986 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
2987 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
2988 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2989 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
2990 eRet = update_portdef(portDefn);
2991 if (eRet == OMX_ErrorNone)
2992 m_port_def = *portDefn;
2993 break;
2994 }
2995 case OMX_IndexParamVideoInit: {
2996 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
2997 OMX_PORT_PARAM_TYPE *portParamType =
2998 (OMX_PORT_PARAM_TYPE *) paramData;
2999 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3000
3001 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3002 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3003 portParamType->nPorts = 2;
3004 portParamType->nStartPortNumber = 0;
3005 break;
3006 }
3007 case OMX_IndexParamVideoPortFormat: {
3008 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3009 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3010 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3011 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3012
3013 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3014 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3015
3016 if (0 == portFmt->nPortIndex) {
3017 if (0 == portFmt->nIndex) {
3018 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
3019 portFmt->eCompressionFormat = eCompressionFormat;
3020 } else {
3021 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3022 " NoMore compression formats");
3023 eRet = OMX_ErrorNoMore;
3024 }
3025 } else if (1 == portFmt->nPortIndex) {
3026 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
3027
3028 // Distinguish non-surface mode from normal playback use-case based on
3029 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3030 // For non-android, use the default list
3031 // Also use default format-list if FLEXIBLE YUV is supported,
3032 // as the client negotiates the standard color-format if it needs to
3033 bool useNonSurfaceMode = false;
3034 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3035 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3036 #endif
3037 portFmt->eColorFormat = useNonSurfaceMode ?
3038 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3039 getPreferredColorFormatDefaultMode(portFmt->nIndex);
3040
3041 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3042 eRet = OMX_ErrorNoMore;
3043 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3044 " NoMore Color formats");
3045 }
3046 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3047 } else {
3048 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3049 (int)portFmt->nPortIndex);
3050 eRet = OMX_ErrorBadPortIndex;
3051 }
3052 break;
3053 }
3054 /*Component should support this port definition*/
3055 case OMX_IndexParamAudioInit: {
3056 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3057 OMX_PORT_PARAM_TYPE *audioPortParamType =
3058 (OMX_PORT_PARAM_TYPE *) paramData;
3059 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3060 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3061 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3062 audioPortParamType->nPorts = 0;
3063 audioPortParamType->nStartPortNumber = 0;
3064 break;
3065 }
3066 /*Component should support this port definition*/
3067 case OMX_IndexParamImageInit: {
3068 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3069 OMX_PORT_PARAM_TYPE *imagePortParamType =
3070 (OMX_PORT_PARAM_TYPE *) paramData;
3071 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3072 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3073 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3074 imagePortParamType->nPorts = 0;
3075 imagePortParamType->nStartPortNumber = 0;
3076 break;
3077
3078 }
3079 /*Component should support this port definition*/
3080 case OMX_IndexParamOtherInit: {
3081 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3082 paramIndex);
3083 eRet =OMX_ErrorUnsupportedIndex;
3084 break;
3085 }
3086 case OMX_IndexParamStandardComponentRole: {
3087 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3088 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3089 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3090 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3091 comp_role->nSize = sizeof(*comp_role);
3092
3093 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3094 paramIndex);
3095 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3096 OMX_MAX_STRINGNAME_SIZE);
3097 break;
3098 }
3099 /* Added for parameter test */
3100 case OMX_IndexParamPriorityMgmt: {
3101 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3102 OMX_PRIORITYMGMTTYPE *priorityMgmType =
3103 (OMX_PRIORITYMGMTTYPE *) paramData;
3104 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3105 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3106 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3107
3108 break;
3109 }
3110 /* Added for parameter test */
3111 case OMX_IndexParamCompBufferSupplier: {
3112 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3113 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3114 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3115 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3116
3117 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3118 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3119 if (0 == bufferSupplierType->nPortIndex)
3120 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3121 else if (1 == bufferSupplierType->nPortIndex)
3122 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3123 else
3124 eRet = OMX_ErrorBadPortIndex;
3125
3126
3127 break;
3128 }
3129 case OMX_IndexParamVideoAvc: {
3130 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3131 paramIndex);
3132 break;
3133 }
3134 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3135 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3136 paramIndex);
3137 break;
3138 }
3139 case OMX_IndexParamVideoH263: {
3140 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3141 paramIndex);
3142 break;
3143 }
3144 case OMX_IndexParamVideoMpeg4: {
3145 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3146 paramIndex);
3147 break;
3148 }
3149 case OMX_IndexParamVideoMpeg2: {
3150 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3151 paramIndex);
3152 break;
3153 }
3154 case OMX_IndexParamVideoProfileLevelQuerySupported: {
3155 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3156 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3157 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3158 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3159 eRet = get_supported_profile_level(profileLevelType);
3160 break;
3161 }
3162 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3163 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3164 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3165 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3166 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3167 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3168
3169 if (secure_mode && !secure_scaling_to_non_secure_opb) {
3170 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3171 GRALLOC_USAGE_PRIVATE_UNCACHED);
3172 } else {
3173 nativeBuffersUsage->nUsage =
3174 (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
3175 GRALLOC_USAGE_PRIVATE_UNCACHED);
3176 }
3177 } else {
3178 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3179 eRet = OMX_ErrorBadParameter;
3180 }
3181 }
3182 break;
3183 #endif
3184
3185 #ifdef FLEXYUV_SUPPORTED
3186 case OMX_QcomIndexFlexibleYUVDescription: {
3187 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3188 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3189 eRet = describeColorFormat(paramData);
3190 break;
3191 }
3192 #endif
3193
3194 default: {
3195 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3196 eRet =OMX_ErrorUnsupportedIndex;
3197 }
3198
3199 }
3200
3201 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3202 drv_ctx.video_resolution.frame_width,
3203 drv_ctx.video_resolution.frame_height,
3204 drv_ctx.video_resolution.stride,
3205 drv_ctx.video_resolution.scan_lines);
3206
3207 return eRet;
3208 }
3209
3210 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3211 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3212 {
3213 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3214 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3215 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3216
3217 if ((params == NULL) ||
3218 (params->nativeBuffer == NULL) ||
3219 (params->nativeBuffer->handle == NULL) ||
3220 !m_enable_android_native_buffers)
3221 return OMX_ErrorBadParameter;
3222 m_use_android_native_buffers = OMX_TRUE;
3223 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3224 private_handle_t *handle = (private_handle_t *)nBuf->handle;
3225 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3226 OMX_U8 *buffer = NULL;
3227 if (!secure_mode) {
3228 buffer = (OMX_U8*)mmap(0, handle->size,
3229 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3230 if (buffer == MAP_FAILED) {
3231 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3232 return OMX_ErrorInsufficientResources;
3233 }
3234 }
3235 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3236 } else {
3237 eRet = OMX_ErrorBadParameter;
3238 }
3239 return eRet;
3240 }
3241 #endif
3242
enable_smoothstreaming()3243 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3244 struct v4l2_control control;
3245 struct v4l2_format fmt;
3246 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3247 control.value = 1;
3248 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3249 if (rc < 0) {
3250 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3251 return OMX_ErrorHardware;
3252 }
3253 m_smoothstreaming_mode = true;
3254 return OMX_ErrorNone;
3255 }
3256
3257 /* ======================================================================
3258 FUNCTION
3259 omx_vdec::Setparameter
3260
3261 DESCRIPTION
3262 OMX Set Parameter method implementation.
3263
3264 PARAMETERS
3265 <TBD>.
3266
3267 RETURN VALUE
3268 OMX Error None if successful.
3269
3270 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3271 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
3272 OMX_IN OMX_INDEXTYPE paramIndex,
3273 OMX_IN OMX_PTR paramData)
3274 {
3275 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3276 int ret=0;
3277 struct v4l2_format fmt;
3278 #ifdef _ANDROID_
3279 char property_value[PROPERTY_VALUE_MAX] = {0};
3280 #endif
3281 if (m_state == OMX_StateInvalid) {
3282 DEBUG_PRINT_ERROR("Set Param in Invalid State");
3283 return OMX_ErrorInvalidState;
3284 }
3285 if (paramData == NULL) {
3286 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
3287 return OMX_ErrorBadParameter;
3288 }
3289 if ((m_state != OMX_StateLoaded) &&
3290 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
3291 (m_out_bEnabled == OMX_TRUE) &&
3292 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
3293 (m_inp_bEnabled == OMX_TRUE)) {
3294 DEBUG_PRINT_ERROR("Set Param in Invalid State");
3295 return OMX_ErrorIncorrectStateOperation;
3296 }
3297 switch ((unsigned long)paramIndex) {
3298 case OMX_IndexParamPortDefinition: {
3299 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3300 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3301 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3302 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
3303 //been called.
3304 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
3305 (int)portDefn->format.video.nFrameHeight,
3306 (int)portDefn->format.video.nFrameWidth);
3307
3308 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3309 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
3310 portDefn->nBufferCountActual);
3311 eRet = OMX_ErrorBadParameter;
3312 break;
3313 }
3314 if (OMX_DirOutput == portDefn->eDir) {
3315 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
3316 bool port_format_changed = false;
3317 m_display_id = portDefn->format.video.pNativeWindow;
3318 unsigned int buffer_size;
3319 /* update output port resolution with client supplied dimensions
3320 in case scaling is enabled, else it follows input resolution set
3321 */
3322 if (is_down_scalar_enabled) {
3323 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
3324 (unsigned int)portDefn->format.video.nFrameWidth,
3325 (unsigned int)portDefn->format.video.nFrameHeight);
3326 if (portDefn->format.video.nFrameHeight != 0x0 &&
3327 portDefn->format.video.nFrameWidth != 0x0) {
3328 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3329 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3330 fmt.fmt.pix_mp.pixelformat = capture_capability;
3331 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
3332 if (ret) {
3333 DEBUG_PRINT_ERROR("Get Resolution failed");
3334 eRet = OMX_ErrorHardware;
3335 break;
3336 }
3337 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
3338 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
3339 port_format_changed = true;
3340 }
3341 update_resolution(portDefn->format.video.nFrameWidth,
3342 portDefn->format.video.nFrameHeight,
3343 portDefn->format.video.nFrameWidth,
3344 portDefn->format.video.nFrameHeight);
3345
3346 /* set crop info */
3347 rectangle.nLeft = 0;
3348 rectangle.nTop = 0;
3349 rectangle.nWidth = portDefn->format.video.nFrameWidth;
3350 rectangle.nHeight = portDefn->format.video.nFrameHeight;
3351
3352 eRet = is_video_session_supported();
3353 if (eRet)
3354 break;
3355 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3356 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3357 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3358 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3359 fmt.fmt.pix_mp.pixelformat = capture_capability;
3360 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
3361 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
3362 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3363 if (ret) {
3364 DEBUG_PRINT_ERROR("Set Resolution failed");
3365 eRet = OMX_ErrorUnsupportedSetting;
3366 } else
3367 eRet = get_buffer_req(&drv_ctx.op_buf);
3368 }
3369
3370 if (eRet) {
3371 break;
3372 }
3373
3374 if (secure_mode) {
3375 struct v4l2_control control;
3376 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
3377 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
3378 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
3379 eRet = OMX_ErrorHardware;
3380 } else {
3381 /* This is a workaround for a bug in fw which uses stride
3382 * and slice instead of width and height to check against
3383 * the threshold.
3384 */
3385 OMX_U32 stride, slice;
3386 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
3387 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
3388 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
3389 } else {
3390 stride = portDefn->format.video.nFrameWidth;
3391 slice = portDefn->format.video.nFrameHeight;
3392 }
3393
3394 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
3395 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
3396
3397 if (stride * slice <= (OMX_U32)control.value) {
3398 secure_scaling_to_non_secure_opb = true;
3399 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
3400 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
3401 control.value = 1;
3402 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
3403 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
3404 eRet = OMX_ErrorUnsupportedSetting;
3405 }
3406 }
3407 }
3408 }
3409 }
3410
3411 if (eRet) {
3412 break;
3413 }
3414
3415 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3416 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
3417 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
3418 eRet = OMX_ErrorBadParameter;
3419 } else if (!client_buffers.get_buffer_req(buffer_size)) {
3420 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
3421 eRet = OMX_ErrorBadParameter;
3422 } else if (!port_format_changed) {
3423
3424 // Buffer count can change only when port is unallocated
3425 if (m_out_mem_ptr &&
3426 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
3427 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
3428
3429 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
3430 eRet = OMX_ErrorInvalidState;
3431 break;
3432 }
3433
3434 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
3435 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) {
3436 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
3437 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
3438 drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount;
3439 drv_ctx.extradata_info.size = drv_ctx.extradata_info.count *
3440 drv_ctx.extradata_info.buffer_size;
3441 eRet = set_buffer_req(&drv_ctx.op_buf);
3442 if (eRet == OMX_ErrorNone)
3443 m_port_def = *portDefn;
3444 } else {
3445 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
3446 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size,
3447 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
3448 eRet = OMX_ErrorBadParameter;
3449 }
3450 }
3451 } else if (OMX_DirInput == portDefn->eDir) {
3452 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
3453 bool port_format_changed = false;
3454 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
3455 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
3456 // Frame rate only should be set if this is a "known value" or to
3457 // activate ts prediction logic (arbitrary mode only) sending input
3458 // timestamps with max value (LLONG_MAX).
3459 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
3460 (unsigned int)portDefn->format.video.xFramerate >> 16);
3461 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
3462 drv_ctx.frame_rate.fps_denominator);
3463 if (!drv_ctx.frame_rate.fps_numerator) {
3464 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
3465 drv_ctx.frame_rate.fps_numerator = 30;
3466 }
3467 if (drv_ctx.frame_rate.fps_denominator)
3468 drv_ctx.frame_rate.fps_numerator = (int)
3469 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
3470 drv_ctx.frame_rate.fps_denominator = 1;
3471 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
3472 drv_ctx.frame_rate.fps_numerator;
3473 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
3474 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
3475 (float)drv_ctx.frame_rate.fps_denominator);
3476
3477 struct v4l2_outputparm oparm;
3478 /*XXX: we're providing timing info as seconds per frame rather than frames
3479 * per second.*/
3480 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
3481 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
3482
3483 struct v4l2_streamparm sparm;
3484 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3485 sparm.parm.output = oparm;
3486 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
3487 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
3488 eRet = OMX_ErrorHardware;
3489 break;
3490 }
3491 //m_perf_control.request_cores(frm_int);
3492 }
3493
3494 if (drv_ctx.video_resolution.frame_height !=
3495 portDefn->format.video.nFrameHeight ||
3496 drv_ctx.video_resolution.frame_width !=
3497 portDefn->format.video.nFrameWidth) {
3498 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
3499 (unsigned int)portDefn->format.video.nFrameWidth,
3500 (unsigned int)portDefn->format.video.nFrameHeight);
3501 port_format_changed = true;
3502 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
3503 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
3504 if (frameHeight != 0x0 && frameWidth != 0x0) {
3505 if (m_smoothstreaming_mode &&
3506 ((frameWidth * frameHeight) <
3507 (m_smoothstreaming_width * m_smoothstreaming_height))) {
3508 frameWidth = m_smoothstreaming_width;
3509 frameHeight = m_smoothstreaming_height;
3510 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
3511 "for adaptive-playback/smooth-streaming",
3512 (unsigned int)frameWidth, (unsigned int)frameHeight);
3513 }
3514 update_resolution(frameWidth, frameHeight,
3515 frameWidth, frameHeight);
3516 eRet = is_video_session_supported();
3517 if (eRet)
3518 break;
3519 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3520 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3521 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3522 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3523 fmt.fmt.pix_mp.pixelformat = output_capability;
3524 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);
3525 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3526 if (ret) {
3527 DEBUG_PRINT_ERROR("Set Resolution failed");
3528 eRet = OMX_ErrorUnsupportedSetting;
3529 } else {
3530 if (!is_down_scalar_enabled)
3531 eRet = get_buffer_req(&drv_ctx.op_buf);
3532 }
3533 }
3534 }
3535 if (m_custom_buffersize.input_buffersize
3536 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
3537 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
3538 m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
3539 eRet = OMX_ErrorBadParameter;
3540 break;
3541 }
3542 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3543 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
3544 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
3545 eRet = OMX_ErrorBadParameter;
3546 break;
3547 }
3548 // Buffer count can change only when port is unallocated
3549 if (m_inp_mem_ptr &&
3550 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
3551 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
3552 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
3553 eRet = OMX_ErrorInvalidState;
3554 break;
3555 }
3556
3557 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
3558 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
3559 port_format_changed = true;
3560 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
3561 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
3562 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
3563 (~(buffer_prop->alignment - 1));
3564 eRet = set_buffer_req(buffer_prop);
3565 }
3566 if (false == port_format_changed) {
3567 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
3568 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
3569 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
3570 eRet = OMX_ErrorBadParameter;
3571 }
3572 } else if (portDefn->eDir == OMX_DirMax) {
3573 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
3574 (int)portDefn->nPortIndex);
3575 eRet = OMX_ErrorBadPortIndex;
3576 }
3577 }
3578 break;
3579 case OMX_IndexParamVideoPortFormat: {
3580 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3581 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3582 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3583 int ret=0;
3584 struct v4l2_format fmt;
3585 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
3586 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
3587
3588 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3589 if (1 == portFmt->nPortIndex) {
3590 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3591 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3592 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3593 fmt.fmt.pix_mp.pixelformat = capture_capability;
3594 enum vdec_output_fromat op_format;
3595 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
3596 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
3597 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
3598 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
3599 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
3600 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
3601 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
3602 else
3603 eRet = OMX_ErrorBadParameter;
3604
3605 if (eRet == OMX_ErrorNone) {
3606 drv_ctx.output_format = op_format;
3607 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3608 if (ret) {
3609 DEBUG_PRINT_ERROR("Set output format failed");
3610 eRet = OMX_ErrorUnsupportedSetting;
3611 /*TODO: How to handle this case */
3612 } else {
3613 eRet = get_buffer_req(&drv_ctx.op_buf);
3614 }
3615 }
3616 if (eRet == OMX_ErrorNone) {
3617 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
3618 DEBUG_PRINT_ERROR("Set color format failed");
3619 eRet = OMX_ErrorBadParameter;
3620 }
3621 }
3622 }
3623 }
3624 break;
3625
3626 case OMX_QcomIndexPortDefn: {
3627 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
3628 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
3629 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
3630 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
3631 (unsigned int)portFmt->nFramePackingFormat);
3632
3633 /* Input port */
3634 if (portFmt->nPortIndex == 0) {
3635 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
3636 // - headers are allocated and
3637 // - headers-indices are derived
3638 // Avoid changing arbitrary_bytes when the port is already allocated
3639 if (m_inp_mem_ptr) {
3640 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
3641 return OMX_ErrorUnsupportedSetting;
3642 }
3643 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
3644 if (secure_mode) {
3645 arbitrary_bytes = false;
3646 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session");
3647 eRet = OMX_ErrorUnsupportedSetting;
3648 } else {
3649 arbitrary_bytes = true;
3650 }
3651 } else if (portFmt->nFramePackingFormat ==
3652 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
3653 arbitrary_bytes = false;
3654 #ifdef _ANDROID_
3655 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
3656 if (atoi(property_value)) {
3657 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
3658 arbitrary_bytes = true;
3659 }
3660 #endif
3661 } else {
3662 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
3663 (unsigned int)portFmt->nFramePackingFormat);
3664 eRet = OMX_ErrorUnsupportedSetting;
3665 }
3666 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3667 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
3668 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
3669 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
3670 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
3671 m_out_mem_region_smi = OMX_TRUE;
3672 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
3673 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
3674 m_use_output_pmem = OMX_TRUE;
3675 }
3676 }
3677 }
3678 }
3679 break;
3680
3681 case OMX_IndexParamStandardComponentRole: {
3682 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3683 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3684 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3685 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
3686 comp_role->cRole);
3687
3688 if ((m_state == OMX_StateLoaded)&&
3689 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
3690 DEBUG_PRINT_LOW("Set Parameter called in valid state");
3691 } else {
3692 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
3693 return OMX_ErrorIncorrectStateOperation;
3694 }
3695
3696 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3697 if (!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3698 strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
3699 } else {
3700 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3701 eRet =OMX_ErrorUnsupportedSetting;
3702 }
3703 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3704 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3705 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
3706 } else {
3707 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3708 eRet =OMX_ErrorUnsupportedSetting;
3709 }
3710 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3711 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3712 strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
3713 } else {
3714 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3715 eRet = OMX_ErrorUnsupportedSetting;
3716 }
3717 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
3718 if (!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
3719 strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
3720 } else {
3721 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3722 eRet =OMX_ErrorUnsupportedSetting;
3723 }
3724 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3725 if (!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3726 strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
3727 } else {
3728 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3729 eRet = OMX_ErrorUnsupportedSetting;
3730 }
3731 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
3732 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
3733 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
3734 ) {
3735 if (!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) {
3736 strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
3737 } else {
3738 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3739 eRet =OMX_ErrorUnsupportedSetting;
3740 }
3741 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
3742 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
3743 ) {
3744 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) {
3745 strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
3746 } else {
3747 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3748 eRet =OMX_ErrorUnsupportedSetting;
3749 }
3750 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
3751 if (!strncmp((const char*)comp_role->cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3752 (!strncmp((const char*)comp_role->cRole,"video_decoder.vpx",OMX_MAX_STRINGNAME_SIZE))) {
3753 strlcpy((char*)m_cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
3754 } else {
3755 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3756 eRet = OMX_ErrorUnsupportedSetting;
3757 }
3758 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3759 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3760 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
3761 } else {
3762 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
3763 eRet = OMX_ErrorUnsupportedSetting;
3764 }
3765 } else {
3766 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
3767 eRet = OMX_ErrorInvalidComponentName;
3768 }
3769 break;
3770 }
3771
3772 case OMX_IndexParamPriorityMgmt: {
3773 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3774 if (m_state != OMX_StateLoaded) {
3775 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
3776 return OMX_ErrorIncorrectStateOperation;
3777 }
3778 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
3779 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
3780 (unsigned int)priorityMgmtype->nGroupID);
3781
3782 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
3783 (unsigned int)priorityMgmtype->nGroupPriority);
3784
3785 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
3786 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
3787
3788 break;
3789 }
3790
3791 case OMX_IndexParamCompBufferSupplier: {
3792 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3793 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3794 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
3795 bufferSupplierType->eBufferSupplier);
3796 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
3797 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
3798
3799 else
3800
3801 eRet = OMX_ErrorBadPortIndex;
3802
3803 break;
3804
3805 }
3806 case OMX_IndexParamVideoAvc: {
3807 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
3808 paramIndex);
3809 break;
3810 }
3811 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3812 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
3813 paramIndex);
3814 break;
3815 }
3816 case OMX_IndexParamVideoH263: {
3817 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
3818 paramIndex);
3819 break;
3820 }
3821 case OMX_IndexParamVideoMpeg4: {
3822 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
3823 paramIndex);
3824 break;
3825 }
3826 case OMX_IndexParamVideoMpeg2: {
3827 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
3828 paramIndex);
3829 break;
3830 }
3831 case OMX_QcomIndexParamVideoDecoderPictureOrder: {
3832 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
3833 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
3834 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
3835 struct v4l2_control control;
3836 int pic_order,rc=0;
3837 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
3838 pictureOrder->eOutputPictureOrder);
3839 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
3840 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
3841 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
3842 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3843 time_stamp_dts.set_timestamp_reorder_mode(false);
3844 } else
3845 eRet = OMX_ErrorBadParameter;
3846 if (eRet == OMX_ErrorNone) {
3847 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3848 control.value = pic_order;
3849 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3850 if (rc) {
3851 DEBUG_PRINT_ERROR("Set picture order failed");
3852 eRet = OMX_ErrorUnsupportedSetting;
3853 }
3854 }
3855 break;
3856 }
3857 case OMX_QcomIndexParamConcealMBMapExtraData:
3858 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3859 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
3860 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3861 break;
3862 case OMX_QcomIndexParamFrameInfoExtraData:
3863 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3864 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
3865 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3866 break;
3867 case OMX_ExtraDataFrameDimension:
3868 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3869 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
3870 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3871 break;
3872 case OMX_QcomIndexParamInterlaceExtraData:
3873 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3874 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
3875 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3876 break;
3877 case OMX_QcomIndexParamH264TimeInfo:
3878 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3879 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
3880 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3881 break;
3882 case OMX_QcomIndexParamVideoFramePackingExtradata:
3883 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3884 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
3885 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3886 break;
3887 case OMX_QcomIndexParamVideoQPExtraData:
3888 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3889 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
3890 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3891 break;
3892 case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
3893 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3894 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
3895 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3896 break;
3897 case OMX_QcomIndexEnableExtnUserData:
3898 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3899 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
3900 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3901 break;
3902 case OMX_QcomIndexParamMpeg2SeqDispExtraData:
3903 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
3904 eRet = enable_extradata(OMX_MPEG2SEQDISP_EXTRADATA, false,
3905 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3906 break;
3907 case OMX_QcomIndexParamVideoDivx: {
3908 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
3909 }
3910 break;
3911 case OMX_QcomIndexPlatformPvt: {
3912 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
3913 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
3914 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
3915 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3916 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
3917 eRet = OMX_ErrorUnsupportedSetting;
3918 } else {
3919 m_out_pvt_entry_pmem = OMX_TRUE;
3920 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
3921 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
3922 m_use_output_pmem = OMX_TRUE;
3923 }
3924 }
3925
3926 }
3927 break;
3928 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
3929 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
3930 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
3931 struct v4l2_control control;
3932 int rc;
3933 drv_ctx.idr_only_decoding = 1;
3934 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
3935 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
3936 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3937 if (rc) {
3938 DEBUG_PRINT_ERROR("Set picture order failed");
3939 eRet = OMX_ErrorUnsupportedSetting;
3940 } else {
3941 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
3942 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
3943 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
3944 if (rc) {
3945 DEBUG_PRINT_ERROR("Sync frame setting failed");
3946 eRet = OMX_ErrorUnsupportedSetting;
3947 }
3948 /*Setting sync frame decoding on driver might change buffer
3949 * requirements so update them here*/
3950 if (get_buffer_req(&drv_ctx.ip_buf)) {
3951 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
3952 eRet = OMX_ErrorUnsupportedSetting;
3953 }
3954 if (get_buffer_req(&drv_ctx.op_buf)) {
3955 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
3956 eRet = OMX_ErrorUnsupportedSetting;
3957 }
3958 }
3959 }
3960 break;
3961
3962 case OMX_QcomIndexParamIndexExtraDataType: {
3963 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
3964 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
3965 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
3966 (extradataIndexType->bEnabled == OMX_TRUE) &&
3967 (extradataIndexType->nPortIndex == 1)) {
3968 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
3969 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
3970
3971 }
3972 }
3973 break;
3974 case OMX_QcomIndexParamEnableSmoothStreaming: {
3975 #ifndef SMOOTH_STREAMING_DISABLED
3976 eRet = enable_smoothstreaming();
3977 #else
3978 eRet = OMX_ErrorUnsupportedSetting;
3979 #endif
3980 }
3981 break;
3982 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3983 /* Need to allow following two set_parameters even in Idle
3984 * state. This is ANDROID architecture which is not in sync
3985 * with openmax standard. */
3986 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
3987 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
3988 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
3989 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
3990 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
3991 eRet = OMX_ErrorUnsupportedSetting;
3992 break;
3993 } else if (m_out_mem_ptr) {
3994 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
3995 eRet = OMX_ErrorInvalidState;
3996 break;
3997 }
3998 if (enableNativeBuffers) {
3999 m_enable_android_native_buffers = enableNativeBuffers->enable;
4000 }
4001 #if !defined(FLEXYUV_SUPPORTED)
4002 if (m_enable_android_native_buffers) {
4003 // Use the most-preferred-native-color-format as surface-mode is hinted here
4004 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4005 DEBUG_PRINT_ERROR("Failed to set native color format!");
4006 eRet = OMX_ErrorUnsupportedSetting;
4007 }
4008 }
4009 #endif
4010 }
4011 break;
4012 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4013 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4014 eRet = use_android_native_buffer(hComp, paramData);
4015 }
4016 break;
4017 case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4018
4019 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4020 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4021
4022 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4023 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
4024 eRet = OMX_ErrorUnsupportedSetting;
4025 break;
4026 } else if (m_inp_mem_ptr) {
4027 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4028 eRet = OMX_ErrorInvalidState;
4029 break;
4030 }
4031
4032 if (allocateNativeHandleParams != NULL) {
4033 allocate_native_handle = allocateNativeHandleParams->enable;
4034 }
4035 }
4036 break;
4037 #endif
4038 case OMX_QcomIndexParamEnableTimeStampReorder: {
4039 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4040 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4041 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4042 if (reorder->bEnable == OMX_TRUE) {
4043 frm_int =0;
4044 time_stamp_dts.set_timestamp_reorder_mode(true);
4045 } else
4046 time_stamp_dts.set_timestamp_reorder_mode(false);
4047 } else {
4048 time_stamp_dts.set_timestamp_reorder_mode(false);
4049 if (reorder->bEnable == OMX_TRUE) {
4050 eRet = OMX_ErrorUnsupportedSetting;
4051 }
4052 }
4053 }
4054 break;
4055 case OMX_IndexParamVideoProfileLevelCurrent: {
4056 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4057 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4058 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4059 if (pParam) {
4060 m_profile_lvl.eProfile = pParam->eProfile;
4061 m_profile_lvl.eLevel = pParam->eLevel;
4062 }
4063 break;
4064
4065 }
4066 case OMX_QcomIndexParamVideoMetaBufferMode:
4067 {
4068 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4069 StoreMetaDataInBuffersParams *metabuffer =
4070 (StoreMetaDataInBuffersParams *)paramData;
4071 if (!metabuffer) {
4072 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4073 eRet = OMX_ErrorBadParameter;
4074 break;
4075 }
4076 if (m_disable_dynamic_buf_mode) {
4077 DEBUG_PRINT_HIGH("Dynamic buffer mode disabled by setprop");
4078 eRet = OMX_ErrorUnsupportedSetting;
4079 break;
4080 }
4081 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4082
4083 if (m_out_mem_ptr) {
4084 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
4085 eRet = OMX_ErrorInvalidState;
4086 break;
4087 }
4088 //set property dynamic buffer mode to driver.
4089 struct v4l2_control control;
4090 struct v4l2_format fmt;
4091 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
4092 if (metabuffer->bStoreMetaData == true) {
4093 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
4094 } else {
4095 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
4096 }
4097 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4098 if (!rc) {
4099 DEBUG_PRINT_HIGH("%s buffer mode",
4100 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4101 dynamic_buf_mode = metabuffer->bStoreMetaData;
4102 } else {
4103 DEBUG_PRINT_ERROR("Failed to %s buffer mode",
4104 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
4105 eRet = OMX_ErrorUnsupportedSetting;
4106 }
4107 } else {
4108 DEBUG_PRINT_ERROR(
4109 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4110 (unsigned int)metabuffer->nPortIndex);
4111 eRet = OMX_ErrorUnsupportedSetting;
4112 }
4113 break;
4114 }
4115 case OMX_QcomIndexParamVideoDownScalar:
4116 {
4117 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4118 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4119 struct v4l2_control control;
4120 int rc;
4121 if (pParam) {
4122 is_down_scalar_enabled = pParam->bEnable;
4123 if (is_down_scalar_enabled) {
4124 control.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
4125 control.value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
4126 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar value = %d", pParam->bEnable);
4127 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4128 if (rc < 0) {
4129 DEBUG_PRINT_ERROR("Failed to set down scalar on driver.");
4130 eRet = OMX_ErrorUnsupportedSetting;
4131 }
4132 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
4133 control.value = 1;
4134 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4135 if (rc < 0) {
4136 DEBUG_PRINT_ERROR("Failed to set keep aspect ratio on driver.");
4137 eRet = OMX_ErrorUnsupportedSetting;
4138 }
4139 }
4140 }
4141 break;
4142 }
4143 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4144 case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4145 {
4146 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4147 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4148 PrepareForAdaptivePlaybackParams* pParams =
4149 (PrepareForAdaptivePlaybackParams *) paramData;
4150 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4151 if (!pParams->bEnable) {
4152 return OMX_ErrorNone;
4153 }
4154 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4155 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4156 DEBUG_PRINT_ERROR(
4157 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4158 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4159 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4160 eRet = OMX_ErrorBadParameter;
4161 } else {
4162 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4163 }
4164 } else {
4165 DEBUG_PRINT_ERROR(
4166 "Prepare for adaptive playback supported only on output port");
4167 eRet = OMX_ErrorBadParameter;
4168 }
4169 break;
4170 }
4171
4172 #endif
4173 case OMX_QcomIndexParamVideoCustomBufferSize:
4174 {
4175 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4176 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4177 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4178 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4179 struct v4l2_control control;
4180 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4181 control.value = pParam->nBufferSize;
4182 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4183 DEBUG_PRINT_ERROR("Failed to set input buffer size");
4184 eRet = OMX_ErrorUnsupportedSetting;
4185 } else {
4186 eRet = get_buffer_req(&drv_ctx.ip_buf);
4187 if (eRet == OMX_ErrorNone) {
4188 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4189 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4190 m_custom_buffersize.input_buffersize);
4191 } else {
4192 DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4193 }
4194 }
4195 } else {
4196 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4197 eRet = OMX_ErrorBadParameter;
4198 }
4199 break;
4200 }
4201 default: {
4202 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4203 eRet = OMX_ErrorUnsupportedIndex;
4204 }
4205 }
4206 if (eRet != OMX_ErrorNone)
4207 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4208 return eRet;
4209 }
4210
4211 /* ======================================================================
4212 FUNCTION
4213 omx_vdec::GetConfig
4214
4215 DESCRIPTION
4216 OMX Get Config Method implementation.
4217
4218 PARAMETERS
4219 <TBD>.
4220
4221 RETURN VALUE
4222 OMX Error None if successful.
4223
4224 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4225 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
4226 OMX_IN OMX_INDEXTYPE configIndex,
4227 OMX_INOUT OMX_PTR configData)
4228 {
4229 (void) hComp;
4230 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4231
4232 if (m_state == OMX_StateInvalid) {
4233 DEBUG_PRINT_ERROR("Get Config in Invalid State");
4234 return OMX_ErrorInvalidState;
4235 }
4236
4237 switch ((unsigned long)configIndex) {
4238 case OMX_QcomIndexConfigInterlaced: {
4239 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
4240 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
4241 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
4242 if (configFmt->nPortIndex == 1) {
4243 if (configFmt->nIndex == 0) {
4244 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
4245 } else if (configFmt->nIndex == 1) {
4246 configFmt->eInterlaceType =
4247 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
4248 } else if (configFmt->nIndex == 2) {
4249 configFmt->eInterlaceType =
4250 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
4251 } else {
4252 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
4253 " NoMore Interlaced formats");
4254 eRet = OMX_ErrorNoMore;
4255 }
4256
4257 } else {
4258 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
4259 (int)configFmt->nPortIndex);
4260 eRet = OMX_ErrorBadPortIndex;
4261 }
4262 break;
4263 }
4264 case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
4265 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
4266 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
4267 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
4268 decoderinstances->nNumOfInstances = 16;
4269 /*TODO: How to handle this case */
4270 break;
4271 }
4272 case OMX_QcomIndexConfigVideoFramePackingArrangement: {
4273 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
4274 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
4275 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
4276 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
4277 memcpy(configFmt, &m_frame_pack_arrangement,
4278 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
4279 } else {
4280 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
4281 }
4282 break;
4283 }
4284 case OMX_IndexConfigCommonOutputCrop: {
4285 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
4286 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
4287 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
4288 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
4289 rectangle.nLeft, rectangle.nTop,
4290 rectangle.nWidth, rectangle.nHeight);
4291 break;
4292 }
4293 case OMX_QcomIndexConfigPerfLevel: {
4294 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
4295 struct v4l2_control control;
4296 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
4297 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
4298
4299 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
4300 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4301 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
4302 eRet = OMX_ErrorHardware;
4303 }
4304
4305 if (eRet == OMX_ErrorNone) {
4306 switch (control.value) {
4307 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
4308 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
4309 break;
4310 default:
4311 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
4312 /* Fall through */
4313 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
4314 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
4315 break;
4316 }
4317 }
4318
4319 break;
4320 }
4321 default: {
4322 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
4323 eRet = OMX_ErrorBadParameter;
4324 }
4325
4326 }
4327
4328 return eRet;
4329 }
4330
4331 /* ======================================================================
4332 FUNCTION
4333 omx_vdec::SetConfig
4334
4335 DESCRIPTION
4336 OMX Set Config method implementation
4337
4338 PARAMETERS
4339 <TBD>.
4340
4341 RETURN VALUE
4342 OMX Error None if successful.
4343 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)4344 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
4345 OMX_IN OMX_INDEXTYPE configIndex,
4346 OMX_IN OMX_PTR configData)
4347 {
4348 (void) hComp;
4349 if (m_state == OMX_StateInvalid) {
4350 DEBUG_PRINT_ERROR("Get Config in Invalid State");
4351 return OMX_ErrorInvalidState;
4352 }
4353
4354 OMX_ERRORTYPE ret = OMX_ErrorNone;
4355 OMX_VIDEO_CONFIG_NALSIZE *pNal;
4356
4357 DEBUG_PRINT_LOW("Set Config Called");
4358
4359 if (configIndex == OMX_IndexConfigVideoNalSize) {
4360 struct v4l2_control temp;
4361 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
4362
4363 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
4364 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
4365 switch (pNal->nNaluBytes) {
4366 case 0:
4367 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
4368 break;
4369 case 2:
4370 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
4371 break;
4372 case 4:
4373 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
4374 break;
4375 default:
4376 return OMX_ErrorUnsupportedSetting;
4377 }
4378
4379 if (!arbitrary_bytes) {
4380 /* In arbitrary bytes mode, the assembler strips out nal size and replaces
4381 * with start code, so only need to notify driver in frame by frame mode */
4382 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
4383 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
4384 return OMX_ErrorHardware;
4385 }
4386 }
4387
4388 nal_length = pNal->nNaluBytes;
4389 m_frame_parser.init_nal_length(nal_length);
4390
4391 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
4392 return ret;
4393 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
4394 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
4395 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
4396
4397 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4398 if (config->bEnabled) {
4399 if ((config->nFps >> 16) > 0) {
4400 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
4401 (unsigned int)config->nFps >> 16);
4402 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
4403 drv_ctx.frame_rate.fps_denominator);
4404
4405 if (!drv_ctx.frame_rate.fps_numerator) {
4406 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4407 drv_ctx.frame_rate.fps_numerator = 30;
4408 }
4409
4410 if (drv_ctx.frame_rate.fps_denominator) {
4411 drv_ctx.frame_rate.fps_numerator = (int)
4412 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4413 }
4414
4415 drv_ctx.frame_rate.fps_denominator = 1;
4416 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4417 drv_ctx.frame_rate.fps_numerator;
4418
4419 struct v4l2_outputparm oparm;
4420 /*XXX: we're providing timing info as seconds per frame rather than frames
4421 * per second.*/
4422 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4423 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4424
4425 struct v4l2_streamparm sparm;
4426 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4427 sparm.parm.output = oparm;
4428 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4429 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
4430 performance might be affected");
4431 ret = OMX_ErrorHardware;
4432 }
4433 client_set_fps = true;
4434 } else {
4435 DEBUG_PRINT_ERROR("Frame rate not supported.");
4436 ret = OMX_ErrorUnsupportedSetting;
4437 }
4438 } else {
4439 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
4440 client_set_fps = false;
4441 }
4442 } else {
4443 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
4444 (int)config->nPortIndex);
4445 ret = OMX_ErrorBadPortIndex;
4446 }
4447
4448 return ret;
4449 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
4450 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
4451 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
4452 struct v4l2_control control;
4453
4454 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
4455
4456 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
4457
4458 switch (perf->ePerfLevel) {
4459 case OMX_QCOM_PerfLevelNominal:
4460 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
4461 break;
4462 case OMX_QCOM_PerfLevelTurbo:
4463 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
4464 break;
4465 default:
4466 ret = OMX_ErrorUnsupportedSetting;
4467 break;
4468 }
4469
4470 if (ret == OMX_ErrorNone) {
4471 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
4472 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
4473 }
4474
4475 return ret;
4476 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
4477 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
4478 DEBUG_PRINT_LOW("Set_config: priority %d", priority->nU32);
4479
4480 struct v4l2_control control;
4481
4482 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
4483 if (priority->nU32 == 0)
4484 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
4485 else
4486 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
4487
4488 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4489 DEBUG_PRINT_ERROR("Failed to set Priority");
4490 ret = OMX_ErrorUnsupportedSetting;
4491 }
4492 return ret;
4493 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
4494 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
4495 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
4496
4497 struct v4l2_control control;
4498
4499 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
4500 control.value = rate->nU32;
4501
4502 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4503 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
4504 OMX_ErrorUnsupportedSetting;
4505 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
4506 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
4507 }
4508 return ret;
4509 }
4510
4511 return OMX_ErrorNotImplemented;
4512 }
4513
4514 #define extn_equals(param, extn) (!strcmp(param, extn))
4515
4516 /* ======================================================================
4517 FUNCTION
4518 omx_vdec::GetExtensionIndex
4519
4520 DESCRIPTION
4521 OMX GetExtensionIndex method implementaion. <TBD>
4522
4523 PARAMETERS
4524 <TBD>.
4525
4526 RETURN VALUE
4527 OMX Error None if everything successful.
4528
4529 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)4530 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
4531 OMX_IN OMX_STRING paramName,
4532 OMX_OUT OMX_INDEXTYPE* indexType)
4533 {
4534 (void) hComp;
4535 if (m_state == OMX_StateInvalid) {
4536 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
4537 return OMX_ErrorInvalidState;
4538 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
4539 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
4540 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
4541 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
4542 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
4543 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
4544 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
4545 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
4546 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
4547 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
4548 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
4549 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
4550 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
4551 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
4552 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_MPEG2SEQDISP_EXTRADATA)) {
4553 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamMpeg2SeqDispExtraData;
4554 }
4555 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4556 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
4557 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
4558 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
4559 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
4560 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
4561 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
4562 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
4563 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
4564 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
4565 } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
4566 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
4567 }
4568 #endif
4569 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
4570 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
4571 }
4572 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4573 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
4574 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
4575 }
4576 #endif
4577 #ifdef FLEXYUV_SUPPORTED
4578 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
4579 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
4580 }
4581 #endif
4582 else {
4583 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
4584 return OMX_ErrorNotImplemented;
4585 }
4586 return OMX_ErrorNone;
4587 }
4588
4589 /* ======================================================================
4590 FUNCTION
4591 omx_vdec::GetState
4592
4593 DESCRIPTION
4594 Returns the state information back to the caller.<TBD>
4595
4596 PARAMETERS
4597 <TBD>.
4598
4599 RETURN VALUE
4600 Error None if everything is successful.
4601 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)4602 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
4603 OMX_OUT OMX_STATETYPE* state)
4604 {
4605 (void) hComp;
4606 *state = m_state;
4607 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
4608 return OMX_ErrorNone;
4609 }
4610
4611 /* ======================================================================
4612 FUNCTION
4613 omx_vdec::ComponentTunnelRequest
4614
4615 DESCRIPTION
4616 OMX Component Tunnel Request method implementation. <TBD>
4617
4618 PARAMETERS
4619 None.
4620
4621 RETURN VALUE
4622 OMX Error None if everything successful.
4623
4624 ========================================================================== */
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)4625 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
4626 OMX_IN OMX_U32 port,
4627 OMX_IN OMX_HANDLETYPE peerComponent,
4628 OMX_IN OMX_U32 peerPort,
4629 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
4630 {
4631 (void) hComp;
4632 (void) port;
4633 (void) peerComponent;
4634 (void) peerPort;
4635 (void) tunnelSetup;
4636 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
4637 return OMX_ErrorNotImplemented;
4638 }
4639
4640 /* ======================================================================
4641 FUNCTION
4642 omx_vdec::UseOutputBuffer
4643
4644 DESCRIPTION
4645 Helper function for Use buffer in the input pin
4646
4647 PARAMETERS
4648 None.
4649
4650 RETURN VALUE
4651 true/false
4652
4653 ========================================================================== */
allocate_extradata()4654 OMX_ERRORTYPE omx_vdec::allocate_extradata()
4655 {
4656 #ifdef USE_ION
4657 if (drv_ctx.extradata_info.buffer_size) {
4658 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
4659 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
4660 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
4661 free_ion_memory(&drv_ctx.extradata_info.ion);
4662 }
4663 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
4664 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
4665 drv_ctx.extradata_info.size, 4096,
4666 &drv_ctx.extradata_info.ion.ion_alloc_data,
4667 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
4668 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
4669 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
4670 return OMX_ErrorInsufficientResources;
4671 }
4672 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
4673 drv_ctx.extradata_info.size,
4674 PROT_READ|PROT_WRITE, MAP_SHARED,
4675 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
4676 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
4677 DEBUG_PRINT_ERROR("Failed to map extradata memory");
4678 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
4679 free_ion_memory(&drv_ctx.extradata_info.ion);
4680 return OMX_ErrorInsufficientResources;
4681 }
4682 }
4683 #endif
4684 if (!m_other_extradata) {
4685 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
4686 if (!m_other_extradata) {
4687 DEBUG_PRINT_ERROR("Failed to alloc memory\n");
4688 return OMX_ErrorInsufficientResources;
4689 }
4690 }
4691 return OMX_ErrorNone;
4692 }
4693
free_extradata()4694 void omx_vdec::free_extradata()
4695 {
4696 #ifdef USE_ION
4697 if (drv_ctx.extradata_info.uaddr) {
4698 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
4699 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
4700 free_ion_memory(&drv_ctx.extradata_info.ion);
4701 }
4702 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
4703 #endif
4704 if (m_other_extradata) {
4705 free(m_other_extradata);
4706 m_other_extradata = NULL;
4707 }
4708 }
4709
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)4710 OMX_ERRORTYPE omx_vdec::use_output_buffer(
4711 OMX_IN OMX_HANDLETYPE hComp,
4712 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4713 OMX_IN OMX_U32 port,
4714 OMX_IN OMX_PTR appData,
4715 OMX_IN OMX_U32 bytes,
4716 OMX_IN OMX_U8* buffer)
4717 {
4718 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4719 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
4720 unsigned i= 0; // Temporary counter
4721 struct vdec_setbuffer_cmd setbuffers;
4722 OMX_PTR privateAppData = NULL;
4723 private_handle_t *handle = NULL;
4724 OMX_U8 *buff = buffer;
4725 struct v4l2_buffer buf;
4726 struct v4l2_plane plane[VIDEO_MAX_PLANES];
4727 int extra_idx = 0;
4728 (void) hComp;
4729 (void) port;
4730
4731 if (!m_out_mem_ptr) {
4732 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
4733 eRet = allocate_output_headers();
4734 if (eRet == OMX_ErrorNone)
4735 eRet = allocate_extradata();
4736 output_use_buffer = true;
4737 }
4738
4739 if (eRet == OMX_ErrorNone) {
4740 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
4741 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
4742 break;
4743 }
4744 }
4745 }
4746
4747 if (i >= drv_ctx.op_buf.actualcount) {
4748 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
4749 eRet = OMX_ErrorInsufficientResources;
4750 }
4751
4752 if (eRet != OMX_ErrorNone)
4753 return eRet;
4754
4755 if (dynamic_buf_mode) {
4756 *bufferHdr = (m_out_mem_ptr + i );
4757 (*bufferHdr)->pBuffer = NULL;
4758 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
4759 enum v4l2_buf_type buf_type;
4760 int rr = 0;
4761 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4762 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
4763 DEBUG_PRINT_ERROR(" STREAMON FAILED : %d",rr);
4764 return OMX_ErrorInsufficientResources;
4765 } else {
4766 streaming[CAPTURE_PORT] = true;
4767 DEBUG_PRINT_LOW("STREAMON Successful");
4768 }
4769 }
4770 BITMASK_SET(&m_out_bm_count,i);
4771 (*bufferHdr)->pAppPrivate = appData;
4772 (*bufferHdr)->pBuffer = buffer;
4773 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
4774 return eRet;
4775 }
4776
4777 if (eRet == OMX_ErrorNone) {
4778 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
4779 if (m_enable_android_native_buffers) {
4780 if (m_use_android_native_buffers) {
4781 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
4782 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4783 handle = (private_handle_t *)nBuf->handle;
4784 privateAppData = params->pAppPrivate;
4785 } else {
4786 handle = (private_handle_t *)buff;
4787 privateAppData = appData;
4788 }
4789 if (!handle) {
4790 DEBUG_PRINT_ERROR("handle is invalid");
4791 return OMX_ErrorBadParameter;
4792 }
4793
4794 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
4795 if (secure_mode && secure_scaling_to_non_secure_opb) {
4796 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
4797 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
4798 } else {
4799 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
4800 " expected %u, got %u",
4801 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
4802 return OMX_ErrorBadParameter;
4803 }
4804 }
4805
4806 drv_ctx.op_buf.buffer_size = handle->size;
4807
4808 if (!m_use_android_native_buffers) {
4809 if (!secure_mode) {
4810 buff = (OMX_U8*)mmap(0, handle->size,
4811 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4812 if (buff == MAP_FAILED) {
4813 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4814 return OMX_ErrorInsufficientResources;
4815 }
4816 }
4817 }
4818 #if defined(_ANDROID_ICS_)
4819 native_buffer[i].nativehandle = handle;
4820 native_buffer[i].privatehandle = handle;
4821 #endif
4822 if (!handle) {
4823 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
4824 return OMX_ErrorBadParameter;
4825 }
4826 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
4827 drv_ctx.ptr_outputbuffer[i].offset = 0;
4828 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
4829 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
4830 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
4831 } else
4832 #endif
4833
4834 if (!ouput_egl_buffers && !m_use_output_pmem) {
4835 #ifdef USE_ION
4836 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
4837 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
4838 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
4839 &drv_ctx.op_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE : 0);
4840 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
4841 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
4842 return OMX_ErrorInsufficientResources;
4843 }
4844 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
4845 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
4846 #else
4847 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
4848 open (MEM_DEVICE,O_RDWR);
4849
4850 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
4851 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
4852 return OMX_ErrorInsufficientResources;
4853 }
4854
4855 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
4856 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
4857 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
4858 open (MEM_DEVICE,O_RDWR);
4859 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
4860 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
4861 return OMX_ErrorInsufficientResources;
4862 }
4863 }
4864
4865 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
4866 drv_ctx.op_buf.buffer_size,
4867 drv_ctx.op_buf.alignment)) {
4868 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
4869 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
4870 return OMX_ErrorInsufficientResources;
4871 }
4872 #endif
4873 if (!secure_mode) {
4874 drv_ctx.ptr_outputbuffer[i].bufferaddr =
4875 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
4876 PROT_READ|PROT_WRITE, MAP_SHARED,
4877 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
4878 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
4879 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
4880 #ifdef USE_ION
4881 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
4882 #endif
4883 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
4884 return OMX_ErrorInsufficientResources;
4885 }
4886 }
4887 drv_ctx.ptr_outputbuffer[i].offset = 0;
4888 privateAppData = appData;
4889 } else {
4890
4891 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
4892 if (!appData || !bytes ) {
4893 if (!secure_mode && !buffer) {
4894 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
4895 return OMX_ErrorBadParameter;
4896 }
4897 }
4898
4899 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
4900 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
4901 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
4902 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
4903 !pmem_list->nEntries ||
4904 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4905 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
4906 return OMX_ErrorBadParameter;
4907 }
4908 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4909 pmem_list->entryList->entry;
4910 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
4911 pmem_info->pmem_fd);
4912 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
4913 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
4914 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
4915 drv_ctx.ptr_outputbuffer[i].mmaped_size =
4916 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
4917 privateAppData = appData;
4918 }
4919 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
4920 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
4921 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
4922 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
4923 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
4924
4925 *bufferHdr = (m_out_mem_ptr + i );
4926 if (secure_mode)
4927 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
4928 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
4929 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
4930 sizeof (vdec_bufferpayload));
4931
4932 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
4933 drv_ctx.ptr_outputbuffer[i].bufferaddr,
4934 drv_ctx.ptr_outputbuffer[i].pmem_fd );
4935
4936 buf.index = i;
4937 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4938 buf.memory = V4L2_MEMORY_USERPTR;
4939 plane[0].length = drv_ctx.op_buf.buffer_size;
4940 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
4941 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
4942 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
4943 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
4944 plane[0].data_offset = 0;
4945 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
4946 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
4947 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
4948 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
4949 #ifdef USE_ION
4950 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
4951 #endif
4952 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
4953 plane[extra_idx].data_offset = 0;
4954 } else if (extra_idx >= VIDEO_MAX_PLANES) {
4955 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
4956 return OMX_ErrorBadParameter;
4957 }
4958 buf.m.planes = plane;
4959 buf.length = drv_ctx.num_planes;
4960
4961 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
4962 DEBUG_PRINT_ERROR("Failed to prepare bufs");
4963 /*TODO: How to handle this case */
4964 return OMX_ErrorInsufficientResources;
4965 }
4966
4967 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
4968 enum v4l2_buf_type buf_type;
4969 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4970 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
4971 return OMX_ErrorInsufficientResources;
4972 } else {
4973 streaming[CAPTURE_PORT] = true;
4974 DEBUG_PRINT_LOW("STREAMON Successful");
4975 }
4976 }
4977
4978 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
4979 if (m_enable_android_native_buffers) {
4980 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
4981 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
4982 } else {
4983 (*bufferHdr)->pBuffer = buff;
4984 }
4985 (*bufferHdr)->pAppPrivate = privateAppData;
4986 BITMASK_SET(&m_out_bm_count,i);
4987 }
4988 return eRet;
4989 }
4990
4991 /* ======================================================================
4992 FUNCTION
4993 omx_vdec::use_input_heap_buffers
4994
4995 DESCRIPTION
4996 OMX Use Buffer Heap allocation method implementation.
4997
4998 PARAMETERS
4999 <TBD>.
5000
5001 RETURN VALUE
5002 OMX Error None , if everything successful.
5003
5004 ========================================================================== */
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)5005 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
5006 OMX_IN OMX_HANDLETYPE hComp,
5007 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5008 OMX_IN OMX_U32 port,
5009 OMX_IN OMX_PTR appData,
5010 OMX_IN OMX_U32 bytes,
5011 OMX_IN OMX_U8* buffer)
5012 {
5013 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5014 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5015
5016 if (secure_mode) {
5017 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
5018 return OMX_ErrorUndefined;
5019 }
5020
5021 if (!m_inp_heap_ptr)
5022 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5023 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5024 drv_ctx.ip_buf.actualcount);
5025 if (!m_phdr_pmem_ptr)
5026 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5027 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5028 drv_ctx.ip_buf.actualcount);
5029 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5030 DEBUG_PRINT_ERROR("Insufficent memory");
5031 eRet = OMX_ErrorInsufficientResources;
5032 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5033 input_use_buffer = true;
5034 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5035 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5036 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5037 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5038 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5039 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5040 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5041 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5042 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5043 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5044 (unsigned)NULL, (unsigned)NULL)) {
5045 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5046 return OMX_ErrorInsufficientResources;
5047 }
5048 m_in_alloc_cnt++;
5049 } else {
5050 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5051 eRet = OMX_ErrorInsufficientResources;
5052 }
5053 return eRet;
5054 }
5055
5056 /* ======================================================================
5057 FUNCTION
5058 omx_vdec::UseBuffer
5059
5060 DESCRIPTION
5061 OMX Use Buffer method implementation.
5062
5063 PARAMETERS
5064 <TBD>.
5065
5066 RETURN VALUE
5067 OMX Error None , if everything successful.
5068
5069 ========================================================================== */
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)5070 OMX_ERRORTYPE omx_vdec::use_buffer(
5071 OMX_IN OMX_HANDLETYPE hComp,
5072 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5073 OMX_IN OMX_U32 port,
5074 OMX_IN OMX_PTR appData,
5075 OMX_IN OMX_U32 bytes,
5076 OMX_IN OMX_U8* buffer)
5077 {
5078 OMX_ERRORTYPE error = OMX_ErrorNone;
5079 struct vdec_setbuffer_cmd setbuffers;
5080
5081 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5082 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5083 return OMX_ErrorBadParameter;
5084 }
5085 if (m_state == OMX_StateInvalid) {
5086 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5087 return OMX_ErrorInvalidState;
5088 }
5089 if (port == OMX_CORE_INPUT_PORT_INDEX) {
5090 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
5091 // ensure that use-buffer was called for previous allocation.
5092 // Mix-and-match of useBuffer and allocateBuffer is not allowed
5093 if (m_inp_mem_ptr && !input_use_buffer) {
5094 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
5095 return OMX_ErrorUndefined;
5096 }
5097 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5098 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
5099 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5100 else {
5101 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5102 error = OMX_ErrorBadPortIndex;
5103 }
5104 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5105 if (error == OMX_ErrorNone) {
5106 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5107 // Send the callback now
5108 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5109 post_event(OMX_CommandStateSet,OMX_StateIdle,
5110 OMX_COMPONENT_GENERATE_EVENT);
5111 }
5112 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5113 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5114 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5115 post_event(OMX_CommandPortEnable,
5116 OMX_CORE_INPUT_PORT_INDEX,
5117 OMX_COMPONENT_GENERATE_EVENT);
5118 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
5119 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5120 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5121 post_event(OMX_CommandPortEnable,
5122 OMX_CORE_OUTPUT_PORT_INDEX,
5123 OMX_COMPONENT_GENERATE_EVENT);
5124 }
5125 }
5126 return error;
5127 }
5128
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)5129 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
5130 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
5131 {
5132 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
5133 if (m_inp_heap_ptr[bufferindex].pBuffer)
5134 free(m_inp_heap_ptr[bufferindex].pBuffer);
5135 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
5136 }
5137 if (pmem_bufferHdr)
5138 free_input_buffer(pmem_bufferHdr);
5139 return OMX_ErrorNone;
5140 }
5141
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5142 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5143 {
5144 unsigned int index = 0;
5145 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
5146 return OMX_ErrorBadParameter;
5147 }
5148
5149 index = bufferHdr - m_inp_mem_ptr;
5150 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5151
5152 bufferHdr->pInputPortPrivate = NULL;
5153
5154 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
5155 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5156 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) {
5157 struct vdec_setbuffer_cmd setbuffers;
5158 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
5159 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
5160 sizeof (vdec_bufferpayload));
5161 if (!secure_mode) {
5162 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
5163 drv_ctx.ptr_inputbuffer[index].pmem_fd);
5164 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p",
5165 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
5166 drv_ctx.ptr_inputbuffer[index].bufferaddr);
5167 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
5168 drv_ctx.ptr_inputbuffer[index].mmaped_size);
5169 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
5170 } else if (allocate_native_handle){
5171 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
5172 native_handle_close(nh);
5173 native_handle_delete(nh);
5174 }
5175 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
5176 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
5177 free(m_desc_buffer_ptr[index].buf_addr);
5178 m_desc_buffer_ptr[index].buf_addr = NULL;
5179 m_desc_buffer_ptr[index].desc_data_size = 0;
5180 }
5181 #ifdef USE_ION
5182 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
5183 #endif
5184 }
5185 }
5186
5187 return OMX_ErrorNone;
5188 }
5189
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5190 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5191 {
5192 unsigned int index = 0;
5193
5194 if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
5195 return OMX_ErrorBadParameter;
5196 }
5197
5198 index = bufferHdr - m_out_mem_ptr;
5199 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
5200
5201 if (index < drv_ctx.op_buf.actualcount
5202 && drv_ctx.ptr_outputbuffer) {
5203 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
5204 drv_ctx.ptr_outputbuffer[index].bufferaddr);
5205
5206 struct vdec_setbuffer_cmd setbuffers;
5207 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5208 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
5209 sizeof (vdec_bufferpayload));
5210
5211 if (!dynamic_buf_mode) {
5212 #ifdef _ANDROID_
5213 if (m_enable_android_native_buffers) {
5214 if (!secure_mode) {
5215 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
5216 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
5217 drv_ctx.ptr_outputbuffer[index].mmaped_size);
5218 }
5219 }
5220 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
5221 } else {
5222 #endif
5223 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
5224 if (!secure_mode) {
5225 DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
5226 drv_ctx.ptr_outputbuffer[0].pmem_fd);
5227 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p",
5228 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
5229 drv_ctx.ptr_outputbuffer[0].bufferaddr);
5230 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
5231 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
5232 }
5233 close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
5234 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
5235 #ifdef USE_ION
5236 free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
5237 #endif
5238 }
5239 #ifdef _ANDROID_
5240 }
5241 #endif
5242 } //!dynamic_buf_mode
5243 if (release_output_done()) {
5244 free_extradata();
5245 }
5246 }
5247
5248 return OMX_ErrorNone;
5249
5250 }
5251
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)5252 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
5253 OMX_BUFFERHEADERTYPE **bufferHdr,
5254 OMX_U32 port,
5255 OMX_PTR appData,
5256 OMX_U32 bytes)
5257 {
5258 OMX_BUFFERHEADERTYPE *input = NULL;
5259 unsigned char *buf_addr = NULL;
5260 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5261 unsigned i = 0;
5262
5263 /* Sanity Check*/
5264 if (bufferHdr == NULL) {
5265 return OMX_ErrorBadParameter;
5266 }
5267
5268 if (m_inp_heap_ptr == NULL) {
5269 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
5270 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5271 drv_ctx.ip_buf.actualcount);
5272 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
5273 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5274 drv_ctx.ip_buf.actualcount);
5275
5276 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
5277 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
5278 return OMX_ErrorInsufficientResources;
5279 }
5280 }
5281
5282 /*Find a Free index*/
5283 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
5284 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
5285 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
5286 break;
5287 }
5288 }
5289
5290 if (i < drv_ctx.ip_buf.actualcount) {
5291 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
5292
5293 if (buf_addr == NULL) {
5294 return OMX_ErrorInsufficientResources;
5295 }
5296
5297 *bufferHdr = (m_inp_heap_ptr + i);
5298 input = *bufferHdr;
5299 BITMASK_SET(&m_heap_inp_bm_count,i);
5300
5301 input->pBuffer = (OMX_U8 *)buf_addr;
5302 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
5303 input->nVersion.nVersion = OMX_SPEC_VERSION;
5304 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
5305 input->pAppPrivate = appData;
5306 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
5307 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
5308 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
5309 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
5310 /*Add the Buffers to freeq*/
5311 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
5312 (unsigned)NULL, (unsigned)NULL)) {
5313 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5314 return OMX_ErrorInsufficientResources;
5315 }
5316 } else {
5317 return OMX_ErrorBadParameter;
5318 }
5319
5320 return eRet;
5321
5322 }
5323
5324
5325 /* ======================================================================
5326 FUNCTION
5327 omx_vdec::AllocateInputBuffer
5328
5329 DESCRIPTION
5330 Helper function for allocate buffer in the input pin
5331
5332 PARAMETERS
5333 None.
5334
5335 RETURN VALUE
5336 true/false
5337
5338 ========================================================================== */
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)5339 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
5340 OMX_IN OMX_HANDLETYPE hComp,
5341 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5342 OMX_IN OMX_U32 port,
5343 OMX_IN OMX_PTR appData,
5344 OMX_IN OMX_U32 bytes)
5345 {
5346 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5347 struct vdec_setbuffer_cmd setbuffers;
5348 OMX_BUFFERHEADERTYPE *input = NULL;
5349 unsigned i = 0;
5350 unsigned char *buf_addr = NULL;
5351 int pmem_fd = -1;
5352 unsigned int align_size = 0;
5353
5354 (void) hComp;
5355 (void) port;
5356
5357
5358
5359 if (bytes != drv_ctx.ip_buf.buffer_size) {
5360 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
5361 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
5362 return OMX_ErrorBadParameter;
5363 }
5364
5365 if (!m_inp_mem_ptr) {
5366 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
5367 drv_ctx.ip_buf.actualcount,
5368 (unsigned int)drv_ctx.ip_buf.buffer_size);
5369
5370 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
5371 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
5372
5373 if (m_inp_mem_ptr == NULL) {
5374 return OMX_ErrorInsufficientResources;
5375 }
5376
5377 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
5378 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
5379
5380 if (drv_ctx.ptr_inputbuffer == NULL) {
5381 return OMX_ErrorInsufficientResources;
5382 }
5383 #ifdef USE_ION
5384 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
5385 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
5386
5387 if (drv_ctx.ip_buf_ion_info == NULL) {
5388 return OMX_ErrorInsufficientResources;
5389 }
5390 #endif
5391
5392 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
5393 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
5394 #ifdef USE_ION
5395 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
5396 #endif
5397 }
5398 }
5399
5400 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
5401 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
5402 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
5403 break;
5404 }
5405 }
5406
5407 if (i < drv_ctx.ip_buf.actualcount) {
5408 struct v4l2_buffer buf;
5409 struct v4l2_plane plane;
5410 int rc;
5411 DEBUG_PRINT_LOW("Allocate input Buffer");
5412 #ifdef USE_ION
5413 align_size = drv_ctx.ip_buf.buffer_size + 512;
5414 align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
5415 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5416 align_size, drv_ctx.op_buf.alignment,
5417 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
5418 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ? ION_SECURE
5419 #ifndef DISABLE_INPUT_BUFFER_CACHE
5420 : ION_FLAG_CACHED
5421 #else
5422 : 0
5423 #endif
5424 );
5425 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
5426 return OMX_ErrorInsufficientResources;
5427 }
5428 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
5429 #else
5430 pmem_fd = open (MEM_DEVICE,O_RDWR);
5431
5432 if (pmem_fd < 0) {
5433 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
5434 return OMX_ErrorInsufficientResources;
5435 }
5436
5437 if (pmem_fd == 0) {
5438 pmem_fd = open (MEM_DEVICE,O_RDWR);
5439
5440 if (pmem_fd < 0) {
5441 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
5442 return OMX_ErrorInsufficientResources;
5443 }
5444 }
5445
5446 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
5447 drv_ctx.ip_buf.alignment)) {
5448 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5449 close(pmem_fd);
5450 return OMX_ErrorInsufficientResources;
5451 }
5452 #endif
5453 if (!secure_mode) {
5454 buf_addr = (unsigned char *)mmap(NULL,
5455 drv_ctx.ip_buf.buffer_size,
5456 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
5457
5458 if (buf_addr == MAP_FAILED) {
5459 close(pmem_fd);
5460 #ifdef USE_ION
5461 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
5462 #endif
5463 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
5464 return OMX_ErrorInsufficientResources;
5465 }
5466 }
5467 *bufferHdr = (m_inp_mem_ptr + i);
5468 if (secure_mode)
5469 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
5470 else
5471 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
5472 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
5473 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
5474 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
5475 drv_ctx.ptr_inputbuffer [i].offset = 0;
5476
5477
5478 buf.index = i;
5479 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5480 buf.memory = V4L2_MEMORY_USERPTR;
5481 plane.bytesused = 0;
5482 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
5483 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
5484 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
5485 plane.reserved[1] = 0;
5486 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
5487 buf.m.planes = &plane;
5488 buf.length = 1;
5489
5490 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
5491 drv_ctx.ptr_inputbuffer[i].bufferaddr);
5492
5493 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
5494
5495 if (rc) {
5496 DEBUG_PRINT_ERROR("Failed to prepare bufs");
5497 /*TODO: How to handle this case */
5498 return OMX_ErrorInsufficientResources;
5499 }
5500
5501 input = *bufferHdr;
5502 BITMASK_SET(&m_inp_bm_count,i);
5503 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
5504 if (allocate_native_handle) {
5505 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
5506 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
5507 input->pBuffer = (OMX_U8 *)nh;
5508 } else if (secure_mode) {
5509 /*Legacy method, pass ion fd stashed directly in pBuffer*/
5510 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer [i].pmem_fd;
5511 } else {
5512 input->pBuffer = (OMX_U8 *)buf_addr;
5513 }
5514 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
5515 input->nVersion.nVersion = OMX_SPEC_VERSION;
5516 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
5517 input->pAppPrivate = appData;
5518 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
5519 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
5520
5521 if (drv_ctx.disable_dmx) {
5522 eRet = allocate_desc_buffer(i);
5523 }
5524 } else {
5525 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
5526 eRet = OMX_ErrorInsufficientResources;
5527 }
5528 return eRet;
5529 }
5530
5531
5532 /* ======================================================================
5533 FUNCTION
5534 omx_vdec::AllocateOutputBuffer
5535
5536 DESCRIPTION
5537 Helper fn for AllocateBuffer in the output pin
5538
5539 PARAMETERS
5540 <TBD>.
5541
5542 RETURN VALUE
5543 OMX Error None if everything went well.
5544
5545 ========================================================================== */
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)5546 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
5547 OMX_IN OMX_HANDLETYPE hComp,
5548 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5549 OMX_IN OMX_U32 port,
5550 OMX_IN OMX_PTR appData,
5551 OMX_IN OMX_U32 bytes)
5552 {
5553 (void)hComp;
5554 (void)port;
5555 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5556 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
5557 unsigned i= 0; // Temporary counter
5558 struct vdec_setbuffer_cmd setbuffers;
5559 int extra_idx = 0;
5560 #ifdef USE_ION
5561 int ion_device_fd =-1;
5562 struct ion_allocation_data ion_alloc_data;
5563 struct ion_fd_data fd_ion_data;
5564 #endif
5565 if (!m_out_mem_ptr) {
5566 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
5567 drv_ctx.op_buf.actualcount,
5568 (unsigned int)drv_ctx.op_buf.buffer_size);
5569 int nBufHdrSize = 0;
5570 int nPlatformEntrySize = 0;
5571 int nPlatformListSize = 0;
5572 int nPMEMInfoSize = 0;
5573 int pmem_fd = -1;
5574 unsigned char *pmem_baseaddress = NULL;
5575
5576 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
5577 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
5578 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
5579
5580 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
5581 drv_ctx.op_buf.actualcount);
5582 nBufHdrSize = drv_ctx.op_buf.actualcount *
5583 sizeof(OMX_BUFFERHEADERTYPE);
5584
5585 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
5586 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
5587 nPlatformListSize = drv_ctx.op_buf.actualcount *
5588 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
5589 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
5590 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
5591
5592 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
5593 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
5594 nPMEMInfoSize,
5595 nPlatformListSize);
5596 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
5597 drv_ctx.op_buf.actualcount);
5598 #ifdef USE_ION
5599 // Allocate output buffers as cached to improve performance of software-reading
5600 // of the YUVs. Output buffers are cache-invalidated in driver.
5601 // If color-conversion is involved, Only the C2D output buffers are cached, no
5602 // need to cache the decoder's output buffers
5603 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
5604 ion_device_fd = alloc_map_ion_memory(
5605 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
5606 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
5607 &ion_alloc_data, &fd_ion_data,
5608 (secure_mode && !secure_scaling_to_non_secure_opb) ? ION_SECURE : cache_flag);
5609 if (ion_device_fd < 0) {
5610 return OMX_ErrorInsufficientResources;
5611 }
5612 pmem_fd = fd_ion_data.fd;
5613 #else
5614 pmem_fd = open (MEM_DEVICE,O_RDWR);
5615
5616 if (pmem_fd < 0) {
5617 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
5618 drv_ctx.op_buf.buffer_size);
5619 return OMX_ErrorInsufficientResources;
5620 }
5621
5622 if (pmem_fd == 0) {
5623 pmem_fd = open (MEM_DEVICE,O_RDWR);
5624
5625 if (pmem_fd < 0) {
5626 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
5627 drv_ctx.op_buf.buffer_size);
5628 return OMX_ErrorInsufficientResources;
5629 }
5630 }
5631
5632 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
5633 drv_ctx.op_buf.actualcount,
5634 drv_ctx.op_buf.alignment)) {
5635 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5636 close(pmem_fd);
5637 return OMX_ErrorInsufficientResources;
5638 }
5639 #endif
5640 if (!secure_mode) {
5641 pmem_baseaddress = (unsigned char *)mmap(NULL,
5642 (drv_ctx.op_buf.buffer_size *
5643 drv_ctx.op_buf.actualcount),
5644 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
5645 if (pmem_baseaddress == MAP_FAILED) {
5646 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
5647 (unsigned int)drv_ctx.op_buf.buffer_size);
5648 close(pmem_fd);
5649 #ifdef USE_ION
5650 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5651 #endif
5652 return OMX_ErrorInsufficientResources;
5653 }
5654 }
5655 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
5656 // Alloc mem for platform specific info
5657 char *pPtr=NULL;
5658 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
5659 nPMEMInfoSize,1);
5660 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
5661 calloc (sizeof(struct vdec_bufferpayload),
5662 drv_ctx.op_buf.actualcount);
5663 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
5664 calloc (sizeof (struct vdec_output_frameinfo),
5665 drv_ctx.op_buf.actualcount);
5666 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
5667 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
5668 return OMX_ErrorInsufficientResources;
5669 }
5670
5671 #ifdef USE_ION
5672 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
5673 calloc (sizeof(struct vdec_ion),
5674 drv_ctx.op_buf.actualcount);
5675 if (!drv_ctx.op_buf_ion_info) {
5676 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
5677 return OMX_ErrorInsufficientResources;
5678 }
5679 #endif
5680
5681 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
5682 && drv_ctx.ptr_respbuffer) {
5683 drv_ctx.ptr_outputbuffer[0].mmaped_size =
5684 (drv_ctx.op_buf.buffer_size *
5685 drv_ctx.op_buf.actualcount);
5686 bufHdr = m_out_mem_ptr;
5687 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
5688 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
5689 (((char *) m_platform_list) + nPlatformListSize);
5690 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5691 (((char *) m_platform_entry) + nPlatformEntrySize);
5692 pPlatformList = m_platform_list;
5693 pPlatformEntry = m_platform_entry;
5694 pPMEMInfo = m_pmem_info;
5695
5696 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
5697
5698 // Settting the entire storage nicely
5699 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
5700 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
5701 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
5702 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
5703 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
5704 // Set the values when we determine the right HxW param
5705 bufHdr->nAllocLen = bytes;
5706 bufHdr->nFilledLen = 0;
5707 bufHdr->pAppPrivate = appData;
5708 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
5709 // Platform specific PMEM Information
5710 // Initialize the Platform Entry
5711 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
5712 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
5713 pPlatformEntry->entry = pPMEMInfo;
5714 // Initialize the Platform List
5715 pPlatformList->nEntries = 1;
5716 pPlatformList->entryList = pPlatformEntry;
5717 // Keep pBuffer NULL till vdec is opened
5718 bufHdr->pBuffer = NULL;
5719 bufHdr->nOffset = 0;
5720
5721 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
5722 pPMEMInfo->pmem_fd = 0;
5723 bufHdr->pPlatformPrivate = pPlatformList;
5724
5725 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
5726 m_pmem_info[i].pmem_fd = pmem_fd;
5727 #ifdef USE_ION
5728 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
5729 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
5730 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
5731 #endif
5732
5733 /*Create a mapping between buffers*/
5734 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
5735 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
5736 &drv_ctx.ptr_outputbuffer[i];
5737 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
5738 drv_ctx.ptr_outputbuffer[i].bufferaddr =
5739 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
5740 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5741 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5742 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5743
5744 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
5745 pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
5746 drv_ctx.ptr_outputbuffer[i].bufferaddr);
5747 // Move the buffer and buffer header pointers
5748 bufHdr++;
5749 pPMEMInfo++;
5750 pPlatformEntry++;
5751 pPlatformList++;
5752 }
5753 } else {
5754 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
5755 m_out_mem_ptr, pPtr);
5756 if (m_out_mem_ptr) {
5757 free(m_out_mem_ptr);
5758 m_out_mem_ptr = NULL;
5759 }
5760 if (pPtr) {
5761 free(pPtr);
5762 pPtr = NULL;
5763 }
5764 if (drv_ctx.ptr_outputbuffer) {
5765 free(drv_ctx.ptr_outputbuffer);
5766 drv_ctx.ptr_outputbuffer = NULL;
5767 }
5768 if (drv_ctx.ptr_respbuffer) {
5769 free(drv_ctx.ptr_respbuffer);
5770 drv_ctx.ptr_respbuffer = NULL;
5771 }
5772 #ifdef USE_ION
5773 if (drv_ctx.op_buf_ion_info) {
5774 DEBUG_PRINT_LOW("Free o/p ion context");
5775 free(drv_ctx.op_buf_ion_info);
5776 drv_ctx.op_buf_ion_info = NULL;
5777 }
5778 #endif
5779 eRet = OMX_ErrorInsufficientResources;
5780 }
5781 if (eRet == OMX_ErrorNone)
5782 eRet = allocate_extradata();
5783 }
5784
5785 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5786 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5787 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
5788 break;
5789 }
5790 }
5791
5792 if (eRet == OMX_ErrorNone) {
5793 if (i < drv_ctx.op_buf.actualcount) {
5794 struct v4l2_buffer buf;
5795 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5796 int rc;
5797 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5798
5799 drv_ctx.ptr_outputbuffer[i].buffer_len =
5800 drv_ctx.op_buf.buffer_size;
5801
5802 *bufferHdr = (m_out_mem_ptr + i );
5803 if (secure_mode) {
5804 #ifdef USE_ION
5805 drv_ctx.ptr_outputbuffer[i].bufferaddr =
5806 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5807 #else
5808 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5809 #endif
5810 }
5811 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
5812
5813 buf.index = i;
5814 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5815 buf.memory = V4L2_MEMORY_USERPTR;
5816 plane[0].length = drv_ctx.op_buf.buffer_size;
5817 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
5818 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
5819 #ifdef USE_ION
5820 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5821 #endif
5822 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
5823 plane[0].data_offset = 0;
5824 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5825 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5826 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5827 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
5828 #ifdef USE_ION
5829 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5830 #endif
5831 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
5832 plane[extra_idx].data_offset = 0;
5833 } else if (extra_idx >= VIDEO_MAX_PLANES) {
5834 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
5835 return OMX_ErrorBadParameter;
5836 }
5837 buf.m.planes = plane;
5838 buf.length = drv_ctx.num_planes;
5839 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
5840 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
5841 if (rc) {
5842 /*TODO: How to handle this case */
5843 return OMX_ErrorInsufficientResources;
5844 }
5845
5846 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
5847 enum v4l2_buf_type buf_type;
5848 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5849 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5850 if (rc) {
5851 return OMX_ErrorInsufficientResources;
5852 } else {
5853 streaming[CAPTURE_PORT] = true;
5854 DEBUG_PRINT_LOW("STREAMON Successful");
5855 }
5856 }
5857
5858 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
5859 (*bufferHdr)->pAppPrivate = appData;
5860 BITMASK_SET(&m_out_bm_count,i);
5861 } else {
5862 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
5863 eRet = OMX_ErrorInsufficientResources;
5864 }
5865 }
5866
5867 return eRet;
5868 }
5869
5870
5871 // AllocateBuffer -- API Call
5872 /* ======================================================================
5873 FUNCTION
5874 omx_vdec::AllocateBuffer
5875
5876 DESCRIPTION
5877 Returns zero if all the buffers released..
5878
5879 PARAMETERS
5880 None.
5881
5882 RETURN VALUE
5883 true/false
5884
5885 ========================================================================== */
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)5886 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
5887 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5888 OMX_IN OMX_U32 port,
5889 OMX_IN OMX_PTR appData,
5890 OMX_IN OMX_U32 bytes)
5891 {
5892 unsigned i = 0;
5893 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
5894
5895 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
5896 if (m_state == OMX_StateInvalid) {
5897 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
5898 return OMX_ErrorInvalidState;
5899 }
5900
5901 if (port == OMX_CORE_INPUT_PORT_INDEX) {
5902 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
5903 // ensure that use-buffer was never called.
5904 // Mix-and-match of useBuffer and allocateBuffer is not allowed
5905 if (m_inp_mem_ptr && input_use_buffer) {
5906 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
5907 return OMX_ErrorUndefined;
5908 }
5909 if (arbitrary_bytes) {
5910 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
5911 } else {
5912 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
5913 }
5914 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
5915 if (output_use_buffer) {
5916 DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
5917 return OMX_ErrorBadParameter;
5918 }
5919 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
5920 appData,bytes);
5921 } else {
5922 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5923 eRet = OMX_ErrorBadPortIndex;
5924 }
5925 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
5926 if (eRet == OMX_ErrorNone) {
5927 if (allocate_done()) {
5928 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5929 // Send the callback now
5930 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5931 post_event(OMX_CommandStateSet,OMX_StateIdle,
5932 OMX_COMPONENT_GENERATE_EVENT);
5933 }
5934 }
5935 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
5936 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5937 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5938 post_event(OMX_CommandPortEnable,
5939 OMX_CORE_INPUT_PORT_INDEX,
5940 OMX_COMPONENT_GENERATE_EVENT);
5941 }
5942 }
5943 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
5944 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5945 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5946 post_event(OMX_CommandPortEnable,
5947 OMX_CORE_OUTPUT_PORT_INDEX,
5948 OMX_COMPONENT_GENERATE_EVENT);
5949 }
5950 }
5951 }
5952 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
5953 return eRet;
5954 }
5955
5956 // Free Buffer - API call
5957 /* ======================================================================
5958 FUNCTION
5959 omx_vdec::FreeBuffer
5960
5961 DESCRIPTION
5962
5963 PARAMETERS
5964 None.
5965
5966 RETURN VALUE
5967 true/false
5968
5969 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5970 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
5971 OMX_IN OMX_U32 port,
5972 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5973 {
5974 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5975 unsigned int nPortIndex;
5976 (void) hComp;
5977 DEBUG_PRINT_LOW("In for decoder free_buffer");
5978
5979 auto_lock l(buf_lock);
5980 if (m_state == OMX_StateIdle &&
5981 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
5982 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
5983 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
5984 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
5985 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
5986 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
5987 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
5988 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
5989 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
5990 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
5991 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
5992 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
5993 post_event(OMX_EventError,
5994 OMX_ErrorPortUnpopulated,
5995 OMX_COMPONENT_GENERATE_EVENT);
5996 m_buffer_error = true;
5997 return OMX_ErrorIncorrectStateOperation;
5998 } else if (m_state != OMX_StateInvalid) {
5999 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6000 post_event(OMX_EventError,
6001 OMX_ErrorPortUnpopulated,
6002 OMX_COMPONENT_GENERATE_EVENT);
6003 }
6004 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6005 /*Check if arbitrary bytes*/
6006 if (!arbitrary_bytes && !input_use_buffer)
6007 nPortIndex = buffer - m_inp_mem_ptr;
6008 else
6009 nPortIndex = buffer - m_inp_heap_ptr;
6010
6011 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6012 if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6013 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6014 // Clear the bit associated with it.
6015 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6016 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6017 if (input_use_buffer == true) {
6018
6019 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6020 if (m_phdr_pmem_ptr)
6021 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6022 } else {
6023 if (arbitrary_bytes) {
6024 if (m_phdr_pmem_ptr)
6025 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
6026 else
6027 free_input_buffer(nPortIndex,NULL);
6028 } else
6029 free_input_buffer(buffer);
6030 }
6031 m_inp_bPopulated = OMX_FALSE;
6032 if(release_input_done())
6033 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
6034 /*Free the Buffer Header*/
6035 if (release_input_done()) {
6036 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6037 free_input_buffer_header();
6038 }
6039 } else {
6040 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6041 eRet = OMX_ErrorBadPortIndex;
6042 }
6043
6044 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6045 && release_input_done()) {
6046 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6047 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6048 post_event(OMX_CommandPortDisable,
6049 OMX_CORE_INPUT_PORT_INDEX,
6050 OMX_COMPONENT_GENERATE_EVENT);
6051 }
6052 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6053 // check if the buffer is valid
6054 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6055 if (nPortIndex < drv_ctx.op_buf.actualcount &&
6056 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6057 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6058 // Clear the bit associated with it.
6059 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6060 m_out_bPopulated = OMX_FALSE;
6061 client_buffers.free_output_buffer (buffer);
6062
6063 if(release_output_done()) {
6064 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
6065 }
6066 if (release_output_done()) {
6067 free_output_buffer_header();
6068 }
6069 } else {
6070 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6071 eRet = OMX_ErrorBadPortIndex;
6072 }
6073 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6074 && release_output_done()) {
6075 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
6076
6077 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6078 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6079 #ifdef _ANDROID_ICS_
6080 if (m_enable_android_native_buffers) {
6081 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6082 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6083 }
6084 #endif
6085
6086 post_event(OMX_CommandPortDisable,
6087 OMX_CORE_OUTPUT_PORT_INDEX,
6088 OMX_COMPONENT_GENERATE_EVENT);
6089 }
6090 } else {
6091 eRet = OMX_ErrorBadPortIndex;
6092 }
6093 if ((eRet == OMX_ErrorNone) &&
6094 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6095 if (release_done()) {
6096 // Send the callback now
6097 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6098 post_event(OMX_CommandStateSet, OMX_StateLoaded,
6099 OMX_COMPONENT_GENERATE_EVENT);
6100 m_buffer_error = false;
6101 }
6102 }
6103 return eRet;
6104 }
6105
6106
6107 /* ======================================================================
6108 FUNCTION
6109 omx_vdec::EmptyThisBuffer
6110
6111 DESCRIPTION
6112 This routine is used to push the encoded video frames to
6113 the video decoder.
6114
6115 PARAMETERS
6116 None.
6117
6118 RETURN VALUE
6119 OMX Error None if everything went successful.
6120
6121 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6122 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
6123 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6124 {
6125 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6126 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6127
6128 if (m_state != OMX_StateExecuting &&
6129 m_state != OMX_StatePause &&
6130 m_state != OMX_StateIdle) {
6131 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6132 return OMX_ErrorInvalidState;
6133 }
6134
6135 if (buffer == NULL) {
6136 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6137 return OMX_ErrorBadParameter;
6138 }
6139
6140 if (!m_inp_bEnabled) {
6141 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
6142 return OMX_ErrorIncorrectStateOperation;
6143 }
6144
6145 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
6146 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
6147 return OMX_ErrorBadPortIndex;
6148 }
6149
6150 #ifdef _ANDROID_
6151 if (iDivXDrmDecrypt) {
6152 OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer);
6153 if (drmErr != OMX_ErrorNone) {
6154 // this error can be ignored
6155 DEBUG_PRINT_LOW("ERROR:iDivXDrmDecrypt->Decrypt %d", drmErr);
6156 }
6157 }
6158 #endif //_ANDROID_
6159 if (perf_flag) {
6160 if (!latency) {
6161 dec_time.stop();
6162 latency = dec_time.processing_time_us();
6163 dec_time.start();
6164 }
6165 }
6166
6167 if (arbitrary_bytes) {
6168 nBufferIndex = buffer - m_inp_heap_ptr;
6169 } else {
6170 if (input_use_buffer == true) {
6171 nBufferIndex = buffer - m_inp_heap_ptr;
6172 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
6173 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
6174 return OMX_ErrorBadParameter;
6175 }
6176 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
6177 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
6178 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
6179 buffer = &m_inp_mem_ptr[nBufferIndex];
6180 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
6181 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
6182 } else {
6183 nBufferIndex = buffer - m_inp_mem_ptr;
6184 }
6185 }
6186
6187 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
6188 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
6189 return OMX_ErrorBadParameter;
6190 }
6191
6192 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6193 codec_config_flag = true;
6194 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
6195 }
6196
6197 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
6198 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
6199 if (arbitrary_bytes) {
6200 post_event ((unsigned long)hComp,(unsigned long)buffer,
6201 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
6202 } else {
6203 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
6204 }
6205 time_stamp_dts.insert_timestamp(buffer);
6206 return OMX_ErrorNone;
6207 }
6208
6209 /* ======================================================================
6210 FUNCTION
6211 omx_vdec::empty_this_buffer_proxy
6212
6213 DESCRIPTION
6214 This routine is used to push the encoded video frames to
6215 the video decoder.
6216
6217 PARAMETERS
6218 None.
6219
6220 RETURN VALUE
6221 OMX Error None if everything went successful.
6222
6223 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6224 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
6225 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6226 {
6227 (void) hComp;
6228 int push_cnt = 0,i=0;
6229 unsigned nPortIndex = 0;
6230 OMX_ERRORTYPE ret = OMX_ErrorNone;
6231 struct vdec_input_frameinfo frameinfo;
6232 struct vdec_bufferpayload *temp_buffer;
6233 struct vdec_seqheader seq_header;
6234 bool port_setting_changed = true;
6235
6236 /*Should we generate a Aync error event*/
6237 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
6238 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
6239 return OMX_ErrorBadParameter;
6240 }
6241
6242 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
6243
6244 if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
6245 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
6246 nPortIndex);
6247 return OMX_ErrorBadParameter;
6248 }
6249
6250 pending_input_buffers++;
6251
6252 /* return zero length and not an EOS buffer */
6253 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
6254 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
6255 DEBUG_PRINT_HIGH("return zero legth buffer");
6256 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6257 OMX_COMPONENT_GENERATE_EBD);
6258 return OMX_ErrorNone;
6259 }
6260
6261 if (input_flush_progress == true) {
6262 DEBUG_PRINT_LOW("Flush in progress return buffer ");
6263 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6264 OMX_COMPONENT_GENERATE_EBD);
6265 return OMX_ErrorNone;
6266 }
6267
6268 auto_lock l(buf_lock);
6269 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
6270
6271 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
6272 return OMX_ErrorBadParameter;
6273 }
6274
6275 if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
6276 DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
6277 return OMX_ErrorBadParameter;
6278 }
6279 /* If its first frame, H264 codec and reject is true, then parse the nal
6280 and get the profile. Based on this, reject the clip playback */
6281 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
6282 m_reject_avc_1080p_mp) {
6283 first_frame = 1;
6284 DEBUG_PRINT_ERROR("Parse nal to get the profile");
6285 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
6286 NALU_TYPE_SPS);
6287 m_profile = h264_parser->get_profile();
6288 ret = is_video_session_supported();
6289 if (ret) {
6290 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
6291 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
6292 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
6293 m_state = OMX_StateInvalid;
6294 return OMX_ErrorNone;
6295 }
6296 }
6297
6298 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6299 /*for use buffer we need to memcpy the data*/
6300 temp_buffer->buffer_len = buffer->nFilledLen;
6301
6302 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
6303 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
6304 if (arbitrary_bytes) {
6305 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
6306 } else {
6307 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
6308 buffer->nFilledLen);
6309 }
6310 } else {
6311 return OMX_ErrorBadParameter;
6312 }
6313
6314 }
6315
6316 frameinfo.bufferaddr = temp_buffer->bufferaddr;
6317 frameinfo.client_data = (void *) buffer;
6318 frameinfo.datalen = temp_buffer->buffer_len;
6319 frameinfo.flags = 0;
6320 frameinfo.offset = buffer->nOffset;
6321 frameinfo.pmem_fd = temp_buffer->pmem_fd;
6322 frameinfo.pmem_offset = temp_buffer->offset;
6323 frameinfo.timestamp = buffer->nTimeStamp;
6324 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
6325 DEBUG_PRINT_LOW("ETB: dmx enabled");
6326 if (m_demux_entries == 0) {
6327 extract_demux_addr_offsets(buffer);
6328 }
6329
6330 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
6331 handle_demux_data(buffer);
6332 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
6333 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
6334 } else {
6335 frameinfo.desc_addr = NULL;
6336 frameinfo.desc_size = 0;
6337 }
6338 if (!arbitrary_bytes) {
6339 frameinfo.flags |= buffer->nFlags;
6340 }
6341
6342 #ifdef _ANDROID_
6343 if (m_debug_timestamp) {
6344 if (arbitrary_bytes) {
6345 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
6346 m_timestamp_list.insert_ts(buffer->nTimeStamp);
6347 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
6348 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
6349 m_timestamp_list.insert_ts(buffer->nTimeStamp);
6350 }
6351 }
6352 #endif
6353
6354 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
6355
6356 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
6357 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6358 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6359 }
6360
6361 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
6362 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
6363 frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
6364 h264_scratch.nFilledLen = 0;
6365 nal_count = 0;
6366 look_ahead_nal = false;
6367 frame_count = 0;
6368 if (m_frame_parser.mutils)
6369 m_frame_parser.mutils->initialize_frame_checking_environment();
6370 m_frame_parser.flush();
6371 h264_last_au_ts = LLONG_MAX;
6372 h264_last_au_flags = 0;
6373 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
6374 m_demux_entries = 0;
6375 }
6376 struct v4l2_buffer buf;
6377 struct v4l2_plane plane;
6378 memset( (void *)&buf, 0, sizeof(buf));
6379 memset( (void *)&plane, 0, sizeof(plane));
6380 int rc;
6381 unsigned long print_count;
6382 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
6383 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
6384 DEBUG_PRINT_HIGH("INPUT EOS reached") ;
6385 }
6386 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6387 buf.index = nPortIndex;
6388 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6389 buf.memory = V4L2_MEMORY_USERPTR;
6390 plane.bytesused = temp_buffer->buffer_len;
6391 plane.length = drv_ctx.ip_buf.buffer_size;
6392 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
6393 (unsigned long)temp_buffer->offset;
6394 plane.reserved[0] = temp_buffer->pmem_fd;
6395 plane.reserved[1] = temp_buffer->offset;
6396 plane.data_offset = 0;
6397 buf.m.planes = &plane;
6398 buf.length = 1;
6399 if (frameinfo.timestamp >= LLONG_MAX) {
6400 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
6401 }
6402 //assumption is that timestamp is in milliseconds
6403 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
6404 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
6405 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
6406 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
6407
6408 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
6409 DEBUG_PRINT_LOW("Increment codec_config buffer counter");
6410 android_atomic_inc(&m_queued_codec_config_count);
6411 }
6412
6413 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
6414 if (rc) {
6415 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
6416 return OMX_ErrorHardware;
6417 }
6418
6419 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
6420 codec_config_flag = false;
6421 }
6422 if (!streaming[OUTPUT_PORT]) {
6423 enum v4l2_buf_type buf_type;
6424 int ret,r;
6425
6426 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6427 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
6428 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6429 if (!ret) {
6430 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
6431 streaming[OUTPUT_PORT] = true;
6432 } else if (errno == EBUSY) {
6433 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
6434 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
6435 OMX_COMPONENT_GENERATE_EBD);
6436 return OMX_ErrorInsufficientResources;
6437 } else {
6438 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
6439 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
6440 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
6441 OMX_COMPONENT_GENERATE_EBD);
6442 return OMX_ErrorBadParameter;
6443 }
6444 }
6445 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
6446 frameinfo.bufferaddr, (long long)frameinfo.timestamp,
6447 (unsigned int)frameinfo.datalen);
6448
6449 return ret;
6450 }
6451
6452 /* ======================================================================
6453 FUNCTION
6454 omx_vdec::FillThisBuffer
6455
6456 DESCRIPTION
6457 IL client uses this method to release the frame buffer
6458 after displaying them.
6459
6460 PARAMETERS
6461 None.
6462
6463 RETURN VALUE
6464 true/false
6465
6466 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6467 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
6468 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6469 {
6470 if (m_state != OMX_StateExecuting &&
6471 m_state != OMX_StatePause &&
6472 m_state != OMX_StateIdle) {
6473 DEBUG_PRINT_ERROR("FTB in Invalid State");
6474 return OMX_ErrorInvalidState;
6475 }
6476
6477 if (!m_out_bEnabled) {
6478 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
6479 return OMX_ErrorIncorrectStateOperation;
6480 }
6481
6482 unsigned nPortIndex = 0;
6483 if (dynamic_buf_mode) {
6484 private_handle_t *handle = NULL;
6485 struct VideoDecoderOutputMetaData *meta;
6486 unsigned int nPortIndex = 0;
6487
6488 if (!buffer || !buffer->pBuffer) {
6489 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
6490 return OMX_ErrorBadParameter;
6491 }
6492
6493 //get the buffer type and fd info
6494 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
6495 handle = (private_handle_t *)meta->pHandle;
6496 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
6497
6498 if (!handle) {
6499 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
6500 return OMX_ErrorBadParameter;
6501 }
6502
6503 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
6504 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
6505 if (nPortIndex < drv_ctx.op_buf.actualcount &&
6506 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
6507 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
6508 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
6509
6510 //Store private handle from GraphicBuffer
6511 native_buffer[nPortIndex].privatehandle = handle;
6512 native_buffer[nPortIndex].nativehandle = handle;
6513 } else {
6514 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
6515 return OMX_ErrorBadParameter;
6516 }
6517
6518 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
6519 //this with a more sane size so that we don't compensate in rest of code
6520 //We'll restore this size later on, so that it's transparent to client
6521 buffer->nFilledLen = 0;
6522 buffer->nAllocLen = handle->size;
6523 }
6524
6525 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6526 if (buffer == NULL ||
6527 (nPortIndex >= drv_ctx.op_buf.actualcount)) {
6528 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
6529 nPortIndex, drv_ctx.op_buf.actualcount);
6530 return OMX_ErrorBadParameter;
6531 }
6532
6533 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
6534 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
6535 return OMX_ErrorBadPortIndex;
6536 }
6537
6538 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6539 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
6540 return OMX_ErrorNone;
6541 }
6542 /* ======================================================================
6543 FUNCTION
6544 omx_vdec::fill_this_buffer_proxy
6545
6546 DESCRIPTION
6547 IL client uses this method to release the frame buffer
6548 after displaying them.
6549
6550 PARAMETERS
6551 None.
6552
6553 RETURN VALUE
6554 true/false
6555
6556 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)6557 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
6558 OMX_IN OMX_HANDLETYPE hComp,
6559 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
6560 {
6561 OMX_ERRORTYPE nRet = OMX_ErrorNone;
6562 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
6563 unsigned nPortIndex = 0;
6564 struct vdec_fillbuffer_cmd fillbuffer;
6565 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
6566 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
6567
6568 auto_lock l(buf_lock);
6569 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
6570
6571 if (!bufferAdd || !bufferAdd->pBuffer || nPortIndex >= drv_ctx.op_buf.actualcount) {
6572 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
6573 nPortIndex, drv_ctx.op_buf.actualcount);
6574 return OMX_ErrorBadParameter;
6575 }
6576
6577 if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
6578 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
6579 return OMX_ErrorBadParameter;
6580 }
6581 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
6582 bufferAdd, bufferAdd->pBuffer);
6583 /*Return back the output buffer to client*/
6584 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
6585 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
6586 buffer->nFilledLen = 0;
6587 m_cb.FillBufferDone (hComp,m_app_data,buffer);
6588 return OMX_ErrorNone;
6589 }
6590
6591 if (dynamic_buf_mode) {
6592
6593 if (drv_ctx.ptr_outputbuffer) {
6594 private_handle_t *handle = NULL;
6595 struct VideoDecoderOutputMetaData *meta;
6596
6597 //get the buffer type and fd info
6598 meta = (struct VideoDecoderOutputMetaData *)bufferAdd->pBuffer;
6599 handle = (private_handle_t *)meta->pHandle;
6600 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
6601
6602 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
6603 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
6604 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) bufferAdd;
6605
6606 //map the buffer handle based on the size set on output port definition.
6607 if (!secure_mode) {
6608 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
6609 (OMX_U8*)mmap(0, drv_ctx.op_buf.buffer_size,
6610 PROT_READ|PROT_WRITE, MAP_SHARED,
6611 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
6612 }
6613
6614 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
6615 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = drv_ctx.op_buf.buffer_size;
6616 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = drv_ctx.op_buf.buffer_size;
6617 buf_ref_add(drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd,
6618 drv_ctx.ptr_outputbuffer[nPortIndex].offset);
6619 } else {
6620 DEBUG_PRINT_ERROR("Output Buffers are already free'd !");
6621 return OMX_ErrorBadParameter;
6622 }
6623 }
6624
6625 pending_output_buffers++;
6626 buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
6627 if (!buffer) {
6628 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
6629 return OMX_ErrorBadParameter;
6630 }
6631 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
6632 if (ptr_respbuffer) {
6633 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
6634 }
6635
6636 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
6637 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
6638 buffer->nFilledLen = 0;
6639 m_cb.FillBufferDone (hComp,m_app_data,buffer);
6640 pending_output_buffers--;
6641 return OMX_ErrorBadParameter;
6642 }
6643
6644 int rc = 0;
6645 struct v4l2_buffer buf;
6646 struct v4l2_plane plane[VIDEO_MAX_PLANES];
6647 memset( (void *)&buf, 0, sizeof(buf));
6648 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
6649 unsigned int extra_idx = 0;
6650
6651 buf.index = nPortIndex;
6652 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6653 buf.memory = V4L2_MEMORY_USERPTR;
6654 plane[0].bytesused = buffer->nFilledLen;
6655 plane[0].length = drv_ctx.op_buf.buffer_size;
6656 plane[0].m.userptr =
6657 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
6658 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
6659 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
6660 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
6661 plane[0].data_offset = 0;
6662 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6663 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6664 plane[extra_idx].bytesused = 0;
6665 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6666 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
6667 #ifdef USE_ION
6668 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6669 #endif
6670 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
6671 plane[extra_idx].data_offset = 0;
6672 } else if (extra_idx >= VIDEO_MAX_PLANES) {
6673 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
6674 return OMX_ErrorBadParameter;
6675 }
6676 buf.m.planes = plane;
6677 buf.length = drv_ctx.num_planes;
6678 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d",
6679 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1]);
6680
6681 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
6682 if (rc) {
6683 /*TODO: How to handle this case */
6684 DEBUG_PRINT_ERROR("Failed to qbuf to driver");
6685 }
6686 return OMX_ErrorNone;
6687 }
6688
6689 /* ======================================================================
6690 FUNCTION
6691 omx_vdec::SetCallbacks
6692
6693 DESCRIPTION
6694 Set the callbacks.
6695
6696 PARAMETERS
6697 None.
6698
6699 RETURN VALUE
6700 OMX Error None if everything successful.
6701
6702 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)6703 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
6704 OMX_IN OMX_CALLBACKTYPE* callbacks,
6705 OMX_IN OMX_PTR appData)
6706 {
6707 (void) hComp;
6708 m_cb = *callbacks;
6709 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
6710 m_cb.EventHandler,m_cb.FillBufferDone);
6711 m_app_data = appData;
6712 return OMX_ErrorNotImplemented;
6713 }
6714
6715 /* ======================================================================
6716 FUNCTION
6717 omx_vdec::ComponentDeInit
6718
6719 DESCRIPTION
6720 Destroys the component and release memory allocated to the heap.
6721
6722 PARAMETERS
6723 <TBD>.
6724
6725 RETURN VALUE
6726 OMX Error None if everything successful.
6727
6728 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)6729 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
6730 {
6731 (void) hComp;
6732 #ifdef _ANDROID_
6733 if (iDivXDrmDecrypt) {
6734 delete iDivXDrmDecrypt;
6735 iDivXDrmDecrypt=NULL;
6736 }
6737 #endif //_ANDROID_
6738
6739 unsigned i = 0;
6740 if (OMX_StateLoaded != m_state) {
6741 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
6742 m_state);
6743 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
6744 } else {
6745 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
6746 }
6747
6748 /*Check if the output buffers have to be cleaned up*/
6749 if (m_out_mem_ptr) {
6750 DEBUG_PRINT_LOW("Freeing the Output Memory");
6751 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
6752 if (BITMASK_PRESENT(&m_out_bm_count, i)) {
6753 BITMASK_CLEAR(&m_out_bm_count, i);
6754 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
6755 }
6756
6757 if (release_output_done()) {
6758 break;
6759 }
6760 }
6761 #ifdef _ANDROID_ICS_
6762 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6763 #endif
6764 }
6765
6766 /*Check if the input buffers have to be cleaned up*/
6767 if (m_inp_mem_ptr || m_inp_heap_ptr) {
6768 DEBUG_PRINT_LOW("Freeing the Input Memory");
6769 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
6770
6771 if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
6772 BITMASK_CLEAR(&m_inp_bm_count, i);
6773 if (m_inp_mem_ptr)
6774 free_input_buffer (i,&m_inp_mem_ptr[i]);
6775 else
6776 free_input_buffer (i,NULL);
6777 }
6778
6779 if (release_input_done()) {
6780 break;
6781 }
6782 }
6783 }
6784 free_input_buffer_header();
6785 free_output_buffer_header();
6786 if (h264_scratch.pBuffer) {
6787 free(h264_scratch.pBuffer);
6788 h264_scratch.pBuffer = NULL;
6789 }
6790
6791 if (h264_parser) {
6792 delete h264_parser;
6793 h264_parser = NULL;
6794 }
6795
6796 if (m_frame_parser.mutils) {
6797 DEBUG_PRINT_LOW("Free utils parser");
6798 delete (m_frame_parser.mutils);
6799 m_frame_parser.mutils = NULL;
6800 }
6801
6802 if (m_platform_list) {
6803 free(m_platform_list);
6804 m_platform_list = NULL;
6805 }
6806 if (m_vendor_config.pData) {
6807 free(m_vendor_config.pData);
6808 m_vendor_config.pData = NULL;
6809 }
6810
6811 // Reset counters in mesg queues
6812 m_ftb_q.m_size=0;
6813 m_cmd_q.m_size=0;
6814 m_etb_q.m_size=0;
6815 m_ftb_q.m_read = m_ftb_q.m_write =0;
6816 m_cmd_q.m_read = m_cmd_q.m_write =0;
6817 m_etb_q.m_read = m_etb_q.m_write =0;
6818 #ifdef _ANDROID_
6819 if (m_debug_timestamp) {
6820 m_timestamp_list.reset_ts_list();
6821 }
6822 #endif
6823
6824 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
6825 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
6826 // NULL);
6827 DEBUG_PRINT_HIGH("Close the driver instance");
6828
6829 if (m_debug.infile) {
6830 fclose(m_debug.infile);
6831 m_debug.infile = NULL;
6832 }
6833 if (m_debug.outfile) {
6834 fclose(m_debug.outfile);
6835 m_debug.outfile = NULL;
6836 }
6837 #ifdef OUTPUT_EXTRADATA_LOG
6838 if (outputExtradataFile)
6839 fclose (outputExtradataFile);
6840 #endif
6841 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
6842 return OMX_ErrorNone;
6843 }
6844
6845 /* ======================================================================
6846 FUNCTION
6847 omx_vdec::UseEGLImage
6848
6849 DESCRIPTION
6850 OMX Use EGL Image method implementation <TBD>.
6851
6852 PARAMETERS
6853 <TBD>.
6854
6855 RETURN VALUE
6856 Not Implemented error.
6857
6858 ========================================================================== */
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)6859 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
6860 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6861 OMX_IN OMX_U32 port,
6862 OMX_IN OMX_PTR appData,
6863 OMX_IN void* eglImage)
6864 {
6865 (void) appData;
6866 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
6867 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
6868 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
6869
6870 #ifdef USE_EGL_IMAGE_GPU
6871 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
6872 EGLint fd = -1, offset = 0,pmemPtr = 0;
6873 #else
6874 int fd = -1, offset = 0;
6875 #endif
6876 DEBUG_PRINT_HIGH("use EGL image support for decoder");
6877 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
6878 DEBUG_PRINT_ERROR("Invalid EGL image");
6879 }
6880 #ifdef USE_EGL_IMAGE_GPU
6881 if (m_display_id == NULL) {
6882 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
6883 return OMX_ErrorInsufficientResources;
6884 }
6885 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
6886 eglGetProcAddress("eglQueryImageKHR");
6887 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
6888 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
6889 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr);
6890 #else //with OMX test app
6891 struct temp_egl {
6892 int pmem_fd;
6893 int offset;
6894 };
6895 struct temp_egl *temp_egl_id = NULL;
6896 void * pmemPtr = (void *) eglImage;
6897 temp_egl_id = (struct temp_egl *)eglImage;
6898 if (temp_egl_id != NULL) {
6899 fd = temp_egl_id->pmem_fd;
6900 offset = temp_egl_id->offset;
6901 }
6902 #endif
6903 if (fd < 0) {
6904 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
6905 return OMX_ErrorInsufficientResources;
6906 }
6907 pmem_info.pmem_fd = (OMX_U32) fd;
6908 pmem_info.offset = (OMX_U32) offset;
6909 pmem_entry.entry = (void *) &pmem_info;
6910 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6911 pmem_list.entryList = &pmem_entry;
6912 pmem_list.nEntries = 1;
6913 ouput_egl_buffers = true;
6914 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
6915 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
6916 (OMX_U8 *)pmemPtr)) {
6917 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
6918 return OMX_ErrorInsufficientResources;
6919 }
6920 return OMX_ErrorNone;
6921 }
6922
6923 /* ======================================================================
6924 FUNCTION
6925 omx_vdec::ComponentRoleEnum
6926
6927 DESCRIPTION
6928 OMX Component Role Enum method implementation.
6929
6930 PARAMETERS
6931 <TBD>.
6932
6933 RETURN VALUE
6934 OMX Error None if everything is successful.
6935 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)6936 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
6937 OMX_OUT OMX_U8* role,
6938 OMX_IN OMX_U32 index)
6939 {
6940 (void) hComp;
6941 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6942
6943 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
6944 if ((0 == index) && role) {
6945 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
6946 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6947 } else {
6948 eRet = OMX_ErrorNoMore;
6949 }
6950 }
6951 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
6952 if ((0 == index) && role) {
6953 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
6954 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6955 } else {
6956 eRet = OMX_ErrorNoMore;
6957 }
6958 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
6959 if ((0 == index) && role) {
6960 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
6961 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6962 } else {
6963 DEBUG_PRINT_LOW("No more roles");
6964 eRet = OMX_ErrorNoMore;
6965 }
6966 }
6967
6968 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
6969 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
6970 if ((0 == index) && role) {
6971 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
6972 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6973 } else {
6974 DEBUG_PRINT_LOW("No more roles");
6975 eRet = OMX_ErrorNoMore;
6976 }
6977 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
6978 if ((0 == index) && role) {
6979 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
6980 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6981 } else {
6982 DEBUG_PRINT_LOW("No more roles");
6983 eRet = OMX_ErrorNoMore;
6984 }
6985 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
6986 if ((0 == index) && role) {
6987 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
6988 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
6989 } else {
6990 DEBUG_PRINT_LOW("No more roles");
6991 eRet = OMX_ErrorNoMore;
6992 }
6993 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
6994 if ((0 == index) && role) {
6995 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
6996 DEBUG_PRINT_LOW("component_role_enum: role %s", role);
6997 } else {
6998 DEBUG_PRINT_LOW("No more roles");
6999 eRet = OMX_ErrorNoMore;
7000 }
7001 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
7002 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
7003 ) {
7004 if ((0 == index) && role) {
7005 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
7006 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7007 } else {
7008 DEBUG_PRINT_LOW("No more roles");
7009 eRet = OMX_ErrorNoMore;
7010 }
7011 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7012 if ((0 == index) && role) {
7013 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7014 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7015 } else {
7016 DEBUG_PRINT_LOW("No more roles");
7017 eRet = OMX_ErrorNoMore;
7018 }
7019 } else {
7020 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7021 eRet = OMX_ErrorInvalidComponentName;
7022 }
7023 return eRet;
7024 }
7025
7026
7027
7028
7029 /* ======================================================================
7030 FUNCTION
7031 omx_vdec::AllocateDone
7032
7033 DESCRIPTION
7034 Checks if entire buffer pool is allocated by IL Client or not.
7035 Need this to move to IDLE state.
7036
7037 PARAMETERS
7038 None.
7039
7040 RETURN VALUE
7041 true/false.
7042
7043 ========================================================================== */
allocate_done(void)7044 bool omx_vdec::allocate_done(void)
7045 {
7046 bool bRet = false;
7047 bool bRet_In = false;
7048 bool bRet_Out = false;
7049
7050 bRet_In = allocate_input_done();
7051 bRet_Out = allocate_output_done();
7052
7053 if (bRet_In && bRet_Out) {
7054 bRet = true;
7055 }
7056
7057 return bRet;
7058 }
7059 /* ======================================================================
7060 FUNCTION
7061 omx_vdec::AllocateInputDone
7062
7063 DESCRIPTION
7064 Checks if I/P buffer pool is allocated by IL Client or not.
7065
7066 PARAMETERS
7067 None.
7068
7069 RETURN VALUE
7070 true/false.
7071
7072 ========================================================================== */
allocate_input_done(void)7073 bool omx_vdec::allocate_input_done(void)
7074 {
7075 bool bRet = false;
7076 unsigned i=0;
7077
7078 if (m_inp_mem_ptr == NULL) {
7079 return bRet;
7080 }
7081 if (m_inp_mem_ptr ) {
7082 for (; i<drv_ctx.ip_buf.actualcount; i++) {
7083 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7084 break;
7085 }
7086 }
7087 }
7088 if (i == drv_ctx.ip_buf.actualcount) {
7089 bRet = true;
7090 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
7091 }
7092 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7093 m_inp_bPopulated = OMX_TRUE;
7094 }
7095 return bRet;
7096 }
7097 /* ======================================================================
7098 FUNCTION
7099 omx_vdec::AllocateOutputDone
7100
7101 DESCRIPTION
7102 Checks if entire O/P buffer pool is allocated by IL Client or not.
7103
7104 PARAMETERS
7105 None.
7106
7107 RETURN VALUE
7108 true/false.
7109
7110 ========================================================================== */
allocate_output_done(void)7111 bool omx_vdec::allocate_output_done(void)
7112 {
7113 bool bRet = false;
7114 unsigned j=0;
7115
7116 if (m_out_mem_ptr == NULL) {
7117 return bRet;
7118 }
7119
7120 if (m_out_mem_ptr) {
7121 for (; j < drv_ctx.op_buf.actualcount; j++) {
7122 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7123 break;
7124 }
7125 }
7126 }
7127
7128 if (j == drv_ctx.op_buf.actualcount) {
7129 bRet = true;
7130 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
7131 if (m_out_bEnabled)
7132 m_out_bPopulated = OMX_TRUE;
7133 }
7134
7135 return bRet;
7136 }
7137
7138 /* ======================================================================
7139 FUNCTION
7140 omx_vdec::ReleaseDone
7141
7142 DESCRIPTION
7143 Checks if IL client has released all the buffers.
7144
7145 PARAMETERS
7146 None.
7147
7148 RETURN VALUE
7149 true/false
7150
7151 ========================================================================== */
release_done(void)7152 bool omx_vdec::release_done(void)
7153 {
7154 bool bRet = false;
7155
7156 if (release_input_done()) {
7157 if (release_output_done()) {
7158 bRet = true;
7159 }
7160 }
7161 return bRet;
7162 }
7163
7164
7165 /* ======================================================================
7166 FUNCTION
7167 omx_vdec::ReleaseOutputDone
7168
7169 DESCRIPTION
7170 Checks if IL client has released all the buffers.
7171
7172 PARAMETERS
7173 None.
7174
7175 RETURN VALUE
7176 true/false
7177
7178 ========================================================================== */
release_output_done(void)7179 bool omx_vdec::release_output_done(void)
7180 {
7181 bool bRet = false;
7182 unsigned i=0,j=0;
7183
7184 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
7185 if (m_out_mem_ptr) {
7186 for (; j < drv_ctx.op_buf.actualcount ; j++) {
7187 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
7188 break;
7189 }
7190 }
7191 if (j == drv_ctx.op_buf.actualcount) {
7192 m_out_bm_count = 0;
7193 bRet = true;
7194 }
7195 } else {
7196 m_out_bm_count = 0;
7197 bRet = true;
7198 }
7199 return bRet;
7200 }
7201 /* ======================================================================
7202 FUNCTION
7203 omx_vdec::ReleaseInputDone
7204
7205 DESCRIPTION
7206 Checks if IL client has released all the buffers.
7207
7208 PARAMETERS
7209 None.
7210
7211 RETURN VALUE
7212 true/false
7213
7214 ========================================================================== */
release_input_done(void)7215 bool omx_vdec::release_input_done(void)
7216 {
7217 bool bRet = false;
7218 unsigned i=0,j=0;
7219
7220 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
7221 if (m_inp_mem_ptr) {
7222 for (; j<drv_ctx.ip_buf.actualcount; j++) {
7223 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
7224 break;
7225 }
7226 }
7227 if (j==drv_ctx.ip_buf.actualcount) {
7228 bRet = true;
7229 }
7230 } else {
7231 bRet = true;
7232 }
7233 return bRet;
7234 }
7235
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7236 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
7237 OMX_BUFFERHEADERTYPE * buffer)
7238 {
7239 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
7240 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
7241 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
7242 return OMX_ErrorBadParameter;
7243 } else if (output_flush_progress) {
7244 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
7245 buffer->nFilledLen = 0;
7246 buffer->nTimeStamp = 0;
7247 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
7248 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7249 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
7250 }
7251
7252 if (m_debug_extradata) {
7253 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7254 DEBUG_PRINT_HIGH("***************************************************");
7255 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
7256 DEBUG_PRINT_HIGH("***************************************************");
7257 }
7258
7259 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
7260 DEBUG_PRINT_HIGH("***************************************************");
7261 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
7262 DEBUG_PRINT_HIGH("***************************************************");
7263 }
7264 }
7265
7266
7267 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
7268 buffer, buffer->pBuffer);
7269 pending_output_buffers --;
7270
7271 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7272 DEBUG_PRINT_HIGH("Output EOS has been reached");
7273 if (!output_flush_progress)
7274 post_event((unsigned)NULL, (unsigned)NULL,
7275 OMX_COMPONENT_GENERATE_EOS_DONE);
7276
7277 if (psource_frame) {
7278 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
7279 psource_frame = NULL;
7280 }
7281 if (pdest_frame) {
7282 pdest_frame->nFilledLen = 0;
7283 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
7284 (unsigned)NULL);
7285 pdest_frame = NULL;
7286 }
7287 }
7288
7289 if (!output_flush_progress && (buffer->nFilledLen > 0)) {
7290 DEBUG_PRINT_LOW("Processing extradata");
7291 handle_extradata(buffer);
7292 }
7293
7294 #ifdef OUTPUT_EXTRADATA_LOG
7295 if (outputExtradataFile) {
7296 int buf_index = buffer - m_out_mem_ptr;
7297 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
7298
7299 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
7300 p_extra = (OMX_OTHER_EXTRADATATYPE *)
7301 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
7302
7303 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
7304 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
7305 p_extra->nSize, p_extra->eType);
7306 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
7307
7308 if (p_extra->eType == OMX_ExtraDataNone) {
7309 break;
7310 }
7311 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7312 }
7313 }
7314 #endif
7315
7316 /* For use buffer we need to copy the data */
7317 if (!output_flush_progress) {
7318 /* This is the error check for non-recoverable errros */
7319 bool is_duplicate_ts_valid = true;
7320 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
7321
7322 if (output_capability == V4L2_PIX_FMT_MPEG4 ||
7323 output_capability == V4L2_PIX_FMT_MPEG2 ||
7324 output_capability == V4L2_PIX_FMT_DIVX ||
7325 output_capability == V4L2_PIX_FMT_DIVX_311)
7326 is_duplicate_ts_valid = false;
7327
7328 if ((output_capability == V4L2_PIX_FMT_H264 ||
7329 output_capability == V4L2_PIX_FMT_H264_MVC) &&
7330 is_interlaced) {
7331 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
7332 is_interlaced = false;
7333 }
7334 }
7335
7336 if (buffer->nFilledLen > 0) {
7337 time_stamp_dts.get_next_timestamp(buffer,
7338 is_interlaced && is_duplicate_ts_valid);
7339 if (m_debug_timestamp) {
7340 {
7341 OMX_TICKS expected_ts = 0;
7342 m_timestamp_list.pop_min_ts(expected_ts);
7343 if (is_interlaced && is_duplicate_ts_valid) {
7344 m_timestamp_list.pop_min_ts(expected_ts);
7345 }
7346 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
7347 buffer->nTimeStamp, expected_ts);
7348
7349 if (buffer->nTimeStamp != expected_ts) {
7350 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
7351 }
7352 }
7353 }
7354 }
7355 }
7356
7357 /* Since we're passing around handles, adjust nFilledLen and nAllocLen
7358 * to size of the handle. Do it _after_ handle_extradata() which
7359 * requires the respective sizes to be accurate. */
7360 if (dynamic_buf_mode) {
7361 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
7362 buffer->nFilledLen = buffer->nFilledLen ?
7363 sizeof(struct VideoDecoderOutputMetaData) : 0;
7364 }
7365 if (m_cb.FillBufferDone) {
7366 if (buffer->nFilledLen > 0) {
7367 if (arbitrary_bytes)
7368 adjust_timestamp(buffer->nTimeStamp);
7369 else
7370 set_frame_rate(buffer->nTimeStamp);
7371
7372 if (perf_flag) {
7373 if (!proc_frms) {
7374 dec_time.stop();
7375 latency = dec_time.processing_time_us() - latency;
7376 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
7377 dec_time.start();
7378 fps_metrics.start();
7379 }
7380 proc_frms++;
7381 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7382 OMX_U64 proc_time = 0;
7383 fps_metrics.stop();
7384 proc_time = fps_metrics.processing_time_us();
7385 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
7386 (unsigned int)proc_frms, (float)proc_time / 1e6,
7387 (float)(1e6 * proc_frms) / proc_time);
7388 proc_frms = 0;
7389 }
7390 }
7391 }
7392 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7393 prev_ts = LLONG_MAX;
7394 rst_prev_ts = true;
7395 }
7396
7397 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7398 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
7399 buffer->pPlatformPrivate)->entryList->entry;
7400 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
7401 OMX_BUFFERHEADERTYPE *il_buffer;
7402 il_buffer = client_buffers.get_il_buf_hdr(buffer);
7403
7404 if (il_buffer && m_last_rendered_TS >= 0) {
7405 int current_framerate = (int)(drv_ctx.frame_rate.fps_numerator /drv_ctx.frame_rate.fps_denominator);
7406 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
7407
7408 // Current frame can be send for rendering if
7409 // (a) current FPS is <= 60
7410 // (b) is the next frame after the frame with TS 0
7411 // (c) is the first frame after seek
7412 // (d) the delta TS b\w two consecutive frames is > 16 ms
7413 // (e) its TS is equal to previous frame TS
7414 // (f) if marked EOS
7415
7416 if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
7417 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
7418 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7419 m_last_rendered_TS = il_buffer->nTimeStamp;
7420 } else {
7421 //mark for droping
7422 buffer->nFilledLen = 0;
7423 }
7424
7425 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
7426 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
7427 il_buffer->nTimeStamp,ts_delta);
7428 }
7429
7430 if (il_buffer) {
7431 log_output_buffers(il_buffer);
7432 if (dynamic_buf_mode) {
7433 unsigned int nPortIndex = 0;
7434 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7435
7436 if (!secure_mode) {
7437 munmap(drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr,
7438 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size);
7439 }
7440
7441 //Clear graphic buffer handles in dynamic mode
7442 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7443 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7444 native_buffer[nPortIndex].privatehandle = NULL;
7445 native_buffer[nPortIndex].nativehandle = NULL;
7446 } else {
7447 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
7448 return OMX_ErrorBadParameter;
7449 }
7450 }
7451 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
7452 } else {
7453 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
7454 return OMX_ErrorBadParameter;
7455 }
7456 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
7457 } else {
7458 return OMX_ErrorBadParameter;
7459 }
7460
7461 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
7462 if (m_smoothstreaming_mode && m_out_mem_ptr) {
7463 OMX_U32 buf_index = buffer - m_out_mem_ptr;
7464 BufferDim_t dim;
7465 private_handle_t *private_handle = NULL;
7466 dim.sliceWidth = framesize.nWidth;
7467 dim.sliceHeight = framesize.nHeight;
7468 if (buf_index < drv_ctx.op_buf.actualcount &&
7469 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
7470 native_buffer[buf_index].privatehandle)
7471 private_handle = native_buffer[buf_index].privatehandle;
7472 if (private_handle) {
7473 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
7474 dim.sliceWidth, dim.sliceHeight);
7475 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
7476 }
7477 }
7478 #endif
7479
7480 return OMX_ErrorNone;
7481 }
7482
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7483 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
7484 OMX_BUFFERHEADERTYPE* buffer)
7485 {
7486
7487 if (buffer == NULL || ((buffer - m_inp_mem_ptr) >= (int)drv_ctx.ip_buf.actualcount)) {
7488 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
7489 return OMX_ErrorBadParameter;
7490 }
7491
7492 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = %x",
7493 buffer, buffer->pBuffer, buffer->nFlags);
7494 pending_input_buffers--;
7495
7496 if (arbitrary_bytes) {
7497 if (pdest_frame == NULL && input_flush_progress == false) {
7498 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
7499 pdest_frame = buffer;
7500 buffer->nFilledLen = 0;
7501 buffer->nTimeStamp = LLONG_MAX;
7502 push_input_buffer (hComp);
7503 } else {
7504 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
7505 buffer->nFilledLen = 0;
7506 if (!m_input_free_q.insert_entry((unsigned long)buffer,
7507 (unsigned)NULL, (unsigned)NULL)) {
7508 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
7509 }
7510 }
7511 } else if (m_cb.EmptyBufferDone) {
7512 buffer->nFilledLen = 0;
7513 if (input_use_buffer == true) {
7514 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
7515 }
7516 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
7517 }
7518 return OMX_ErrorNone;
7519 }
7520
async_message_process(void * context,void * message)7521 int omx_vdec::async_message_process (void *context, void* message)
7522 {
7523 omx_vdec* omx = NULL;
7524 struct vdec_msginfo *vdec_msg = NULL;
7525 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
7526 struct v4l2_buffer *v4l2_buf_ptr = NULL;
7527 struct vdec_output_frameinfo *output_respbuf = NULL;
7528 int rc=1;
7529 if (context == NULL || message == NULL) {
7530 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
7531 return -1;
7532 }
7533 vdec_msg = (struct vdec_msginfo *)message;
7534
7535 omx = reinterpret_cast<omx_vdec*>(context);
7536
7537 switch (vdec_msg->msgcode) {
7538
7539 case VDEC_MSG_EVT_HW_ERROR:
7540 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7541 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
7542 break;
7543
7544 case VDEC_MSG_EVT_HW_OVERLOAD:
7545 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7546 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
7547 break;
7548
7549 case VDEC_MSG_EVT_HW_UNSUPPORTED:
7550 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7551 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
7552 break;
7553
7554 case VDEC_MSG_RESP_START_DONE:
7555 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7556 OMX_COMPONENT_GENERATE_START_DONE);
7557 break;
7558
7559 case VDEC_MSG_RESP_STOP_DONE:
7560 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7561 OMX_COMPONENT_GENERATE_STOP_DONE);
7562 break;
7563
7564 case VDEC_MSG_RESP_RESUME_DONE:
7565 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7566 OMX_COMPONENT_GENERATE_RESUME_DONE);
7567 break;
7568
7569 case VDEC_MSG_RESP_PAUSE_DONE:
7570 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7571 OMX_COMPONENT_GENERATE_PAUSE_DONE);
7572 break;
7573
7574 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
7575 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7576 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
7577 break;
7578 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
7579 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
7580 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
7581 break;
7582 case VDEC_MSG_RESP_INPUT_FLUSHED:
7583 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
7584
7585 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
7586 vdec_msg->msgdata.input_frame_clientdata; */
7587
7588 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
7589 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index;
7590 if (omxhdr == NULL ||
7591 ((omxhdr - omx->m_inp_mem_ptr) > (int)omx->drv_ctx.ip_buf.actualcount) ) {
7592 omxhdr = NULL;
7593 vdec_msg->status_code = VDEC_S_EFATAL;
7594 break;
7595 }
7596 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
7597 DEBUG_PRINT_HIGH("Unsupported input");
7598 omx->omx_report_error ();
7599 }
7600 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
7601 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
7602 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
7603 }
7604 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7605
7606 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
7607 android_atomic_dec(&omx->m_queued_codec_config_count);
7608 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
7609 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
7610 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
7611 sem_post(&omx->m_safe_flush);
7612 }
7613 }
7614
7615 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
7616 OMX_COMPONENT_GENERATE_EBD);
7617 break;
7618 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
7619 int64_t *timestamp;
7620 timestamp = (int64_t *) malloc(sizeof(int64_t));
7621 if (timestamp) {
7622 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
7623 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
7624 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
7625 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
7626 (long long)vdec_msg->msgdata.output_frame.time_stamp);
7627 }
7628 break;
7629 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
7630 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
7631
7632 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
7633 omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index;
7634
7635 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
7636 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
7637 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
7638 (unsigned int)vdec_msg->msgdata.output_frame.len,
7639 vdec_msg->msgdata.output_frame.framesize.left,
7640 vdec_msg->msgdata.output_frame.framesize.top,
7641 vdec_msg->msgdata.output_frame.framesize.right,
7642 vdec_msg->msgdata.output_frame.framesize.bottom);
7643
7644 if (omxhdr && omxhdr->pOutputPortPrivate &&
7645 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
7646 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
7647 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
7648
7649 if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
7650 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
7651 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
7652 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
7653 omxhdr->nFlags = 0;
7654
7655 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
7656 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
7657 //rc = -1;
7658 }
7659 if (omxhdr->nFilledLen) {
7660 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
7661 }
7662 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
7663 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
7664 } else {
7665 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
7666 }
7667 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
7668 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7669 }
7670 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
7671 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
7672 }
7673
7674 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
7675 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
7676 }
7677
7678 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
7679 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
7680 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
7681 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
7682 }
7683
7684 if (omx->dynamic_buf_mode && !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY)) {
7685 omx->buf_ref_remove(omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
7686 omxhdr->nOffset);
7687 }
7688 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
7689 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
7690 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
7691 omx->time_stamp_dts.remove_time_stamp(
7692 omxhdr->nTimeStamp,
7693 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
7694 ?true:false);
7695 omx->post_event ((unsigned long)NULL,(unsigned long)omxhdr,
7696 OMX_COMPONENT_GENERATE_FTB);
7697 break;
7698 }
7699 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
7700 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
7701 }
7702 vdec_msg->msgdata.output_frame.bufferaddr =
7703 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
7704
7705 /* Post event if resolution OR crop changed */
7706 /* filled length will be changed if resolution changed */
7707 /* Crop parameters can be changed even without resolution change */
7708 if (omxhdr->nFilledLen
7709 && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
7710 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
7711 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
7712 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
7713 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
7714 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
7715 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
7716
7717 DEBUG_PRINT_HIGH("Paramters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
7718 omx->prev_n_filled_len,
7719 omx->drv_ctx.video_resolution.frame_width,
7720 omx->drv_ctx.video_resolution.frame_height,
7721 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
7722 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
7723 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
7724 vdec_msg->msgdata.output_frame.picsize.frame_height,
7725 vdec_msg->msgdata.output_frame.framesize.left,
7726 vdec_msg->msgdata.output_frame.framesize.top,
7727 vdec_msg->msgdata.output_frame.framesize.right,
7728 vdec_msg->msgdata.output_frame.framesize.bottom);
7729
7730 omx->drv_ctx.video_resolution.frame_width =
7731 vdec_msg->msgdata.output_frame.picsize.frame_width;
7732 omx->drv_ctx.video_resolution.frame_height =
7733 vdec_msg->msgdata.output_frame.picsize.frame_height;
7734 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
7735 omx->drv_ctx.video_resolution.stride =
7736 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
7737 omx->drv_ctx.video_resolution.scan_lines =
7738 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
7739 }
7740 memcpy(&omx->drv_ctx.frame_size,
7741 &vdec_msg->msgdata.output_frame.framesize,
7742 sizeof(struct vdec_framesize));
7743
7744 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
7745 OMX_IndexConfigCommonOutputCrop,
7746 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
7747 }
7748
7749 if (omxhdr->nFilledLen)
7750 omx->prev_n_filled_len = omxhdr->nFilledLen;
7751
7752 output_respbuf = (struct vdec_output_frameinfo *)\
7753 omxhdr->pOutputPortPrivate;
7754 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
7755 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
7756 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
7757 output_respbuf->pic_type = PICTURE_TYPE_I;
7758 }
7759 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
7760 output_respbuf->pic_type = PICTURE_TYPE_P;
7761 }
7762 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
7763 output_respbuf->pic_type = PICTURE_TYPE_B;
7764 }
7765
7766 if (!omx->m_enable_android_native_buffers && omx->output_use_buffer)
7767 memcpy ( omxhdr->pBuffer, (void *)
7768 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
7769 (unsigned long)vdec_msg->msgdata.output_frame.offset),
7770 vdec_msg->msgdata.output_frame.len);
7771 } else {
7772 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
7773 (unsigned int)vdec_msg->msgdata.output_frame.len,
7774 omxhdr->nAllocLen, omx->prev_n_filled_len);
7775 omxhdr->nFilledLen = 0;
7776 }
7777
7778 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
7779 OMX_COMPONENT_GENERATE_FBD);
7780
7781 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
7782 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
7783 OMX_COMPONENT_GENERATE_EOS_DONE);
7784 } else {
7785 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
7786 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
7787 }
7788 break;
7789 case VDEC_MSG_EVT_CONFIG_CHANGED:
7790 DEBUG_PRINT_HIGH("Port settings changed");
7791 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
7792 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
7793 break;
7794 default:
7795 break;
7796 }
7797 return rc;
7798 }
7799
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)7800 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
7801 OMX_HANDLETYPE hComp,
7802 OMX_BUFFERHEADERTYPE *buffer
7803 )
7804 {
7805 unsigned address,p2,id;
7806 DEBUG_PRINT_LOW("Empty this arbitrary");
7807
7808 if (buffer == NULL) {
7809 return OMX_ErrorBadParameter;
7810 }
7811 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7812 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
7813 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
7814
7815 /* return zero length and not an EOS buffer */
7816 /* return buffer if input flush in progress */
7817 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
7818 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
7819 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
7820 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
7821 return OMX_ErrorNone;
7822 }
7823
7824 if (psource_frame == NULL) {
7825 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
7826 psource_frame = buffer;
7827 DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
7828 push_input_buffer (hComp);
7829 } else {
7830 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
7831 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
7832 (unsigned)NULL)) {
7833 return OMX_ErrorBadParameter;
7834 }
7835 }
7836
7837 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7838 codec_config_flag = false;
7839 }
7840 return OMX_ErrorNone;
7841 }
7842
push_input_buffer(OMX_HANDLETYPE hComp)7843 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
7844 {
7845 unsigned long address,p2,id;
7846 OMX_ERRORTYPE ret = OMX_ErrorNone;
7847
7848 if (pdest_frame == NULL || psource_frame == NULL) {
7849 /*Check if we have a destination buffer*/
7850 if (pdest_frame == NULL) {
7851 DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
7852 if (m_input_free_q.m_size) {
7853 m_input_free_q.pop_entry(&address,&p2,&id);
7854 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
7855 pdest_frame->nFilledLen = 0;
7856 pdest_frame->nTimeStamp = LLONG_MAX;
7857 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
7858 }
7859 }
7860
7861 /*Check if we have a destination buffer*/
7862 if (psource_frame == NULL) {
7863 DEBUG_PRINT_LOW("Get a source buffer from the queue");
7864 if (m_input_pending_q.m_size) {
7865 m_input_pending_q.pop_entry(&address,&p2,&id);
7866 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
7867 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
7868 psource_frame->nTimeStamp);
7869 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
7870 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
7871
7872 }
7873 }
7874
7875 }
7876
7877 while ((pdest_frame != NULL) && (psource_frame != NULL)) {
7878 switch (codec_type_parse) {
7879 case CODEC_TYPE_MPEG4:
7880 case CODEC_TYPE_H263:
7881 case CODEC_TYPE_MPEG2:
7882 ret = push_input_sc_codec(hComp);
7883 break;
7884 case CODEC_TYPE_H264:
7885 ret = push_input_h264(hComp);
7886 break;
7887 case CODEC_TYPE_HEVC:
7888 ret = push_input_hevc(hComp);
7889 break;
7890 case CODEC_TYPE_VC1:
7891 ret = push_input_vc1(hComp);
7892 break;
7893 default:
7894 break;
7895 }
7896 if (ret != OMX_ErrorNone) {
7897 DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
7898 omx_report_error ();
7899 break;
7900 }
7901 }
7902
7903 return ret;
7904 }
7905
push_input_sc_codec(OMX_HANDLETYPE hComp)7906 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
7907 {
7908 OMX_U32 partial_frame = 1;
7909 OMX_BOOL generate_ebd = OMX_TRUE;
7910 unsigned long address = 0, p2 = 0, id = 0;
7911
7912 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
7913 psource_frame,psource_frame->nTimeStamp);
7914 if (m_frame_parser.parse_sc_frame(psource_frame,
7915 pdest_frame,&partial_frame) == -1) {
7916 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
7917 return OMX_ErrorBadParameter;
7918 }
7919
7920 if (partial_frame == 0) {
7921 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
7922 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
7923
7924
7925 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
7926 /*First Parsed buffer will have only header Hence skip*/
7927 if (frame_count == 0) {
7928 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
7929
7930 if (codec_type_parse == CODEC_TYPE_MPEG4 ||
7931 codec_type_parse == CODEC_TYPE_DIVX) {
7932 mp4StreamType psBits;
7933 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
7934 psBits.numBytes = pdest_frame->nFilledLen;
7935 mp4_headerparser.parseHeader(&psBits);
7936 }
7937
7938 frame_count++;
7939 } else {
7940 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
7941 if (pdest_frame->nFilledLen) {
7942 /*Push the frame to the Decoder*/
7943 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
7944 return OMX_ErrorBadParameter;
7945 }
7946 frame_count++;
7947 pdest_frame = NULL;
7948
7949 if (m_input_free_q.m_size) {
7950 m_input_free_q.pop_entry(&address,&p2,&id);
7951 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
7952 pdest_frame->nFilledLen = 0;
7953 }
7954 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
7955 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
7956 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
7957 (unsigned)NULL);
7958 pdest_frame = NULL;
7959 }
7960 }
7961 } else {
7962 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
7963 /*Check if Destination Buffer is full*/
7964 if (pdest_frame->nAllocLen ==
7965 pdest_frame->nFilledLen + pdest_frame->nOffset) {
7966 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
7967 return OMX_ErrorStreamCorrupt;
7968 }
7969 }
7970
7971 if (psource_frame->nFilledLen == 0) {
7972 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
7973 if (pdest_frame) {
7974 pdest_frame->nFlags |= psource_frame->nFlags;
7975 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
7976 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
7977 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
7978 (unsigned int)pdest_frame->nFilledLen,frame_count++);
7979 /*Push the frame to the Decoder*/
7980 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
7981 return OMX_ErrorBadParameter;
7982 }
7983 frame_count++;
7984 pdest_frame = NULL;
7985 } else {
7986 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
7987 generate_ebd = OMX_FALSE;
7988 }
7989 }
7990 if (generate_ebd) {
7991 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
7992 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
7993 psource_frame = NULL;
7994
7995 if (m_input_pending_q.m_size) {
7996 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
7997 m_input_pending_q.pop_entry(&address,&p2,&id);
7998 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
7999 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8000 psource_frame->nTimeStamp);
8001 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8002 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8003 }
8004 }
8005 }
8006 return OMX_ErrorNone;
8007 }
8008
push_input_h264(OMX_HANDLETYPE hComp)8009 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
8010 {
8011 OMX_U32 partial_frame = 1;
8012 unsigned long address = 0, p2 = 0, id = 0;
8013 OMX_BOOL isNewFrame = OMX_FALSE;
8014 OMX_BOOL generate_ebd = OMX_TRUE;
8015
8016 if (h264_scratch.pBuffer == NULL) {
8017 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
8018 return OMX_ErrorBadParameter;
8019 }
8020 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
8021 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
8022 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
8023 if (h264_scratch.nFilledLen && look_ahead_nal) {
8024 look_ahead_nal = false;
8025 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8026 h264_scratch.nFilledLen) {
8027 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8028 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8029 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8030 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
8031 h264_scratch.nFilledLen = 0;
8032 } else {
8033 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
8034 return OMX_ErrorBadParameter;
8035 }
8036 }
8037
8038 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
8039 in EOS flag getting associated with the destination
8040 */
8041 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
8042 pdest_frame->nFilledLen) {
8043 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
8044 generate_ebd = OMX_FALSE;
8045 }
8046
8047 if (nal_length == 0) {
8048 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
8049 if (m_frame_parser.parse_sc_frame(psource_frame,
8050 &h264_scratch,&partial_frame) == -1) {
8051 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8052 return OMX_ErrorBadParameter;
8053 }
8054 } else {
8055 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
8056 if (m_frame_parser.parse_h264_nallength(psource_frame,
8057 &h264_scratch,&partial_frame) == -1) {
8058 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
8059 return OMX_ErrorBadParameter;
8060 }
8061 }
8062
8063 if (partial_frame == 0) {
8064 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
8065 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
8066 nal_count++;
8067 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
8068 h264_scratch.nFlags = psource_frame->nFlags;
8069 } else {
8070 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
8071 if (h264_scratch.nFilledLen) {
8072 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
8073 NALU_TYPE_SPS);
8074 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8075 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
8076 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8077 h264_scratch.nFilledLen, NALU_TYPE_SEI);
8078 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8079 // If timeinfo is present frame info from SEI is already processed
8080 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
8081 h264_scratch.nFilledLen, NALU_TYPE_SEI);
8082 #endif
8083 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8084 nal_count++;
8085 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
8086 pdest_frame->nTimeStamp = h264_last_au_ts;
8087 pdest_frame->nFlags = h264_last_au_flags;
8088 #ifdef PANSCAN_HDLR
8089 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
8090 h264_parser->update_panscan_data(h264_last_au_ts);
8091 #endif
8092 }
8093 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
8094 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
8095 h264_last_au_ts = h264_scratch.nTimeStamp;
8096 h264_last_au_flags = h264_scratch.nFlags;
8097 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8098 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
8099 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
8100 if (!VALID_TS(h264_last_au_ts))
8101 h264_last_au_ts = ts_in_sei;
8102 }
8103 #endif
8104 } else
8105 h264_last_au_ts = LLONG_MAX;
8106 }
8107
8108 if (!isNewFrame) {
8109 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8110 h264_scratch.nFilledLen) {
8111 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
8112 (unsigned int)h264_scratch.nFilledLen);
8113 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8114 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8115 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8116 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
8117 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8118 h264_scratch.nFilledLen = 0;
8119 } else {
8120 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
8121 return OMX_ErrorBadParameter;
8122 }
8123 } else if(h264_scratch.nFilledLen) {
8124 look_ahead_nal = true;
8125 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
8126 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8127 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8128 (unsigned int)pdest_frame->nFilledLen,frame_count++);
8129
8130 if (pdest_frame->nFilledLen == 0) {
8131 DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
8132 look_ahead_nal = false;
8133 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8134 h264_scratch.nFilledLen) {
8135 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8136 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8137 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8138 h264_scratch.nFilledLen = 0;
8139 } else {
8140 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
8141 return OMX_ErrorBadParameter;
8142 }
8143 } else {
8144 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
8145 DEBUG_PRINT_LOW("Reset the EOS Flag");
8146 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8147 }
8148 /*Push the frame to the Decoder*/
8149 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8150 return OMX_ErrorBadParameter;
8151 }
8152 //frame_count++;
8153 pdest_frame = NULL;
8154 if (m_input_free_q.m_size) {
8155 m_input_free_q.pop_entry(&address,&p2,&id);
8156 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8157 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
8158 pdest_frame->nFilledLen = 0;
8159 pdest_frame->nFlags = 0;
8160 pdest_frame->nTimeStamp = LLONG_MAX;
8161 }
8162 }
8163 }
8164 }
8165 } else {
8166 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
8167 /*Check if Destination Buffer is full*/
8168 if (h264_scratch.nAllocLen ==
8169 h264_scratch.nFilledLen + h264_scratch.nOffset) {
8170 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
8171 return OMX_ErrorStreamCorrupt;
8172 }
8173 }
8174
8175 if (!psource_frame->nFilledLen) {
8176 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
8177
8178 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8179 if (pdest_frame) {
8180 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
8181 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8182 h264_scratch.nFilledLen) {
8183 if(pdest_frame->nFilledLen == 0) {
8184 /* No residual frame from before, send whatever
8185 * we have left */
8186 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8187 h264_scratch.pBuffer, h264_scratch.nFilledLen);
8188 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8189 h264_scratch.nFilledLen = 0;
8190 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
8191 } else {
8192 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
8193 if(!isNewFrame) {
8194 /* Have a residual frame, but we know that the
8195 * AU in this frame is belonging to whatever
8196 * frame we had left over. So append it */
8197 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8198 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8199 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8200 h264_scratch.nFilledLen = 0;
8201 if (h264_last_au_ts != LLONG_MAX)
8202 pdest_frame->nTimeStamp = h264_last_au_ts;
8203 } else {
8204 /* Completely new frame, let's just push what
8205 * we have now. The resulting EBD would trigger
8206 * another push */
8207 generate_ebd = OMX_FALSE;
8208 pdest_frame->nTimeStamp = h264_last_au_ts;
8209 h264_last_au_ts = h264_scratch.nTimeStamp;
8210 }
8211 }
8212 } else {
8213 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
8214 return OMX_ErrorBadParameter;
8215 }
8216
8217 /* Iff we coalesced two buffers, inherit the flags of both bufs */
8218 if(generate_ebd == OMX_TRUE) {
8219 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
8220 }
8221
8222 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
8223 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8224 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
8225 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8226 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
8227 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
8228 if (!VALID_TS(pdest_frame->nTimeStamp))
8229 pdest_frame->nTimeStamp = ts_in_sei;
8230 }
8231 #endif
8232 /*Push the frame to the Decoder*/
8233 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8234 return OMX_ErrorBadParameter;
8235 }
8236 frame_count++;
8237 pdest_frame = NULL;
8238 } else {
8239 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
8240 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
8241 generate_ebd = OMX_FALSE;
8242 }
8243 }
8244 }
8245 if (generate_ebd && !psource_frame->nFilledLen) {
8246 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8247 psource_frame = NULL;
8248 if (m_input_pending_q.m_size) {
8249 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8250 m_input_pending_q.pop_entry(&address,&p2,&id);
8251 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8252 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
8253 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8254 }
8255 }
8256 return OMX_ErrorNone;
8257 }
8258
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)8259 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
8260 {
8261 OMX_ERRORTYPE rc = OMX_ErrorNone;
8262 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
8263 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
8264 if (pDst->nTimeStamp == LLONG_MAX) {
8265 pDst->nTimeStamp = pSrc->nTimeStamp;
8266 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
8267 }
8268 pDst->nFilledLen += pSrc->nFilledLen;
8269 pSrc->nFilledLen = 0;
8270 } else {
8271 DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
8272 rc = OMX_ErrorBadParameter;
8273 }
8274 return rc;
8275 }
8276
push_input_hevc(OMX_HANDLETYPE hComp)8277 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
8278 {
8279 OMX_U32 partial_frame = 1;
8280 unsigned long address,p2,id;
8281 OMX_BOOL isNewFrame = OMX_FALSE;
8282 OMX_BOOL generate_ebd = OMX_TRUE;
8283 OMX_ERRORTYPE rc = OMX_ErrorNone;
8284 if (h264_scratch.pBuffer == NULL) {
8285 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
8286 return OMX_ErrorBadParameter;
8287 }
8288
8289 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
8290 pdest_frame nFilledLen %u nTimeStamp %lld",
8291 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
8292
8293 if (h264_scratch.nFilledLen && look_ahead_nal) {
8294 look_ahead_nal = false;
8295 rc = copy_buffer(pdest_frame, &h264_scratch);
8296 if (rc != OMX_ErrorNone) {
8297 return rc;
8298 }
8299 }
8300
8301 if (nal_length == 0) {
8302 if (m_frame_parser.parse_sc_frame(psource_frame,
8303 &h264_scratch,&partial_frame) == -1) {
8304 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8305 return OMX_ErrorBadParameter;
8306 }
8307 } else {
8308 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
8309 if (m_frame_parser.parse_h264_nallength(psource_frame,
8310 &h264_scratch,&partial_frame) == -1) {
8311 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
8312 return OMX_ErrorBadParameter;
8313 }
8314 }
8315
8316 if (partial_frame == 0) {
8317 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
8318 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
8319 nal_count++;
8320 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
8321 h264_scratch.nFlags = psource_frame->nFlags;
8322 } else {
8323 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
8324 if (h264_scratch.nFilledLen) {
8325 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
8326 nal_count++;
8327 }
8328
8329 if (!isNewFrame) {
8330 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
8331 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
8332 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
8333 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
8334 rc = copy_buffer(pdest_frame, &h264_scratch);
8335 if (rc != OMX_ErrorNone) {
8336 return rc;
8337 }
8338 } else {
8339 look_ahead_nal = true;
8340 if (pdest_frame->nFilledLen == 0) {
8341 look_ahead_nal = false;
8342 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
8343 rc = copy_buffer(pdest_frame, &h264_scratch);
8344 if (rc != OMX_ErrorNone) {
8345 return OMX_ErrorBadParameter;
8346 }
8347 } else {
8348 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
8349 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8350 }
8351 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
8352 nTimeStamp %lld, look_ahead_nal in h264_scratch \
8353 nFilledLen %u nTimeStamp %lld",
8354 frame_count++, (unsigned int)pdest_frame->nFilledLen,
8355 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
8356 h264_scratch.nTimeStamp);
8357 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
8358 return OMX_ErrorBadParameter;
8359 }
8360 pdest_frame = NULL;
8361 if (m_input_free_q.m_size) {
8362 m_input_free_q.pop_entry(&address, &p2, &id);
8363 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8364 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
8365 pdest_frame->nFilledLen = 0;
8366 pdest_frame->nFlags = 0;
8367 pdest_frame->nTimeStamp = LLONG_MAX;
8368 }
8369 }
8370 }
8371 }
8372 } else {
8373 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
8374 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
8375 nFilledLen %u nTimeStamp %lld",
8376 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
8377 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
8378 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
8379
8380 if (h264_scratch.nAllocLen ==
8381 h264_scratch.nFilledLen + h264_scratch.nOffset) {
8382 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
8383 return OMX_ErrorStreamCorrupt;
8384 }
8385 }
8386
8387 if (!psource_frame->nFilledLen) {
8388 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
8389 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8390 if (pdest_frame) {
8391 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
8392 rc = copy_buffer(pdest_frame, &h264_scratch);
8393 if ( rc != OMX_ErrorNone ) {
8394 return rc;
8395 }
8396 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
8397 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
8398 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
8399 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
8400 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
8401 return OMX_ErrorBadParameter;
8402 }
8403 frame_count++;
8404 pdest_frame = NULL;
8405 } else {
8406 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
8407 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
8408 generate_ebd = OMX_FALSE;
8409 }
8410 }
8411 }
8412
8413 if (generate_ebd && !psource_frame->nFilledLen) {
8414 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
8415 psource_frame = NULL;
8416 if (m_input_pending_q.m_size) {
8417 m_input_pending_q.pop_entry(&address, &p2, &id);
8418 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
8419 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
8420 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
8421 }
8422 }
8423 return OMX_ErrorNone;
8424 }
8425
push_input_vc1(OMX_HANDLETYPE hComp)8426 OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
8427 {
8428 OMX_U8 *buf, *pdest;
8429 OMX_U32 partial_frame = 1;
8430 OMX_U32 buf_len, dest_len;
8431
8432 if (first_frame == 0) {
8433 first_frame = 1;
8434 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
8435 if (!m_vendor_config.pData) {
8436 DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
8437 buf = psource_frame->pBuffer;
8438 buf_len = psource_frame->nFilledLen;
8439
8440 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
8441 VC1_SP_MP_START_CODE) {
8442 m_vc1_profile = VC1_SP_MP_RCV;
8443 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
8444 m_vc1_profile = VC1_AP;
8445 } else {
8446 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
8447 return OMX_ErrorStreamCorrupt;
8448 }
8449 } else {
8450 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
8451 pdest_frame->nOffset;
8452 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
8453 pdest_frame->nOffset);
8454
8455 if (dest_len < m_vendor_config.nDataSize) {
8456 DEBUG_PRINT_ERROR("Destination buffer full");
8457 return OMX_ErrorBadParameter;
8458 } else {
8459 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
8460 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
8461 }
8462 }
8463 }
8464
8465 switch (m_vc1_profile) {
8466 case VC1_AP:
8467 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
8468 if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
8469 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
8470 return OMX_ErrorBadParameter;
8471 }
8472 break;
8473
8474 case VC1_SP_MP_RCV:
8475 default:
8476 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
8477 return OMX_ErrorBadParameter;
8478 }
8479 return OMX_ErrorNone;
8480 }
8481
8482 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)8483 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
8484 OMX_U32 alignment)
8485 {
8486 struct pmem_allocation allocation;
8487 allocation.size = buffer_size;
8488 allocation.align = clip2(alignment);
8489 if (allocation.align < 4096) {
8490 allocation.align = 4096;
8491 }
8492 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
8493 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
8494 allocation.align, allocation.size);
8495 return false;
8496 }
8497 return true;
8498 }
8499 #endif
8500 #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)8501 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
8502 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
8503 struct ion_fd_data *fd_data, int flag)
8504 {
8505 int fd = -EINVAL;
8506 int rc = -EINVAL;
8507 int ion_dev_flag;
8508 struct vdec_ion ion_buf_info;
8509 if (!alloc_data || buffer_size <= 0 || !fd_data) {
8510 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
8511 return -EINVAL;
8512 }
8513 ion_dev_flag = O_RDONLY;
8514 fd = open (MEM_DEVICE, ion_dev_flag);
8515 if (fd < 0) {
8516 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
8517 return fd;
8518 }
8519 alloc_data->flags = 0;
8520 if (!secure_mode && (flag & ION_FLAG_CACHED)) {
8521 alloc_data->flags |= ION_FLAG_CACHED;
8522 }
8523 alloc_data->len = buffer_size;
8524 alloc_data->align = clip2(alignment);
8525 if (alloc_data->align < 4096) {
8526 alloc_data->align = 4096;
8527 }
8528 if ((secure_mode) && (flag & ION_SECURE))
8529 alloc_data->flags |= ION_SECURE;
8530
8531 alloc_data->ION_HEAP_MASK = ION_HEAP(ION_IOMMU_HEAP_ID);
8532 if (secure_mode && (alloc_data->flags & ION_SECURE))
8533 alloc_data->ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID);
8534 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
8535 if (rc || !alloc_data->handle) {
8536 DEBUG_PRINT_ERROR("ION ALLOC memory failed");
8537 alloc_data->handle = 0;
8538 close(fd);
8539 fd = -ENOMEM;
8540 return fd;
8541 }
8542 fd_data->handle = alloc_data->handle;
8543 rc = ioctl(fd,ION_IOC_MAP,fd_data);
8544 if (rc) {
8545 DEBUG_PRINT_ERROR("ION MAP failed ");
8546 ion_buf_info.ion_alloc_data = *alloc_data;
8547 ion_buf_info.ion_device_fd = fd;
8548 ion_buf_info.fd_ion_data = *fd_data;
8549 free_ion_memory(&ion_buf_info);
8550 fd_data->fd =-1;
8551 fd = -ENOMEM;
8552 }
8553
8554 return fd;
8555 }
8556
free_ion_memory(struct vdec_ion * buf_ion_info)8557 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
8558 {
8559
8560 if (!buf_ion_info) {
8561 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
8562 return;
8563 }
8564 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
8565 &buf_ion_info->ion_alloc_data.handle)) {
8566 DEBUG_PRINT_ERROR("ION: free failed" );
8567 }
8568 close(buf_ion_info->ion_device_fd);
8569 buf_ion_info->ion_device_fd = -1;
8570 buf_ion_info->ion_alloc_data.handle = 0;
8571 buf_ion_info->fd_ion_data.fd = -1;
8572 }
8573 #endif
free_output_buffer_header()8574 void omx_vdec::free_output_buffer_header()
8575 {
8576 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
8577 output_use_buffer = false;
8578 ouput_egl_buffers = false;
8579
8580 if (m_out_mem_ptr) {
8581 free (m_out_mem_ptr);
8582 m_out_mem_ptr = NULL;
8583 }
8584
8585 if (m_platform_list) {
8586 free(m_platform_list);
8587 m_platform_list = NULL;
8588 }
8589
8590 if (drv_ctx.ptr_respbuffer) {
8591 free (drv_ctx.ptr_respbuffer);
8592 drv_ctx.ptr_respbuffer = NULL;
8593 }
8594 if (drv_ctx.ptr_outputbuffer) {
8595 free (drv_ctx.ptr_outputbuffer);
8596 drv_ctx.ptr_outputbuffer = NULL;
8597 }
8598 #ifdef USE_ION
8599 if (drv_ctx.op_buf_ion_info) {
8600 DEBUG_PRINT_LOW("Free o/p ion context");
8601 free(drv_ctx.op_buf_ion_info);
8602 drv_ctx.op_buf_ion_info = NULL;
8603 }
8604 #endif
8605 if (out_dynamic_list) {
8606 free(out_dynamic_list);
8607 out_dynamic_list = NULL;
8608 }
8609 }
8610
free_input_buffer_header()8611 void omx_vdec::free_input_buffer_header()
8612 {
8613 input_use_buffer = false;
8614 if (arbitrary_bytes) {
8615 if (m_inp_heap_ptr) {
8616 DEBUG_PRINT_LOW("Free input Heap Pointer");
8617 free (m_inp_heap_ptr);
8618 m_inp_heap_ptr = NULL;
8619 }
8620
8621 if (m_phdr_pmem_ptr) {
8622 DEBUG_PRINT_LOW("Free input pmem header Pointer");
8623 free (m_phdr_pmem_ptr);
8624 m_phdr_pmem_ptr = NULL;
8625 }
8626 }
8627 if (m_inp_mem_ptr) {
8628 DEBUG_PRINT_LOW("Free input pmem Pointer area");
8629 free (m_inp_mem_ptr);
8630 m_inp_mem_ptr = NULL;
8631 }
8632 /* We just freed all the buffer headers, every thing in m_input_free_q,
8633 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
8634 while (m_input_free_q.m_size) {
8635 unsigned long address, p2, id;
8636 m_input_free_q.pop_entry(&address, &p2, &id);
8637 }
8638 while (m_input_pending_q.m_size) {
8639 unsigned long address, p2, id;
8640 m_input_pending_q.pop_entry(&address, &p2, &id);
8641 }
8642 pdest_frame = NULL;
8643 psource_frame = NULL;
8644 if (drv_ctx.ptr_inputbuffer) {
8645 DEBUG_PRINT_LOW("Free Driver Context pointer");
8646 free (drv_ctx.ptr_inputbuffer);
8647 drv_ctx.ptr_inputbuffer = NULL;
8648 }
8649 #ifdef USE_ION
8650 if (drv_ctx.ip_buf_ion_info) {
8651 DEBUG_PRINT_LOW("Free ion context");
8652 free(drv_ctx.ip_buf_ion_info);
8653 drv_ctx.ip_buf_ion_info = NULL;
8654 }
8655 #endif
8656 }
8657
stream_off(OMX_U32 port)8658 int omx_vdec::stream_off(OMX_U32 port)
8659 {
8660 enum v4l2_buf_type btype;
8661 int rc = 0;
8662 enum v4l2_ports v4l2_port = OUTPUT_PORT;
8663
8664 if (port == OMX_CORE_INPUT_PORT_INDEX) {
8665 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8666 v4l2_port = OUTPUT_PORT;
8667 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
8668 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8669 v4l2_port = CAPTURE_PORT;
8670 } else if (port == OMX_ALL) {
8671 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
8672 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
8673
8674 if (!rc_input)
8675 return rc_input;
8676 else
8677 return rc_output;
8678 }
8679
8680 if (!streaming[v4l2_port]) {
8681 // already streamed off, warn and move on
8682 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
8683 " which is already streamed off", v4l2_port);
8684 return 0;
8685 }
8686
8687 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
8688
8689 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
8690 if (rc) {
8691 /*TODO: How to handle this case */
8692 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
8693 } else {
8694 streaming[v4l2_port] = false;
8695 }
8696
8697 return rc;
8698 }
8699
get_buffer_req(vdec_allocatorproperty * buffer_prop)8700 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
8701 {
8702 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8703 struct v4l2_requestbuffers bufreq;
8704 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
8705 unsigned int final_extra_data_size = 0;
8706 struct v4l2_format fmt;
8707 int ret = 0;
8708 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
8709 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8710 bufreq.memory = V4L2_MEMORY_USERPTR;
8711 bufreq.count = 1;
8712 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8713 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8714 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8715 fmt.fmt.pix_mp.pixelformat = output_capability;
8716 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8717 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8718 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8719 fmt.fmt.pix_mp.pixelformat = capture_capability;
8720 } else {
8721 eRet = OMX_ErrorBadParameter;
8722 }
8723 if (eRet==OMX_ErrorNone) {
8724 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
8725 }
8726 if (ret) {
8727 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
8728 /*TODO: How to handle this case */
8729 eRet = OMX_ErrorInsufficientResources;
8730 return eRet;
8731 } else {
8732 buffer_prop->actualcount = bufreq.count;
8733 buffer_prop->mincount = bufreq.count;
8734 DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
8735 }
8736 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
8737 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8738
8739 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
8740 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
8741
8742 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
8743
8744 update_resolution(fmt.fmt.pix_mp.width,
8745 fmt.fmt.pix_mp.height,
8746 fmt.fmt.pix_mp.plane_fmt[0].bytesperline,
8747 fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
8748 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
8749 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
8750 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
8751
8752 if (ret) {
8753 /*TODO: How to handle this case */
8754 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
8755 eRet = OMX_ErrorInsufficientResources;
8756 } else {
8757 int extra_idx = 0;
8758
8759 eRet = is_video_session_supported();
8760 if (eRet)
8761 return eRet;
8762
8763 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
8764 buf_size = buffer_prop->buffer_size;
8765 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
8766 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8767 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
8768 } else if (extra_idx >= VIDEO_MAX_PLANES) {
8769 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
8770 return OMX_ErrorBadParameter;
8771 }
8772
8773 default_extra_data_size = VENUS_EXTRADATA_SIZE(
8774 drv_ctx.video_resolution.frame_height,
8775 drv_ctx.video_resolution.frame_width);
8776 final_extra_data_size = extra_data_size > default_extra_data_size ?
8777 extra_data_size : default_extra_data_size;
8778
8779 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
8780 (~(buffer_prop->alignment - 1));
8781
8782 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
8783 drv_ctx.extradata_info.count = buffer_prop->actualcount;
8784 drv_ctx.extradata_info.buffer_size = final_extra_data_size;
8785 if (!secure_mode)
8786 buf_size += final_extra_data_size;
8787 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
8788 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
8789 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
8790 if (extra_data_size)
8791 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
8792 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
8793
8794 if (in_reconfig) // BufReq will be set to driver when port is disabled
8795 buffer_prop->buffer_size = buf_size;
8796 else if (buf_size != buffer_prop->buffer_size) {
8797 buffer_prop->buffer_size = buf_size;
8798 eRet = set_buffer_req(buffer_prop);
8799 }
8800 }
8801 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
8802 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8803 return eRet;
8804 }
8805
set_buffer_req(vdec_allocatorproperty * buffer_prop)8806 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
8807 {
8808 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8809 unsigned buf_size = 0;
8810 struct v4l2_format fmt;
8811 struct v4l2_requestbuffers bufreq;
8812 int ret;
8813 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
8814 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
8815 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
8816 if (buf_size != buffer_prop->buffer_size) {
8817 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
8818 (unsigned int)buffer_prop->buffer_size, buf_size);
8819 eRet = OMX_ErrorBadParameter;
8820 } else {
8821 memset(&fmt, 0x0, sizeof(struct v4l2_format));
8822 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
8823 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
8824
8825 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8826 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8827 fmt.fmt.pix_mp.pixelformat = output_capability;
8828 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
8829 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8830 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8831 fmt.fmt.pix_mp.pixelformat = capture_capability;
8832 } else {
8833 eRet = OMX_ErrorBadParameter;
8834 }
8835
8836 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
8837 if (ret) {
8838 /*TODO: How to handle this case */
8839 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
8840 eRet = OMX_ErrorInsufficientResources;
8841 }
8842
8843 bufreq.memory = V4L2_MEMORY_USERPTR;
8844 bufreq.count = buffer_prop->actualcount;
8845 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
8846 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8847 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
8848 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8849 } else {
8850 eRet = OMX_ErrorBadParameter;
8851 }
8852
8853 if (eRet==OMX_ErrorNone) {
8854 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
8855 }
8856
8857 if (ret) {
8858 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
8859 /*TODO: How to handle this case */
8860 eRet = OMX_ErrorInsufficientResources;
8861 } else if (bufreq.count < buffer_prop->actualcount) {
8862 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
8863 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
8864 buffer_prop->actualcount, bufreq.count);
8865 eRet = OMX_ErrorInsufficientResources;
8866 } else {
8867 if (!client_buffers.update_buffer_req()) {
8868 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
8869 eRet = OMX_ErrorInsufficientResources;
8870 }
8871 }
8872 }
8873 return eRet;
8874 }
8875
update_picture_resolution()8876 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
8877 {
8878 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8879 return eRet;
8880 }
8881
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)8882 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
8883 {
8884 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8885 struct v4l2_format fmt;
8886 if (!portDefn) {
8887 return OMX_ErrorBadParameter;
8888 }
8889 DEBUG_PRINT_LOW("omx_vdec::update_portdef");
8890 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
8891 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
8892 portDefn->eDomain = OMX_PortDomainVideo;
8893 if (drv_ctx.frame_rate.fps_denominator > 0)
8894 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
8895 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
8896 else {
8897 DEBUG_PRINT_ERROR("Error: Divide by zero");
8898 return OMX_ErrorBadParameter;
8899 }
8900 memset(&fmt, 0x0, sizeof(struct v4l2_format));
8901 if (0 == portDefn->nPortIndex) {
8902 portDefn->eDir = OMX_DirInput;
8903 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
8904 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
8905 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
8906 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
8907 portDefn->format.video.eCompressionFormat = eCompressionFormat;
8908 portDefn->bEnabled = m_inp_bEnabled;
8909 portDefn->bPopulated = m_inp_bPopulated;
8910
8911 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
8912 fmt.fmt.pix_mp.pixelformat = output_capability;
8913 } else if (1 == portDefn->nPortIndex) {
8914 unsigned int buf_size = 0;
8915 if (!client_buffers.update_buffer_req()) {
8916 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
8917 return OMX_ErrorHardware;
8918 }
8919 if (!client_buffers.get_buffer_req(buf_size)) {
8920 DEBUG_PRINT_ERROR("update buffer requirements");
8921 return OMX_ErrorHardware;
8922 }
8923 portDefn->nBufferSize = buf_size;
8924 portDefn->eDir = OMX_DirOutput;
8925 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
8926 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
8927 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
8928 portDefn->bEnabled = m_out_bEnabled;
8929 portDefn->bPopulated = m_out_bPopulated;
8930 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
8931 DEBUG_PRINT_ERROR("Error in getting color format");
8932 return OMX_ErrorHardware;
8933 }
8934 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
8935 fmt.fmt.pix_mp.pixelformat = capture_capability;
8936 } else {
8937 portDefn->eDir = OMX_DirMax;
8938 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
8939 (int)portDefn->nPortIndex);
8940 eRet = OMX_ErrorBadPortIndex;
8941 }
8942 if (is_down_scalar_enabled) {
8943 int ret = 0;
8944 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
8945 if (ret) {
8946 DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution");
8947 return OMX_ErrorHardware;
8948 } else {
8949 portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width;
8950 portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height;
8951 portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
8952 portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
8953 }
8954 } else {
8955 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
8956 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
8957 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
8958 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
8959 }
8960
8961 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
8962 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
8963 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
8964 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
8965 }
8966 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
8967 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
8968 (unsigned int)portDefn->nPortIndex,
8969 (unsigned int)portDefn->format.video.nFrameWidth,
8970 (unsigned int)portDefn->format.video.nFrameHeight,
8971 (int)portDefn->format.video.nStride,
8972 (unsigned int)portDefn->format.video.nSliceHeight,
8973 (unsigned int)portDefn->format.video.eColorFormat,
8974 (unsigned int)portDefn->nBufferSize,
8975 (unsigned int)portDefn->nBufferCountActual);
8976
8977 return eRet;
8978 }
8979
allocate_output_headers()8980 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
8981 {
8982 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8983 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
8984 unsigned i= 0;
8985
8986 if (!m_out_mem_ptr) {
8987 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
8988 int nBufHdrSize = 0;
8989 int nPlatformEntrySize = 0;
8990 int nPlatformListSize = 0;
8991 int nPMEMInfoSize = 0;
8992 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
8993 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
8994 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
8995
8996 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
8997 drv_ctx.op_buf.actualcount);
8998 nBufHdrSize = drv_ctx.op_buf.actualcount *
8999 sizeof(OMX_BUFFERHEADERTYPE);
9000
9001 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
9002 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9003 nPlatformListSize = drv_ctx.op_buf.actualcount *
9004 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9005 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9006 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9007
9008 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
9009 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
9010 nPMEMInfoSize,
9011 nPlatformListSize);
9012 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
9013 m_out_bm_count);
9014 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
9015 // Alloc mem for platform specific info
9016 char *pPtr=NULL;
9017 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9018 nPMEMInfoSize,1);
9019 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9020 calloc (sizeof(struct vdec_bufferpayload),
9021 drv_ctx.op_buf.actualcount);
9022 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
9023 calloc (sizeof (struct vdec_output_frameinfo),
9024 drv_ctx.op_buf.actualcount);
9025 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9026 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
9027 return OMX_ErrorInsufficientResources;
9028 }
9029
9030 #ifdef USE_ION
9031 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9032 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9033 if (!drv_ctx.op_buf_ion_info) {
9034 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9035 return OMX_ErrorInsufficientResources;
9036 }
9037 #endif
9038 if (dynamic_buf_mode) {
9039 out_dynamic_list = (struct dynamic_buf_list *) \
9040 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
9041 }
9042
9043 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9044 && drv_ctx.ptr_respbuffer) {
9045 bufHdr = m_out_mem_ptr;
9046 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9047 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9048 (((char *) m_platform_list) + nPlatformListSize);
9049 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
9050 (((char *) m_platform_entry) + nPlatformEntrySize);
9051 pPlatformList = m_platform_list;
9052 pPlatformEntry = m_platform_entry;
9053 pPMEMInfo = m_pmem_info;
9054
9055 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
9056
9057 // Settting the entire storage nicely
9058 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
9059 m_out_mem_ptr,pPlatformEntry);
9060 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
9061 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
9062 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
9063 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
9064 // Set the values when we determine the right HxW param
9065 bufHdr->nAllocLen = 0;
9066 bufHdr->nFilledLen = 0;
9067 bufHdr->pAppPrivate = NULL;
9068 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9069 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
9070 pPlatformEntry->entry = pPMEMInfo;
9071 // Initialize the Platform List
9072 pPlatformList->nEntries = 1;
9073 pPlatformList->entryList = pPlatformEntry;
9074 // Keep pBuffer NULL till vdec is opened
9075 bufHdr->pBuffer = NULL;
9076 pPMEMInfo->offset = 0;
9077 pPMEMInfo->pmem_fd = 0;
9078 bufHdr->pPlatformPrivate = pPlatformList;
9079 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
9080 #ifdef USE_ION
9081 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
9082 #endif
9083 /*Create a mapping between buffers*/
9084 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
9085 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
9086 &drv_ctx.ptr_outputbuffer[i];
9087 // Move the buffer and buffer header pointers
9088 bufHdr++;
9089 pPMEMInfo++;
9090 pPlatformEntry++;
9091 pPlatformList++;
9092 }
9093 } else {
9094 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
9095 m_out_mem_ptr, pPtr);
9096 if (m_out_mem_ptr) {
9097 free(m_out_mem_ptr);
9098 m_out_mem_ptr = NULL;
9099 }
9100 if (pPtr) {
9101 free(pPtr);
9102 pPtr = NULL;
9103 }
9104 if (drv_ctx.ptr_outputbuffer) {
9105 free(drv_ctx.ptr_outputbuffer);
9106 drv_ctx.ptr_outputbuffer = NULL;
9107 }
9108 if (drv_ctx.ptr_respbuffer) {
9109 free(drv_ctx.ptr_respbuffer);
9110 drv_ctx.ptr_respbuffer = NULL;
9111 }
9112 #ifdef USE_ION
9113 if (drv_ctx.op_buf_ion_info) {
9114 DEBUG_PRINT_LOW("Free o/p ion context");
9115 free(drv_ctx.op_buf_ion_info);
9116 drv_ctx.op_buf_ion_info = NULL;
9117 }
9118 #endif
9119 eRet = OMX_ErrorInsufficientResources;
9120 }
9121 } else {
9122 eRet = OMX_ErrorInsufficientResources;
9123 }
9124 return eRet;
9125 }
9126
complete_pending_buffer_done_cbs()9127 void omx_vdec::complete_pending_buffer_done_cbs()
9128 {
9129 unsigned long p1, p2, ident;
9130 omx_cmd_queue tmp_q, pending_bd_q;
9131 pthread_mutex_lock(&m_lock);
9132 // pop all pending GENERATE FDB from ftb queue
9133 while (m_ftb_q.m_size) {
9134 m_ftb_q.pop_entry(&p1,&p2,&ident);
9135 if (ident == OMX_COMPONENT_GENERATE_FBD) {
9136 pending_bd_q.insert_entry(p1,p2,ident);
9137 } else {
9138 tmp_q.insert_entry(p1,p2,ident);
9139 }
9140 }
9141 //return all non GENERATE FDB to ftb queue
9142 while (tmp_q.m_size) {
9143 tmp_q.pop_entry(&p1,&p2,&ident);
9144 m_ftb_q.insert_entry(p1,p2,ident);
9145 }
9146 // pop all pending GENERATE EDB from etb queue
9147 while (m_etb_q.m_size) {
9148 m_etb_q.pop_entry(&p1,&p2,&ident);
9149 if (ident == OMX_COMPONENT_GENERATE_EBD) {
9150 pending_bd_q.insert_entry(p1,p2,ident);
9151 } else {
9152 tmp_q.insert_entry(p1,p2,ident);
9153 }
9154 }
9155 //return all non GENERATE FDB to etb queue
9156 while (tmp_q.m_size) {
9157 tmp_q.pop_entry(&p1,&p2,&ident);
9158 m_etb_q.insert_entry(p1,p2,ident);
9159 }
9160 pthread_mutex_unlock(&m_lock);
9161 // process all pending buffer dones
9162 while (pending_bd_q.m_size) {
9163 pending_bd_q.pop_entry(&p1,&p2,&ident);
9164 switch (ident) {
9165 case OMX_COMPONENT_GENERATE_EBD:
9166 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
9167 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
9168 omx_report_error ();
9169 }
9170 break;
9171
9172 case OMX_COMPONENT_GENERATE_FBD:
9173 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
9174 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
9175 omx_report_error ();
9176 }
9177 break;
9178 }
9179 }
9180 }
9181
set_frame_rate(OMX_S64 act_timestamp)9182 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
9183 {
9184 OMX_U32 new_frame_interval = 0;
9185 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
9186 && llabs(act_timestamp - prev_ts) > 2000) {
9187 new_frame_interval = client_set_fps ? frm_int :
9188 llabs(act_timestamp - prev_ts);
9189 if (new_frame_interval != frm_int || frm_int == 0) {
9190 frm_int = new_frame_interval;
9191 if (frm_int) {
9192 drv_ctx.frame_rate.fps_numerator = 1e6;
9193 drv_ctx.frame_rate.fps_denominator = frm_int;
9194 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
9195 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
9196 (float)drv_ctx.frame_rate.fps_denominator);
9197 //m_perf_control.request_cores(frm_int);
9198 /* We need to report the difference between this FBD and the previous FBD
9199 * back to the driver for clock scaling purposes. */
9200 struct v4l2_outputparm oparm;
9201 /*XXX: we're providing timing info as seconds per frame rather than frames
9202 * per second.*/
9203 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
9204 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
9205
9206 struct v4l2_streamparm sparm;
9207 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9208 sparm.parm.output = oparm;
9209 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
9210 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
9211 performance might be affected");
9212 }
9213
9214 }
9215 }
9216 }
9217 prev_ts = act_timestamp;
9218 }
9219
adjust_timestamp(OMX_S64 & act_timestamp)9220 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
9221 {
9222 if (rst_prev_ts && VALID_TS(act_timestamp)) {
9223 prev_ts = act_timestamp;
9224 rst_prev_ts = false;
9225 } else if (VALID_TS(prev_ts)) {
9226 bool codec_cond = (drv_ctx.timestamp_adjust)?
9227 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts || llabs(act_timestamp - prev_ts) <= 2000) :
9228 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts);
9229 if (frm_int > 0 && codec_cond) {
9230 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
9231 act_timestamp = prev_ts + frm_int;
9232 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
9233 prev_ts = act_timestamp;
9234 } else {
9235 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
9236 // ensure that timestamps can never step backwards when in display order
9237 act_timestamp = prev_ts;
9238 }
9239 set_frame_rate(act_timestamp);
9240 }
9241 } else if (frm_int > 0) // In this case the frame rate was set along
9242 { // with the port definition, start ts with 0
9243 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
9244 rst_prev_ts = true;
9245 }
9246 }
9247
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)9248 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
9249 {
9250 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
9251 OMX_U32 num_conceal_MB = 0;
9252 OMX_TICKS time_stamp = 0;
9253 OMX_U32 frame_rate = 0;
9254 unsigned long consumed_len = 0;
9255 OMX_U32 num_MB_in_frame;
9256 OMX_U32 recovery_sei_flags = 1;
9257 int enable = 0;
9258
9259 int buf_index = p_buf_hdr - m_out_mem_ptr;
9260 if (buf_index >= drv_ctx.extradata_info.count) {
9261 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
9262 buf_index, drv_ctx.extradata_info.count);
9263 return;
9264 }
9265 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
9266 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
9267 p_buf_hdr->nOffset;
9268
9269 if (!drv_ctx.extradata_info.uaddr) {
9270 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
9271 return;
9272 }
9273 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
9274 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
9275 p_extra = NULL;
9276 return;
9277 }
9278 if (!secure_mode)
9279 p_extra = (OMX_OTHER_EXTRADATATYPE *)
9280 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
9281 else
9282 p_extra = m_other_extradata;
9283 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
9284
9285 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
9286 p_extra = NULL;
9287 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
9288 return;
9289 }
9290 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
9291 if (data && p_extra) {
9292 while ((consumed_len < drv_ctx.extradata_info.buffer_size)
9293 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
9294 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
9295 DEBUG_PRINT_LOW("Invalid extra data size");
9296 break;
9297 }
9298 DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType);
9299 switch ((unsigned long)data->eType) {
9300 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
9301 struct msm_vidc_interlace_payload *payload;
9302 payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
9303 if (payload) {
9304 enable = 1;
9305 switch (payload->format) {
9306 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
9307 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9308 enable = 0;
9309 break;
9310 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
9311 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
9312 break;
9313 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
9314 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
9315 break;
9316 default:
9317 DEBUG_PRINT_LOW("default case - set interlace to topfield");
9318 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
9319 }
9320 }
9321
9322 if (m_enable_android_native_buffers) {
9323 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d mbaff:%d",
9324 payload->format, enable,
9325 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
9326 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
9327 PP_PARAM_INTERLACED, (void*)&enable);
9328 }
9329 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
9330 append_interlace_extradata(p_extra, payload->format,
9331 p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF);
9332 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9333 }
9334 break;
9335 case MSM_VIDC_EXTRADATA_FRAME_RATE:
9336 struct msm_vidc_framerate_payload *frame_rate_payload;
9337 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
9338 frame_rate = frame_rate_payload->frame_rate;
9339 break;
9340 case MSM_VIDC_EXTRADATA_TIMESTAMP:
9341 struct msm_vidc_ts_payload *time_stamp_payload;
9342 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
9343 time_stamp = time_stamp_payload->timestamp_lo;
9344 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
9345 p_buf_hdr->nTimeStamp = time_stamp;
9346 break;
9347 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
9348 struct msm_vidc_concealmb_payload *conceal_mb_payload;
9349 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
9350 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
9351 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
9352 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
9353 break;
9354 case MSM_VIDC_EXTRADATA_INDEX:
9355 int *etype;
9356 etype = (int *)(void *)data->data;
9357 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
9358 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
9359 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
9360 if (aspect_ratio_payload) {
9361 ((struct vdec_output_frameinfo *)
9362 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
9363 ((struct vdec_output_frameinfo *)
9364 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
9365 }
9366 }
9367 break;
9368 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
9369 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
9370 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
9371 recovery_sei_flags = recovery_sei_payload->flags;
9372 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
9373 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9374 DEBUG_PRINT_HIGH("***************************************************");
9375 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
9376 DEBUG_PRINT_HIGH("***************************************************");
9377 }
9378 break;
9379 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
9380 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
9381 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
9382 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
9383 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
9384 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
9385 return;
9386 }
9387 break;
9388 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
9389 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
9390 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)(void *)data->data;
9391 if (seqdisp_payload) {
9392 m_disp_hor_size = seqdisp_payload->disp_width;
9393 m_disp_vert_size = seqdisp_payload->disp_height;
9394 if (client_extradata & OMX_MPEG2SEQDISP_EXTRADATA) {
9395 append_mpeg2_seqdisplay_extradata(p_extra, seqdisp_payload);
9396 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9397 }
9398 }
9399 break;
9400 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
9401 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
9402 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
9403 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
9404 append_framepack_extradata(p_extra, s3d_frame_packing_payload);
9405 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9406 }
9407 break;
9408 case MSM_VIDC_EXTRADATA_FRAME_QP:
9409 struct msm_vidc_frame_qp_payload *qp_payload;
9410 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
9411 if (client_extradata & OMX_QP_EXTRADATA) {
9412 append_qp_extradata(p_extra, qp_payload);
9413 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9414 }
9415 break;
9416 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
9417 struct msm_vidc_frame_bits_info_payload *bits_info_payload;
9418 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
9419 if (client_extradata & OMX_BITSINFO_EXTRADATA) {
9420 append_bitsinfo_extradata(p_extra, bits_info_payload);
9421 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9422 }
9423 break;
9424 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
9425 if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
9426 append_user_extradata(p_extra, data);
9427 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9428 }
9429 break;
9430 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
9431 struct msm_vidc_vui_display_info_payload *display_info_payload;
9432 display_info_payload = (struct msm_vidc_vui_display_info_payload*)(void *)data->data;
9433
9434 if (client_extradata & OMX_VUI_DISPLAY_INFO_EXTRADATA) {
9435 /* This extradata usually isn't needed by clients. Leave it unimplemented for now */
9436 DEBUG_PRINT_ERROR("VUI display info not propagated to client");
9437 }
9438
9439 if (m_enable_android_native_buffers
9440 && display_info_payload->video_signal_present_flag
9441 && display_info_payload->color_description_present_flag) {
9442 ColorSpace_t color_space = ITU_R_601;
9443
9444 switch (display_info_payload->color_primaries) {
9445 case 1:
9446 color_space = ITU_R_709;
9447 break;
9448 case 5:
9449 color_space = display_info_payload->video_full_range_flag ?
9450 ITU_R_601_FR : ITU_R_601;
9451 break;
9452 }
9453
9454 DEBUG_PRINT_LOW("colorspace from VUI = %d", color_space);
9455 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
9456 UPDATE_COLOR_SPACE, (void*)&color_space);
9457 }
9458 break;
9459 default:
9460 DEBUG_PRINT_LOW("Unrecognized extradata");
9461 goto unrecognized_extradata;
9462 }
9463 consumed_len += data->nSize;
9464 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
9465 }
9466 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
9467 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
9468 append_frame_info_extradata(p_extra,
9469 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
9470 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
9471 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
9472 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9473 }
9474 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
9475 append_frame_dimension_extradata(p_extra);
9476 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
9477 }
9478 }
9479 unrecognized_extradata:
9480 if (client_extradata && p_extra) {
9481 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
9482 append_terminator_extradata(p_extra);
9483 }
9484 if (secure_mode && p_extradata && m_other_extradata) {
9485 struct vdec_output_frameinfo *ptr_extradatabuff = NULL;
9486 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
9487 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
9488 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
9489 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
9490 }
9491 return;
9492 }
9493
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)9494 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
9495 bool is_internal, bool enable)
9496 {
9497 OMX_ERRORTYPE ret = OMX_ErrorNone;
9498 struct v4l2_control control;
9499 if (m_state != OMX_StateLoaded) {
9500 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
9501 return OMX_ErrorIncorrectStateOperation;
9502 }
9503
9504 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
9505 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
9506
9507 if (!is_internal) {
9508 if (enable)
9509 client_extradata |= requested_extradata;
9510 else
9511 client_extradata = client_extradata & ~requested_extradata;
9512 }
9513
9514 if (enable) {
9515 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
9516 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9517 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
9518 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9519 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
9520 " Quality of interlaced clips might be impacted.");
9521 }
9522 }
9523 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
9524 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9525 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
9526 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9527 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
9528 }
9529 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9530 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
9531 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9532 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
9533 }
9534 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9535 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
9536 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9537 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
9538 }
9539 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9540 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
9541 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9542 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
9543 }
9544 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9545 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
9546 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9547 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
9548 }
9549 }
9550 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
9551 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9552 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
9553 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9554 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
9555 }
9556 }
9557 if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
9558 if (output_capability == V4L2_PIX_FMT_H264) {
9559 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
9560 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9561 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
9562 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9563 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
9564 }
9565 } else {
9566 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
9567 }
9568 }
9569 if (requested_extradata & OMX_QP_EXTRADATA) {
9570 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9571 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
9572 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9573 DEBUG_PRINT_HIGH("Failed to set QP extradata");
9574 }
9575 }
9576 if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
9577 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9578 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
9579 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9580 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
9581 }
9582 }
9583 if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
9584 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9585 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
9586 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9587 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
9588 }
9589 }
9590 if (requested_extradata & OMX_MPEG2SEQDISP_EXTRADATA) {
9591 if (output_capability == V4L2_PIX_FMT_MPEG2) {
9592 DEBUG_PRINT_HIGH("Enable seq display extradata");
9593 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9594 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
9595 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9596 DEBUG_PRINT_HIGH("Failed to set seqdisp extradata");
9597 }
9598 } else {
9599 DEBUG_PRINT_HIGH("Seq display extradata is supported for MPEG2 only");
9600 }
9601 }
9602 if (requested_extradata & OMX_VUI_DISPLAY_INFO_EXTRADATA) {
9603 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
9604 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
9605 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
9606 DEBUG_PRINT_HIGH("Failed to set display VUI extradata");
9607 }
9608 }
9609 }
9610 ret = get_buffer_req(&drv_ctx.op_buf);
9611 return ret;
9612 }
9613
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)9614 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
9615 {
9616 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
9617 OMX_U8 *data_ptr = extra->data, data = 0;
9618 while (byte_count < extra->nDataSize) {
9619 data = *data_ptr;
9620 while (data) {
9621 num_MB += (data&0x01);
9622 data >>= 1;
9623 }
9624 data_ptr++;
9625 byte_count++;
9626 }
9627 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
9628 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
9629 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
9630 }
9631
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)9632 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
9633 {
9634 if (!m_debug_extradata || !extra)
9635 return;
9636
9637
9638 DEBUG_PRINT_HIGH(
9639 "============== Extra Data ==============\n"
9640 " Size: %u\n"
9641 " Version: %u\n"
9642 " PortIndex: %u\n"
9643 " Type: %x\n"
9644 " DataSize: %u",
9645 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
9646 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
9647
9648 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
9649 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
9650 DEBUG_PRINT_HIGH(
9651 "------ Interlace Format ------\n"
9652 " Size: %u\n"
9653 " Version: %u\n"
9654 " PortIndex: %u\n"
9655 " Is Interlace Format: %d\n"
9656 " Interlace Formats: %u\n"
9657 "=========== End of Interlace ===========",
9658 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
9659 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
9660 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
9661 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
9662
9663 DEBUG_PRINT_HIGH(
9664 "-------- Frame Format --------\n"
9665 " Picture Type: %d\n"
9666 " Interlace Type: %d\n"
9667 " Pan Scan Total Frame Num: %u\n"
9668 " Concealed Macro Blocks: %u\n"
9669 " frame rate: %u\n"
9670 " Time Stamp: %llu\n"
9671 " Aspect Ratio X: %u\n"
9672 " Aspect Ratio Y: %u",
9673 fminfo->ePicType,
9674 fminfo->interlaceType,
9675 (unsigned int)fminfo->panScan.numWindows,
9676 (unsigned int)fminfo->nConcealedMacroblocks,
9677 (unsigned int)fminfo->nFrameRate,
9678 fminfo->nTimeStamp,
9679 (unsigned int)fminfo->aspectRatio.aspectRatioX,
9680 (unsigned int)fminfo->aspectRatio.aspectRatioY);
9681
9682 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
9683 DEBUG_PRINT_HIGH(
9684 "------------------------------"
9685 " Pan Scan Frame Num: %u\n"
9686 " Rectangle x: %d\n"
9687 " Rectangle y: %d\n"
9688 " Rectangle dx: %d\n"
9689 " Rectangle dy: %d",
9690 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
9691 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
9692 }
9693
9694 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
9695 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
9696 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
9697 DEBUG_PRINT_HIGH(
9698 "------------------ Framepack Format ----------\n"
9699 " id: %u \n"
9700 " cancel_flag: %u \n"
9701 " type: %u \n"
9702 " quincunx_sampling_flagFormat: %u \n"
9703 " content_interpretation_type: %u \n"
9704 " spatial_flipping_flag: %u \n"
9705 " frame0_flipped_flag: %u \n"
9706 " field_views_flag: %u \n"
9707 " current_frame_is_frame0_flag: %u \n"
9708 " frame0_self_contained_flag: %u \n"
9709 " frame1_self_contained_flag: %u \n"
9710 " frame0_grid_position_x: %u \n"
9711 " frame0_grid_position_y: %u \n"
9712 " frame1_grid_position_x: %u \n"
9713 " frame1_grid_position_y: %u \n"
9714 " reserved_byte: %u \n"
9715 " repetition_period: %u \n"
9716 " extension_flag: %u \n"
9717 "================== End of Framepack ===========",
9718 (unsigned int)framepack->id,
9719 (unsigned int)framepack->cancel_flag,
9720 (unsigned int)framepack->type,
9721 (unsigned int)framepack->quincunx_sampling_flag,
9722 (unsigned int)framepack->content_interpretation_type,
9723 (unsigned int)framepack->spatial_flipping_flag,
9724 (unsigned int)framepack->frame0_flipped_flag,
9725 (unsigned int)framepack->field_views_flag,
9726 (unsigned int)framepack->current_frame_is_frame0_flag,
9727 (unsigned int)framepack->frame0_self_contained_flag,
9728 (unsigned int)framepack->frame1_self_contained_flag,
9729 (unsigned int)framepack->frame0_grid_position_x,
9730 (unsigned int)framepack->frame0_grid_position_y,
9731 (unsigned int)framepack->frame1_grid_position_x,
9732 (unsigned int)framepack->frame1_grid_position_y,
9733 (unsigned int)framepack->reserved_byte,
9734 (unsigned int)framepack->repetition_period,
9735 (unsigned int)framepack->extension_flag);
9736 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
9737 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
9738 DEBUG_PRINT_HIGH(
9739 "---- QP (Frame quantization parameter) ----\n"
9740 " Frame QP: %u \n"
9741 "================ End of QP ================\n",
9742 (unsigned int)qp->nQP);
9743 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
9744 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
9745 DEBUG_PRINT_HIGH(
9746 "--------- Input bits information --------\n"
9747 " Header bits: %u \n"
9748 " Frame bits: %u \n"
9749 "===== End of Input bits information =====\n",
9750 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
9751 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
9752 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
9753 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
9754 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
9755 OMX_U32 i = 0;
9756 DEBUG_PRINT_HIGH(
9757 "-------------- Userdata -------------\n"
9758 " Stream userdata type: %u\n"
9759 " userdata size: %u\n"
9760 " STREAM_USERDATA:",
9761 (unsigned int)userdata->type, (unsigned int)userdata_size);
9762 for (i = 0; i < userdata_size; i+=4) {
9763 DEBUG_PRINT_HIGH(" %x %x %x %x",
9764 data_ptr[i], data_ptr[i+1],
9765 data_ptr[i+2], data_ptr[i+3]);
9766 }
9767 DEBUG_PRINT_HIGH(
9768 "=========== End of Userdata ===========");
9769 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay) {
9770 OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY*)(void*)extra->data;
9771 DEBUG_PRINT_HIGH(
9772 "------Mpeg2SeqDisplay ------\n"
9773 " Frame Width: %d\n"
9774 " Frame Height: %d\n"
9775 "=========== End of Mpeg2SeqDisplay ===========",
9776 seq_display->disp_width, seq_display->disp_height);
9777 } else if (extra->eType == OMX_ExtraDataNone) {
9778 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
9779 } else {
9780 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
9781 }
9782 }
9783
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type,bool is_mbaff)9784 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9785 OMX_U32 interlaced_format_type, bool is_mbaff)
9786 {
9787 OMX_STREAMINTERLACEFORMAT *interlace_format;
9788
9789 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
9790 return;
9791 }
9792 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
9793 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9794 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9795 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
9796 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
9797 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
9798 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
9799 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
9800 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9801
9802 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) {
9803 interlace_format->bInterlaceFormat = OMX_FALSE;
9804 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
9805 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9806 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) {
9807 interlace_format->bInterlaceFormat = OMX_TRUE;
9808 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
9809 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9810 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) {
9811 interlace_format->bInterlaceFormat = OMX_TRUE;
9812 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
9813 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
9814 } else {
9815 interlace_format->bInterlaceFormat = OMX_TRUE;
9816 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
9817 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
9818 }
9819 print_debug_extradata(extra);
9820 }
9821
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)9822 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
9823 {
9824 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
9825 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
9826 return;
9827 }
9828 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
9829 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9830 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9831 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
9832 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
9833 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
9834 frame_dimension->nDecWidth = rectangle.nLeft;
9835 frame_dimension->nDecHeight = rectangle.nTop;
9836 frame_dimension->nActualWidth = rectangle.nWidth;
9837 frame_dimension->nActualHeight = rectangle.nHeight;
9838 }
9839
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)9840 void omx_vdec::fill_aspect_ratio_info(
9841 struct vdec_aspectratioinfo *aspect_ratio_info,
9842 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
9843 {
9844 m_extradata = frame_info;
9845 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
9846 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
9847 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
9848 (unsigned int)m_extradata->aspectRatio.aspectRatioY);
9849 }
9850
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 picture_type,OMX_U32 frame_rate,OMX_TICKS time_stamp,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)9851 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9852 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
9853 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
9854 struct vdec_aspectratioinfo *aspect_ratio_info)
9855 {
9856 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
9857 struct msm_vidc_panscan_window *panscan_window;
9858 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
9859 return;
9860 }
9861 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
9862 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9863 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9864 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
9865 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
9866 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
9867 switch (picture_type) {
9868 case PICTURE_TYPE_I:
9869 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
9870 break;
9871 case PICTURE_TYPE_P:
9872 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
9873 break;
9874 case PICTURE_TYPE_B:
9875 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
9876 break;
9877 default:
9878 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
9879 }
9880 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
9881 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
9882 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
9883 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
9884 else
9885 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
9886 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
9887 frame_info->nConcealedMacroblocks = num_conceal_mb;
9888 frame_info->nFrameRate = frame_rate;
9889 frame_info->nTimeStamp = time_stamp;
9890 frame_info->panScan.numWindows = 0;
9891 if (output_capability == V4L2_PIX_FMT_MPEG2) {
9892 if (m_disp_hor_size && m_disp_vert_size) {
9893 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
9894 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
9895 } else {
9896 frame_info->displayAspectRatio.displayHorizontalSize = 0;
9897 frame_info->displayAspectRatio.displayVerticalSize = 0;
9898 }
9899 }
9900
9901 if (panscan_payload) {
9902 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
9903 panscan_window = &panscan_payload->wnd[0];
9904 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
9905 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
9906 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
9907 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
9908 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
9909 panscan_window++;
9910 }
9911 }
9912 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
9913 print_debug_extradata(extra);
9914 }
9915
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)9916 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
9917 {
9918 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
9919 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
9920 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9921 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9922 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
9923 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9924 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
9925 *portDefn = m_port_def;
9926 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
9927 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
9928 (unsigned int)portDefn->format.video.nFrameWidth,
9929 (unsigned int)portDefn->format.video.nStride,
9930 (unsigned int)portDefn->format.video.nSliceHeight);
9931 }
9932
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)9933 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9934 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
9935 {
9936 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
9937 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
9938 DEBUG_PRINT_ERROR("frame packing size mismatch");
9939 return;
9940 }
9941 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
9942 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9943 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9944 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
9945 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
9946 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
9947 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
9948 framepack->nVersion.nVersion = OMX_SPEC_VERSION;
9949 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9950 memcpy(&framepack->id, s3d_frame_packing_payload,
9951 sizeof(struct msm_vidc_s3d_frame_packing_payload));
9952 memcpy(&m_frame_pack_arrangement, framepack,
9953 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
9954 print_debug_extradata(extra);
9955 }
9956
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)9957 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9958 struct msm_vidc_frame_qp_payload *qp_payload)
9959 {
9960 OMX_QCOM_EXTRADATA_QP * qp = NULL;
9961 if (!qp_payload) {
9962 DEBUG_PRINT_ERROR("QP payload is NULL");
9963 return;
9964 }
9965 extra->nSize = OMX_QP_EXTRADATA_SIZE;
9966 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9967 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9968 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
9969 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
9970 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
9971 qp->nQP = qp_payload->frame_qp;
9972 print_debug_extradata(extra);
9973 }
9974
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)9975 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9976 struct msm_vidc_frame_bits_info_payload *bits_payload)
9977 {
9978 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
9979 if (!bits_payload) {
9980 DEBUG_PRINT_ERROR("bits info payload is NULL");
9981 return;
9982 }
9983 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
9984 extra->nVersion.nVersion = OMX_SPEC_VERSION;
9985 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
9986 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
9987 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
9988 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
9989 bits->frame_bits = bits_payload->frame_bits;
9990 bits->header_bits = bits_payload->header_bits;
9991 print_debug_extradata(extra);
9992 }
9993
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)9994 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
9995 OMX_OTHER_EXTRADATATYPE *p_user)
9996 {
9997 int userdata_size = 0;
9998 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
9999 userdata_payload =
10000 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
10001 userdata_size = p_user->nDataSize;
10002 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
10003 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10004 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10005 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
10006 extra->nDataSize = userdata_size;
10007 if (extra->data && p_user->data && extra->nDataSize)
10008 memcpy(extra->data, p_user->data, extra->nDataSize);
10009 print_debug_extradata(extra);
10010 }
10011
append_mpeg2_seqdisplay_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_mpeg2_seqdisp_payload * seq_display_payload)10012 void omx_vdec::append_mpeg2_seqdisplay_extradata(OMX_OTHER_EXTRADATATYPE *extra,
10013 struct msm_vidc_mpeg2_seqdisp_payload *seq_display_payload)
10014 {
10015 OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *seq_display = NULL;
10016 extra->nSize = OMX_MPEG2SEQDISP_EXTRADATA_SIZE;
10017 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10018 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10019 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMpeg2SeqDisplay;
10020 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY);
10021 seq_display = (OMX_QCOM_EXTRADATA_MPEG2SEQDISPLAY *)(void *)extra->data;
10022 seq_display->disp_width = seq_display_payload->disp_width;
10023 seq_display->disp_height = seq_display_payload->disp_height;
10024 print_debug_extradata(extra);
10025 }
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)10026 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10027 {
10028 if (!client_extradata) {
10029 return;
10030 }
10031 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
10032 extra->nVersion.nVersion = OMX_SPEC_VERSION;
10033 extra->eType = OMX_ExtraDataNone;
10034 extra->nDataSize = 0;
10035 extra->data[0] = 0;
10036
10037 print_debug_extradata(extra);
10038 }
10039
allocate_desc_buffer(OMX_U32 index)10040 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
10041 {
10042 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10043 if (index >= drv_ctx.ip_buf.actualcount) {
10044 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
10045 return OMX_ErrorInsufficientResources;
10046 }
10047 if (m_desc_buffer_ptr == NULL) {
10048 m_desc_buffer_ptr = (desc_buffer_hdr*) \
10049 calloc( (sizeof(desc_buffer_hdr)),
10050 drv_ctx.ip_buf.actualcount);
10051 if (m_desc_buffer_ptr == NULL) {
10052 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
10053 return OMX_ErrorInsufficientResources;
10054 }
10055 }
10056
10057 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
10058 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
10059 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
10060 return OMX_ErrorInsufficientResources;
10061 }
10062
10063 return eRet;
10064 }
10065
insert_demux_addr_offset(OMX_U32 address_offset)10066 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
10067 {
10068 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
10069 if (m_demux_entries < 8192) {
10070 m_demux_offsets[m_demux_entries++] = address_offset;
10071 }
10072 return;
10073 }
10074
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)10075 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
10076 {
10077 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
10078 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
10079 OMX_U32 index = 0;
10080
10081 m_demux_entries = 0;
10082
10083 while (index < bytes_to_parse) {
10084 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
10085 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
10086 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
10087 (buf[index+2] == 0x01)) ) {
10088 //Found start code, insert address offset
10089 insert_demux_addr_offset(index);
10090 if (buf[index+2] == 0x01) // 3 byte start code
10091 index += 3;
10092 else //4 byte start code
10093 index += 4;
10094 } else
10095 index++;
10096 }
10097 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
10098 return;
10099 }
10100
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)10101 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
10102 {
10103 //fix this, handle 3 byte start code, vc1 terminator entry
10104 OMX_U8 *p_demux_data = NULL;
10105 OMX_U32 desc_data = 0;
10106 OMX_U32 start_addr = 0;
10107 OMX_U32 nal_size = 0;
10108 OMX_U32 suffix_byte = 0;
10109 OMX_U32 demux_index = 0;
10110 OMX_U32 buffer_index = 0;
10111
10112 if (m_desc_buffer_ptr == NULL) {
10113 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
10114 return OMX_ErrorBadParameter;
10115 }
10116
10117 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
10118 if (buffer_index > drv_ctx.ip_buf.actualcount) {
10119 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
10120 return OMX_ErrorBadParameter;
10121 }
10122
10123 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
10124
10125 if ( ((OMX_U8*)p_demux_data == NULL) ||
10126 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
10127 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
10128 return OMX_ErrorBadParameter;
10129 } else {
10130 for (; demux_index < m_demux_entries; demux_index++) {
10131 desc_data = 0;
10132 start_addr = m_demux_offsets[demux_index];
10133 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
10134 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
10135 } else {
10136 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
10137 }
10138 if (demux_index < (m_demux_entries - 1)) {
10139 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
10140 } else {
10141 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
10142 }
10143 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
10144 (unsigned int)start_addr,
10145 (unsigned int)suffix_byte,
10146 (unsigned int)nal_size,
10147 (unsigned int)demux_index);
10148 desc_data = (start_addr >> 3) << 1;
10149 desc_data |= (start_addr & 7) << 21;
10150 desc_data |= suffix_byte << 24;
10151
10152 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
10153 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
10154 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
10155 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
10156
10157 p_demux_data += 16;
10158 }
10159 if (codec_type_parse == CODEC_TYPE_VC1) {
10160 DEBUG_PRINT_LOW("VC1 terminator entry");
10161 desc_data = 0;
10162 desc_data = 0x82 << 24;
10163 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
10164 memset(p_demux_data + 4, 0, sizeof(OMX_U32));
10165 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
10166 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
10167 p_demux_data += 16;
10168 m_demux_entries++;
10169 }
10170 //Add zero word to indicate end of descriptors
10171 memset(p_demux_data, 0, sizeof(OMX_U32));
10172
10173 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
10174 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
10175 }
10176 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
10177 m_demux_entries = 0;
10178 DEBUG_PRINT_LOW("Demux table complete!");
10179 return OMX_ErrorNone;
10180 }
10181
createDivxDrmContext()10182 OMX_ERRORTYPE omx_vdec::createDivxDrmContext()
10183 {
10184 OMX_ERRORTYPE err = OMX_ErrorNone;
10185 iDivXDrmDecrypt = DivXDrmDecrypt::Create();
10186 if (iDivXDrmDecrypt) {
10187 OMX_ERRORTYPE err = iDivXDrmDecrypt->Init();
10188 if (err!=OMX_ErrorNone) {
10189 DEBUG_PRINT_ERROR("ERROR :iDivXDrmDecrypt->Init %d", err);
10190 delete iDivXDrmDecrypt;
10191 iDivXDrmDecrypt = NULL;
10192 }
10193 } else {
10194 DEBUG_PRINT_ERROR("Unable to Create DIVX DRM");
10195 err = OMX_ErrorUndefined;
10196 }
10197 return err;
10198 }
10199
allocate_color_convert_buf()10200 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
10201 {
10202 enabled = false;
10203 omx = NULL;
10204 init_members();
10205 ColorFormat = OMX_COLOR_FormatMax;
10206 dest_format = YCbCr420P;
10207 }
10208
set_vdec_client(void * client)10209 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
10210 {
10211 omx = reinterpret_cast<omx_vdec*>(client);
10212 }
10213
init_members()10214 void omx_vdec::allocate_color_convert_buf::init_members()
10215 {
10216 allocated_count = 0;
10217 buffer_size_req = 0;
10218 buffer_alignment_req = 0;
10219 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
10220 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
10221 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
10222 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
10223 #ifdef USE_ION
10224 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
10225 #endif
10226 for (int i = 0; i < MAX_COUNT; i++)
10227 pmem_fd[i] = -1;
10228 }
10229
~allocate_color_convert_buf()10230 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
10231 {
10232 c2d.destroy();
10233 }
10234
update_buffer_req()10235 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
10236 {
10237 bool status = true;
10238 unsigned int src_size = 0, destination_size = 0;
10239 OMX_COLOR_FORMATTYPE drv_color_format;
10240 if (!omx) {
10241 DEBUG_PRINT_ERROR("Invalid client in color convert");
10242 return false;
10243 }
10244 if (!enabled) {
10245 DEBUG_PRINT_HIGH("No color conversion required");
10246 return status;
10247 }
10248 pthread_mutex_lock(&omx->c_lock);
10249 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
10250 ColorFormat != OMX_COLOR_FormatYUV420Planar) {
10251 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
10252 status = false;
10253 goto fail_update_buf_req;
10254 }
10255 c2d.close();
10256 status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
10257 omx->drv_ctx.video_resolution.frame_width,
10258 NV12_128m,dest_format);
10259 if (status) {
10260 status = c2d.get_buffer_size(C2D_INPUT,src_size);
10261 if (status)
10262 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
10263 }
10264 if (status) {
10265 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
10266 !destination_size) {
10267 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
10268 "driver size %u destination size %d",
10269 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
10270 destination_size);
10271 status = false;
10272 c2d.close();
10273 buffer_size_req = 0;
10274 } else {
10275 buffer_size_req = destination_size;
10276 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
10277 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
10278 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
10279 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
10280 }
10281 }
10282 fail_update_buf_req:
10283 pthread_mutex_unlock(&omx->c_lock);
10284 return status;
10285 }
10286
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)10287 bool omx_vdec::allocate_color_convert_buf::set_color_format(
10288 OMX_COLOR_FORMATTYPE dest_color_format)
10289 {
10290 bool status = true;
10291 OMX_COLOR_FORMATTYPE drv_color_format;
10292 if (!omx) {
10293 DEBUG_PRINT_ERROR("Invalid client in color convert");
10294 return false;
10295 }
10296 pthread_mutex_lock(&omx->c_lock);
10297 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
10298 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
10299 drv_color_format = (OMX_COLOR_FORMATTYPE)
10300 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
10301 else
10302 drv_color_format = (OMX_COLOR_FORMATTYPE)
10303 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10304 else {
10305 DEBUG_PRINT_ERROR("Incorrect color format");
10306 status = false;
10307 }
10308 if (status && !omx->is_component_secure() &&
10309 drv_color_format != dest_color_format &&
10310 drv_color_format != (OMX_COLOR_FORMATTYPE)
10311 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) {
10312 DEBUG_PRINT_LOW("Enabling C2D");
10313 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
10314 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
10315 DEBUG_PRINT_ERROR("Unsupported color format for c2d");
10316 status = false;
10317 } else {
10318 ColorFormat = dest_color_format;
10319 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
10320 YCbCr420P : YCbCr420SP;
10321 if (enabled)
10322 c2d.destroy();
10323 enabled = false;
10324 if (!c2d.init()) {
10325 DEBUG_PRINT_ERROR("open failed for c2d");
10326 status = false;
10327 } else
10328 enabled = true;
10329 }
10330 } else {
10331 if (enabled)
10332 c2d.destroy();
10333 enabled = false;
10334 }
10335 pthread_mutex_unlock(&omx->c_lock);
10336 return status;
10337 }
10338
get_il_buf_hdr()10339 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
10340 {
10341 if (!omx) {
10342 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
10343 return NULL;
10344 }
10345 if (!enabled)
10346 return omx->m_out_mem_ptr;
10347 return m_out_mem_ptr_client;
10348 }
10349
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)10350 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
10351 (OMX_BUFFERHEADERTYPE *bufadd)
10352 {
10353 if (!omx) {
10354 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
10355 return NULL;
10356 }
10357 if (!enabled)
10358 return bufadd;
10359
10360 unsigned index = 0;
10361 index = bufadd - omx->m_out_mem_ptr;
10362 if (index < omx->drv_ctx.op_buf.actualcount) {
10363 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
10364 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
10365 bool status;
10366 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
10367 pthread_mutex_lock(&omx->c_lock);
10368 cache_clean_buffer(index);
10369 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
10370 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
10371 pmem_baseaddress[index], pmem_baseaddress[index]);
10372 if (!status) {
10373 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
10374 m_out_mem_ptr_client[index].nFilledLen = 0;
10375 pthread_mutex_unlock(&omx->c_lock);
10376 return &m_out_mem_ptr_client[index];
10377 } else {
10378 unsigned int filledLen = 0;
10379 c2d.get_output_filled_length(filledLen);
10380 m_out_mem_ptr_client[index].nFilledLen = filledLen;
10381 cache_clean_invalidate_buffer(index);
10382 }
10383 pthread_mutex_unlock(&omx->c_lock);
10384 } else
10385 m_out_mem_ptr_client[index].nFilledLen = 0;
10386 return &m_out_mem_ptr_client[index];
10387 }
10388 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
10389 return NULL;
10390 }
10391
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)10392 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
10393 (OMX_BUFFERHEADERTYPE *bufadd)
10394 {
10395 if (!omx) {
10396 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
10397 return NULL;
10398 }
10399 if (!enabled)
10400 return bufadd;
10401 unsigned index = 0;
10402 index = bufadd - m_out_mem_ptr_client;
10403 if (index < omx->drv_ctx.op_buf.actualcount) {
10404 return &omx->m_out_mem_ptr[index];
10405 }
10406 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
10407 return NULL;
10408 }
get_buffer_req(unsigned int & buffer_size)10409 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
10410 (unsigned int &buffer_size)
10411 {
10412 bool status = true;
10413 pthread_mutex_lock(&omx->c_lock);
10414 if (!enabled)
10415 buffer_size = omx->drv_ctx.op_buf.buffer_size;
10416 else {
10417 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
10418 DEBUG_PRINT_ERROR("Get buffer size failed");
10419 status = false;
10420 goto fail_get_buffer_size;
10421 }
10422 }
10423 if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
10424 buffer_size = omx->drv_ctx.op_buf.buffer_size;
10425 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
10426 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
10427 fail_get_buffer_size:
10428 pthread_mutex_unlock(&omx->c_lock);
10429 return status;
10430 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)10431 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
10432 OMX_BUFFERHEADERTYPE *bufhdr)
10433 {
10434 unsigned int index = 0;
10435
10436 if (!enabled)
10437 return omx->free_output_buffer(bufhdr);
10438 if (enabled && omx->is_component_secure())
10439 return OMX_ErrorNone;
10440 if (!allocated_count || !bufhdr) {
10441 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
10442 return OMX_ErrorBadParameter;
10443 }
10444 index = bufhdr - m_out_mem_ptr_client;
10445 if (index >= omx->drv_ctx.op_buf.actualcount) {
10446 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
10447 return OMX_ErrorBadParameter;
10448 }
10449 if (pmem_fd[index] > 0) {
10450 munmap(pmem_baseaddress[index], buffer_size_req);
10451 close(pmem_fd[index]);
10452 }
10453 pmem_fd[index] = -1;
10454 #ifdef USE_ION
10455 omx->free_ion_memory(&op_buf_ion_info[index]);
10456 #endif
10457 m_heap_ptr[index].video_heap_ptr = NULL;
10458 if (allocated_count > 0)
10459 allocated_count--;
10460 else
10461 allocated_count = 0;
10462 if (!allocated_count) {
10463 pthread_mutex_lock(&omx->c_lock);
10464 c2d.close();
10465 init_members();
10466 pthread_mutex_unlock(&omx->c_lock);
10467 }
10468 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
10469 }
10470
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)10471 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
10472 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
10473 {
10474 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10475 if (!enabled) {
10476 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
10477 return eRet;
10478 }
10479 if (enabled && omx->is_component_secure()) {
10480 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
10481 omx->is_component_secure());
10482 return OMX_ErrorUnsupportedSetting;
10483 }
10484 if (!bufferHdr || bytes > buffer_size_req) {
10485 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
10486 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
10487 (unsigned int)buffer_size_req, (unsigned int)bytes);
10488 return OMX_ErrorBadParameter;
10489 }
10490 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
10491 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
10492 return OMX_ErrorInsufficientResources;
10493 }
10494 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
10495 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
10496 port,appData,omx->drv_ctx.op_buf.buffer_size);
10497 if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
10498 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
10499 return eRet;
10500 }
10501 if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
10502 (int)omx->drv_ctx.op_buf.actualcount) {
10503 DEBUG_PRINT_ERROR("Invalid header index %ld",
10504 (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
10505 return OMX_ErrorUndefined;
10506 }
10507 unsigned int i = allocated_count;
10508 #ifdef USE_ION
10509 // Allocate color-conversion buffers as cached to improve software-reading
10510 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
10511 // cache invalidation.
10512 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
10513 buffer_size_req,buffer_alignment_req,
10514 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
10515 ION_FLAG_CACHED);
10516 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
10517 if (op_buf_ion_info[i].ion_device_fd < 0) {
10518 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
10519 return OMX_ErrorInsufficientResources;
10520 }
10521 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
10522 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
10523
10524 if (pmem_baseaddress[i] == MAP_FAILED) {
10525 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
10526 close(pmem_fd[i]);
10527 omx->free_ion_memory(&op_buf_ion_info[i]);
10528 return OMX_ErrorInsufficientResources;
10529 }
10530 m_heap_ptr[i].video_heap_ptr = new VideoHeap (
10531 op_buf_ion_info[i].ion_device_fd,buffer_size_req,
10532 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
10533 #endif
10534 m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
10535 m_pmem_info_client[i].offset = 0;
10536 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
10537 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10538 m_platform_list_client[i].nEntries = 1;
10539 m_platform_list_client[i].entryList = &m_platform_entry_client[i];
10540 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
10541 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
10542 m_out_mem_ptr_client[i].nFilledLen = 0;
10543 m_out_mem_ptr_client[i].nFlags = 0;
10544 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10545 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
10546 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
10547 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
10548 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
10549 m_out_mem_ptr_client[i].pAppPrivate = appData;
10550 *bufferHdr = &m_out_mem_ptr_client[i];
10551 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
10552 allocated_count++;
10553 return eRet;
10554 }
10555
is_component_secure()10556 bool omx_vdec::is_component_secure()
10557 {
10558 return secure_mode;
10559 }
10560
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)10561 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
10562 {
10563 bool status = true;
10564 if (!enabled) {
10565 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
10566 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
10567 dest_color_format = (OMX_COLOR_FORMATTYPE)
10568 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
10569 else
10570 dest_color_format = (OMX_COLOR_FORMATTYPE)
10571 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10572 else
10573 status = false;
10574 } else {
10575 if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
10576 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
10577 dest_color_format = ColorFormat;
10578 } else
10579 status = false;
10580 }
10581 return status;
10582 }
10583
cache_ops(unsigned int index,unsigned int cmd)10584 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
10585 unsigned int index, unsigned int cmd)
10586 {
10587 if (!enabled) {
10588 return OMX_ErrorNone;
10589 }
10590
10591 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
10592 DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
10593 return OMX_ErrorBadParameter;
10594 }
10595
10596 struct ion_flush_data flush_data;
10597 struct ion_custom_data custom_data;
10598
10599 memset(&flush_data, 0x0, sizeof(flush_data));
10600 memset(&custom_data, 0x0, sizeof(custom_data));
10601
10602 flush_data.vaddr = pmem_baseaddress[index];
10603 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
10604 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
10605 flush_data.length = buffer_size_req;
10606 custom_data.cmd = cmd;
10607 custom_data.arg = (unsigned long)&flush_data;
10608
10609 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
10610 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
10611 flush_data.fd, flush_data.handle, flush_data.vaddr,
10612 flush_data.length);
10613 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
10614 if (ret < 0) {
10615 DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
10616 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
10617 strerror(errno));
10618 return OMX_ErrorUndefined;
10619 }
10620 return OMX_ErrorNone;
10621 }
10622
buf_ref_add(OMX_U32 fd,OMX_U32 offset)10623 void omx_vdec::buf_ref_add(OMX_U32 fd, OMX_U32 offset)
10624 {
10625 unsigned long i = 0;
10626 bool buf_present = false;
10627
10628 if (!dynamic_buf_mode) {
10629 return;
10630 }
10631
10632 if (!out_dynamic_list) {
10633 DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL");
10634 return;
10635 }
10636
10637 pthread_mutex_lock(&m_lock);
10638 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
10639 //check the buffer fd, offset, uv addr with list contents
10640 //If present increment reference.
10641 if ((out_dynamic_list[i].fd == fd) &&
10642 (out_dynamic_list[i].offset == offset)) {
10643 out_dynamic_list[i].ref_count++;
10644 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
10645 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
10646 buf_present = true;
10647 break;
10648 }
10649 }
10650 if (!buf_present) {
10651 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
10652 //search for a entry to insert details of the new buffer
10653 if (out_dynamic_list[i].dup_fd == 0) {
10654 out_dynamic_list[i].fd = fd;
10655 out_dynamic_list[i].offset = offset;
10656 out_dynamic_list[i].dup_fd = dup(fd);
10657 out_dynamic_list[i].ref_count++;
10658 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
10659 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
10660 break;
10661 }
10662 }
10663 }
10664 pthread_mutex_unlock(&m_lock);
10665 }
10666
buf_ref_remove(OMX_U32 fd,OMX_U32 offset)10667 void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset)
10668 {
10669 unsigned long i = 0;
10670
10671 if (!dynamic_buf_mode) {
10672 return;
10673 }
10674
10675 if (!out_dynamic_list) {
10676 DEBUG_PRINT_ERROR("buf_ref_add: out_dynamic_list is NULL");
10677 return;
10678 }
10679
10680 pthread_mutex_lock(&m_lock);
10681 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
10682 //check the buffer fd, offset, uv addr with list contents
10683 //If present decrement reference.
10684 if ((out_dynamic_list[i].fd == fd) &&
10685 (out_dynamic_list[i].offset == offset)) {
10686 out_dynamic_list[i].ref_count--;
10687 if (out_dynamic_list[i].ref_count == 0) {
10688 close(out_dynamic_list[i].dup_fd);
10689 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
10690 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
10691 out_dynamic_list[i].dup_fd = 0;
10692 out_dynamic_list[i].fd = 0;
10693 out_dynamic_list[i].offset = 0;
10694 }
10695 break;
10696 }
10697 }
10698 if (i >= drv_ctx.op_buf.actualcount) {
10699 DEBUG_PRINT_ERROR("Error - could not remove ref, no match with any entry in list");
10700 }
10701 pthread_mutex_unlock(&m_lock);
10702 }
10703
10704 #ifdef _MSM8974_
send_codec_config()10705 void omx_vdec::send_codec_config() {
10706 if (codec_config_flag) {
10707 unsigned long p1 = 0; // Parameter - 1
10708 unsigned long p2 = 0; // Parameter - 2
10709 unsigned long ident = 0;
10710 pthread_mutex_lock(&m_lock);
10711 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
10712 while (m_etb_q.m_size) {
10713 m_etb_q.pop_entry(&p1,&p2,&ident);
10714 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
10715 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
10716 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
10717 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
10718 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
10719 omx_report_error();
10720 }
10721 } else {
10722 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
10723 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
10724 }
10725 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
10726 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
10727 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
10728 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
10729 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
10730 omx_report_error ();
10731 }
10732 } else {
10733 pending_input_buffers++;
10734 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
10735 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
10736 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
10737 }
10738 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
10739 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
10740 (OMX_BUFFERHEADERTYPE *)p1);
10741 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
10742 }
10743 }
10744 pthread_mutex_unlock(&m_lock);
10745 }
10746 }
10747 #endif
10748
perf_control()10749 omx_vdec::perf_control::perf_control ()
10750 {
10751 m_perf_lib = NULL;
10752 m_perf_handle = -1;
10753 m_perf_lock_acquire = NULL;
10754 m_perf_lock_release = NULL;
10755 }
10756
~perf_control()10757 omx_vdec::perf_control::~perf_control()
10758 {
10759 if (m_perf_handle >= 0 && m_perf_lock_release) {
10760 DEBUG_PRINT_LOW("NOTE2: release perf lock");
10761 m_perf_lock_release(m_perf_handle);
10762 }
10763 if (m_perf_lib) {
10764 dlclose(m_perf_lib);
10765 }
10766 }
10767
request_cores(int frame_duration_us)10768 void omx_vdec::perf_control::request_cores(int frame_duration_us)
10769 {
10770 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
10771 return;
10772 }
10773 load_lib();
10774 if (m_perf_lock_acquire && m_perf_handle < 0) {
10775 int arg = 0x700 /*base value*/ + 2 /*cores*/;
10776 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
10777 if (m_perf_handle) {
10778 DEBUG_PRINT_HIGH("perf lock acquired");
10779 }
10780 }
10781 }
10782
load_lib()10783 void omx_vdec::perf_control::load_lib()
10784 {
10785 char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
10786 if (m_perf_lib)
10787 return;
10788
10789 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
10790 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
10791 return;
10792 }
10793
10794 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
10795 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
10796 } else {
10797 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
10798 if (m_perf_lock_acquire == NULL) {
10799 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
10800 }
10801 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
10802 if (m_perf_lock_release == NULL) {
10803 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
10804 }
10805 }
10806 }
10807
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)10808 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
10809 unsigned long nMaxFrameHeight)
10810 {
10811
10812 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10813 int ret = 0;
10814 unsigned long min_res_buf_count = 0;
10815
10816 eRet = enable_smoothstreaming();
10817 if (eRet != OMX_ErrorNone) {
10818 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
10819 return eRet;
10820 }
10821
10822 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
10823 nMaxFrameWidth,
10824 nMaxFrameHeight);
10825 m_smoothstreaming_mode = true;
10826 m_smoothstreaming_width = nMaxFrameWidth;
10827 m_smoothstreaming_height = nMaxFrameHeight;
10828
10829 //Get upper limit buffer count for min supported resolution
10830 struct v4l2_format fmt;
10831 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10832 fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
10833 fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
10834 fmt.fmt.pix_mp.pixelformat = output_capability;
10835
10836 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10837 if (ret) {
10838 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
10839 m_decoder_capability.min_height,
10840 m_decoder_capability.min_width);
10841 return OMX_ErrorUnsupportedSetting;
10842 }
10843
10844 eRet = get_buffer_req(&drv_ctx.op_buf);
10845 if (eRet != OMX_ErrorNone) {
10846 DEBUG_PRINT_ERROR("failed to get_buffer_req");
10847 return eRet;
10848 }
10849
10850 min_res_buf_count = drv_ctx.op_buf.mincount;
10851 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
10852 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
10853
10854 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
10855 m_smoothstreaming_width, m_smoothstreaming_height);
10856 eRet = is_video_session_supported();
10857 if (eRet != OMX_ErrorNone) {
10858 DEBUG_PRINT_ERROR("video session is not supported");
10859 return eRet;
10860 }
10861
10862 //Get upper limit buffer size for max smooth streaming resolution set
10863 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10864 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10865 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10866 fmt.fmt.pix_mp.pixelformat = output_capability;
10867 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10868 if (ret) {
10869 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
10870 return OMX_ErrorUnsupportedSetting;
10871 }
10872
10873 eRet = get_buffer_req(&drv_ctx.op_buf);
10874 if (eRet != OMX_ErrorNone) {
10875 DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
10876 return eRet;
10877 }
10878 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
10879 (unsigned int)drv_ctx.op_buf.buffer_size);
10880
10881 drv_ctx.op_buf.mincount = min_res_buf_count;
10882 drv_ctx.op_buf.actualcount = min_res_buf_count;
10883 eRet = set_buffer_req(&drv_ctx.op_buf);
10884 if (eRet != OMX_ErrorNone) {
10885 DEBUG_PRINT_ERROR("failed to set_buffer_req");
10886 return eRet;
10887 }
10888
10889 eRet = get_buffer_req(&drv_ctx.op_buf);
10890 if (eRet != OMX_ErrorNone) {
10891 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
10892 return eRet;
10893 }
10894 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
10895 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
10896 return eRet;
10897 }
10898
10899 //static
describeColorFormat(OMX_PTR pParam)10900 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
10901
10902 #ifndef FLEXYUV_SUPPORTED
10903 (void) pParam;
10904 return OMX_ErrorUndefined;
10905 #else
10906
10907 if (pParam == NULL) {
10908 DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
10909 return OMX_ErrorBadParameter;
10910 }
10911
10912 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
10913
10914 MediaImage *img = &(params->sMediaImage);
10915 switch(params->eColorFormat) {
10916 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
10917 {
10918 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
10919 img->mNumPlanes = 3;
10920 // mWidth and mHeight represent the W x H of the largest plane
10921 // In our case, this happens to be the Stride x Scanlines of Y plane
10922 img->mWidth = params->nFrameWidth;
10923 img->mHeight = params->nFrameHeight;
10924 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
10925 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
10926 img->mBitDepth = 8;
10927 //Plane 0 (Y)
10928 img->mPlane[MediaImage::Y].mOffset = 0;
10929 img->mPlane[MediaImage::Y].mColInc = 1;
10930 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
10931 img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
10932 img->mPlane[MediaImage::Y].mVertSubsampling = 1;
10933 //Plane 1 (U)
10934 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
10935 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
10936 img->mPlane[MediaImage::U].mRowInc =
10937 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
10938 img->mPlane[MediaImage::U].mHorizSubsampling = 2;
10939 img->mPlane[MediaImage::U].mVertSubsampling = 2;
10940 //Plane 2 (V)
10941 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
10942 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
10943 img->mPlane[MediaImage::V].mRowInc =
10944 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
10945 img->mPlane[MediaImage::V].mHorizSubsampling = 2;
10946 img->mPlane[MediaImage::V].mVertSubsampling = 2;
10947 break;
10948 }
10949
10950 case OMX_COLOR_FormatYUV420Planar:
10951 case OMX_COLOR_FormatYUV420SemiPlanar:
10952 // We need not describe the standard OMX linear formats as these are
10953 // understood by client. Fail this deliberately to let client fill-in
10954 return OMX_ErrorUnsupportedSetting;
10955
10956 default:
10957 // Rest all formats which are non-linear cannot be described
10958 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
10959 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
10960 return OMX_ErrorNone;
10961 };
10962
10963 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
10964 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
10965 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
10966 for (size_t i = 0; i < img->mNumPlanes; ++i) {
10967 DEBUG_PRINT_LOW(" Plane[%d] : offset=%d / xStep=%d / yStep = %d",
10968 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
10969 }
10970 return OMX_ErrorNone;
10971 #endif //FLEXYUV_SUPPORTED
10972 }
10973