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