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