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