1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2016, 2018, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 /*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33 This module contains the implementation of the OpenMAX core & component.
34
35 *//*========================================================================*/
36
37 //////////////////////////////////////////////////////////////////////////////
38 // Include Files
39 //////////////////////////////////////////////////////////////////////////////
40
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <media/hardware/HardwareAPI.h>
55 #include <media/msm_media_info.h>
56 #include <sys/eventfd.h>
57 #include <nativebase/nativebase.h>
58
59 #ifndef _ANDROID_
60 #include <sys/ioctl.h>
61 #include <sys/mman.h>
62 #endif //_ANDROID_
63
64 #ifdef _ANDROID_
65 #include <cutils/properties.h>
66 #undef USE_EGL_IMAGE_GPU
67 #endif
68
69 #include <qdMetaData.h>
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/media/extradata";
87 #endif
88
89 #define DEFAULT_FPS 30
90 #define MAX_SUPPORTED_FPS 120
91 #define DEFAULT_WIDTH_ALIGNMENT 128
92 #define DEFAULT_HEIGHT_ALIGNMENT 32
93
94 #define VC1_SP_MP_START_CODE 0xC5000000
95 #define VC1_SP_MP_START_CODE_MASK 0xFF000000
96 #define VC1_AP_SEQ_START_CODE 0x0F010000
97 #define VC1_STRUCT_C_PROFILE_MASK 0xF0
98 #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
99 #define VC1_SIMPLE_PROFILE 0
100 #define VC1_MAIN_PROFILE 1
101 #define VC1_ADVANCE_PROFILE 3
102 #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
103 #define VC1_SIMPLE_PROFILE_MED_LEVEL 2
104 #define VC1_STRUCT_C_LEN 4
105 #define VC1_STRUCT_C_POS 8
106 #define VC1_STRUCT_A_POS 12
107 #define VC1_STRUCT_B_POS 24
108 #define VC1_SEQ_LAYER_SIZE 36
109 #define POLL_TIMEOUT 0x7fffffff
110
111 #define MEM_DEVICE "/dev/ion"
112
113 #ifdef _ANDROID_
114 extern "C" {
115 #include<utils/Log.h>
116 }
117 #endif//_ANDROID_
118
119 #define SZ_4K 0x1000
120 #define SZ_1M 0x100000
121
122 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
123 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
124 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
125 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
126
127 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA)
128 #define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
129
130 #ifndef ION_FLAG_CP_BITSTREAM
131 #define ION_FLAG_CP_BITSTREAM 0
132 #endif
133
134 #ifndef ION_FLAG_CP_PIXEL
135 #define ION_FLAG_CP_PIXEL 0
136 #endif
137
138 #ifdef MASTER_SIDE_CP
139 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
140 #define SECURE_ALIGN SZ_4K
141 #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
142 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
143 #else //SLAVE_SIDE_CP
144 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
145 #define SECURE_ALIGN SZ_1M
146 #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
147 #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
148 #endif
149
150 static OMX_U32 maxSmoothStreamingWidth = 1920;
151 static OMX_U32 maxSmoothStreamingHeight = 1088;
152
async_message_thread(void * input)153 void* async_message_thread (void *input)
154 {
155 OMX_BUFFERHEADERTYPE *buffer;
156 struct v4l2_plane plane[VIDEO_MAX_PLANES];
157 struct pollfd pfds[2];
158 struct v4l2_buffer v4l2_buf;
159 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
160 struct v4l2_event dqevent;
161 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
162 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
163 pfds[1].events = POLLIN | POLLERR;
164 pfds[0].fd = omx->drv_ctx.video_driver_fd;
165 pfds[1].fd = omx->m_poll_efd;
166 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
167 DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
168 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
169 while (!omx->async_thread_force_stop) {
170 rc = poll(pfds, 2, POLL_TIMEOUT);
171 if (!rc) {
172 DEBUG_PRINT_ERROR("Poll timedout");
173 break;
174 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
175 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
176 break;
177 }
178 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
179 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
180 break;
181 }
182 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
183 struct vdec_msginfo vdec_msg;
184 memset(&vdec_msg, 0, sizeof(vdec_msg));
185 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
186 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
187 v4l2_buf.length = omx->drv_ctx.num_planes;
188 v4l2_buf.m.planes = plane;
189 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
190 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
191 vdec_msg.status_code=VDEC_S_SUCCESS;
192 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
193 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
194 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
195 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
196 (uint64_t)v4l2_buf.timestamp.tv_usec;
197 if (vdec_msg.msgdata.output_frame.len) {
198 vdec_msg.msgdata.output_frame.framesize.left = plane[0].reserved[2];
199 vdec_msg.msgdata.output_frame.framesize.top = plane[0].reserved[3];
200 vdec_msg.msgdata.output_frame.framesize.right = plane[0].reserved[4];
201 vdec_msg.msgdata.output_frame.framesize.bottom = plane[0].reserved[5];
202 vdec_msg.msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
203 vdec_msg.msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
204 }
205 if (omx->async_message_process(input,&vdec_msg) < 0) {
206 DEBUG_PRINT_HIGH("async_message_thread Exited");
207 break;
208 }
209 }
210 }
211 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
212 struct vdec_msginfo vdec_msg;
213 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
214 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
215 v4l2_buf.length = 1;
216 v4l2_buf.m.planes = plane;
217 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
218 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
219 vdec_msg.status_code=VDEC_S_SUCCESS;
220 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
221 if (omx->async_message_process(input,&vdec_msg) < 0) {
222 DEBUG_PRINT_HIGH("async_message_thread Exited");
223 break;
224 }
225 }
226 }
227 if (pfds[0].revents & POLLPRI) {
228 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
229 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
230 struct vdec_msginfo vdec_msg;
231 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
232
233 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
234 vdec_msg.status_code=VDEC_S_SUCCESS;
235 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
236 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
237 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
238 if (omx->async_message_process(input,&vdec_msg) < 0) {
239 DEBUG_PRINT_HIGH("async_message_thread Exited");
240 break;
241 }
242 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT ) {
243 struct vdec_msginfo vdec_msg;
244 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
245 vdec_msg.status_code=VDEC_S_SUCCESS;
246 omx->dpb_bit_depth = dqevent.u.data[0];
247 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", dqevent.u.data[0]);
248 if (omx->async_message_process(input,&vdec_msg) < 0) {
249 DEBUG_PRINT_HIGH("async_message_thread Exited");
250 break;
251 }
252 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
253 struct vdec_msginfo vdec_msg;
254 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
255 vdec_msg.status_code=VDEC_S_SUCCESS;
256 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
257 if (omx->async_message_process(input,&vdec_msg) < 0) {
258 DEBUG_PRINT_HIGH("async_message_thread Exited");
259 break;
260 }
261 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
262 vdec_msg.status_code=VDEC_S_SUCCESS;
263 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
264 if (omx->async_message_process(input,&vdec_msg) < 0) {
265 DEBUG_PRINT_HIGH("async_message_thread Exited");
266 break;
267 }
268 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
269 struct vdec_msginfo vdec_msg;
270 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
271 vdec_msg.status_code=VDEC_S_SUCCESS;
272 DEBUG_PRINT_ERROR("HW Overload received");
273 if (omx->async_message_process(input,&vdec_msg) < 0) {
274 DEBUG_PRINT_HIGH("async_message_thread Exited");
275 break;
276 }
277 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
278 struct vdec_msginfo vdec_msg;
279 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
280 vdec_msg.status_code=VDEC_S_SUCCESS;
281 DEBUG_PRINT_ERROR("HW Unsupported received");
282 if (omx->async_message_process(input,&vdec_msg) < 0) {
283 DEBUG_PRINT_HIGH("async_message_thread Exited");
284 break;
285 }
286 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
287 struct vdec_msginfo vdec_msg;
288 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
289 vdec_msg.status_code = VDEC_S_SUCCESS;
290 DEBUG_PRINT_HIGH("SYS Error Recieved");
291 if (omx->async_message_process(input,&vdec_msg) < 0) {
292 DEBUG_PRINT_HIGH("async_message_thread Exited");
293 break;
294 }
295 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
296 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
297
298 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
299 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
300 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
301 struct vdec_msginfo vdec_msg;
302
303 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
304
305 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
306 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
307 v4l2_buf.length = omx->drv_ctx.num_planes;
308 v4l2_buf.m.planes = plane;
309 v4l2_buf.index = ptr[5];
310 v4l2_buf.flags = 0;
311
312 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
313 vdec_msg.status_code = VDEC_S_SUCCESS;
314 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
315 vdec_msg.msgdata.output_frame.len = 0;
316 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
317 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
318 (uint64_t)ptr[4];
319 if (omx->async_message_process(input,&vdec_msg) < 0) {
320 DEBUG_PRINT_HIGH("async_message_thread Exitedn");
321 break;
322 }
323 } else {
324 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
325 continue;
326 }
327 }
328 }
329 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
330 return NULL;
331 }
332
message_thread(void * input)333 void* message_thread(void *input)
334 {
335 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
336 unsigned char id;
337 int n;
338
339 fd_set readFds;
340 int res = 0;
341 struct timeval tv;
342
343 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
344 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
345 while (!omx->message_thread_stop) {
346
347 tv.tv_sec = 2;
348 tv.tv_usec = 0;
349
350 FD_ZERO(&readFds);
351 FD_SET(omx->m_pipe_in, &readFds);
352
353 res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
354 if (res < 0) {
355 DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
356 continue;
357 } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
358 continue;
359 }
360
361 n = read(omx->m_pipe_in, &id, 1);
362
363 if (0 == n) {
364 break;
365 }
366
367 if (1 == n) {
368 omx->process_event_cb(omx, id);
369 }
370
371 if ((n < 0) && (errno != EINTR)) {
372 DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
373 break;
374 }
375 }
376 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
377 return 0;
378 }
379
post_message(omx_vdec * omx,unsigned char id)380 void post_message(omx_vdec *omx, unsigned char id)
381 {
382 int ret_value;
383 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
384 ret_value = write(omx->m_pipe_out, &id, 1);
385 if (ret_value <= 0) {
386 DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
387 } else {
388 DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
389 }
390 }
391
392 // omx_cmd_queue destructor
~omx_cmd_queue()393 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
394 {
395 // Nothing to do
396 }
397
398 // omx cmd queue constructor
omx_cmd_queue()399 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
400 {
401 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
402 }
403
404 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)405 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
406 {
407 bool ret = true;
408 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
409 m_q[m_write].id = id;
410 m_q[m_write].param1 = p1;
411 m_q[m_write].param2 = p2;
412 m_write++;
413 m_size ++;
414 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
415 m_write = 0;
416 }
417 } else {
418 ret = false;
419 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
420 }
421 return ret;
422 }
423
424 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)425 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
426 {
427 bool ret = true;
428 if (m_size > 0) {
429 *id = m_q[m_read].id;
430 *p1 = m_q[m_read].param1;
431 *p2 = m_q[m_read].param2;
432 // Move the read pointer ahead
433 ++m_read;
434 --m_size;
435 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
436 m_read = 0;
437 }
438 } else {
439 ret = false;
440 }
441 return ret;
442 }
443
444 // Retrieve the first mesg type in the queue
get_q_msg_type()445 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
446 {
447 return m_q[m_read].id;
448 }
449
450 #ifdef _ANDROID_
ts_arr_list()451 omx_vdec::ts_arr_list::ts_arr_list()
452 {
453 //initialize timestamps array
454 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
455 }
~ts_arr_list()456 omx_vdec::ts_arr_list::~ts_arr_list()
457 {
458 //free m_ts_arr_list?
459 }
460
insert_ts(OMX_TICKS ts)461 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
462 {
463 bool ret = true;
464 bool duplicate_ts = false;
465 int idx = 0;
466
467 //insert at the first available empty location
468 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
469 if (!m_ts_arr_list[idx].valid) {
470 //found invalid or empty entry, save timestamp
471 m_ts_arr_list[idx].valid = true;
472 m_ts_arr_list[idx].timestamp = ts;
473 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
474 ts, idx);
475 break;
476 }
477 }
478
479 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
480 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
481 ret = false;
482 }
483 return ret;
484 }
485
pop_min_ts(OMX_TICKS & ts)486 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
487 {
488 bool ret = true;
489 int min_idx = -1;
490 OMX_TICKS min_ts = 0;
491 int idx = 0;
492
493 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
494
495 if (m_ts_arr_list[idx].valid) {
496 //found valid entry, save index
497 if (min_idx < 0) {
498 //first valid entry
499 min_ts = m_ts_arr_list[idx].timestamp;
500 min_idx = idx;
501 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
502 min_ts = m_ts_arr_list[idx].timestamp;
503 min_idx = idx;
504 }
505 }
506
507 }
508
509 if (min_idx < 0) {
510 //no valid entries found
511 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
512 ts = 0;
513 ret = false;
514 } else {
515 ts = m_ts_arr_list[min_idx].timestamp;
516 m_ts_arr_list[min_idx].valid = false;
517 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
518 ts, min_idx);
519 }
520
521 return ret;
522
523 }
524
525
reset_ts_list()526 bool omx_vdec::ts_arr_list::reset_ts_list()
527 {
528 bool ret = true;
529 int idx = 0;
530
531 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
532 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
533 m_ts_arr_list[idx].valid = false;
534 }
535 return ret;
536 }
537 #endif
538
539 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)540 void *get_omx_component_factory_fn(void)
541 {
542 return (new omx_vdec);
543 }
544
545 #ifdef _ANDROID_
546 #ifdef USE_ION
VideoHeap(int devicefd,size_t size,void * base,ion_user_handle_t handle,int ionMapfd)547 VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
548 ion_user_handle_t handle, int ionMapfd)
549 {
550 (void) devicefd;
551 (void) size;
552 (void) base;
553 (void) handle;
554 (void) ionMapfd;
555 // ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
556 }
557 #else
VideoHeap(int fd,size_t size,void * base)558 VideoHeap::VideoHeap(int fd, size_t size, void* base)
559 {
560 // dup file descriptor, map once, use pmem
561 init(dup(fd), base, size, 0 , MEM_DEVICE);
562 }
563 #endif
564 #endif // _ANDROID_
565 /* ======================================================================
566 FUNCTION
567 omx_vdec::omx_vdec
568
569 DESCRIPTION
570 Constructor
571
572 PARAMETERS
573 None
574
575 RETURN VALUE
576 None.
577 ========================================================================== */
omx_vdec()578 omx_vdec::omx_vdec(): m_error_propogated(false),
579 m_state(OMX_StateInvalid),
580 m_app_data(NULL),
581 m_inp_mem_ptr(NULL),
582 m_out_mem_ptr(NULL),
583 input_flush_progress (false),
584 output_flush_progress (false),
585 input_use_buffer (false),
586 output_use_buffer (false),
587 ouput_egl_buffers(false),
588 m_use_output_pmem(OMX_FALSE),
589 m_out_mem_region_smi(OMX_FALSE),
590 m_out_pvt_entry_pmem(OMX_FALSE),
591 pending_input_buffers(0),
592 pending_output_buffers(0),
593 m_out_bm_count(0),
594 m_inp_bm_count(0),
595 m_inp_bPopulated(OMX_FALSE),
596 m_out_bPopulated(OMX_FALSE),
597 m_flags(0),
598 #ifdef _ANDROID_
599 m_heap_ptr(NULL),
600 #endif
601 m_inp_bEnabled(OMX_TRUE),
602 m_out_bEnabled(OMX_TRUE),
603 m_in_alloc_cnt(0),
604 m_platform_list(NULL),
605 m_platform_entry(NULL),
606 m_pmem_info(NULL),
607 h264_parser(NULL),
608 arbitrary_bytes (true),
609 psource_frame (NULL),
610 pdest_frame (NULL),
611 m_inp_heap_ptr (NULL),
612 m_phdr_pmem_ptr(NULL),
613 m_heap_inp_bm_count (0),
614 codec_type_parse ((codec_type)0),
615 first_frame_meta (true),
616 frame_count (0),
617 nal_count (0),
618 nal_length(0),
619 look_ahead_nal (false),
620 first_frame(0),
621 first_buffer(NULL),
622 first_frame_size (0),
623 m_device_file_ptr(NULL),
624 m_vc1_profile((vc1_profile_type)0),
625 h264_last_au_ts(LLONG_MAX),
626 h264_last_au_flags(0),
627 m_disp_hor_size(0),
628 m_disp_vert_size(0),
629 prev_ts(LLONG_MAX),
630 prev_ts_actual(LLONG_MAX),
631 rst_prev_ts(true),
632 frm_int(0),
633 in_reconfig(false),
634 m_display_id(NULL),
635 client_extradata(0),
636 m_reject_avc_1080p_mp (0),
637 #ifdef _ANDROID_
638 m_enable_android_native_buffers(OMX_FALSE),
639 m_use_android_native_buffers(OMX_FALSE),
640 #endif
641 m_desc_buffer_ptr(NULL),
642 secure_mode(false),
643 allocate_native_handle(false),
644 m_other_extradata(NULL),
645 m_profile(0),
646 client_set_fps(false),
647 m_last_rendered_TS(-1),
648 m_queued_codec_config_count(0),
649 current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
650 secure_scaling_to_non_secure_opb(false),
651 m_force_compressed_for_dpb(false),
652 m_buffer_error(false)
653 {
654 m_pipe_in = -1;
655 m_pipe_out = -1;
656 m_poll_efd = -1;
657 drv_ctx.video_driver_fd = -1;
658 drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
659 /* Assumption is that , to begin with , we have all the frames with decoder */
660 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
661 memset(&m_debug,0,sizeof(m_debug));
662 #ifdef _ANDROID_
663 char property_value[PROPERTY_VALUE_MAX] = {0};
664 property_get("vidc.debug.level", property_value, "1");
665 debug_level = atoi(property_value);
666 property_value[0] = '\0';
667
668 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
669
670 property_get("vidc.dec.debug.perf", property_value, "0");
671 perf_flag = atoi(property_value);
672 if (perf_flag) {
673 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
674 dec_time.start();
675 proc_frms = latency = 0;
676 }
677 prev_n_filled_len = 0;
678 property_value[0] = '\0';
679 property_get("vidc.dec.debug.ts", property_value, "0");
680 m_debug_timestamp = atoi(property_value);
681 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
682 if (m_debug_timestamp) {
683 time_stamp_dts.set_timestamp_reorder_mode(true);
684 time_stamp_dts.enable_debug_print(true);
685 }
686
687 property_value[0] = '\0';
688 property_get("vidc.dec.debug.concealedmb", property_value, "0");
689 m_debug_concealedmb = atoi(property_value);
690 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
691
692 property_value[0] = '\0';
693 property_get("vidc.dec.profile.check", property_value, "0");
694 m_reject_avc_1080p_mp = atoi(property_value);
695 DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
696
697 property_value[0] = '\0';
698 property_get("vidc.dec.log.in", property_value, "0");
699 m_debug.in_buffer_log = atoi(property_value);
700
701 property_value[0] = '\0';
702 property_get("vidc.dec.log.out", property_value, "0");
703 m_debug.out_buffer_log = atoi(property_value);
704 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
705
706 property_value[0] = '\0';
707 property_get("vidc.dec.meta.log.out", property_value, "0");
708 m_debug.out_meta_buffer_log = atoi(property_value);
709 snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
710
711 property_value[0] = '\0';
712 property_get("vidc.log.loc", property_value, "");
713 if (*property_value)
714 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
715
716 property_value[0] = '\0';
717 property_get("vidc.dec.120fps.enabled", property_value, "0");
718
719 //if this feature is not enabled then reset this value -ve
720 if(atoi(property_value)) {
721 DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
722 m_last_rendered_TS = 0;
723 }
724
725 property_value[0] = '\0';
726 property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
727 m_disable_dynamic_buf_mode = atoi(property_value);
728 DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
729
730 #ifdef _UBWC_
731 property_value[0] = '\0';
732 property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
733 m_disable_ubwc_mode = atoi(property_value);
734 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
735 #else
736 m_disable_ubwc_mode = true;
737 #endif
738 #endif
739 memset(&m_cmp,0,sizeof(m_cmp));
740 memset(&m_cb,0,sizeof(m_cb));
741 memset (&drv_ctx,0,sizeof(drv_ctx));
742 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
743 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
744 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
745 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
746 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
747 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
748 m_demux_entries = 0;
749 msg_thread_id = 0;
750 async_thread_id = 0;
751 msg_thread_created = false;
752 async_thread_created = false;
753 async_thread_force_stop = false;
754 message_thread_stop = false;
755 #ifdef _ANDROID_ICS_
756 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
757 #endif
758 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
759
760 /* invalidate m_frame_pack_arrangement */
761 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
762 m_frame_pack_arrangement.cancel_flag = 1;
763
764 drv_ctx.timestamp_adjust = false;
765 m_vendor_config.pData = NULL;
766 pthread_mutex_init(&m_lock, NULL);
767 pthread_mutex_init(&c_lock, NULL);
768 pthread_mutex_init(&buf_lock, NULL);
769 sem_init(&m_cmd_lock,0,0);
770 sem_init(&m_safe_flush, 0, 0);
771 streaming[CAPTURE_PORT] =
772 streaming[OUTPUT_PORT] = false;
773 #ifdef _ANDROID_
774 char extradata_value[PROPERTY_VALUE_MAX] = {0};
775 property_get("vidc.dec.debug.extradata", extradata_value, "0");
776 m_debug_extradata = atoi(extradata_value);
777 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
778 #endif
779 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
780 client_buffers.set_vdec_client(this);
781 dynamic_buf_mode = false;
782 out_dynamic_list = NULL;
783 is_down_scalar_enabled = false;
784 m_downscalar_width = 0;
785 m_downscalar_height = 0;
786 m_force_down_scalar = 0;
787 m_reconfig_height = 0;
788 m_reconfig_width = 0;
789 m_smoothstreaming_mode = false;
790 m_smoothstreaming_width = 0;
791 m_smoothstreaming_height = 0;
792 m_decode_order_mode = false;
793 is_q6_platform = false;
794 m_perf_control.send_hint_to_mpctl(true);
795 m_input_pass_buffer_fd = false;
796 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
797 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
798 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
799 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
800 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
801
802 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
803 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
804 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
805 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
806 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
807 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
808 }
809
810 static const int event_type[] = {
811 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
812 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
813 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
814 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
815 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
816 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
817 V4L2_EVENT_MSM_VIDC_SYS_ERROR,
818 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
819 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
820 };
821
subscribe_to_events(int fd)822 static OMX_ERRORTYPE subscribe_to_events(int fd)
823 {
824 OMX_ERRORTYPE eRet = OMX_ErrorNone;
825 struct v4l2_event_subscription sub;
826 int array_sz = sizeof(event_type)/sizeof(int);
827 int i,rc;
828 if (fd < 0) {
829 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
830 return OMX_ErrorBadParameter;
831 }
832
833 for (i = 0; i < array_sz; ++i) {
834 memset(&sub, 0, sizeof(sub));
835 sub.type = event_type[i];
836 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
837 if (rc) {
838 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
839 break;
840 }
841 }
842 if (i < array_sz) {
843 for (--i; i >=0 ; i--) {
844 memset(&sub, 0, sizeof(sub));
845 sub.type = event_type[i];
846 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
847 if (rc)
848 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
849 }
850 eRet = OMX_ErrorNotImplemented;
851 }
852 return eRet;
853 }
854
855
unsubscribe_to_events(int fd)856 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
857 {
858 OMX_ERRORTYPE eRet = OMX_ErrorNone;
859 struct v4l2_event_subscription sub;
860 int array_sz = sizeof(event_type)/sizeof(int);
861 int i,rc;
862 if (fd < 0) {
863 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
864 return OMX_ErrorBadParameter;
865 }
866
867 for (i = 0; i < array_sz; ++i) {
868 memset(&sub, 0, sizeof(sub));
869 sub.type = event_type[i];
870 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
871 if (rc) {
872 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
873 break;
874 }
875 }
876 return eRet;
877 }
878
879 /* ======================================================================
880 FUNCTION
881 omx_vdec::~omx_vdec
882
883 DESCRIPTION
884 Destructor
885
886 PARAMETERS
887 None
888
889 RETURN VALUE
890 None.
891 ========================================================================== */
~omx_vdec()892 omx_vdec::~omx_vdec()
893 {
894 m_pmem_info = NULL;
895 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
896 if (msg_thread_created) {
897 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
898 message_thread_stop = true;
899 post_message(this, OMX_COMPONENT_CLOSE_MSG);
900 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
901 pthread_join(msg_thread_id,NULL);
902 }
903 close(m_pipe_in);
904 close(m_pipe_out);
905 m_pipe_in = -1;
906 m_pipe_out = -1;
907 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
908 if(eventfd_write(m_poll_efd, 1)) {
909 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
910 async_thread_force_stop = true;
911 }
912
913 if (async_thread_created)
914 pthread_join(async_thread_id,NULL);
915 unsubscribe_to_events(drv_ctx.video_driver_fd);
916 close(m_poll_efd);
917 close(drv_ctx.video_driver_fd);
918 pthread_mutex_destroy(&m_lock);
919 pthread_mutex_destroy(&c_lock);
920 pthread_mutex_destroy(&buf_lock);
921 sem_destroy(&m_cmd_lock);
922 if (perf_flag) {
923 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
924 dec_time.end();
925 }
926 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
927 m_perf_control.send_hint_to_mpctl(false);
928 }
929
release_buffers(omx_vdec * obj,enum vdec_buffer buffer_type)930 int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
931 {
932 struct v4l2_requestbuffers bufreq;
933 int rc = 0;
934 if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
935 bufreq.memory = V4L2_MEMORY_USERPTR;
936 bufreq.count = 0;
937 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
938 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
939 } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
940 bufreq.memory = V4L2_MEMORY_USERPTR;
941 bufreq.count = 0;
942 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
943 rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
944 }
945 return rc;
946 }
947
set_dpb(bool is_split_mode,int dpb_color_format)948 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
949 {
950 int rc = 0;
951 struct v4l2_ext_control ctrl[2];
952 struct v4l2_ext_controls controls;
953
954 DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
955 is_split_mode ? "split" : "combined",
956 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
957 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
958 dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
959 "unknown",
960 capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
961 capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
962 "unknown");
963
964 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
965 if (is_split_mode) {
966 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
967 } else {
968 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
969 }
970
971 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
972 ctrl[1].value = dpb_color_format;
973
974 controls.count = 2;
975 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
976 controls.controls = ctrl;
977
978 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
979 if (rc) {
980 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
981 return OMX_ErrorUnsupportedSetting;
982 }
983 return OMX_ErrorNone;
984 }
985
986
decide_dpb_buffer_mode(bool force_split_mode)987 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
988 {
989 OMX_ERRORTYPE eRet = OMX_ErrorNone;
990
991 bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC;
992
993 bool is_res_above_1080p = (drv_ctx.video_resolution.frame_width > 1920 &&
994 drv_ctx.video_resolution.frame_height > 1088) ||
995 (drv_ctx.video_resolution.frame_height > 1088 &&
996 drv_ctx.video_resolution.frame_width > 1920);
997
998 if (cpu_access) {
999 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1000 if ((m_force_compressed_for_dpb || is_res_above_1080p) &&
1001 !force_split_mode) {
1002 //split DPB-OPB
1003 //DPB -> UBWC , OPB -> Linear
1004 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1005 } else if (force_split_mode) {
1006 //DPB -> Linear, OPB -> Linear
1007 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1008 } else {
1009 //DPB-OPB combined linear
1010 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1011 }
1012 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1013 //split DPB-OPB
1014 //DPB -> UBWC, OPB -> Linear
1015 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1016 }
1017 } else { //no cpu access
1018 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
1019 if (force_split_mode) {
1020 //split DPB-OPB
1021 //DPB -> UBWC, OPB -> UBWC
1022 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
1023 } else {
1024 //DPB-OPB combined UBWC
1025 eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
1026 }
1027 } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1028 //split DPB-OPB
1029 //DPB -> UBWC, OPB -> UBWC
1030 eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
1031 }
1032 }
1033 if (eRet) {
1034 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1035 }
1036 return eRet;
1037 }
1038
enable_downscalar()1039 int omx_vdec::enable_downscalar()
1040 {
1041 int rc = 0;
1042 struct v4l2_control control;
1043 struct v4l2_format fmt;
1044
1045 if (is_down_scalar_enabled) {
1046 DEBUG_PRINT_LOW("%s: already enabled", __func__);
1047 return 0;
1048 }
1049
1050 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1051 rc = decide_dpb_buffer_mode(true);
1052 if (rc) {
1053 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1054 return rc;
1055 }
1056 is_down_scalar_enabled = true;
1057
1058 memset(&control, 0x0, sizeof(struct v4l2_control));
1059 control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
1060 control.value = 1;
1061 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
1062 if (rc) {
1063 DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
1064 return rc;
1065 }
1066
1067 return 0;
1068 }
1069
disable_downscalar()1070 int omx_vdec::disable_downscalar()
1071 {
1072 int rc = 0;
1073 struct v4l2_control control;
1074
1075 if (!is_down_scalar_enabled) {
1076 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1077 return 0;
1078 }
1079
1080 rc = decide_dpb_buffer_mode(false);
1081 if (rc < 0) {
1082 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1083 return rc;
1084 }
1085 is_down_scalar_enabled = false;
1086
1087 return rc;
1088 }
1089
decide_downscalar()1090 int omx_vdec::decide_downscalar()
1091 {
1092 int rc = 0;
1093 struct v4l2_format fmt;
1094 enum color_fmts color_format;
1095
1096 if (!m_downscalar_width || !m_downscalar_height) {
1097 DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
1098 return 0;
1099 }
1100
1101 if (m_force_down_scalar) {
1102 DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1103 return 0;
1104 }
1105
1106 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1107 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1108 fmt.fmt.pix_mp.pixelformat = capture_capability;
1109 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1110 if (rc < 0) {
1111 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1112 return rc;
1113 }
1114
1115 DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__,
1116 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height);
1117
1118 if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) {
1119 rc = enable_downscalar();
1120 if (rc < 0) {
1121 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1122 return rc;
1123 }
1124
1125 OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1126 fmt.fmt.pix_mp.width : m_downscalar_width;
1127 OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1128 fmt.fmt.pix_mp.height : m_downscalar_height;
1129 switch (capture_capability) {
1130 case V4L2_PIX_FMT_NV12:
1131 color_format = COLOR_FMT_NV12;
1132 break;
1133 case V4L2_PIX_FMT_NV12_UBWC:
1134 color_format = COLOR_FMT_NV12_UBWC;
1135 break;
1136 case V4L2_PIX_FMT_NV12_TP10_UBWC:
1137 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1138 break;
1139 default:
1140 DEBUG_PRINT_ERROR("Color format not recognized\n");
1141 rc = OMX_ErrorUndefined;
1142 return rc;
1143 }
1144
1145 rc = update_resolution(width, height,
1146 VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height));
1147 if (rc < 0) {
1148 DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height);
1149 return rc;
1150 }
1151 } else {
1152
1153 rc = disable_downscalar();
1154 if (rc < 0) {
1155 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1156 return rc;
1157 }
1158
1159 rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
1160 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
1161 if (rc < 0) {
1162 DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width,
1163 fmt.fmt.pix_mp.height);
1164 return rc;
1165 }
1166 }
1167
1168 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1169 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1170 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1171 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1172 fmt.fmt.pix_mp.pixelformat = capture_capability;
1173 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1174 if (rc) {
1175 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1176 return rc;
1177 }
1178
1179 rc = get_buffer_req(&drv_ctx.op_buf);
1180 if (rc) {
1181 DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1182 return rc;
1183 }
1184
1185 return rc;
1186 }
1187
1188 /* ======================================================================
1189 FUNCTION
1190 omx_vdec::OMXCntrlProcessMsgCb
1191
1192 DESCRIPTION
1193 IL Client callbacks are generated through this routine. The decoder
1194 provides the thread context for this routine.
1195
1196 PARAMETERS
1197 ctxt -- Context information related to the self.
1198 id -- Event identifier. This could be any of the following:
1199 1. Command completion event
1200 2. Buffer done callback event
1201 3. Frame done callback event
1202
1203 RETURN VALUE
1204 None.
1205
1206 ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)1207 void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
1208 {
1209 unsigned long p1; // Parameter - 1
1210 unsigned long p2; // Parameter - 2
1211 unsigned long ident;
1212 unsigned qsize=0; // qsize
1213 omx_vdec *pThis = (omx_vdec *) ctxt;
1214
1215 if (!pThis) {
1216 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1217 __func__);
1218 return;
1219 }
1220
1221 // Protect the shared queue data structure
1222 do {
1223 /*Read the message id's from the queue*/
1224 pthread_mutex_lock(&pThis->m_lock);
1225 qsize = pThis->m_cmd_q.m_size;
1226 if (qsize) {
1227 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1228 }
1229
1230 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1231 qsize = pThis->m_ftb_q.m_size;
1232 if (qsize) {
1233 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1234 }
1235 }
1236
1237 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1238 qsize = pThis->m_etb_q.m_size;
1239 if (qsize) {
1240 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1241 }
1242 }
1243 pthread_mutex_unlock(&pThis->m_lock);
1244
1245 /*process message if we have one*/
1246 if (qsize > 0) {
1247 id = ident;
1248 switch (id) {
1249 case OMX_COMPONENT_GENERATE_EVENT:
1250 if (pThis->m_cb.EventHandler) {
1251 switch (p1) {
1252 case OMX_CommandStateSet:
1253 pThis->m_state = (OMX_STATETYPE) p2;
1254 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1255 pThis->m_state);
1256 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1257 OMX_EventCmdComplete, p1, p2, NULL);
1258 break;
1259
1260 case OMX_EventError:
1261 if (p2 == OMX_StateInvalid) {
1262 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1263 pThis->m_state = (OMX_STATETYPE) p2;
1264 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1265 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1266 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1267 pThis->omx_report_error();
1268 } else {
1269 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1270 OMX_EventError, p2, (OMX_U32)NULL, NULL );
1271 }
1272 break;
1273
1274 case OMX_CommandPortDisable:
1275 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1276 if (BITMASK_PRESENT(&pThis->m_flags,
1277 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1278 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1279 break;
1280 }
1281 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1282 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1283 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1284 if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
1285 DEBUG_PRINT_HIGH("Failed to release output buffers");
1286 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1287 pThis->in_reconfig = false;
1288 if (eRet != OMX_ErrorNone) {
1289 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1290 pThis->omx_report_error();
1291 break;
1292 }
1293 }
1294 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1295 OMX_EventCmdComplete, p1, p2, NULL );
1296 break;
1297 case OMX_CommandPortEnable:
1298 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1299 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1300 OMX_EventCmdComplete, p1, p2, NULL );
1301 break;
1302
1303 default:
1304 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1305 OMX_EventCmdComplete, p1, p2, NULL );
1306 break;
1307
1308 }
1309 } else {
1310 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1311 }
1312 break;
1313 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1314 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1315 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1316 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1317 pThis->omx_report_error ();
1318 }
1319 break;
1320 case OMX_COMPONENT_GENERATE_ETB: {
1321 OMX_ERRORTYPE iret;
1322 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1323 if (iret == OMX_ErrorInsufficientResources) {
1324 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1325 pThis->omx_report_hw_overload ();
1326 } else if (iret != OMX_ErrorNone) {
1327 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1328 pThis->omx_report_error ();
1329 }
1330 }
1331 break;
1332
1333 case OMX_COMPONENT_GENERATE_FTB:
1334 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1335 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1336 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1337 pThis->omx_report_error ();
1338 }
1339 break;
1340
1341 case OMX_COMPONENT_GENERATE_COMMAND:
1342 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1343 (OMX_U32)p2,(OMX_PTR)NULL);
1344 break;
1345
1346 case OMX_COMPONENT_GENERATE_EBD:
1347
1348 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1349 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1350 pThis->omx_report_error ();
1351 } else {
1352 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1353 pThis->time_stamp_dts.remove_time_stamp(
1354 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1355 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1356 ?true:false);
1357 }
1358
1359 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1360 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1361 DEBUG_PRINT_ERROR("empty_buffer_done failure");
1362 pThis->omx_report_error ();
1363 }
1364 }
1365 break;
1366 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1367 int64_t *timestamp = (int64_t *)(intptr_t)p1;
1368 if (p1) {
1369 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1370 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1371 ?true:false);
1372 free(timestamp);
1373 }
1374 }
1375 break;
1376 case OMX_COMPONENT_GENERATE_FBD:
1377 if (p2 != VDEC_S_SUCCESS) {
1378 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1379 pThis->omx_report_error ();
1380 } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1381 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1382 DEBUG_PRINT_ERROR("fill_buffer_done failure");
1383 pThis->omx_report_error ();
1384 }
1385 break;
1386
1387 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1388 DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
1389 if (!pThis->input_flush_progress) {
1390 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1391 } else {
1392 pThis->execute_input_flush();
1393 if (pThis->m_cb.EventHandler) {
1394 if (p2 != VDEC_S_SUCCESS) {
1395 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1396 pThis->omx_report_error ();
1397 } else {
1398 /*Check if we need generate event for Flush done*/
1399 pThis->notify_flush_done(ctxt);
1400
1401 if (BITMASK_PRESENT(&pThis->m_flags,
1402 OMX_COMPONENT_IDLE_PENDING)) {
1403 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1404 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1405 pThis->omx_report_error ();
1406 } else {
1407 pThis->streaming[OUTPUT_PORT] = false;
1408 }
1409 if (!pThis->output_flush_progress) {
1410 DEBUG_PRINT_LOW("Input flush done hence issue stop");
1411 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1412 OMX_COMPONENT_GENERATE_STOP_DONE);
1413 }
1414 }
1415 }
1416 } else {
1417 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1418 }
1419 }
1420 break;
1421
1422 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1423 DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
1424 if (!pThis->output_flush_progress) {
1425 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1426 } else {
1427 pThis->execute_output_flush();
1428 if (pThis->m_cb.EventHandler) {
1429 if (p2 != VDEC_S_SUCCESS) {
1430 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1431 pThis->omx_report_error ();
1432 } else {
1433 /*Check if we need generate event for Flush done*/
1434 pThis->notify_flush_done(ctxt);
1435
1436 if (BITMASK_PRESENT(&pThis->m_flags,
1437 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1438 DEBUG_PRINT_LOW("Internal flush complete");
1439 BITMASK_CLEAR (&pThis->m_flags,
1440 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1441 if (BITMASK_PRESENT(&pThis->m_flags,
1442 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1443 pThis->post_event(OMX_CommandPortDisable,
1444 OMX_CORE_OUTPUT_PORT_INDEX,
1445 OMX_COMPONENT_GENERATE_EVENT);
1446 BITMASK_CLEAR (&pThis->m_flags,
1447 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1448 BITMASK_CLEAR (&pThis->m_flags,
1449 OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1450
1451 }
1452 }
1453
1454 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1455 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1456 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1457 pThis->omx_report_error ();
1458 break;
1459 }
1460 pThis->streaming[CAPTURE_PORT] = false;
1461 if (!pThis->input_flush_progress) {
1462 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1463 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1464 OMX_COMPONENT_GENERATE_STOP_DONE);
1465 }
1466 }
1467 }
1468 } else {
1469 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1470 }
1471 }
1472 break;
1473
1474 case OMX_COMPONENT_GENERATE_START_DONE:
1475 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
1476
1477 if (pThis->m_cb.EventHandler) {
1478 if (p2 != VDEC_S_SUCCESS) {
1479 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1480 pThis->omx_report_error ();
1481 } else {
1482 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1483 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1484 DEBUG_PRINT_LOW("Move to executing");
1485 // Send the callback now
1486 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1487 pThis->m_state = OMX_StateExecuting;
1488 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1489 OMX_EventCmdComplete,OMX_CommandStateSet,
1490 OMX_StateExecuting, NULL);
1491 } else if (BITMASK_PRESENT(&pThis->m_flags,
1492 OMX_COMPONENT_PAUSE_PENDING)) {
1493 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1494 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1495 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1496 pThis->omx_report_error ();
1497 }
1498 }
1499 }
1500 } else {
1501 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1502 }
1503 break;
1504
1505 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1506 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1507 if (pThis->m_cb.EventHandler) {
1508 if (p2 != VDEC_S_SUCCESS) {
1509 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1510 pThis->omx_report_error ();
1511 } else {
1512 pThis->complete_pending_buffer_done_cbs();
1513 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1514 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1515 //Send the callback now
1516 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1517 pThis->m_state = OMX_StatePause;
1518 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1519 OMX_EventCmdComplete,OMX_CommandStateSet,
1520 OMX_StatePause, NULL);
1521 }
1522 }
1523 } else {
1524 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1525 }
1526
1527 break;
1528
1529 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1530 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1531 if (pThis->m_cb.EventHandler) {
1532 if (p2 != VDEC_S_SUCCESS) {
1533 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1534 pThis->omx_report_error ();
1535 } else {
1536 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1537 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1538 // Send the callback now
1539 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1540 pThis->m_state = OMX_StateExecuting;
1541 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1542 OMX_EventCmdComplete,OMX_CommandStateSet,
1543 OMX_StateExecuting,NULL);
1544 }
1545 }
1546 } else {
1547 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1548 }
1549
1550 break;
1551
1552 case OMX_COMPONENT_GENERATE_STOP_DONE:
1553 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1554 if (pThis->m_cb.EventHandler) {
1555 if (p2 != VDEC_S_SUCCESS) {
1556 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1557 pThis->omx_report_error ();
1558 } else {
1559 pThis->complete_pending_buffer_done_cbs();
1560 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1561 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1562 // Send the callback now
1563 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1564 pThis->m_state = OMX_StateIdle;
1565 DEBUG_PRINT_LOW("Move to Idle State");
1566 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1567 OMX_EventCmdComplete,OMX_CommandStateSet,
1568 OMX_StateIdle,NULL);
1569 }
1570 }
1571 } else {
1572 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1573 }
1574
1575 break;
1576
1577 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1578 if (p2 == OMX_IndexParamPortDefinition) {
1579 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1580 pThis->in_reconfig = true;
1581 } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1582 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1583
1584 /* Check if resolution is changed in smooth streaming mode */
1585 if (pThis->m_smoothstreaming_mode &&
1586 (pThis->framesize.nWidth !=
1587 pThis->drv_ctx.video_resolution.frame_width) ||
1588 (pThis->framesize.nHeight !=
1589 pThis->drv_ctx.video_resolution.frame_height)) {
1590
1591 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1592 pThis->framesize.nWidth,
1593 pThis->framesize.nHeight,
1594 pThis->drv_ctx.video_resolution.frame_width,
1595 pThis->drv_ctx.video_resolution.frame_height);
1596
1597 /* Update new resolution */
1598 pThis->framesize.nWidth =
1599 pThis->drv_ctx.video_resolution.frame_width;
1600 pThis->framesize.nHeight =
1601 pThis->drv_ctx.video_resolution.frame_height;
1602
1603 /* Update C2D with new resolution */
1604 if (!pThis->client_buffers.update_buffer_req()) {
1605 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1606 }
1607 }
1608
1609 /* Update new crop information */
1610 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1611 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1612 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1613 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1614
1615 /* Validate the new crop information */
1616 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1617 pThis->drv_ctx.video_resolution.frame_width) {
1618
1619 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1620 pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1621 pThis->drv_ctx.video_resolution.frame_width);
1622 pThis->rectangle.nLeft = 0;
1623
1624 if (pThis->rectangle.nWidth >
1625 pThis->drv_ctx.video_resolution.frame_width) {
1626
1627 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1628 pThis->rectangle.nWidth,
1629 pThis->drv_ctx.video_resolution.frame_width);
1630 pThis->rectangle.nWidth =
1631 pThis->drv_ctx.video_resolution.frame_width;
1632 }
1633 }
1634 if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1635 pThis->drv_ctx.video_resolution.frame_height) {
1636
1637 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1638 pThis->rectangle.nTop, pThis->rectangle.nHeight,
1639 pThis->drv_ctx.video_resolution.frame_height);
1640 pThis->rectangle.nTop = 0;
1641
1642 if (pThis->rectangle.nHeight >
1643 pThis->drv_ctx.video_resolution.frame_height) {
1644
1645 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1646 pThis->rectangle.nHeight,
1647 pThis->drv_ctx.video_resolution.frame_height);
1648 pThis->rectangle.nHeight =
1649 pThis->drv_ctx.video_resolution.frame_height;
1650 }
1651 }
1652 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1653 pThis->rectangle.nLeft, pThis->rectangle.nTop,
1654 pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1655 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1656 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1657 } else {
1658 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1659 break;
1660 }
1661 if (pThis->m_debug.outfile) {
1662 fclose(pThis->m_debug.outfile);
1663 pThis->m_debug.outfile = NULL;
1664 }
1665 if (pThis->m_debug.out_ymeta_file) {
1666 fclose(pThis->m_debug.out_ymeta_file);
1667 pThis->m_debug.out_ymeta_file = NULL;
1668 }
1669 if (pThis->m_debug.out_uvmeta_file) {
1670 fclose(pThis->m_debug.out_uvmeta_file);
1671 pThis->m_debug.out_uvmeta_file = NULL;
1672 }
1673
1674 if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
1675 pThis->prefetchNewBuffers();
1676 }
1677
1678 if (pThis->m_cb.EventHandler) {
1679 uint32_t frame_data[2];
1680 frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
1681 pThis->m_reconfig_height : pThis->rectangle.nHeight;
1682 frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
1683 pThis->m_reconfig_width : pThis->rectangle.nWidth;
1684 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1685 OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
1686 } else {
1687 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1688 }
1689 break;
1690
1691 case OMX_COMPONENT_GENERATE_EOS_DONE:
1692 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1693 if (pThis->m_cb.EventHandler) {
1694 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1695 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1696 } else {
1697 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1698 }
1699 pThis->prev_ts = LLONG_MAX;
1700 pThis->rst_prev_ts = true;
1701 break;
1702
1703 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1704 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1705 pThis->omx_report_error();
1706 break;
1707
1708 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1709 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1710 pThis->omx_report_unsupported_setting();
1711 break;
1712
1713 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1714 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1715 pThis->omx_report_hw_overload();
1716 break;
1717
1718 default:
1719 break;
1720 }
1721 }
1722 pthread_mutex_lock(&pThis->m_lock);
1723 qsize = pThis->m_cmd_q.m_size;
1724 if (pThis->m_state != OMX_StatePause)
1725 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1726 pthread_mutex_unlock(&pThis->m_lock);
1727 } while (qsize>0);
1728
1729 }
1730
update_resolution(int width,int height,int stride,int scan_lines)1731 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1732 {
1733 int format_changed = 0;
1734 if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1735 (width != (int)drv_ctx.video_resolution.frame_width)) {
1736 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1737 width, drv_ctx.video_resolution.frame_width,
1738 height,drv_ctx.video_resolution.frame_height);
1739 format_changed = 1;
1740 }
1741 drv_ctx.video_resolution.frame_height = height;
1742 drv_ctx.video_resolution.frame_width = width;
1743 drv_ctx.video_resolution.scan_lines = scan_lines;
1744 drv_ctx.video_resolution.stride = stride;
1745 if(!is_down_scalar_enabled) {
1746 rectangle.nLeft = 0;
1747 rectangle.nTop = 0;
1748 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
1749 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
1750 }
1751 return format_changed;
1752 }
1753
is_video_session_supported()1754 OMX_ERRORTYPE omx_vdec::is_video_session_supported()
1755 {
1756 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
1757 OMX_MAX_STRINGNAME_SIZE) &&
1758 (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
1759 m_decoder_capability.max_width = 1280;
1760 m_decoder_capability.max_height = 720;
1761 DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
1762 }
1763
1764 if ((drv_ctx.video_resolution.frame_width *
1765 drv_ctx.video_resolution.frame_height >
1766 m_decoder_capability.max_width *
1767 m_decoder_capability.max_height) ||
1768 (drv_ctx.video_resolution.frame_width*
1769 drv_ctx.video_resolution.frame_height <
1770 m_decoder_capability.min_width *
1771 m_decoder_capability.min_height)) {
1772 DEBUG_PRINT_ERROR(
1773 "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
1774 drv_ctx.video_resolution.frame_width,
1775 drv_ctx.video_resolution.frame_height,
1776 m_decoder_capability.min_width,
1777 m_decoder_capability.min_height,
1778 m_decoder_capability.max_width,
1779 m_decoder_capability.max_height);
1780 return OMX_ErrorUnsupportedSetting;
1781 }
1782 DEBUG_PRINT_HIGH("video session supported");
1783 return OMX_ErrorNone;
1784 }
1785
log_input_buffers(const char * buffer_addr,int buffer_len)1786 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
1787 {
1788 if (m_debug.in_buffer_log && !m_debug.infile) {
1789 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
1790 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
1791 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1792 } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
1793 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
1794 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1795 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
1796 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
1797 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1798 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
1799 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
1800 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
1801 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1802 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
1803 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
1804 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1805 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
1806 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1807 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1808 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
1809 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
1810 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1811 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
1812 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1813 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1814 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1815 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
1816 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1817 } else {
1818 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
1819 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1820 }
1821 m_debug.infile = fopen (m_debug.infile_name, "ab");
1822 if (!m_debug.infile) {
1823 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
1824 m_debug.infile_name[0] = '\0';
1825 return -1;
1826 }
1827 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1828 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1829 struct ivf_file_header {
1830 OMX_U8 signature[4]; //='DKIF';
1831 OMX_U8 version ; //= 0;
1832 OMX_U8 headersize ; //= 32;
1833 OMX_U32 FourCC;
1834 OMX_U8 width;
1835 OMX_U8 height;
1836 OMX_U32 rate;
1837 OMX_U32 scale;
1838 OMX_U32 length;
1839 OMX_U8 unused[4];
1840 } file_header;
1841
1842 memset((void *)&file_header,0,sizeof(file_header));
1843 file_header.signature[0] = 'D';
1844 file_header.signature[1] = 'K';
1845 file_header.signature[2] = 'I';
1846 file_header.signature[3] = 'F';
1847 file_header.version = 0;
1848 file_header.headersize = 32;
1849 switch (drv_ctx.decoder_format) {
1850 case VDEC_CODECTYPE_VP8:
1851 file_header.FourCC = 0x30385056;
1852 break;
1853 case VDEC_CODECTYPE_VP9:
1854 file_header.FourCC = 0x30395056;
1855 break;
1856 default:
1857 DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
1858 break;
1859 }
1860 fwrite((const char *)&file_header,
1861 sizeof(file_header),1,m_debug.infile);
1862 }
1863 }
1864 if (m_debug.infile && buffer_addr && buffer_len) {
1865 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
1866 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
1867 struct vpx_ivf_frame_header {
1868 OMX_U32 framesize;
1869 OMX_U32 timestamp_lo;
1870 OMX_U32 timestamp_hi;
1871 } vpx_frame_header;
1872 vpx_frame_header.framesize = buffer_len;
1873 /* Currently FW doesn't use timestamp values */
1874 vpx_frame_header.timestamp_lo = 0;
1875 vpx_frame_header.timestamp_hi = 0;
1876 fwrite((const char *)&vpx_frame_header,
1877 sizeof(vpx_frame_header),1,m_debug.infile);
1878 }
1879 fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
1880 }
1881 return 0;
1882 }
1883
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)1884 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
1885 int buf_index = 0;
1886 char *temp = NULL;
1887
1888 if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
1889 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
1890 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1891 m_debug.outfile = fopen (m_debug.outfile_name, "ab");
1892 if (!m_debug.outfile) {
1893 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
1894 m_debug.outfile_name[0] = '\0';
1895 return -1;
1896 }
1897 }
1898
1899 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
1900 && buffer->nFilledLen) {
1901 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
1902 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1903 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
1904 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
1905 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
1906 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
1907 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
1908 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
1909 m_debug.out_ymetafile_name[0] = '\0';
1910 m_debug.out_uvmetafile_name[0] = '\0';
1911 return -1;
1912 }
1913 }
1914
1915 if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
1916 return 0;
1917
1918 buf_index = buffer - m_out_mem_ptr;
1919 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1920
1921 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
1922 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
1923 drv_ctx.video_resolution.frame_width,
1924 drv_ctx.video_resolution.frame_height);
1925
1926 if (m_debug.outfile)
1927 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
1928
1929 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
1930 unsigned int width = 0, height = 0;
1931 unsigned int y_plane, y_meta_plane;
1932 int y_stride = 0, y_sclines = 0;
1933 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
1934 int color_fmt = COLOR_FMT_NV12_UBWC;
1935 int i;
1936 int bytes_written = 0;
1937
1938 width = drv_ctx.video_resolution.frame_width;
1939 height = drv_ctx.video_resolution.frame_height;
1940 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
1941 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
1942 y_stride = VENUS_Y_STRIDE(color_fmt, width);
1943 y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
1944 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
1945 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
1946
1947 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
1948 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
1949
1950 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
1951 for (i = 0; i < y_meta_scanlines; i++) {
1952 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
1953 temp += y_meta_stride;
1954 }
1955
1956 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
1957 for(i = 0; i < uv_meta_scanlines; i++) {
1958 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
1959 temp += uv_meta_stride;
1960 }
1961 }
1962 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) {
1963 int stride = drv_ctx.video_resolution.stride;
1964 int scanlines = drv_ctx.video_resolution.scan_lines;
1965 if (m_smoothstreaming_mode) {
1966 stride = drv_ctx.video_resolution.frame_width;
1967 scanlines = drv_ctx.video_resolution.frame_height;
1968 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
1969 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
1970 }
1971 unsigned i;
1972 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
1973 drv_ctx.video_resolution.frame_width,
1974 drv_ctx.video_resolution.frame_height, stride, scanlines);
1975 int bytes_written = 0;
1976 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
1977 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1978 temp += stride;
1979 }
1980 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
1981 int stride_c = stride;
1982 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
1983 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
1984 temp += stride_c;
1985 }
1986 }
1987 return 0;
1988 }
1989
1990 /* ======================================================================
1991 FUNCTION
1992 omx_vdec::ComponentInit
1993
1994 DESCRIPTION
1995 Initialize the component.
1996
1997 PARAMETERS
1998 ctxt -- Context information related to the self.
1999 id -- Event identifier. This could be any of the following:
2000 1. Command completion event
2001 2. Buffer done callback event
2002 3. Frame done callback event
2003
2004 RETURN VALUE
2005 None.
2006
2007 ========================================================================== */
component_init(OMX_STRING role)2008 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2009 {
2010
2011 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2012 struct v4l2_fmtdesc fdesc;
2013 struct v4l2_format fmt;
2014 struct v4l2_requestbuffers bufreq;
2015 struct v4l2_control control;
2016 struct v4l2_frmsizeenum frmsize;
2017 unsigned int alignment = 0,buffer_size = 0;
2018 int fds[2];
2019 int r,ret=0;
2020 bool codec_ambiguous = false;
2021 OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2022 char property_value[PROPERTY_VALUE_MAX] = {0};
2023 FILE *soc_file = NULL;
2024 char buffer[10];
2025
2026 #ifdef _ANDROID_
2027 char platform_name[PROPERTY_VALUE_MAX];
2028 property_get("ro.board.platform", platform_name, "0");
2029 if (!strncmp(platform_name, "msm8610", 7)) {
2030 device_name = (OMX_STRING)"/dev/video/q6_dec";
2031 is_q6_platform = true;
2032 maxSmoothStreamingWidth = 1280;
2033 maxSmoothStreamingHeight = 720;
2034 }
2035 #endif
2036
2037 is_thulium_v1 = false;
2038 soc_file = fopen("/sys/devices/soc0/soc_id", "r");
2039 if (soc_file) {
2040 fread(buffer, 1, 4, soc_file);
2041 fclose(soc_file);
2042 if (atoi(buffer) == 246) {
2043 soc_file = fopen("/sys/devices/soc0/revision", "r");
2044 if (soc_file) {
2045 fread(buffer, 1, 4, soc_file);
2046 fclose(soc_file);
2047 if (atoi(buffer) == 1) {
2048 is_thulium_v1 = true;
2049 DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
2050 }
2051 }
2052 }
2053 }
2054
2055 #ifdef _ANDROID_
2056 /*
2057 * turn off frame parsing for Android by default.
2058 * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
2059 */
2060 arbitrary_bytes = false;
2061 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
2062 if (atoi(property_value)) {
2063 DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
2064 arbitrary_bytes = true;
2065 }
2066 #endif
2067
2068 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2069 OMX_MAX_STRINGNAME_SIZE)) {
2070 secure_mode = true;
2071 arbitrary_bytes = false;
2072 role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2073 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2074 OMX_MAX_STRINGNAME_SIZE)) {
2075 secure_mode = true;
2076 arbitrary_bytes = false;
2077 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2078 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2079 OMX_MAX_STRINGNAME_SIZE)) {
2080 secure_mode = true;
2081 arbitrary_bytes = false;
2082 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2083 } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
2084 OMX_MAX_STRINGNAME_SIZE)) {
2085 secure_mode = true;
2086 arbitrary_bytes = false;
2087 role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
2088 } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
2089 OMX_MAX_STRINGNAME_SIZE)) {
2090 secure_mode = true;
2091 arbitrary_bytes = false;
2092 role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
2093 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
2094 OMX_MAX_STRINGNAME_SIZE)) {
2095 secure_mode = true;
2096 arbitrary_bytes = false;
2097 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
2098 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2099 OMX_MAX_STRINGNAME_SIZE)) {
2100 secure_mode = true;
2101 arbitrary_bytes = false;
2102 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2103 }
2104
2105 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2106
2107 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2108
2109 if (drv_ctx.video_driver_fd < 0) {
2110 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2111 return OMX_ErrorInsufficientResources;
2112 }
2113 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2114 drv_ctx.frame_rate.fps_denominator = 1;
2115 m_poll_efd = eventfd(0, 0);
2116 if (m_poll_efd < 0) {
2117 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2118 return OMX_ErrorInsufficientResources;
2119 }
2120 ret = subscribe_to_events(drv_ctx.video_driver_fd);
2121 if (!ret) {
2122 async_thread_created = true;
2123 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2124 }
2125 if (ret) {
2126 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2127 async_thread_created = false;
2128 return OMX_ErrorInsufficientResources;
2129 }
2130
2131 #ifdef OUTPUT_EXTRADATA_LOG
2132 outputExtradataFile = fopen (output_extradata_filename, "ab");
2133 #endif
2134
2135 // Copy the role information which provides the decoder kind
2136 strlcpy(drv_ctx.kind,role,128);
2137
2138 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
2139 OMX_MAX_STRINGNAME_SIZE)) {
2140 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
2141 OMX_MAX_STRINGNAME_SIZE);
2142 drv_ctx.timestamp_adjust = true;
2143 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
2144 eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2145 output_capability=V4L2_PIX_FMT_MPEG4;
2146 /*Initialize Start Code for MPEG4*/
2147 codec_type_parse = CODEC_TYPE_MPEG4;
2148 m_frame_parser.init_start_codes(codec_type_parse);
2149 } else if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2150 OMX_MAX_STRINGNAME_SIZE)) {
2151 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2152 OMX_MAX_STRINGNAME_SIZE);
2153 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2154 output_capability = V4L2_PIX_FMT_MPEG2;
2155 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2156 /*Initialize Start Code for MPEG2*/
2157 codec_type_parse = CODEC_TYPE_MPEG2;
2158 m_frame_parser.init_start_codes(codec_type_parse);
2159 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
2160 OMX_MAX_STRINGNAME_SIZE)) {
2161 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
2162 DEBUG_PRINT_LOW("H263 Decoder selected");
2163 drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
2164 eCompressionFormat = OMX_VIDEO_CodingH263;
2165 output_capability = V4L2_PIX_FMT_H263;
2166 codec_type_parse = CODEC_TYPE_H263;
2167 m_frame_parser.init_start_codes(codec_type_parse);
2168 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
2169 OMX_MAX_STRINGNAME_SIZE)) {
2170 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2171 DEBUG_PRINT_LOW ("DIVX 311 Decoder selected");
2172 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
2173 output_capability = V4L2_PIX_FMT_DIVX_311;
2174 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2175 codec_type_parse = CODEC_TYPE_DIVX;
2176 m_frame_parser.init_start_codes(codec_type_parse);
2177
2178 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
2179 OMX_MAX_STRINGNAME_SIZE)) {
2180 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2181 DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected");
2182 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
2183 output_capability = V4L2_PIX_FMT_DIVX;
2184 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2185 codec_type_parse = CODEC_TYPE_DIVX;
2186 codec_ambiguous = true;
2187 m_frame_parser.init_start_codes(codec_type_parse);
2188
2189 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
2190 OMX_MAX_STRINGNAME_SIZE)) {
2191 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
2192 DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected");
2193 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
2194 output_capability = V4L2_PIX_FMT_DIVX;
2195 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
2196 codec_type_parse = CODEC_TYPE_DIVX;
2197 codec_ambiguous = true;
2198 m_frame_parser.init_start_codes(codec_type_parse);
2199
2200 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2201 OMX_MAX_STRINGNAME_SIZE)) {
2202 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2203 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2204 output_capability=V4L2_PIX_FMT_H264;
2205 eCompressionFormat = OMX_VIDEO_CodingAVC;
2206 codec_type_parse = CODEC_TYPE_H264;
2207 m_frame_parser.init_start_codes(codec_type_parse);
2208 m_frame_parser.init_nal_length(nal_length);
2209 if (is_thulium_v1) {
2210 arbitrary_bytes = true;
2211 DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
2212 }
2213 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2214 OMX_MAX_STRINGNAME_SIZE)) {
2215 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2216 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2217 output_capability = V4L2_PIX_FMT_H264_MVC;
2218 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2219 codec_type_parse = CODEC_TYPE_H264;
2220 m_frame_parser.init_start_codes(codec_type_parse);
2221 m_frame_parser.init_nal_length(nal_length);
2222 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2223 OMX_MAX_STRINGNAME_SIZE)) {
2224 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2225 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2226 output_capability = V4L2_PIX_FMT_HEVC;
2227 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2228 codec_type_parse = CODEC_TYPE_HEVC;
2229 m_frame_parser.init_start_codes(codec_type_parse);
2230 m_frame_parser.init_nal_length(nal_length);
2231 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
2232 OMX_MAX_STRINGNAME_SIZE)) {
2233 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2234 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
2235 eCompressionFormat = OMX_VIDEO_CodingWMV;
2236 codec_type_parse = CODEC_TYPE_VC1;
2237 output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
2238 m_frame_parser.init_start_codes(codec_type_parse);
2239 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
2240 OMX_MAX_STRINGNAME_SIZE)) {
2241 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
2242 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
2243 eCompressionFormat = OMX_VIDEO_CodingWMV;
2244 codec_type_parse = CODEC_TYPE_VC1;
2245 output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
2246 m_frame_parser.init_start_codes(codec_type_parse);
2247 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
2248 OMX_MAX_STRINGNAME_SIZE)) {
2249 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2250 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2251 output_capability = V4L2_PIX_FMT_VP8;
2252 eCompressionFormat = OMX_VIDEO_CodingVP8;
2253 codec_type_parse = CODEC_TYPE_VP8;
2254 arbitrary_bytes = false;
2255 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \
2256 OMX_MAX_STRINGNAME_SIZE)) {
2257 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2258 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2259 output_capability = V4L2_PIX_FMT_VP9;
2260 eCompressionFormat = OMX_VIDEO_CodingVP9;
2261 codec_type_parse = CODEC_TYPE_VP9;
2262 arbitrary_bytes = false;
2263 } else {
2264 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2265 eRet = OMX_ErrorInvalidComponentName;
2266 }
2267
2268 if (eRet == OMX_ErrorNone) {
2269 OMX_COLOR_FORMATTYPE dest_color_format;
2270 if (m_disable_ubwc_mode) {
2271 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2272 } else {
2273 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2274 }
2275 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2276 dest_color_format = (OMX_COLOR_FORMATTYPE)
2277 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2278 else
2279 dest_color_format = (OMX_COLOR_FORMATTYPE)
2280 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2281 if (!client_buffers.set_color_format(dest_color_format)) {
2282 DEBUG_PRINT_ERROR("Setting color format failed");
2283 eRet = OMX_ErrorInsufficientResources;
2284 }
2285
2286 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2287
2288 if (m_disable_ubwc_mode) {
2289 capture_capability = V4L2_PIX_FMT_NV12;
2290 } else {
2291 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2292 }
2293
2294 struct v4l2_capability cap;
2295 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2296 if (ret) {
2297 DEBUG_PRINT_ERROR("Failed to query capabilities");
2298 /*TODO: How to handle this case */
2299 } else {
2300 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2301 " version = %d, capabilities = %x", cap.driver, cap.card,
2302 cap.bus_info, cap.version, cap.capabilities);
2303 }
2304 ret=0;
2305 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2306 fdesc.index=0;
2307 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2308 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2309 fdesc.pixelformat, fdesc.flags);
2310 fdesc.index++;
2311 }
2312 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2313 fdesc.index=0;
2314 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2315
2316 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2317 fdesc.pixelformat, fdesc.flags);
2318 fdesc.index++;
2319 }
2320 update_resolution(320, 240, 320, 240);
2321 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2322 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2323 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2324 fmt.fmt.pix_mp.pixelformat = output_capability;
2325 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2326 if (ret) {
2327 /*TODO: How to handle this case */
2328 DEBUG_PRINT_ERROR("Failed to set format on output port");
2329 return OMX_ErrorInsufficientResources;
2330 }
2331 DEBUG_PRINT_HIGH("Set Format was successful");
2332 if (codec_ambiguous) {
2333 if (output_capability == V4L2_PIX_FMT_DIVX) {
2334 struct v4l2_control divx_ctrl;
2335
2336 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
2337 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
2338 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
2339 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
2340 } else {
2341 divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
2342 }
2343
2344 divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
2345 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
2346 if (ret) {
2347 DEBUG_PRINT_ERROR("Failed to set divx version");
2348 }
2349 } else {
2350 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
2351 }
2352 }
2353
2354 property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
2355 m_conceal_color= atoi(property_value);
2356 DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
2357 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
2358 control.value = m_conceal_color;
2359 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2360 if (ret) {
2361 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2362 }
2363
2364 //Get the hardware capabilities
2365 memset((void *)&frmsize,0,sizeof(frmsize));
2366 frmsize.index = 0;
2367 frmsize.pixel_format = output_capability;
2368 ret = ioctl(drv_ctx.video_driver_fd,
2369 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2370 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2371 DEBUG_PRINT_ERROR("Failed to get framesizes");
2372 return OMX_ErrorHardware;
2373 }
2374
2375 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2376 m_decoder_capability.min_width = frmsize.stepwise.min_width;
2377 m_decoder_capability.max_width = frmsize.stepwise.max_width;
2378 m_decoder_capability.min_height = frmsize.stepwise.min_height;
2379 m_decoder_capability.max_height = frmsize.stepwise.max_height;
2380 }
2381
2382 memset(&fmt, 0x0, sizeof(struct v4l2_format));
2383 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2384 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2385 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2386 fmt.fmt.pix_mp.pixelformat = capture_capability;
2387 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2388 if (ret) {
2389 /*TODO: How to handle this case */
2390 DEBUG_PRINT_ERROR("Failed to set format on capture port");
2391 }
2392 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2393 framesize.nWidth = drv_ctx.video_resolution.frame_width;
2394 framesize.nHeight = drv_ctx.video_resolution.frame_height;
2395
2396 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2397 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2398 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2399
2400 DEBUG_PRINT_HIGH("Set Format was successful");
2401 if (secure_mode) {
2402 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2403 control.value = 1;
2404 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2405 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2406 if (ret) {
2407 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2408 return OMX_ErrorInsufficientResources;
2409 }
2410 }
2411 if (output_capability == V4L2_PIX_FMT_H264_MVC) {
2412 control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
2413 control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
2414 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2415 if (ret) {
2416 DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
2417 return OMX_ErrorInsufficientResources;
2418 }
2419 }
2420
2421 if (is_thulium_v1) {
2422 eRet = enable_smoothstreaming();
2423 if (eRet != OMX_ErrorNone) {
2424 DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
2425 return eRet;
2426 }
2427 }
2428
2429 /*Get the Buffer requirements for input and output ports*/
2430 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2431 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2432
2433 if (secure_mode) {
2434 drv_ctx.op_buf.alignment = SECURE_ALIGN;
2435 drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2436 } else {
2437 drv_ctx.op_buf.alignment = SZ_4K;
2438 drv_ctx.ip_buf.alignment = SZ_4K;
2439 }
2440
2441 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2442 drv_ctx.extradata = 0;
2443 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2444 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2445 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2446 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2447 drv_ctx.idr_only_decoding = 0;
2448
2449 #ifdef _ANDROID_
2450 property_get("vidc.dec.downscalar_width",property_value,"0");
2451 if (atoi(property_value)) {
2452 m_downscalar_width = atoi(property_value);
2453 }
2454 property_get("vidc.dec.downscalar_height",property_value,"0");
2455 if (atoi(property_value)) {
2456 m_downscalar_height = atoi(property_value);
2457 }
2458
2459 if (m_downscalar_width < m_decoder_capability.min_width ||
2460 m_downscalar_height < m_decoder_capability.min_height) {
2461 m_downscalar_width = 0;
2462 m_downscalar_height = 0;
2463 }
2464
2465 DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
2466 m_downscalar_width, m_downscalar_height);
2467 #endif
2468 m_state = OMX_StateLoaded;
2469 #ifdef DEFAULT_EXTRADATA
2470 if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",
2471 OMX_MAX_STRINGNAME_SIZE) &&
2472 strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",
2473 OMX_MAX_STRINGNAME_SIZE)) &&
2474 (eRet == OMX_ErrorNone))
2475 enable_extradata(DEFAULT_EXTRADATA, true, true);
2476 #endif
2477 eRet = get_buffer_req(&drv_ctx.ip_buf);
2478 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2479 get_buffer_req(&drv_ctx.op_buf);
2480 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2481 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2482 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2483 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2484 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2485 h264_scratch.nFilledLen = 0;
2486 h264_scratch.nOffset = 0;
2487
2488 if (h264_scratch.pBuffer == NULL) {
2489 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2490 return OMX_ErrorInsufficientResources;
2491 }
2492 }
2493 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2494 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2495 if (m_frame_parser.mutils == NULL) {
2496 m_frame_parser.mutils = new H264_Utils();
2497 if (m_frame_parser.mutils == NULL) {
2498 DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2499 eRet = OMX_ErrorInsufficientResources;
2500 } else {
2501 m_frame_parser.mutils->initialize_frame_checking_environment();
2502 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2503 }
2504 }
2505
2506 h264_parser = new h264_stream_parser();
2507 if (!h264_parser) {
2508 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2509 eRet = OMX_ErrorInsufficientResources;
2510 }
2511 }
2512
2513 if (pipe(fds)) {
2514 DEBUG_PRINT_ERROR("pipe creation failed");
2515 eRet = OMX_ErrorInsufficientResources;
2516 } else {
2517 m_pipe_in = fds[0];
2518 m_pipe_out = fds[1];
2519 msg_thread_created = true;
2520 r = pthread_create(&msg_thread_id,0,message_thread,this);
2521
2522 if (r < 0) {
2523 DEBUG_PRINT_ERROR("component_init(): message_thread creation failed");
2524 msg_thread_created = false;
2525 eRet = OMX_ErrorInsufficientResources;
2526 }
2527 }
2528 }
2529
2530 {
2531 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2532 init_vendor_extensions(*extStore);
2533 mVendorExtensionStore.dumpExtensions((const char *)role);
2534 }
2535
2536 if (eRet != OMX_ErrorNone) {
2537 DEBUG_PRINT_ERROR("Component Init Failed");
2538 } else {
2539 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2540 drv_ctx.video_driver_fd);
2541 }
2542 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2543 return eRet;
2544 }
2545
2546 /* ======================================================================
2547 FUNCTION
2548 omx_vdec::GetComponentVersion
2549
2550 DESCRIPTION
2551 Returns the component version.
2552
2553 PARAMETERS
2554 TBD.
2555
2556 RETURN VALUE
2557 OMX_ErrorNone.
2558
2559 ========================================================================== */
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)2560 OMX_ERRORTYPE omx_vdec::get_component_version
2561 (
2562 OMX_IN OMX_HANDLETYPE hComp,
2563 OMX_OUT OMX_STRING componentName,
2564 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2565 OMX_OUT OMX_VERSIONTYPE* specVersion,
2566 OMX_OUT OMX_UUIDTYPE* componentUUID
2567 )
2568 {
2569 (void) hComp;
2570 (void) componentName;
2571 (void) componentVersion;
2572 (void) componentUUID;
2573 if (m_state == OMX_StateInvalid) {
2574 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2575 return OMX_ErrorInvalidState;
2576 }
2577 /* TBD -- Return the proper version */
2578 if (specVersion) {
2579 specVersion->nVersion = OMX_SPEC_VERSION;
2580 }
2581 return OMX_ErrorNone;
2582 }
2583 /* ======================================================================
2584 FUNCTION
2585 omx_vdec::SendCommand
2586
2587 DESCRIPTION
2588 Returns zero if all the buffers released..
2589
2590 PARAMETERS
2591 None.
2592
2593 RETURN VALUE
2594 true/false
2595
2596 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2597 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2598 OMX_IN OMX_COMMANDTYPE cmd,
2599 OMX_IN OMX_U32 param1,
2600 OMX_IN OMX_PTR cmdData
2601 )
2602 {
2603 (void) hComp;
2604 (void) cmdData;
2605 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2606 if (m_state == OMX_StateInvalid) {
2607 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2608 return OMX_ErrorInvalidState;
2609 }
2610 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2611 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2612 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2613 "to invalid port: %u", (unsigned int)param1);
2614 return OMX_ErrorBadPortIndex;
2615 }
2616
2617 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2618 sem_wait(&m_cmd_lock);
2619 DEBUG_PRINT_LOW("send_command: Command Processed");
2620 return OMX_ErrorNone;
2621 }
2622
2623 /* ======================================================================
2624 FUNCTION
2625 omx_vdec::SendCommand
2626
2627 DESCRIPTION
2628 Returns zero if all the buffers released..
2629
2630 PARAMETERS
2631 None.
2632
2633 RETURN VALUE
2634 true/false
2635
2636 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2637 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2638 OMX_IN OMX_COMMANDTYPE cmd,
2639 OMX_IN OMX_U32 param1,
2640 OMX_IN OMX_PTR cmdData
2641 )
2642 {
2643 (void) hComp;
2644 (void) cmdData;
2645 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2646 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2647 int bFlag = 1,sem_posted = 0,ret=0;
2648
2649 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2650 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2651 m_state, eState);
2652
2653 if (cmd == OMX_CommandStateSet) {
2654 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2655 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2656 /***************************/
2657 /* Current State is Loaded */
2658 /***************************/
2659 if (m_state == OMX_StateLoaded) {
2660 if (eState == OMX_StateIdle) {
2661 //if all buffers are allocated or all ports disabled
2662 if (allocate_done() ||
2663 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2664 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2665 } else {
2666 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2667 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2668 // Skip the event notification
2669 bFlag = 0;
2670 }
2671 }
2672 /* Requesting transition from Loaded to Loaded */
2673 else if (eState == OMX_StateLoaded) {
2674 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2675 post_event(OMX_EventError,OMX_ErrorSameState,\
2676 OMX_COMPONENT_GENERATE_EVENT);
2677 eRet = OMX_ErrorSameState;
2678 }
2679 /* Requesting transition from Loaded to WaitForResources */
2680 else if (eState == OMX_StateWaitForResources) {
2681 /* Since error is None , we will post an event
2682 at the end of this function definition */
2683 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2684 }
2685 /* Requesting transition from Loaded to Executing */
2686 else if (eState == OMX_StateExecuting) {
2687 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2688 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2689 OMX_COMPONENT_GENERATE_EVENT);
2690 eRet = OMX_ErrorIncorrectStateTransition;
2691 }
2692 /* Requesting transition from Loaded to Pause */
2693 else if (eState == OMX_StatePause) {
2694 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2695 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2696 OMX_COMPONENT_GENERATE_EVENT);
2697 eRet = OMX_ErrorIncorrectStateTransition;
2698 }
2699 /* Requesting transition from Loaded to Invalid */
2700 else if (eState == OMX_StateInvalid) {
2701 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2702 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2703 eRet = OMX_ErrorInvalidState;
2704 } else {
2705 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2706 eState);
2707 eRet = OMX_ErrorBadParameter;
2708 }
2709 }
2710
2711 /***************************/
2712 /* Current State is IDLE */
2713 /***************************/
2714 else if (m_state == OMX_StateIdle) {
2715 if (eState == OMX_StateLoaded) {
2716 if (release_done()) {
2717 /*
2718 Since error is None , we will post an event at the end
2719 of this function definition
2720 */
2721 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2722 } else {
2723 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2724 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2725 // Skip the event notification
2726 bFlag = 0;
2727 }
2728 }
2729 /* Requesting transition from Idle to Executing */
2730 else if (eState == OMX_StateExecuting) {
2731 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2732 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
2733 bFlag = 1;
2734 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2735 m_state=OMX_StateExecuting;
2736 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
2737 }
2738 /* Requesting transition from Idle to Idle */
2739 else if (eState == OMX_StateIdle) {
2740 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2741 post_event(OMX_EventError,OMX_ErrorSameState,\
2742 OMX_COMPONENT_GENERATE_EVENT);
2743 eRet = OMX_ErrorSameState;
2744 }
2745 /* Requesting transition from Idle to WaitForResources */
2746 else if (eState == OMX_StateWaitForResources) {
2747 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2748 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2749 OMX_COMPONENT_GENERATE_EVENT);
2750 eRet = OMX_ErrorIncorrectStateTransition;
2751 }
2752 /* Requesting transition from Idle to Pause */
2753 else if (eState == OMX_StatePause) {
2754 /*To pause the Video core we need to start the driver*/
2755 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2756 NULL) < */0) {
2757 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2758 omx_report_error ();
2759 eRet = OMX_ErrorHardware;
2760 } else {
2761 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2762 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2763 bFlag = 0;
2764 }
2765 }
2766 /* Requesting transition from Idle to Invalid */
2767 else if (eState == OMX_StateInvalid) {
2768 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2769 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2770 eRet = OMX_ErrorInvalidState;
2771 } else {
2772 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2773 eRet = OMX_ErrorBadParameter;
2774 }
2775 }
2776
2777 /******************************/
2778 /* Current State is Executing */
2779 /******************************/
2780 else if (m_state == OMX_StateExecuting) {
2781 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2782 /* Requesting transition from Executing to Idle */
2783 if (eState == OMX_StateIdle) {
2784 /* Since error is None , we will post an event
2785 at the end of this function definition
2786 */
2787 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2788 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2789 if (!sem_posted) {
2790 sem_posted = 1;
2791 sem_post (&m_cmd_lock);
2792 execute_omx_flush(OMX_ALL);
2793 }
2794 bFlag = 0;
2795 }
2796 /* Requesting transition from Executing to Paused */
2797 else if (eState == OMX_StatePause) {
2798 DEBUG_PRINT_LOW("PAUSE Command Issued");
2799 m_state = OMX_StatePause;
2800 bFlag = 1;
2801 }
2802 /* Requesting transition from Executing to Loaded */
2803 else if (eState == OMX_StateLoaded) {
2804 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2805 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2806 OMX_COMPONENT_GENERATE_EVENT);
2807 eRet = OMX_ErrorIncorrectStateTransition;
2808 }
2809 /* Requesting transition from Executing to WaitForResources */
2810 else if (eState == OMX_StateWaitForResources) {
2811 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2812 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2813 OMX_COMPONENT_GENERATE_EVENT);
2814 eRet = OMX_ErrorIncorrectStateTransition;
2815 }
2816 /* Requesting transition from Executing to Executing */
2817 else if (eState == OMX_StateExecuting) {
2818 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2819 post_event(OMX_EventError,OMX_ErrorSameState,\
2820 OMX_COMPONENT_GENERATE_EVENT);
2821 eRet = OMX_ErrorSameState;
2822 }
2823 /* Requesting transition from Executing to Invalid */
2824 else if (eState == OMX_StateInvalid) {
2825 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2826 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2827 eRet = OMX_ErrorInvalidState;
2828 } else {
2829 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2830 eRet = OMX_ErrorBadParameter;
2831 }
2832 }
2833 /***************************/
2834 /* Current State is Pause */
2835 /***************************/
2836 else if (m_state == OMX_StatePause) {
2837 /* Requesting transition from Pause to Executing */
2838 if (eState == OMX_StateExecuting) {
2839 DEBUG_PRINT_LOW("Pause --> Executing");
2840 m_state = OMX_StateExecuting;
2841 bFlag = 1;
2842 }
2843 /* Requesting transition from Pause to Idle */
2844 else if (eState == OMX_StateIdle) {
2845 /* Since error is None , we will post an event
2846 at the end of this function definition */
2847 DEBUG_PRINT_LOW("Pause --> Idle");
2848 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2849 if (!sem_posted) {
2850 sem_posted = 1;
2851 sem_post (&m_cmd_lock);
2852 execute_omx_flush(OMX_ALL);
2853 }
2854 bFlag = 0;
2855 }
2856 /* Requesting transition from Pause to loaded */
2857 else if (eState == OMX_StateLoaded) {
2858 DEBUG_PRINT_ERROR("Pause --> loaded");
2859 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2860 OMX_COMPONENT_GENERATE_EVENT);
2861 eRet = OMX_ErrorIncorrectStateTransition;
2862 }
2863 /* Requesting transition from Pause to WaitForResources */
2864 else if (eState == OMX_StateWaitForResources) {
2865 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
2866 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2867 OMX_COMPONENT_GENERATE_EVENT);
2868 eRet = OMX_ErrorIncorrectStateTransition;
2869 }
2870 /* Requesting transition from Pause to Pause */
2871 else if (eState == OMX_StatePause) {
2872 DEBUG_PRINT_ERROR("Pause --> Pause");
2873 post_event(OMX_EventError,OMX_ErrorSameState,\
2874 OMX_COMPONENT_GENERATE_EVENT);
2875 eRet = OMX_ErrorSameState;
2876 }
2877 /* Requesting transition from Pause to Invalid */
2878 else if (eState == OMX_StateInvalid) {
2879 DEBUG_PRINT_ERROR("Pause --> Invalid");
2880 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2881 eRet = OMX_ErrorInvalidState;
2882 } else {
2883 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
2884 eRet = OMX_ErrorBadParameter;
2885 }
2886 }
2887 /***************************/
2888 /* Current State is WaitForResources */
2889 /***************************/
2890 else if (m_state == OMX_StateWaitForResources) {
2891 /* Requesting transition from WaitForResources to Loaded */
2892 if (eState == OMX_StateLoaded) {
2893 /* Since error is None , we will post an event
2894 at the end of this function definition */
2895 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
2896 }
2897 /* Requesting transition from WaitForResources to WaitForResources */
2898 else if (eState == OMX_StateWaitForResources) {
2899 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
2900 post_event(OMX_EventError,OMX_ErrorSameState,
2901 OMX_COMPONENT_GENERATE_EVENT);
2902 eRet = OMX_ErrorSameState;
2903 }
2904 /* Requesting transition from WaitForResources to Executing */
2905 else if (eState == OMX_StateExecuting) {
2906 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
2907 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2908 OMX_COMPONENT_GENERATE_EVENT);
2909 eRet = OMX_ErrorIncorrectStateTransition;
2910 }
2911 /* Requesting transition from WaitForResources to Pause */
2912 else if (eState == OMX_StatePause) {
2913 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
2914 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2915 OMX_COMPONENT_GENERATE_EVENT);
2916 eRet = OMX_ErrorIncorrectStateTransition;
2917 }
2918 /* Requesting transition from WaitForResources to Invalid */
2919 else if (eState == OMX_StateInvalid) {
2920 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
2921 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2922 eRet = OMX_ErrorInvalidState;
2923 }
2924 /* Requesting transition from WaitForResources to Loaded -
2925 is NOT tested by Khronos TS */
2926
2927 } else {
2928 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
2929 eRet = OMX_ErrorBadParameter;
2930 }
2931 }
2932 /********************************/
2933 /* Current State is Invalid */
2934 /*******************************/
2935 else if (m_state == OMX_StateInvalid) {
2936 /* State Transition from Invalid to any state */
2937 if (eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
2938 eState == OMX_StateIdle || eState == OMX_StateExecuting ||
2939 eState == OMX_StatePause || eState == OMX_StateInvalid) {
2940 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
2941 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2942 OMX_COMPONENT_GENERATE_EVENT);
2943 eRet = OMX_ErrorInvalidState;
2944 }
2945 } else if (cmd == OMX_CommandFlush) {
2946 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
2947 "with param1: %u", (unsigned int)param1);
2948 #ifdef _MSM8974_
2949 send_codec_config();
2950 #endif
2951 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
2952 param1 == OMX_ALL)) {
2953 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
2954 struct timespec ts;
2955
2956 clock_gettime(CLOCK_REALTIME, &ts);
2957 ts.tv_sec += 2;
2958 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
2959 m_queued_codec_config_count);
2960 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
2961 if (sem_timedwait(&m_safe_flush, &ts)) {
2962 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
2963 }
2964 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
2965 }
2966 }
2967
2968 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2969 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2970 }
2971 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
2972 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2973 }
2974 if (!sem_posted) {
2975 sem_posted = 1;
2976 DEBUG_PRINT_LOW("Set the Semaphore");
2977 sem_post (&m_cmd_lock);
2978 execute_omx_flush(param1);
2979 }
2980 bFlag = 0;
2981 } else if ( cmd == OMX_CommandPortEnable) {
2982 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
2983 "with param1: %u", (unsigned int)param1);
2984 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
2985 m_inp_bEnabled = OMX_TRUE;
2986
2987 if ( (m_state == OMX_StateLoaded &&
2988 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2989 || allocate_input_done()) {
2990 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2991 OMX_COMPONENT_GENERATE_EVENT);
2992 } else {
2993 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
2994 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2995 // Skip the event notification
2996 bFlag = 0;
2997 }
2998 }
2999 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3000 DEBUG_PRINT_LOW("Enable output Port command recieved");
3001 m_out_bEnabled = OMX_TRUE;
3002
3003 if ( (m_state == OMX_StateLoaded &&
3004 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3005 || (allocate_output_done())) {
3006 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3007 OMX_COMPONENT_GENERATE_EVENT);
3008
3009 } else {
3010 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3011 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3012 // Skip the event notification
3013 bFlag = 0;
3014 /* enable/disable downscaling if required */
3015 ret = decide_downscalar();
3016 if (ret) {
3017 DEBUG_PRINT_LOW("decide_downscalar failed\n");
3018 }
3019 }
3020 }
3021 } else if (cmd == OMX_CommandPortDisable) {
3022 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3023 "with param1: %u", (unsigned int)param1);
3024 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3025 codec_config_flag = false;
3026 m_inp_bEnabled = OMX_FALSE;
3027 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3028 && release_input_done()) {
3029 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3030 OMX_COMPONENT_GENERATE_EVENT);
3031 } else {
3032 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3033 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3034 if (!sem_posted) {
3035 sem_posted = 1;
3036 sem_post (&m_cmd_lock);
3037 }
3038 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3039 }
3040
3041 // Skip the event notification
3042 bFlag = 0;
3043 }
3044 }
3045 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3046 m_out_bEnabled = OMX_FALSE;
3047 DEBUG_PRINT_LOW("Disable output Port command recieved");
3048 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3049 && release_output_done()) {
3050 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3051 OMX_COMPONENT_GENERATE_EVENT);
3052 } else {
3053 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3054 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3055 if (!sem_posted) {
3056 sem_posted = 1;
3057 sem_post (&m_cmd_lock);
3058 }
3059 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3060 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3061 }
3062 // Skip the event notification
3063 bFlag = 0;
3064
3065 }
3066 }
3067 } else {
3068 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3069 eRet = OMX_ErrorNotImplemented;
3070 }
3071 if (eRet == OMX_ErrorNone && bFlag) {
3072 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3073 }
3074 if (!sem_posted) {
3075 sem_post(&m_cmd_lock);
3076 }
3077
3078 return eRet;
3079 }
3080
3081 /* ======================================================================
3082 FUNCTION
3083 omx_vdec::ExecuteOmxFlush
3084
3085 DESCRIPTION
3086 Executes the OMX flush.
3087
3088 PARAMETERS
3089 flushtype - input flush(1)/output flush(0)/ both.
3090
3091 RETURN VALUE
3092 true/false
3093
3094 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3095 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3096 {
3097 bool bRet = false;
3098 struct v4l2_plane plane;
3099 struct v4l2_buffer v4l2_buf;
3100 struct v4l2_decoder_cmd dec;
3101 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3102 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3103 dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
3104
3105 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3106
3107 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3108 output_flush_progress = true;
3109 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3110 } else {
3111 /* XXX: The driver/hardware does not support flushing of individual ports
3112 * in all states. So we pretty much need to flush both ports internally,
3113 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3114 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3115 * we automatically omit sending the FLUSH done for the "opposite" port. */
3116 input_flush_progress = true;
3117 output_flush_progress = true;
3118 dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
3119 request_perf_level(VIDC_TURBO);
3120 }
3121
3122 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3123 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3124 bRet = false;
3125 }
3126
3127 return bRet;
3128 }
3129 /*=========================================================================
3130 FUNCTION : execute_output_flush
3131
3132 DESCRIPTION
3133 Executes the OMX flush at OUTPUT PORT.
3134
3135 PARAMETERS
3136 None.
3137
3138 RETURN VALUE
3139 true/false
3140 ==========================================================================*/
execute_output_flush()3141 bool omx_vdec::execute_output_flush()
3142 {
3143 unsigned long p1 = 0; // Parameter - 1
3144 unsigned long p2 = 0; // Parameter - 2
3145 unsigned long ident = 0;
3146 bool bRet = true;
3147
3148 /*Generate FBD for all Buffers in the FTBq*/
3149 pthread_mutex_lock(&m_lock);
3150 DEBUG_PRINT_LOW("Initiate Output Flush");
3151
3152 //reset last render TS
3153 if(m_last_rendered_TS > 0) {
3154 m_last_rendered_TS = 0;
3155 }
3156
3157 while (m_ftb_q.m_size) {
3158 DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
3159 m_ftb_q.m_size,pending_output_buffers);
3160 m_ftb_q.pop_entry(&p1,&p2,&ident);
3161 DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
3162 if (ident == m_fill_output_msg ) {
3163 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3164 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3165 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3166 }
3167 }
3168 pthread_mutex_unlock(&m_lock);
3169 output_flush_progress = false;
3170
3171 if (arbitrary_bytes) {
3172 prev_ts = LLONG_MAX;
3173 rst_prev_ts = true;
3174 }
3175 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3176 return bRet;
3177 }
3178 /*=========================================================================
3179 FUNCTION : execute_input_flush
3180
3181 DESCRIPTION
3182 Executes the OMX flush at INPUT PORT.
3183
3184 PARAMETERS
3185 None.
3186
3187 RETURN VALUE
3188 true/false
3189 ==========================================================================*/
execute_input_flush()3190 bool omx_vdec::execute_input_flush()
3191 {
3192 unsigned i =0;
3193 unsigned long p1 = 0; // Parameter - 1
3194 unsigned long p2 = 0; // Parameter - 2
3195 unsigned long ident = 0;
3196 bool bRet = true;
3197
3198 /*Generate EBD for all Buffers in the ETBq*/
3199 DEBUG_PRINT_LOW("Initiate Input Flush");
3200
3201 pthread_mutex_lock(&m_lock);
3202 DEBUG_PRINT_LOW("Check if the Queue is empty");
3203 while (m_etb_q.m_size) {
3204 m_etb_q.pop_entry(&p1,&p2,&ident);
3205
3206 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3207 DEBUG_PRINT_LOW("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
3208 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3209 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3210 pending_input_buffers++;
3211 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
3212 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
3213 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3214 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3215 DEBUG_PRINT_LOW("Flush Input OMX_COMPONENT_GENERATE_EBD %p",
3216 (OMX_BUFFERHEADERTYPE *)p1);
3217 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3218 }
3219 }
3220 time_stamp_dts.flush_timestamp();
3221 /*Check if Heap Buffers are to be flushed*/
3222 if (arbitrary_bytes && !(codec_config_flag)) {
3223 DEBUG_PRINT_LOW("Reset all the variables before flusing");
3224 h264_scratch.nFilledLen = 0;
3225 nal_count = 0;
3226 look_ahead_nal = false;
3227 frame_count = 0;
3228 h264_last_au_ts = LLONG_MAX;
3229 h264_last_au_flags = 0;
3230 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3231 m_demux_entries = 0;
3232 DEBUG_PRINT_LOW("Initialize parser");
3233 if (m_frame_parser.mutils) {
3234 m_frame_parser.mutils->initialize_frame_checking_environment();
3235 }
3236
3237 while (m_input_pending_q.m_size) {
3238 m_input_pending_q.pop_entry(&p1,&p2,&ident);
3239 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3240 }
3241
3242 if (psource_frame) {
3243 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3244 psource_frame = NULL;
3245 }
3246
3247 if (pdest_frame) {
3248 pdest_frame->nFilledLen = 0;
3249 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3250 (unsigned int)NULL);
3251 pdest_frame = NULL;
3252 }
3253 m_frame_parser.flush();
3254 } else if (codec_config_flag) {
3255 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3256 "is not sent to the driver yet");
3257 }
3258 pthread_mutex_unlock(&m_lock);
3259 input_flush_progress = false;
3260 if (!arbitrary_bytes) {
3261 prev_ts = LLONG_MAX;
3262 rst_prev_ts = true;
3263 }
3264 #ifdef _ANDROID_
3265 if (m_debug_timestamp) {
3266 m_timestamp_list.reset_ts_list();
3267 }
3268 #endif
3269 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3270 return bRet;
3271 }
3272
3273 /*=========================================================================
3274 FUNCTION : notify_flush_done
3275 DESCRIPTION
3276 Notifies flush done to the OMX Client.
3277 PARAMETERS
3278 ctxt -- Context information related to the self..
3279 RETURN VALUE
3280 NONE
3281 ==========================================================================*/
notify_flush_done(void * ctxt)3282 void omx_vdec::notify_flush_done(void *ctxt) {
3283 omx_vdec *pThis = (omx_vdec *) ctxt;
3284 if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3285 if (BITMASK_PRESENT(&pThis->m_flags,
3286 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3287 DEBUG_PRINT_LOW("Notify Output Flush done");
3288 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3289 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3290 OMX_EventCmdComplete,OMX_CommandFlush,
3291 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3292 }
3293
3294 if (BITMASK_PRESENT(&pThis->m_flags,
3295 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3296 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3297 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3298 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3299 OMX_EventCmdComplete,OMX_CommandFlush,
3300 OMX_CORE_INPUT_PORT_INDEX,NULL );
3301 }
3302 }
3303 }
3304
3305 /* ======================================================================
3306 FUNCTION
3307 omx_vdec::SendCommandEvent
3308
3309 DESCRIPTION
3310 Send the event to decoder pipe. This is needed to generate the callbacks
3311 in decoder thread context.
3312
3313 PARAMETERS
3314 None.
3315
3316 RETURN VALUE
3317 true/false
3318
3319 ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3320 bool omx_vdec::post_event(unsigned long p1,
3321 unsigned long p2,
3322 unsigned long id)
3323 {
3324 bool bRet = false;
3325
3326 /* Just drop messages typically generated by hardware (w/o client request),
3327 * if we've reported an error to client. */
3328 if (m_error_propogated) {
3329 switch (id) {
3330 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3331 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3332 DEBUG_PRINT_ERROR("Dropping message %lx "
3333 "since client expected to be in error state", id);
3334 return false;
3335 default:
3336 /* whatever */
3337 break;
3338 }
3339 }
3340
3341 pthread_mutex_lock(&m_lock);
3342
3343 if (id == m_fill_output_msg ||
3344 id == OMX_COMPONENT_GENERATE_FBD ||
3345 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3346 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3347 m_ftb_q.insert_entry(p1,p2,id);
3348 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3349 id == OMX_COMPONENT_GENERATE_EBD ||
3350 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3351 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3352 m_etb_q.insert_entry(p1,p2,id);
3353 } else {
3354 m_cmd_q.insert_entry(p1,p2,id);
3355 }
3356
3357 bRet = true;
3358 DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
3359 post_message(this, id);
3360
3361 pthread_mutex_unlock(&m_lock);
3362
3363 return bRet;
3364 }
3365
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3366 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3367 {
3368 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3369 if (!profileLevelType)
3370 return OMX_ErrorBadParameter;
3371
3372 if (profileLevelType->nPortIndex == 0) {
3373 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
3374 if (profileLevelType->nProfileIndex == 0) {
3375 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
3376 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
3377
3378 } else if (profileLevelType->nProfileIndex == 1) {
3379 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
3380 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
3381 } else if (profileLevelType->nProfileIndex == 2) {
3382 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
3383 profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
3384 } else {
3385 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3386 (unsigned int)profileLevelType->nProfileIndex);
3387 eRet = OMX_ErrorNoMore;
3388 }
3389 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
3390 if (profileLevelType->nProfileIndex == 0) {
3391 profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
3392 profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51;
3393 } else {
3394 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3395 (unsigned int)profileLevelType->nProfileIndex);
3396 eRet = OMX_ErrorNoMore;
3397 }
3398 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
3399 if (profileLevelType->nProfileIndex == 0) {
3400 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
3401 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
3402 } else if (profileLevelType->nProfileIndex == 1) {
3403 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
3404 profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
3405 } else {
3406 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3407 (unsigned int)profileLevelType->nProfileIndex);
3408 eRet = OMX_ErrorNoMore;
3409 }
3410 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) {
3411 if (profileLevelType->nProfileIndex == 0) {
3412 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
3413 profileLevelType->eLevel = OMX_VIDEO_H263Level70;
3414 } else {
3415 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3416 (unsigned int)profileLevelType->nProfileIndex);
3417 eRet = OMX_ErrorNoMore;
3418 }
3419 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
3420 if (profileLevelType->nProfileIndex == 0) {
3421 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3422 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
3423 } else if (profileLevelType->nProfileIndex == 1) {
3424 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3425 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
3426 } else {
3427 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3428 (unsigned int)profileLevelType->nProfileIndex);
3429 eRet = OMX_ErrorNoMore;
3430 }
3431 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
3432 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
3433 eRet = OMX_ErrorNoMore;
3434 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
3435 if (profileLevelType->nProfileIndex == 0) {
3436 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
3437 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
3438 } else if (profileLevelType->nProfileIndex == 1) {
3439 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
3440 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
3441 } else {
3442 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3443 (unsigned int)profileLevelType->nProfileIndex);
3444 eRet = OMX_ErrorNoMore;
3445 }
3446 } else {
3447 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
3448 eRet = OMX_ErrorNoMore;
3449 }
3450 } else {
3451 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
3452 (unsigned int)profileLevelType->nPortIndex);
3453 eRet = OMX_ErrorBadPortIndex;
3454 }
3455 return eRet;
3456 }
3457
3458 /* ======================================================================
3459 FUNCTION
3460 omx_vdec::GetParameter
3461
3462 DESCRIPTION
3463 OMX Get Parameter method implementation
3464
3465 PARAMETERS
3466 <TBD>.
3467
3468 RETURN VALUE
3469 Error None if successful.
3470
3471 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3472 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
3473 OMX_IN OMX_INDEXTYPE paramIndex,
3474 OMX_INOUT OMX_PTR paramData)
3475 {
3476 (void) hComp;
3477 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3478
3479 DEBUG_PRINT_LOW("get_parameter:");
3480 if (m_state == OMX_StateInvalid) {
3481 DEBUG_PRINT_ERROR("Get Param in Invalid State");
3482 return OMX_ErrorInvalidState;
3483 }
3484 if (paramData == NULL) {
3485 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3486 return OMX_ErrorBadParameter;
3487 }
3488 switch ((unsigned long)paramIndex) {
3489 case OMX_IndexParamPortDefinition: {
3490 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3491 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3492 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3493 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3494 decide_dpb_buffer_mode(is_down_scalar_enabled);
3495 eRet = update_portdef(portDefn);
3496 if (eRet == OMX_ErrorNone)
3497 m_port_def = *portDefn;
3498 break;
3499 }
3500 case OMX_IndexParamVideoInit: {
3501 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3502 OMX_PORT_PARAM_TYPE *portParamType =
3503 (OMX_PORT_PARAM_TYPE *) paramData;
3504 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3505
3506 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3507 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3508 portParamType->nPorts = 2;
3509 portParamType->nStartPortNumber = 0;
3510 break;
3511 }
3512 case OMX_IndexParamVideoPortFormat: {
3513 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3514 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3515 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3516 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3517
3518 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3519 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3520
3521 if (0 == portFmt->nPortIndex) {
3522 if (0 == portFmt->nIndex) {
3523 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
3524 portFmt->eCompressionFormat = eCompressionFormat;
3525 } else {
3526 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3527 " NoMore compression formats");
3528 eRet = OMX_ErrorNoMore;
3529 }
3530 } else if (1 == portFmt->nPortIndex) {
3531 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
3532
3533 // Distinguish non-surface mode from normal playback use-case based on
3534 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3535 // For non-android, use the default list
3536 // Also use default format-list if FLEXIBLE YUV is supported,
3537 // as the client negotiates the standard color-format if it needs to
3538 bool useNonSurfaceMode = false;
3539 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
3540 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3541 #endif
3542 if (is_thulium_v1) {
3543 portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
3544 } else {
3545 portFmt->eColorFormat = useNonSurfaceMode ?
3546 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3547 getPreferredColorFormatDefaultMode(portFmt->nIndex);
3548 }
3549
3550 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3551 eRet = OMX_ErrorNoMore;
3552 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3553 " NoMore Color formats");
3554 }
3555 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3556 } else {
3557 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3558 (int)portFmt->nPortIndex);
3559 eRet = OMX_ErrorBadPortIndex;
3560 }
3561 break;
3562 }
3563 /*Component should support this port definition*/
3564 case OMX_IndexParamAudioInit: {
3565 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3566 OMX_PORT_PARAM_TYPE *audioPortParamType =
3567 (OMX_PORT_PARAM_TYPE *) paramData;
3568 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3569 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3570 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3571 audioPortParamType->nPorts = 0;
3572 audioPortParamType->nStartPortNumber = 0;
3573 break;
3574 }
3575 /*Component should support this port definition*/
3576 case OMX_IndexParamImageInit: {
3577 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3578 OMX_PORT_PARAM_TYPE *imagePortParamType =
3579 (OMX_PORT_PARAM_TYPE *) paramData;
3580 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3581 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3582 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3583 imagePortParamType->nPorts = 0;
3584 imagePortParamType->nStartPortNumber = 0;
3585 break;
3586
3587 }
3588 /*Component should support this port definition*/
3589 case OMX_IndexParamOtherInit: {
3590 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3591 paramIndex);
3592 eRet =OMX_ErrorUnsupportedIndex;
3593 break;
3594 }
3595 case OMX_IndexParamStandardComponentRole: {
3596 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3597 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3598 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3599 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3600 comp_role->nSize = sizeof(*comp_role);
3601
3602 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3603 paramIndex);
3604 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3605 OMX_MAX_STRINGNAME_SIZE);
3606 break;
3607 }
3608 /* Added for parameter test */
3609 case OMX_IndexParamPriorityMgmt: {
3610 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3611 OMX_PRIORITYMGMTTYPE *priorityMgmType =
3612 (OMX_PRIORITYMGMTTYPE *) paramData;
3613 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3614 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3615 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3616
3617 break;
3618 }
3619 /* Added for parameter test */
3620 case OMX_IndexParamCompBufferSupplier: {
3621 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3622 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3623 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3624 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3625
3626 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3627 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3628 if (0 == bufferSupplierType->nPortIndex)
3629 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3630 else if (1 == bufferSupplierType->nPortIndex)
3631 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3632 else
3633 eRet = OMX_ErrorBadPortIndex;
3634
3635
3636 break;
3637 }
3638 case OMX_IndexParamVideoAvc: {
3639 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3640 paramIndex);
3641 break;
3642 }
3643 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3644 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3645 paramIndex);
3646 break;
3647 }
3648 case OMX_IndexParamVideoH263: {
3649 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
3650 paramIndex);
3651 break;
3652 }
3653 case OMX_IndexParamVideoMpeg4: {
3654 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
3655 paramIndex);
3656 break;
3657 }
3658 case OMX_IndexParamVideoMpeg2: {
3659 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3660 paramIndex);
3661 break;
3662 }
3663 case OMX_IndexParamVideoProfileLevelQuerySupported: {
3664 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3665 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3666 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3667 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3668 eRet = get_supported_profile_level(profileLevelType);
3669 break;
3670 }
3671 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3672 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3673 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3674 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3675 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3676 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3677
3678 if (secure_mode && !secure_scaling_to_non_secure_opb) {
3679 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3680 GRALLOC_USAGE_PRIVATE_UNCACHED);
3681 } else {
3682 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3683 }
3684 } else {
3685 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3686 eRet = OMX_ErrorBadParameter;
3687 }
3688 }
3689 break;
3690 #endif
3691
3692 #ifdef FLEXYUV_SUPPORTED
3693 case OMX_QcomIndexFlexibleYUVDescription: {
3694 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3695 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3696 eRet = describeColorFormat(paramData);
3697 break;
3698 }
3699 #endif
3700 case OMX_IndexParamVideoProfileLevelCurrent: {
3701 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3702 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3703 struct v4l2_control profile_control, level_control;
3704
3705 switch (drv_ctx.decoder_format) {
3706 case VDEC_CODECTYPE_H264:
3707 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3708 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3709 break;
3710 default:
3711 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3712 eRet = OMX_ErrorNotImplemented;
3713 break;
3714 }
3715
3716 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3717 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3718 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3719 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3720 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3721 break;
3722 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3723 pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3724 break;
3725 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3726 pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3727 break;
3728 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3729 pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3730 break;
3731 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3732 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3733 break;
3734 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3735 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3736 break;
3737 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3738 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3739 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3740 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3741 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3742 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3743 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3744 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3745 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3746 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3747 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3748 eRet = OMX_ErrorUnsupportedIndex;
3749 break;
3750 }
3751 } else {
3752 eRet = OMX_ErrorUnsupportedIndex;
3753 }
3754
3755
3756 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3757 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3758 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3759 pParam->eLevel = OMX_VIDEO_AVCLevel1;
3760 break;
3761 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3762 pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3763 break;
3764 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3765 pParam->eLevel = OMX_VIDEO_AVCLevel11;
3766 break;
3767 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3768 pParam->eLevel = OMX_VIDEO_AVCLevel12;
3769 break;
3770 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3771 pParam->eLevel = OMX_VIDEO_AVCLevel13;
3772 break;
3773 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
3774 pParam->eLevel = OMX_VIDEO_AVCLevel2;
3775 break;
3776 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
3777 pParam->eLevel = OMX_VIDEO_AVCLevel21;
3778 break;
3779 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
3780 pParam->eLevel = OMX_VIDEO_AVCLevel22;
3781 break;
3782 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
3783 pParam->eLevel = OMX_VIDEO_AVCLevel3;
3784 break;
3785 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
3786 pParam->eLevel = OMX_VIDEO_AVCLevel31;
3787 break;
3788 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
3789 pParam->eLevel = OMX_VIDEO_AVCLevel32;
3790 break;
3791 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
3792 pParam->eLevel = OMX_VIDEO_AVCLevel4;
3793 break;
3794 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
3795 pParam->eLevel = OMX_VIDEO_AVCLevel41;
3796 break;
3797 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
3798 pParam->eLevel = OMX_VIDEO_AVCLevel42;
3799 break;
3800 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
3801 pParam->eLevel = OMX_VIDEO_AVCLevel5;
3802 break;
3803 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
3804 pParam->eLevel = OMX_VIDEO_AVCLevel51;
3805 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
3806 pParam->eLevel = OMX_VIDEO_AVCLevel52;
3807 break;
3808 }
3809 } else {
3810 eRet = OMX_ErrorUnsupportedIndex;
3811 }
3812
3813 break;
3814
3815 }
3816 default: {
3817 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
3818 eRet =OMX_ErrorUnsupportedIndex;
3819 }
3820
3821 }
3822
3823 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
3824 drv_ctx.video_resolution.frame_width,
3825 drv_ctx.video_resolution.frame_height,
3826 drv_ctx.video_resolution.stride,
3827 drv_ctx.video_resolution.scan_lines);
3828
3829 return eRet;
3830 }
3831
3832 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)3833 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
3834 {
3835 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
3836 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3837 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
3838
3839 if ((params == NULL) ||
3840 (params->nativeBuffer == NULL) ||
3841 (params->nativeBuffer->handle == NULL) ||
3842 !m_enable_android_native_buffers)
3843 return OMX_ErrorBadParameter;
3844 m_use_android_native_buffers = OMX_TRUE;
3845 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3846 private_handle_t *handle = (private_handle_t *)nBuf->handle;
3847 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
3848 OMX_U8 *buffer = NULL;
3849 if (!secure_mode) {
3850 buffer = (OMX_U8*)mmap(0, handle->size,
3851 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3852 if (buffer == MAP_FAILED) {
3853 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3854 return OMX_ErrorInsufficientResources;
3855 }
3856 }
3857 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
3858 } else {
3859 eRet = OMX_ErrorBadParameter;
3860 }
3861 return eRet;
3862 }
3863 #endif
3864
enable_smoothstreaming()3865 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
3866 struct v4l2_control control;
3867 struct v4l2_format fmt;
3868 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
3869 control.value = 1;
3870 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
3871 if (rc < 0) {
3872 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3873 return OMX_ErrorHardware;
3874 }
3875 m_smoothstreaming_mode = true;
3876 return OMX_ErrorNone;
3877 }
3878
3879 /* ======================================================================
3880 FUNCTION
3881 omx_vdec::Setparameter
3882
3883 DESCRIPTION
3884 OMX Set Parameter method implementation.
3885
3886 PARAMETERS
3887 <TBD>.
3888
3889 RETURN VALUE
3890 OMX Error None if successful.
3891
3892 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)3893 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
3894 OMX_IN OMX_INDEXTYPE paramIndex,
3895 OMX_IN OMX_PTR paramData)
3896 {
3897 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3898 int ret=0;
3899 struct v4l2_format fmt;
3900 #ifdef _ANDROID_
3901 char property_value[PROPERTY_VALUE_MAX] = {0};
3902 #endif
3903 if (m_state == OMX_StateInvalid) {
3904 DEBUG_PRINT_ERROR("Set Param in Invalid State");
3905 return OMX_ErrorInvalidState;
3906 }
3907 if (paramData == NULL) {
3908 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
3909 return OMX_ErrorBadParameter;
3910 }
3911 if ((m_state != OMX_StateLoaded) &&
3912 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
3913 (m_out_bEnabled == OMX_TRUE) &&
3914 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
3915 (m_inp_bEnabled == OMX_TRUE)) {
3916 DEBUG_PRINT_ERROR("Set Param in Invalid State");
3917 return OMX_ErrorIncorrectStateOperation;
3918 }
3919 switch ((unsigned long)paramIndex) {
3920 case OMX_IndexParamPortDefinition: {
3921 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3922 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
3923 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3924 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
3925 //been called.
3926 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
3927 (int)portDefn->format.video.nFrameHeight,
3928 (int)portDefn->format.video.nFrameWidth);
3929
3930 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
3931 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
3932 portDefn->nBufferCountActual);
3933 eRet = OMX_ErrorBadParameter;
3934 break;
3935 }
3936 if (OMX_DirOutput == portDefn->eDir) {
3937 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
3938 bool port_format_changed = false;
3939 m_display_id = portDefn->format.video.pNativeWindow;
3940 unsigned int buffer_size;
3941 /* update output port resolution with client supplied dimensions
3942 in case scaling is enabled, else it follows input resolution set
3943 */
3944 decide_dpb_buffer_mode(is_down_scalar_enabled);
3945 if (is_down_scalar_enabled) {
3946 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
3947 (unsigned int)portDefn->format.video.nFrameWidth,
3948 (unsigned int)portDefn->format.video.nFrameHeight);
3949 if (portDefn->format.video.nFrameHeight != 0x0 &&
3950 portDefn->format.video.nFrameWidth != 0x0) {
3951 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3952 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3953 fmt.fmt.pix_mp.pixelformat = capture_capability;
3954 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
3955 if (ret) {
3956 DEBUG_PRINT_ERROR("Get Resolution failed");
3957 eRet = OMX_ErrorHardware;
3958 break;
3959 }
3960 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
3961 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
3962 port_format_changed = true;
3963 }
3964 update_resolution(portDefn->format.video.nFrameWidth,
3965 portDefn->format.video.nFrameHeight,
3966 portDefn->format.video.nFrameWidth,
3967 portDefn->format.video.nFrameHeight);
3968
3969 /* set crop info */
3970 rectangle.nLeft = 0;
3971 rectangle.nTop = 0;
3972 rectangle.nWidth = portDefn->format.video.nFrameWidth;
3973 rectangle.nHeight = portDefn->format.video.nFrameHeight;
3974
3975 eRet = is_video_session_supported();
3976 if (eRet)
3977 break;
3978 memset(&fmt, 0x0, sizeof(struct v4l2_format));
3979 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3980 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3981 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3982 fmt.fmt.pix_mp.pixelformat = capture_capability;
3983 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
3984 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
3985 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3986 if (ret) {
3987 DEBUG_PRINT_ERROR("Set Resolution failed");
3988 eRet = OMX_ErrorUnsupportedSetting;
3989 } else
3990 eRet = get_buffer_req(&drv_ctx.op_buf);
3991 }
3992
3993 if (eRet) {
3994 break;
3995 }
3996
3997 if (secure_mode) {
3998 struct v4l2_control control;
3999 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
4000 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
4001 DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
4002 eRet = OMX_ErrorHardware;
4003 } else {
4004 /* This is a workaround for a bug in fw which uses stride
4005 * and slice instead of width and height to check against
4006 * the threshold.
4007 */
4008 OMX_U32 stride, slice;
4009 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
4010 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
4011 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
4012 } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
4013 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
4014 slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
4015 } else {
4016 stride = portDefn->format.video.nFrameWidth;
4017 slice = portDefn->format.video.nFrameHeight;
4018 }
4019
4020 DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
4021 DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
4022
4023 if (stride * slice <= (OMX_U32)control.value) {
4024 secure_scaling_to_non_secure_opb = true;
4025 DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
4026 control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
4027 control.value = 1;
4028 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
4029 DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
4030 eRet = OMX_ErrorUnsupportedSetting;
4031 }
4032 }
4033 }
4034 }
4035 }
4036
4037 if (eRet) {
4038 break;
4039 }
4040
4041 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4042 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4043 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4044 eRet = OMX_ErrorBadParameter;
4045 } else if (!client_buffers.get_buffer_req(buffer_size)) {
4046 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4047 eRet = OMX_ErrorBadParameter;
4048 } else if (!port_format_changed) {
4049
4050 // Buffer count can change only when port is unallocated
4051 if (m_out_mem_ptr &&
4052 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4053 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4054
4055 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4056 eRet = OMX_ErrorInvalidState;
4057 break;
4058 }
4059
4060 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
4061 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) {
4062 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
4063 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
4064 drv_ctx.extradata_info.count = drv_ctx.op_buf.actualcount;
4065 drv_ctx.extradata_info.size = drv_ctx.extradata_info.count *
4066 drv_ctx.extradata_info.buffer_size;
4067 eRet = set_buffer_req(&drv_ctx.op_buf);
4068 if (eRet == OMX_ErrorNone)
4069 m_port_def = *portDefn;
4070 } else {
4071 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4072 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size,
4073 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4074 eRet = OMX_ErrorBadParameter;
4075 }
4076 }
4077 } else if (OMX_DirInput == portDefn->eDir) {
4078 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4079 bool port_format_changed = false;
4080 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4081 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4082 // Frame rate only should be set if this is a "known value" or to
4083 // activate ts prediction logic (arbitrary mode only) sending input
4084 // timestamps with max value (LLONG_MAX).
4085 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4086 (unsigned int)portDefn->format.video.xFramerate >> 16);
4087 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4088 drv_ctx.frame_rate.fps_denominator);
4089 if (!drv_ctx.frame_rate.fps_numerator) {
4090 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4091 drv_ctx.frame_rate.fps_numerator = 30;
4092 }
4093 if (drv_ctx.frame_rate.fps_denominator)
4094 drv_ctx.frame_rate.fps_numerator = (int)
4095 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4096 drv_ctx.frame_rate.fps_denominator = 1;
4097 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4098 drv_ctx.frame_rate.fps_numerator;
4099 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4100 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4101 (float)drv_ctx.frame_rate.fps_denominator);
4102
4103 struct v4l2_outputparm oparm;
4104 /*XXX: we're providing timing info as seconds per frame rather than frames
4105 * per second.*/
4106 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4107 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4108
4109 struct v4l2_streamparm sparm;
4110 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4111 sparm.parm.output = oparm;
4112 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4113 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4114 eRet = OMX_ErrorHardware;
4115 break;
4116 }
4117 m_perf_control.request_cores(frm_int);
4118 }
4119
4120 if (drv_ctx.video_resolution.frame_height !=
4121 portDefn->format.video.nFrameHeight ||
4122 drv_ctx.video_resolution.frame_width !=
4123 portDefn->format.video.nFrameWidth) {
4124 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4125 (unsigned int)portDefn->format.video.nFrameWidth,
4126 (unsigned int)portDefn->format.video.nFrameHeight);
4127 port_format_changed = true;
4128 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4129 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4130 if (frameHeight != 0x0 && frameWidth != 0x0) {
4131 if (m_smoothstreaming_mode &&
4132 ((frameWidth * frameHeight) <
4133 (m_smoothstreaming_width * m_smoothstreaming_height))) {
4134 frameWidth = m_smoothstreaming_width;
4135 frameHeight = m_smoothstreaming_height;
4136 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4137 "for adaptive-playback/smooth-streaming",
4138 (unsigned int)frameWidth, (unsigned int)frameHeight);
4139 }
4140 update_resolution(frameWidth, frameHeight,
4141 frameWidth, frameHeight);
4142 eRet = is_video_session_supported();
4143 if (eRet)
4144 break;
4145 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4146 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4147 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4148 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4149 fmt.fmt.pix_mp.pixelformat = output_capability;
4150 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);
4151 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4152 if (ret) {
4153 DEBUG_PRINT_ERROR("Set Resolution failed");
4154 eRet = OMX_ErrorUnsupportedSetting;
4155 } else {
4156 if (!is_down_scalar_enabled)
4157 eRet = get_buffer_req(&drv_ctx.op_buf);
4158 }
4159 }
4160 }
4161 if (m_custom_buffersize.input_buffersize
4162 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4163 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4164 m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4165 eRet = OMX_ErrorBadParameter;
4166 break;
4167 }
4168 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4169 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4170 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4171 eRet = OMX_ErrorBadParameter;
4172 break;
4173 }
4174 // Buffer count can change only when port is unallocated
4175 if (m_inp_mem_ptr &&
4176 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4177 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4178 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4179 eRet = OMX_ErrorInvalidState;
4180 break;
4181 }
4182
4183 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4184 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4185 port_format_changed = true;
4186 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4187 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4188 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4189 (~(buffer_prop->alignment - 1));
4190 eRet = set_buffer_req(buffer_prop);
4191 }
4192 if (false == port_format_changed) {
4193 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4194 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4195 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4196 eRet = OMX_ErrorBadParameter;
4197 }
4198 } else if (portDefn->eDir == OMX_DirMax) {
4199 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4200 (int)portDefn->nPortIndex);
4201 eRet = OMX_ErrorBadPortIndex;
4202 }
4203 }
4204 break;
4205 case OMX_IndexParamVideoPortFormat: {
4206 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4207 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4208 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4209 int ret=0;
4210 struct v4l2_format fmt;
4211 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4212 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4213
4214 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4215 if (1 == portFmt->nPortIndex) {
4216 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4217 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4218 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4219 enum vdec_output_fromat op_format;
4220 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4221 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4222 portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4223 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
4224 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4225 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4226 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
4227 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4228 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4229 op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
4230 } else
4231 eRet = OMX_ErrorBadParameter;
4232
4233 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4234 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
4235 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4236 } else {
4237 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4238 }
4239
4240 if (eRet == OMX_ErrorNone) {
4241 drv_ctx.output_format = op_format;
4242 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4243 if (ret) {
4244 DEBUG_PRINT_ERROR("Set output format failed");
4245 eRet = OMX_ErrorUnsupportedSetting;
4246 /*TODO: How to handle this case */
4247 } else {
4248 eRet = get_buffer_req(&drv_ctx.op_buf);
4249 }
4250 }
4251 if (eRet == OMX_ErrorNone) {
4252 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4253 DEBUG_PRINT_ERROR("Set color format failed");
4254 eRet = OMX_ErrorBadParameter;
4255 }
4256 }
4257 }
4258 }
4259 break;
4260
4261 case OMX_QcomIndexPortDefn: {
4262 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4263 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4264 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4265 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4266 (unsigned int)portFmt->nFramePackingFormat);
4267
4268 /* Input port */
4269 if (portFmt->nPortIndex == 0) {
4270 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4271 // - headers are allocated and
4272 // - headers-indices are derived
4273 // Avoid changing arbitrary_bytes when the port is already allocated
4274 if (m_inp_mem_ptr) {
4275 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4276 return OMX_ErrorUnsupportedSetting;
4277 }
4278 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4279 if (secure_mode || m_input_pass_buffer_fd) {
4280 arbitrary_bytes = false;
4281 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4282 eRet = OMX_ErrorUnsupportedSetting;
4283 } else {
4284 arbitrary_bytes = true;
4285 }
4286 } else if (portFmt->nFramePackingFormat ==
4287 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4288 arbitrary_bytes = false;
4289 #ifdef _ANDROID_
4290 property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
4291 if (atoi(property_value)) {
4292 DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
4293 arbitrary_bytes = true;
4294 }
4295 #endif
4296 } else {
4297 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4298 (unsigned int)portFmt->nFramePackingFormat);
4299 eRet = OMX_ErrorUnsupportedSetting;
4300 }
4301 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4302 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
4303 if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
4304 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
4305 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
4306 m_out_mem_region_smi = OMX_TRUE;
4307 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4308 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
4309 m_use_output_pmem = OMX_TRUE;
4310 }
4311 }
4312 }
4313 }
4314 if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
4315 OMX_MAX_STRINGNAME_SIZE)) {
4316 arbitrary_bytes = true;
4317 DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
4318 }
4319 break;
4320
4321 case OMX_IndexParamStandardComponentRole: {
4322 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4323 OMX_PARAM_COMPONENTROLETYPE *comp_role;
4324 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4325 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4326 comp_role->cRole);
4327
4328 if ((m_state == OMX_StateLoaded)&&
4329 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4330 DEBUG_PRINT_LOW("Set Parameter called in valid state");
4331 } else {
4332 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4333 return OMX_ErrorIncorrectStateOperation;
4334 }
4335
4336 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4337 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4338 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4339 } else {
4340 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4341 eRet =OMX_ErrorUnsupportedSetting;
4342 }
4343 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4344 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4345 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4346 } else {
4347 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4348 eRet = OMX_ErrorUnsupportedSetting;
4349 }
4350 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4351 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
4352 strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
4353 } else {
4354 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4355 eRet = OMX_ErrorUnsupportedSetting;
4356 }
4357 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4358 if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
4359 strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
4360 } else {
4361 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4362 eRet =OMX_ErrorUnsupportedSetting;
4363 }
4364 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4365 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4366 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4367 } else {
4368 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4369 eRet = OMX_ErrorUnsupportedSetting;
4370 }
4371 } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
4372 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
4373 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
4374 ) {
4375 if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
4376 strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
4377 } else {
4378 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4379 eRet =OMX_ErrorUnsupportedSetting;
4380 }
4381 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
4382 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
4383 ) {
4384 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
4385 strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
4386 } else {
4387 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4388 eRet =OMX_ErrorUnsupportedSetting;
4389 }
4390 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4391 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4392 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4393 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4394 } else {
4395 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4396 eRet = OMX_ErrorUnsupportedSetting;
4397 }
4398 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4399 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4400 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4401 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4402 } else {
4403 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4404 eRet = OMX_ErrorUnsupportedSetting;
4405 }
4406 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4407 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4408 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4409 } else {
4410 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4411 eRet = OMX_ErrorUnsupportedSetting;
4412 }
4413 } else {
4414 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4415 eRet = OMX_ErrorInvalidComponentName;
4416 }
4417 break;
4418 }
4419
4420 case OMX_IndexParamPriorityMgmt: {
4421 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4422 if (m_state != OMX_StateLoaded) {
4423 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4424 return OMX_ErrorIncorrectStateOperation;
4425 }
4426 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4427 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4428 (unsigned int)priorityMgmtype->nGroupID);
4429
4430 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4431 (unsigned int)priorityMgmtype->nGroupPriority);
4432
4433 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4434 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4435
4436 break;
4437 }
4438
4439 case OMX_IndexParamCompBufferSupplier: {
4440 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4441 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4442 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4443 bufferSupplierType->eBufferSupplier);
4444 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4445 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4446
4447 else
4448
4449 eRet = OMX_ErrorBadPortIndex;
4450
4451 break;
4452
4453 }
4454 case OMX_IndexParamVideoAvc: {
4455 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4456 paramIndex);
4457 break;
4458 }
4459 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4460 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4461 paramIndex);
4462 break;
4463 }
4464 case OMX_IndexParamVideoH263: {
4465 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
4466 paramIndex);
4467 break;
4468 }
4469 case OMX_IndexParamVideoMpeg4: {
4470 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
4471 paramIndex);
4472 break;
4473 }
4474 case OMX_IndexParamVideoMpeg2: {
4475 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4476 paramIndex);
4477 break;
4478 }
4479 case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4480 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4481 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4482 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4483 struct v4l2_control control;
4484 int pic_order,rc=0;
4485 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4486 pictureOrder->eOutputPictureOrder);
4487 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4488 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4489 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4490 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4491 time_stamp_dts.set_timestamp_reorder_mode(false);
4492 } else
4493 eRet = OMX_ErrorBadParameter;
4494 if (eRet == OMX_ErrorNone) {
4495 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4496 control.value = pic_order;
4497 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4498 if (rc) {
4499 DEBUG_PRINT_ERROR("Set picture order failed");
4500 eRet = OMX_ErrorUnsupportedSetting;
4501 }
4502 }
4503 m_decode_order_mode =
4504 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4505 break;
4506 }
4507 case OMX_QcomIndexParamConcealMBMapExtraData:
4508 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4509 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
4510 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4511 break;
4512 case OMX_QcomIndexParamFrameInfoExtraData:
4513 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4514 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4515 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4516 break;
4517 case OMX_ExtraDataFrameDimension:
4518 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4519 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4520 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4521 break;
4522 case OMX_QcomIndexParamInterlaceExtraData:
4523 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4524 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4525 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4526 break;
4527 case OMX_QcomIndexParamH264TimeInfo:
4528 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4529 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4530 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4531 break;
4532 case OMX_QcomIndexParamVideoFramePackingExtradata:
4533 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4534 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4535 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4536 break;
4537 case OMX_QcomIndexParamVideoQPExtraData:
4538 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4539 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4540 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4541 break;
4542 case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4543 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4544 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4545 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4546 break;
4547 case OMX_QcomIndexEnableExtnUserData:
4548 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4549 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4550 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4551 break;
4552 case OMX_QTIIndexParamVQZipSEIExtraData:
4553 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4554 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4555 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4556 break;
4557 case OMX_QcomIndexParamVideoDivx: {
4558 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
4559 }
4560 break;
4561 case OMX_QcomIndexPlatformPvt: {
4562 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
4563 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
4564 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
4565 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4566 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
4567 eRet = OMX_ErrorUnsupportedSetting;
4568 } else {
4569 m_out_pvt_entry_pmem = OMX_TRUE;
4570 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
4571 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
4572 m_use_output_pmem = OMX_TRUE;
4573 }
4574 }
4575
4576 }
4577 break;
4578 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4579 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4580 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4581 struct v4l2_control control;
4582 int rc;
4583 drv_ctx.idr_only_decoding = 1;
4584 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4585 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4586 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4587 if (rc) {
4588 DEBUG_PRINT_ERROR("Set picture order failed");
4589 eRet = OMX_ErrorUnsupportedSetting;
4590 } else {
4591 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4592 control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
4593 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4594 if (rc) {
4595 DEBUG_PRINT_ERROR("Sync frame setting failed");
4596 eRet = OMX_ErrorUnsupportedSetting;
4597 }
4598 /*Setting sync frame decoding on driver might change buffer
4599 * requirements so update them here*/
4600 if (get_buffer_req(&drv_ctx.ip_buf)) {
4601 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4602 eRet = OMX_ErrorUnsupportedSetting;
4603 }
4604 if (get_buffer_req(&drv_ctx.op_buf)) {
4605 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4606 eRet = OMX_ErrorUnsupportedSetting;
4607 }
4608 }
4609 }
4610 break;
4611
4612 case OMX_QcomIndexParamIndexExtraDataType: {
4613 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4614 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4615 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4616 (extradataIndexType->bEnabled == OMX_TRUE) &&
4617 (extradataIndexType->nPortIndex == 1)) {
4618 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4619 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4620
4621 }
4622 }
4623 break;
4624 case OMX_QcomIndexParamEnableSmoothStreaming: {
4625 #ifndef SMOOTH_STREAMING_DISABLED
4626 eRet = enable_smoothstreaming();
4627 #else
4628 eRet = OMX_ErrorUnsupportedSetting;
4629 #endif
4630 }
4631 break;
4632 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4633 /* Need to allow following two set_parameters even in Idle
4634 * state. This is ANDROID architecture which is not in sync
4635 * with openmax standard. */
4636 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4637 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4638 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4639 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4640 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4641 eRet = OMX_ErrorUnsupportedSetting;
4642 break;
4643 } else if (m_out_mem_ptr) {
4644 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4645 eRet = OMX_ErrorInvalidState;
4646 break;
4647 }
4648 if (enableNativeBuffers) {
4649 m_enable_android_native_buffers = enableNativeBuffers->enable;
4650 }
4651 #if !defined(FLEXYUV_SUPPORTED)
4652 if (m_enable_android_native_buffers) {
4653 // Use the most-preferred-native-color-format as surface-mode is hinted here
4654 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4655 DEBUG_PRINT_ERROR("Failed to set native color format!");
4656 eRet = OMX_ErrorUnsupportedSetting;
4657 }
4658 }
4659 #endif
4660 }
4661 break;
4662 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4663 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4664 eRet = use_android_native_buffer(hComp, paramData);
4665 }
4666 break;
4667 case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4668
4669 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4670 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4671
4672 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4673 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
4674 eRet = OMX_ErrorUnsupportedSetting;
4675 break;
4676 } else if (m_inp_mem_ptr) {
4677 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4678 eRet = OMX_ErrorInvalidState;
4679 break;
4680 }
4681
4682 if (allocateNativeHandleParams != NULL) {
4683 allocate_native_handle = allocateNativeHandleParams->enable;
4684 }
4685 }
4686 break;
4687 #endif
4688 case OMX_QcomIndexParamEnableTimeStampReorder: {
4689 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4690 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4691 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4692 if (reorder->bEnable == OMX_TRUE) {
4693 frm_int =0;
4694 time_stamp_dts.set_timestamp_reorder_mode(true);
4695 } else
4696 time_stamp_dts.set_timestamp_reorder_mode(false);
4697 } else {
4698 time_stamp_dts.set_timestamp_reorder_mode(false);
4699 if (reorder->bEnable == OMX_TRUE) {
4700 eRet = OMX_ErrorUnsupportedSetting;
4701 }
4702 }
4703 }
4704 break;
4705 case OMX_IndexParamVideoProfileLevelCurrent: {
4706 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4707 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4708 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4709 if (pParam) {
4710 m_profile_lvl.eProfile = pParam->eProfile;
4711 m_profile_lvl.eLevel = pParam->eLevel;
4712 }
4713 break;
4714
4715 }
4716 case OMX_QcomIndexParamVideoMetaBufferMode:
4717 {
4718 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4719 StoreMetaDataInBuffersParams *metabuffer =
4720 (StoreMetaDataInBuffersParams *)paramData;
4721 if (!metabuffer) {
4722 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4723 eRet = OMX_ErrorBadParameter;
4724 break;
4725 }
4726 if (m_disable_dynamic_buf_mode) {
4727 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4728 eRet = OMX_ErrorUnsupportedSetting;
4729 break;
4730 }
4731 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4732
4733 if (m_out_mem_ptr) {
4734 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
4735 eRet = OMX_ErrorInvalidState;
4736 break;
4737 }
4738 //set property dynamic buffer mode to driver.
4739 struct v4l2_control control;
4740 struct v4l2_format fmt;
4741 control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
4742 if (metabuffer->bStoreMetaData == true) {
4743 control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
4744 } else {
4745 control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
4746 }
4747 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4748 if (!rc) {
4749 DEBUG_PRINT_HIGH("%s buffer mode",
4750 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
4751 } else {
4752 DEBUG_PRINT_ERROR("Failed to %s buffer mode",
4753 (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
4754 }
4755 dynamic_buf_mode = metabuffer->bStoreMetaData;
4756 } else {
4757 DEBUG_PRINT_ERROR(
4758 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
4759 (unsigned int)metabuffer->nPortIndex);
4760 eRet = OMX_ErrorUnsupportedSetting;
4761 }
4762 break;
4763 }
4764 case OMX_QcomIndexParamVideoDownScalar:
4765 {
4766 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
4767 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
4768 struct v4l2_control control;
4769 int rc;
4770 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
4771
4772 if (pParam && pParam->bEnable) {
4773 rc = enable_downscalar();
4774 if (rc < 0) {
4775 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
4776 return OMX_ErrorUnsupportedSetting;
4777 }
4778 m_force_down_scalar = pParam->bEnable;
4779 } else {
4780 rc = disable_downscalar();
4781 if (rc < 0) {
4782 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
4783 return OMX_ErrorUnsupportedSetting;
4784 }
4785 m_force_down_scalar = pParam->bEnable;
4786 }
4787 break;
4788 }
4789 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
4790 case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
4791 {
4792 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
4793 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
4794 PrepareForAdaptivePlaybackParams* pParams =
4795 (PrepareForAdaptivePlaybackParams *) paramData;
4796 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4797 if (!pParams->bEnable) {
4798 return OMX_ErrorNone;
4799 }
4800 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
4801 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
4802 DEBUG_PRINT_ERROR(
4803 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
4804 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
4805 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
4806 eRet = OMX_ErrorBadParameter;
4807 } else {
4808 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
4809 }
4810 } else {
4811 DEBUG_PRINT_ERROR(
4812 "Prepare for adaptive playback supported only on output port");
4813 eRet = OMX_ErrorBadParameter;
4814 }
4815 break;
4816 }
4817
4818 case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
4819 {
4820 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4821 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
4822 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4823 if (m_disable_dynamic_buf_mode) {
4824 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
4825 }
4826 break;
4827 }
4828 #endif
4829 case OMX_QcomIndexParamVideoCustomBufferSize:
4830 {
4831 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
4832 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
4833 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
4834 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
4835 struct v4l2_control control;
4836 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
4837 control.value = pParam->nBufferSize;
4838 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
4839 DEBUG_PRINT_ERROR("Failed to set input buffer size");
4840 eRet = OMX_ErrorUnsupportedSetting;
4841 } else {
4842 eRet = get_buffer_req(&drv_ctx.ip_buf);
4843 if (eRet == OMX_ErrorNone) {
4844 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
4845 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
4846 m_custom_buffersize.input_buffersize);
4847 } else {
4848 DEBUG_PRINT_ERROR("Failed to get buffer requirement");
4849 }
4850 }
4851 } else {
4852 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
4853 eRet = OMX_ErrorBadParameter;
4854 }
4855 break;
4856 }
4857 case OMX_QTIIndexParamVQZIPSEIType:
4858 {
4859 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
4860 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
4861 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
4862 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
4863 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
4864 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4865 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4866 if (eRet != OMX_ErrorNone) {
4867 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
4868 eRet = OMX_ErrorBadParameter;
4869 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4870 } else {
4871 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4872 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4873 if (eRet != OMX_ErrorNone) {
4874 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
4875 eRet = OMX_ErrorBadParameter;
4876 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
4877 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
4878 }
4879 }
4880 break;
4881 }
4882
4883 case OMX_QTIIndexParamPassInputBufferFd:
4884 {
4885 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4886 if (arbitrary_bytes) {
4887 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
4888 eRet = OMX_ErrorUnsupportedSetting;
4889 break;
4890 }
4891
4892 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
4893 if (m_input_pass_buffer_fd)
4894 DEBUG_PRINT_LOW("Enable passing input buffer FD");
4895 break;
4896 }
4897 case OMX_QTIIndexParamForceCompressedForDPB:
4898 {
4899 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
4900 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
4901 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
4902 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
4903 if (m_disable_ubwc_mode) {
4904 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
4905 eRet = OMX_ErrorUnsupportedSetting;
4906 break;
4907 }
4908 if (!paramData) {
4909 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
4910 eRet = OMX_ErrorBadParameter;
4911 break;
4912 }
4913
4914 m_force_compressed_for_dpb = pParam->bEnable;
4915 break;
4916 }
4917 case OMX_QTIIndexParamForceUnCompressedForOPB:
4918 {
4919 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE);
4920 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
4921 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
4922 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
4923 if (!paramData) {
4924 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
4925 eRet = OMX_ErrorBadParameter;
4926 break;
4927 }
4928 m_disable_ubwc_mode = pParam->bEnable;
4929 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
4930 break;
4931 }
4932
4933
4934 default: {
4935 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
4936 eRet = OMX_ErrorUnsupportedIndex;
4937 }
4938 }
4939 if (eRet != OMX_ErrorNone)
4940 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
4941 return eRet;
4942 }
4943
4944 /* ======================================================================
4945 FUNCTION
4946 omx_vdec::GetConfig
4947
4948 DESCRIPTION
4949 OMX Get Config Method implementation.
4950
4951 PARAMETERS
4952 <TBD>.
4953
4954 RETURN VALUE
4955 OMX Error None if successful.
4956
4957 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)4958 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
4959 OMX_IN OMX_INDEXTYPE configIndex,
4960 OMX_INOUT OMX_PTR configData)
4961 {
4962 (void) hComp;
4963 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4964
4965 if (m_state == OMX_StateInvalid) {
4966 DEBUG_PRINT_ERROR("Get Config in Invalid State");
4967 return OMX_ErrorInvalidState;
4968 }
4969
4970 switch ((unsigned long)configIndex) {
4971 case OMX_QcomIndexConfigInterlaced: {
4972 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
4973 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
4974 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
4975 if (configFmt->nPortIndex == 1) {
4976 if (configFmt->nIndex == 0) {
4977 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
4978 } else if (configFmt->nIndex == 1) {
4979 configFmt->eInterlaceType =
4980 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
4981 } else if (configFmt->nIndex == 2) {
4982 configFmt->eInterlaceType =
4983 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
4984 } else {
4985 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
4986 " NoMore Interlaced formats");
4987 eRet = OMX_ErrorNoMore;
4988 }
4989
4990 } else {
4991 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
4992 (int)configFmt->nPortIndex);
4993 eRet = OMX_ErrorBadPortIndex;
4994 }
4995 break;
4996 }
4997 case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
4998 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
4999 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5000 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5001 decoderinstances->nNumOfInstances = 16;
5002 /*TODO: How to handle this case */
5003 break;
5004 }
5005 case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5006 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5007 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5008 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5009 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5010 memcpy(configFmt, &m_frame_pack_arrangement,
5011 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5012 } else {
5013 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5014 }
5015 break;
5016 }
5017 case OMX_IndexConfigCommonOutputCrop: {
5018 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5019 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5020 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5021 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5022 rectangle.nLeft, rectangle.nTop,
5023 rectangle.nWidth, rectangle.nHeight);
5024 break;
5025 }
5026 case OMX_QcomIndexConfigPerfLevel: {
5027 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
5028 struct v4l2_control control;
5029 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5030 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5031
5032 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5033 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
5034 DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
5035 eRet = OMX_ErrorHardware;
5036 }
5037
5038 if (eRet == OMX_ErrorNone) {
5039 switch (control.value) {
5040 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
5041 perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
5042 break;
5043 default:
5044 DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
5045 /* Fall through */
5046 case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
5047 perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
5048 break;
5049 }
5050 }
5051
5052 break;
5053 }
5054 case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5055 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5056 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5057 struct v4l2_control control;
5058
5059 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5060 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5061 eRet = OMX_ErrorNotImplemented;
5062 break;
5063 }
5064
5065 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5066 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5067 coding->bCabac = (OMX_BOOL)
5068 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5069 /* We can't query driver at the moment for the cabac mode, so
5070 * just use 0xff...f as a place holder for future improvement */
5071 coding->nCabacInitIdc = ~0;
5072 } else {
5073 eRet = OMX_ErrorUnsupportedIndex;
5074 }
5075
5076 break;
5077 }
5078 case OMX_QTIIndexConfigDescribeColorAspects:
5079 {
5080 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5081 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5082
5083 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5084 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5085
5086 if (params->bRequestingDataSpace) {
5087 DEBUG_PRINT_ERROR("Does not handle dataspace request");
5088 return OMX_ErrorUnsupportedSetting;
5089 }
5090 if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) {
5091 DEBUG_PRINT_LOW("Updating Client's color aspects with internal");
5092 memcpy(&(m_client_color_space.sAspects),
5093 &(m_internal_color_space.sAspects), sizeof(ColorAspects));
5094 m_internal_color_space.bDataSpaceChanged = OMX_FALSE;
5095 }
5096 memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects));
5097
5098 break;
5099 }
5100 case OMX_IndexConfigAndroidVendorExtension:
5101 {
5102 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5103
5104 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5105 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5106 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5107 return get_vendor_extension_config(ext);
5108 }
5109 default:
5110 {
5111 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5112 eRet = OMX_ErrorBadParameter;
5113 }
5114
5115 }
5116
5117 return eRet;
5118 }
5119
5120 /* ======================================================================
5121 FUNCTION
5122 omx_vdec::SetConfig
5123
5124 DESCRIPTION
5125 OMX Set Config method implementation
5126
5127 PARAMETERS
5128 <TBD>.
5129
5130 RETURN VALUE
5131 OMX Error None if successful.
5132 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5133 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
5134 OMX_IN OMX_INDEXTYPE configIndex,
5135 OMX_IN OMX_PTR configData)
5136 {
5137 (void) hComp;
5138 if (m_state == OMX_StateInvalid) {
5139 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5140 return OMX_ErrorInvalidState;
5141 }
5142
5143 OMX_ERRORTYPE ret = OMX_ErrorNone;
5144 OMX_VIDEO_CONFIG_NALSIZE *pNal;
5145
5146 DEBUG_PRINT_LOW("Set Config Called");
5147
5148 if (configIndex == OMX_IndexConfigVideoNalSize) {
5149 struct v4l2_control temp;
5150 temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
5151
5152 VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
5153 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
5154 switch (pNal->nNaluBytes) {
5155 case 0:
5156 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
5157 break;
5158 case 2:
5159 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
5160 break;
5161 case 4:
5162 temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
5163 break;
5164 default:
5165 return OMX_ErrorUnsupportedSetting;
5166 }
5167
5168 if (!arbitrary_bytes) {
5169 /* In arbitrary bytes mode, the assembler strips out nal size and replaces
5170 * with start code, so only need to notify driver in frame by frame mode */
5171 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
5172 DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
5173 return OMX_ErrorHardware;
5174 }
5175 }
5176
5177 nal_length = pNal->nNaluBytes;
5178 m_frame_parser.init_nal_length(nal_length);
5179
5180 DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
5181 return ret;
5182 } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5183 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5184 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5185
5186 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5187 if (config->bEnabled) {
5188 if ((config->nFps >> 16) > 0) {
5189 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5190 (unsigned int)config->nFps >> 16);
5191 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5192 drv_ctx.frame_rate.fps_denominator);
5193
5194 if (!drv_ctx.frame_rate.fps_numerator) {
5195 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5196 drv_ctx.frame_rate.fps_numerator = 30;
5197 }
5198
5199 if (drv_ctx.frame_rate.fps_denominator) {
5200 drv_ctx.frame_rate.fps_numerator = (int)
5201 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5202 }
5203
5204 drv_ctx.frame_rate.fps_denominator = 1;
5205 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5206 drv_ctx.frame_rate.fps_numerator;
5207
5208 struct v4l2_outputparm oparm;
5209 /*XXX: we're providing timing info as seconds per frame rather than frames
5210 * per second.*/
5211 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5212 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5213
5214 struct v4l2_streamparm sparm;
5215 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5216 sparm.parm.output = oparm;
5217 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5218 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5219 performance might be affected");
5220 ret = OMX_ErrorHardware;
5221 }
5222 client_set_fps = true;
5223 } else {
5224 DEBUG_PRINT_ERROR("Frame rate not supported.");
5225 ret = OMX_ErrorUnsupportedSetting;
5226 }
5227 } else {
5228 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5229 client_set_fps = false;
5230 }
5231 } else {
5232 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5233 (int)config->nPortIndex);
5234 ret = OMX_ErrorBadPortIndex;
5235 }
5236
5237 return ret;
5238 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
5239 OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
5240 (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
5241 struct v4l2_control control;
5242
5243 DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
5244
5245 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
5246
5247 switch (perf->ePerfLevel) {
5248 case OMX_QCOM_PerfLevelNominal:
5249 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
5250 break;
5251 case OMX_QCOM_PerfLevelTurbo:
5252 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
5253 break;
5254 default:
5255 ret = OMX_ErrorUnsupportedSetting;
5256 break;
5257 }
5258
5259 if (ret == OMX_ErrorNone) {
5260 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5261 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5262 }
5263
5264 return ret;
5265 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5266 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5267 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5268 struct v4l2_control control;
5269 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5270 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5271
5272 switch (config->eDecodeType) {
5273 case OMX_QCOM_PictypeDecode_I:
5274 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
5275 break;
5276 case OMX_QCOM_PictypeDecode_IPB:
5277 default:
5278 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
5279 break;
5280 }
5281
5282 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5283 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5284 if (ret)
5285 DEBUG_PRINT_ERROR("Failed to set picture type decode");
5286
5287 return ret;
5288 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5289 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5290 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5291
5292 struct v4l2_control control;
5293
5294 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5295 if (priority->nU32 == 0)
5296 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
5297 else
5298 control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
5299
5300 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5301 DEBUG_PRINT_ERROR("Failed to set Priority");
5302 ret = OMX_ErrorUnsupportedSetting;
5303 }
5304 return ret;
5305 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5306 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5307 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5308
5309 struct v4l2_control control;
5310
5311 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5312 control.value = rate->nU32;
5313
5314 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5315 ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5316 OMX_ErrorUnsupportedSetting;
5317 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5318 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5319 }
5320 return ret;
5321
5322 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5323 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5324 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5325 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5326 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
5327 }
5328
5329 print_debug_color_aspects(&(params->sAspects), "Set Config");
5330 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5331 return ret;
5332 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5333 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5334
5335 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5336 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5337 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5338
5339 return set_vendor_extension_config(ext);
5340 }
5341
5342 return OMX_ErrorNotImplemented;
5343 }
5344
5345 #define extn_equals(param, extn) (!strcmp(param, extn))
5346
5347 /* ======================================================================
5348 FUNCTION
5349 omx_vdec::GetExtensionIndex
5350
5351 DESCRIPTION
5352 OMX GetExtensionIndex method implementaion. <TBD>
5353
5354 PARAMETERS
5355 <TBD>.
5356
5357 RETURN VALUE
5358 OMX Error None if everything successful.
5359
5360 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5361 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
5362 OMX_IN OMX_STRING paramName,
5363 OMX_OUT OMX_INDEXTYPE* indexType)
5364 {
5365 (void) hComp;
5366 if (m_state == OMX_StateInvalid) {
5367 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5368 return OMX_ErrorInvalidState;
5369 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5370 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5371 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5372 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5373 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5374 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5375 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5376 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5377 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5378 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5379 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5380 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5381 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5382 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5383 }
5384 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5385 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5386 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5387 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5388 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5389 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5390 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5391 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5392 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5393 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5394 } else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5395 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5396 }
5397 #endif
5398 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5399 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5400 }
5401 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5402 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5403 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5404 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5405 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5406 }
5407 #endif
5408 #ifdef FLEXYUV_SUPPORTED
5409 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5410 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5411 }
5412 #endif
5413 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5414 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5415 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5416 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5417 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5418 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5419 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5420 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5421 } else {
5422 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5423 return OMX_ErrorNotImplemented;
5424 }
5425 return OMX_ErrorNone;
5426 }
5427
5428 /* ======================================================================
5429 FUNCTION
5430 omx_vdec::GetState
5431
5432 DESCRIPTION
5433 Returns the state information back to the caller.<TBD>
5434
5435 PARAMETERS
5436 <TBD>.
5437
5438 RETURN VALUE
5439 Error None if everything is successful.
5440 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5441 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
5442 OMX_OUT OMX_STATETYPE* state)
5443 {
5444 (void) hComp;
5445 *state = m_state;
5446 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5447 return OMX_ErrorNone;
5448 }
5449
5450 /* ======================================================================
5451 FUNCTION
5452 omx_vdec::ComponentTunnelRequest
5453
5454 DESCRIPTION
5455 OMX Component Tunnel Request method implementation. <TBD>
5456
5457 PARAMETERS
5458 None.
5459
5460 RETURN VALUE
5461 OMX Error None if everything successful.
5462
5463 ========================================================================== */
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)5464 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
5465 OMX_IN OMX_U32 port,
5466 OMX_IN OMX_HANDLETYPE peerComponent,
5467 OMX_IN OMX_U32 peerPort,
5468 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5469 {
5470 (void) hComp;
5471 (void) port;
5472 (void) peerComponent;
5473 (void) peerPort;
5474 (void) tunnelSetup;
5475 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5476 return OMX_ErrorNotImplemented;
5477 }
5478
5479 /* ======================================================================
5480 FUNCTION
5481 omx_vdec::UseOutputBuffer
5482
5483 DESCRIPTION
5484 Helper function for Use buffer in the input pin
5485
5486 PARAMETERS
5487 None.
5488
5489 RETURN VALUE
5490 true/false
5491
5492 ========================================================================== */
allocate_extradata()5493 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5494 {
5495 #ifdef USE_ION
5496 if (drv_ctx.extradata_info.buffer_size) {
5497 if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) {
5498 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5499 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5500 free_ion_memory(&drv_ctx.extradata_info.ion);
5501 }
5502 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5503 drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
5504 drv_ctx.extradata_info.size, 4096,
5505 &drv_ctx.extradata_info.ion.ion_alloc_data,
5506 &drv_ctx.extradata_info.ion.fd_ion_data, 0);
5507 if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
5508 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5509 return OMX_ErrorInsufficientResources;
5510 }
5511 drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
5512 drv_ctx.extradata_info.size,
5513 PROT_READ|PROT_WRITE, MAP_SHARED,
5514 drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
5515 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5516 DEBUG_PRINT_ERROR("Failed to map extradata memory");
5517 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5518 free_ion_memory(&drv_ctx.extradata_info.ion);
5519 return OMX_ErrorInsufficientResources;
5520 }
5521 }
5522 #endif
5523 if (!m_other_extradata) {
5524 m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
5525 if (!m_other_extradata) {
5526 DEBUG_PRINT_ERROR("Failed to alloc memory\n");
5527 return OMX_ErrorInsufficientResources;
5528 }
5529 }
5530 return OMX_ErrorNone;
5531 }
5532
free_extradata()5533 void omx_vdec::free_extradata()
5534 {
5535 #ifdef USE_ION
5536 if (drv_ctx.extradata_info.uaddr) {
5537 munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size);
5538 close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
5539 free_ion_memory(&drv_ctx.extradata_info.ion);
5540 }
5541 memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
5542 #endif
5543 if (m_other_extradata) {
5544 free(m_other_extradata);
5545 m_other_extradata = NULL;
5546 }
5547 }
5548
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)5549 OMX_ERRORTYPE omx_vdec::use_output_buffer(
5550 OMX_IN OMX_HANDLETYPE hComp,
5551 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5552 OMX_IN OMX_U32 port,
5553 OMX_IN OMX_PTR appData,
5554 OMX_IN OMX_U32 bytes,
5555 OMX_IN OMX_U8* buffer)
5556 {
5557 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5558 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
5559 unsigned i= 0; // Temporary counter
5560 struct vdec_setbuffer_cmd setbuffers;
5561 OMX_PTR privateAppData = NULL;
5562 private_handle_t *handle = NULL;
5563 OMX_U8 *buff = buffer;
5564 struct v4l2_buffer buf;
5565 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5566 int extra_idx = 0;
5567 (void) hComp;
5568 (void) port;
5569
5570 if (!m_out_mem_ptr) {
5571 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
5572 eRet = allocate_output_headers();
5573 if (eRet == OMX_ErrorNone)
5574 eRet = allocate_extradata();
5575 output_use_buffer = true;
5576 }
5577
5578 if (eRet == OMX_ErrorNone) {
5579 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5580 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5581 break;
5582 }
5583 }
5584 }
5585
5586 if (i >= drv_ctx.op_buf.actualcount) {
5587 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5588 eRet = OMX_ErrorInsufficientResources;
5589 }
5590
5591 if (eRet != OMX_ErrorNone)
5592 return eRet;
5593
5594 if (dynamic_buf_mode) {
5595 *bufferHdr = (m_out_mem_ptr + i );
5596 (*bufferHdr)->pBuffer = NULL;
5597 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5598 enum v4l2_buf_type buf_type;
5599 int rr = 0;
5600 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5601 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5602 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5603 return OMX_ErrorInsufficientResources;
5604 } else {
5605 streaming[CAPTURE_PORT] = true;
5606 DEBUG_PRINT_LOW("STREAMON Successful");
5607 }
5608
5609 DEBUG_PRINT_HIGH("Enabling Turbo mode");
5610 request_perf_level(VIDC_TURBO);
5611 }
5612 BITMASK_SET(&m_out_bm_count,i);
5613 (*bufferHdr)->pAppPrivate = appData;
5614 (*bufferHdr)->pBuffer = buffer;
5615 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5616 return eRet;
5617 }
5618
5619 if (eRet == OMX_ErrorNone) {
5620 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5621 if (m_enable_android_native_buffers) {
5622 if (m_use_android_native_buffers) {
5623 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5624 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5625 handle = (private_handle_t *)nBuf->handle;
5626 privateAppData = params->pAppPrivate;
5627 } else {
5628 handle = (private_handle_t *)buff;
5629 privateAppData = appData;
5630 }
5631 if (!handle) {
5632 DEBUG_PRINT_ERROR("handle is invalid");
5633 return OMX_ErrorBadParameter;
5634 }
5635
5636 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5637 if (secure_mode && secure_scaling_to_non_secure_opb) {
5638 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5639 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5640 } else {
5641 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5642 " expected %u, got %u",
5643 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5644 return OMX_ErrorBadParameter;
5645 }
5646 }
5647
5648 drv_ctx.op_buf.buffer_size = handle->size;
5649
5650 if (!m_use_android_native_buffers) {
5651 if (!secure_mode) {
5652 buff = (OMX_U8*)mmap(0, handle->size,
5653 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
5654 if (buff == MAP_FAILED) {
5655 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5656 return OMX_ErrorInsufficientResources;
5657 }
5658 }
5659 }
5660 #if defined(_ANDROID_ICS_)
5661 native_buffer[i].nativehandle = handle;
5662 native_buffer[i].privatehandle = handle;
5663 #endif
5664 if (!handle) {
5665 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5666 return OMX_ErrorBadParameter;
5667 }
5668 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5669 drv_ctx.ptr_outputbuffer[i].offset = 0;
5670 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5671 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5672 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5673 } else
5674 #endif
5675
5676 if (!ouput_egl_buffers && !m_use_output_pmem) {
5677 #ifdef USE_ION
5678 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
5679 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
5680 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
5681 &drv_ctx.op_buf_ion_info[i].fd_ion_data,
5682 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5683 if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
5684 DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
5685 return OMX_ErrorInsufficientResources;
5686 }
5687 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5688 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
5689 #else
5690 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5691 open (MEM_DEVICE,O_RDWR);
5692
5693 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5694 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5695 return OMX_ErrorInsufficientResources;
5696 }
5697
5698 /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
5699 if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
5700 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5701 open (MEM_DEVICE,O_RDWR);
5702 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
5703 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
5704 return OMX_ErrorInsufficientResources;
5705 }
5706 }
5707
5708 if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5709 drv_ctx.op_buf.buffer_size,
5710 drv_ctx.op_buf.alignment)) {
5711 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
5712 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5713 return OMX_ErrorInsufficientResources;
5714 }
5715 #endif
5716 if (!secure_mode) {
5717 drv_ctx.ptr_outputbuffer[i].bufferaddr =
5718 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
5719 PROT_READ|PROT_WRITE, MAP_SHARED,
5720 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
5721 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5722 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
5723 #ifdef USE_ION
5724 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5725 #endif
5726 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5727 return OMX_ErrorInsufficientResources;
5728 }
5729 }
5730 drv_ctx.ptr_outputbuffer[i].offset = 0;
5731 privateAppData = appData;
5732 } else {
5733
5734 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5735 if (!appData || !bytes ) {
5736 if (!secure_mode && !buffer) {
5737 DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
5738 return OMX_ErrorBadParameter;
5739 }
5740 }
5741
5742 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
5743 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
5744 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
5745 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
5746 !pmem_list->nEntries ||
5747 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
5748 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
5749 return OMX_ErrorBadParameter;
5750 }
5751 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
5752 pmem_list->entryList->entry;
5753 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
5754 pmem_info->pmem_fd);
5755 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
5756 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
5757 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5758 drv_ctx.ptr_outputbuffer[i].mmaped_size =
5759 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5760 privateAppData = appData;
5761 }
5762 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
5763 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5764 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
5765 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
5766 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
5767
5768 *bufferHdr = (m_out_mem_ptr + i );
5769 if (secure_mode)
5770 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
5771 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
5772 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
5773 sizeof (vdec_bufferpayload));
5774
5775 DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
5776 drv_ctx.ptr_outputbuffer[i].bufferaddr,
5777 drv_ctx.ptr_outputbuffer[i].pmem_fd );
5778
5779 buf.index = i;
5780 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5781 buf.memory = V4L2_MEMORY_USERPTR;
5782 plane[0].length = drv_ctx.op_buf.buffer_size;
5783 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
5784 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
5785 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
5786 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
5787 plane[0].data_offset = 0;
5788 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
5789 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
5790 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
5791 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
5792 #ifdef USE_ION
5793 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
5794 #endif
5795 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
5796 plane[extra_idx].data_offset = 0;
5797 } else if (extra_idx >= VIDEO_MAX_PLANES) {
5798 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
5799 return OMX_ErrorBadParameter;
5800 }
5801 buf.m.planes = plane;
5802 buf.length = drv_ctx.num_planes;
5803
5804 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
5805 DEBUG_PRINT_ERROR("Failed to prepare bufs");
5806 /*TODO: How to handle this case */
5807 return OMX_ErrorInsufficientResources;
5808 }
5809
5810 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
5811 enum v4l2_buf_type buf_type;
5812 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5813 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
5814 return OMX_ErrorInsufficientResources;
5815 } else {
5816 streaming[CAPTURE_PORT] = true;
5817 DEBUG_PRINT_LOW("STREAMON Successful");
5818 }
5819
5820 DEBUG_PRINT_HIGH("Enabling Turbo mode");
5821 request_perf_level(VIDC_TURBO);
5822 }
5823
5824 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
5825 if (m_enable_android_native_buffers) {
5826 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
5827 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
5828 } else {
5829 (*bufferHdr)->pBuffer = buff;
5830 }
5831 (*bufferHdr)->pAppPrivate = privateAppData;
5832 BITMASK_SET(&m_out_bm_count,i);
5833 }
5834 return eRet;
5835 }
5836
5837 /* ======================================================================
5838 FUNCTION
5839 omx_vdec::use_input_heap_buffers
5840
5841 DESCRIPTION
5842 OMX Use Buffer Heap allocation method implementation.
5843
5844 PARAMETERS
5845 <TBD>.
5846
5847 RETURN VALUE
5848 OMX Error None , if everything successful.
5849
5850 ========================================================================== */
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)5851 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
5852 OMX_IN OMX_HANDLETYPE hComp,
5853 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5854 OMX_IN OMX_U32 port,
5855 OMX_IN OMX_PTR appData,
5856 OMX_IN OMX_U32 bytes,
5857 OMX_IN OMX_U8* buffer)
5858 {
5859 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
5860 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5861
5862 if (secure_mode) {
5863 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
5864 return OMX_ErrorUndefined;
5865 }
5866
5867 if (!m_inp_heap_ptr)
5868 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
5869 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
5870 drv_ctx.ip_buf.actualcount);
5871 if (!m_phdr_pmem_ptr)
5872 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
5873 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
5874 drv_ctx.ip_buf.actualcount);
5875 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
5876 DEBUG_PRINT_ERROR("Insufficent memory");
5877 eRet = OMX_ErrorInsufficientResources;
5878 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
5879 input_use_buffer = true;
5880 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
5881 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
5882 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
5883 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
5884 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
5885 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
5886 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
5887 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
5888 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
5889 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
5890 (unsigned)NULL, (unsigned)NULL)) {
5891 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
5892 return OMX_ErrorInsufficientResources;
5893 }
5894 m_in_alloc_cnt++;
5895 } else {
5896 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
5897 eRet = OMX_ErrorInsufficientResources;
5898 }
5899 return eRet;
5900 }
5901
5902 /* ======================================================================
5903 FUNCTION
5904 omx_vdec::UseBuffer
5905
5906 DESCRIPTION
5907 OMX Use Buffer method implementation.
5908
5909 PARAMETERS
5910 <TBD>.
5911
5912 RETURN VALUE
5913 OMX Error None , if everything successful.
5914
5915 ========================================================================== */
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)5916 OMX_ERRORTYPE omx_vdec::use_buffer(
5917 OMX_IN OMX_HANDLETYPE hComp,
5918 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5919 OMX_IN OMX_U32 port,
5920 OMX_IN OMX_PTR appData,
5921 OMX_IN OMX_U32 bytes,
5922 OMX_IN OMX_U8* buffer)
5923 {
5924 OMX_ERRORTYPE error = OMX_ErrorNone;
5925 struct vdec_setbuffer_cmd setbuffers;
5926
5927 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
5928 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
5929 return OMX_ErrorBadParameter;
5930 }
5931 if (m_state == OMX_StateInvalid) {
5932 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
5933 return OMX_ErrorInvalidState;
5934 }
5935 if (port == OMX_CORE_INPUT_PORT_INDEX) {
5936 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
5937 // ensure that use-buffer was called for previous allocation.
5938 // Mix-and-match of useBuffer and allocateBuffer is not allowed
5939 if (m_inp_mem_ptr && !input_use_buffer) {
5940 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
5941 return OMX_ErrorUndefined;
5942 }
5943 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
5944 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
5945 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
5946 else {
5947 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
5948 error = OMX_ErrorBadPortIndex;
5949 }
5950 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
5951 if (error == OMX_ErrorNone) {
5952 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
5953 // Send the callback now
5954 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5955 post_event(OMX_CommandStateSet,OMX_StateIdle,
5956 OMX_COMPONENT_GENERATE_EVENT);
5957 }
5958 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
5959 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
5960 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5961 post_event(OMX_CommandPortEnable,
5962 OMX_CORE_INPUT_PORT_INDEX,
5963 OMX_COMPONENT_GENERATE_EVENT);
5964 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
5965 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
5966 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5967 post_event(OMX_CommandPortEnable,
5968 OMX_CORE_OUTPUT_PORT_INDEX,
5969 OMX_COMPONENT_GENERATE_EVENT);
5970 }
5971 }
5972 return error;
5973 }
5974
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)5975 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
5976 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
5977 {
5978 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
5979 if (m_inp_heap_ptr[bufferindex].pBuffer)
5980 free(m_inp_heap_ptr[bufferindex].pBuffer);
5981 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
5982 }
5983 if (pmem_bufferHdr)
5984 free_input_buffer(pmem_bufferHdr);
5985 return OMX_ErrorNone;
5986 }
5987
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)5988 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
5989 {
5990 unsigned int index = 0;
5991 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
5992 return OMX_ErrorBadParameter;
5993 }
5994
5995 index = bufferHdr - m_inp_mem_ptr;
5996 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
5997
5998 bufferHdr->pInputPortPrivate = NULL;
5999
6000 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6001 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6002 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6003 struct vdec_setbuffer_cmd setbuffers;
6004 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
6005 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
6006 sizeof (vdec_bufferpayload));
6007 if (!secure_mode) {
6008 DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
6009 drv_ctx.ptr_inputbuffer[index].pmem_fd);
6010 DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p",
6011 (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
6012 drv_ctx.ptr_inputbuffer[index].bufferaddr);
6013 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
6014 drv_ctx.ptr_inputbuffer[index].mmaped_size);
6015 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
6016 } else if (allocate_native_handle){
6017 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6018 native_handle_close(nh);
6019 native_handle_delete(nh);
6020 }
6021 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6022 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6023 free(m_desc_buffer_ptr[index].buf_addr);
6024 m_desc_buffer_ptr[index].buf_addr = NULL;
6025 m_desc_buffer_ptr[index].desc_data_size = 0;
6026 }
6027 #ifdef USE_ION
6028 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6029 #endif
6030 }
6031 }
6032
6033 return OMX_ErrorNone;
6034 }
6035
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6036 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6037 {
6038 unsigned int index = 0;
6039
6040 if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
6041 return OMX_ErrorBadParameter;
6042 }
6043
6044 index = bufferHdr - m_out_mem_ptr;
6045 DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
6046
6047 if (index < drv_ctx.op_buf.actualcount
6048 && drv_ctx.ptr_outputbuffer) {
6049 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6050 drv_ctx.ptr_outputbuffer[index].bufferaddr);
6051
6052 struct vdec_setbuffer_cmd setbuffers;
6053 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
6054 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
6055 sizeof (vdec_bufferpayload));
6056
6057 if (!dynamic_buf_mode) {
6058 if (streaming[CAPTURE_PORT] &&
6059 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6060 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6061 DEBUG_PRINT_ERROR("STREAMOFF Failed");
6062 } else {
6063 DEBUG_PRINT_LOW("STREAMOFF Successful");
6064 }
6065 }
6066 #ifdef _ANDROID_
6067 if (m_enable_android_native_buffers) {
6068 if (!secure_mode) {
6069 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
6070 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
6071 drv_ctx.ptr_outputbuffer[index].mmaped_size);
6072 }
6073 }
6074 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
6075 } else {
6076 #endif
6077 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
6078 if (!secure_mode) {
6079 DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
6080 drv_ctx.ptr_outputbuffer[0].pmem_fd);
6081 DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p",
6082 (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
6083 drv_ctx.ptr_outputbuffer[0].bufferaddr);
6084 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
6085 drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
6086 }
6087 close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
6088 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
6089 #ifdef USE_ION
6090 free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
6091 #endif
6092 }
6093 #ifdef _ANDROID_
6094 }
6095 #endif
6096 } //!dynamic_buf_mode
6097 if (release_output_done()) {
6098 free_extradata();
6099 }
6100 }
6101
6102 return OMX_ErrorNone;
6103
6104 }
6105
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6106 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
6107 OMX_BUFFERHEADERTYPE **bufferHdr,
6108 OMX_U32 port,
6109 OMX_PTR appData,
6110 OMX_U32 bytes)
6111 {
6112 OMX_BUFFERHEADERTYPE *input = NULL;
6113 unsigned char *buf_addr = NULL;
6114 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6115 unsigned i = 0;
6116
6117 /* Sanity Check*/
6118 if (bufferHdr == NULL) {
6119 return OMX_ErrorBadParameter;
6120 }
6121
6122 if (m_inp_heap_ptr == NULL) {
6123 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6124 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6125 drv_ctx.ip_buf.actualcount);
6126 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6127 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6128 drv_ctx.ip_buf.actualcount);
6129
6130 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6131 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6132 return OMX_ErrorInsufficientResources;
6133 }
6134 }
6135
6136 /*Find a Free index*/
6137 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6138 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6139 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6140 break;
6141 }
6142 }
6143
6144 if (i < drv_ctx.ip_buf.actualcount) {
6145 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6146
6147 if (buf_addr == NULL) {
6148 return OMX_ErrorInsufficientResources;
6149 }
6150
6151 *bufferHdr = (m_inp_heap_ptr + i);
6152 input = *bufferHdr;
6153 BITMASK_SET(&m_heap_inp_bm_count,i);
6154
6155 input->pBuffer = (OMX_U8 *)buf_addr;
6156 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6157 input->nVersion.nVersion = OMX_SPEC_VERSION;
6158 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6159 input->pAppPrivate = appData;
6160 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6161 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6162 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6163 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6164 /*Add the Buffers to freeq*/
6165 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6166 (unsigned)NULL, (unsigned)NULL)) {
6167 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6168 return OMX_ErrorInsufficientResources;
6169 }
6170 } else {
6171 return OMX_ErrorBadParameter;
6172 }
6173
6174 return eRet;
6175
6176 }
6177
6178
6179 /* ======================================================================
6180 FUNCTION
6181 omx_vdec::AllocateInputBuffer
6182
6183 DESCRIPTION
6184 Helper function for allocate buffer in the input pin
6185
6186 PARAMETERS
6187 None.
6188
6189 RETURN VALUE
6190 true/false
6191
6192 ========================================================================== */
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)6193 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
6194 OMX_IN OMX_HANDLETYPE hComp,
6195 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6196 OMX_IN OMX_U32 port,
6197 OMX_IN OMX_PTR appData,
6198 OMX_IN OMX_U32 bytes)
6199 {
6200 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6201 struct vdec_setbuffer_cmd setbuffers;
6202 OMX_BUFFERHEADERTYPE *input = NULL;
6203 unsigned i = 0;
6204 unsigned char *buf_addr = NULL;
6205 int pmem_fd = -1, ret = 0;
6206 unsigned int align_size = 0;
6207
6208 (void) hComp;
6209 (void) port;
6210
6211
6212 if (bytes != drv_ctx.ip_buf.buffer_size) {
6213 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6214 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6215 return OMX_ErrorBadParameter;
6216 }
6217
6218 if (!m_inp_mem_ptr) {
6219 struct v4l2_requestbuffers bufreq;
6220 bufreq.memory = V4L2_MEMORY_USERPTR;
6221 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6222 bufreq.count = drv_ctx.ip_buf.actualcount;
6223 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6224 if (ret) {
6225 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %s", strerror(errno));
6226 /*TODO: How to handle this case */
6227 eRet = OMX_ErrorInsufficientResources;
6228 } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6229 DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6230 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6231 eRet = OMX_ErrorInsufficientResources;
6232 }
6233
6234 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6235 drv_ctx.ip_buf.actualcount,
6236 (unsigned int)drv_ctx.ip_buf.buffer_size);
6237
6238 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6239 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6240
6241 if (m_inp_mem_ptr == NULL) {
6242 return OMX_ErrorInsufficientResources;
6243 }
6244
6245 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6246 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6247
6248 if (drv_ctx.ptr_inputbuffer == NULL) {
6249 return OMX_ErrorInsufficientResources;
6250 }
6251 #ifdef USE_ION
6252 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6253 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6254
6255 if (drv_ctx.ip_buf_ion_info == NULL) {
6256 return OMX_ErrorInsufficientResources;
6257 }
6258 #endif
6259
6260 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6261 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6262 #ifdef USE_ION
6263 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
6264 #endif
6265 }
6266 }
6267
6268 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6269 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6270 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6271 break;
6272 }
6273 }
6274
6275 if (i < drv_ctx.ip_buf.actualcount) {
6276 struct v4l2_buffer buf;
6277 struct v4l2_plane plane;
6278 int rc;
6279 DEBUG_PRINT_LOW("Allocate input Buffer");
6280 #ifdef USE_ION
6281 align_size = drv_ctx.ip_buf.buffer_size + 512;
6282 align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6283 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
6284 align_size, drv_ctx.op_buf.alignment,
6285 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
6286 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
6287 SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6288 if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
6289 return OMX_ErrorInsufficientResources;
6290 }
6291 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
6292 #else
6293 pmem_fd = open (MEM_DEVICE,O_RDWR);
6294
6295 if (pmem_fd < 0) {
6296 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6297 return OMX_ErrorInsufficientResources;
6298 }
6299
6300 if (pmem_fd == 0) {
6301 pmem_fd = open (MEM_DEVICE,O_RDWR);
6302
6303 if (pmem_fd < 0) {
6304 DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
6305 return OMX_ErrorInsufficientResources;
6306 }
6307 }
6308
6309 if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
6310 drv_ctx.ip_buf.alignment)) {
6311 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6312 close(pmem_fd);
6313 return OMX_ErrorInsufficientResources;
6314 }
6315 #endif
6316 if (!secure_mode) {
6317 buf_addr = (unsigned char *)mmap(NULL,
6318 drv_ctx.ip_buf.buffer_size,
6319 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
6320
6321 if (buf_addr == MAP_FAILED) {
6322 close(pmem_fd);
6323 #ifdef USE_ION
6324 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6325 #endif
6326 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6327 return OMX_ErrorInsufficientResources;
6328 }
6329 }
6330 *bufferHdr = (m_inp_mem_ptr + i);
6331 if (secure_mode)
6332 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6333 else
6334 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6335 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6336 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6337 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6338 drv_ctx.ptr_inputbuffer [i].offset = 0;
6339
6340
6341 buf.index = i;
6342 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6343 buf.memory = V4L2_MEMORY_USERPTR;
6344 plane.bytesused = 0;
6345 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
6346 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
6347 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
6348 plane.reserved[1] = 0;
6349 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
6350 buf.m.planes = &plane;
6351 buf.length = 1;
6352
6353 DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
6354 drv_ctx.ptr_inputbuffer[i].bufferaddr);
6355
6356 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6357
6358 if (rc) {
6359 DEBUG_PRINT_ERROR("Failed to prepare bufs");
6360 /*TODO: How to handle this case */
6361 return OMX_ErrorInsufficientResources;
6362 }
6363
6364 input = *bufferHdr;
6365 BITMASK_SET(&m_inp_bm_count,i);
6366 DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
6367 if (allocate_native_handle) {
6368 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6369 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6370 input->pBuffer = (OMX_U8 *)nh;
6371 } else if (secure_mode || m_input_pass_buffer_fd) {
6372 /*Legacy method, pass ion fd stashed directly in pBuffer*/
6373 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6374 } else {
6375 input->pBuffer = (OMX_U8 *)buf_addr;
6376 }
6377 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6378 input->nVersion.nVersion = OMX_SPEC_VERSION;
6379 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6380 input->pAppPrivate = appData;
6381 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6382 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6383
6384 if (drv_ctx.disable_dmx) {
6385 eRet = allocate_desc_buffer(i);
6386 }
6387 } else {
6388 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6389 eRet = OMX_ErrorInsufficientResources;
6390 }
6391 return eRet;
6392 }
6393
6394
6395 /* ======================================================================
6396 FUNCTION
6397 omx_vdec::AllocateOutputBuffer
6398
6399 DESCRIPTION
6400 Helper fn for AllocateBuffer in the output pin
6401
6402 PARAMETERS
6403 <TBD>.
6404
6405 RETURN VALUE
6406 OMX Error None if everything went well.
6407
6408 ========================================================================== */
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)6409 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
6410 OMX_IN OMX_HANDLETYPE hComp,
6411 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6412 OMX_IN OMX_U32 port,
6413 OMX_IN OMX_PTR appData,
6414 OMX_IN OMX_U32 bytes)
6415 {
6416 (void)hComp;
6417 (void)port;
6418 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6419 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
6420 unsigned i= 0; // Temporary counter
6421 struct vdec_setbuffer_cmd setbuffers;
6422 int extra_idx = 0;
6423 #ifdef USE_ION
6424 int ion_device_fd =-1;
6425 struct ion_allocation_data ion_alloc_data;
6426 struct ion_fd_data fd_ion_data;
6427 #endif
6428 if (!m_out_mem_ptr) {
6429 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6430 drv_ctx.op_buf.actualcount,
6431 (unsigned int)drv_ctx.op_buf.buffer_size);
6432 int nBufHdrSize = 0;
6433 int nPlatformEntrySize = 0;
6434 int nPlatformListSize = 0;
6435 int nPMEMInfoSize = 0;
6436 int pmem_fd = -1;
6437 unsigned char *pmem_baseaddress = NULL;
6438
6439 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
6440 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
6441 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6442
6443 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
6444 drv_ctx.op_buf.actualcount);
6445 nBufHdrSize = drv_ctx.op_buf.actualcount *
6446 sizeof(OMX_BUFFERHEADERTYPE);
6447
6448 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
6449 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6450 nPlatformListSize = drv_ctx.op_buf.actualcount *
6451 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6452 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6453 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6454
6455 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
6456 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
6457 nPMEMInfoSize,
6458 nPlatformListSize);
6459 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
6460 drv_ctx.op_buf.actualcount);
6461 #ifdef USE_ION
6462 // Allocate output buffers as cached to improve performance of software-reading
6463 // of the YUVs. Output buffers are cache-invalidated in driver.
6464 // If color-conversion is involved, Only the C2D output buffers are cached, no
6465 // need to cache the decoder's output buffers
6466 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6467 ion_device_fd = alloc_map_ion_memory(
6468 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
6469 secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
6470 &ion_alloc_data, &fd_ion_data,
6471 (secure_mode && !secure_scaling_to_non_secure_opb) ?
6472 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6473 if (ion_device_fd < 0) {
6474 return OMX_ErrorInsufficientResources;
6475 }
6476 pmem_fd = fd_ion_data.fd;
6477 #else
6478 pmem_fd = open (MEM_DEVICE,O_RDWR);
6479
6480 if (pmem_fd < 0) {
6481 DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
6482 drv_ctx.op_buf.buffer_size);
6483 return OMX_ErrorInsufficientResources;
6484 }
6485
6486 if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
6487 drv_ctx.op_buf.actualcount,
6488 drv_ctx.op_buf.alignment)) {
6489 DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
6490 close(pmem_fd);
6491 return OMX_ErrorInsufficientResources;
6492 }
6493 #endif
6494 if (!secure_mode) {
6495 pmem_baseaddress = (unsigned char *)mmap(NULL,
6496 (drv_ctx.op_buf.buffer_size *
6497 drv_ctx.op_buf.actualcount),
6498 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
6499 if (pmem_baseaddress == MAP_FAILED) {
6500 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6501 (unsigned int)drv_ctx.op_buf.buffer_size);
6502 close(pmem_fd);
6503 #ifdef USE_ION
6504 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6505 #endif
6506 return OMX_ErrorInsufficientResources;
6507 }
6508 }
6509 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
6510 // Alloc mem for platform specific info
6511 char *pPtr=NULL;
6512 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6513 nPMEMInfoSize,1);
6514 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
6515 calloc (sizeof(struct vdec_bufferpayload),
6516 drv_ctx.op_buf.actualcount);
6517 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
6518 calloc (sizeof (struct vdec_output_frameinfo),
6519 drv_ctx.op_buf.actualcount);
6520 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
6521 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
6522 return OMX_ErrorInsufficientResources;
6523 }
6524
6525 #ifdef USE_ION
6526 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
6527 calloc (sizeof(struct vdec_ion),
6528 drv_ctx.op_buf.actualcount);
6529 if (!drv_ctx.op_buf_ion_info) {
6530 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
6531 return OMX_ErrorInsufficientResources;
6532 }
6533 #endif
6534
6535 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
6536 && drv_ctx.ptr_respbuffer) {
6537 drv_ctx.ptr_outputbuffer[0].mmaped_size =
6538 (drv_ctx.op_buf.buffer_size *
6539 drv_ctx.op_buf.actualcount);
6540 bufHdr = m_out_mem_ptr;
6541 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6542 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6543 (((char *) m_platform_list) + nPlatformListSize);
6544 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6545 (((char *) m_platform_entry) + nPlatformEntrySize);
6546 pPlatformList = m_platform_list;
6547 pPlatformEntry = m_platform_entry;
6548 pPMEMInfo = m_pmem_info;
6549
6550 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
6551
6552 // Settting the entire storage nicely
6553 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
6554 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
6555 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6556 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6557 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
6558 // Set the values when we determine the right HxW param
6559 bufHdr->nAllocLen = bytes;
6560 bufHdr->nFilledLen = 0;
6561 bufHdr->pAppPrivate = appData;
6562 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
6563 // Platform specific PMEM Information
6564 // Initialize the Platform Entry
6565 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6566 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6567 pPlatformEntry->entry = pPMEMInfo;
6568 // Initialize the Platform List
6569 pPlatformList->nEntries = 1;
6570 pPlatformList->entryList = pPlatformEntry;
6571 // Keep pBuffer NULL till vdec is opened
6572 bufHdr->pBuffer = NULL;
6573 bufHdr->nOffset = 0;
6574
6575 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
6576 pPMEMInfo->pmem_fd = -1;
6577 bufHdr->pPlatformPrivate = pPlatformList;
6578
6579 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
6580 m_pmem_info[i].pmem_fd = pmem_fd;
6581 #ifdef USE_ION
6582 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
6583 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
6584 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
6585 #endif
6586
6587 /*Create a mapping between buffers*/
6588 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
6589 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
6590 &drv_ctx.ptr_outputbuffer[i];
6591 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
6592 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6593 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
6594 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6595 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6596 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6597
6598 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
6599 pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
6600 drv_ctx.ptr_outputbuffer[i].bufferaddr);
6601 // Move the buffer and buffer header pointers
6602 bufHdr++;
6603 pPMEMInfo++;
6604 pPlatformEntry++;
6605 pPlatformList++;
6606 }
6607 } else {
6608 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6609 m_out_mem_ptr, pPtr);
6610 if (m_out_mem_ptr) {
6611 free(m_out_mem_ptr);
6612 m_out_mem_ptr = NULL;
6613 }
6614 if (pPtr) {
6615 free(pPtr);
6616 pPtr = NULL;
6617 }
6618 if (drv_ctx.ptr_outputbuffer) {
6619 free(drv_ctx.ptr_outputbuffer);
6620 drv_ctx.ptr_outputbuffer = NULL;
6621 }
6622 if (drv_ctx.ptr_respbuffer) {
6623 free(drv_ctx.ptr_respbuffer);
6624 drv_ctx.ptr_respbuffer = NULL;
6625 }
6626 #ifdef USE_ION
6627 if (drv_ctx.op_buf_ion_info) {
6628 DEBUG_PRINT_LOW("Free o/p ion context");
6629 free(drv_ctx.op_buf_ion_info);
6630 drv_ctx.op_buf_ion_info = NULL;
6631 }
6632 #endif
6633 eRet = OMX_ErrorInsufficientResources;
6634 }
6635 if (eRet == OMX_ErrorNone)
6636 eRet = allocate_extradata();
6637 }
6638
6639 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6640 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6641 DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
6642 break;
6643 }
6644 }
6645
6646 if (eRet == OMX_ErrorNone) {
6647 if (i < drv_ctx.op_buf.actualcount) {
6648 struct v4l2_buffer buf;
6649 struct v4l2_plane plane[VIDEO_MAX_PLANES];
6650 int rc;
6651 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6652
6653 drv_ctx.ptr_outputbuffer[i].buffer_len =
6654 drv_ctx.op_buf.buffer_size;
6655
6656 *bufferHdr = (m_out_mem_ptr + i );
6657 if (secure_mode) {
6658 #ifdef USE_ION
6659 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6660 (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6661 #else
6662 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6663 #endif
6664 }
6665 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6666
6667 buf.index = i;
6668 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6669 buf.memory = V4L2_MEMORY_USERPTR;
6670 plane[0].length = drv_ctx.op_buf.buffer_size;
6671 plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
6672 (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
6673 #ifdef USE_ION
6674 plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
6675 #endif
6676 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
6677 plane[0].data_offset = 0;
6678 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
6679 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
6680 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
6681 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
6682 #ifdef USE_ION
6683 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
6684 #endif
6685 plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
6686 plane[extra_idx].data_offset = 0;
6687 } else if (extra_idx >= VIDEO_MAX_PLANES) {
6688 DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
6689 return OMX_ErrorBadParameter;
6690 }
6691 buf.m.planes = plane;
6692 buf.length = drv_ctx.num_planes;
6693 DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
6694 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
6695 if (rc) {
6696 /*TODO: How to handle this case */
6697 return OMX_ErrorInsufficientResources;
6698 }
6699
6700 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6701 enum v4l2_buf_type buf_type;
6702 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6703 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6704 if (rc) {
6705 return OMX_ErrorInsufficientResources;
6706 } else {
6707 streaming[CAPTURE_PORT] = true;
6708 DEBUG_PRINT_LOW("STREAMON Successful");
6709 }
6710
6711 DEBUG_PRINT_HIGH("Enabling Turbo mode");
6712 request_perf_level(VIDC_TURBO);
6713 }
6714
6715 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
6716 (*bufferHdr)->pAppPrivate = appData;
6717 BITMASK_SET(&m_out_bm_count,i);
6718 } else {
6719 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
6720 eRet = OMX_ErrorInsufficientResources;
6721 }
6722 }
6723
6724 return eRet;
6725 }
6726
6727
6728 // AllocateBuffer -- API Call
6729 /* ======================================================================
6730 FUNCTION
6731 omx_vdec::AllocateBuffer
6732
6733 DESCRIPTION
6734 Returns zero if all the buffers released..
6735
6736 PARAMETERS
6737 None.
6738
6739 RETURN VALUE
6740 true/false
6741
6742 ========================================================================== */
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)6743 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
6744 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6745 OMX_IN OMX_U32 port,
6746 OMX_IN OMX_PTR appData,
6747 OMX_IN OMX_U32 bytes)
6748 {
6749 unsigned i = 0;
6750 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
6751
6752 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
6753 if (m_state == OMX_StateInvalid) {
6754 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
6755 return OMX_ErrorInvalidState;
6756 }
6757
6758 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6759 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6760 // ensure that use-buffer was never called.
6761 // Mix-and-match of useBuffer and allocateBuffer is not allowed
6762 if (m_inp_mem_ptr && input_use_buffer) {
6763 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
6764 return OMX_ErrorUndefined;
6765 }
6766 if (arbitrary_bytes) {
6767 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
6768 } else {
6769 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
6770 }
6771 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6772 if (output_use_buffer) {
6773 DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
6774 return OMX_ErrorBadParameter;
6775 }
6776 eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
6777 appData,bytes);
6778 } else {
6779 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6780 eRet = OMX_ErrorBadPortIndex;
6781 }
6782 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
6783 if (eRet == OMX_ErrorNone) {
6784 if (allocate_done()) {
6785 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6786 // Send the callback now
6787 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6788 post_event(OMX_CommandStateSet,OMX_StateIdle,
6789 OMX_COMPONENT_GENERATE_EVENT);
6790 }
6791 }
6792 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
6793 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6794 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6795 post_event(OMX_CommandPortEnable,
6796 OMX_CORE_INPUT_PORT_INDEX,
6797 OMX_COMPONENT_GENERATE_EVENT);
6798 }
6799 }
6800 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
6801 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6802 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6803 post_event(OMX_CommandPortEnable,
6804 OMX_CORE_OUTPUT_PORT_INDEX,
6805 OMX_COMPONENT_GENERATE_EVENT);
6806 }
6807 }
6808 }
6809 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
6810 return eRet;
6811 }
6812
6813 // Free Buffer - API call
6814 /* ======================================================================
6815 FUNCTION
6816 omx_vdec::FreeBuffer
6817
6818 DESCRIPTION
6819
6820 PARAMETERS
6821 None.
6822
6823 RETURN VALUE
6824 true/false
6825
6826 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6827 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
6828 OMX_IN OMX_U32 port,
6829 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6830 {
6831 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6832 unsigned int nPortIndex;
6833 (void) hComp;
6834 DEBUG_PRINT_LOW("In for decoder free_buffer");
6835
6836 auto_lock l(buf_lock);
6837 if (m_state == OMX_StateIdle &&
6838 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6839 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
6840 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
6841 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
6842 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
6843 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
6844 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
6845 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
6846 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
6847 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
6848 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
6849 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
6850 post_event(OMX_EventError,
6851 OMX_ErrorPortUnpopulated,
6852 OMX_COMPONENT_GENERATE_EVENT);
6853 m_buffer_error = true;
6854 return OMX_ErrorIncorrectStateOperation;
6855 } else if (m_state != OMX_StateInvalid) {
6856 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
6857 post_event(OMX_EventError,
6858 OMX_ErrorPortUnpopulated,
6859 OMX_COMPONENT_GENERATE_EVENT);
6860 }
6861
6862 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6863 /*Check if arbitrary bytes*/
6864 if (!arbitrary_bytes && !input_use_buffer)
6865 nPortIndex = buffer - m_inp_mem_ptr;
6866 else
6867 nPortIndex = buffer - m_inp_heap_ptr;
6868
6869 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
6870 if (nPortIndex < drv_ctx.ip_buf.actualcount &&
6871 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
6872 // Clear the bit associated with it.
6873 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
6874 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
6875 if (input_use_buffer == true) {
6876
6877 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
6878 if (m_phdr_pmem_ptr)
6879 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
6880 } else {
6881 if (arbitrary_bytes) {
6882 if (m_phdr_pmem_ptr)
6883 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
6884 else
6885 free_input_buffer(nPortIndex,NULL);
6886 } else
6887 free_input_buffer(buffer);
6888 }
6889 m_inp_bPopulated = OMX_FALSE;
6890 if(release_input_done())
6891 release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
6892 /*Free the Buffer Header*/
6893 if (release_input_done()) {
6894 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
6895 free_input_buffer_header();
6896 }
6897 } else {
6898 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
6899 eRet = OMX_ErrorBadPortIndex;
6900 }
6901
6902 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
6903 && release_input_done()) {
6904 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6905 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
6906 post_event(OMX_CommandPortDisable,
6907 OMX_CORE_INPUT_PORT_INDEX,
6908 OMX_COMPONENT_GENERATE_EVENT);
6909 }
6910 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6911 // check if the buffer is valid
6912 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
6913 if (nPortIndex < drv_ctx.op_buf.actualcount &&
6914 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
6915 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
6916 // Clear the bit associated with it.
6917 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
6918 m_out_bPopulated = OMX_FALSE;
6919 client_buffers.free_output_buffer (buffer);
6920
6921 if(release_output_done()) {
6922 release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
6923 }
6924 if (release_output_done()) {
6925 free_output_buffer_header();
6926 }
6927 } else {
6928 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
6929 eRet = OMX_ErrorBadPortIndex;
6930 }
6931 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
6932 && release_output_done()) {
6933 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
6934
6935 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
6936 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
6937 #ifdef _ANDROID_ICS_
6938 if (m_enable_android_native_buffers) {
6939 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
6940 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
6941 }
6942 #endif
6943
6944 post_event(OMX_CommandPortDisable,
6945 OMX_CORE_OUTPUT_PORT_INDEX,
6946 OMX_COMPONENT_GENERATE_EVENT);
6947 }
6948 } else {
6949 eRet = OMX_ErrorBadPortIndex;
6950 }
6951 if ((eRet == OMX_ErrorNone) &&
6952 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
6953 if (release_done()) {
6954 // Send the callback now
6955 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
6956 post_event(OMX_CommandStateSet, OMX_StateLoaded,
6957 OMX_COMPONENT_GENERATE_EVENT);
6958 m_buffer_error = false;
6959 }
6960 }
6961 return eRet;
6962 }
6963
6964
6965 /* ======================================================================
6966 FUNCTION
6967 omx_vdec::EmptyThisBuffer
6968
6969 DESCRIPTION
6970 This routine is used to push the encoded video frames to
6971 the video decoder.
6972
6973 PARAMETERS
6974 None.
6975
6976 RETURN VALUE
6977 OMX Error None if everything went successful.
6978
6979 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)6980 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
6981 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
6982 {
6983 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
6984 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
6985
6986 if (m_state != OMX_StateExecuting &&
6987 m_state != OMX_StatePause &&
6988 m_state != OMX_StateIdle) {
6989 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
6990 return OMX_ErrorInvalidState;
6991 }
6992
6993 if (buffer == NULL) {
6994 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
6995 return OMX_ErrorBadParameter;
6996 }
6997
6998 if (!m_inp_bEnabled) {
6999 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7000 return OMX_ErrorIncorrectStateOperation;
7001 }
7002
7003 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7004 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7005 return OMX_ErrorBadPortIndex;
7006 }
7007
7008 if (perf_flag) {
7009 if (!latency) {
7010 dec_time.stop();
7011 latency = dec_time.processing_time_us();
7012 dec_time.start();
7013 }
7014 }
7015
7016 if (arbitrary_bytes) {
7017 nBufferIndex = buffer - m_inp_heap_ptr;
7018 } else {
7019 if (input_use_buffer == true) {
7020 nBufferIndex = buffer - m_inp_heap_ptr;
7021 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7022 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7023 return OMX_ErrorBadParameter;
7024 }
7025 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7026 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7027 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7028 buffer = &m_inp_mem_ptr[nBufferIndex];
7029 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7030 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7031 } else {
7032 nBufferIndex = buffer - m_inp_mem_ptr;
7033 }
7034 }
7035
7036 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7037 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7038 return OMX_ErrorBadParameter;
7039 }
7040
7041 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7042 codec_config_flag = true;
7043 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7044 }
7045
7046 /* The client should not set this when codec is in arbitrary bytes mode */
7047 if (m_input_pass_buffer_fd) {
7048 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7049 }
7050
7051 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7052 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7053 if (arbitrary_bytes) {
7054 post_event ((unsigned long)hComp,(unsigned long)buffer,
7055 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7056 } else {
7057 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7058 }
7059 time_stamp_dts.insert_timestamp(buffer);
7060 return OMX_ErrorNone;
7061 }
7062
7063 /* ======================================================================
7064 FUNCTION
7065 omx_vdec::empty_this_buffer_proxy
7066
7067 DESCRIPTION
7068 This routine is used to push the encoded video frames to
7069 the video decoder.
7070
7071 PARAMETERS
7072 None.
7073
7074 RETURN VALUE
7075 OMX Error None if everything went successful.
7076
7077 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7078 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
7079 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7080 {
7081 (void) hComp;
7082 int push_cnt = 0,i=0;
7083 unsigned nPortIndex = 0;
7084 OMX_ERRORTYPE ret = OMX_ErrorNone;
7085 struct vdec_input_frameinfo frameinfo;
7086 struct vdec_bufferpayload *temp_buffer;
7087 struct vdec_seqheader seq_header;
7088 bool port_setting_changed = true;
7089
7090 /*Should we generate a Aync error event*/
7091 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7092 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7093 return OMX_ErrorBadParameter;
7094 }
7095
7096 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7097
7098 if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7099 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7100 nPortIndex);
7101 return OMX_ErrorBadParameter;
7102 }
7103
7104 pending_input_buffers++;
7105
7106 /* return zero length and not an EOS buffer */
7107 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7108 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7109 DEBUG_PRINT_HIGH("return zero legth buffer");
7110 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7111 OMX_COMPONENT_GENERATE_EBD);
7112 return OMX_ErrorNone;
7113 }
7114
7115 if (input_flush_progress == true) {
7116 DEBUG_PRINT_LOW("Flush in progress return buffer ");
7117 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7118 OMX_COMPONENT_GENERATE_EBD);
7119 return OMX_ErrorNone;
7120 }
7121
7122 auto_lock l(buf_lock);
7123 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7124
7125 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7126 return OMX_ErrorBadParameter;
7127 }
7128
7129 if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7130 DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7131 return OMX_ErrorBadParameter;
7132 }
7133 /* If its first frame, H264 codec and reject is true, then parse the nal
7134 and get the profile. Based on this, reject the clip playback */
7135 if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
7136 m_reject_avc_1080p_mp) {
7137 first_frame = 1;
7138 DEBUG_PRINT_ERROR("Parse nal to get the profile");
7139 h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
7140 NALU_TYPE_SPS);
7141 m_profile = h264_parser->get_profile();
7142 ret = is_video_session_supported();
7143 if (ret) {
7144 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
7145 post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
7146 /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
7147 m_state = OMX_StateInvalid;
7148 return OMX_ErrorNone;
7149 }
7150 }
7151
7152 DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7153 /*for use buffer we need to memcpy the data*/
7154 temp_buffer->buffer_len = buffer->nFilledLen;
7155
7156 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7157 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7158 if (arbitrary_bytes) {
7159 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7160 } else {
7161 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7162 buffer->nFilledLen);
7163 }
7164 } else {
7165 return OMX_ErrorBadParameter;
7166 }
7167
7168 }
7169
7170 frameinfo.bufferaddr = temp_buffer->bufferaddr;
7171 frameinfo.client_data = (void *) buffer;
7172 frameinfo.datalen = temp_buffer->buffer_len;
7173 frameinfo.flags = 0;
7174 frameinfo.offset = buffer->nOffset;
7175 frameinfo.pmem_fd = temp_buffer->pmem_fd;
7176 frameinfo.pmem_offset = temp_buffer->offset;
7177 frameinfo.timestamp = buffer->nTimeStamp;
7178 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7179 DEBUG_PRINT_LOW("ETB: dmx enabled");
7180 if (m_demux_entries == 0) {
7181 extract_demux_addr_offsets(buffer);
7182 }
7183
7184 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7185 handle_demux_data(buffer);
7186 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
7187 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
7188 } else {
7189 frameinfo.desc_addr = NULL;
7190 frameinfo.desc_size = 0;
7191 }
7192 if (!arbitrary_bytes) {
7193 frameinfo.flags |= buffer->nFlags;
7194 }
7195
7196 #ifdef _ANDROID_
7197 if (m_debug_timestamp) {
7198 if (arbitrary_bytes) {
7199 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7200 m_timestamp_list.insert_ts(buffer->nTimeStamp);
7201 } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7202 DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
7203 m_timestamp_list.insert_ts(buffer->nTimeStamp);
7204 }
7205 }
7206 #endif
7207
7208 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
7209
7210 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7211 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7212 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7213 }
7214
7215 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7216 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7217 frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
7218 h264_scratch.nFilledLen = 0;
7219 nal_count = 0;
7220 look_ahead_nal = false;
7221 frame_count = 0;
7222 if (m_frame_parser.mutils)
7223 m_frame_parser.mutils->initialize_frame_checking_environment();
7224 m_frame_parser.flush();
7225 h264_last_au_ts = LLONG_MAX;
7226 h264_last_au_flags = 0;
7227 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7228 m_demux_entries = 0;
7229 }
7230 struct v4l2_buffer buf;
7231 struct v4l2_plane plane;
7232 memset( (void *)&buf, 0, sizeof(buf));
7233 memset( (void *)&plane, 0, sizeof(plane));
7234 int rc;
7235 unsigned long print_count;
7236 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7237 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7238 DEBUG_PRINT_HIGH("INPUT EOS reached") ;
7239 }
7240 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7241 buf.index = nPortIndex;
7242 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7243 buf.memory = V4L2_MEMORY_USERPTR;
7244 plane.bytesused = temp_buffer->buffer_len;
7245 plane.length = drv_ctx.ip_buf.buffer_size;
7246 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7247 (unsigned long)temp_buffer->offset;
7248 plane.reserved[0] = temp_buffer->pmem_fd;
7249 plane.reserved[1] = temp_buffer->offset;
7250 plane.data_offset = 0;
7251 buf.m.planes = &plane;
7252 buf.length = 1;
7253 if (frameinfo.timestamp >= LLONG_MAX) {
7254 buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
7255 }
7256 //assumption is that timestamp is in milliseconds
7257 buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
7258 buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
7259 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7260 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7261
7262 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7263 DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7264 android_atomic_inc(&m_queued_codec_config_count);
7265 }
7266
7267 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7268 if (rc) {
7269 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver");
7270 return OMX_ErrorHardware;
7271 }
7272
7273 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7274 codec_config_flag = false;
7275 }
7276 if (!streaming[OUTPUT_PORT]) {
7277 enum v4l2_buf_type buf_type;
7278 int ret,r;
7279
7280 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7281 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7282 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7283 if (!ret) {
7284 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7285 streaming[OUTPUT_PORT] = true;
7286 } else if (errno == EBUSY) {
7287 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7288 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7289 OMX_COMPONENT_GENERATE_EBD);
7290 return OMX_ErrorInsufficientResources;
7291 } else {
7292 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7293 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7294 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7295 OMX_COMPONENT_GENERATE_EBD);
7296 return OMX_ErrorBadParameter;
7297 }
7298 }
7299 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
7300 frameinfo.bufferaddr, (long long)frameinfo.timestamp,
7301 (unsigned int)frameinfo.datalen);
7302
7303 return ret;
7304 }
7305
7306 /* ======================================================================
7307 FUNCTION
7308 omx_vdec::FillThisBuffer
7309
7310 DESCRIPTION
7311 IL client uses this method to release the frame buffer
7312 after displaying them.
7313
7314 PARAMETERS
7315 None.
7316
7317 RETURN VALUE
7318 true/false
7319
7320 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7321 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7322 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7323 {
7324 if (m_state != OMX_StateExecuting &&
7325 m_state != OMX_StatePause &&
7326 m_state != OMX_StateIdle) {
7327 DEBUG_PRINT_ERROR("FTB in Invalid State");
7328 return OMX_ErrorInvalidState;
7329 }
7330
7331 if (!m_out_bEnabled) {
7332 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7333 return OMX_ErrorIncorrectStateOperation;
7334 }
7335
7336 unsigned nPortIndex = 0;
7337 if (dynamic_buf_mode) {
7338 private_handle_t *handle = NULL;
7339 struct VideoDecoderOutputMetaData *meta;
7340 unsigned int nPortIndex = 0;
7341
7342 if (!buffer || !buffer->pBuffer) {
7343 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7344 return OMX_ErrorBadParameter;
7345 }
7346
7347 //get the buffer type and fd info
7348 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7349 handle = (private_handle_t *)meta->pHandle;
7350 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
7351
7352 if (!handle) {
7353 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7354 return OMX_ErrorBadParameter;
7355 }
7356 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7357 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7358 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7359 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7360 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7361 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7362
7363 //Store private handle from GraphicBuffer
7364 native_buffer[nPortIndex].privatehandle = handle;
7365 native_buffer[nPortIndex].nativehandle = handle;
7366 } else {
7367 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7368 return OMX_ErrorBadParameter;
7369 }
7370
7371 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7372 //this with a more sane size so that we don't compensate in rest of code
7373 //We'll restore this size later on, so that it's transparent to client
7374 buffer->nFilledLen = 0;
7375 buffer->nAllocLen = handle->size;
7376 drv_ctx.op_buf.buffer_size = handle->size;
7377 }
7378
7379 nPortIndex = buffer - client_buffers.get_il_buf_hdr();
7380 if (buffer == NULL ||
7381 (nPortIndex >= drv_ctx.op_buf.actualcount)) {
7382 DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7383 nPortIndex, drv_ctx.op_buf.actualcount);
7384 return OMX_ErrorBadParameter;
7385 }
7386
7387 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7388 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
7389 return OMX_ErrorBadPortIndex;
7390 }
7391
7392 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
7393 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7394 return OMX_ErrorNone;
7395 }
7396 /* ======================================================================
7397 FUNCTION
7398 omx_vdec::fill_this_buffer_proxy
7399
7400 DESCRIPTION
7401 IL client uses this method to release the frame buffer
7402 after displaying them.
7403
7404 PARAMETERS
7405 None.
7406
7407 RETURN VALUE
7408 true/false
7409
7410 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7411 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
7412 OMX_IN OMX_HANDLETYPE hComp,
7413 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7414 {
7415 OMX_ERRORTYPE nRet = OMX_ErrorNone;
7416 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7417 unsigned nPortIndex = 0;
7418 struct vdec_fillbuffer_cmd fillbuffer;
7419 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
7420 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
7421
7422 auto_lock l(buf_lock);
7423 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
7424
7425 if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
7426 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
7427 nPortIndex, drv_ctx.op_buf.actualcount);
7428 return OMX_ErrorBadParameter;
7429 }
7430
7431 if (BITMASK_ABSENT(&m_out_bm_count, nPortIndex) || m_buffer_error) {
7432 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7433 return OMX_ErrorBadParameter;
7434 }
7435 DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
7436 bufferAdd, bufferAdd->pBuffer);
7437 /*Return back the output buffer to client*/
7438 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true) {
7439 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7440 buffer->nFilledLen = 0;
7441 m_cb.FillBufferDone (hComp,m_app_data,buffer);
7442 return OMX_ErrorNone;
7443 }
7444
7445 if (dynamic_buf_mode) {
7446 drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
7447 drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
7448 buf_ref_add(nPortIndex);
7449 drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
7450 }
7451
7452 pending_output_buffers++;
7453 buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
7454 if (!buffer) {
7455 DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
7456 return OMX_ErrorBadParameter;
7457 }
7458 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7459 if (ptr_respbuffer) {
7460 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7461 }
7462
7463 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7464 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
7465 buffer->nFilledLen = 0;
7466 m_cb.FillBufferDone (hComp,m_app_data,buffer);
7467 pending_output_buffers--;
7468 return OMX_ErrorBadParameter;
7469 }
7470
7471 int rc = 0;
7472 struct v4l2_buffer buf;
7473 struct v4l2_plane plane[VIDEO_MAX_PLANES];
7474 memset( (void *)&buf, 0, sizeof(buf));
7475 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7476 unsigned int extra_idx = 0;
7477
7478 buf.index = nPortIndex;
7479 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7480 buf.memory = V4L2_MEMORY_USERPTR;
7481 plane[0].bytesused = buffer->nFilledLen;
7482 plane[0].length = buffer->nAllocLen;
7483 plane[0].m.userptr =
7484 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
7485 (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7486 plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
7487 plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
7488 plane[0].data_offset = 0;
7489 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7490 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7491 plane[extra_idx].bytesused = 0;
7492 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7493 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
7494 #ifdef USE_ION
7495 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
7496 #endif
7497 plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
7498 plane[extra_idx].data_offset = 0;
7499 } else if (extra_idx >= VIDEO_MAX_PLANES) {
7500 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7501 return OMX_ErrorBadParameter;
7502 }
7503 buf.m.planes = plane;
7504 buf.length = drv_ctx.num_planes;
7505 DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
7506 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
7507
7508 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7509 if (rc) {
7510 /*TODO: How to handle this case */
7511 DEBUG_PRINT_ERROR("Failed to qbuf to driver");
7512 }
7513 return OMX_ErrorNone;
7514 }
7515
7516 /* ======================================================================
7517 FUNCTION
7518 omx_vdec::SetCallbacks
7519
7520 DESCRIPTION
7521 Set the callbacks.
7522
7523 PARAMETERS
7524 None.
7525
7526 RETURN VALUE
7527 OMX Error None if everything successful.
7528
7529 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7530 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
7531 OMX_IN OMX_CALLBACKTYPE* callbacks,
7532 OMX_IN OMX_PTR appData)
7533 {
7534 (void) hComp;
7535 m_cb = *callbacks;
7536 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7537 m_cb.EventHandler,m_cb.FillBufferDone);
7538 m_app_data = appData;
7539 return OMX_ErrorNotImplemented;
7540 }
7541
7542 /* ======================================================================
7543 FUNCTION
7544 omx_vdec::ComponentDeInit
7545
7546 DESCRIPTION
7547 Destroys the component and release memory allocated to the heap.
7548
7549 PARAMETERS
7550 <TBD>.
7551
7552 RETURN VALUE
7553 OMX Error None if everything successful.
7554
7555 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7556 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7557 {
7558 (void) hComp;
7559
7560 unsigned i = 0;
7561 if (OMX_StateLoaded != m_state) {
7562 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7563 m_state);
7564 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7565 } else {
7566 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7567 }
7568
7569 /*Check if the output buffers have to be cleaned up*/
7570 if (m_out_mem_ptr) {
7571 DEBUG_PRINT_LOW("Freeing the Output Memory");
7572 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7573 if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7574 BITMASK_CLEAR(&m_out_bm_count, i);
7575 client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
7576 }
7577
7578 if (release_output_done()) {
7579 break;
7580 }
7581 }
7582 #ifdef _ANDROID_ICS_
7583 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7584 #endif
7585 }
7586
7587 /*Check if the input buffers have to be cleaned up*/
7588 if (m_inp_mem_ptr || m_inp_heap_ptr) {
7589 DEBUG_PRINT_LOW("Freeing the Input Memory");
7590 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7591
7592 if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7593 BITMASK_CLEAR(&m_inp_bm_count, i);
7594 if (m_inp_mem_ptr)
7595 free_input_buffer (i,&m_inp_mem_ptr[i]);
7596 else
7597 free_input_buffer (i,NULL);
7598 }
7599
7600 if (release_input_done()) {
7601 break;
7602 }
7603 }
7604 }
7605 free_input_buffer_header();
7606 free_output_buffer_header();
7607 if (h264_scratch.pBuffer) {
7608 free(h264_scratch.pBuffer);
7609 h264_scratch.pBuffer = NULL;
7610 }
7611
7612 if (h264_parser) {
7613 delete h264_parser;
7614 h264_parser = NULL;
7615 }
7616
7617 if (m_frame_parser.mutils) {
7618 DEBUG_PRINT_LOW("Free utils parser");
7619 delete (m_frame_parser.mutils);
7620 m_frame_parser.mutils = NULL;
7621 }
7622
7623 if (m_platform_list) {
7624 free(m_platform_list);
7625 m_platform_list = NULL;
7626 }
7627 if (m_vendor_config.pData) {
7628 free(m_vendor_config.pData);
7629 m_vendor_config.pData = NULL;
7630 }
7631
7632 // Reset counters in mesg queues
7633 m_ftb_q.m_size=0;
7634 m_cmd_q.m_size=0;
7635 m_etb_q.m_size=0;
7636 m_ftb_q.m_read = m_ftb_q.m_write =0;
7637 m_cmd_q.m_read = m_cmd_q.m_write =0;
7638 m_etb_q.m_read = m_etb_q.m_write =0;
7639 #ifdef _ANDROID_
7640 if (m_debug_timestamp) {
7641 m_timestamp_list.reset_ts_list();
7642 }
7643 #endif
7644
7645 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7646 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7647 // NULL);
7648 DEBUG_PRINT_HIGH("Close the driver instance");
7649
7650 if (m_debug.infile) {
7651 fclose(m_debug.infile);
7652 m_debug.infile = NULL;
7653 }
7654 if (m_debug.outfile) {
7655 fclose(m_debug.outfile);
7656 m_debug.outfile = NULL;
7657 }
7658 if (m_debug.out_ymeta_file) {
7659 fclose(m_debug.out_ymeta_file);
7660 m_debug.out_ymeta_file = NULL;
7661 }
7662 if (m_debug.out_uvmeta_file) {
7663 fclose(m_debug.out_uvmeta_file);
7664 m_debug.out_uvmeta_file = NULL;
7665 }
7666 #ifdef OUTPUT_EXTRADATA_LOG
7667 if (outputExtradataFile)
7668 fclose (outputExtradataFile);
7669 #endif
7670 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
7671 return OMX_ErrorNone;
7672 }
7673
7674 /* ======================================================================
7675 FUNCTION
7676 omx_vdec::UseEGLImage
7677
7678 DESCRIPTION
7679 OMX Use EGL Image method implementation <TBD>.
7680
7681 PARAMETERS
7682 <TBD>.
7683
7684 RETURN VALUE
7685 Not Implemented error.
7686
7687 ========================================================================== */
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)7688 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
7689 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7690 OMX_IN OMX_U32 port,
7691 OMX_IN OMX_PTR appData,
7692 OMX_IN void* eglImage)
7693 {
7694 (void) appData;
7695 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
7696 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
7697 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
7698
7699 #ifdef USE_EGL_IMAGE_GPU
7700 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
7701 EGLint fd = -1, offset = 0,pmemPtr = 0;
7702 #else
7703 int fd = -1, offset = 0;
7704 #endif
7705 DEBUG_PRINT_HIGH("use EGL image support for decoder");
7706 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
7707 DEBUG_PRINT_ERROR("Invalid EGL image");
7708 }
7709 #ifdef USE_EGL_IMAGE_GPU
7710 if (m_display_id == NULL) {
7711 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
7712 return OMX_ErrorInsufficientResources;
7713 }
7714 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
7715 eglGetProcAddress("eglQueryImageKHR");
7716 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
7717 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
7718 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
7719 #else //with OMX test app
7720 struct temp_egl {
7721 int pmem_fd;
7722 int offset;
7723 };
7724 struct temp_egl *temp_egl_id = NULL;
7725 void * pmemPtr = (void *) eglImage;
7726 temp_egl_id = (struct temp_egl *)eglImage;
7727 if (temp_egl_id != NULL) {
7728 fd = temp_egl_id->pmem_fd;
7729 offset = temp_egl_id->offset;
7730 }
7731 #endif
7732 if (fd < 0) {
7733 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
7734 return OMX_ErrorInsufficientResources;
7735 }
7736 pmem_info.pmem_fd = (OMX_U32) fd;
7737 pmem_info.offset = (OMX_U32) offset;
7738 pmem_entry.entry = (void *) &pmem_info;
7739 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7740 pmem_list.entryList = &pmem_entry;
7741 pmem_list.nEntries = 1;
7742 ouput_egl_buffers = true;
7743 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
7744 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
7745 (OMX_U8 *)pmemPtr)) {
7746 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
7747 return OMX_ErrorInsufficientResources;
7748 }
7749 return OMX_ErrorNone;
7750 }
7751
7752 /* ======================================================================
7753 FUNCTION
7754 omx_vdec::ComponentRoleEnum
7755
7756 DESCRIPTION
7757 OMX Component Role Enum method implementation.
7758
7759 PARAMETERS
7760 <TBD>.
7761
7762 RETURN VALUE
7763 OMX Error None if everything is successful.
7764 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)7765 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
7766 OMX_OUT OMX_U8* role,
7767 OMX_IN OMX_U32 index)
7768 {
7769 (void) hComp;
7770 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7771
7772 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
7773 if ((0 == index) && role) {
7774 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
7775 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7776 } else {
7777 eRet = OMX_ErrorNoMore;
7778 }
7779 }
7780 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
7781 if ((0 == index) && role) {
7782 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
7783 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7784 } else {
7785 eRet = OMX_ErrorNoMore;
7786 }
7787 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
7788 if ((0 == index) && role) {
7789 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
7790 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7791 } else {
7792 DEBUG_PRINT_LOW("No more roles");
7793 eRet = OMX_ErrorNoMore;
7794 }
7795 }
7796
7797 else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
7798 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
7799 if ((0 == index) && role) {
7800 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
7801 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7802 } else {
7803 DEBUG_PRINT_LOW("No more roles");
7804 eRet = OMX_ErrorNoMore;
7805 }
7806 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
7807 if ((0 == index) && role) {
7808 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
7809 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7810 } else {
7811 DEBUG_PRINT_LOW("No more roles");
7812 eRet = OMX_ErrorNoMore;
7813 }
7814 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
7815 if ((0 == index) && role) {
7816 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
7817 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7818 } else {
7819 DEBUG_PRINT_LOW("No more roles");
7820 eRet = OMX_ErrorNoMore;
7821 }
7822 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
7823 if ((0 == index) && role) {
7824 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
7825 DEBUG_PRINT_LOW("component_role_enum: role %s", role);
7826 } else {
7827 DEBUG_PRINT_LOW("No more roles");
7828 eRet = OMX_ErrorNoMore;
7829 }
7830 } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
7831 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
7832 ) {
7833 if ((0 == index) && role) {
7834 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
7835 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7836 } else {
7837 DEBUG_PRINT_LOW("No more roles");
7838 eRet = OMX_ErrorNoMore;
7839 }
7840 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
7841 if ((0 == index) && role) {
7842 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
7843 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7844 } else {
7845 DEBUG_PRINT_LOW("No more roles");
7846 eRet = OMX_ErrorNoMore;
7847 }
7848 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
7849 if ((0 == index) && role) {
7850 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
7851 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
7852 } else {
7853 DEBUG_PRINT_LOW("No more roles");
7854 eRet = OMX_ErrorNoMore;
7855 }
7856 } else {
7857 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
7858 eRet = OMX_ErrorInvalidComponentName;
7859 }
7860 return eRet;
7861 }
7862
7863
7864
7865
7866 /* ======================================================================
7867 FUNCTION
7868 omx_vdec::AllocateDone
7869
7870 DESCRIPTION
7871 Checks if entire buffer pool is allocated by IL Client or not.
7872 Need this to move to IDLE state.
7873
7874 PARAMETERS
7875 None.
7876
7877 RETURN VALUE
7878 true/false.
7879
7880 ========================================================================== */
allocate_done(void)7881 bool omx_vdec::allocate_done(void)
7882 {
7883 bool bRet = false;
7884 bool bRet_In = false;
7885 bool bRet_Out = false;
7886
7887 bRet_In = allocate_input_done();
7888 bRet_Out = allocate_output_done();
7889
7890 if (bRet_In && bRet_Out) {
7891 bRet = true;
7892 }
7893
7894 return bRet;
7895 }
7896 /* ======================================================================
7897 FUNCTION
7898 omx_vdec::AllocateInputDone
7899
7900 DESCRIPTION
7901 Checks if I/P buffer pool is allocated by IL Client or not.
7902
7903 PARAMETERS
7904 None.
7905
7906 RETURN VALUE
7907 true/false.
7908
7909 ========================================================================== */
allocate_input_done(void)7910 bool omx_vdec::allocate_input_done(void)
7911 {
7912 bool bRet = false;
7913 unsigned i=0;
7914
7915 if (m_inp_mem_ptr == NULL) {
7916 return bRet;
7917 }
7918 if (m_inp_mem_ptr ) {
7919 for (; i<drv_ctx.ip_buf.actualcount; i++) {
7920 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
7921 break;
7922 }
7923 }
7924 }
7925 if (i == drv_ctx.ip_buf.actualcount) {
7926 bRet = true;
7927 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
7928 }
7929 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
7930 m_inp_bPopulated = OMX_TRUE;
7931 }
7932 return bRet;
7933 }
7934 /* ======================================================================
7935 FUNCTION
7936 omx_vdec::AllocateOutputDone
7937
7938 DESCRIPTION
7939 Checks if entire O/P buffer pool is allocated by IL Client or not.
7940
7941 PARAMETERS
7942 None.
7943
7944 RETURN VALUE
7945 true/false.
7946
7947 ========================================================================== */
allocate_output_done(void)7948 bool omx_vdec::allocate_output_done(void)
7949 {
7950 bool bRet = false;
7951 unsigned j=0;
7952
7953 if (m_out_mem_ptr == NULL) {
7954 return bRet;
7955 }
7956
7957 if (m_out_mem_ptr) {
7958 for (; j < drv_ctx.op_buf.actualcount; j++) {
7959 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
7960 break;
7961 }
7962 }
7963 }
7964
7965 if (j == drv_ctx.op_buf.actualcount) {
7966 bRet = true;
7967 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
7968 if (m_out_bEnabled)
7969 m_out_bPopulated = OMX_TRUE;
7970 }
7971
7972 return bRet;
7973 }
7974
7975 /* ======================================================================
7976 FUNCTION
7977 omx_vdec::ReleaseDone
7978
7979 DESCRIPTION
7980 Checks if IL client has released all the buffers.
7981
7982 PARAMETERS
7983 None.
7984
7985 RETURN VALUE
7986 true/false
7987
7988 ========================================================================== */
release_done(void)7989 bool omx_vdec::release_done(void)
7990 {
7991 bool bRet = false;
7992
7993 if (release_input_done()) {
7994 if (release_output_done()) {
7995 bRet = true;
7996 }
7997 }
7998 return bRet;
7999 }
8000
8001
8002 /* ======================================================================
8003 FUNCTION
8004 omx_vdec::ReleaseOutputDone
8005
8006 DESCRIPTION
8007 Checks if IL client has released all the buffers.
8008
8009 PARAMETERS
8010 None.
8011
8012 RETURN VALUE
8013 true/false
8014
8015 ========================================================================== */
release_output_done(void)8016 bool omx_vdec::release_output_done(void)
8017 {
8018 bool bRet = false;
8019 unsigned i=0,j=0;
8020
8021 DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
8022 if (m_out_mem_ptr) {
8023 for (; j < drv_ctx.op_buf.actualcount ; j++) {
8024 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8025 break;
8026 }
8027 }
8028 if (j == drv_ctx.op_buf.actualcount) {
8029 m_out_bm_count = 0;
8030 bRet = true;
8031 }
8032 } else {
8033 m_out_bm_count = 0;
8034 bRet = true;
8035 }
8036 return bRet;
8037 }
8038 /* ======================================================================
8039 FUNCTION
8040 omx_vdec::ReleaseInputDone
8041
8042 DESCRIPTION
8043 Checks if IL client has released all the buffers.
8044
8045 PARAMETERS
8046 None.
8047
8048 RETURN VALUE
8049 true/false
8050
8051 ========================================================================== */
release_input_done(void)8052 bool omx_vdec::release_input_done(void)
8053 {
8054 bool bRet = false;
8055 unsigned i=0,j=0;
8056
8057 DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
8058 if (m_inp_mem_ptr) {
8059 for (; j<drv_ctx.ip_buf.actualcount; j++) {
8060 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8061 break;
8062 }
8063 }
8064 if (j==drv_ctx.ip_buf.actualcount) {
8065 bRet = true;
8066 }
8067 } else {
8068 bRet = true;
8069 }
8070 return bRet;
8071 }
8072
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8073 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8074 OMX_BUFFERHEADERTYPE * buffer)
8075 {
8076 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8077 if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
8078 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8079 return OMX_ErrorBadParameter;
8080 } else if (output_flush_progress) {
8081 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8082 buffer->nFilledLen = 0;
8083 buffer->nTimeStamp = 0;
8084 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8085 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8086 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8087 }
8088
8089 if (m_debug_extradata) {
8090 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8091 DEBUG_PRINT_HIGH("***************************************************");
8092 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8093 DEBUG_PRINT_HIGH("***************************************************");
8094 }
8095
8096 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8097 DEBUG_PRINT_HIGH("***************************************************");
8098 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8099 DEBUG_PRINT_HIGH("***************************************************");
8100 }
8101 }
8102
8103
8104 DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
8105 buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
8106 pending_output_buffers --;
8107
8108 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8109 DEBUG_PRINT_HIGH("Output EOS has been reached");
8110 if (!output_flush_progress)
8111 post_event((unsigned)NULL, (unsigned)NULL,
8112 OMX_COMPONENT_GENERATE_EOS_DONE);
8113
8114 if (psource_frame) {
8115 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8116 psource_frame = NULL;
8117 }
8118 if (pdest_frame) {
8119 pdest_frame->nFilledLen = 0;
8120 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8121 (unsigned)NULL);
8122 pdest_frame = NULL;
8123 }
8124 }
8125
8126 if (!output_flush_progress && (buffer->nFilledLen > 0)) {
8127 // set the default colorspace advised by client, since the bitstream may be
8128 // devoid of colorspace-info.
8129 if (m_enable_android_native_buffers) {
8130 ColorSpace_t color_space = ITU_R_601;
8131
8132 // Disabled ?
8133 // WA for VP8. Vp8 encoder does not embed color-info (yet!).
8134 // Encoding RGBA results in 601-LR for all resolutions.
8135 // This conflicts with the client't defaults which are based on resolution.
8136 // Eg: 720p will be encoded as 601-LR. Client will say 709.
8137 // Re-enable this code once vp8 encoder generates color-info and hence the
8138 // decoder will be able to override with the correct source color.
8139 #if 0
8140 switch (m_client_color_space.sAspects.mPrimaries) {
8141 case ColorAspects::PrimariesBT601_6_625:
8142 case ColorAspects::PrimariesBT601_6_525:
8143 {
8144 color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
8145 ITU_R_601_FR : ITU_R_601;
8146 break;
8147 }
8148 case ColorAspects::PrimariesBT709_5:
8149 {
8150 color_space = ITU_R_709;
8151 break;
8152 }
8153 default:
8154 {
8155 break;
8156 }
8157 }
8158 #endif
8159 DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
8160 color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
8161 set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr);
8162 }
8163 DEBUG_PRINT_LOW("Processing extradata");
8164 handle_extradata(buffer);
8165 }
8166
8167 #ifdef OUTPUT_EXTRADATA_LOG
8168 if (outputExtradataFile) {
8169 int buf_index = buffer - m_out_mem_ptr;
8170 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
8171
8172 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8173 p_extra = (OMX_OTHER_EXTRADATATYPE *)
8174 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8175
8176 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8177 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8178 p_extra->nSize, p_extra->eType);
8179 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8180
8181 if (p_extra->eType == OMX_ExtraDataNone) {
8182 break;
8183 }
8184 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8185 }
8186 }
8187 #endif
8188
8189 /* For use buffer we need to copy the data */
8190 if (!output_flush_progress) {
8191 /* This is the error check for non-recoverable errros */
8192 bool is_duplicate_ts_valid = true;
8193 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8194
8195 if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8196 output_capability == V4L2_PIX_FMT_MPEG2 ||
8197 output_capability == V4L2_PIX_FMT_DIVX ||
8198 output_capability == V4L2_PIX_FMT_DIVX_311)
8199 is_duplicate_ts_valid = false;
8200
8201 if ((output_capability == V4L2_PIX_FMT_H264 ||
8202 output_capability == V4L2_PIX_FMT_H264_MVC) &&
8203 is_interlaced) {
8204 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
8205 is_interlaced = false;
8206 }
8207 }
8208
8209 if (buffer->nFilledLen > 0) {
8210 time_stamp_dts.get_next_timestamp(buffer,
8211 is_interlaced && is_duplicate_ts_valid);
8212 if (m_debug_timestamp) {
8213 {
8214 OMX_TICKS expected_ts = 0;
8215 m_timestamp_list.pop_min_ts(expected_ts);
8216 if (is_interlaced && is_duplicate_ts_valid) {
8217 m_timestamp_list.pop_min_ts(expected_ts);
8218 }
8219 DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
8220 buffer->nTimeStamp, expected_ts);
8221
8222 if (buffer->nTimeStamp != expected_ts) {
8223 DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
8224 }
8225 }
8226 }
8227 }
8228 }
8229
8230 if (m_cb.FillBufferDone) {
8231 if (buffer->nFilledLen > 0) {
8232 if (arbitrary_bytes)
8233 adjust_timestamp(buffer->nTimeStamp);
8234 else
8235 set_frame_rate(buffer->nTimeStamp);
8236
8237 if (perf_flag) {
8238 if (!proc_frms) {
8239 dec_time.stop();
8240 latency = dec_time.processing_time_us() - latency;
8241 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8242 dec_time.start();
8243 fps_metrics.start();
8244 }
8245 proc_frms++;
8246 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8247 OMX_U64 proc_time = 0;
8248 fps_metrics.stop();
8249 proc_time = fps_metrics.processing_time_us();
8250 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8251 (unsigned int)proc_frms, (float)proc_time / 1e6,
8252 (float)(1e6 * proc_frms) / proc_time);
8253 proc_frms = 0;
8254 }
8255 }
8256 }
8257 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8258 prev_ts = LLONG_MAX;
8259 rst_prev_ts = true;
8260 }
8261
8262 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8263 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8264 buffer->pPlatformPrivate)->entryList->entry;
8265 DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
8266 OMX_BUFFERHEADERTYPE *il_buffer;
8267 il_buffer = client_buffers.get_il_buf_hdr(buffer);
8268 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8269
8270 if (il_buffer && m_last_rendered_TS >= 0) {
8271 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8272
8273 // Current frame can be send for rendering if
8274 // (a) current FPS is <= 60
8275 // (b) is the next frame after the frame with TS 0
8276 // (c) is the first frame after seek
8277 // (d) the delta TS b\w two consecutive frames is > 16 ms
8278 // (e) its TS is equal to previous frame TS
8279 // (f) if marked EOS
8280
8281 if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
8282 il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
8283 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8284 m_last_rendered_TS = il_buffer->nTimeStamp;
8285 } else {
8286 //mark for droping
8287 buffer->nFilledLen = 0;
8288 }
8289
8290 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8291 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8292 il_buffer->nTimeStamp,ts_delta);
8293
8294 //above code makes sure that delta b\w two consecutive frames is not
8295 //greater than 16ms, slow-mo feature, so cap fps to max 60
8296 if (current_framerate > 60 ) {
8297 current_framerate = 60;
8298 }
8299 }
8300
8301 // add current framerate to gralloc meta data
8302 if (m_enable_android_native_buffers && m_out_mem_ptr) {
8303 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8304 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8305 UPDATE_REFRESH_RATE, (void*)¤t_framerate);
8306 }
8307
8308 if (il_buffer) {
8309 log_output_buffers(il_buffer);
8310 if (dynamic_buf_mode) {
8311 unsigned int nPortIndex = 0;
8312 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
8313
8314 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8315 // to size of the handle. Do it _after_ log_output_buffers which
8316 // requires the respective sizes to be accurate.
8317
8318 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8319 buffer->nFilledLen = buffer->nFilledLen ?
8320 sizeof(struct VideoDecoderOutputMetaData) : 0;
8321
8322 //Clear graphic buffer handles in dynamic mode
8323 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8324 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8325 native_buffer[nPortIndex].privatehandle = NULL;
8326 native_buffer[nPortIndex].nativehandle = NULL;
8327 } else {
8328 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8329 return OMX_ErrorBadParameter;
8330 }
8331 }
8332 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8333 } else {
8334 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8335 return OMX_ErrorBadParameter;
8336 }
8337 DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
8338 } else {
8339 return OMX_ErrorBadParameter;
8340 }
8341
8342 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8343 if (m_smoothstreaming_mode && m_out_mem_ptr) {
8344 OMX_U32 buf_index = buffer - m_out_mem_ptr;
8345 BufferDim_t dim;
8346 private_handle_t *private_handle = NULL;
8347 dim.sliceWidth = framesize.nWidth;
8348 dim.sliceHeight = framesize.nHeight;
8349 if (buf_index < drv_ctx.op_buf.actualcount &&
8350 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8351 native_buffer[buf_index].privatehandle)
8352 private_handle = native_buffer[buf_index].privatehandle;
8353 if (private_handle) {
8354 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8355 dim.sliceWidth, dim.sliceHeight);
8356 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8357 }
8358 }
8359 #endif
8360
8361 return OMX_ErrorNone;
8362 }
8363
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8364 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
8365 OMX_BUFFERHEADERTYPE* buffer)
8366 {
8367
8368 int nBufferIndex = buffer - m_inp_mem_ptr;
8369
8370 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8371 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8372 return OMX_ErrorBadParameter;
8373 }
8374
8375 DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
8376 buffer, buffer->pBuffer, buffer->nFlags);
8377 pending_input_buffers--;
8378
8379 if (arbitrary_bytes) {
8380 if (pdest_frame == NULL && input_flush_progress == false) {
8381 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8382 pdest_frame = buffer;
8383 buffer->nFilledLen = 0;
8384 buffer->nTimeStamp = LLONG_MAX;
8385 push_input_buffer (hComp);
8386 } else {
8387 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8388 buffer->nFilledLen = 0;
8389 if (!m_input_free_q.insert_entry((unsigned long)buffer,
8390 (unsigned)NULL, (unsigned)NULL)) {
8391 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8392 }
8393 }
8394 } else if (m_cb.EmptyBufferDone) {
8395 buffer->nFilledLen = 0;
8396 if (input_use_buffer == true) {
8397 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8398 }
8399
8400 /* Restore the FD that we over-wrote in ETB */
8401 if (m_input_pass_buffer_fd) {
8402 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8403 }
8404
8405 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8406 }
8407 return OMX_ErrorNone;
8408 }
8409
async_message_process(void * context,void * message)8410 int omx_vdec::async_message_process (void *context, void* message)
8411 {
8412 omx_vdec* omx = NULL;
8413 struct vdec_msginfo *vdec_msg = NULL;
8414 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8415 struct v4l2_buffer *v4l2_buf_ptr = NULL;
8416 struct vdec_output_frameinfo *output_respbuf = NULL;
8417 int rc=1;
8418 if (context == NULL || message == NULL) {
8419 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8420 return -1;
8421 }
8422 vdec_msg = (struct vdec_msginfo *)message;
8423
8424 omx = reinterpret_cast<omx_vdec*>(context);
8425
8426 switch (vdec_msg->msgcode) {
8427
8428 case VDEC_MSG_EVT_HW_ERROR:
8429 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8430 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8431 break;
8432
8433 case VDEC_MSG_EVT_HW_OVERLOAD:
8434 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8435 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8436 break;
8437
8438 case VDEC_MSG_EVT_HW_UNSUPPORTED:
8439 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8440 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8441 break;
8442
8443 case VDEC_MSG_RESP_START_DONE:
8444 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8445 OMX_COMPONENT_GENERATE_START_DONE);
8446 break;
8447
8448 case VDEC_MSG_RESP_STOP_DONE:
8449 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8450 OMX_COMPONENT_GENERATE_STOP_DONE);
8451 break;
8452
8453 case VDEC_MSG_RESP_RESUME_DONE:
8454 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8455 OMX_COMPONENT_GENERATE_RESUME_DONE);
8456 break;
8457
8458 case VDEC_MSG_RESP_PAUSE_DONE:
8459 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8460 OMX_COMPONENT_GENERATE_PAUSE_DONE);
8461 break;
8462
8463 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8464 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8465 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8466 break;
8467 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8468 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8469 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8470 break;
8471 case VDEC_MSG_RESP_INPUT_FLUSHED:
8472 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8473
8474 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8475 vdec_msg->msgdata.input_frame_clientdata; */
8476
8477 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8478 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8479 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8480 omxhdr = NULL;
8481 vdec_msg->status_code = VDEC_S_EFATAL;
8482 break;
8483
8484 }
8485 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8486
8487 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8488 DEBUG_PRINT_HIGH("Unsupported input");
8489 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8490 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8491 }
8492 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8493 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8494 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8495 }
8496 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8497
8498 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8499 android_atomic_dec(&omx->m_queued_codec_config_count);
8500 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8501 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8502 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8503 sem_post(&omx->m_safe_flush);
8504 }
8505 }
8506 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
8507 v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8508 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8509 }
8510 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8511 OMX_COMPONENT_GENERATE_EBD);
8512 break;
8513 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8514 int64_t *timestamp;
8515 timestamp = (int64_t *) malloc(sizeof(int64_t));
8516 if (timestamp) {
8517 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8518 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8519 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8520 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8521 (long long)vdec_msg->msgdata.output_frame.time_stamp);
8522 }
8523 break;
8524 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8525 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
8526
8527 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8528
8529 if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
8530 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8531 omxhdr = NULL;
8532 vdec_msg->status_code = VDEC_S_EFATAL;
8533 break;
8534 }
8535
8536 omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
8537
8538 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x) FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8539 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8540 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8541 (unsigned int)vdec_msg->msgdata.output_frame.len,
8542 vdec_msg->msgdata.output_frame.framesize.left,
8543 vdec_msg->msgdata.output_frame.framesize.top,
8544 vdec_msg->msgdata.output_frame.framesize.right,
8545 vdec_msg->msgdata.output_frame.framesize.bottom);
8546
8547 if (omxhdr && omxhdr->pOutputPortPrivate &&
8548 ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
8549 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8550 - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8551
8552 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
8553 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8554 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8555 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8556 omxhdr->nFlags = 0;
8557
8558 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8559 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8560 //rc = -1;
8561 }
8562 if (omxhdr->nFilledLen) {
8563 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8564 }
8565 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
8566 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8567 } else {
8568 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8569 }
8570 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
8571 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8572 }
8573 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8574 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8575 }
8576
8577 if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
8578 omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
8579 }
8580
8581 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8582 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8583 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8584 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8585 }
8586
8587 if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
8588 !omx->output_flush_progress &&
8589 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
8590 !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
8591 unsigned int index = v4l2_buf_ptr->index;
8592 unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
8593 struct v4l2_plane *plane = v4l2_buf_ptr->m.planes;
8594 omx->time_stamp_dts.remove_time_stamp(
8595 omxhdr->nTimeStamp,
8596 (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
8597 ?true:false);
8598 plane[0].bytesused = 0;
8599 plane[0].m.userptr =
8600 (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
8601 (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
8602 plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
8603 plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
8604 plane[0].data_offset = 0;
8605 v4l2_buf_ptr->flags = 0x0;
8606 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
8607 plane[extra_idx].bytesused = 0;
8608 plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
8609 plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
8610 #ifdef USE_ION
8611 plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
8612 #endif
8613 plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
8614 plane[extra_idx].data_offset = 0;
8615 } else if (extra_idx >= VIDEO_MAX_PLANES) {
8616 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
8617 return -1;
8618 }
8619
8620 DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
8621 plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
8622 if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
8623 DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]);
8624 return -1;
8625 }
8626 break;
8627 }
8628 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
8629 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8630 }
8631 vdec_msg->msgdata.output_frame.bufferaddr =
8632 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8633
8634 /* Post event if resolution OR crop changed */
8635 /* filled length will be changed if resolution changed */
8636 /* Crop parameters can be changed even without resolution change */
8637 if (omxhdr->nFilledLen
8638 && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8639 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8640 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8641 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8642 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
8643 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
8644 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
8645
8646 DEBUG_PRINT_HIGH("Paramters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
8647 omx->prev_n_filled_len,
8648 omx->drv_ctx.video_resolution.frame_width,
8649 omx->drv_ctx.video_resolution.frame_height,
8650 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
8651 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
8652 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
8653 vdec_msg->msgdata.output_frame.picsize.frame_height,
8654 vdec_msg->msgdata.output_frame.framesize.left,
8655 vdec_msg->msgdata.output_frame.framesize.top,
8656 vdec_msg->msgdata.output_frame.framesize.right,
8657 vdec_msg->msgdata.output_frame.framesize.bottom);
8658
8659 omx->drv_ctx.video_resolution.frame_width =
8660 vdec_msg->msgdata.output_frame.picsize.frame_width;
8661 omx->drv_ctx.video_resolution.frame_height =
8662 vdec_msg->msgdata.output_frame.picsize.frame_height;
8663 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
8664 omx->drv_ctx.video_resolution.stride =
8665 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
8666 omx->drv_ctx.video_resolution.scan_lines =
8667 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
8668 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
8669 omx->drv_ctx.video_resolution.stride =
8670 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
8671 omx->drv_ctx.video_resolution.scan_lines =
8672 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
8673 }
8674
8675 memcpy(&omx->drv_ctx.frame_size,
8676 &vdec_msg->msgdata.output_frame.framesize,
8677 sizeof(struct vdec_framesize));
8678
8679 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
8680 OMX_IndexConfigCommonOutputCrop,
8681 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8682 }
8683
8684 if (omxhdr->nFilledLen)
8685 omx->prev_n_filled_len = omxhdr->nFilledLen;
8686
8687 output_respbuf = (struct vdec_output_frameinfo *)\
8688 omxhdr->pOutputPortPrivate;
8689 if (!output_respbuf) {
8690 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8691 return -1;
8692 }
8693 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8694 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8695
8696 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8697 output_respbuf->pic_type = PICTURE_TYPE_I;
8698 }
8699 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8700 output_respbuf->pic_type = PICTURE_TYPE_P;
8701 }
8702 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8703 output_respbuf->pic_type = PICTURE_TYPE_B;
8704 }
8705 if (omxhdr && omxhdr->nFilledLen) {
8706 omx->request_perf_level(VIDC_NOMINAL);
8707 }
8708 if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
8709 vdec_msg->msgdata.output_frame.bufferaddr)
8710 memcpy ( omxhdr->pBuffer, (void *)
8711 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
8712 (unsigned long)vdec_msg->msgdata.output_frame.offset),
8713 vdec_msg->msgdata.output_frame.len);
8714 } else {
8715 DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
8716 (unsigned int)vdec_msg->msgdata.output_frame.len,
8717 omxhdr->nAllocLen, omx->prev_n_filled_len);
8718 omxhdr->nFilledLen = 0;
8719 }
8720
8721 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
8722 OMX_COMPONENT_GENERATE_FBD);
8723
8724 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
8725 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
8726 OMX_COMPONENT_GENERATE_EOS_DONE);
8727 } else {
8728 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
8729 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8730 }
8731 break;
8732 case VDEC_MSG_EVT_CONFIG_CHANGED:
8733 DEBUG_PRINT_HIGH("Port settings changed");
8734 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8735 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8736 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
8737 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
8738 omx->request_perf_level(VIDC_NOMINAL);
8739 break;
8740 default:
8741 break;
8742 }
8743 return rc;
8744 }
8745
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8746 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
8747 OMX_HANDLETYPE hComp,
8748 OMX_BUFFERHEADERTYPE *buffer
8749 )
8750 {
8751 unsigned address,p2,id;
8752 DEBUG_PRINT_LOW("Empty this arbitrary");
8753
8754 if (buffer == NULL) {
8755 return OMX_ErrorBadParameter;
8756 }
8757 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
8758 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
8759 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
8760
8761 /* return zero length and not an EOS buffer */
8762 /* return buffer if input flush in progress */
8763 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
8764 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
8765 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
8766 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
8767 return OMX_ErrorNone;
8768 }
8769
8770 if (psource_frame == NULL) {
8771 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
8772 psource_frame = buffer;
8773 DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
8774 push_input_buffer (hComp);
8775 } else {
8776 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
8777 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
8778 (unsigned)NULL)) {
8779 return OMX_ErrorBadParameter;
8780 }
8781 }
8782
8783 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
8784 codec_config_flag = false;
8785 }
8786 return OMX_ErrorNone;
8787 }
8788
push_input_buffer(OMX_HANDLETYPE hComp)8789 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
8790 {
8791 unsigned long address,p2,id;
8792 OMX_ERRORTYPE ret = OMX_ErrorNone;
8793
8794 if (pdest_frame == NULL || psource_frame == NULL) {
8795 /*Check if we have a destination buffer*/
8796 if (pdest_frame == NULL) {
8797 DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
8798 if (m_input_free_q.m_size) {
8799 m_input_free_q.pop_entry(&address,&p2,&id);
8800 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
8801 pdest_frame->nFilledLen = 0;
8802 pdest_frame->nTimeStamp = LLONG_MAX;
8803 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
8804 }
8805 }
8806
8807 /*Check if we have a destination buffer*/
8808 if (psource_frame == NULL) {
8809 DEBUG_PRINT_LOW("Get a source buffer from the queue");
8810 if (m_input_pending_q.m_size) {
8811 m_input_pending_q.pop_entry(&address,&p2,&id);
8812 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
8813 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8814 psource_frame->nTimeStamp);
8815 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8816 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8817
8818 }
8819 }
8820
8821 }
8822
8823 while ((pdest_frame != NULL) && (psource_frame != NULL)) {
8824 switch (codec_type_parse) {
8825 case CODEC_TYPE_MPEG4:
8826 case CODEC_TYPE_H263:
8827 case CODEC_TYPE_MPEG2:
8828 ret = push_input_sc_codec(hComp);
8829 break;
8830 case CODEC_TYPE_H264:
8831 ret = push_input_h264(hComp);
8832 break;
8833 case CODEC_TYPE_HEVC:
8834 ret = push_input_hevc(hComp);
8835 break;
8836 case CODEC_TYPE_VC1:
8837 ret = push_input_vc1(hComp);
8838 break;
8839 default:
8840 break;
8841 }
8842 if (ret != OMX_ErrorNone) {
8843 DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
8844 omx_report_error ();
8845 break;
8846 }
8847 }
8848
8849 return ret;
8850 }
8851
push_input_sc_codec(OMX_HANDLETYPE hComp)8852 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
8853 {
8854 OMX_U32 partial_frame = 1;
8855 OMX_BOOL generate_ebd = OMX_TRUE;
8856 unsigned long address = 0, p2 = 0, id = 0;
8857
8858 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
8859 psource_frame,psource_frame->nTimeStamp);
8860 if (m_frame_parser.parse_sc_frame(psource_frame,
8861 pdest_frame,&partial_frame) == -1) {
8862 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8863 return OMX_ErrorBadParameter;
8864 }
8865
8866 if (partial_frame == 0) {
8867 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
8868 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
8869
8870
8871 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
8872 /*First Parsed buffer will have only header Hence skip*/
8873 if (frame_count == 0) {
8874 DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
8875
8876 if (codec_type_parse == CODEC_TYPE_MPEG4 ||
8877 codec_type_parse == CODEC_TYPE_DIVX) {
8878 mp4StreamType psBits;
8879 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
8880 psBits.numBytes = pdest_frame->nFilledLen;
8881 mp4_headerparser.parseHeader(&psBits);
8882 }
8883
8884 frame_count++;
8885 } else {
8886 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
8887 if (pdest_frame->nFilledLen) {
8888 /*Push the frame to the Decoder*/
8889 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8890 return OMX_ErrorBadParameter;
8891 }
8892 frame_count++;
8893 pdest_frame = NULL;
8894
8895 if (m_input_free_q.m_size) {
8896 m_input_free_q.pop_entry(&address,&p2,&id);
8897 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
8898 pdest_frame->nFilledLen = 0;
8899 }
8900 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
8901 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
8902 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
8903 (unsigned)NULL);
8904 pdest_frame = NULL;
8905 }
8906 }
8907 } else {
8908 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
8909 /*Check if Destination Buffer is full*/
8910 if (pdest_frame->nAllocLen ==
8911 pdest_frame->nFilledLen + pdest_frame->nOffset) {
8912 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
8913 return OMX_ErrorStreamCorrupt;
8914 }
8915 }
8916
8917 if (psource_frame->nFilledLen == 0) {
8918 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
8919 if (pdest_frame) {
8920 pdest_frame->nFlags |= psource_frame->nFlags;
8921 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
8922 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
8923 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
8924 (unsigned int)pdest_frame->nFilledLen,frame_count++);
8925 /*Push the frame to the Decoder*/
8926 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
8927 return OMX_ErrorBadParameter;
8928 }
8929 frame_count++;
8930 pdest_frame = NULL;
8931 } else {
8932 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
8933 generate_ebd = OMX_FALSE;
8934 }
8935 }
8936 if (generate_ebd) {
8937 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
8938 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
8939 psource_frame = NULL;
8940
8941 if (m_input_pending_q.m_size) {
8942 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
8943 m_input_pending_q.pop_entry(&address,&p2,&id);
8944 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
8945 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
8946 psource_frame->nTimeStamp);
8947 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
8948 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
8949 }
8950 }
8951 }
8952 return OMX_ErrorNone;
8953 }
8954
push_input_h264(OMX_HANDLETYPE hComp)8955 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
8956 {
8957 OMX_U32 partial_frame = 1;
8958 unsigned long address = 0, p2 = 0, id = 0;
8959 OMX_BOOL isNewFrame = OMX_FALSE;
8960 OMX_BOOL generate_ebd = OMX_TRUE;
8961
8962 if (h264_scratch.pBuffer == NULL) {
8963 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
8964 return OMX_ErrorBadParameter;
8965 }
8966 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
8967 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
8968 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
8969 if (h264_scratch.nFilledLen && look_ahead_nal) {
8970 look_ahead_nal = false;
8971 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
8972 h264_scratch.nFilledLen) {
8973 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
8974 h264_scratch.pBuffer,h264_scratch.nFilledLen);
8975 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
8976 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
8977 h264_scratch.nFilledLen = 0;
8978 } else {
8979 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
8980 return OMX_ErrorBadParameter;
8981 }
8982 }
8983
8984 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
8985 in EOS flag getting associated with the destination
8986 */
8987 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
8988 pdest_frame->nFilledLen) {
8989 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
8990 generate_ebd = OMX_FALSE;
8991 }
8992
8993 if (nal_length == 0) {
8994 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
8995 if (m_frame_parser.parse_sc_frame(psource_frame,
8996 &h264_scratch,&partial_frame) == -1) {
8997 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
8998 return OMX_ErrorBadParameter;
8999 }
9000 } else {
9001 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9002 if (m_frame_parser.parse_h264_nallength(psource_frame,
9003 &h264_scratch,&partial_frame) == -1) {
9004 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9005 return OMX_ErrorBadParameter;
9006 }
9007 }
9008
9009 if (partial_frame == 0) {
9010 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9011 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9012 nal_count++;
9013 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9014 h264_scratch.nFlags = psource_frame->nFlags;
9015 } else {
9016 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9017 if (h264_scratch.nFilledLen) {
9018 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9019 NALU_TYPE_SPS);
9020 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9021 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9022 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9023 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9024 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9025 // If timeinfo is present frame info from SEI is already processed
9026 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9027 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9028 #endif
9029 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9030 nal_count++;
9031 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9032 pdest_frame->nTimeStamp = h264_last_au_ts;
9033 pdest_frame->nFlags = h264_last_au_flags;
9034 #ifdef PANSCAN_HDLR
9035 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9036 h264_parser->update_panscan_data(h264_last_au_ts);
9037 #endif
9038 }
9039 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9040 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9041 h264_last_au_ts = h264_scratch.nTimeStamp;
9042 h264_last_au_flags = h264_scratch.nFlags;
9043 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9044 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9045 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9046 if (!VALID_TS(h264_last_au_ts))
9047 h264_last_au_ts = ts_in_sei;
9048 }
9049 #endif
9050 } else
9051 h264_last_au_ts = LLONG_MAX;
9052 }
9053
9054 if (!isNewFrame) {
9055 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9056 h264_scratch.nFilledLen) {
9057 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9058 (unsigned int)h264_scratch.nFilledLen);
9059 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9060 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9061 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9062 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9063 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9064 h264_scratch.nFilledLen = 0;
9065 } else {
9066 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9067 return OMX_ErrorBadParameter;
9068 }
9069 } else if(h264_scratch.nFilledLen) {
9070 look_ahead_nal = true;
9071 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9072 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9073 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9074 (unsigned int)pdest_frame->nFilledLen,frame_count++);
9075
9076 if (pdest_frame->nFilledLen == 0) {
9077 DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9078 look_ahead_nal = false;
9079 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9080 h264_scratch.nFilledLen) {
9081 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9082 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9083 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9084 h264_scratch.nFilledLen = 0;
9085 } else {
9086 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9087 return OMX_ErrorBadParameter;
9088 }
9089 } else {
9090 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9091 DEBUG_PRINT_LOW("Reset the EOS Flag");
9092 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9093 }
9094 /*Push the frame to the Decoder*/
9095 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9096 return OMX_ErrorBadParameter;
9097 }
9098 //frame_count++;
9099 pdest_frame = NULL;
9100 if (m_input_free_q.m_size) {
9101 m_input_free_q.pop_entry(&address,&p2,&id);
9102 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9103 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9104 pdest_frame->nFilledLen = 0;
9105 pdest_frame->nFlags = 0;
9106 pdest_frame->nTimeStamp = LLONG_MAX;
9107 }
9108 }
9109 }
9110 }
9111 } else {
9112 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9113 /*Check if Destination Buffer is full*/
9114 if (h264_scratch.nAllocLen ==
9115 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9116 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9117 return OMX_ErrorStreamCorrupt;
9118 }
9119 }
9120
9121 if (!psource_frame->nFilledLen) {
9122 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9123
9124 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9125 if (pdest_frame) {
9126 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9127 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9128 h264_scratch.nFilledLen) {
9129 if(pdest_frame->nFilledLen == 0) {
9130 /* No residual frame from before, send whatever
9131 * we have left */
9132 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9133 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9134 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9135 h264_scratch.nFilledLen = 0;
9136 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9137 } else {
9138 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9139 if(!isNewFrame) {
9140 /* Have a residual frame, but we know that the
9141 * AU in this frame is belonging to whatever
9142 * frame we had left over. So append it */
9143 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9144 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9145 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9146 h264_scratch.nFilledLen = 0;
9147 if (h264_last_au_ts != LLONG_MAX)
9148 pdest_frame->nTimeStamp = h264_last_au_ts;
9149 } else {
9150 /* Completely new frame, let's just push what
9151 * we have now. The resulting EBD would trigger
9152 * another push */
9153 generate_ebd = OMX_FALSE;
9154 pdest_frame->nTimeStamp = h264_last_au_ts;
9155 h264_last_au_ts = h264_scratch.nTimeStamp;
9156 }
9157 }
9158 } else {
9159 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9160 return OMX_ErrorBadParameter;
9161 }
9162
9163 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9164 if(generate_ebd == OMX_TRUE) {
9165 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9166 }
9167
9168 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9169 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9170 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9171 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9172 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9173 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9174 if (!VALID_TS(pdest_frame->nTimeStamp))
9175 pdest_frame->nTimeStamp = ts_in_sei;
9176 }
9177 #endif
9178 /*Push the frame to the Decoder*/
9179 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9180 return OMX_ErrorBadParameter;
9181 }
9182 frame_count++;
9183 pdest_frame = NULL;
9184 } else {
9185 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9186 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9187 generate_ebd = OMX_FALSE;
9188 }
9189 }
9190 }
9191 if (generate_ebd && !psource_frame->nFilledLen) {
9192 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9193 psource_frame = NULL;
9194 if (m_input_pending_q.m_size) {
9195 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9196 m_input_pending_q.pop_entry(&address,&p2,&id);
9197 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9198 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9199 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9200 }
9201 }
9202 return OMX_ErrorNone;
9203 }
9204
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9205 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9206 {
9207 OMX_ERRORTYPE rc = OMX_ErrorNone;
9208 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9209 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9210 if (pDst->nTimeStamp == LLONG_MAX) {
9211 pDst->nTimeStamp = pSrc->nTimeStamp;
9212 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9213 }
9214 pDst->nFilledLen += pSrc->nFilledLen;
9215 pSrc->nFilledLen = 0;
9216 } else {
9217 DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9218 rc = OMX_ErrorBadParameter;
9219 }
9220 return rc;
9221 }
9222
push_input_hevc(OMX_HANDLETYPE hComp)9223 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9224 {
9225 OMX_U32 partial_frame = 1;
9226 unsigned long address,p2,id;
9227 OMX_BOOL isNewFrame = OMX_FALSE;
9228 OMX_BOOL generate_ebd = OMX_TRUE;
9229 OMX_ERRORTYPE rc = OMX_ErrorNone;
9230 if (h264_scratch.pBuffer == NULL) {
9231 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9232 return OMX_ErrorBadParameter;
9233 }
9234
9235 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9236 pdest_frame nFilledLen %u nTimeStamp %lld",
9237 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9238
9239 if (h264_scratch.nFilledLen && look_ahead_nal) {
9240 look_ahead_nal = false;
9241 rc = copy_buffer(pdest_frame, &h264_scratch);
9242 if (rc != OMX_ErrorNone) {
9243 return rc;
9244 }
9245 }
9246
9247 if (nal_length == 0) {
9248 if (m_frame_parser.parse_sc_frame(psource_frame,
9249 &h264_scratch,&partial_frame) == -1) {
9250 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9251 return OMX_ErrorBadParameter;
9252 }
9253 } else {
9254 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9255 if (m_frame_parser.parse_h264_nallength(psource_frame,
9256 &h264_scratch,&partial_frame) == -1) {
9257 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9258 return OMX_ErrorBadParameter;
9259 }
9260 }
9261
9262 if (partial_frame == 0) {
9263 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9264 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9265 nal_count++;
9266 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9267 h264_scratch.nFlags = psource_frame->nFlags;
9268 } else {
9269 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9270 if (h264_scratch.nFilledLen) {
9271 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9272 nal_count++;
9273 }
9274
9275 if (!isNewFrame) {
9276 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9277 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9278 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9279 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9280 rc = copy_buffer(pdest_frame, &h264_scratch);
9281 if (rc != OMX_ErrorNone) {
9282 return rc;
9283 }
9284 } else {
9285 look_ahead_nal = true;
9286 if (pdest_frame->nFilledLen == 0) {
9287 look_ahead_nal = false;
9288 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9289 rc = copy_buffer(pdest_frame, &h264_scratch);
9290 if (rc != OMX_ErrorNone) {
9291 return OMX_ErrorBadParameter;
9292 }
9293 } else {
9294 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9295 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9296 }
9297 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9298 nTimeStamp %lld, look_ahead_nal in h264_scratch \
9299 nFilledLen %u nTimeStamp %lld",
9300 frame_count++, (unsigned int)pdest_frame->nFilledLen,
9301 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9302 h264_scratch.nTimeStamp);
9303 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9304 return OMX_ErrorBadParameter;
9305 }
9306 pdest_frame = NULL;
9307 if (m_input_free_q.m_size) {
9308 m_input_free_q.pop_entry(&address, &p2, &id);
9309 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9310 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9311 pdest_frame->nFilledLen = 0;
9312 pdest_frame->nFlags = 0;
9313 pdest_frame->nTimeStamp = LLONG_MAX;
9314 }
9315 }
9316 }
9317 }
9318 } else {
9319 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9320 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9321 nFilledLen %u nTimeStamp %lld",
9322 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9323 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9324 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9325
9326 if (h264_scratch.nAllocLen ==
9327 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9328 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9329 return OMX_ErrorStreamCorrupt;
9330 }
9331 }
9332
9333 if (!psource_frame->nFilledLen) {
9334 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9335 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9336 if (pdest_frame) {
9337 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9338 rc = copy_buffer(pdest_frame, &h264_scratch);
9339 if ( rc != OMX_ErrorNone ) {
9340 return rc;
9341 }
9342 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9343 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9344 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9345 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9346 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9347 return OMX_ErrorBadParameter;
9348 }
9349 frame_count++;
9350 pdest_frame = NULL;
9351 } else {
9352 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9353 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9354 generate_ebd = OMX_FALSE;
9355 }
9356 }
9357 }
9358
9359 if (generate_ebd && !psource_frame->nFilledLen) {
9360 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9361 psource_frame = NULL;
9362 if (m_input_pending_q.m_size) {
9363 m_input_pending_q.pop_entry(&address, &p2, &id);
9364 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9365 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9366 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9367 }
9368 }
9369 return OMX_ErrorNone;
9370 }
9371
push_input_vc1(OMX_HANDLETYPE hComp)9372 OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
9373 {
9374 OMX_U8 *buf, *pdest;
9375 OMX_U32 partial_frame = 1;
9376 OMX_U32 buf_len, dest_len;
9377
9378 if (first_frame == 0) {
9379 first_frame = 1;
9380 DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
9381 if (!m_vendor_config.pData) {
9382 DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
9383 buf = psource_frame->pBuffer;
9384 buf_len = psource_frame->nFilledLen;
9385
9386 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
9387 VC1_SP_MP_START_CODE) {
9388 m_vc1_profile = VC1_SP_MP_RCV;
9389 } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
9390 m_vc1_profile = VC1_AP;
9391 } else {
9392 DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
9393 return OMX_ErrorStreamCorrupt;
9394 }
9395 } else {
9396 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
9397 pdest_frame->nOffset;
9398 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
9399 pdest_frame->nOffset);
9400
9401 if (dest_len < m_vendor_config.nDataSize) {
9402 DEBUG_PRINT_ERROR("Destination buffer full");
9403 return OMX_ErrorBadParameter;
9404 } else {
9405 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
9406 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
9407 }
9408 }
9409 }
9410
9411 switch (m_vc1_profile) {
9412 case VC1_AP:
9413 DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
9414 if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
9415 DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
9416 return OMX_ErrorBadParameter;
9417 }
9418 break;
9419
9420 case VC1_SP_MP_RCV:
9421 default:
9422 DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
9423 return OMX_ErrorBadParameter;
9424 }
9425 return OMX_ErrorNone;
9426 }
9427
9428 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9429 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9430 OMX_U32 alignment)
9431 {
9432 struct pmem_allocation allocation;
9433 allocation.size = buffer_size;
9434 allocation.align = clip2(alignment);
9435 if (allocation.align < 4096) {
9436 allocation.align = 4096;
9437 }
9438 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9439 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9440 allocation.align, allocation.size);
9441 return false;
9442 }
9443 return true;
9444 }
9445 #endif
9446 #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)9447 int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
9448 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
9449 struct ion_fd_data *fd_data, int flag)
9450 {
9451 int fd = -EINVAL;
9452 int rc = -EINVAL;
9453 int ion_dev_flag;
9454 struct vdec_ion ion_buf_info;
9455 if (!alloc_data || buffer_size <= 0 || !fd_data) {
9456 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9457 return -EINVAL;
9458 }
9459 ion_dev_flag = O_RDONLY;
9460 fd = open (MEM_DEVICE, ion_dev_flag);
9461 if (fd < 0) {
9462 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
9463 return fd;
9464 }
9465
9466 alloc_data->flags = flag;
9467 alloc_data->len = buffer_size;
9468 alloc_data->align = clip2(alignment);
9469 if (alloc_data->align < 4096) {
9470 alloc_data->align = 4096;
9471 }
9472
9473 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
9474 if (secure_mode && (alloc_data->flags & ION_SECURE)) {
9475 alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9476 }
9477
9478 /* Use secure display cma heap for obvious reasons. */
9479 if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
9480 alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9481 }
9482
9483 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
9484 if (rc || !alloc_data->handle) {
9485 DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9486 alloc_data->handle = 0;
9487 close(fd);
9488 fd = -ENOMEM;
9489 return fd;
9490 }
9491 fd_data->handle = alloc_data->handle;
9492 rc = ioctl(fd,ION_IOC_MAP,fd_data);
9493 if (rc) {
9494 DEBUG_PRINT_ERROR("ION MAP failed ");
9495 ion_buf_info.ion_alloc_data = *alloc_data;
9496 ion_buf_info.ion_device_fd = fd;
9497 ion_buf_info.fd_ion_data = *fd_data;
9498 free_ion_memory(&ion_buf_info);
9499 fd_data->fd =-1;
9500 fd = -ENOMEM;
9501 }
9502
9503 return fd;
9504 }
9505
free_ion_memory(struct vdec_ion * buf_ion_info)9506 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9507 {
9508
9509 if (!buf_ion_info) {
9510 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9511 return;
9512 }
9513 if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
9514 &buf_ion_info->ion_alloc_data.handle)) {
9515 DEBUG_PRINT_ERROR("ION: free failed" );
9516 }
9517 close(buf_ion_info->ion_device_fd);
9518 buf_ion_info->ion_device_fd = -1;
9519 buf_ion_info->ion_alloc_data.handle = 0;
9520 buf_ion_info->fd_ion_data.fd = -1;
9521 }
9522 #endif
free_output_buffer_header()9523 void omx_vdec::free_output_buffer_header()
9524 {
9525 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
9526 output_use_buffer = false;
9527 ouput_egl_buffers = false;
9528
9529 if (m_out_mem_ptr) {
9530 free (m_out_mem_ptr);
9531 m_out_mem_ptr = NULL;
9532 }
9533
9534 if (m_platform_list) {
9535 free(m_platform_list);
9536 m_platform_list = NULL;
9537 }
9538
9539 if (drv_ctx.ptr_respbuffer) {
9540 free (drv_ctx.ptr_respbuffer);
9541 drv_ctx.ptr_respbuffer = NULL;
9542 }
9543 if (drv_ctx.ptr_outputbuffer) {
9544 free (drv_ctx.ptr_outputbuffer);
9545 drv_ctx.ptr_outputbuffer = NULL;
9546 }
9547 #ifdef USE_ION
9548 if (drv_ctx.op_buf_ion_info) {
9549 DEBUG_PRINT_LOW("Free o/p ion context");
9550 free(drv_ctx.op_buf_ion_info);
9551 drv_ctx.op_buf_ion_info = NULL;
9552 }
9553 #endif
9554 buf_ref_remove();
9555 }
9556
free_input_buffer_header()9557 void omx_vdec::free_input_buffer_header()
9558 {
9559 input_use_buffer = false;
9560 if (arbitrary_bytes) {
9561 if (m_inp_heap_ptr) {
9562 DEBUG_PRINT_LOW("Free input Heap Pointer");
9563 free (m_inp_heap_ptr);
9564 m_inp_heap_ptr = NULL;
9565 }
9566
9567 if (m_phdr_pmem_ptr) {
9568 DEBUG_PRINT_LOW("Free input pmem header Pointer");
9569 free (m_phdr_pmem_ptr);
9570 m_phdr_pmem_ptr = NULL;
9571 }
9572 }
9573 if (m_inp_mem_ptr) {
9574 DEBUG_PRINT_LOW("Free input pmem Pointer area");
9575 free (m_inp_mem_ptr);
9576 m_inp_mem_ptr = NULL;
9577 }
9578 /* We just freed all the buffer headers, every thing in m_input_free_q,
9579 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
9580 while (m_input_free_q.m_size) {
9581 unsigned long address, p2, id;
9582 m_input_free_q.pop_entry(&address, &p2, &id);
9583 }
9584 while (m_input_pending_q.m_size) {
9585 unsigned long address, p2, id;
9586 m_input_pending_q.pop_entry(&address, &p2, &id);
9587 }
9588 pdest_frame = NULL;
9589 psource_frame = NULL;
9590 if (drv_ctx.ptr_inputbuffer) {
9591 DEBUG_PRINT_LOW("Free Driver Context pointer");
9592 free (drv_ctx.ptr_inputbuffer);
9593 drv_ctx.ptr_inputbuffer = NULL;
9594 }
9595 #ifdef USE_ION
9596 if (drv_ctx.ip_buf_ion_info) {
9597 DEBUG_PRINT_LOW("Free ion context");
9598 free(drv_ctx.ip_buf_ion_info);
9599 drv_ctx.ip_buf_ion_info = NULL;
9600 }
9601 #endif
9602 }
9603
stream_off(OMX_U32 port)9604 int omx_vdec::stream_off(OMX_U32 port)
9605 {
9606 enum v4l2_buf_type btype;
9607 int rc = 0;
9608 enum v4l2_ports v4l2_port = OUTPUT_PORT;
9609
9610 if (port == OMX_CORE_INPUT_PORT_INDEX) {
9611 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9612 v4l2_port = OUTPUT_PORT;
9613 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
9614 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9615 v4l2_port = CAPTURE_PORT;
9616 } else if (port == OMX_ALL) {
9617 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
9618 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
9619
9620 if (!rc_input)
9621 return rc_input;
9622 else
9623 return rc_output;
9624 }
9625
9626 if (!streaming[v4l2_port]) {
9627 // already streamed off, warn and move on
9628 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
9629 " which is already streamed off", v4l2_port);
9630 return 0;
9631 }
9632
9633 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
9634
9635 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
9636 if (rc) {
9637 /*TODO: How to handle this case */
9638 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
9639 } else {
9640 streaming[v4l2_port] = false;
9641 }
9642
9643 return rc;
9644 }
9645
get_buffer_req(vdec_allocatorproperty * buffer_prop)9646 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
9647 {
9648 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9649 struct v4l2_requestbuffers bufreq;
9650 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
9651 unsigned int final_extra_data_size = 0;
9652 struct v4l2_format fmt;
9653 int ret = 0;
9654 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9655 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9656 bufreq.memory = V4L2_MEMORY_USERPTR;
9657 bufreq.count = 1;
9658 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9659 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9660 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9661 fmt.fmt.pix_mp.pixelformat = output_capability;
9662 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9663 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9664 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9665 fmt.fmt.pix_mp.pixelformat = capture_capability;
9666 } else {
9667 eRet = OMX_ErrorBadParameter;
9668 }
9669 if (eRet==OMX_ErrorNone) {
9670 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9671 }
9672 if (ret) {
9673 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9674 /*TODO: How to handle this case */
9675 eRet = OMX_ErrorInsufficientResources;
9676 return eRet;
9677 } else {
9678 buffer_prop->actualcount = bufreq.count;
9679 buffer_prop->mincount = bufreq.count;
9680 DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
9681 }
9682 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
9683 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9684
9685 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9686 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9687
9688 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9689
9690 update_resolution(fmt.fmt.pix_mp.width,
9691 fmt.fmt.pix_mp.height,
9692 fmt.fmt.pix_mp.plane_fmt[0].bytesperline,
9693 fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
9694 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
9695 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
9696 DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
9697
9698 if (ret) {
9699 /*TODO: How to handle this case */
9700 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
9701 eRet = OMX_ErrorInsufficientResources;
9702 } else {
9703 int extra_idx = 0;
9704
9705 eRet = is_video_session_supported();
9706 if (eRet)
9707 return eRet;
9708
9709 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
9710 buf_size = buffer_prop->buffer_size;
9711 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
9712 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
9713 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
9714 } else if (extra_idx >= VIDEO_MAX_PLANES) {
9715 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
9716 return OMX_ErrorBadParameter;
9717 }
9718
9719 default_extra_data_size = VENUS_EXTRADATA_SIZE(
9720 drv_ctx.video_resolution.frame_height,
9721 drv_ctx.video_resolution.frame_width);
9722 final_extra_data_size = extra_data_size > default_extra_data_size ?
9723 extra_data_size : default_extra_data_size;
9724
9725 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
9726 (~(buffer_prop->alignment - 1));
9727
9728 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
9729 drv_ctx.extradata_info.count = buffer_prop->actualcount;
9730 drv_ctx.extradata_info.buffer_size = final_extra_data_size;
9731 if (!secure_mode)
9732 buf_size += final_extra_data_size;
9733 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9734 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
9735 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
9736 if (extra_data_size)
9737 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
9738 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
9739
9740 if (in_reconfig) // BufReq will be set to driver when port is disabled
9741 buffer_prop->buffer_size = buf_size;
9742 else if (buf_size != buffer_prop->buffer_size) {
9743 buffer_prop->buffer_size = buf_size;
9744 eRet = set_buffer_req(buffer_prop);
9745 }
9746 }
9747 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
9748 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9749 return eRet;
9750 }
9751
set_buffer_req(vdec_allocatorproperty * buffer_prop)9752 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
9753 {
9754 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9755 unsigned buf_size = 0;
9756 struct v4l2_format fmt;
9757 struct v4l2_requestbuffers bufreq;
9758 int ret;
9759 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
9760 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
9761 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
9762 if (buf_size != buffer_prop->buffer_size) {
9763 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
9764 (unsigned int)buffer_prop->buffer_size, buf_size);
9765 eRet = OMX_ErrorBadParameter;
9766 } else {
9767 memset(&fmt, 0x0, sizeof(struct v4l2_format));
9768 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
9769 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
9770 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
9771
9772 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9773 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9774 fmt.fmt.pix_mp.pixelformat = output_capability;
9775 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9776 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9777 fmt.fmt.pix_mp.pixelformat = capture_capability;
9778 } else {
9779 eRet = OMX_ErrorBadParameter;
9780 }
9781
9782 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
9783 if (ret) {
9784 /*TODO: How to handle this case */
9785 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
9786 eRet = OMX_ErrorInsufficientResources;
9787 }
9788
9789 bufreq.memory = V4L2_MEMORY_USERPTR;
9790 bufreq.count = buffer_prop->actualcount;
9791 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
9792 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9793 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
9794 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9795 } else {
9796 eRet = OMX_ErrorBadParameter;
9797 }
9798
9799 if (eRet==OMX_ErrorNone) {
9800 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
9801 }
9802
9803 if (ret) {
9804 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
9805 /*TODO: How to handle this case */
9806 eRet = OMX_ErrorInsufficientResources;
9807 } else if (bufreq.count < buffer_prop->actualcount) {
9808 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
9809 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
9810 buffer_prop->actualcount, bufreq.count);
9811 eRet = OMX_ErrorInsufficientResources;
9812 } else {
9813 if (!client_buffers.update_buffer_req()) {
9814 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
9815 eRet = OMX_ErrorInsufficientResources;
9816 }
9817 }
9818 }
9819 return eRet;
9820 }
9821
update_picture_resolution()9822 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
9823 {
9824 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9825 return eRet;
9826 }
9827
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)9828 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
9829 {
9830 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9831 struct v4l2_format fmt;
9832 if (!portDefn) {
9833 return OMX_ErrorBadParameter;
9834 }
9835 DEBUG_PRINT_LOW("omx_vdec::update_portdef");
9836 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
9837 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
9838 portDefn->eDomain = OMX_PortDomainVideo;
9839 if (drv_ctx.frame_rate.fps_denominator > 0)
9840 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
9841 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
9842 else {
9843 DEBUG_PRINT_ERROR("Error: Divide by zero");
9844 return OMX_ErrorBadParameter;
9845 }
9846 memset(&fmt, 0x0, sizeof(struct v4l2_format));
9847 if (0 == portDefn->nPortIndex) {
9848 portDefn->eDir = OMX_DirInput;
9849 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
9850 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
9851 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
9852 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
9853 portDefn->format.video.eCompressionFormat = eCompressionFormat;
9854 portDefn->bEnabled = m_inp_bEnabled;
9855 portDefn->bPopulated = m_inp_bPopulated;
9856
9857 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
9858 fmt.fmt.pix_mp.pixelformat = output_capability;
9859 } else if (1 == portDefn->nPortIndex) {
9860 unsigned int buf_size = 0;
9861 if (!client_buffers.update_buffer_req()) {
9862 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
9863 return OMX_ErrorHardware;
9864 }
9865 if (!client_buffers.get_buffer_req(buf_size)) {
9866 DEBUG_PRINT_ERROR("update buffer requirements");
9867 return OMX_ErrorHardware;
9868 }
9869 portDefn->nBufferSize = buf_size;
9870 portDefn->eDir = OMX_DirOutput;
9871 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
9872 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
9873 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
9874 portDefn->bEnabled = m_out_bEnabled;
9875 portDefn->bPopulated = m_out_bPopulated;
9876 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
9877 DEBUG_PRINT_ERROR("Error in getting color format");
9878 return OMX_ErrorHardware;
9879 }
9880 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
9881 fmt.fmt.pix_mp.pixelformat = capture_capability;
9882 } else {
9883 portDefn->eDir = OMX_DirMax;
9884 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
9885 (int)portDefn->nPortIndex);
9886 eRet = OMX_ErrorBadPortIndex;
9887 }
9888 if (is_down_scalar_enabled) {
9889 int ret = 0;
9890 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
9891 if (ret) {
9892 DEBUG_PRINT_ERROR("update_portdef : Error in getting port resolution");
9893 return OMX_ErrorHardware;
9894 } else {
9895 portDefn->format.video.nFrameWidth = fmt.fmt.pix_mp.width;
9896 portDefn->format.video.nFrameHeight = fmt.fmt.pix_mp.height;
9897 portDefn->format.video.nStride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
9898 portDefn->format.video.nSliceHeight = fmt.fmt.pix_mp.plane_fmt[0].reserved[0];
9899 }
9900 } else {
9901 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
9902 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
9903 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
9904 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
9905 }
9906
9907 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
9908 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
9909 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
9910 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
9911 }
9912 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
9913 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
9914 (unsigned int)portDefn->nPortIndex,
9915 (unsigned int)portDefn->format.video.nFrameWidth,
9916 (unsigned int)portDefn->format.video.nFrameHeight,
9917 (int)portDefn->format.video.nStride,
9918 (unsigned int)portDefn->format.video.nSliceHeight,
9919 (unsigned int)portDefn->format.video.eColorFormat,
9920 (unsigned int)portDefn->nBufferSize,
9921 (unsigned int)portDefn->nBufferCountActual);
9922
9923 return eRet;
9924 }
9925
allocate_output_headers()9926 OMX_ERRORTYPE omx_vdec::allocate_output_headers()
9927 {
9928 OMX_ERRORTYPE eRet = OMX_ErrorNone;
9929 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
9930 unsigned i= 0;
9931
9932 if (!m_out_mem_ptr) {
9933 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
9934 int nBufHdrSize = 0;
9935 int nPlatformEntrySize = 0;
9936 int nPlatformListSize = 0;
9937 int nPMEMInfoSize = 0;
9938 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
9939 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
9940 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
9941
9942 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
9943 drv_ctx.op_buf.actualcount);
9944 nBufHdrSize = drv_ctx.op_buf.actualcount *
9945 sizeof(OMX_BUFFERHEADERTYPE);
9946
9947 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
9948 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
9949 nPlatformListSize = drv_ctx.op_buf.actualcount *
9950 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
9951 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
9952 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
9953
9954 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
9955 (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
9956 nPMEMInfoSize,
9957 nPlatformListSize);
9958 DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
9959 m_out_bm_count);
9960 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
9961 // Alloc mem for platform specific info
9962 char *pPtr=NULL;
9963 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
9964 nPMEMInfoSize,1);
9965 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
9966 calloc (sizeof(struct vdec_bufferpayload),
9967 drv_ctx.op_buf.actualcount);
9968 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
9969 calloc (sizeof (struct vdec_output_frameinfo),
9970 drv_ctx.op_buf.actualcount);
9971 if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
9972 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
9973 return OMX_ErrorInsufficientResources;
9974 }
9975
9976 #ifdef USE_ION
9977 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
9978 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
9979 if (!drv_ctx.op_buf_ion_info) {
9980 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
9981 return OMX_ErrorInsufficientResources;
9982 }
9983 #endif
9984 if (dynamic_buf_mode) {
9985 out_dynamic_list = (struct dynamic_buf_list *) \
9986 calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
9987 if (out_dynamic_list) {
9988 for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
9989 out_dynamic_list[i].dup_fd = -1;
9990 }
9991 }
9992
9993 if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
9994 && drv_ctx.ptr_respbuffer) {
9995 bufHdr = m_out_mem_ptr;
9996 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
9997 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
9998 (((char *) m_platform_list) + nPlatformListSize);
9999 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10000 (((char *) m_platform_entry) + nPlatformEntrySize);
10001 pPlatformList = m_platform_list;
10002 pPlatformEntry = m_platform_entry;
10003 pPMEMInfo = m_pmem_info;
10004
10005 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
10006
10007 // Settting the entire storage nicely
10008 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10009 m_out_mem_ptr,pPlatformEntry);
10010 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10011 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10012 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
10013 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
10014 // Set the values when we determine the right HxW param
10015 bufHdr->nAllocLen = 0;
10016 bufHdr->nFilledLen = 0;
10017 bufHdr->pAppPrivate = NULL;
10018 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10019 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10020 pPlatformEntry->entry = pPMEMInfo;
10021 // Initialize the Platform List
10022 pPlatformList->nEntries = 1;
10023 pPlatformList->entryList = pPlatformEntry;
10024 // Keep pBuffer NULL till vdec is opened
10025 bufHdr->pBuffer = NULL;
10026 pPMEMInfo->offset = 0;
10027 pPMEMInfo->pmem_fd = -1;
10028 bufHdr->pPlatformPrivate = pPlatformList;
10029 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
10030 #ifdef USE_ION
10031 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
10032 #endif
10033 /*Create a mapping between buffers*/
10034 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
10035 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
10036 &drv_ctx.ptr_outputbuffer[i];
10037 // Move the buffer and buffer header pointers
10038 bufHdr++;
10039 pPMEMInfo++;
10040 pPlatformEntry++;
10041 pPlatformList++;
10042 }
10043 } else {
10044 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10045 m_out_mem_ptr, pPtr);
10046 if (m_out_mem_ptr) {
10047 free(m_out_mem_ptr);
10048 m_out_mem_ptr = NULL;
10049 }
10050 if (pPtr) {
10051 free(pPtr);
10052 pPtr = NULL;
10053 }
10054 if (drv_ctx.ptr_outputbuffer) {
10055 free(drv_ctx.ptr_outputbuffer);
10056 drv_ctx.ptr_outputbuffer = NULL;
10057 }
10058 if (drv_ctx.ptr_respbuffer) {
10059 free(drv_ctx.ptr_respbuffer);
10060 drv_ctx.ptr_respbuffer = NULL;
10061 }
10062 #ifdef USE_ION
10063 if (drv_ctx.op_buf_ion_info) {
10064 DEBUG_PRINT_LOW("Free o/p ion context");
10065 free(drv_ctx.op_buf_ion_info);
10066 drv_ctx.op_buf_ion_info = NULL;
10067 }
10068 #endif
10069 eRet = OMX_ErrorInsufficientResources;
10070 }
10071 } else {
10072 eRet = OMX_ErrorInsufficientResources;
10073 }
10074 return eRet;
10075 }
10076
complete_pending_buffer_done_cbs()10077 void omx_vdec::complete_pending_buffer_done_cbs()
10078 {
10079 unsigned long p1, p2, ident;
10080 omx_cmd_queue tmp_q, pending_bd_q;
10081 pthread_mutex_lock(&m_lock);
10082 // pop all pending GENERATE FDB from ftb queue
10083 while (m_ftb_q.m_size) {
10084 m_ftb_q.pop_entry(&p1,&p2,&ident);
10085 if (ident == OMX_COMPONENT_GENERATE_FBD) {
10086 pending_bd_q.insert_entry(p1,p2,ident);
10087 } else {
10088 tmp_q.insert_entry(p1,p2,ident);
10089 }
10090 }
10091 //return all non GENERATE FDB to ftb queue
10092 while (tmp_q.m_size) {
10093 tmp_q.pop_entry(&p1,&p2,&ident);
10094 m_ftb_q.insert_entry(p1,p2,ident);
10095 }
10096 // pop all pending GENERATE EDB from etb queue
10097 while (m_etb_q.m_size) {
10098 m_etb_q.pop_entry(&p1,&p2,&ident);
10099 if (ident == OMX_COMPONENT_GENERATE_EBD) {
10100 pending_bd_q.insert_entry(p1,p2,ident);
10101 } else {
10102 tmp_q.insert_entry(p1,p2,ident);
10103 }
10104 }
10105 //return all non GENERATE FDB to etb queue
10106 while (tmp_q.m_size) {
10107 tmp_q.pop_entry(&p1,&p2,&ident);
10108 m_etb_q.insert_entry(p1,p2,ident);
10109 }
10110 pthread_mutex_unlock(&m_lock);
10111 // process all pending buffer dones
10112 while (pending_bd_q.m_size) {
10113 pending_bd_q.pop_entry(&p1,&p2,&ident);
10114 switch (ident) {
10115 case OMX_COMPONENT_GENERATE_EBD:
10116 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10117 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10118 omx_report_error ();
10119 }
10120 break;
10121
10122 case OMX_COMPONENT_GENERATE_FBD:
10123 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10124 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10125 omx_report_error ();
10126 }
10127 break;
10128 }
10129 }
10130 }
10131
set_frame_rate(OMX_S64 act_timestamp)10132 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10133 {
10134 OMX_U32 new_frame_interval = 0;
10135 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10136 && llabs(act_timestamp - prev_ts) > 2000) {
10137 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10138 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10139 if (new_frame_interval != frm_int || frm_int == 0) {
10140 frm_int = new_frame_interval;
10141 if (frm_int) {
10142 drv_ctx.frame_rate.fps_numerator = 1e6;
10143 drv_ctx.frame_rate.fps_denominator = frm_int;
10144 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10145 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10146 (float)drv_ctx.frame_rate.fps_denominator);
10147 m_perf_control.request_cores(frm_int);
10148 /* We need to report the difference between this FBD and the previous FBD
10149 * back to the driver for clock scaling purposes. */
10150 struct v4l2_outputparm oparm;
10151 /*XXX: we're providing timing info as seconds per frame rather than frames
10152 * per second.*/
10153 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10154 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10155
10156 struct v4l2_streamparm sparm;
10157 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10158 sparm.parm.output = oparm;
10159 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10160 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10161 performance might be affected");
10162 }
10163
10164 }
10165 }
10166 }
10167 prev_ts = act_timestamp;
10168 }
10169
adjust_timestamp(OMX_S64 & act_timestamp)10170 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10171 {
10172 if (rst_prev_ts && VALID_TS(act_timestamp)) {
10173 prev_ts = act_timestamp;
10174 prev_ts_actual = act_timestamp;
10175 rst_prev_ts = false;
10176 } else if (VALID_TS(prev_ts)) {
10177 bool codec_cond = (drv_ctx.timestamp_adjust)?
10178 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10179 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10180 prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10181 if (frm_int > 0 && codec_cond) {
10182 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10183 act_timestamp = prev_ts + frm_int;
10184 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10185 prev_ts = act_timestamp;
10186 } else {
10187 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10188 // ensure that timestamps can never step backwards when in display order
10189 act_timestamp = prev_ts;
10190 }
10191 set_frame_rate(act_timestamp);
10192 }
10193 } else if (frm_int > 0) // In this case the frame rate was set along
10194 { // with the port definition, start ts with 0
10195 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
10196 rst_prev_ts = true;
10197 }
10198 }
10199
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorSpace_t * color_space,ColorAspects * aspects)10200 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10201 OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
10202 {
10203 switch (primaries) {
10204 case MSM_VIDC_BT709_5:
10205 *color_space = ITU_R_709;
10206 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10207 break;
10208 case MSM_VIDC_BT470_6_M:
10209 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10210 break;
10211 case MSM_VIDC_BT601_6_625:
10212 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10213 break;
10214 case MSM_VIDC_BT601_6_525:
10215 *color_space = range ? ITU_R_601_FR : ITU_R_601;
10216 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10217 break;
10218 case MSM_VIDC_GENERIC_FILM:
10219 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10220 break;
10221 case MSM_VIDC_BT2020:
10222 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10223 break;
10224 case MSM_VIDC_UNSPECIFIED:
10225 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10226 default:
10227 //aspects->mPrimaries = ColorAspects::PrimariesOther;
10228 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10229 break;
10230 }
10231
10232 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10233
10234 switch (transfer) {
10235 case MSM_VIDC_TRANSFER_BT709_5:
10236 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10237 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10238 break;
10239 case MSM_VIDC_TRANSFER_BT_470_6_M:
10240 aspects->mTransfer = ColorAspects::TransferGamma22;
10241 break;
10242 case MSM_VIDC_TRANSFER_BT_470_6_BG:
10243 aspects->mTransfer = ColorAspects::TransferGamma28;
10244 break;
10245 case MSM_VIDC_TRANSFER_SMPTE_240M:
10246 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10247 break;
10248 case MSM_VIDC_TRANSFER_LINEAR:
10249 aspects->mTransfer = ColorAspects::TransferLinear;
10250 break;
10251 case MSM_VIDC_TRANSFER_IEC_61966:
10252 aspects->mTransfer = ColorAspects::TransferXvYCC;
10253 break;
10254 case MSM_VIDC_TRANSFER_BT_1361:
10255 aspects->mTransfer = ColorAspects::TransferBT1361;
10256 break;
10257 case MSM_VIDC_TRANSFER_SRGB:
10258 aspects->mTransfer = ColorAspects::TransferSRGB;
10259 break;
10260 default:
10261 //aspects->mTransfer = ColorAspects::TransferOther;
10262 aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10263 break;
10264 }
10265
10266 switch (matrix) {
10267 case MSM_VIDC_MATRIX_BT_709_5:
10268 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10269 break;
10270 case MSM_VIDC_MATRIX_FCC_47:
10271 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10272 break;
10273 case MSM_VIDC_MATRIX_601_6_625:
10274 case MSM_VIDC_MATRIX_601_6_525:
10275 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10276 break;
10277 case MSM_VIDC_MATRIX_SMPTE_240M:
10278 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10279 break;
10280 case MSM_VIDC_MATRIX_BT_2020:
10281 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10282 break;
10283 case MSM_VIDC_MATRIX_BT_2020_CONST:
10284 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10285 break;
10286 default:
10287 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10288 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10289 break;
10290 }
10291 }
10292
print_debug_color_aspects(ColorAspects * aspects,const char * prefix)10293 void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
10294 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
10295 prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
10296 }
10297
handle_color_space_info(void * data,unsigned int buf_index)10298 void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
10299 {
10300 ColorSpace_t color_space = ITU_R_601;
10301 ColorAspects tempAspects;
10302 memset(&tempAspects, 0x0, sizeof(ColorAspects));
10303 ColorAspects *aspects = &tempAspects;
10304
10305 switch(output_capability) {
10306 case V4L2_PIX_FMT_MPEG2:
10307 {
10308 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10309 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10310
10311 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10312 * understand this code */
10313
10314 if (seqdisp_payload && seqdisp_payload->color_descp) {
10315
10316 convert_color_space_info(seqdisp_payload->color_primaries, 1,
10317 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10318 &color_space,aspects);
10319 m_disp_hor_size = seqdisp_payload->disp_width;
10320 m_disp_vert_size = seqdisp_payload->disp_height;
10321 }
10322 }
10323 break;
10324 case V4L2_PIX_FMT_H264:
10325 case V4L2_PIX_FMT_HEVC:
10326 {
10327 struct msm_vidc_vui_display_info_payload *display_info_payload;
10328 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10329
10330 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10331
10332 if (display_info_payload->video_signal_present_flag &&
10333 display_info_payload->color_description_present_flag) {
10334 convert_color_space_info(display_info_payload->color_primaries,
10335 display_info_payload->video_full_range_flag,
10336 display_info_payload->transfer_characteristics,
10337 display_info_payload->matrix_coefficients,
10338 &color_space,aspects);
10339 }
10340 }
10341 break;
10342 case V4L2_PIX_FMT_VC1_ANNEX_G:
10343 case V4L2_PIX_FMT_VC1_ANNEX_L:
10344 {
10345 struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
10346 vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
10347
10348 /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
10349 * SMPTE 421M to understand this code */
10350
10351 if (m_enable_android_native_buffers &&
10352 vc1_seq_disp_payload->color_primaries) {
10353
10354 convert_color_space_info(vc1_seq_disp_payload->color_primaries,
10355 1,
10356 vc1_seq_disp_payload->transfer_char,
10357 vc1_seq_disp_payload->matrix_coeffs,
10358 &color_space,aspects);
10359 }
10360 }
10361 break;
10362 case V4L2_PIX_FMT_VP8:
10363 {
10364 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10365 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10366
10367 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10368 * to understand this code */
10369
10370 if (vpx_color_space_payload->color_space == 0) {
10371 color_space = ITU_R_601;
10372 } else {
10373 DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10374 break;
10375 }
10376 }
10377 break;
10378 case V4L2_PIX_FMT_VP9:
10379 {
10380 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10381 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10382
10383 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10384 * to understand this code */
10385
10386 switch(vpx_color_space_payload->color_space) {
10387 case MSM_VIDC_CS_BT_601:
10388 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10389 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10390 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10391 aspects->mRange = m_client_color_space.sAspects.mRange;
10392 break;
10393 case MSM_VIDC_CS_BT_709:
10394 color_space = ITU_R_709;
10395 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10396 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10397 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10398 aspects->mRange = m_client_color_space.sAspects.mRange;
10399 break;
10400 case MSM_VIDC_CS_SMPTE_170:
10401 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10402 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10403 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10404 aspects->mRange = m_client_color_space.sAspects.mRange;
10405 break;
10406 case MSM_VIDC_CS_SMPTE_240:
10407 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10408 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10409 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10410 aspects->mRange = m_client_color_space.sAspects.mRange;
10411 break;
10412 case MSM_VIDC_CS_BT_2020:
10413 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10414 aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
10415 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10416 aspects->mRange = m_client_color_space.sAspects.mRange;
10417 break;
10418 case MSM_VIDC_CS_RESERVED:
10419 aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10420 aspects->mTransfer = ColorAspects::TransferOther;
10421 aspects->mPrimaries = ColorAspects::PrimariesOther;
10422 aspects->mRange = m_client_color_space.sAspects.mRange;
10423 break;
10424 case MSM_VIDC_CS_RGB:
10425 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10426 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10427 aspects->mPrimaries = ColorAspects::PrimariesOther;
10428 aspects->mRange = m_client_color_space.sAspects.mRange;
10429 break;
10430 default:
10431 break;
10432 }
10433 }
10434 break;
10435 default:
10436 break;
10437 }
10438 if (m_enable_android_native_buffers) {
10439 DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
10440 set_colorspace_in_handle(color_space, buf_index);
10441 }
10442 print_debug_color_aspects(aspects, "Bitstream");
10443
10444 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
10445 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
10446 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
10447 m_internal_color_space.sAspects.mRange != aspects->mRange) {
10448 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
10449 m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
10450
10451 DEBUG_PRINT_HIGH("Initiating PORT Reconfig");
10452 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
10453 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
10454
10455 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
10456 OMX_QTIIndexConfigDescribeColorAspects,
10457 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
10458 }
10459 }
10460
set_colorspace_in_handle(ColorSpace_t color_space,unsigned int buf_index)10461 void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
10462 private_handle_t *private_handle = NULL;
10463 if (buf_index < drv_ctx.op_buf.actualcount &&
10464 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
10465 native_buffer[buf_index].privatehandle) {
10466 private_handle = native_buffer[buf_index].privatehandle;
10467 }
10468 if (private_handle) {
10469 setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
10470 }
10471 }
10472
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)10473 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
10474 {
10475 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
10476 OMX_U32 num_conceal_MB = 0;
10477 OMX_TICKS time_stamp = 0;
10478 OMX_U32 frame_rate = 0;
10479 unsigned long consumed_len = 0;
10480 OMX_U32 num_MB_in_frame;
10481 OMX_U32 recovery_sei_flags = 1;
10482 int enable = 0;
10483
10484 int buf_index = p_buf_hdr - m_out_mem_ptr;
10485 if (buf_index >= drv_ctx.extradata_info.count) {
10486 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
10487 buf_index, drv_ctx.extradata_info.count);
10488 return;
10489 }
10490 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
10491
10492 if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
10493 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
10494 return;
10495 }
10496
10497 OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
10498 p_buf_hdr->nOffset;
10499
10500 if (!drv_ctx.extradata_info.uaddr) {
10501 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
10502 return;
10503 }
10504 if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
10505 DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
10506 p_extra = NULL;
10507 return;
10508 }
10509 if (!secure_mode)
10510 p_extra = (OMX_OTHER_EXTRADATATYPE *)
10511 ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
10512 else
10513 p_extra = m_other_extradata;
10514 char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
10515
10516 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10517 p_extra = NULL;
10518 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10519 return;
10520 }
10521 OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
10522 if (data && p_extra) {
10523 while ((consumed_len < drv_ctx.extradata_info.buffer_size)
10524 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
10525 if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
10526 DEBUG_PRINT_LOW("Invalid extra data size");
10527 break;
10528 }
10529
10530 if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
10531 p_extra = NULL;
10532 DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
10533 return;
10534 }
10535
10536 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
10537 switch ((unsigned long)data->eType) {
10538 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
10539 struct msm_vidc_interlace_payload *payload;
10540 OMX_U32 interlace_color_format;
10541 payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
10542 if (payload) {
10543 enable = 1;
10544 switch (payload->format) {
10545 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
10546 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
10547 enable = 0;
10548 break;
10549 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
10550 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10551 break;
10552 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
10553 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
10554 break;
10555 default:
10556 DEBUG_PRINT_LOW("default case - set interlace to topfield");
10557 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
10558 }
10559 switch (payload->color_format) {
10560 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
10561 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10562 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
10563 break;
10564 case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
10565 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
10566 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
10567 break;
10568 default:
10569 interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
10570 DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
10571 }
10572 }
10573
10574 if (m_enable_android_native_buffers) {
10575 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
10576 payload->format, interlace_color_format ,enable,
10577 (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
10578
10579 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10580 PP_PARAM_INTERLACED, (void*)&enable);
10581
10582 if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
10583 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
10584 LINEAR_FORMAT, (void*)&interlace_color_format);
10585 }
10586 }
10587 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
10588 append_interlace_extradata(p_extra, payload->format,
10589 p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF);
10590 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10591 }
10592 break;
10593 case MSM_VIDC_EXTRADATA_FRAME_RATE:
10594 struct msm_vidc_framerate_payload *frame_rate_payload;
10595 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
10596 frame_rate = frame_rate_payload->frame_rate;
10597 break;
10598 case MSM_VIDC_EXTRADATA_TIMESTAMP:
10599 struct msm_vidc_ts_payload *time_stamp_payload;
10600 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
10601 time_stamp = time_stamp_payload->timestamp_lo;
10602 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
10603 p_buf_hdr->nTimeStamp = time_stamp;
10604 break;
10605 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
10606 struct msm_vidc_concealmb_payload *conceal_mb_payload;
10607 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
10608 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10609 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10610 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
10611 break;
10612 case MSM_VIDC_EXTRADATA_INDEX:
10613 int *etype;
10614 etype = (int *)(void *)data->data;
10615 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
10616 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
10617 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
10618 if (aspect_ratio_payload) {
10619 ((struct vdec_output_frameinfo *)
10620 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
10621 ((struct vdec_output_frameinfo *)
10622 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
10623 }
10624 }
10625 break;
10626 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
10627 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
10628 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
10629 recovery_sei_flags = recovery_sei_payload->flags;
10630 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
10631 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
10632 DEBUG_PRINT_HIGH("***************************************************");
10633 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
10634 DEBUG_PRINT_HIGH("***************************************************");
10635 }
10636 break;
10637 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
10638 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
10639 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
10640 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
10641 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
10642 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
10643 return;
10644 }
10645 break;
10646 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
10647 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
10648 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
10649 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
10650 handle_color_space_info((void *)data->data, buf_index);
10651 break;
10652 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
10653 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
10654 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
10655 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
10656 append_framepack_extradata(p_extra, s3d_frame_packing_payload);
10657 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10658 }
10659 break;
10660 case MSM_VIDC_EXTRADATA_FRAME_QP:
10661 struct msm_vidc_frame_qp_payload *qp_payload;
10662 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
10663 if (client_extradata & OMX_QP_EXTRADATA) {
10664 append_qp_extradata(p_extra, qp_payload);
10665 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10666 }
10667 break;
10668 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
10669 struct msm_vidc_frame_bits_info_payload *bits_info_payload;
10670 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
10671 if (client_extradata & OMX_BITSINFO_EXTRADATA) {
10672 append_bitsinfo_extradata(p_extra, bits_info_payload);
10673 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10674 }
10675 break;
10676 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
10677 if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
10678 append_user_extradata(p_extra, data);
10679 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10680 }
10681 break;
10682 case MSM_VIDC_EXTRADATA_VQZIP_SEI:
10683 struct msm_vidc_vqzip_sei_payload *vqzip_payload;
10684 vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
10685 if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
10686 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10687 append_vqzip_extradata(p_extra, vqzip_payload);
10688 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10689 }
10690 break;
10691 default:
10692 DEBUG_PRINT_LOW("Unrecognized extradata");
10693 goto unrecognized_extradata;
10694 }
10695 consumed_len += data->nSize;
10696 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
10697 }
10698 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
10699 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10700 append_frame_info_extradata(p_extra,
10701 num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
10702 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
10703 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
10704 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10705 }
10706 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
10707 append_frame_dimension_extradata(p_extra);
10708 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
10709 }
10710 }
10711 unrecognized_extradata:
10712 if (client_extradata && p_extra) {
10713 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
10714 append_terminator_extradata(p_extra);
10715 }
10716 if (secure_mode && p_extradata && m_other_extradata) {
10717 struct vdec_output_frameinfo *ptr_extradatabuff = NULL;
10718 memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
10719 ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
10720 ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
10721 ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
10722 }
10723 return;
10724 }
10725
enable_extradata(OMX_U32 requested_extradata,bool is_internal,bool enable)10726 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
10727 bool is_internal, bool enable)
10728 {
10729 OMX_ERRORTYPE ret = OMX_ErrorNone;
10730 struct v4l2_control control;
10731 if (m_state != OMX_StateLoaded) {
10732 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
10733 return OMX_ErrorIncorrectStateOperation;
10734 }
10735 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
10736 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
10737
10738 if (!is_internal) {
10739 if (enable)
10740 client_extradata |= requested_extradata;
10741 else
10742 client_extradata = client_extradata & ~requested_extradata;
10743 }
10744
10745 if (enable) {
10746 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
10747 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10748 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
10749 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10750 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
10751 " Quality of interlaced clips might be impacted.");
10752 }
10753 }
10754 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
10755 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10756 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
10757 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10758 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
10759 }
10760 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10761 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
10762 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10763 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
10764 }
10765 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10766 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
10767 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10768 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
10769 }
10770 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10771 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
10772 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10773 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10774 }
10775 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10776 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
10777 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10778 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10779 }
10780 if (output_capability == V4L2_PIX_FMT_MPEG2) {
10781 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10782 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10783 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10784 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
10785 }
10786 }
10787 }
10788 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
10789 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10790 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
10791 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10792 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
10793 }
10794 }
10795 if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
10796 if (output_capability == V4L2_PIX_FMT_H264) {
10797 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
10798 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10799 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
10800 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10801 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
10802 }
10803 } else {
10804 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
10805 }
10806 }
10807 if (requested_extradata & OMX_QP_EXTRADATA) {
10808 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10809 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10810 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10811 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10812 }
10813 }
10814 if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
10815 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10816 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
10817 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10818 DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
10819 }
10820 }
10821 if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
10822 if (secure_mode) {
10823 DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions");
10824 return OMX_ErrorUnsupportedSetting;
10825 }
10826 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10827 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
10828 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10829 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
10830 }
10831 }
10832 if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
10833 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10834 control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
10835 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10836 DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
10837 }
10838 client_extradata |= OMX_VQZIPSEI_EXTRADATA;
10839
10840 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10841 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
10842 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10843 DEBUG_PRINT_HIGH("Failed to set QP extradata");
10844 }
10845 client_extradata |= OMX_QP_EXTRADATA;
10846 }
10847 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
10848 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
10849 switch(output_capability) {
10850 case V4L2_PIX_FMT_H264:
10851 case V4L2_PIX_FMT_HEVC:
10852 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
10853 break;
10854 case CODEC_TYPE_MPEG2:
10855 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
10856 break;
10857 case V4L2_PIX_FMT_VP8:
10858 case V4L2_PIX_FMT_VP9:
10859 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
10860 break;
10861 case V4L2_PIX_FMT_VC1_ANNEX_G:
10862 case V4L2_PIX_FMT_VC1_ANNEX_L:
10863 control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
10864 break;
10865 default:
10866 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
10867 return ret;
10868 }
10869
10870 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
10871 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
10872 }
10873 }
10874 }
10875 ret = get_buffer_req(&drv_ctx.op_buf);
10876 return ret;
10877 }
10878
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)10879 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10880 {
10881 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
10882 OMX_U8 *data_ptr = extra->data, data = 0;
10883 while (byte_count < extra->nDataSize) {
10884 data = *data_ptr;
10885 while (data) {
10886 num_MB += (data&0x01);
10887 data >>= 1;
10888 }
10889 data_ptr++;
10890 byte_count++;
10891 }
10892 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
10893 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
10894 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
10895 }
10896
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)10897 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
10898 {
10899 if (!m_debug_extradata || !extra)
10900 return;
10901
10902
10903 DEBUG_PRINT_HIGH(
10904 "============== Extra Data ==============\n"
10905 " Size: %u\n"
10906 " Version: %u\n"
10907 " PortIndex: %u\n"
10908 " Type: %x\n"
10909 " DataSize: %u",
10910 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
10911 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
10912
10913 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
10914 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
10915 DEBUG_PRINT_HIGH(
10916 "------ Interlace Format ------\n"
10917 " Size: %u\n"
10918 " Version: %u\n"
10919 " PortIndex: %u\n"
10920 " Is Interlace Format: %d\n"
10921 " Interlace Formats: %u\n"
10922 "=========== End of Interlace ===========",
10923 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
10924 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
10925 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
10926 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
10927
10928 DEBUG_PRINT_HIGH(
10929 "-------- Frame Format --------\n"
10930 " Picture Type: %d\n"
10931 " Interlace Type: %d\n"
10932 " Pan Scan Total Frame Num: %u\n"
10933 " Concealed Macro Blocks: %u\n"
10934 " frame rate: %u\n"
10935 " Time Stamp: %llu\n"
10936 " Aspect Ratio X: %u\n"
10937 " Aspect Ratio Y: %u",
10938 fminfo->ePicType,
10939 fminfo->interlaceType,
10940 (unsigned int)fminfo->panScan.numWindows,
10941 (unsigned int)fminfo->nConcealedMacroblocks,
10942 (unsigned int)fminfo->nFrameRate,
10943 fminfo->nTimeStamp,
10944 (unsigned int)fminfo->aspectRatio.aspectRatioX,
10945 (unsigned int)fminfo->aspectRatio.aspectRatioY);
10946
10947 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
10948 DEBUG_PRINT_HIGH(
10949 "------------------------------"
10950 " Pan Scan Frame Num: %u\n"
10951 " Rectangle x: %d\n"
10952 " Rectangle y: %d\n"
10953 " Rectangle dx: %d\n"
10954 " Rectangle dy: %d",
10955 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
10956 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
10957 }
10958
10959 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
10960 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
10961 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
10962 DEBUG_PRINT_HIGH(
10963 "------------------ Framepack Format ----------\n"
10964 " id: %u \n"
10965 " cancel_flag: %u \n"
10966 " type: %u \n"
10967 " quincunx_sampling_flagFormat: %u \n"
10968 " content_interpretation_type: %u \n"
10969 " spatial_flipping_flag: %u \n"
10970 " frame0_flipped_flag: %u \n"
10971 " field_views_flag: %u \n"
10972 " current_frame_is_frame0_flag: %u \n"
10973 " frame0_self_contained_flag: %u \n"
10974 " frame1_self_contained_flag: %u \n"
10975 " frame0_grid_position_x: %u \n"
10976 " frame0_grid_position_y: %u \n"
10977 " frame1_grid_position_x: %u \n"
10978 " frame1_grid_position_y: %u \n"
10979 " reserved_byte: %u \n"
10980 " repetition_period: %u \n"
10981 " extension_flag: %u \n"
10982 "================== End of Framepack ===========",
10983 (unsigned int)framepack->id,
10984 (unsigned int)framepack->cancel_flag,
10985 (unsigned int)framepack->type,
10986 (unsigned int)framepack->quincunx_sampling_flag,
10987 (unsigned int)framepack->content_interpretation_type,
10988 (unsigned int)framepack->spatial_flipping_flag,
10989 (unsigned int)framepack->frame0_flipped_flag,
10990 (unsigned int)framepack->field_views_flag,
10991 (unsigned int)framepack->current_frame_is_frame0_flag,
10992 (unsigned int)framepack->frame0_self_contained_flag,
10993 (unsigned int)framepack->frame1_self_contained_flag,
10994 (unsigned int)framepack->frame0_grid_position_x,
10995 (unsigned int)framepack->frame0_grid_position_y,
10996 (unsigned int)framepack->frame1_grid_position_x,
10997 (unsigned int)framepack->frame1_grid_position_y,
10998 (unsigned int)framepack->reserved_byte,
10999 (unsigned int)framepack->repetition_period,
11000 (unsigned int)framepack->extension_flag);
11001 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
11002 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11003 DEBUG_PRINT_HIGH(
11004 "---- QP (Frame quantization parameter) ----\n"
11005 " Frame QP: %u \n"
11006 "================ End of QP ================\n",
11007 (unsigned int)qp->nQP);
11008 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
11009 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
11010 DEBUG_PRINT_HIGH(
11011 "--------- Input bits information --------\n"
11012 " Header bits: %u \n"
11013 " Frame bits: %u \n"
11014 "===== End of Input bits information =====\n",
11015 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
11016 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
11017 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
11018 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
11019 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
11020 OMX_U32 i = 0;
11021 DEBUG_PRINT_HIGH(
11022 "-------------- Userdata -------------\n"
11023 " Stream userdata type: %u\n"
11024 " userdata size: %u\n"
11025 " STREAM_USERDATA:",
11026 (unsigned int)userdata->type, (unsigned int)userdata_size);
11027 for (i = 0; i < userdata_size; i+=4) {
11028 DEBUG_PRINT_HIGH(" %x %x %x %x",
11029 data_ptr[i], data_ptr[i+1],
11030 data_ptr[i+2], data_ptr[i+3]);
11031 }
11032 DEBUG_PRINT_HIGH(
11033 "=========== End of Userdata ===========");
11034 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
11035 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11036 DEBUG_PRINT_HIGH(
11037 "-------------- VQZip -------------\n"
11038 " Size: %u\n",
11039 (unsigned int)vq->nSize);
11040 DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
11041 } else if (extra->eType == OMX_ExtraDataNone) {
11042 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
11043 } else {
11044 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
11045 }
11046 }
11047
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type,bool is_mbaff)11048 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11049 OMX_U32 interlaced_format_type, bool is_mbaff)
11050 {
11051 OMX_STREAMINTERLACEFORMAT *interlace_format;
11052
11053 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
11054 return;
11055 }
11056 if (!extra) {
11057 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
11058 return;
11059 }
11060 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
11061 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11062 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11063 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
11064 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11065 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11066 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11067 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
11068 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11069
11070 if ((interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) && !is_mbaff) {
11071 interlace_format->bInterlaceFormat = OMX_FALSE;
11072 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11073 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11074 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) && !is_mbaff) {
11075 interlace_format->bInterlaceFormat = OMX_TRUE;
11076 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
11077 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11078 } else if ((interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) && !is_mbaff) {
11079 interlace_format->bInterlaceFormat = OMX_TRUE;
11080 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11081 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11082 } else {
11083 interlace_format->bInterlaceFormat = OMX_TRUE;
11084 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
11085 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11086 }
11087 print_debug_extradata(extra);
11088 }
11089
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)11090 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11091 {
11092 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
11093 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
11094 return;
11095 }
11096 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
11097 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11098 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11099 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
11100 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
11101 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
11102 frame_dimension->nDecWidth = rectangle.nLeft;
11103 frame_dimension->nDecHeight = rectangle.nTop;
11104 frame_dimension->nActualWidth = rectangle.nWidth;
11105 frame_dimension->nActualHeight = rectangle.nHeight;
11106 }
11107
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)11108 void omx_vdec::fill_aspect_ratio_info(
11109 struct vdec_aspectratioinfo *aspect_ratio_info,
11110 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
11111 {
11112 m_extradata = frame_info;
11113 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
11114 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
11115 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
11116 (unsigned int)m_extradata->aspectRatio.aspectRatioY);
11117 }
11118
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)11119 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11120 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
11121 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
11122 struct vdec_aspectratioinfo *aspect_ratio_info)
11123 {
11124 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
11125 struct msm_vidc_panscan_window *panscan_window;
11126 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
11127 return;
11128 }
11129 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
11130 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11131 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11132 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
11133 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
11134 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11135 switch (picture_type) {
11136 case PICTURE_TYPE_I:
11137 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
11138 break;
11139 case PICTURE_TYPE_P:
11140 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
11141 break;
11142 case PICTURE_TYPE_B:
11143 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
11144 break;
11145 default:
11146 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
11147 }
11148 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
11149 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
11150 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
11151 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
11152 else
11153 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
11154 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
11155 frame_info->nConcealedMacroblocks = num_conceal_mb;
11156 frame_info->nFrameRate = frame_rate;
11157 frame_info->nTimeStamp = time_stamp;
11158 frame_info->panScan.numWindows = 0;
11159 if (output_capability == V4L2_PIX_FMT_MPEG2) {
11160 if (m_disp_hor_size && m_disp_vert_size) {
11161 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
11162 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
11163 } else {
11164 frame_info->displayAspectRatio.displayHorizontalSize = 0;
11165 frame_info->displayAspectRatio.displayVerticalSize = 0;
11166 }
11167 }
11168
11169 if (panscan_payload) {
11170 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
11171 panscan_window = &panscan_payload->wnd[0];
11172 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
11173 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
11174 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
11175 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
11176 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
11177 panscan_window++;
11178 }
11179 }
11180 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
11181 print_debug_extradata(extra);
11182 }
11183
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)11184 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11185 {
11186 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
11187 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
11188 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11189 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11190 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
11191 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
11192 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
11193 *portDefn = m_port_def;
11194 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
11195 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
11196 (unsigned int)portDefn->format.video.nFrameWidth,
11197 (unsigned int)portDefn->format.video.nStride,
11198 (unsigned int)portDefn->format.video.nSliceHeight);
11199 }
11200
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)11201 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11202 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
11203 {
11204 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
11205 if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
11206 DEBUG_PRINT_ERROR("frame packing size mismatch");
11207 return;
11208 }
11209 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
11210 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11211 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11212 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
11213 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11214 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11215 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
11216 framepack->nVersion.nVersion = OMX_SPEC_VERSION;
11217 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11218 memcpy(&framepack->id, s3d_frame_packing_payload,
11219 sizeof(struct msm_vidc_s3d_frame_packing_payload));
11220 memcpy(&m_frame_pack_arrangement, framepack,
11221 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
11222 print_debug_extradata(extra);
11223 }
11224
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)11225 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11226 struct msm_vidc_frame_qp_payload *qp_payload)
11227 {
11228 OMX_QCOM_EXTRADATA_QP * qp = NULL;
11229 if (!qp_payload) {
11230 DEBUG_PRINT_ERROR("QP payload is NULL");
11231 return;
11232 }
11233 extra->nSize = OMX_QP_EXTRADATA_SIZE;
11234 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11235 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11236 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
11237 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
11238 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11239 qp->nQP = qp_payload->frame_qp;
11240 print_debug_extradata(extra);
11241 }
11242
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)11243 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11244 struct msm_vidc_frame_bits_info_payload *bits_payload)
11245 {
11246 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
11247 if (!bits_payload) {
11248 DEBUG_PRINT_ERROR("bits info payload is NULL");
11249 return;
11250 }
11251 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
11252 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11253 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11254 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
11255 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
11256 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
11257 bits->frame_bits = bits_payload->frame_bits;
11258 bits->header_bits = bits_payload->header_bits;
11259 print_debug_extradata(extra);
11260 }
11261
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)11262 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11263 OMX_OTHER_EXTRADATATYPE *p_user)
11264 {
11265 int userdata_size = 0;
11266 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
11267 userdata_payload =
11268 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
11269 userdata_size = p_user->nDataSize;
11270 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
11271 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11272 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11273 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
11274 extra->nDataSize = userdata_size;
11275 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
11276 memcpy(extra->data, p_user->data, extra->nDataSize);
11277 print_debug_extradata(extra);
11278 }
11279
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)11280 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11281 {
11282 if (!client_extradata) {
11283 return;
11284 }
11285 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
11286 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11287 extra->eType = OMX_ExtraDataNone;
11288 extra->nDataSize = 0;
11289 extra->data[0] = 0;
11290
11291 print_debug_extradata(extra);
11292 }
11293
append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_vqzip_sei_payload * vqzip_payload)11294 void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11295 struct msm_vidc_vqzip_sei_payload *vqzip_payload)
11296 {
11297 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
11298
11299 extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
11300 extra->nVersion.nVersion = OMX_SPEC_VERSION;
11301 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11302 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
11303 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
11304
11305 vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11306 vq->nSize = vqzip_payload->size;
11307 memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
11308
11309 print_debug_extradata(extra);
11310 }
11311
allocate_desc_buffer(OMX_U32 index)11312 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
11313 {
11314 OMX_ERRORTYPE eRet = OMX_ErrorNone;
11315 if (index >= drv_ctx.ip_buf.actualcount) {
11316 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
11317 return OMX_ErrorInsufficientResources;
11318 }
11319 if (m_desc_buffer_ptr == NULL) {
11320 m_desc_buffer_ptr = (desc_buffer_hdr*) \
11321 calloc( (sizeof(desc_buffer_hdr)),
11322 drv_ctx.ip_buf.actualcount);
11323 if (m_desc_buffer_ptr == NULL) {
11324 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
11325 return OMX_ErrorInsufficientResources;
11326 }
11327 }
11328
11329 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
11330 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
11331 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
11332 return OMX_ErrorInsufficientResources;
11333 }
11334
11335 return eRet;
11336 }
11337
insert_demux_addr_offset(OMX_U32 address_offset)11338 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
11339 {
11340 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
11341 if (m_demux_entries < 8192) {
11342 m_demux_offsets[m_demux_entries++] = address_offset;
11343 }
11344 return;
11345 }
11346
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)11347 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
11348 {
11349 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
11350 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
11351 OMX_U32 index = 0;
11352
11353 m_demux_entries = 0;
11354
11355 while (index < bytes_to_parse) {
11356 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11357 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
11358 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
11359 (buf[index+2] == 0x01)) ) {
11360 //Found start code, insert address offset
11361 insert_demux_addr_offset(index);
11362 if (buf[index+2] == 0x01) // 3 byte start code
11363 index += 3;
11364 else //4 byte start code
11365 index += 4;
11366 } else
11367 index++;
11368 }
11369 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
11370 return;
11371 }
11372
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)11373 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11374 {
11375 //fix this, handle 3 byte start code, vc1 terminator entry
11376 OMX_U8 *p_demux_data = NULL;
11377 OMX_U32 desc_data = 0;
11378 OMX_U32 start_addr = 0;
11379 OMX_U32 nal_size = 0;
11380 OMX_U32 suffix_byte = 0;
11381 OMX_U32 demux_index = 0;
11382 OMX_U32 buffer_index = 0;
11383
11384 if (m_desc_buffer_ptr == NULL) {
11385 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
11386 return OMX_ErrorBadParameter;
11387 }
11388
11389 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
11390 if (buffer_index > drv_ctx.ip_buf.actualcount) {
11391 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
11392 return OMX_ErrorBadParameter;
11393 }
11394
11395 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
11396
11397 if ( ((OMX_U8*)p_demux_data == NULL) ||
11398 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
11399 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
11400 return OMX_ErrorBadParameter;
11401 } else {
11402 for (; demux_index < m_demux_entries; demux_index++) {
11403 desc_data = 0;
11404 start_addr = m_demux_offsets[demux_index];
11405 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
11406 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
11407 } else {
11408 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
11409 }
11410 if (demux_index < (m_demux_entries - 1)) {
11411 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
11412 } else {
11413 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
11414 }
11415 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
11416 (unsigned int)start_addr,
11417 (unsigned int)suffix_byte,
11418 (unsigned int)nal_size,
11419 (unsigned int)demux_index);
11420 desc_data = (start_addr >> 3) << 1;
11421 desc_data |= (start_addr & 7) << 21;
11422 desc_data |= suffix_byte << 24;
11423
11424 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11425 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
11426 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11427 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11428
11429 p_demux_data += 16;
11430 }
11431 if (codec_type_parse == CODEC_TYPE_VC1) {
11432 DEBUG_PRINT_LOW("VC1 terminator entry");
11433 desc_data = 0;
11434 desc_data = 0x82 << 24;
11435 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
11436 memset(p_demux_data + 4, 0, sizeof(OMX_U32));
11437 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
11438 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
11439 p_demux_data += 16;
11440 m_demux_entries++;
11441 }
11442 //Add zero word to indicate end of descriptors
11443 memset(p_demux_data, 0, sizeof(OMX_U32));
11444
11445 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
11446 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
11447 }
11448 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
11449 m_demux_entries = 0;
11450 DEBUG_PRINT_LOW("Demux table complete!");
11451 return OMX_ErrorNone;
11452 }
11453
request_perf_level(enum vidc_perf_level perf_level)11454 void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
11455 {
11456 struct v4l2_control control;
11457 char property_value[PROPERTY_VALUE_MAX] = {0};
11458
11459 property_get("vidc.debug.turbo", property_value, "0");
11460 memset(&control, 0, sizeof(v4l2_control));
11461 control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
11462 switch (perf_level) {
11463 case VIDC_NOMINAL:
11464 if (atoi(property_value))
11465 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11466 else
11467 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
11468 break;
11469 case VIDC_TURBO:
11470 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
11471 break;
11472 default:
11473 DEBUG_PRINT_ERROR("Requested PERF level not supported");
11474 break;
11475 }
11476 if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
11477 return;
11478
11479 DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
11480 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11481 current_perf_level = control.value;
11482 } else {
11483 DEBUG_PRINT_ERROR("Failed to set PERF level");
11484 }
11485 }
11486
allocate_color_convert_buf()11487 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
11488 {
11489 enabled = false;
11490 omx = NULL;
11491 init_members();
11492 ColorFormat = OMX_COLOR_FormatMax;
11493 dest_format = YCbCr420P;
11494 }
11495
set_vdec_client(void * client)11496 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
11497 {
11498 omx = reinterpret_cast<omx_vdec*>(client);
11499 }
11500
init_members()11501 void omx_vdec::allocate_color_convert_buf::init_members()
11502 {
11503 allocated_count = 0;
11504 buffer_size_req = 0;
11505 buffer_alignment_req = 0;
11506 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
11507 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
11508 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
11509 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
11510 #ifdef USE_ION
11511 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
11512 #endif
11513 for (int i = 0; i < MAX_COUNT; i++)
11514 pmem_fd[i] = -1;
11515 }
11516
~allocate_color_convert_buf()11517 omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
11518 {
11519 c2d.destroy();
11520 }
11521
update_buffer_req()11522 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
11523 {
11524 bool status = true;
11525 unsigned int src_size = 0, destination_size = 0;
11526 OMX_COLOR_FORMATTYPE drv_color_format;
11527 if (!omx) {
11528 DEBUG_PRINT_ERROR("Invalid client in color convert");
11529 return false;
11530 }
11531 if (!enabled) {
11532 DEBUG_PRINT_HIGH("No color conversion required");
11533 return status;
11534 }
11535 pthread_mutex_lock(&omx->c_lock);
11536 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
11537 ColorFormat != OMX_COLOR_FormatYUV420Planar) {
11538 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
11539 status = false;
11540 goto fail_update_buf_req;
11541 }
11542 c2d.close();
11543 status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
11544 omx->drv_ctx.video_resolution.frame_width,
11545 NV12_128m,dest_format);
11546 if (status) {
11547 status = c2d.get_buffer_size(C2D_INPUT,src_size);
11548 if (status)
11549 status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
11550 }
11551 if (status) {
11552 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
11553 !destination_size) {
11554 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
11555 "driver size %u destination size %d",
11556 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
11557 destination_size);
11558 status = false;
11559 c2d.close();
11560 buffer_size_req = 0;
11561 } else {
11562 buffer_size_req = destination_size;
11563 if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
11564 buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
11565 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11566 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11567 }
11568 }
11569 fail_update_buf_req:
11570 pthread_mutex_unlock(&omx->c_lock);
11571 return status;
11572 }
11573
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)11574 bool omx_vdec::allocate_color_convert_buf::set_color_format(
11575 OMX_COLOR_FORMATTYPE dest_color_format)
11576 {
11577 bool status = true;
11578 OMX_COLOR_FORMATTYPE drv_color_format;
11579 if (!omx) {
11580 DEBUG_PRINT_ERROR("Invalid client in color convert");
11581 return false;
11582 }
11583 pthread_mutex_lock(&omx->c_lock);
11584 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
11585 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11586 drv_color_format = (OMX_COLOR_FORMATTYPE)
11587 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11588 else
11589 drv_color_format = (OMX_COLOR_FORMATTYPE)
11590 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11591 else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
11592 drv_color_format = (OMX_COLOR_FORMATTYPE)
11593 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11594 } else {
11595 DEBUG_PRINT_ERROR("Incorrect color format");
11596 status = false;
11597 }
11598 if (status &&
11599 drv_color_format != dest_color_format &&
11600 drv_color_format != (OMX_COLOR_FORMATTYPE)
11601 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView &&
11602 drv_color_format != (OMX_COLOR_FORMATTYPE)
11603 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed &&
11604 dest_color_format != (OMX_COLOR_FORMATTYPE)
11605 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
11606 DEBUG_PRINT_LOW("Enabling C2D");
11607 if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
11608 (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
11609 DEBUG_PRINT_ERROR("Unsupported color format for c2d");
11610 status = false;
11611 } else {
11612 ColorFormat = dest_color_format;
11613 dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
11614 YCbCr420P : YCbCr420SP;
11615 if (enabled)
11616 c2d.destroy();
11617 enabled = false;
11618 if (!c2d.init()) {
11619 DEBUG_PRINT_ERROR("open failed for c2d");
11620 status = false;
11621 } else
11622 enabled = true;
11623 }
11624 } else {
11625 if (enabled)
11626 c2d.destroy();
11627 enabled = false;
11628 }
11629 pthread_mutex_unlock(&omx->c_lock);
11630 return status;
11631 }
11632
get_il_buf_hdr()11633 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
11634 {
11635 if (!omx) {
11636 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11637 return NULL;
11638 }
11639 if (!enabled)
11640 return omx->m_out_mem_ptr;
11641 return m_out_mem_ptr_client;
11642 }
11643
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11644 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
11645 (OMX_BUFFERHEADERTYPE *bufadd)
11646 {
11647 if (!omx) {
11648 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11649 return NULL;
11650 }
11651 if (!enabled)
11652 return bufadd;
11653
11654 unsigned index = 0;
11655 index = bufadd - omx->m_out_mem_ptr;
11656 if (index < omx->drv_ctx.op_buf.actualcount) {
11657 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
11658 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
11659 bool status;
11660 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
11661 pthread_mutex_lock(&omx->c_lock);
11662 cache_clean_buffer(index);
11663 status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
11664 omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
11665 pmem_baseaddress[index], pmem_baseaddress[index]);
11666 if (!status) {
11667 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
11668 m_out_mem_ptr_client[index].nFilledLen = 0;
11669 pthread_mutex_unlock(&omx->c_lock);
11670 return &m_out_mem_ptr_client[index];
11671 } else {
11672 unsigned int filledLen = 0;
11673 c2d.get_output_filled_length(filledLen);
11674 m_out_mem_ptr_client[index].nFilledLen = filledLen;
11675 cache_clean_invalidate_buffer(index);
11676 }
11677 pthread_mutex_unlock(&omx->c_lock);
11678 } else
11679 m_out_mem_ptr_client[index].nFilledLen = 0;
11680 return &m_out_mem_ptr_client[index];
11681 }
11682 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
11683 return NULL;
11684 }
11685
get_dr_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)11686 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
11687 (OMX_BUFFERHEADERTYPE *bufadd)
11688 {
11689 if (!omx) {
11690 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
11691 return NULL;
11692 }
11693 if (!enabled)
11694 return bufadd;
11695 unsigned index = 0;
11696 index = bufadd - m_out_mem_ptr_client;
11697 if (index < omx->drv_ctx.op_buf.actualcount) {
11698 return &omx->m_out_mem_ptr[index];
11699 }
11700 DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
11701 return NULL;
11702 }
get_buffer_req(unsigned int & buffer_size)11703 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
11704 (unsigned int &buffer_size)
11705 {
11706 bool status = true;
11707 pthread_mutex_lock(&omx->c_lock);
11708 if (!enabled)
11709 buffer_size = omx->drv_ctx.op_buf.buffer_size;
11710 else {
11711 if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
11712 DEBUG_PRINT_ERROR("Get buffer size failed");
11713 status = false;
11714 goto fail_get_buffer_size;
11715 }
11716 }
11717 if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
11718 buffer_size = omx->drv_ctx.op_buf.buffer_size;
11719 if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
11720 buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
11721 fail_get_buffer_size:
11722 pthread_mutex_unlock(&omx->c_lock);
11723 return status;
11724 }
free_output_buffer(OMX_BUFFERHEADERTYPE * bufhdr)11725 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
11726 OMX_BUFFERHEADERTYPE *bufhdr)
11727 {
11728 unsigned int index = 0;
11729
11730 if (!enabled)
11731 return omx->free_output_buffer(bufhdr);
11732 if (enabled && omx->is_component_secure())
11733 return OMX_ErrorNone;
11734 if (!allocated_count || !bufhdr) {
11735 DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
11736 return OMX_ErrorBadParameter;
11737 }
11738 index = bufhdr - m_out_mem_ptr_client;
11739 if (index >= omx->drv_ctx.op_buf.actualcount) {
11740 DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
11741 return OMX_ErrorBadParameter;
11742 }
11743 if (pmem_fd[index] >= 0) {
11744 munmap(pmem_baseaddress[index], buffer_size_req);
11745 close(pmem_fd[index]);
11746 }
11747 pmem_fd[index] = -1;
11748 #ifdef USE_ION
11749 omx->free_ion_memory(&op_buf_ion_info[index]);
11750 #endif
11751 m_heap_ptr[index].video_heap_ptr = NULL;
11752 if (allocated_count > 0)
11753 allocated_count--;
11754 else
11755 allocated_count = 0;
11756 if (!allocated_count) {
11757 pthread_mutex_lock(&omx->c_lock);
11758 c2d.close();
11759 init_members();
11760 pthread_mutex_unlock(&omx->c_lock);
11761 }
11762 return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
11763 }
11764
allocate_buffers_color_convert(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)11765 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
11766 OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
11767 {
11768 OMX_ERRORTYPE eRet = OMX_ErrorNone;
11769 if (!enabled) {
11770 eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
11771 return eRet;
11772 }
11773 if (enabled && omx->is_component_secure()) {
11774 DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
11775 omx->is_component_secure());
11776 return OMX_ErrorUnsupportedSetting;
11777 }
11778 if (!bufferHdr || bytes > buffer_size_req) {
11779 DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
11780 DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
11781 (unsigned int)buffer_size_req, (unsigned int)bytes);
11782 return OMX_ErrorBadParameter;
11783 }
11784 if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
11785 DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
11786 return OMX_ErrorInsufficientResources;
11787 }
11788 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
11789 eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
11790 port,appData,omx->drv_ctx.op_buf.buffer_size);
11791 if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
11792 DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
11793 return eRet;
11794 }
11795 if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
11796 (int)omx->drv_ctx.op_buf.actualcount) {
11797 DEBUG_PRINT_ERROR("Invalid header index %ld",
11798 (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
11799 return OMX_ErrorUndefined;
11800 }
11801 unsigned int i = allocated_count;
11802 #ifdef USE_ION
11803 // Allocate color-conversion buffers as cached to improve software-reading
11804 // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
11805 // cache invalidation.
11806 op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
11807 buffer_size_req,buffer_alignment_req,
11808 &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
11809 ION_FLAG_CACHED);
11810 pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
11811 if (op_buf_ion_info[i].ion_device_fd < 0) {
11812 DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
11813 return OMX_ErrorInsufficientResources;
11814 }
11815 pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
11816 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
11817
11818 if (pmem_baseaddress[i] == MAP_FAILED) {
11819 DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
11820 close(pmem_fd[i]);
11821 omx->free_ion_memory(&op_buf_ion_info[i]);
11822 return OMX_ErrorInsufficientResources;
11823 }
11824 m_heap_ptr[i].video_heap_ptr = new VideoHeap (
11825 op_buf_ion_info[i].ion_device_fd,buffer_size_req,
11826 pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
11827 #endif
11828 m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
11829 m_pmem_info_client[i].offset = 0;
11830 m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
11831 m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
11832 m_platform_list_client[i].nEntries = 1;
11833 m_platform_list_client[i].entryList = &m_platform_entry_client[i];
11834 m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
11835 m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
11836 m_out_mem_ptr_client[i].nFilledLen = 0;
11837 m_out_mem_ptr_client[i].nFlags = 0;
11838 m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11839 m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
11840 m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
11841 m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
11842 m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
11843 m_out_mem_ptr_client[i].pAppPrivate = appData;
11844 *bufferHdr = &m_out_mem_ptr_client[i];
11845 DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
11846 allocated_count++;
11847 return eRet;
11848 }
11849
is_component_secure()11850 bool omx_vdec::is_component_secure()
11851 {
11852 return secure_mode;
11853 }
11854
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)11855 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
11856 {
11857 bool status = true;
11858 if (!enabled) {
11859 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
11860 if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
11861 dest_color_format = (OMX_COLOR_FORMATTYPE)
11862 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
11863 else
11864 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
11865 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
11866 dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
11867 } else
11868 status = false;
11869 } else {
11870 if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
11871 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
11872 dest_color_format = ColorFormat;
11873 } else
11874 status = false;
11875 }
11876 return status;
11877 }
11878
cache_ops(unsigned int index,unsigned int cmd)11879 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
11880 unsigned int index, unsigned int cmd)
11881 {
11882 if (!enabled) {
11883 return OMX_ErrorNone;
11884 }
11885
11886 if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
11887 DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
11888 return OMX_ErrorBadParameter;
11889 }
11890
11891 struct ion_flush_data flush_data;
11892 struct ion_custom_data custom_data;
11893
11894 memset(&flush_data, 0x0, sizeof(flush_data));
11895 memset(&custom_data, 0x0, sizeof(custom_data));
11896
11897 flush_data.vaddr = pmem_baseaddress[index];
11898 flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
11899 flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
11900 flush_data.length = buffer_size_req;
11901 custom_data.cmd = cmd;
11902 custom_data.arg = (unsigned long)&flush_data;
11903
11904 DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
11905 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11906 flush_data.fd, flush_data.handle, flush_data.vaddr,
11907 flush_data.length);
11908 int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
11909 if (ret < 0) {
11910 DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
11911 (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
11912 strerror(errno));
11913 return OMX_ErrorUndefined;
11914 }
11915 return OMX_ErrorNone;
11916 }
11917
buf_ref_add(int nPortIndex)11918 void omx_vdec::buf_ref_add(int nPortIndex)
11919 {
11920 unsigned long i = 0;
11921 bool buf_present = false;
11922 long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
11923 OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
11924
11925 if (!dynamic_buf_mode || !out_dynamic_list) {
11926 return;
11927 }
11928
11929 pthread_mutex_lock(&m_lock);
11930 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11931 //check the buffer fd, offset, uv addr with list contents
11932 //If present increment reference.
11933 if ((out_dynamic_list[i].fd == fd) &&
11934 (out_dynamic_list[i].offset == offset)) {
11935 DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
11936 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11937 if (!secure_mode) {
11938 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
11939 }
11940 buf_present = true;
11941 break;
11942 }
11943 }
11944 if (!buf_present) {
11945 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11946 //search for a entry to insert details of the new buffer
11947 if (out_dynamic_list[i].dup_fd < 0) {
11948 out_dynamic_list[i].fd = fd;
11949 out_dynamic_list[i].offset = offset;
11950 out_dynamic_list[i].dup_fd = dup(fd);
11951 out_dynamic_list[i].ref_count++;
11952 DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
11953 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11954
11955 if (!secure_mode) {
11956 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
11957 (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
11958 PROT_READ|PROT_WRITE, MAP_SHARED,
11959 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
11960 //mmap returns (void *)-1 on failure and sets error code in errno.
11961 if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
11962 DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
11963 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
11964 break;
11965 }
11966 out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
11967 out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
11968 DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11969 }
11970 break;
11971 }
11972 }
11973 }
11974 pthread_mutex_unlock(&m_lock);
11975 }
11976
buf_ref_remove()11977 void omx_vdec::buf_ref_remove()
11978 {
11979 unsigned long i = 0;
11980
11981 if (!dynamic_buf_mode || !out_dynamic_list) {
11982 return;
11983 }
11984
11985 pthread_mutex_lock(&m_lock);
11986 for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
11987 if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
11988 DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
11989 munmap(out_dynamic_list[i].buffaddr,
11990 out_dynamic_list[i].mapped_size);
11991 }
11992
11993 DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
11994 (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
11995 close(out_dynamic_list[i].dup_fd);
11996 out_dynamic_list[i].dup_fd = -1;
11997 }
11998 pthread_mutex_unlock(&m_lock);
11999
12000 if (out_dynamic_list) {
12001 free(out_dynamic_list);
12002 out_dynamic_list = NULL;
12003 }
12004 }
12005
12006 #ifdef _MSM8974_
send_codec_config()12007 void omx_vdec::send_codec_config() {
12008 if (codec_config_flag) {
12009 unsigned long p1 = 0; // Parameter - 1
12010 unsigned long p2 = 0; // Parameter - 2
12011 unsigned long ident = 0;
12012 pthread_mutex_lock(&m_lock);
12013 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
12014 while (m_etb_q.m_size) {
12015 m_etb_q.pop_entry(&p1,&p2,&ident);
12016 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
12017 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12018 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
12019 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12020 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
12021 omx_report_error();
12022 }
12023 } else {
12024 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
12025 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
12026 }
12027 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
12028 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12029 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
12030 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12031 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
12032 omx_report_error ();
12033 }
12034 } else {
12035 pending_input_buffers++;
12036 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
12037 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
12038 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
12039 }
12040 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
12041 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
12042 (OMX_BUFFERHEADERTYPE *)p1);
12043 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
12044 }
12045 }
12046 pthread_mutex_unlock(&m_lock);
12047 }
12048 }
12049 #endif
12050
perf_control()12051 omx_vdec::perf_control::perf_control()
12052 {
12053 m_perf_lib = NULL;
12054 m_perf_handle = 0;
12055 m_perf_lock_acquire = NULL;
12056 m_perf_lock_release = NULL;
12057 }
12058
~perf_control()12059 omx_vdec::perf_control::~perf_control()
12060 {
12061 if (m_perf_handle != 0 && m_perf_lock_release) {
12062 DEBUG_PRINT_LOW("NOTE2: release perf lock");
12063 m_perf_lock_release(m_perf_handle);
12064 }
12065 if (m_perf_lib) {
12066 dlclose(m_perf_lib);
12067 }
12068 }
12069
12070 struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
12071
12072 omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
12073
send_hint_to_mpctl(bool state)12074 void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
12075 {
12076 if (load_lib() == false) {
12077 return;
12078 }
12079 m_perf_lock.lock();
12080 /* 0x4401 maps to video decode playback hint
12081 * in perflock, enum number is 44 and state
12082 * being sent on perflock acquire is 01 (true)
12083 */
12084 int arg = 0x4401;
12085
12086 if (state == true) {
12087 mpctl_obj.vid_inst_count++;
12088 } else if (state == false) {
12089 mpctl_obj.vid_inst_count--;
12090 }
12091
12092 if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
12093 mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
12094 mpctl_obj.vid_acquired = true;
12095 DEBUG_PRINT_INFO("Video slvp perflock acquired");
12096 } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
12097 m_perf_lock_release(mpctl_obj.vid_disp_handle);
12098 mpctl_obj.vid_acquired = false;
12099 DEBUG_PRINT_INFO("Video slvp perflock released");
12100 }
12101 m_perf_lock.unlock();
12102 }
12103
request_cores(int frame_duration_us)12104 void omx_vdec::perf_control::request_cores(int frame_duration_us)
12105 {
12106 if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
12107 return;
12108 }
12109 bool retVal = load_lib();
12110 if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
12111 int arg = 0x700 /*base value*/ + 2 /*cores*/;
12112 m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
12113 if (m_perf_handle) {
12114 DEBUG_PRINT_HIGH("perf lock acquired");
12115 }
12116 }
12117 }
12118
load_lib()12119 bool omx_vdec::perf_control::load_lib()
12120 {
12121 char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
12122 if (m_perf_lib)
12123 return true;
12124
12125 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
12126 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
12127 goto handle_err;
12128 }
12129
12130 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
12131 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
12132 goto handle_err;
12133 } else {
12134 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
12135 if (m_perf_lock_acquire == NULL) {
12136 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
12137 goto handle_err;
12138 }
12139 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
12140 if (m_perf_lock_release == NULL) {
12141 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
12142 goto handle_err;
12143 }
12144 }
12145 return true;
12146
12147 handle_err:
12148 if (m_perf_lib) {
12149 dlclose(m_perf_lib);
12150 }
12151 m_perf_lib = NULL;
12152 return false;
12153 }
12154
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)12155 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
12156 unsigned long nMaxFrameHeight)
12157 {
12158
12159 OMX_ERRORTYPE eRet = OMX_ErrorNone;
12160 int ret = 0;
12161 unsigned long min_res_buf_count = 0;
12162
12163 eRet = enable_smoothstreaming();
12164 if (eRet != OMX_ErrorNone) {
12165 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
12166 return eRet;
12167 }
12168
12169 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
12170 nMaxFrameWidth,
12171 nMaxFrameHeight);
12172 m_smoothstreaming_mode = true;
12173 m_smoothstreaming_width = nMaxFrameWidth;
12174 m_smoothstreaming_height = nMaxFrameHeight;
12175
12176 //Get upper limit buffer count for min supported resolution
12177 struct v4l2_format fmt;
12178 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12179 fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
12180 fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
12181 fmt.fmt.pix_mp.pixelformat = output_capability;
12182
12183 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12184 if (ret) {
12185 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
12186 m_decoder_capability.min_height,
12187 m_decoder_capability.min_width);
12188 return OMX_ErrorUnsupportedSetting;
12189 }
12190
12191 eRet = get_buffer_req(&drv_ctx.op_buf);
12192 if (eRet != OMX_ErrorNone) {
12193 DEBUG_PRINT_ERROR("failed to get_buffer_req");
12194 return eRet;
12195 }
12196
12197 min_res_buf_count = drv_ctx.op_buf.mincount;
12198 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
12199 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
12200
12201 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
12202 m_smoothstreaming_width, m_smoothstreaming_height);
12203 eRet = is_video_session_supported();
12204 if (eRet != OMX_ErrorNone) {
12205 DEBUG_PRINT_ERROR("video session is not supported");
12206 return eRet;
12207 }
12208
12209 //Get upper limit buffer size for max smooth streaming resolution set
12210 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12211 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
12212 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
12213 fmt.fmt.pix_mp.pixelformat = output_capability;
12214 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12215 if (ret) {
12216 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
12217 return OMX_ErrorUnsupportedSetting;
12218 }
12219
12220 eRet = get_buffer_req(&drv_ctx.op_buf);
12221 if (eRet != OMX_ErrorNone) {
12222 DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
12223 return eRet;
12224 }
12225 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
12226 (unsigned int)drv_ctx.op_buf.buffer_size);
12227
12228 drv_ctx.op_buf.mincount = min_res_buf_count;
12229 drv_ctx.op_buf.actualcount = min_res_buf_count;
12230 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
12231 eRet = set_buffer_req(&drv_ctx.op_buf);
12232 if (eRet != OMX_ErrorNone) {
12233 DEBUG_PRINT_ERROR("failed to set_buffer_req");
12234 return eRet;
12235 }
12236
12237 eRet = get_buffer_req(&drv_ctx.op_buf);
12238 if (eRet != OMX_ErrorNone) {
12239 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
12240 return eRet;
12241 }
12242 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
12243 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
12244 return eRet;
12245 }
12246
12247 //static
describeColorFormat(OMX_PTR pParam)12248 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
12249
12250 #ifndef FLEXYUV_SUPPORTED
12251 return OMX_ErrorUndefined;
12252 #else
12253
12254 if (pParam == NULL) {
12255 DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
12256 return OMX_ErrorBadParameter;
12257 }
12258
12259 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
12260
12261 MediaImage *img = &(params->sMediaImage);
12262 switch(params->eColorFormat) {
12263 case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
12264 {
12265 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
12266 img->mNumPlanes = 3;
12267 // mWidth and mHeight represent the W x H of the largest plane
12268 // In our case, this happens to be the Stride x Scanlines of Y plane
12269 img->mWidth = params->nFrameWidth;
12270 img->mHeight = params->nFrameHeight;
12271 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12272 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
12273 img->mBitDepth = 8;
12274 //Plane 0 (Y)
12275 img->mPlane[MediaImage::Y].mOffset = 0;
12276 img->mPlane[MediaImage::Y].mColInc = 1;
12277 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
12278 img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
12279 img->mPlane[MediaImage::Y].mVertSubsampling = 1;
12280 //Plane 1 (U)
12281 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
12282 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
12283 img->mPlane[MediaImage::U].mRowInc =
12284 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12285 img->mPlane[MediaImage::U].mHorizSubsampling = 2;
12286 img->mPlane[MediaImage::U].mVertSubsampling = 2;
12287 //Plane 2 (V)
12288 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
12289 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
12290 img->mPlane[MediaImage::V].mRowInc =
12291 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12292 img->mPlane[MediaImage::V].mHorizSubsampling = 2;
12293 img->mPlane[MediaImage::V].mVertSubsampling = 2;
12294 break;
12295 }
12296
12297 case OMX_COLOR_FormatYUV420Planar:
12298 case OMX_COLOR_FormatYUV420SemiPlanar:
12299 // We need not describe the standard OMX linear formats as these are
12300 // understood by client. Fail this deliberately to let client fill-in
12301 return OMX_ErrorUnsupportedSetting;
12302
12303 default:
12304 // Rest all formats which are non-linear cannot be described
12305 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
12306 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
12307 return OMX_ErrorNone;
12308 };
12309
12310 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
12311 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
12312 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
12313 for (size_t i = 0; i < img->mNumPlanes; ++i) {
12314 DEBUG_PRINT_LOW(" Plane[%zd] : offset=%d / xStep=%d / yStep = %d",
12315 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
12316 }
12317 return OMX_ErrorNone;
12318 #endif //FLEXYUV_SUPPORTED
12319 }
12320
prefetchNewBuffers()12321 void omx_vdec::prefetchNewBuffers() {
12322
12323 struct v4l2_decoder_cmd dec;
12324 uint32_t prefetch_count;
12325 uint32_t prefetch_size;
12326 uint32_t want_size;
12327 uint32_t have_size;
12328 int color_fmt, rc;
12329 uint32_t new_calculated_size;
12330 uint32_t new_buffer_size;
12331 uint32_t new_buffer_count;
12332 uint32_t old_buffer_size;
12333 uint32_t old_buffer_count;
12334
12335 memset((void *)&dec, 0 , sizeof(dec));
12336 DEBUG_PRINT_LOW("Old size : %d, count : %d, width : %u, height : %u\n",
12337 (int)drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
12338 drv_ctx.video_resolution.frame_width,
12339 drv_ctx.video_resolution.frame_height);
12340 dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
12341 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
12342 DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
12343 } else {
12344 DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
12345 dec.raw.data[0], dec.raw.data[1]);
12346 }
12347
12348 switch ((int)drv_ctx.output_format) {
12349 case VDEC_YUV_FORMAT_NV12:
12350 color_fmt = COLOR_FMT_NV12;
12351 break;
12352 case VDEC_YUV_FORMAT_NV12_UBWC:
12353 color_fmt = COLOR_FMT_NV12_UBWC;
12354 break;
12355 default:
12356 color_fmt = -1;
12357 }
12358
12359 new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
12360 DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
12361 m_reconfig_width, m_reconfig_height, new_calculated_size);
12362 new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
12363 new_buffer_count = dec.raw.data[1];
12364 old_buffer_size = drv_ctx.op_buf.buffer_size;
12365 old_buffer_count = drv_ctx.op_buf.actualcount;
12366
12367 new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
12368
12369 prefetch_count = new_buffer_count;
12370 prefetch_size = new_buffer_size - old_buffer_size;
12371 want_size = new_buffer_size * new_buffer_count;
12372 have_size = old_buffer_size * old_buffer_count;
12373
12374 if (want_size > have_size) {
12375 DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
12376 DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
12377
12378 int ion_fd = open(MEM_DEVICE, O_RDONLY);
12379 if (ion_fd < 0) {
12380 DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
12381 return;
12382 }
12383
12384 struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
12385 struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
12386 struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
12387 size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
12388
12389 if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
12390 DEBUG_PRINT_ERROR("prefetch data allocation failed");
12391 goto prefetch_exit;
12392 }
12393
12394 for (uint32_t i = 0; i < prefetch_count; i++) {
12395 sizes[i] = prefetch_size;
12396 }
12397
12398 regions[0].nr_sizes = prefetch_count;
12399 regions[0].sizes = sizes;
12400 regions[0].vmid = ION_FLAG_CP_PIXEL;
12401
12402 prefetch_data->nr_regions = 1;
12403 prefetch_data->regions = regions;
12404 prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
12405
12406 custom_data->cmd = ION_IOC_PREFETCH;
12407 custom_data->arg = (unsigned long )prefetch_data;
12408
12409 rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
12410 if (rc) {
12411 DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
12412 }
12413
12414 prefetch_exit:
12415 close(ion_fd);
12416 free(sizes);
12417 free(regions);
12418 free(prefetch_data);
12419 free(custom_data);
12420 }
12421 }
12422
12423 // No code beyond this !
12424
12425 // inline import of vendor-extensions implementation
12426 #include "omx_vdec_extensions.hpp"
12427