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