1 /*---------------------------------------------------------------------------------------
2 Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 /*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33 *//** @file omx_vdpp.cpp
34 This module contains the implementation of the OpenMAX video post-processing component.
35
36 *//*========================================================================*/
37
38 //////////////////////////////////////////////////////////////////////////////
39 // Include Files
40 //////////////////////////////////////////////////////////////////////////////
41 #define LOG_NDEBUG 0
42 #include <string.h>
43 #include <pthread.h>
44 #include <sys/prctl.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include "omx_vdpp.h"
49 #include <fcntl.h>
50 #include <limits.h>
51 #include <media/msm_media_info.h>
52
53 #ifndef _ANDROID_
54 #include <sys/ioctl.h>
55 #include <sys/mman.h>
56 #endif //_ANDROID_
57
58 #ifdef _ANDROID_
59 #include <cutils/properties.h>
60 #undef USE_EGL_IMAGE_GPU
61 #endif
62
63 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
64 #include <gralloc_priv.h>
65 #endif
66
67 #ifdef INPUT_BUFFER_LOG
68 int inputBufferFile;
69 char inputfilename[] = "/sdcard/input-bitstream";
70 #endif
71 #ifdef OUTPUT_BUFFER_LOG
72 int outputBufferFile;
73 char outputfilename[] = "/sdcard/output.yuv";
74 #endif
75 #ifdef OUTPUT_EXTRADATA_LOG
76 FILE *outputExtradataFile;
77 char ouputextradatafilename[] = "/data/extradata";
78 #endif
79
80 #include <stdarg.h>
81 #include <sys/stat.h>
82 #include <dirent.h>
83
84 #ifdef _ANDROID_
85 extern "C"{
86 #include<utils/Log.h>
87 }
88 #endif//_ANDROID_
89
90 #define POLL_TIMEOUT 0x7fffffff //10000//
91 #define MEM_DEVICE "/dev/ion"
92 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
93
94 #define DEFAULT_FPS 30
95 #define MAX_INPUT_ERROR DEFAULT_FPS
96 #define MAX_SUPPORTED_FPS 120
97
98 #define SZ_4K 0x1000
99
100 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
101 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
102 #define EXTRADATA_IDX(__num_planes) (__num_planes - 1)
103
104 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA)
105
106 #ifndef STUB_VPU
async_message_thread(void * input)107 void* async_message_thread (void *input)
108 {
109 int extra_idx = 0;
110 int rc = 0;
111 OMX_BUFFERHEADERTYPE *buffer;
112 struct v4l2_plane plane[VIDEO_MAX_PLANES];
113 struct pollfd pfd[2];
114 struct v4l2_buffer v4l2_buf;
115 struct v4l2_event dqevent;
116 omx_vdpp *omx = reinterpret_cast<omx_vdpp*>(input);
117 pfd[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
118 pfd[0].fd = omx->drv_ctx.video_vpu_fd;
119 pfd[1].events = POLLIN | POLLPRI | POLLERR;
120 pfd[1].fd = omx->m_ctrl_in;
121
122 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
123 DEBUG_PRINT_LOW("omx_vdpp: Async thread start\n");
124 prctl(PR_SET_NAME, (unsigned long)"VdppCallBackThread", 0, 0, 0);
125 while (1)
126 {
127 rc = poll(pfd, 2, POLL_TIMEOUT);
128
129 if (!rc) {
130 DEBUG_PRINT_HIGH("Poll timedout\n");
131 break; // no input buffers EOS reached
132 } else if (rc < 0) {
133 DEBUG_PRINT_ERROR("Error while polling: %d\n", rc);
134 break;
135 }
136 //DEBUG_PRINT_LOW("async_message_thread 1 POLL_TIMEOUT = 0x%x", POLL_TIMEOUT);
137
138 if (pfd[1].revents & (POLLIN | POLLPRI | POLLERR))
139 {
140 DEBUG_PRINT_HIGH("pipe event, exit async thread");
141 break;
142 }
143
144 // output buffer ready for fbd
145 if ((pfd[0].revents & POLLIN) || (pfd[0].revents & POLLRDNORM)) {
146 //DEBUG_PRINT_LOW("async_message_thread 1\n");
147 struct vdpp_msginfo vdpp_msg;
148 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
149 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
150 v4l2_buf.length = omx->drv_ctx.output_num_planes;
151 v4l2_buf.m.planes = plane;
152 while(!ioctl(pfd[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
153 DEBUG_PRINT_LOW("async_message_thread 2\n");
154 vdpp_msg.msgcode=VDPP_MSG_RESP_OUTPUT_BUFFER_DONE;
155 vdpp_msg.status_code=VDPP_S_SUCCESS;
156 vdpp_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
157
158 // driver returns ION buffer address, but case VDPP_MSG_RESP_OUTPUT_BUFFER_DONE
159 // will pass mmaped address to upper layer, and then driver sets it when returnning
160 // DQBUF for output buffers.
161 extra_idx = EXTRADATA_IDX(omx->drv_ctx.output_num_planes);
162 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
163 // this len is used in fill_buffer_done buffer->nFilledLen
164 // is different from FTBProxy plane[0].length
165 vdpp_msg.msgdata.output_frame.len= v4l2_buf.m.planes[0].bytesused + v4l2_buf.m.planes[extra_idx].bytesused;
166 //DEBUG_PRINT_HIGH("async_message_thread 2.5 omx->drv_ctx.op_buf.buffer_size = %d, plane[0].bytesused = %d, plane[%d].bytesused = %d\n", omx->drv_ctx.op_buf.buffer_size, v4l2_buf.m.planes[0].bytesused, extra_idx, v4l2_buf.m.planes[extra_idx].bytesused);
167 }
168 else {
169 vdpp_msg.msgdata.output_frame.len=v4l2_buf.m.planes[0].bytesused;
170 //DEBUG_PRINT_HIGH("async_message_thread 2.5 - 2 plane[0].bytesused = %d\n", v4l2_buf.m.planes[0].bytesused);
171 }
172 vdpp_msg.msgdata.output_frame.bufferaddr=(void*)v4l2_buf.m.planes[0].m.userptr;
173
174 // currently V4L2 driver just passes timestamp to maple FW, and maple FW
175 // pass the timestamp back to OMX
176 vdpp_msg.msgdata.output_frame.time_stamp = *(uint64_t *)(&v4l2_buf.timestamp);
177
178 //DEBUG_PRINT_HIGH("async_message_thread 2.6.0 v4l2_buf.timestamp.tv_sec = 0x%08lx, v4l2_buf.timestamp.tv_usec = 0x%08lx\n", v4l2_buf.timestamp.tv_sec, v4l2_buf.timestamp.tv_usec);
179 if (omx->async_message_process(input,&vdpp_msg) < 0) {
180 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
181 break;
182 }
183 }
184 }
185 // input buffer ready for empty buffer done (ebd)
186 if((pfd[0].revents & POLLOUT) || (pfd[0].revents & POLLWRNORM)) {
187 struct vdpp_msginfo vdpp_msg;
188 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
189 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
190 v4l2_buf.length = omx->drv_ctx.input_num_planes;
191 v4l2_buf.m.planes = plane;
192 DEBUG_PRINT_LOW("async_message_thread 3\n");
193 while(!ioctl(pfd[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
194 vdpp_msg.msgcode=VDPP_MSG_RESP_INPUT_BUFFER_DONE;
195 vdpp_msg.status_code=VDPP_S_SUCCESS;
196 vdpp_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
197
198 extra_idx = EXTRADATA_IDX(omx->drv_ctx.input_num_planes);
199 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
200 vdpp_msg.msgdata.output_frame.len=v4l2_buf.m.planes[0].bytesused + v4l2_buf.m.planes[extra_idx].bytesused; // user doesn't need this for ebd, just set in case is used
201 //DEBUG_PRINT_HIGH("async_message_thread 3.5 plane[0].bytesused = %d, plane[extra_idx].bytesused = %d\n", v4l2_buf.m.planes[0].bytesused, v4l2_buf.m.planes[extra_idx].bytesused);
202 }
203 else {
204 vdpp_msg.msgdata.output_frame.len=v4l2_buf.m.planes[0].bytesused;
205 //DEBUG_PRINT_HIGH("async_message_thread 3.5 - 2 plane[0].bytesused = %d\n", v4l2_buf.m.planes[0].bytesused);
206 }
207 if (omx->async_message_process(input,&vdpp_msg) < 0) {
208 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
209 break;
210 }
211 }
212 }
213 if (pfd[0].revents & POLLPRI){
214 DEBUG_PRINT_HIGH("async_message_thread 4\n");
215 memset(&dqevent, 0, sizeof(struct v4l2_event));
216 rc = ioctl(pfd[0].fd, VIDIOC_DQEVENT, &dqevent);
217 if(dqevent.type == VPU_EVENT_HW_ERROR)
218 {
219 struct vdpp_msginfo vdpp_msg;
220 vdpp_msg.msgcode=VDPP_MSG_EVT_HW_ERROR;
221 vdpp_msg.status_code=VDPP_S_SUCCESS;
222 DEBUG_PRINT_HIGH(" SYS Error Recieved \n");
223 if (omx->async_message_process(input,&vdpp_msg) < 0)
224 {
225 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
226 break;
227 }
228 }
229 else if (dqevent.type == VPU_EVENT_FLUSH_DONE) {
230 struct vdpp_msginfo vdpp_msg;
231 enum v4l2_buf_type buf_type;
232 memcpy(&buf_type, dqevent.u.data, sizeof(buf_type));
233 if(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == buf_type)
234 {
235 vdpp_msg.msgcode=VDPP_MSG_RESP_FLUSH_INPUT_DONE;
236 vdpp_msg.status_code=VDPP_S_SUCCESS;
237 DEBUG_PRINT_HIGH("VDPP Input Flush Done Recieved \n");
238 if (omx->async_message_process(input,&vdpp_msg) < 0) {
239 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
240 break;
241 }
242 }
243 else if(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == buf_type)
244 {
245 vdpp_msg.msgcode=VDPP_MSG_RESP_FLUSH_OUTPUT_DONE;
246 vdpp_msg.status_code=VDPP_S_SUCCESS;
247 DEBUG_PRINT_HIGH("VDPP Output Flush Done Recieved \n");
248 if (omx->async_message_process(input,&vdpp_msg) < 0) {
249 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
250 break;
251 }
252 }
253 else
254 {
255 DEBUG_PRINT_HIGH(" Wrong buf_type recieved %d\n", buf_type);
256 }
257 }
258 else if(dqevent.type == VPU_EVENT_ACTIVE_REGION_CHANGED)
259 {
260 DEBUG_PRINT_HIGH(" VPU_EVENT_ACTIVE_REGION_CHANGED\n");
261 struct vdpp_msginfo vdpp_msg;
262 vdpp_msg.msgcode=VDPP_MSG_EVT_ACTIVE_REGION_DETECTION_STATUS;
263 vdpp_msg.status_code=VDPP_S_SUCCESS;
264
265 // get the active region dection result struct from the event associated data
266 memcpy(&vdpp_msg.msgdata.ar_result, dqevent.u.data, sizeof(v4l2_rect));
267 DEBUG_PRINT_HIGH(" VPU_EVENT_ACTIVE_REGION_CHANGED Recieved \n");
268 if(omx->m_ar_callback_setup)
269 {
270 if (omx->async_message_process(input,&vdpp_msg) < 0)
271 {
272 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
273 break;
274 }
275 }
276 }
277 else
278 {
279 DEBUG_PRINT_HIGH(" VPU Some Event recieved \n");
280 continue;
281 }
282
283 }
284 }
285 DEBUG_PRINT_HIGH("omx_vdpp: Async thread stop\n");
286 return NULL;
287 }
288 #else // use stub to simulate vpu events for now
async_message_thread(void * input)289 void* async_message_thread (void *input)
290 {
291 OMX_BUFFERHEADERTYPE *buffer;
292 struct v4l2_plane plane[VIDEO_MAX_PLANES];
293 struct pollfd pfd;
294 struct v4l2_buffer v4l2_buf;
295 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
296 struct v4l2_event dqevent;
297 omx_vdpp *omx = reinterpret_cast<omx_vdpp*>(input);
298
299 pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
300 pfd.fd = omx->drv_ctx.video_vpu_fd;
301 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
302 DEBUG_PRINT_HIGH("omx_vdpp: Async thread start\n");
303 prctl(PR_SET_NAME, (unsigned long)"VdppCallBackThread", 0, 0, 0);
304 while (1)
305 {
306 DEBUG_PRINT_HIGH("omx_vdpp: Async thread start 0\n");
307 sem_wait(&(omx->drv_ctx.async_lock));
308 DEBUG_PRINT_HIGH("omx_vdpp: Async thread start pfd.revents = %d\n", pfd.revents);
309 if ((omx->drv_ctx.etb_ftb_info.ftb_cnt > 0))
310 {
311 DEBUG_PRINT_LOW("async_message_thread 1 omx->drv_ctx.etb_ftb_info.ftb_cnt = %d\n", omx->drv_ctx.etb_ftb_info.ftb_cnt);
312 struct vdpp_msginfo vdpp_msg;
313 unsigned p1 = 0;
314 unsigned p2 = 0;
315 unsigned ident = 0;
316 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
317 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
318 omx->m_index_q_ftb.pop_entry(&p1,&p2,&ident);
319 v4l2_buf.index = ident;
320 v4l2_buf.bytesused = omx->drv_ctx.etb_ftb_info.ftb_len;
321 omx->drv_ctx.etb_ftb_info.ftb_cnt--;
322 DEBUG_PRINT_HIGH("async_message_thread 1.5 omx->drv_ctx.etb_ftb_info.ftb_cnt = %d\n", omx->drv_ctx.etb_ftb_info.ftb_cnt);
323 /*while(!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) */{
324 DEBUG_PRINT_LOW("async_message_thread 2\n", rc);
325 vdpp_msg.msgcode=VDPP_MSG_RESP_OUTPUT_BUFFER_DONE;
326 vdpp_msg.status_code=VDPP_S_SUCCESS;
327 vdpp_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
328 vdpp_msg.msgdata.output_frame.len=v4l2_buf.bytesused;
329 vdpp_msg.msgdata.output_frame.bufferaddr=(void*)v4l2_buf.m.userptr;
330
331 vdpp_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
332 (uint64_t)v4l2_buf.timestamp.tv_usec;
333 if (omx->async_message_process(input,&vdpp_msg) < 0) {
334 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
335 break;
336 }
337 }
338 }
339 if(omx->drv_ctx.etb_ftb_info.etb_cnt > 0) {
340 struct vdpp_msginfo vdpp_msg;
341 unsigned p1 = 0;
342 unsigned p2 = 0;
343 unsigned ident = 0;
344 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
345 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
346
347 omx->m_index_q_etb.pop_entry(&p1,&p2,&ident);
348 v4l2_buf.index = ident;
349 DEBUG_PRINT_LOW("async_message_thread 3 omx->drv_ctx.etb_ftb_info.etb_cnt = %d\n", omx->drv_ctx.etb_ftb_info.etb_cnt);
350 omx->drv_ctx.etb_ftb_info.etb_cnt--;
351 DEBUG_PRINT_LOW("async_message_thread 4 omx->drv_ctx.etb_ftb_info.etb_cnt = %d\n", omx->drv_ctx.etb_ftb_info.etb_cnt);
352
353 /*while(!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf))*/ {
354 vdpp_msg.msgcode=VDPP_MSG_RESP_INPUT_BUFFER_DONE;
355 vdpp_msg.status_code=VDPP_S_SUCCESS;
356 vdpp_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
357 if (omx->async_message_process(input,&vdpp_msg) < 0) {
358 DEBUG_PRINT_HIGH(" async_message_thread Exited \n");
359 break;
360 }
361 }
362 }
363
364 if(omx->drv_ctx.thread_exit)
365 {
366 break;
367 }
368 }
369 DEBUG_PRINT_HIGH("omx_vdpp: Async thread stop\n");
370 return NULL;
371 }
372 #endif
373
message_thread(void * input)374 void* message_thread(void *input)
375 {
376 omx_vdpp* omx = reinterpret_cast<omx_vdpp*>(input);
377 unsigned char id;
378 int n;
379
380 DEBUG_PRINT_LOW("omx_vdpp: message thread start\n");
381 prctl(PR_SET_NAME, (unsigned long)"VideoPostProcessingMsgThread", 0, 0, 0);
382 while (1)
383 {
384
385 n = read(omx->m_pipe_in, &id, 1);
386
387 if(0 == n)
388 {
389 break;
390 }
391
392 if (1 == n)
393 {
394 omx->process_event_cb(omx, id);
395 }
396 if ((n < 0) && (errno != EINTR))
397 {
398 DEBUG_PRINT_ERROR("ERROR: read from pipe failed, ret %d errno %d", n, errno);
399 break;
400 }
401 }
402 DEBUG_PRINT_HIGH("omx_vdpp: message thread stop\n");
403 return 0;
404 }
405
post_message(omx_vdpp * omx,unsigned char id)406 void post_message(omx_vdpp *omx, unsigned char id)
407 {
408 int ret_value;
409 //DEBUG_PRINT_LOW("omx_vdpp: post_message %d pipe out 0x%x\n", id,omx->m_pipe_out);
410 ret_value = write(omx->m_pipe_out, &id, 1);
411 //DEBUG_PRINT_HIGH("post_message to pipe done %d\n",ret_value);
412 }
413
414 // omx_cmd_queue destructor
~omx_cmd_queue()415 omx_vdpp::omx_cmd_queue::~omx_cmd_queue()
416 {
417 // Nothing to do
418 }
419
420 // omx cmd queue constructor
omx_cmd_queue()421 omx_vdpp::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
422 {
423 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
424 }
425
426 // omx cmd queue insert
insert_entry(unsigned p1,unsigned p2,unsigned id)427 bool omx_vdpp::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
428 {
429 bool ret = true;
430 if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE)
431 {
432 m_q[m_write].id = id;
433 m_q[m_write].param1 = p1;
434 m_q[m_write].param2 = p2;
435 m_write++;
436 m_size ++;
437 if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE)
438 {
439 m_write = 0;
440 }
441 }
442 else
443 {
444 ret = false;
445 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full\n", __func__);
446 }
447 return ret;
448 }
449
450 // omx cmd queue pop
pop_entry(unsigned * p1,unsigned * p2,unsigned * id)451 bool omx_vdpp::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
452 {
453 bool ret = true;
454 if (m_size > 0)
455 {
456 *id = m_q[m_read].id;
457 *p1 = m_q[m_read].param1;
458 *p2 = m_q[m_read].param2;
459 // Move the read pointer ahead
460 ++m_read;
461 --m_size;
462 if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE)
463 {
464 m_read = 0;
465 }
466 }
467 else
468 {
469 ret = false;
470 }
471 return ret;
472 }
473
474 // Retrieve the first mesg type in the queue
get_q_msg_type()475 unsigned omx_vdpp::omx_cmd_queue::get_q_msg_type()
476 {
477 return m_q[m_read].id;
478 }
479
480 #ifdef _ANDROID_
ts_arr_list()481 omx_vdpp::ts_arr_list::ts_arr_list()
482 {
483 //initialize timestamps array
484 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
485 }
~ts_arr_list()486 omx_vdpp::ts_arr_list::~ts_arr_list()
487 {
488 //free m_ts_arr_list?
489 }
490
insert_ts(OMX_TICKS ts)491 bool omx_vdpp::ts_arr_list::insert_ts(OMX_TICKS ts)
492 {
493 bool ret = true;
494 bool duplicate_ts = false;
495 int idx = 0;
496
497 //insert at the first available empty location
498 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
499 {
500 if (!m_ts_arr_list[idx].valid)
501 {
502 //found invalid or empty entry, save timestamp
503 m_ts_arr_list[idx].valid = true;
504 m_ts_arr_list[idx].timestamp = ts;
505 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
506 ts, idx);
507 break;
508 }
509 }
510
511 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS)
512 {
513 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
514 ret = false;
515 }
516 return ret;
517 }
518
pop_min_ts(OMX_TICKS & ts)519 bool omx_vdpp::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
520 {
521 bool ret = true;
522 int min_idx = -1;
523 OMX_TICKS min_ts = 0;
524 int idx = 0;
525
526 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
527 {
528
529 if (m_ts_arr_list[idx].valid)
530 {
531 //found valid entry, save index
532 if (min_idx < 0)
533 {
534 //first valid entry
535 min_ts = m_ts_arr_list[idx].timestamp;
536 min_idx = idx;
537 }
538 else if (m_ts_arr_list[idx].timestamp < min_ts)
539 {
540 min_ts = m_ts_arr_list[idx].timestamp;
541 min_idx = idx;
542 }
543 }
544
545 }
546
547 if (min_idx < 0)
548 {
549 //no valid entries found
550 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
551 ts = 0;
552 ret = false;
553 }
554 else
555 {
556 ts = m_ts_arr_list[min_idx].timestamp;
557 m_ts_arr_list[min_idx].valid = false;
558 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
559 ts, min_idx);
560 }
561
562 return ret;
563
564 }
565
566
reset_ts_list()567 bool omx_vdpp::ts_arr_list::reset_ts_list()
568 {
569 bool ret = true;
570 int idx = 0;
571
572 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
573 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
574 {
575 m_ts_arr_list[idx].valid = false;
576 }
577 return ret;
578 }
579 #endif
580
581 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)582 void *get_omx_component_factory_fn(void)
583 {
584 return (new omx_vdpp);
585 }
586
587 /* ======================================================================
588 FUNCTION
589 omx_vdpp::omx_vdpp
590
591 DESCRIPTION
592 Constructor
593
594 PARAMETERS
595 None
596
597 RETURN VALUE
598 None.
599 ========================================================================== */
omx_vdpp()600 omx_vdpp::omx_vdpp(): m_ar_callback_setup(false),
601 m_error_propogated(false),
602 m_state(OMX_StateInvalid),
603 m_app_data(NULL),
604 m_inp_mem_ptr(NULL),
605 m_out_mem_ptr(NULL),
606 m_inp_err_count(0),
607 input_flush_progress (false),
608 output_flush_progress (false),
609 input_use_buffer (false),
610 output_use_buffer (false),
611 ouput_egl_buffers(false),
612 m_use_output_pmem(OMX_FALSE),
613 m_out_mem_region_smi(OMX_FALSE),
614 m_out_pvt_entry_pmem(OMX_FALSE),
615 pending_input_buffers(0),
616 pending_output_buffers(0),
617 input_qbuf_count(0),
618 input_dqbuf_count(0),
619 output_qbuf_count(0),
620 output_dqbuf_count(0),
621 #ifdef OUTPUT_BUFFER_LOG
622 output_buffer_write_counter(0),
623 input_buffer_write_counter(0),
624 #endif
625 m_out_bm_count(0),
626 m_inp_bm_count(0),
627 m_inp_bPopulated(OMX_FALSE),
628 m_out_bPopulated(OMX_FALSE),
629 m_flags(0),
630 m_inp_bEnabled(OMX_TRUE),
631 m_out_bEnabled(OMX_TRUE),
632 m_in_alloc_cnt(0),
633 m_platform_list(NULL),
634 m_platform_entry(NULL),
635 m_pmem_info(NULL),
636 psource_frame (NULL),
637 pdest_frame (NULL),
638 m_inp_heap_ptr (NULL),
639 m_phdr_pmem_ptr(NULL),
640 m_heap_inp_bm_count (0),
641 prev_ts(LLONG_MAX),
642 rst_prev_ts(true),
643 frm_int(0),
644 in_reconfig(false),
645 client_extradata(0),
646 m_enable_android_native_buffers(OMX_FALSE),
647 m_use_android_native_buffers(OMX_FALSE),
648 client_set_fps(false),
649 interlace_user_flag(false)
650 {
651 DEBUG_PRINT_LOW("In OMX vdpp Constructor");
652
653 memset(&m_cmp,0,sizeof(m_cmp));
654 memset(&m_cb,0,sizeof(m_cb));
655 memset (&drv_ctx,0,sizeof(drv_ctx));
656 msg_thread_id = 0;
657 async_thread_id = 0;
658 msg_thread_created = false;
659 async_thread_created = false;
660 #ifdef _ANDROID_ICS_
661 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
662 #endif
663
664 drv_ctx.timestamp_adjust = false;
665 drv_ctx.video_vpu_fd = -1;
666 pthread_mutex_init(&m_lock, NULL);
667 sem_init(&m_cmd_lock,0,0);
668 streaming[CAPTURE_PORT] = false;
669 streaming[OUTPUT_PORT] = false;
670
671 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
672
673 #ifdef STUB_VPU
674 drv_ctx.thread_exit = false;
675 sem_init(&(drv_ctx.async_lock),0,0);
676 #endif
677 }
678
subscribe_to_events(int fd)679 static OMX_ERRORTYPE subscribe_to_events(int fd)
680 {
681 OMX_ERRORTYPE eRet = OMX_ErrorNone;
682 struct v4l2_event_subscription sub;
683 int rc;
684 if (fd < 0) {
685 DEBUG_PRINT_ERROR("Invalid input: %d\n", fd);
686 return OMX_ErrorBadParameter;
687 }
688
689 #ifndef STUB_VPU
690 sub.type = V4L2_EVENT_ALL;
691 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
692 if (rc < 0)
693 {
694 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x\n", sub.type);
695 eRet = OMX_ErrorNotImplemented;
696 }
697 #endif
698
699 return eRet;
700 }
701
702
unsubscribe_to_events(int fd)703 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
704 {
705 OMX_ERRORTYPE eRet = OMX_ErrorNone;
706 struct v4l2_event_subscription sub;
707
708 int rc;
709 if (fd < 0) {
710 DEBUG_PRINT_ERROR("Invalid input: %d\n", fd);
711 return OMX_ErrorBadParameter;
712 }
713
714 #ifndef STUB_VPU
715 memset(&sub, 0, sizeof(sub));
716 sub.type = V4L2_EVENT_ALL;
717 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
718 if (rc) {
719 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x\n", sub.type);
720 }
721 #endif
722
723 return eRet;
724 }
725
726 /* ======================================================================
727 FUNCTION
728 omx_vdpp::~omx_vdpp
729
730 DESCRIPTION
731 Destructor
732
733 PARAMETERS
734 None
735
736 RETURN VALUE
737 None.
738 ========================================================================== */
~omx_vdpp()739 omx_vdpp::~omx_vdpp()
740 {
741 m_pmem_info = NULL;
742 DEBUG_PRINT_HIGH("In OMX vdpp Destructor");
743 if(m_pipe_in) close(m_pipe_in);
744 if(m_pipe_out) close(m_pipe_out);
745 m_pipe_in = -1;
746 m_pipe_out = -1;
747 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
748 if (msg_thread_created)
749 pthread_join(msg_thread_id,NULL);
750 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
751
752 #ifdef STUB_VPU
753 DEBUG_PRINT_HIGH("drv_ctx.etb_ftb_info.ftb_cnt = %d, drv_ctx.etb_ftb_info.etb_cnt = %d", drv_ctx.etb_ftb_info.ftb_cnt, drv_ctx.etb_ftb_info.etb_cnt);
754 drv_ctx.etb_ftb_info.ftb_cnt = 0;
755 drv_ctx.etb_ftb_info.etb_cnt = 0;
756 sem_post (&(drv_ctx.async_lock));
757 drv_ctx.thread_exit = true;
758 #endif
759 // notify async thread to exit
760 DEBUG_PRINT_LOW("write control pipe to notify async thread to exit");
761 write(m_ctrl_out, "1", 1);
762
763 if (async_thread_created)
764 pthread_join(async_thread_id,NULL);
765 DEBUG_PRINT_HIGH("async_thread exits");
766 unsubscribe_to_events(drv_ctx.video_vpu_fd);
767 close(drv_ctx.video_vpu_fd);
768 pthread_mutex_destroy(&m_lock);
769 sem_destroy(&m_cmd_lock);
770
771 #ifdef STUB_VPU
772 sem_destroy(&(drv_ctx.async_lock));
773 #endif
774 if(m_ctrl_in) close(m_ctrl_in);
775 if(m_ctrl_out) close(m_ctrl_out);
776 m_ctrl_in = -1;
777 m_ctrl_out = -1;
778 DEBUG_PRINT_HIGH("Exit OMX vdpp Destructor");
779 }
780
release_buffers(omx_vdpp * obj,enum vdpp_buffer buffer_type)781 int release_buffers(omx_vdpp* obj, enum vdpp_buffer buffer_type) {
782 struct v4l2_requestbuffers bufreq;
783 int rc = 0;
784 #ifndef STUB_VPU
785 if (buffer_type == VDPP_BUFFER_TYPE_OUTPUT){
786 bufreq.memory = V4L2_MEMORY_USERPTR;
787 bufreq.count = 0;
788 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
789 rc = ioctl(obj->drv_ctx.video_vpu_fd,VIDIOC_REQBUFS, &bufreq);
790 }else if(buffer_type == VDPP_BUFFER_TYPE_INPUT) {
791 bufreq.memory = V4L2_MEMORY_USERPTR;
792 bufreq.count = 0;
793 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
794 rc = ioctl(obj->drv_ctx.video_vpu_fd,VIDIOC_REQBUFS, &bufreq);
795 }
796 #endif
797 return rc;
798 }
799
800 /* ======================================================================
801 FUNCTION
802 omx_vdpp::process_event_cb
803
804 DESCRIPTION
805 IL Client callbacks are generated through this routine. The VDPP
806 provides the thread context for this routine.
807
808 PARAMETERS
809 ctxt -- Context information related to the self.
810 id -- Event identifier. This could be any of the following:
811 1. Command completion event
812 2. Buffer done callback event
813 3. Frame done callback event
814
815 RETURN VALUE
816 None.
817
818 ========================================================================== */
process_event_cb(void * ctxt,unsigned char id)819 void omx_vdpp::process_event_cb(void *ctxt, unsigned char id)
820 {
821 signed p1; // Parameter - 1
822 signed p2; // Parameter - 2
823 unsigned ident;
824 unsigned qsize=0; // qsize
825 omx_vdpp *pThis = (omx_vdpp *) ctxt;
826
827 if(!pThis)
828 {
829 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n",
830 __func__);
831 return;
832 }
833
834 // Protect the shared queue data structure
835 do
836 {
837 /*Read the message id's from the queue*/
838 pthread_mutex_lock(&pThis->m_lock);
839
840 // first check command queue
841 qsize = pThis->m_cmd_q.m_size;
842 if(qsize)
843 {
844 pThis->m_cmd_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
845 //DEBUG_PRINT_HIGH("process_event_cb m_cmd_q.pop_entry ident = %d", ident);
846 }
847
848 // then check ftb queue
849 if (qsize == 0 && pThis->m_state != OMX_StatePause)
850 {
851
852 qsize = pThis->m_ftb_q.m_size;
853 if (qsize)
854 {
855 pThis->m_ftb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
856 DEBUG_PRINT_HIGH("process_event_cb, p1 = 0x%08x, p2 = 0x%08x, ident = 0x%08x", p1, p2, ident);
857 }
858 }
859
860 // last check etb queue
861 if (qsize == 0 && pThis->m_state != OMX_StatePause)
862 {
863 qsize = pThis->m_etb_q.m_size;
864 if (qsize)
865 {
866 pThis->m_etb_q.pop_entry((unsigned *)&p1, (unsigned *)&p2, &ident);
867 }
868 }
869 pthread_mutex_unlock(&pThis->m_lock);
870
871 /*process message if we have one*/
872 if(qsize > 0)
873 {
874 id = ident;
875 switch (id)
876 {
877 case OMX_COMPONENT_GENERATE_EVENT:
878 if (pThis->m_cb.EventHandler)
879 {
880 switch (p1)
881 {
882 case OMX_CommandStateSet:
883 pThis->m_state = (OMX_STATETYPE) p2;
884 DEBUG_PRINT_HIGH(" OMX_CommandStateSet complete, m_state = %d, pThis->m_cb.EventHandler = %p",
885 pThis->m_state, pThis->m_cb.EventHandler);
886 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
887 OMX_EventCmdComplete, p1, p2, NULL);
888 break;
889
890 case OMX_EventError:
891 if(p2 == OMX_StateInvalid)
892 {
893 DEBUG_PRINT_ERROR(" OMX_EventError: p2 is OMX_StateInvalid");
894 pThis->m_state = (OMX_STATETYPE) p2;
895 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
896 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
897 }
898 else if (p2 == OMX_ErrorHardware)
899 {
900 pThis->omx_report_error();
901 }
902 else
903 {
904 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
905 OMX_EventError, p2, (OMX_U32)NULL, NULL );
906 }
907 break;
908
909 case OMX_CommandPortDisable:
910 DEBUG_PRINT_HIGH(" OMX_CommandPortDisable complete for port [%d], pThis->in_reconfig = %d", p2, pThis->in_reconfig);
911 if (BITMASK_PRESENT(&pThis->m_flags,
912 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
913 {
914 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
915 break;
916 }
917 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX)
918 {
919 OMX_ERRORTYPE eRet = OMX_ErrorNone;
920 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
921 if(release_buffers(pThis, VDPP_BUFFER_TYPE_OUTPUT))
922 DEBUG_PRINT_HIGH("Failed to release output buffers\n");
923 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
924 pThis->in_reconfig = false;
925 if(eRet != OMX_ErrorNone)
926 {
927 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
928 pThis->omx_report_error();
929 break;
930 }
931 }
932 if (p2 == OMX_CORE_INPUT_PORT_INDEX)
933 {
934 OMX_ERRORTYPE eRet = OMX_ErrorNone;
935 pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX);
936 if(release_buffers(pThis, VDPP_BUFFER_TYPE_INPUT))
937 DEBUG_PRINT_HIGH("Failed to release output buffers\n");
938 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.ip_buf);
939 pThis->in_reconfig = false;
940 if(eRet != OMX_ErrorNone)
941 {
942 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
943 pThis->omx_report_error();
944 break;
945 }
946 }
947 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
948 OMX_EventCmdComplete, p1, p2, NULL );
949 break;
950 case OMX_CommandPortEnable:
951 DEBUG_PRINT_HIGH(" OMX_CommandPortEnable complete for port [%d]", p2);
952 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
953 OMX_EventCmdComplete, p1, p2, NULL );
954 break;
955
956 default:
957 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
958 OMX_EventCmdComplete, p1, p2, NULL );
959 break;
960
961 }
962 }
963 else
964 {
965 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__);
966 }
967 break;
968 break;
969 case OMX_COMPONENT_GENERATE_ETB:
970 if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
971 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
972 {
973 DEBUG_PRINT_ERROR(" empty_this_buffer_proxy failure");
974 pThis->omx_report_error ();
975 }
976 break;
977
978 case OMX_COMPONENT_GENERATE_FTB:
979 {
980 DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_FTB p2 = 0x%08x", p2);
981 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
982 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
983 {
984 DEBUG_PRINT_ERROR(" fill_this_buffer_proxy failure");
985 pThis->omx_report_error ();
986 }
987 }
988 break;
989
990 case OMX_COMPONENT_GENERATE_COMMAND:
991 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
992 (OMX_U32)p2,(OMX_PTR)NULL);
993 break;
994
995 case OMX_COMPONENT_GENERATE_EBD:
996 if (p2 != VDPP_S_SUCCESS && p2 != VDPP_S_INPUT_BITSTREAM_ERR)
997 {
998 DEBUG_PRINT_HIGH(" OMX_COMPONENT_GENERATE_EBD failure");
999 pThis->omx_report_error ();
1000 }
1001 else
1002 {
1003 DEBUG_PRINT_HIGH(" OMX_COMPONENT_GENERATE_EBD 1");
1004 if (p2 == VDPP_S_INPUT_BITSTREAM_ERR && p1)
1005 {
1006 pThis->m_inp_err_count++;
1007 DEBUG_PRINT_HIGH(" OMX_COMPONENT_GENERATE_EBD 2");
1008 //pThis->time_stamp_dts.remove_time_stamp(
1009 //((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp,
1010 //(pThis->drv_ctx.interlace != VDPP_InterlaceFrameProgressive)
1011 // ?true:false);
1012 }
1013 else
1014 {
1015 pThis->m_inp_err_count = 0;
1016 }
1017 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1018 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
1019 {
1020 DEBUG_PRINT_ERROR(" empty_buffer_done failure");
1021 pThis->omx_report_error ();
1022 }
1023 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_EBD 4");
1024 if(pThis->m_inp_err_count >= MAX_INPUT_ERROR)
1025 {
1026 DEBUG_PRINT_ERROR(" Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR);
1027 pThis->omx_report_error ();
1028 }
1029 }
1030 break;
1031 case OMX_COMPONENT_GENERATE_FBD:
1032 if (p2 != VDPP_S_SUCCESS)
1033 {
1034 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_FBD failure");
1035 pThis->omx_report_error ();
1036 }
1037 else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1038 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
1039 {
1040 DEBUG_PRINT_ERROR(" fill_buffer_done failure");
1041 pThis->omx_report_error ();
1042 }
1043 break;
1044
1045 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1046 DEBUG_PRINT_HIGH(" Driver flush i/p Port complete");
1047 if (!pThis->input_flush_progress)
1048 {
1049 DEBUG_PRINT_ERROR(" WARNING: Unexpected flush from driver");
1050 }
1051 else
1052 {
1053 pThis->execute_input_flush();
1054 if (pThis->m_cb.EventHandler)
1055 {
1056 if (p2 != VDPP_S_SUCCESS)
1057 {
1058 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1059 pThis->omx_report_error ();
1060 }
1061 else
1062 {
1063 /*Check if we need generate event for Flush done*/
1064 if(BITMASK_PRESENT(&pThis->m_flags,
1065 OMX_COMPONENT_INPUT_FLUSH_PENDING))
1066 {
1067 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
1068 DEBUG_PRINT_LOW(" Input Flush completed - Notify Client");
1069 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1070 OMX_EventCmdComplete,OMX_CommandFlush,
1071 OMX_CORE_INPUT_PORT_INDEX,NULL );
1072 }
1073 if (BITMASK_PRESENT(&pThis->m_flags,
1074 OMX_COMPONENT_IDLE_PENDING))
1075 {
1076 if(pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1077 DEBUG_PRINT_ERROR(" Failed to call streamoff on OUTPUT Port \n");
1078 pThis->omx_report_error ();
1079 } else {
1080 DEBUG_PRINT_HIGH(" Successful to call streamoff on OUTPUT Port \n");
1081 pThis->streaming[OUTPUT_PORT] = false;
1082 }
1083 if (!pThis->output_flush_progress)
1084 {
1085 DEBUG_PRINT_LOW(" Input flush done hence issue stop");
1086 pThis->post_event ((unsigned int)NULL, VDPP_S_SUCCESS,\
1087 OMX_COMPONENT_GENERATE_STOP_DONE);
1088 }
1089 }
1090 }
1091 }
1092 else
1093 {
1094 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1095 }
1096 }
1097 break;
1098
1099 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1100 DEBUG_PRINT_HIGH(" Driver flush o/p Port complete");
1101 if (!pThis->output_flush_progress)
1102 {
1103 DEBUG_PRINT_ERROR(" WARNING: Unexpected flush from driver");
1104 }
1105 else
1106 {
1107 pThis->execute_output_flush();
1108 if (pThis->m_cb.EventHandler)
1109 {
1110 if (p2 != VDPP_S_SUCCESS)
1111 {
1112 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1113 pThis->omx_report_error ();
1114 }
1115 else
1116 {
1117 /*Check if we need generate event for Flush done*/
1118 if(BITMASK_PRESENT(&pThis->m_flags,
1119 OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
1120 {
1121 DEBUG_PRINT_LOW(" Notify Output Flush done");
1122 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
1123 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1124 OMX_EventCmdComplete,OMX_CommandFlush,
1125 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1126 }
1127 if(BITMASK_PRESENT(&pThis->m_flags,
1128 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
1129 {
1130 DEBUG_PRINT_LOW(" Internal flush complete");
1131 BITMASK_CLEAR (&pThis->m_flags,
1132 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1133 if (BITMASK_PRESENT(&pThis->m_flags,
1134 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED))
1135 {
1136 pThis->post_event(OMX_CommandPortDisable,
1137 OMX_CORE_OUTPUT_PORT_INDEX,
1138 OMX_COMPONENT_GENERATE_EVENT);
1139 BITMASK_CLEAR (&pThis->m_flags,
1140 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1141
1142 }
1143 }
1144
1145 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH 1 \n");
1146
1147 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING))
1148 {
1149 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH 2 \n");
1150 if(pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1151 DEBUG_PRINT_ERROR(" Failed to call streamoff on CAPTURE Port \n");
1152 pThis->omx_report_error ();
1153 break;
1154 }
1155 pThis->streaming[CAPTURE_PORT] = false;
1156 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH 3 pThis->input_flush_progress =%d \n", pThis->input_flush_progress);
1157 if (!pThis->input_flush_progress)
1158 {
1159 DEBUG_PRINT_LOW(" Output flush done hence issue stop");
1160 pThis->post_event ((unsigned int)NULL, VDPP_S_SUCCESS,\
1161 OMX_COMPONENT_GENERATE_STOP_DONE);
1162 }
1163 }
1164 }
1165 }
1166 else
1167 {
1168 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1169 }
1170 }
1171 break;
1172
1173 case OMX_COMPONENT_GENERATE_START_DONE:
1174 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_START_DONE");
1175
1176 if (pThis->m_cb.EventHandler)
1177 {
1178 if (p2 != VDPP_S_SUCCESS)
1179 {
1180 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_START_DONE Failure");
1181 pThis->omx_report_error ();
1182 }
1183 else
1184 {
1185 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_START_DONE Success");
1186 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
1187 {
1188 DEBUG_PRINT_LOW(" Move to executing");
1189 // Send the callback now
1190 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1191 pThis->m_state = OMX_StateExecuting;
1192 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1193 OMX_EventCmdComplete,OMX_CommandStateSet,
1194 OMX_StateExecuting, NULL);
1195 }
1196 else if (BITMASK_PRESENT(&pThis->m_flags,
1197 OMX_COMPONENT_PAUSE_PENDING))
1198 {
1199 if (/*ioctl (pThis->drv_ctx.video_vpu_fd,
1200 VDPP_IOCTL_CMD_PAUSE,NULL ) < */0)
1201 {
1202 DEBUG_PRINT_ERROR(" VDPP_IOCTL_CMD_PAUSE failed");
1203 pThis->omx_report_error ();
1204 }
1205 }
1206 }
1207 }
1208 else
1209 {
1210 DEBUG_PRINT_LOW(" Event Handler callback is NULL");
1211 }
1212 break;
1213
1214 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1215 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1216 if (pThis->m_cb.EventHandler)
1217 {
1218 if (p2 != VDPP_S_SUCCESS)
1219 {
1220 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1221 pThis->omx_report_error ();
1222 }
1223 else
1224 {
1225 pThis->complete_pending_buffer_done_cbs();
1226 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING))
1227 {
1228 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1229 //Send the callback now
1230 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1231 pThis->m_state = OMX_StatePause;
1232 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1233 OMX_EventCmdComplete,OMX_CommandStateSet,
1234 OMX_StatePause, NULL);
1235 }
1236 }
1237 }
1238 else
1239 {
1240 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1241 }
1242
1243 break;
1244
1245 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1246 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1247 if (pThis->m_cb.EventHandler)
1248 {
1249 if (p2 != VDPP_S_SUCCESS)
1250 {
1251 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1252 pThis->omx_report_error ();
1253 }
1254 else
1255 {
1256 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
1257 {
1258 DEBUG_PRINT_LOW(" Moving the VDPP to execute state");
1259 // Send the callback now
1260 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1261 pThis->m_state = OMX_StateExecuting;
1262 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1263 OMX_EventCmdComplete,OMX_CommandStateSet,
1264 OMX_StateExecuting,NULL);
1265 }
1266 }
1267 }
1268 else
1269 {
1270 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1271 }
1272
1273 break;
1274
1275 case OMX_COMPONENT_GENERATE_STOP_DONE:
1276 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1277 if (pThis->m_cb.EventHandler)
1278 {
1279 if (p2 != VDPP_S_SUCCESS)
1280 {
1281 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1282 pThis->omx_report_error ();
1283 }
1284 else
1285 {
1286 pThis->complete_pending_buffer_done_cbs();
1287 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING))
1288 {
1289 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_STOP_DONE Success");
1290 // Send the callback now
1291 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1292 pThis->m_state = OMX_StateIdle;
1293 DEBUG_PRINT_LOW(" Move to Idle State, pThis->m_cb.EventHandler = %p", pThis->m_cb.EventHandler);
1294 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1295 OMX_EventCmdComplete,OMX_CommandStateSet,
1296 OMX_StateIdle,NULL);
1297 DEBUG_PRINT_LOW(" OMX_COMPONENT_GENERATE_STOP_DONE cb finished");
1298 }
1299 }
1300 }
1301 else
1302 {
1303 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1304 }
1305
1306 break;
1307
1308 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1309 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG");
1310
1311 if (p2 == OMX_IndexParamPortDefinition) {
1312 pThis->in_reconfig = true;
1313 }
1314 if (pThis->m_cb.EventHandler) {
1315 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1316 OMX_EventPortSettingsChanged, p1, p2, NULL );
1317 } else {
1318 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1319 }
1320
1321 if (pThis->drv_ctx.interlace != V4L2_FIELD_NONE/*VDPP_InterlaceFrameProgressive*/)
1322 {
1323 OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1;
1324 OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged;
1325 if (pThis->drv_ctx.interlace == V4L2_FIELD_INTERLACED_TB/*VDPP_InterlaceInterleaveFrameTopFieldFirst*/)
1326 format = OMX_InterlaceInterleaveFrameTopFieldFirst;
1327 else if (pThis->drv_ctx.interlace == V4L2_FIELD_INTERLACED_BT/*VDPP_InterlaceInterleaveFrameBottomFieldFirst*/)
1328 format = OMX_InterlaceInterleaveFrameBottomFieldFirst;
1329 else //unsupported interlace format; raise a error
1330 event = OMX_EventError;
1331 if (pThis->m_cb.EventHandler) {
1332 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1333 event, format, 0, NULL );
1334 } else {
1335 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1336 }
1337 }
1338 break;
1339
1340 case OMX_COMPONENT_GENERATE_EOS_DONE:
1341 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1342 if (pThis->m_cb.EventHandler) {
1343 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1344 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1345 } else {
1346 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1347 }
1348 pThis->prev_ts = LLONG_MAX;
1349 pThis->rst_prev_ts = true;
1350 break;
1351
1352 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1353 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1354 pThis->omx_report_error ();
1355 break;
1356
1357 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1358 DEBUG_PRINT_ERROR(" OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING\n");
1359 pThis->omx_report_unsupported_setting();
1360 break;
1361
1362 case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG:
1363 {
1364 DEBUG_PRINT_HIGH(" Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG");
1365 if (pThis->m_cb.EventHandler) {
1366 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1367 (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
1368 } else {
1369 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1370 }
1371 }
1372 // extensions
1373 case OMX_COMPONENT_GENERATE_ACTIVE_REGION_DETECTION_STATUS:
1374 {
1375 struct v4l2_rect * ar_result = (struct v4l2_rect *) p1;
1376 QOMX_ACTIVEREGIONDETECTION_STATUSTYPE arstatus;
1377 arstatus.nSize = sizeof(QOMX_ACTIVEREGIONDETECTION_STATUSTYPE);
1378 arstatus.nPortIndex = 0;
1379 arstatus.bDetected = OMX_TRUE;
1380 memcpy(&arstatus.sDetectedRegion, ar_result, sizeof(QOMX_RECTTYPE));
1381 DEBUG_PRINT_HIGH(" OMX_COMPONENT_GENERATE_ACTIVE_REGION_DETECTION_STATUS");
1382 // data2 should be (OMX_INDEXTYPE)OMX_QcomIndexConfigActiveRegionDetectionStatus
1383 // pdata should be QOMX_ACTIVEREGIONDETECTION_STATUSTYPE
1384 if (pThis->m_cb.EventHandler) {
1385 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1386 (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, (OMX_INDEXTYPE)OMX_QcomIndexConfigActiveRegionDetectionStatus, &arstatus);
1387 } else {
1388 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1389 }
1390 }
1391 default:
1392 break;
1393 }
1394 }
1395 pthread_mutex_lock(&pThis->m_lock);
1396 qsize = pThis->m_cmd_q.m_size;
1397 if (pThis->m_state != OMX_StatePause)
1398 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1399 pthread_mutex_unlock(&pThis->m_lock);
1400 }
1401 while(qsize>0);
1402
1403 }
1404
update_resolution(uint32_t width,uint32_t height,uint32_t stride,uint32_t scan_lines)1405 int omx_vdpp::update_resolution(uint32_t width, uint32_t height, uint32_t stride, uint32_t scan_lines)
1406 {
1407 int format_changed = 0;
1408 if ((height != drv_ctx.video_resolution_input.frame_height) ||
1409 (width != drv_ctx.video_resolution_input.frame_width)) {
1410 DEBUG_PRINT_HIGH("NOTE: W/H %d (%d), %d (%d)\n",
1411 width, drv_ctx.video_resolution_input.frame_width,
1412 height,drv_ctx.video_resolution_input.frame_height);
1413 format_changed = 1;
1414 }
1415 drv_ctx.video_resolution_input.frame_height = height;
1416 drv_ctx.video_resolution_input.frame_width = width;
1417 drv_ctx.video_resolution_input.scan_lines = scan_lines;
1418 drv_ctx.video_resolution_input.stride = stride;
1419 rectangle.nLeft = 0;
1420 rectangle.nTop = 0;
1421 rectangle.nWidth = drv_ctx.video_resolution_input.frame_width;
1422 rectangle.nHeight = drv_ctx.video_resolution_input.frame_height;
1423 return format_changed;
1424 }
1425
1426 /* ======================================================================
1427 FUNCTION
1428 omx_vdpp::ComponentInit
1429
1430 DESCRIPTION
1431 Initialize the component.
1432
1433 PARAMETERS
1434 ctxt -- Context information related to the self.
1435 id -- Event identifier. This could be any of the following:
1436 1. Command completion event
1437 2. Buffer done callback event
1438 3. Frame done callback event
1439
1440 RETURN VALUE
1441 None.
1442
1443 ========================================================================== */
component_init(OMX_STRING role)1444 OMX_ERRORTYPE omx_vdpp::component_init(OMX_STRING role)
1445 {
1446
1447 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1448 struct v4l2_format fmt;
1449 int fds[2];
1450 int fctl[2];
1451 int ret=0;
1452 int i = 0;
1453 int sessionNum = 0;
1454
1455 errno = 0;
1456
1457 #ifndef STUB_VPU
1458 drv_ctx.video_vpu_fd = openInput("msm_vpu");
1459 #else
1460 drv_ctx.video_vpu_fd = 1;
1461 #endif
1462 DEBUG_PRINT_HIGH(" omx_vdpp::component_init(): Open returned fd %d, errno %d",
1463 drv_ctx.video_vpu_fd, errno);
1464
1465 if(drv_ctx.video_vpu_fd == 0){
1466 DEBUG_PRINT_ERROR("omx_vdpp:: Got fd as 0 for vpu, Opening again\n");
1467 drv_ctx.video_vpu_fd = openInput("msm_vpu");
1468 }
1469
1470 if(drv_ctx.video_vpu_fd < 0)
1471 {
1472 DEBUG_PRINT_ERROR("omx_vdpp::Comp Init Returning failure, errno %d\n", errno);
1473 return OMX_ErrorInsufficientResources;
1474 }
1475
1476 #ifndef STUB_VPU
1477 // query number of sessions and attach to session #1
1478 /* Check how many sessions are suported by H/W */
1479 ret = ioctl(drv_ctx.video_vpu_fd, VPU_QUERY_SESSIONS,
1480 &drv_ctx.sessionsSupported);
1481 if (ret < 0)
1482 {
1483 DEBUG_PRINT_ERROR("QUERY_SESSIONS: VPU_QUERY_SESSIONS failed.");
1484 close(drv_ctx.video_vpu_fd);
1485 drv_ctx.video_vpu_fd = 0;
1486 return OMX_ErrorInsufficientResources;
1487 }
1488 else
1489 {
1490 DEBUG_PRINT_HIGH("QUERY_SESSIONS: The number of sessions supported are %d.",
1491 drv_ctx.sessionsSupported);
1492 }
1493 #endif
1494
1495 /* Attach Client to Session. */
1496 sessionNum = VDPP_SESSION;
1497
1498 #ifndef STUB_VPU
1499 ret = ioctl(drv_ctx.video_vpu_fd, VPU_ATTACH_TO_SESSION, &sessionNum);
1500 if (ret < 0)
1501 {
1502 if( errno == EINVAL )
1503 DEBUG_PRINT_ERROR("VPU_ATTACH_TO_SESSION: session %d is out of valid "
1504 "range.", sessionNum);
1505 else if( errno == EBUSY)
1506 DEBUG_PRINT_ERROR("VPU_ATTACH_TO_SESSION: max. allowed number of"
1507 "clients attached to session.");
1508 else
1509 DEBUG_PRINT_ERROR("VPU_ATTACH_TO_SESSION: failed for unknown reason.");
1510 return OMX_ErrorUndefined;
1511 }
1512 else
1513 {
1514 DEBUG_PRINT_HIGH("VPU_ATTACH_TO_SESSION: client successfully attached "
1515 "to session.");
1516 }
1517 #endif
1518 drv_ctx.sessionAttached = sessionNum;
1519
1520 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1521 drv_ctx.frame_rate.fps_denominator = 1;
1522
1523 ret = subscribe_to_events(drv_ctx.video_vpu_fd);
1524
1525 /* create control pipes */
1526 if (!ret)
1527 {
1528 if(pipe(fctl))
1529 {
1530 DEBUG_PRINT_ERROR("pipe creation failed\n");
1531 eRet = OMX_ErrorInsufficientResources;
1532 }
1533 else
1534 {
1535 int temp2[2];
1536 if(fctl[0] == 0 || fctl[1] == 0)
1537 {
1538 if (pipe (temp2))
1539 {
1540 DEBUG_PRINT_ERROR("pipe creation failed\n");
1541 return OMX_ErrorInsufficientResources;
1542 }
1543 fctl[0] = temp2 [0];
1544 fctl[1] = temp2 [1];
1545 }
1546 m_ctrl_in = fctl[0];
1547 m_ctrl_out = fctl[1];
1548
1549 fcntl(m_ctrl_in, F_SETFL, O_NONBLOCK);
1550 fcntl(m_ctrl_out, F_SETFL, O_NONBLOCK);
1551 }
1552 }
1553
1554 if (!ret) {
1555 async_thread_created = true;
1556 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
1557 }
1558 if(ret) {
1559 DEBUG_PRINT_ERROR(" Failed to create async_message_thread \n");
1560 async_thread_created = false;
1561 return OMX_ErrorInsufficientResources;
1562 }
1563
1564 #ifdef INPUT_BUFFER_LOG
1565 inputBufferFile = open(inputfilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR);
1566 if(inputBufferFile < 0)
1567 {
1568 DEBUG_PRINT_ERROR(" Failed to create inputBufferFile 0, errno = %d\n", errno);
1569 }
1570
1571 #endif
1572
1573 #ifdef OUTPUT_BUFFER_LOG
1574 outputBufferFile = open(outputfilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR);
1575 if(outputBufferFile < 0)
1576 {
1577 DEBUG_PRINT_ERROR(" Failed to create outputBufferFile 0 , errno = %d\n", errno);
1578 }
1579 #endif
1580
1581 #ifdef OUTPUT_EXTRADATA_LOG
1582 outputExtradataFile = open (ouputextradatafilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR);
1583 if(outputExtradataFile == -1)
1584 {
1585 DEBUG_PRINT_ERROR(" Failed to create outputExtradataFile , errno = %d\n", errno);
1586 }
1587 #endif
1588
1589 // Copy the role information which provides the vdpp kind
1590 strlcpy(drv_ctx.kind,role,128);
1591
1592 // Default set to progressive mode for 8084. drv_ctx.interlace will be changed by
1593 // interlace format filed of OMX buffer header extra data. User can also overwrite
1594 // this setting by OMX_IndexParamInterlaceFormat
1595 drv_ctx.interlace = V4L2_FIELD_NONE;
1596
1597 // Default input pixel format
1598 output_capability=V4L2_PIX_FMT_NV12;
1599
1600 if (eRet == OMX_ErrorNone)
1601 {
1602 // set default output format to V4L2_PIX_FMT_NV12. User can use SetParam
1603 // with OMX_IndexParamVideoPortFormat to set vdpp output format
1604 drv_ctx.output_format = V4L2_PIX_FMT_NV12;
1605 capture_capability = V4L2_PIX_FMT_NV12;
1606
1607 struct v4l2_capability cap;
1608 #ifndef STUB_VPU
1609 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_QUERYCAP, &cap);
1610 if (ret) {
1611 DEBUG_PRINT_ERROR("Failed to query capabilities\n");
1612 return OMX_ErrorUndefined;
1613 } else {
1614 DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
1615 " version = %d, capabilities = %x\n", cap.driver, cap.card,
1616 cap.bus_info, cap.version, cap.capabilities);
1617
1618 if ((cap.capabilities & V4L2_CAP_STREAMING) == 0)
1619 {
1620 DEBUG_PRINT_ERROR("device does not support streaming i/o\n");
1621 return OMX_ErrorInsufficientResources;
1622 }
1623 }
1624 #endif
1625 // set initial input h/w and pixel format
1626 update_resolution(640, 480, 640, 480);
1627
1628 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1629 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_input.frame_height;
1630 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_input.frame_width;
1631 if (V4L2_FIELD_NONE == drv_ctx.interlace)
1632 {
1633 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1634 }
1635 else
1636 {
1637 fmt.fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
1638 }
1639 fmt.fmt.pix_mp.pixelformat = output_capability;
1640
1641 // NV12 has 2 planes.
1642 /* Set format for each plane. */
1643 setFormatParams(output_capability, drv_ctx.input_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
1644 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
1645 {
1646 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.input_bytesperpixel[i] * fmt.fmt.pix_mp.height);
1647 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.input_bytesperpixel[0]); // NV12 UV plane has the same width as Y, but 1/2 YH
1648 DEBUG_PRINT_HIGH(" fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n ", i, fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
1649 }
1650 #ifndef STUB_VPU
1651 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
1652
1653 if (ret) {
1654 DEBUG_PRINT_ERROR("Failed to set format on output port\n");
1655 return OMX_ErrorUndefined;
1656 }
1657 DEBUG_PRINT_HIGH(" Set Format was successful drv_ctx.interlace = %d\n ", drv_ctx.interlace);
1658 #endif
1659 // set initial output format
1660 // initial input/output resolution are the same. portdefinition changes both
1661 memset(&fmt, 0, sizeof(fmt));
1662
1663 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1664 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_input.frame_height;
1665 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_input.frame_width;
1666 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1667 fmt.fmt.pix_mp.pixelformat = capture_capability;
1668 DEBUG_PRINT_HIGH("VP output frame width = %d, height = %d", fmt.fmt.pix_mp.width,
1669 fmt.fmt.pix_mp.height);
1670
1671 setFormatParams(capture_capability, drv_ctx.output_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
1672 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
1673 {
1674 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width *
1675 drv_ctx.output_bytesperpixel[i] *
1676 fmt.fmt.pix_mp.height);
1677 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[0]);
1678 DEBUG_PRINT_HIGH(" fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n ", i, fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
1679 }
1680 #ifndef STUB_VPU
1681 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
1682 if (ret < 0)
1683 {
1684 DEBUG_PRINT_ERROR("VIDIOC_S_FMT setup VP output format error");
1685 return OMX_ErrorUndefined;
1686 }
1687 #endif
1688 // update initial output resolution
1689 drv_ctx.video_resolution_output.frame_height = fmt.fmt.pix_mp.height;
1690 drv_ctx.video_resolution_output.frame_width = fmt.fmt.pix_mp.width;
1691 drv_ctx.video_resolution_output.scan_lines = fmt.fmt.pix_mp.height;
1692 drv_ctx.video_resolution_output.stride = fmt.fmt.pix_mp.width;
1693
1694 if (ret) {
1695 DEBUG_PRINT_ERROR("Failed to set format on capture port\n");
1696 return OMX_ErrorUndefined;
1697 }
1698 DEBUG_PRINT_HIGH(" Set Format was successful \n ");
1699
1700 /*Get the Buffer requirements for input and output ports*/
1701 drv_ctx.ip_buf.buffer_type = VDPP_BUFFER_TYPE_INPUT;
1702 drv_ctx.op_buf.buffer_type = VDPP_BUFFER_TYPE_OUTPUT;
1703
1704 drv_ctx.op_buf.alignment=SZ_4K;
1705 drv_ctx.ip_buf.alignment=SZ_4K;
1706
1707 m_state = OMX_StateLoaded;
1708
1709 eRet=get_buffer_req(&drv_ctx.ip_buf);
1710 DEBUG_PRINT_HIGH("Input Buffer Size =%d \n ",drv_ctx.ip_buf.buffer_size);
1711 get_buffer_req(&drv_ctx.op_buf);
1712
1713 /* create pipes for message thread*/
1714 if(pipe(fds))
1715 {
1716 DEBUG_PRINT_ERROR("pipe creation failed\n");
1717 eRet = OMX_ErrorInsufficientResources;
1718 }
1719 else
1720 {
1721 int temp1[2];
1722 if(fds[0] == 0 || fds[1] == 0)
1723 {
1724 if (pipe (temp1))
1725 {
1726 DEBUG_PRINT_ERROR("pipe creation failed\n");
1727 return OMX_ErrorInsufficientResources;
1728 }
1729 fds[0] = temp1 [0];
1730 fds[1] = temp1 [1];
1731 }
1732 m_pipe_in = fds[0];
1733 m_pipe_out = fds[1];
1734 msg_thread_created = true;
1735 ret = pthread_create(&msg_thread_id,0,message_thread,this);
1736
1737 if(ret < 0)
1738 {
1739 DEBUG_PRINT_ERROR(" component_init(): message_thread creation failed");
1740 msg_thread_created = false;
1741 eRet = OMX_ErrorInsufficientResources;
1742 }
1743 }
1744 }
1745
1746 if (eRet != OMX_ErrorNone)
1747 {
1748 DEBUG_PRINT_ERROR(" Component Init Failed");
1749 }
1750 else
1751 {
1752 DEBUG_PRINT_HIGH(" omx_vdpp::component_init() success");
1753 }
1754
1755 return eRet;
1756 }
1757
1758 /* ======================================================================
1759 FUNCTION
1760 omx_vdpp::GetComponentVersion
1761
1762 DESCRIPTION
1763 Returns the component version.
1764
1765 PARAMETERS
1766 TBD.
1767
1768 RETURN VALUE
1769 OMX_ErrorNone.
1770
1771 ========================================================================== */
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)1772 OMX_ERRORTYPE omx_vdpp::get_component_version
1773 (
1774 OMX_IN OMX_HANDLETYPE hComp,
1775 OMX_OUT OMX_STRING componentName,
1776 OMX_OUT OMX_VERSIONTYPE* componentVersion,
1777 OMX_OUT OMX_VERSIONTYPE* specVersion,
1778 OMX_OUT OMX_UUIDTYPE* componentUUID
1779 )
1780 {
1781 if(m_state == OMX_StateInvalid)
1782 {
1783 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n");
1784 return OMX_ErrorInvalidState;
1785 }
1786 /* TBD -- Return the proper version */
1787 if (specVersion)
1788 {
1789 specVersion->nVersion = OMX_SPEC_VERSION;
1790 }
1791 return OMX_ErrorNone;
1792 }
1793 /* ======================================================================
1794 FUNCTION
1795 omx_vdpp::SendCommand
1796
1797 DESCRIPTION
1798 Returns zero if all the buffers released..
1799
1800 PARAMETERS
1801 None.
1802
1803 RETURN VALUE
1804 true/false
1805
1806 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1807 OMX_ERRORTYPE omx_vdpp::send_command(OMX_IN OMX_HANDLETYPE hComp,
1808 OMX_IN OMX_COMMANDTYPE cmd,
1809 OMX_IN OMX_U32 param1,
1810 OMX_IN OMX_PTR cmdData
1811 )
1812 {
1813 DEBUG_PRINT_LOW(" send_command: Recieved a Command from Client cmd = %d", cmd);
1814 if(m_state == OMX_StateInvalid)
1815 {
1816 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
1817 return OMX_ErrorInvalidState;
1818 }
1819 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
1820 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL)
1821 {
1822 DEBUG_PRINT_ERROR(" send_command(): ERROR OMX_CommandFlush "
1823 "to invalid port: %lu", param1);
1824 return OMX_ErrorBadPortIndex;
1825 }
1826 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
1827 sem_wait(&m_cmd_lock);
1828 DEBUG_PRINT_LOW(" send_command: Command Processed cmd = %d\n", cmd);
1829 return OMX_ErrorNone;
1830 }
1831
1832 /* ======================================================================
1833 FUNCTION
1834 omx_vdpp::SendCommand
1835
1836 DESCRIPTION
1837 Returns zero if all the buffers released..
1838
1839 PARAMETERS
1840 None.
1841
1842 RETURN VALUE
1843 true/false
1844
1845 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)1846 OMX_ERRORTYPE omx_vdpp::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
1847 OMX_IN OMX_COMMANDTYPE cmd,
1848 OMX_IN OMX_U32 param1,
1849 OMX_IN OMX_PTR cmdData
1850 )
1851 {
1852 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1853 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
1854 int bFlag = 1,sem_posted = 0,ret=0;
1855
1856 DEBUG_PRINT_LOW(" send_command_proxy(): cmd = %d", cmd);
1857 DEBUG_PRINT_HIGH("end_command_proxy(): Current State %d, Expected State %d",
1858 m_state, eState);
1859
1860 if(cmd == OMX_CommandStateSet)
1861 {
1862 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
1863 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
1864 /***************************/
1865 /* Current State is Loaded */
1866 /***************************/
1867 if(m_state == OMX_StateLoaded)
1868 {
1869 if(eState == OMX_StateIdle)
1870 {
1871 //if all buffers are allocated or all ports disabled
1872 if(allocate_done() ||
1873 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE))
1874 {
1875 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n");
1876 }
1877 else
1878 {
1879 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending\n");
1880 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
1881 // Skip the event notification
1882 bFlag = 0;
1883 }
1884 }
1885 /* Requesting transition from Loaded to Loaded */
1886 else if(eState == OMX_StateLoaded)
1887 {
1888 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded\n");
1889 post_event(OMX_EventError,OMX_ErrorSameState,\
1890 OMX_COMPONENT_GENERATE_EVENT);
1891 eRet = OMX_ErrorSameState;
1892 }
1893 /* Requesting transition from Loaded to WaitForResources */
1894 else if(eState == OMX_StateWaitForResources)
1895 {
1896 /* Since error is None , we will post an event
1897 at the end of this function definition */
1898 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources\n");
1899 }
1900 /* Requesting transition from Loaded to Executing */
1901 else if(eState == OMX_StateExecuting)
1902 {
1903 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n");
1904 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1905 OMX_COMPONENT_GENERATE_EVENT);
1906 eRet = OMX_ErrorIncorrectStateTransition;
1907 }
1908 /* Requesting transition from Loaded to Pause */
1909 else if(eState == OMX_StatePause)
1910 {
1911 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n");
1912 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1913 OMX_COMPONENT_GENERATE_EVENT);
1914 eRet = OMX_ErrorIncorrectStateTransition;
1915 }
1916 /* Requesting transition from Loaded to Invalid */
1917 else if(eState == OMX_StateInvalid)
1918 {
1919 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n");
1920 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1921 eRet = OMX_ErrorInvalidState;
1922 }
1923 else
1924 {
1925 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\
1926 eState);
1927 eRet = OMX_ErrorBadParameter;
1928 }
1929 }
1930
1931 /***************************/
1932 /* Current State is IDLE */
1933 /***************************/
1934 else if(m_state == OMX_StateIdle)
1935 {
1936 if(eState == OMX_StateLoaded)
1937 {
1938 if(release_done())
1939 {
1940 /*
1941 Since error is None , we will post an event at the end
1942 of this function definition
1943 */
1944 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded\n");
1945 }
1946 else
1947 {
1948 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending\n");
1949 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
1950 // Skip the event notification
1951 bFlag = 0;
1952 }
1953 }
1954 /* Requesting transition from Idle to Executing */
1955 else if(eState == OMX_StateExecuting)
1956 {
1957 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
1958 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
1959 bFlag = 1;
1960 m_state=OMX_StateExecuting;
1961 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful\n");
1962 }
1963 /* Requesting transition from Idle to Idle */
1964 else if(eState == OMX_StateIdle)
1965 {
1966 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n");
1967 post_event(OMX_EventError,OMX_ErrorSameState,\
1968 OMX_COMPONENT_GENERATE_EVENT);
1969 eRet = OMX_ErrorSameState;
1970 }
1971 /* Requesting transition from Idle to WaitForResources */
1972 else if(eState == OMX_StateWaitForResources)
1973 {
1974 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n");
1975 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1976 OMX_COMPONENT_GENERATE_EVENT);
1977 eRet = OMX_ErrorIncorrectStateTransition;
1978 }
1979 /* Requesting transition from Idle to Pause */
1980 else if(eState == OMX_StatePause)
1981 {
1982 /*To pause the Video core we need to start the driver*/
1983 if (/*ioctl (drv_ctx.video_vpu_fd,VDPP_IOCTL_CMD_START,
1984 NULL) < */0)
1985 {
1986 DEBUG_PRINT_ERROR(" VDPP_IOCTL_CMD_START FAILED");
1987 omx_report_error ();
1988 eRet = OMX_ErrorHardware;
1989 }
1990 else
1991 {
1992 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
1993 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n");
1994 bFlag = 0;
1995 }
1996 }
1997 /* Requesting transition from Idle to Invalid */
1998 else if(eState == OMX_StateInvalid)
1999 {
2000 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n");
2001 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2002 eRet = OMX_ErrorInvalidState;
2003 }
2004 else
2005 {
2006 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState);
2007 eRet = OMX_ErrorBadParameter;
2008 }
2009 }
2010
2011 /******************************/
2012 /* Current State is Executing */
2013 /******************************/
2014 else if(m_state == OMX_StateExecuting)
2015 {
2016 DEBUG_PRINT_LOW(" Command Recieved in OMX_StateExecuting");
2017 /* Requesting transition from Executing to Idle */
2018 if(eState == OMX_StateIdle)
2019 {
2020 /* Since error is None , we will post an event
2021 at the end of this function definition
2022 */
2023 DEBUG_PRINT_LOW(" send_command_proxy(): Executing --> Idle \n");
2024 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2025 if(!sem_posted)
2026 {
2027 sem_posted = 1;
2028 sem_post (&m_cmd_lock);
2029 execute_omx_flush(OMX_ALL);
2030 }
2031 bFlag = 0;
2032 }
2033 /* Requesting transition from Executing to Paused */
2034 else if(eState == OMX_StatePause)
2035 {
2036 DEBUG_PRINT_LOW(" PAUSE Command Issued");
2037 m_state = OMX_StatePause;
2038 bFlag = 1;
2039 }
2040 /* Requesting transition from Executing to Loaded */
2041 else if(eState == OMX_StateLoaded)
2042 {
2043 DEBUG_PRINT_ERROR(" send_command_proxy(): Executing --> Loaded \n");
2044 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2045 OMX_COMPONENT_GENERATE_EVENT);
2046 eRet = OMX_ErrorIncorrectStateTransition;
2047 }
2048 /* Requesting transition from Executing to WaitForResources */
2049 else if(eState == OMX_StateWaitForResources)
2050 {
2051 DEBUG_PRINT_ERROR(" send_command_proxy(): Executing --> WaitForResources \n");
2052 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2053 OMX_COMPONENT_GENERATE_EVENT);
2054 eRet = OMX_ErrorIncorrectStateTransition;
2055 }
2056 /* Requesting transition from Executing to Executing */
2057 else if(eState == OMX_StateExecuting)
2058 {
2059 DEBUG_PRINT_ERROR(" send_command_proxy(): Executing --> Executing \n");
2060 post_event(OMX_EventError,OMX_ErrorSameState,\
2061 OMX_COMPONENT_GENERATE_EVENT);
2062 eRet = OMX_ErrorSameState;
2063 }
2064 /* Requesting transition from Executing to Invalid */
2065 else if(eState == OMX_StateInvalid)
2066 {
2067 DEBUG_PRINT_ERROR(" send_command_proxy(): Executing --> Invalid \n");
2068 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2069 eRet = OMX_ErrorInvalidState;
2070 }
2071 else
2072 {
2073 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState);
2074 eRet = OMX_ErrorBadParameter;
2075 }
2076 }
2077 /***************************/
2078 /* Current State is Pause */
2079 /***************************/
2080 else if(m_state == OMX_StatePause)
2081 {
2082 /* Requesting transition from Pause to Executing */
2083 if(eState == OMX_StateExecuting)
2084 {
2085 DEBUG_PRINT_LOW(" Pause --> Executing \n");
2086 m_state = OMX_StateExecuting;
2087 bFlag = 1;
2088 }
2089 /* Requesting transition from Pause to Idle */
2090 else if(eState == OMX_StateIdle)
2091 {
2092 /* Since error is None , we will post an event
2093 at the end of this function definition */
2094 DEBUG_PRINT_LOW(" Pause --> Idle \n");
2095 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2096 if(!sem_posted)
2097 {
2098 sem_posted = 1;
2099 sem_post (&m_cmd_lock);
2100 execute_omx_flush(OMX_ALL);
2101 }
2102 bFlag = 0;
2103 }
2104 /* Requesting transition from Pause to loaded */
2105 else if(eState == OMX_StateLoaded)
2106 {
2107 DEBUG_PRINT_ERROR(" Pause --> loaded \n");
2108 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2109 OMX_COMPONENT_GENERATE_EVENT);
2110 eRet = OMX_ErrorIncorrectStateTransition;
2111 }
2112 /* Requesting transition from Pause to WaitForResources */
2113 else if(eState == OMX_StateWaitForResources)
2114 {
2115 DEBUG_PRINT_ERROR(" Pause --> WaitForResources \n");
2116 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2117 OMX_COMPONENT_GENERATE_EVENT);
2118 eRet = OMX_ErrorIncorrectStateTransition;
2119 }
2120 /* Requesting transition from Pause to Pause */
2121 else if(eState == OMX_StatePause)
2122 {
2123 DEBUG_PRINT_ERROR(" Pause --> Pause \n");
2124 post_event(OMX_EventError,OMX_ErrorSameState,\
2125 OMX_COMPONENT_GENERATE_EVENT);
2126 eRet = OMX_ErrorSameState;
2127 }
2128 /* Requesting transition from Pause to Invalid */
2129 else if(eState == OMX_StateInvalid)
2130 {
2131 DEBUG_PRINT_ERROR(" Pause --> Invalid \n");
2132 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2133 eRet = OMX_ErrorInvalidState;
2134 }
2135 else
2136 {
2137 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState);
2138 eRet = OMX_ErrorBadParameter;
2139 }
2140 }
2141 /***************************/
2142 /* Current State is WaitForResources */
2143 /***************************/
2144 else if(m_state == OMX_StateWaitForResources)
2145 {
2146 /* Requesting transition from WaitForResources to Loaded */
2147 if(eState == OMX_StateLoaded)
2148 {
2149 /* Since error is None , we will post an event
2150 at the end of this function definition */
2151 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded\n");
2152 }
2153 /* Requesting transition from WaitForResources to WaitForResources */
2154 else if (eState == OMX_StateWaitForResources)
2155 {
2156 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n");
2157 post_event(OMX_EventError,OMX_ErrorSameState,
2158 OMX_COMPONENT_GENERATE_EVENT);
2159 eRet = OMX_ErrorSameState;
2160 }
2161 /* Requesting transition from WaitForResources to Executing */
2162 else if(eState == OMX_StateExecuting)
2163 {
2164 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n");
2165 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2166 OMX_COMPONENT_GENERATE_EVENT);
2167 eRet = OMX_ErrorIncorrectStateTransition;
2168 }
2169 /* Requesting transition from WaitForResources to Pause */
2170 else if(eState == OMX_StatePause)
2171 {
2172 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n");
2173 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2174 OMX_COMPONENT_GENERATE_EVENT);
2175 eRet = OMX_ErrorIncorrectStateTransition;
2176 }
2177 /* Requesting transition from WaitForResources to Invalid */
2178 else if(eState == OMX_StateInvalid)
2179 {
2180 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n");
2181 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2182 eRet = OMX_ErrorInvalidState;
2183 }
2184 /* Requesting transition from WaitForResources to Loaded -
2185 is NOT tested by Khronos TS */
2186
2187 }
2188 else
2189 {
2190 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState);
2191 eRet = OMX_ErrorBadParameter;
2192 }
2193 }
2194 /********************************/
2195 /* Current State is Invalid */
2196 /*******************************/
2197 else if(m_state == OMX_StateInvalid)
2198 {
2199 /* State Transition from Invalid to any state */
2200 if(eState == OMX_StateLoaded || eState == OMX_StateWaitForResources ||
2201 eState == OMX_StateIdle || eState == OMX_StateExecuting ||
2202 eState == OMX_StatePause || eState == OMX_StateInvalid)
2203 {
2204 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n");
2205 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2206 OMX_COMPONENT_GENERATE_EVENT);
2207 eRet = OMX_ErrorInvalidState;
2208 }
2209 }
2210 else if (cmd == OMX_CommandFlush)
2211 {
2212 DEBUG_PRINT_HIGH(" send_command_proxy(): OMX_CommandFlush issued "
2213 "with param1: 0x%x", param1);
2214 if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1)
2215 { // do not call flush ioctl if there is no buffer queued. Just return callback
2216 #ifndef STUB_VPU // VPU stub doesn't set any streaming flag
2217 if(!streaming[OUTPUT_PORT])
2218 {
2219 m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete,OMX_CommandFlush,
2220 OMX_CORE_INPUT_PORT_INDEX,NULL );
2221 sem_posted = 1;
2222 sem_post (&m_cmd_lock);
2223 }
2224 else
2225 #endif
2226 {
2227 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2228 }
2229 }
2230 if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1)
2231 {
2232 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2233 }
2234 if (!sem_posted){
2235 sem_posted = 1;
2236 DEBUG_PRINT_LOW(" Set the Semaphore");
2237 sem_post (&m_cmd_lock);
2238 execute_omx_flush(param1);
2239 }
2240 bFlag = 0;
2241 }
2242 else if ( cmd == OMX_CommandPortEnable)
2243 {
2244 DEBUG_PRINT_HIGH(" send_command_proxy(): OMX_CommandPortEnable issued "
2245 "with param1: %lu", param1);
2246 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
2247 {
2248 m_inp_bEnabled = OMX_TRUE;
2249
2250 if( (m_state == OMX_StateLoaded &&
2251 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2252 || allocate_input_done())
2253 {
2254 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2255 OMX_COMPONENT_GENERATE_EVENT);
2256 }
2257 else
2258 {
2259 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
2260 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2261 // Skip the event notification
2262 bFlag = 0;
2263 }
2264 }
2265 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
2266 {
2267 DEBUG_PRINT_LOW(" Enable output Port command recieved");
2268 m_out_bEnabled = OMX_TRUE;
2269
2270 if( (m_state == OMX_StateLoaded &&
2271 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2272 || (allocate_output_done()))
2273 {
2274 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2275 OMX_COMPONENT_GENERATE_EVENT);
2276
2277 }
2278 else
2279 {
2280 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
2281 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2282 // Skip the event notification
2283 bFlag = 0;
2284 }
2285 }
2286 }
2287 else if (cmd == OMX_CommandPortDisable)
2288 {
2289 DEBUG_PRINT_HIGH(" send_command_proxy(): OMX_CommandPortDisable issued"
2290 "with param1: %lu m_state = %d, streaming[OUTPUT_PORT] = %d", param1, m_state, streaming[OUTPUT_PORT]);
2291 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
2292 {
2293 m_inp_bEnabled = OMX_FALSE;
2294 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2295 && release_input_done())
2296 {
2297 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2298 OMX_COMPONENT_GENERATE_EVENT);
2299 DEBUG_PRINT_LOW("OMX_CommandPortDisable 1");
2300 }
2301 else
2302 {
2303 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2304 DEBUG_PRINT_LOW("OMX_CommandPortDisable 2");
2305 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
2306 {
2307 if(!sem_posted)
2308 {
2309 sem_posted = 1;
2310 sem_post (&m_cmd_lock);
2311 }
2312 if(!streaming[OUTPUT_PORT])
2313 {
2314 DEBUG_PRINT_LOW("OMX_CommandPortDisable 3 ");
2315 //IL client calls disable port and then free buffers.
2316 //from free buffer, disable port done event will be sent
2317 }
2318 else
2319 {
2320 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2321 }
2322 }
2323
2324 // Skip the event notification
2325 bFlag = 0;
2326 }
2327 }
2328 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
2329 {
2330 m_out_bEnabled = OMX_FALSE;
2331 DEBUG_PRINT_LOW(" Disable output Port command recieved m_state = %d", m_state);
2332 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2333 && release_output_done())
2334 {
2335 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2336 OMX_COMPONENT_GENERATE_EVENT);
2337 }
2338 else
2339 {
2340 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2341 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
2342 {
2343 if (!sem_posted)
2344 {
2345 sem_posted = 1;
2346 sem_post (&m_cmd_lock);
2347 }
2348 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2349 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2350 }
2351 // Skip the event notification
2352 bFlag = 0;
2353
2354 }
2355 }
2356 }
2357 else
2358 {
2359 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd);
2360 eRet = OMX_ErrorNotImplemented;
2361 }
2362 if(eRet == OMX_ErrorNone && bFlag)
2363 {
2364 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2365 }
2366 if(!sem_posted)
2367 {
2368 sem_post(&m_cmd_lock);
2369 }
2370
2371 return eRet;
2372 }
2373
2374 /* ======================================================================
2375 FUNCTION
2376 omx_vdpp::ExecuteOmxFlush
2377
2378 DESCRIPTION
2379 Executes the OMX flush.
2380
2381 PARAMETERS
2382 flushtype - input flush(1)/output flush(0)/ both.
2383
2384 RETURN VALUE
2385 true/false
2386
2387 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)2388 bool omx_vdpp::execute_omx_flush(OMX_U32 flushType)
2389 {
2390 bool bRet = false;
2391 struct v4l2_requestbuffers bufreq;
2392 struct vdpp_msginfo vdpp_msg;
2393 enum v4l2_buf_type buf_type;
2394 unsigned i = 0;
2395
2396 DEBUG_PRINT_LOW("in %s flushType = %d", __func__, flushType);
2397 memset((void *)&vdpp_msg,0,sizeof(vdpp_msg));
2398
2399 switch (flushType)
2400 {
2401 case OMX_CORE_INPUT_PORT_INDEX:
2402 input_flush_progress = true;
2403
2404 break;
2405 case OMX_CORE_OUTPUT_PORT_INDEX:
2406 output_flush_progress = true;
2407
2408 break;
2409 default:
2410 input_flush_progress = true;
2411 output_flush_progress = true;
2412 }
2413
2414 DEBUG_PRINT_HIGH("omx_vdpp::execute_omx_flush m_ftb_q.m_size = %d, m_etb_q.m_size = %d\n", m_ftb_q.m_size, m_etb_q.m_size);
2415 // vpu doesn't have flush right now, simulate flush done from here
2416 #ifdef STUB_VPU
2417 {
2418 // dq output
2419 if(output_flush_progress)
2420 {
2421 vdpp_msg.msgcode=VDPP_MSG_RESP_FLUSH_OUTPUT_DONE;
2422 vdpp_msg.status_code=VDPP_S_SUCCESS;
2423 DEBUG_PRINT_HIGH("Simulate VDPP Output Flush Done Recieved From Driver\n");
2424 if (async_message_process(this,&vdpp_msg) < 0) {
2425 DEBUG_PRINT_HIGH(" VDPP Output Flush Done returns < 0 \n");
2426 }
2427 }
2428
2429 // dq input
2430 if(input_flush_progress)
2431 {
2432 vdpp_msg.msgcode=VDPP_MSG_RESP_FLUSH_INPUT_DONE;
2433 vdpp_msg.status_code=VDPP_S_SUCCESS;
2434 DEBUG_PRINT_HIGH("Simulate VDPP Input Flush Done Recieved From Driver \n");
2435 if (async_message_process(this,&vdpp_msg) < 0) {
2436 DEBUG_PRINT_HIGH(" VDPP Input Flush Done returns < 0 \n");
2437 }
2438
2439 }
2440
2441 }
2442 #else
2443 // flush input port
2444 if(input_flush_progress)
2445 {
2446 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2447
2448 if(ioctl(drv_ctx.video_vpu_fd, VPU_FLUSH_BUFS, &buf_type))
2449 {
2450 DEBUG_PRINT_ERROR("VDPP input Flush error! \n");
2451 return false;
2452 }
2453 else
2454 {
2455 DEBUG_PRINT_LOW("VDPP input Flush success! \n");
2456 }
2457 }
2458
2459 // flush output port
2460 if(output_flush_progress)
2461 {
2462 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2463
2464 if(ioctl(drv_ctx.video_vpu_fd, VPU_FLUSH_BUFS, &buf_type))
2465 {
2466 DEBUG_PRINT_ERROR("VDPP output Flush error! \n");
2467 return false;
2468 }
2469 else
2470 {
2471 DEBUG_PRINT_LOW("VDPP output Flush success! \n");
2472 }
2473 }
2474 #endif
2475
2476 return bRet;
2477 }
2478 /*=========================================================================
2479 FUNCTION : execute_output_flush
2480
2481 DESCRIPTION
2482 Executes the OMX flush at OUTPUT PORT.
2483
2484 PARAMETERS
2485 None.
2486
2487 RETURN VALUE
2488 true/false
2489 ==========================================================================*/
execute_output_flush()2490 bool omx_vdpp::execute_output_flush()
2491 {
2492 unsigned p1 = 0; // Parameter - 1
2493 unsigned p2 = 0; // Parameter - 2
2494 unsigned ident = 0;
2495 bool bRet = true;
2496
2497 /*Generate FBD for all Buffers in the FTBq*/
2498 pthread_mutex_lock(&m_lock);
2499 DEBUG_PRINT_LOW(" Initiate Output Flush, m_ftb_q.m_size = %d", m_ftb_q.m_size);
2500 while (m_ftb_q.m_size)
2501 {
2502 DEBUG_PRINT_LOW(" Buffer queue size %d pending buf cnt %d",
2503 m_ftb_q.m_size,pending_output_buffers);
2504 m_ftb_q.pop_entry(&p1,&p2,&ident);
2505 DEBUG_PRINT_LOW(" ID(%x) P1(%x) P2(%x)", ident, p1, p2);
2506 if(ident == m_fill_output_msg )
2507 {
2508 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2509 }
2510 else if (ident == OMX_COMPONENT_GENERATE_FBD)
2511 {
2512 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2513 }
2514 }
2515 pthread_mutex_unlock(&m_lock);
2516 output_flush_progress = false;
2517
2518 DEBUG_PRINT_HIGH(" OMX flush o/p Port complete PenBuf(%d), output_qbuf_count(%d), output_dqbuf_count(%d)",
2519 pending_output_buffers, output_qbuf_count, output_dqbuf_count);
2520 return bRet;
2521 }
2522 /*=========================================================================
2523 FUNCTION : execute_input_flush
2524
2525 DESCRIPTION
2526 Executes the OMX flush at INPUT PORT.
2527
2528 PARAMETERS
2529 None.
2530
2531 RETURN VALUE
2532 true/false
2533 ==========================================================================*/
execute_input_flush()2534 bool omx_vdpp::execute_input_flush()
2535 {
2536 unsigned i =0;
2537 unsigned p1 = 0; // Parameter - 1
2538 unsigned p2 = 0; // Parameter - 2
2539 unsigned ident = 0;
2540 bool bRet = true;
2541
2542 /*Generate EBD for all Buffers in the ETBq*/
2543 DEBUG_PRINT_LOW(" Initiate Input Flush \n");
2544
2545 pthread_mutex_lock(&m_lock);
2546 DEBUG_PRINT_LOW(" Check if the Queue is empty \n");
2547 while (m_etb_q.m_size)
2548 {
2549 DEBUG_PRINT_LOW(" m_etb_q.m_size = %d \n", m_etb_q.m_size);
2550 m_etb_q.pop_entry(&p1,&p2,&ident);
2551 DEBUG_PRINT_LOW("ident = %d \n", ident);
2552 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
2553 {
2554 DEBUG_PRINT_LOW(" Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
2555 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2556 }
2557 else if(ident == OMX_COMPONENT_GENERATE_ETB)
2558 {
2559 pending_input_buffers++;
2560 DEBUG_PRINT_LOW(" Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
2561 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
2562 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2563 }
2564 else if (ident == OMX_COMPONENT_GENERATE_EBD)
2565 {
2566 DEBUG_PRINT_LOW(" Flush Input OMX_COMPONENT_GENERATE_EBD %p",
2567 (OMX_BUFFERHEADERTYPE *)p1);
2568 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2569 }
2570 }
2571
2572 pthread_mutex_unlock(&m_lock);
2573 input_flush_progress = false;
2574
2575 prev_ts = LLONG_MAX;
2576 rst_prev_ts = true;
2577
2578 #ifdef _ANDROID_
2579 if (m_debug_timestamp)
2580 {
2581 m_timestamp_list.reset_ts_list();
2582 }
2583 #endif
2584
2585 DEBUG_PRINT_HIGH(" OMX flush i/p Port complete PenBuf(%d), input_qbuf_count(%d), input_dqbuf_count(%d)",
2586 pending_input_buffers, input_qbuf_count, input_dqbuf_count);
2587 return bRet;
2588 }
2589
2590
2591 /* ======================================================================
2592 FUNCTION
2593 omx_vdpp::SendCommandEvent
2594
2595 DESCRIPTION
2596 Send the event to VDPP pipe. This is needed to generate the callbacks
2597 in VDPP thread context.
2598
2599 PARAMETERS
2600 None.
2601
2602 RETURN VALUE
2603 true/false
2604
2605 ========================================================================== */
post_event(unsigned int p1,unsigned int p2,unsigned int id)2606 bool omx_vdpp::post_event(unsigned int p1,
2607 unsigned int p2,
2608 unsigned int id)
2609 {
2610 bool bRet = false;
2611
2612 pthread_mutex_lock(&m_lock);
2613 //DEBUG_PRINT_LOW("m_fill_output_msg = %d, OMX_COMPONENT_GENERATE_FBD = %d, id = %d", m_fill_output_msg, OMX_COMPONENT_GENERATE_FBD, id);
2614 if (id == m_fill_output_msg ||
2615 id == OMX_COMPONENT_GENERATE_FBD)
2616 {
2617 //DEBUG_PRINT_LOW(" post_event p2 = 0x%x, id = 0x%x", p2, id);
2618 m_ftb_q.insert_entry(p1,p2,id);
2619 }
2620 else if (id == OMX_COMPONENT_GENERATE_ETB ||
2621 id == OMX_COMPONENT_GENERATE_EBD ||
2622 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
2623 {
2624 m_etb_q.insert_entry(p1,p2,id);
2625 }
2626 else
2627 {
2628 m_cmd_q.insert_entry(p1,p2,id);
2629 }
2630
2631 bRet = true;
2632 //DEBUG_PRINT_LOW(" Value of this pointer in post_event %p, id = %d",this, id);
2633 post_message(this, id);
2634
2635 pthread_mutex_unlock(&m_lock);
2636
2637 return bRet;
2638 }
2639
2640 /* ======================================================================
2641 FUNCTION
2642 omx_vdpp::GetParameter
2643
2644 DESCRIPTION
2645 OMX Get Parameter method implementation
2646
2647 PARAMETERS
2648 <TBD>.
2649
2650 RETURN VALUE
2651 Error None if successful.
2652
2653 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)2654 OMX_ERRORTYPE omx_vdpp::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
2655 OMX_IN OMX_INDEXTYPE paramIndex,
2656 OMX_INOUT OMX_PTR paramData)
2657 {
2658 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2659
2660 DEBUG_PRINT_HIGH("get_parameter: \n");
2661 if(m_state == OMX_StateInvalid)
2662 {
2663 DEBUG_PRINT_ERROR("Get Param in Invalid State\n");
2664 return OMX_ErrorInvalidState;
2665 }
2666 if(paramData == NULL)
2667 {
2668 DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n");
2669 return OMX_ErrorBadParameter;
2670 }
2671 //DEBUG_PRINT_HIGH("get_parameter 1 : \n");
2672 switch((unsigned long)paramIndex)
2673 {
2674 case OMX_IndexParamPortDefinition:
2675 {
2676 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
2677 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2678 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
2679 eRet = update_portdef(portDefn);
2680 if (eRet == OMX_ErrorNone)
2681 m_port_def = *portDefn;
2682 break;
2683 }
2684 case OMX_IndexParamVideoInit:
2685 {
2686 OMX_PORT_PARAM_TYPE *portParamType =
2687 (OMX_PORT_PARAM_TYPE *) paramData;
2688 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");
2689
2690 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2691 portParamType->nSize = sizeof(portParamType);
2692 portParamType->nPorts = 2;
2693 portParamType->nStartPortNumber = 0;
2694 break;
2695 }
2696 case OMX_IndexParamVideoPortFormat:
2697 {
2698 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2699 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2700 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n");
2701
2702 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
2703 portFmt->nSize = sizeof(portFmt);
2704
2705 if (OMX_CORE_INPUT_PORT_INDEX == portFmt->nPortIndex)
2706 {
2707 if (0 == portFmt->nIndex)
2708 {
2709 portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;//OMX_COLOR_FormatYUV420Planar;//OMX_COLOR_FormatUnused;
2710 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
2711 }
2712 else
2713 {
2714 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
2715 " NoMore compression formats\n");
2716 eRet = OMX_ErrorNoMore;
2717 }
2718 }
2719 else if (OMX_CORE_OUTPUT_PORT_INDEX == portFmt->nPortIndex)
2720 {
2721 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
2722
2723 if(0 == portFmt->nIndex)
2724 portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
2725 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2726 else
2727 {
2728 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
2729 " NoMore Color formats\n");
2730 eRet = OMX_ErrorNoMore;
2731 }
2732 DEBUG_PRINT_ERROR("returning %d\n", portFmt->eColorFormat);
2733 }
2734 else
2735 {
2736 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n",
2737 (int)portFmt->nPortIndex);
2738 eRet = OMX_ErrorBadPortIndex;
2739 }
2740 break;
2741 }
2742 /*Component should support this port definition*/
2743 case OMX_IndexParamAudioInit:
2744 {
2745 OMX_PORT_PARAM_TYPE *audioPortParamType =
2746 (OMX_PORT_PARAM_TYPE *) paramData;
2747 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n");
2748 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2749 audioPortParamType->nSize = sizeof(audioPortParamType);
2750 audioPortParamType->nPorts = 0;
2751 audioPortParamType->nStartPortNumber = 0;
2752 break;
2753 }
2754 /*Component should support this port definition*/
2755 case OMX_IndexParamImageInit:
2756 {
2757 OMX_PORT_PARAM_TYPE *imagePortParamType =
2758 (OMX_PORT_PARAM_TYPE *) paramData;
2759 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n");
2760 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2761 imagePortParamType->nSize = sizeof(imagePortParamType);
2762 imagePortParamType->nPorts = 0;
2763 imagePortParamType->nStartPortNumber = 0;
2764 break;
2765
2766 }
2767 /*Component should support this port definition*/
2768 case OMX_IndexParamOtherInit:
2769 {
2770 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n",
2771 paramIndex);
2772 eRet =OMX_ErrorUnsupportedIndex;
2773 break;
2774 }
2775 case OMX_IndexParamStandardComponentRole:
2776 {
2777 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2778 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2779 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
2780 comp_role->nSize = sizeof(*comp_role);
2781
2782 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",
2783 paramIndex);
2784 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
2785 OMX_MAX_STRINGNAME_SIZE);
2786 break;
2787 }
2788 /* Added for parameter test */
2789 case OMX_IndexParamPriorityMgmt:
2790 {
2791
2792 OMX_PRIORITYMGMTTYPE *priorityMgmType =
2793 (OMX_PRIORITYMGMTTYPE *) paramData;
2794 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
2795 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
2796 priorityMgmType->nSize = sizeof(priorityMgmType);
2797
2798 break;
2799 }
2800 /* Added for parameter test */
2801 case OMX_IndexParamCompBufferSupplier:
2802 {
2803 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
2804 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
2805 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");
2806
2807 bufferSupplierType->nSize = sizeof(bufferSupplierType);
2808 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
2809 if(OMX_CORE_INPUT_PORT_INDEX == bufferSupplierType->nPortIndex)
2810 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2811 else if (OMX_CORE_OUTPUT_PORT_INDEX == bufferSupplierType->nPortIndex)
2812 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2813 else
2814 eRet = OMX_ErrorBadPortIndex;
2815
2816
2817 break;
2818 }
2819 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
2820 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
2821 {
2822 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
2823 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
2824 if((nativeBuffersUsage->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) || (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX))
2825 {
2826 #ifdef USE_ION
2827 #if defined (MAX_RES_720P)
2828 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_CAMERA_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2829 DEBUG_PRINT_HIGH("ION:720P: nUsage 0x%x",nativeBuffersUsage->nUsage);
2830 #else
2831 {
2832 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
2833 DEBUG_PRINT_HIGH("ION:non_secure_mode: nUsage 0x%lx",nativeBuffersUsage->nUsage);
2834 }
2835 #endif //(MAX_RES_720P)
2836 #else // USE_ION
2837 #if defined (MAX_RES_720P) || defined (MAX_RES_1080P_EBI)
2838 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2839 DEBUG_PRINT_HIGH("720P/1080P_EBI: nUsage 0x%x",nativeBuffersUsage->nUsage);
2840 #elif MAX_RES_1080P
2841 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_SMI_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2842 DEBUG_PRINT_HIGH("1080P: nUsage 0x%x",nativeBuffersUsage->nUsage);
2843 #endif
2844 #endif // USE_ION
2845 } else {
2846 DEBUG_PRINT_ERROR(" get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
2847 eRet = OMX_ErrorBadParameter;
2848 }
2849 }
2850 break;
2851 #endif
2852
2853 default:
2854 {
2855 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex);
2856 eRet =OMX_ErrorUnsupportedIndex;
2857 }
2858
2859 }
2860
2861 DEBUG_PRINT_LOW(" get_parameter returning input WxH(%d x %d) SxSH(%d x %d)\n",
2862 drv_ctx.video_resolution_input.frame_width,
2863 drv_ctx.video_resolution_input.frame_height,
2864 drv_ctx.video_resolution_input.stride,
2865 drv_ctx.video_resolution_input.scan_lines);
2866
2867 DEBUG_PRINT_LOW(" get_parameter returning output WxH(%d x %d) SxSH(%d x %d)\n",
2868 drv_ctx.video_resolution_output.frame_width,
2869 drv_ctx.video_resolution_output.frame_height,
2870 drv_ctx.video_resolution_output.stride,
2871 drv_ctx.video_resolution_output.scan_lines);
2872
2873 return eRet;
2874 }
2875
2876 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)2877 OMX_ERRORTYPE omx_vdpp::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
2878 {
2879 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
2880 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2881 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
2882
2883 if((params == NULL) ||
2884 (params->nativeBuffer == NULL) ||
2885 (params->nativeBuffer->handle == NULL) ||
2886 !m_enable_android_native_buffers)
2887 return OMX_ErrorBadParameter;
2888 m_use_android_native_buffers = OMX_TRUE;
2889 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
2890 private_handle_t *handle = (private_handle_t *)nBuf->handle;
2891 if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
2892 OMX_U8 *buffer = NULL;
2893
2894 buffer = (OMX_U8*)mmap(0, handle->size,
2895 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
2896 if(buffer == MAP_FAILED) {
2897 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
2898 return OMX_ErrorInsufficientResources;
2899 }
2900 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
2901 } else {
2902 eRet = OMX_ErrorBadParameter;
2903 }
2904 return eRet;
2905 }
2906 #endif
2907 /* ======================================================================
2908 FUNCTION
2909 omx_vdpp::Setparameter
2910
2911 DESCRIPTION
2912 OMX Set Parameter method implementation.
2913
2914 PARAMETERS
2915 <TBD>.
2916
2917 RETURN VALUE
2918 OMX Error None if successful.
2919
2920 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)2921 OMX_ERRORTYPE omx_vdpp::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
2922 OMX_IN OMX_INDEXTYPE paramIndex,
2923 OMX_IN OMX_PTR paramData)
2924 {
2925 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2926 int ret=0;
2927 int i = 0;
2928 struct v4l2_format fmt;
2929
2930 if(m_state == OMX_StateInvalid)
2931 {
2932 DEBUG_PRINT_ERROR("Set Param in Invalid State\n");
2933 return OMX_ErrorInvalidState;
2934 }
2935 if(paramData == NULL)
2936 {
2937 DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n");
2938 return OMX_ErrorBadParameter;
2939 }
2940 if((m_state != OMX_StateLoaded) &&
2941 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
2942 (m_out_bEnabled == OMX_TRUE) &&
2943 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
2944 (m_inp_bEnabled == OMX_TRUE)) {
2945 DEBUG_PRINT_ERROR("Set Param in Invalid State \n");
2946 return OMX_ErrorIncorrectStateOperation;
2947 }
2948 switch((unsigned long)paramIndex)
2949 {
2950 case OMX_IndexParamPortDefinition:
2951 {
2952 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2953 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2954
2955 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
2956 (int)portDefn->format.video.nFrameHeight,
2957 (int)portDefn->format.video.nFrameWidth);
2958
2959 if(OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex)
2960 {
2961 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port\n");
2962
2963 unsigned int buffer_size;
2964 memset(&fmt, 0, sizeof(fmt));
2965
2966 // set output resolution based on port definition. scan_lines and stride settings need
2967 // to match format setting requirement (QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)
2968 {
2969 DEBUG_PRINT_LOW(" SetParam OP: WxH(%lu x %lu)\n",
2970 portDefn->format.video.nFrameWidth,
2971 portDefn->format.video.nFrameHeight);
2972 if (portDefn->format.video.nFrameHeight != 0x0 &&
2973 portDefn->format.video.nFrameWidth != 0x0)
2974 {
2975 drv_ctx.video_resolution_output.frame_height = portDefn->format.video.nFrameHeight;
2976 drv_ctx.video_resolution_output.frame_width = portDefn->format.video.nFrameWidth;
2977 drv_ctx.video_resolution_output.scan_lines = paddedFrameWidth32(portDefn->format.video.nFrameHeight);
2978 drv_ctx.video_resolution_output.stride = paddedFrameWidth128(portDefn->format.video.nFrameWidth);
2979
2980 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2981 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_output.frame_height;
2982 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_output.frame_width;
2983 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
2984 fmt.fmt.pix_mp.pixelformat = capture_capability;
2985 DEBUG_PRINT_HIGH("VP output frame width = %d, height = %d, drv_ctx.video_resolution_output.stride = %d, drv_ctx.video_resolution_output.scan_lines = %d", fmt.fmt.pix_mp.width,
2986 fmt.fmt.pix_mp.height, drv_ctx.video_resolution_output.stride, drv_ctx.video_resolution_output.scan_lines);
2987 // NV12 has 2 planes.
2988 /* Set format for each plane. */
2989 setFormatParams(capture_capability, drv_ctx.output_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
2990 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
2991 {
2992 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[i] * fmt.fmt.pix_mp.height);
2993 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[0]); // both plane have the same plane stride
2994 DEBUG_PRINT_HIGH("before VIDIOC_S_FMT (op) fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
2995
2996 }
2997
2998 #ifndef STUB_VPU
2999 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
3000 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3001 {
3002 DEBUG_PRINT_HIGH("after VIDIOC_S_FMT (op) fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
3003 }
3004
3005 if (ret)
3006 {
3007 DEBUG_PRINT_ERROR(" Set Resolution failed");
3008 eRet = OMX_ErrorUnsupportedSetting;
3009 }
3010 else
3011 #endif
3012 {
3013 eRet = get_buffer_req(&drv_ctx.op_buf);
3014
3015 // eRet = get_buffer_req(&drv_ctx.ip_buf);
3016 }
3017
3018 }
3019 }
3020 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount /*||
3021 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size*/ )
3022 {
3023 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
3024 //drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
3025 eRet = set_buffer_req(&drv_ctx.op_buf);
3026 if (eRet == OMX_ErrorNone)
3027 m_port_def = *portDefn;
3028 }
3029 else
3030 {
3031 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%lu: %lu)\n",
3032 drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size,
3033 portDefn->nBufferCountActual, portDefn->nBufferSize);
3034 eRet = OMX_ErrorBadParameter;
3035 }
3036 }
3037 else if(OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex)
3038 {
3039 // TODO for 8092 the frame rate code below can be enabled to debug frame rate
3040 #ifdef FRC_ENABLE
3041 if((portDefn->format.video.xFramerate >> 16) > 0 &&
3042 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS)
3043 {
3044 // Frame rate only should be set if this is a "known value" or to
3045 // activate ts prediction logic (arbitrary mode only) sending input
3046 // timestamps with max value (LLONG_MAX).
3047 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %lu",
3048 portDefn->format.video.xFramerate >> 16);
3049 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
3050 drv_ctx.frame_rate.fps_denominator);
3051 if(!drv_ctx.frame_rate.fps_numerator)
3052 {
3053 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
3054 drv_ctx.frame_rate.fps_numerator = 30;
3055 }
3056 if(drv_ctx.frame_rate.fps_denominator)
3057 drv_ctx.frame_rate.fps_numerator = (int)
3058 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
3059 drv_ctx.frame_rate.fps_denominator = 1;
3060 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
3061 drv_ctx.frame_rate.fps_numerator;
3062 DEBUG_PRINT_HIGH("set_parameter: frm_int(%lu) fps(%.2f)",
3063 frm_int, drv_ctx.frame_rate.fps_numerator /
3064 (float)drv_ctx.frame_rate.fps_denominator);
3065
3066 struct v4l2_outputparm oparm;
3067 /*XXX: we're providing timing info as seconds per frame rather than frames
3068 * per second.*/
3069 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
3070 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
3071
3072 struct v4l2_streamparm sparm;
3073 memset(&sparm, 0, sizeof(struct v4l2_streamparm));
3074 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3075 sparm.parm.output = oparm;
3076 if (ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_PARM, &sparm)) {
3077 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
3078 performance might be affected");
3079 eRet = OMX_ErrorHardware;
3080 }
3081 }
3082 #endif
3083 memset(&fmt, 0, sizeof(fmt));
3084 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port\n");
3085 if(drv_ctx.video_resolution_input.frame_height !=
3086 portDefn->format.video.nFrameHeight ||
3087 drv_ctx.video_resolution_input.frame_width !=
3088 portDefn->format.video.nFrameWidth)
3089 {
3090 DEBUG_PRINT_LOW(" SetParam IP: WxH(%lu x %lu)\n",
3091 portDefn->format.video.nFrameWidth,
3092 portDefn->format.video.nFrameHeight);
3093 if (portDefn->format.video.nFrameHeight != 0x0 &&
3094 portDefn->format.video.nFrameWidth != 0x0)
3095 {
3096 update_resolution(portDefn->format.video.nFrameWidth,
3097 (portDefn->format.video.nFrameHeight),
3098 portDefn->format.video.nStride,
3099 (portDefn->format.video.nSliceHeight));
3100
3101 // decoder stride information is not used in S_FMT and QBUF, since paddedWidth
3102 // will ensure the buffer length/size is always aligned with 128 bytes, which
3103 // has the same effect as stride.
3104 // output has Width 720, and nStride = 768
3105 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3106 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_input.frame_height;
3107 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_input.frame_width;
3108 if (V4L2_FIELD_NONE == drv_ctx.interlace)
3109 {
3110 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
3111 }
3112 else
3113 {
3114 fmt.fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
3115 }
3116 fmt.fmt.pix_mp.pixelformat = output_capability;
3117
3118 // NV12 has 2 planes.
3119 /* Set format for each plane. */
3120 setFormatParams(output_capability, drv_ctx.input_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
3121 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3122 {
3123 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.input_bytesperpixel[i] * fmt.fmt.pix_mp.height);
3124 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.input_bytesperpixel[0]); // both plane have the same plane stride
3125 DEBUG_PRINT_HIGH("before VIDIOC_S_FMT (ip) fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
3126 }
3127
3128 #ifndef STUB_VPU
3129 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
3130 // for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3131 // {
3132 //DEBUG_PRINT_HIGH("after VIDIOC_S_FMT (ip) fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
3133 // }
3134 if (ret)
3135 {
3136 DEBUG_PRINT_ERROR(" Set Resolution failed");
3137 eRet = OMX_ErrorUnsupportedSetting;
3138 }
3139 else
3140 #endif
3141 {
3142 DEBUG_PRINT_HIGH("after VIDIOC_S_FMT (ip) drv_ctx.interlace = %d", drv_ctx.interlace);
3143 // set output resolution the same as input
3144 drv_ctx.video_resolution_output.frame_height = portDefn->format.video.nFrameHeight;
3145 drv_ctx.video_resolution_output.frame_width = portDefn->format.video.nFrameWidth;
3146 drv_ctx.video_resolution_output.scan_lines = paddedFrameWidth32(portDefn->format.video.nSliceHeight);
3147 drv_ctx.video_resolution_output.stride = paddedFrameWidth128(portDefn->format.video.nStride);
3148
3149 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3150 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_output.frame_height;
3151 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_output.frame_width;
3152 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
3153 fmt.fmt.pix_mp.pixelformat = capture_capability;
3154 DEBUG_PRINT_HIGH("VP output frame width = %d, height = %d, drv_ctx.video_resolution_output.stride = %d, drv_ctx.video_resolution_output.scan_lines = %d", fmt.fmt.pix_mp.width,
3155 fmt.fmt.pix_mp.height, drv_ctx.video_resolution_output.stride, drv_ctx.video_resolution_output.scan_lines);
3156 // NV12 has 2 planes.
3157 /* Set format for each plane. */
3158 setFormatParams(capture_capability, drv_ctx.output_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
3159 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3160 {
3161 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[i] * fmt.fmt.pix_mp.height);
3162 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[0]); // both plane have the same plane stride
3163 DEBUG_PRINT_HIGH("before VIDIOC_S_FMT op fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
3164 }
3165
3166 #ifndef STUB_VPU
3167 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
3168 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3169 {
3170 DEBUG_PRINT_HIGH("after VIDIOC_S_FMT op fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n",i,fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
3171 }
3172
3173 if (ret)
3174 {
3175 DEBUG_PRINT_ERROR(" Set Resolution failed");
3176 eRet = OMX_ErrorUnsupportedSetting;
3177 }
3178 else
3179 #endif
3180 {
3181 // get buffer req for input, output buffer size is
3182 // determined by output pixel format and output resolution
3183 //eRet = get_buffer_req(&drv_ctx.op_buf);
3184 eRet = get_buffer_req(&drv_ctx.ip_buf);
3185 }
3186 }
3187 }
3188 }
3189
3190 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
3191 /*|| portDefn->nBufferSize >= drv_ctx.ip_buf.buffer_size*/)
3192 // only allocate larger size
3193 {
3194 DEBUG_PRINT_HIGH("portDefn->nBufferCountActual = %lu portDefn->nBufferSize = %lu, drv_ctx.ip_buf.buffer_size=%d \n", portDefn->nBufferCountActual, portDefn->nBufferSize, drv_ctx.ip_buf.buffer_size);
3195 vdpp_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
3196 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
3197 //if(portDefn->nBufferSize >= drv_ctx.ip_buf.buffer_size)
3198 //{
3199 // drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
3200 // (~(buffer_prop->alignment - 1));
3201 // DEBUG_PRINT_HIGH("drv_ctx.ip_buf.buffer_size = %d, buffer_prop->alignment = %d\n", drv_ctx.ip_buf.buffer_size, buffer_prop->alignment);
3202 //}
3203 eRet = set_buffer_req(buffer_prop);
3204 }
3205 else
3206 {
3207 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%lu: %lu)\n",
3208 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size,
3209 portDefn->nBufferCountActual, portDefn->nBufferSize);
3210 eRet = OMX_ErrorBadParameter;
3211 }
3212 }
3213 else if (portDefn->eDir == OMX_DirMax)
3214 {
3215 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
3216 (int)portDefn->nPortIndex);
3217 eRet = OMX_ErrorBadPortIndex;
3218 }
3219 }
3220 break;
3221 case OMX_IndexParamVideoPortFormat:
3222 {
3223 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3224 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3225 int ret=0;
3226 struct v4l2_format fmt;
3227 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
3228 portFmt->eColorFormat);
3229
3230 if(OMX_CORE_OUTPUT_PORT_INDEX == portFmt->nPortIndex)
3231 {
3232 uint32_t op_format;
3233
3234 memset(&fmt, 0, sizeof(fmt));
3235 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3236 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_output.frame_height;
3237 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_output.frame_width;
3238 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
3239
3240 // TODO based on output format
3241 // update OMX format type for additional output format supported by 8084
3242 if((portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
3243 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) ||
3244 (portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar))
3245 op_format = (uint32_t)V4L2_PIX_FMT_NV12;
3246 else if(portFmt->eColorFormat ==
3247 (OMX_COLOR_FORMATTYPE)
3248 QOMX_COLOR_FormatYVU420SemiPlanar)
3249 op_format = V4L2_PIX_FMT_NV21;
3250 else
3251 eRet = OMX_ErrorBadParameter;
3252
3253 if(eRet == OMX_ErrorNone)
3254 {
3255 drv_ctx.output_format = op_format;
3256 capture_capability = op_format;
3257 fmt.fmt.pix_mp.pixelformat = capture_capability;
3258
3259 DEBUG_PRINT_HIGH("VP output frame width = %d, height = %d", fmt.fmt.pix_mp.width,
3260 fmt.fmt.pix_mp.height);
3261
3262 setFormatParams(capture_capability, drv_ctx.output_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
3263 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
3264 {
3265 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width *
3266 drv_ctx.output_bytesperpixel[i] *
3267 fmt.fmt.pix_mp.height);
3268 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[0]);
3269 }
3270 #ifndef STUB_VPU
3271 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
3272 if(ret)
3273 {
3274 DEBUG_PRINT_ERROR(" Set output format failed");
3275 eRet = OMX_ErrorUnsupportedSetting;
3276 }
3277 else
3278 #endif
3279 {
3280 eRet = get_buffer_req(&drv_ctx.op_buf);
3281 }
3282 }
3283 }
3284 }
3285 break;
3286
3287 case OMX_IndexParamStandardComponentRole:
3288 {
3289 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3290 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3291 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n",
3292 comp_role->cRole);
3293
3294 if((m_state == OMX_StateLoaded)&&
3295 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3296 {
3297 DEBUG_PRINT_LOW("Set Parameter called in valid state");
3298 }
3299 else
3300 {
3301 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
3302 return OMX_ErrorIncorrectStateOperation;
3303 }
3304
3305 // no component role yet
3306 /* if(!strncmp(drv_ctx.kind, "OMX.qcom.video.vidpp",OMX_MAX_STRINGNAME_SIZE))
3307 {
3308 if(!strncmp((char*)comp_role->cRole,"video.vidpp",OMX_MAX_STRINGNAME_SIZE))
3309 {
3310 strlcpy((char*)m_cRole,"video.vidpp",OMX_MAX_STRINGNAME_SIZE);
3311 }
3312 else
3313 {
3314 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3315 eRet =OMX_ErrorUnsupportedSetting;
3316 }
3317 }
3318 else
3319 {
3320 DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", drv_ctx.kind);
3321 eRet = OMX_ErrorInvalidComponentName;
3322 } */
3323 break;
3324 }
3325
3326 case OMX_IndexParamPriorityMgmt:
3327 {
3328 if(m_state != OMX_StateLoaded)
3329 {
3330 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
3331 return OMX_ErrorIncorrectStateOperation;
3332 }
3333 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
3334 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %lu\n",
3335 priorityMgmtype->nGroupID);
3336
3337 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %lu\n",
3338 priorityMgmtype->nGroupPriority);
3339
3340 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
3341 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
3342
3343 break;
3344 }
3345
3346 case OMX_IndexParamCompBufferSupplier:
3347 {
3348 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3349 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
3350 bufferSupplierType->eBufferSupplier);
3351 if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
3352 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
3353
3354 else
3355
3356 eRet = OMX_ErrorBadPortIndex;
3357
3358 break;
3359
3360 }
3361 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3362 /* Need to allow following two set_parameters even in Idle
3363 * state. This is ANDROID architecture which is not in sync
3364 * with openmax standard. */
3365 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
3366 {
3367 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
3368 if(enableNativeBuffers) {
3369 m_enable_android_native_buffers = enableNativeBuffers->enable;
3370 }
3371 DEBUG_PRINT_HIGH("OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: enableNativeBuffers %d\n", m_enable_android_native_buffers);
3372 }
3373 break;
3374 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
3375 {
3376 eRet = use_android_native_buffer(hComp, paramData);
3377 }
3378 break;
3379 #endif
3380 case OMX_QcomIndexParamInterlaceExtraData:
3381 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA,
3382 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3383
3384 break;
3385 case OMX_IndexParamInterlaceFormat:
3386 {
3387 OMX_INTERLACEFORMATTYPE *interlaceFormat = ( OMX_INTERLACEFORMATTYPE *)paramData;
3388 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamInterlaceFormat %ld\n",
3389 interlaceFormat->nFormat);
3390
3391 if(OMX_InterlaceInterleaveFrameBottomFieldFirst == (OMX_U32)interlaceFormat->nFormat)
3392 {
3393 drv_ctx.interlace = V4L2_FIELD_INTERLACED_BT;
3394 DEBUG_PRINT_LOW("set_parameter: V4L2_FIELD_INTERLACED_BT");
3395 interlace_user_flag = true;
3396 }
3397 else if(OMX_InterlaceInterleaveFrameTopFieldFirst == (OMX_U32)interlaceFormat->nFormat)
3398 {
3399 drv_ctx.interlace = V4L2_FIELD_INTERLACED_TB;
3400 DEBUG_PRINT_LOW("set_parameter: V4L2_FIELD_INTERLACED_TB");
3401 interlace_user_flag = true;
3402 }
3403 else if(OMX_InterlaceFrameProgressive == (OMX_U32)interlaceFormat->nFormat)
3404 {
3405 drv_ctx.interlace = V4L2_FIELD_NONE;
3406 DEBUG_PRINT_LOW("set_parameter: V4L2_FIELD_NONE");
3407 interlace_user_flag = true;
3408 }
3409 else
3410 {
3411 DEBUG_PRINT_ERROR("Setparameter: unknown param %lu\n", interlaceFormat->nFormat);
3412 eRet = OMX_ErrorBadParameter;
3413 }
3414 }
3415 break;
3416 default:
3417 {
3418 DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex);
3419 eRet = OMX_ErrorUnsupportedIndex;
3420 }
3421 }
3422 return eRet;
3423 }
3424
3425 /* ======================================================================
3426 FUNCTION
3427 omx_vdpp::GetConfig
3428
3429 DESCRIPTION
3430 OMX Get Config Method implementation.
3431
3432 PARAMETERS
3433 <TBD>.
3434
3435 RETURN VALUE
3436 OMX Error None if successful.
3437
3438 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)3439 OMX_ERRORTYPE omx_vdpp::get_config(OMX_IN OMX_HANDLETYPE hComp,
3440 OMX_IN OMX_INDEXTYPE configIndex,
3441 OMX_INOUT OMX_PTR configData)
3442 {
3443 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3444
3445 if (m_state == OMX_StateInvalid)
3446 {
3447 DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
3448 return OMX_ErrorInvalidState;
3449 }
3450
3451 switch ((unsigned long)configIndex)
3452 {
3453 case OMX_IndexConfigCommonOutputCrop:
3454 {
3455 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
3456 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
3457 break;
3458 }
3459
3460 // OMX extensions
3461 case OMX_QcomIndexConfigActiveRegionDetectionStatus:
3462 break;
3463
3464 default:
3465 {
3466 DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex);
3467 eRet = OMX_ErrorBadParameter;
3468 }
3469
3470 }
3471
3472 return eRet;
3473 }
3474
3475 /* ======================================================================
3476 FUNCTION
3477 omx_vdpp::SetConfig
3478
3479 DESCRIPTION
3480 OMX Set Config method implementation
3481
3482 PARAMETERS
3483 <TBD>.
3484
3485 RETURN VALUE
3486 OMX Error None if successful.
3487 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)3488 OMX_ERRORTYPE omx_vdpp::set_config(OMX_IN OMX_HANDLETYPE hComp,
3489 OMX_IN OMX_INDEXTYPE configIndex,
3490 OMX_IN OMX_PTR configData)
3491 {
3492 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3493 struct vpu_control control;
3494 int result = 0;
3495
3496 DEBUG_PRINT_LOW("omx_vdpp::set_config \n");
3497 if(m_state == OMX_StateInvalid)
3498 {
3499 DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
3500 return OMX_ErrorInvalidState;
3501 }
3502
3503 switch ((unsigned long)configIndex)
3504 {
3505 // OMX extensions
3506 case OMX_QcomIndexConfigActiveRegionDetection:
3507 {
3508 struct vpu_ctrl_active_region_param *ard = &control.data.active_region_param;
3509 memset(&control, 0, sizeof(control));
3510 control.control_id = VPU_CTRL_ACTIVE_REGION_PARAM;
3511 mExtensionData.activeRegionDetectionDirtyFlag = true;
3512 memcpy(&(mExtensionData.activeRegionDetection),
3513 configData,
3514 sizeof(mExtensionData.activeRegionDetection));
3515
3516 /* Set control. */
3517 ard->enable = mExtensionData.activeRegionDetection.bEnable;
3518 ard->num_exclusions = mExtensionData.activeRegionDetection.nNumExclusionRegions;
3519 memcpy(&(ard->detection_region), &(mExtensionData.activeRegionDetection.sROI), sizeof(QOMX_RECTTYPE));
3520 if(ard->num_exclusions > 0)
3521 {
3522 memcpy(&(ard->detection_region), &(mExtensionData.activeRegionDetection.sExclusionRegions), (ard->num_exclusions * sizeof(QOMX_RECTTYPE)));
3523 }
3524
3525 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_ACTIVE_REGION_MEASURE : "
3526 "top %d left %d width %d height %d",
3527 ard->detection_region.top, ard->detection_region.left,
3528 ard->detection_region.width, ard->detection_region.height);
3529 #ifndef STUB_VPU
3530 result = ioctl(drv_ctx.video_vpu_fd, VPU_S_CONTROL, &control);
3531 if (result < 0)
3532 {
3533 DEBUG_PRINT_ERROR("VIDIOC_S_CTRL VPU_S_CTRL_ACTIVE_REGION_MEASURE failed, result = %d", result);
3534 eRet = OMX_ErrorUnsupportedSetting;
3535 }
3536 else
3537 {
3538 mExtensionData.activeRegionDetectionDirtyFlag = false;
3539 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_ACTIVE_REGION_MEASURE set to: "
3540 "top %d left %d width %d height %d",
3541 ard->detection_region.top, ard->detection_region.left,
3542 ard->detection_region.width, ard->detection_region.height);
3543 }
3544 #endif
3545 break;
3546 }
3547
3548 case OMX_QcomIndexConfigScalingMode:
3549 {
3550 struct vpu_ctrl_standard *anmph = &control.data.standard;
3551 memset(&control, 0, sizeof(control));
3552 control.control_id = VPU_CTRL_ANAMORPHIC_SCALING;
3553 mExtensionData.scalingModeDirtyFlag = true;
3554 memcpy(&(mExtensionData.scalingMode),
3555 configData,
3556 sizeof(mExtensionData.scalingMode));
3557
3558 /* Set control. */
3559 anmph->enable = 1;
3560 anmph->value = mExtensionData.scalingMode.eScaleMode;
3561
3562 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_ANAMORPHIC_SCALING %d, anmph->enable = %d", anmph->value, anmph->enable);
3563 #ifndef STUB_VPU
3564 result = ioctl(drv_ctx.video_vpu_fd, VPU_S_CONTROL, &control);
3565 if (result < 0)
3566 {
3567 DEBUG_PRINT_ERROR("VIDIOC_S_CTRL VPU_S_CTRL_ANAMORPHIC_SCALING failed, result = %d", result);
3568 eRet = OMX_ErrorUnsupportedSetting;
3569 }
3570 else
3571 {
3572 mExtensionData.scalingModeDirtyFlag = false;
3573 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_ANAMORPHIC_SCALING set to %d", anmph->value);
3574 }
3575 #endif
3576 break;
3577 }
3578
3579 case OMX_QcomIndexConfigNoiseReduction:
3580 {
3581 struct vpu_ctrl_auto_manual *nr = &control.data.auto_manual;
3582 memset(&control, 0, sizeof(control));
3583 control.control_id = VPU_CTRL_NOISE_REDUCTION;
3584 mExtensionData.noiseReductionDirtyFlag = true;
3585 memcpy(&(mExtensionData.noiseReduction),
3586 configData,
3587 sizeof(mExtensionData.noiseReduction));
3588
3589 /* Set control. */
3590 nr->enable = mExtensionData.noiseReduction.bEnable;
3591 nr->auto_mode = mExtensionData.noiseReduction.bAutoMode;
3592 nr->value = mExtensionData.noiseReduction.nNoiseReduction;
3593
3594 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_NOISE_REDUCTION %d, nr->enable = %d, nr->auto_mode = %d", nr->value, nr->enable, nr->auto_mode);
3595 #ifndef STUB_VPU
3596 result = ioctl(drv_ctx.video_vpu_fd, VPU_S_CONTROL, &control);
3597 if (result < 0)
3598 {
3599 DEBUG_PRINT_ERROR("VIDIOC_S_CTRL VPU_S_CTRL_NOISE_REDUCTION failed, result = %d", result);
3600 eRet = OMX_ErrorUnsupportedSetting;
3601 }
3602 else
3603 {
3604 mExtensionData.noiseReductionDirtyFlag = false;
3605 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_NOISE_REDUCTION set to %d", nr->value);
3606 }
3607 #endif
3608 break;
3609 }
3610
3611 case OMX_QcomIndexConfigImageEnhancement:
3612 {
3613 struct vpu_ctrl_auto_manual *ie = &control.data.auto_manual;
3614 memset(&control, 0, sizeof(control));
3615 control.control_id = VPU_CTRL_IMAGE_ENHANCEMENT;
3616 mExtensionData.imageEnhancementDirtyFlag = true;
3617 memcpy(&(mExtensionData.imageEnhancement),
3618 configData,
3619 sizeof(mExtensionData.imageEnhancement));
3620
3621 /* Set control. */
3622 ie->enable = mExtensionData.imageEnhancement.bEnable;
3623 ie->auto_mode = mExtensionData.imageEnhancement.bAutoMode;
3624 ie->value = mExtensionData.imageEnhancement.nImageEnhancement;
3625
3626 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_IMAGE_ENHANCEMENT %d, ie->enable = %d, ie->auto_mode = %d", ie->value, ie->enable, ie->auto_mode);
3627 #ifndef STUB_VPU
3628 result = ioctl(drv_ctx.video_vpu_fd, VPU_S_CONTROL, &control);
3629 if (result < 0)
3630 {
3631 DEBUG_PRINT_ERROR("VIDIOC_S_CTRL VPU_S_CTRL_IMAGE_ENHANCEMENT failed, result = %d", result);
3632 eRet = OMX_ErrorUnsupportedSetting;
3633 }
3634 else
3635 {
3636 mExtensionData.imageEnhancementDirtyFlag = false;
3637 DEBUG_PRINT_HIGH("VIDIOC_S_CTRL: VPU_S_CTRL_IMAGE_ENHANCEMENT set to %d", ie->value);
3638 }
3639 #endif
3640 break;
3641 }
3642 #ifdef FRC_ENABLE
3643 case OMX_IndexVendorVideoFrameRate:
3644 {
3645
3646 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
3647 DEBUG_PRINT_HIGH("OMX_IndexVendorVideoFrameRate %d", config->nFps);
3648
3649 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
3650 if (config->bEnabled) {
3651 if ((config->nFps >> 16) > 0) {
3652 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %d",
3653 config->nFps >> 16);
3654 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
3655 drv_ctx.frame_rate.fps_denominator);
3656
3657 if (!drv_ctx.frame_rate.fps_numerator) {
3658 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
3659 drv_ctx.frame_rate.fps_numerator = 30;
3660 }
3661
3662 if (drv_ctx.frame_rate.fps_denominator) {
3663 drv_ctx.frame_rate.fps_numerator = (int)
3664 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
3665 }
3666
3667 drv_ctx.frame_rate.fps_denominator = 1;
3668 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
3669 drv_ctx.frame_rate.fps_numerator;
3670
3671 struct v4l2_outputparm oparm;
3672 /*XXX: we're providing timing info as seconds per frame rather than frames
3673 * per second.*/
3674 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
3675 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
3676
3677 struct v4l2_streamparm sparm;
3678 memset(&sparm, 0, sizeof(struct v4l2_streamparm));
3679 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3680 sparm.parm.output = oparm;
3681 #ifndef STUB_VPU
3682 if (ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_PARM, &sparm)) {
3683 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
3684 performance might be affected");
3685 eRet = OMX_ErrorHardware;
3686 }
3687 #endif
3688 client_set_fps = true;
3689 } else {
3690 DEBUG_PRINT_ERROR("Frame rate not supported.");
3691 eRet = OMX_ErrorUnsupportedSetting;
3692 }
3693 } else {
3694 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
3695 client_set_fps = false;
3696 }
3697 } else { // 8084 doesn't support FRC (only 8092 does). only input framerate setting is supported.
3698 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
3699 (int)config->nPortIndex);
3700 eRet = OMX_ErrorBadPortIndex;
3701 }
3702
3703 }
3704 break;
3705 #endif
3706 case OMX_IndexConfigCallbackRequest:
3707 {
3708 OMX_CONFIG_CALLBACKREQUESTTYPE *callbackRequest = (OMX_CONFIG_CALLBACKREQUESTTYPE *) configData;
3709 DEBUG_PRINT_HIGH("OMX_IndexConfigCallbackRequest %d", callbackRequest->bEnable);
3710
3711 if (callbackRequest->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
3712 if ((callbackRequest->bEnable) && (OMX_QcomIndexConfigActiveRegionDetectionStatus == (OMX_QCOM_EXTN_INDEXTYPE)callbackRequest->nIndex))
3713 {
3714 m_ar_callback_setup = true;
3715 }
3716 }
3717 }
3718 break;
3719 case OMX_IndexConfigCommonOutputCrop:
3720 {
3721 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
3722 memcpy(&rectangle, rect, sizeof(OMX_CONFIG_RECTTYPE));
3723 break;
3724 }
3725 default:
3726 {
3727 DEBUG_PRINT_ERROR("set_config: unknown param 0x%08x\n",configIndex);
3728 eRet = OMX_ErrorBadParameter;
3729 }
3730 }
3731
3732 return eRet;
3733 }
3734
3735 /* ======================================================================
3736 FUNCTION
3737 omx_vdpp::GetExtensionIndex
3738
3739 DESCRIPTION
3740 OMX GetExtensionIndex method implementaion. <TBD>
3741
3742 PARAMETERS
3743 <TBD>.
3744
3745 RETURN VALUE
3746 OMX Error None if everything successful.
3747
3748 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)3749 OMX_ERRORTYPE omx_vdpp::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
3750 OMX_IN OMX_STRING paramName,
3751 OMX_OUT OMX_INDEXTYPE* indexType)
3752 {
3753 DEBUG_PRINT_LOW("omx_vdpp::get_extension_index %s\n", paramName);
3754 if(m_state == OMX_StateInvalid)
3755 {
3756 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n");
3757 return OMX_ErrorInvalidState;
3758 }
3759 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3760 else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
3761 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
3762 DEBUG_PRINT_HIGH("OMX.google.android.index.enableAndroidNativeBuffers");
3763 }
3764 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
3765 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
3766 DEBUG_PRINT_HIGH("OMX.google.android.index.useAndroidNativeBuffer2");
3767 }
3768 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
3769 DEBUG_PRINT_ERROR("Extension: %s is supported\n", paramName);
3770 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
3771 DEBUG_PRINT_HIGH("OMX.google.android.index.useAndroidNativeBuffer");
3772 }
3773 else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
3774 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
3775 DEBUG_PRINT_HIGH("OMX.google.android.index.getAndroidNativeBufferUsage");
3776 }
3777 #endif
3778
3779 /* VIDPP extension
3780 */
3781 else if(!strncmp(paramName,
3782 OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION_STATUS,
3783 sizeof(OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION_STATUS) - 1))
3784 {
3785 DEBUG_PRINT_LOW("get_extension_index OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION_STATUS 0x%x \n", OMX_QcomIndexConfigActiveRegionDetectionStatus);
3786 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigActiveRegionDetectionStatus;
3787 }
3788 else if(!strncmp(paramName,
3789 OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION,
3790 sizeof(OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION) - 1))
3791 {
3792 DEBUG_PRINT_LOW("get_extension_index OMX_QCOM_INDEX_CONFIG_ACTIVE_REGION_DETECTION 0x%x \n", OMX_QcomIndexConfigActiveRegionDetection);
3793 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigActiveRegionDetection;
3794 }
3795 else if(!strncmp(paramName,
3796 OMX_QCOM_INDEX_CONFIG_SCALING_MODE,
3797 sizeof(OMX_QCOM_INDEX_CONFIG_SCALING_MODE) - 1))
3798 {
3799 DEBUG_PRINT_LOW("get_extension_index OMX_QCOM_INDEX_CONFIG_SCALING_MODE 0x%x \n", OMX_QcomIndexConfigScalingMode);
3800 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigScalingMode;
3801 }
3802 else if(!strncmp(paramName,
3803 OMX_QCOM_INDEX_CONFIG_NOISEREDUCTION,
3804 sizeof(OMX_QCOM_INDEX_CONFIG_NOISEREDUCTION) - 1))
3805 {
3806 DEBUG_PRINT_LOW("get_extension_index OMX_QCOM_INDEX_CONFIG_NOISEREDUCTION 0x%x \n", OMX_QcomIndexConfigNoiseReduction);
3807 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNoiseReduction;
3808 }
3809 else if(!strncmp(paramName,
3810 OMX_QCOM_INDEX_CONFIG_IMAGEENHANCEMENT,
3811 sizeof(OMX_QCOM_INDEX_CONFIG_IMAGEENHANCEMENT) - 1))
3812 {
3813 DEBUG_PRINT_LOW("get_extension_index OMX_QCOM_INDEX_CONFIG_IMAGEENHANCEMENT 0x%x \n", OMX_QcomIndexConfigImageEnhancement);
3814 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigImageEnhancement;
3815 }
3816
3817 else {
3818 DEBUG_PRINT_ERROR("Extension: %s not implemented\n", paramName);
3819 return OMX_ErrorNotImplemented;
3820 }
3821 return OMX_ErrorNone;
3822 }
3823
3824 /* ======================================================================
3825 FUNCTION
3826 omx_vdpp::GetState
3827
3828 DESCRIPTION
3829 Returns the state information back to the caller.<TBD>
3830
3831 PARAMETERS
3832 <TBD>.
3833
3834 RETURN VALUE
3835 Error None if everything is successful.
3836 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)3837 OMX_ERRORTYPE omx_vdpp::get_state(OMX_IN OMX_HANDLETYPE hComp,
3838 OMX_OUT OMX_STATETYPE* state)
3839 {
3840 *state = m_state;
3841 DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state);
3842 return OMX_ErrorNone;
3843 }
3844
3845 /* ======================================================================
3846 FUNCTION
3847 omx_vdpp::ComponentTunnelRequest
3848
3849 DESCRIPTION
3850 OMX Component Tunnel Request method implementation. <TBD>
3851
3852 PARAMETERS
3853 None.
3854
3855 RETURN VALUE
3856 OMX Error None if everything successful.
3857
3858 ========================================================================== */
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)3859 OMX_ERRORTYPE omx_vdpp::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
3860 OMX_IN OMX_U32 port,
3861 OMX_IN OMX_HANDLETYPE peerComponent,
3862 OMX_IN OMX_U32 peerPort,
3863 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
3864 {
3865 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n");
3866 return OMX_ErrorNotImplemented;
3867 }
3868
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)3869 OMX_ERRORTYPE omx_vdpp::use_output_buffer(
3870 OMX_IN OMX_HANDLETYPE hComp,
3871 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3872 OMX_IN OMX_U32 port,
3873 OMX_IN OMX_PTR appData,
3874 OMX_IN OMX_U32 bytes,
3875 OMX_IN OMX_U8* buffer)
3876 {
3877 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3878 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
3879 unsigned i= 0; // Temporary counter
3880 struct vdpp_setbuffer_cmd setbuffers;
3881 OMX_PTR privateAppData = NULL;
3882 private_handle_t *handle = NULL;
3883 OMX_U8 *buff = buffer;
3884 struct v4l2_buffer buf;
3885 struct v4l2_plane plane[VIDEO_MAX_PLANES];
3886 int extra_idx = 0;
3887
3888 DEBUG_PRINT_HIGH("Inside omx_vdpp::use_output_buffer buffer = %p, bytes= %lu", buffer, bytes);
3889
3890 if (!m_out_mem_ptr) {
3891 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers buffer = %p, bytes= %lu", buffer, bytes);
3892 eRet = allocate_output_headers();
3893 }
3894
3895 if (eRet == OMX_ErrorNone) {
3896 for(i=0; i< drv_ctx.op_buf.actualcount; i++) {
3897 if(BITMASK_ABSENT(&m_out_bm_count,i))
3898 {
3899 break;
3900 }
3901 }
3902 }
3903
3904 if(i >= drv_ctx.op_buf.actualcount) {
3905 DEBUG_PRINT_ERROR("Already using %d o/p buffers\n", drv_ctx.op_buf.actualcount);
3906 eRet = OMX_ErrorInsufficientResources;
3907 }
3908
3909 if (eRet == OMX_ErrorNone) {
3910 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
3911 if(m_enable_android_native_buffers) {
3912 DEBUG_PRINT_HIGH("Use_op_buf:m_enable_android_native_buffers 1\n");
3913 if (m_use_android_native_buffers) {
3914 DEBUG_PRINT_HIGH("Use_op_buf:m_enable_android_native_buffers 2\n");
3915 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
3916 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3917 handle = (private_handle_t *)nBuf->handle;
3918 privateAppData = params->pAppPrivate;
3919 } else {
3920 DEBUG_PRINT_HIGH("Use_op_buf:m_enable_android_native_buffers 3\n");
3921 handle = (private_handle_t *)buff;
3922 privateAppData = appData;
3923 }
3924
3925 if(!handle) {
3926 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
3927 return OMX_ErrorBadParameter;
3928 }
3929
3930 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
3931 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
3932 " expected %u, got %lu",
3933 drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size);
3934 return OMX_ErrorBadParameter;
3935 }
3936
3937 #if defined(_ANDROID_ICS_)
3938 native_buffer[i].nativehandle = handle;
3939 native_buffer[i].privatehandle = handle;
3940 #endif
3941 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
3942 drv_ctx.ptr_outputbuffer[i].offset = 0;
3943 drv_ctx.ptr_outputbuffer[i].bufferaddr = NULL;
3944 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3945 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
3946 DEBUG_PRINT_HIGH("Use_op_buf:m_enable_android_native_buffers 5 drv_ctx.ptr_outputbuffer[i].bufferaddr = %p, size1=%d, size2=%d\n",
3947 drv_ctx.ptr_outputbuffer[i].bufferaddr,
3948 drv_ctx.op_buf.buffer_size,
3949 handle->size);
3950 } else
3951 #endif
3952
3953 if (!ouput_egl_buffers && !m_use_output_pmem) {
3954 #ifdef USE_ION
3955 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
3956 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
3957 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
3958 &drv_ctx.op_buf_ion_info[i].fd_ion_data, 0);
3959 if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
3960 DEBUG_PRINT_ERROR("ION device fd is bad %d\n", drv_ctx.op_buf_ion_info[i].ion_device_fd);
3961 return OMX_ErrorInsufficientResources;
3962 }
3963 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3964 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
3965 #else
3966 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3967 open (MEM_DEVICE,O_RDWR);
3968
3969 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3970 DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d\n", drv_ctx.ptr_outputbuffer[i].pmem_fd);
3971 return OMX_ErrorInsufficientResources;
3972 }
3973
3974 if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
3975 drv_ctx.op_buf.buffer_size,
3976 drv_ctx.op_buf.alignment))
3977 {
3978 DEBUG_PRINT_ERROR(" align_pmem_buffers() failed");
3979 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3980 return OMX_ErrorInsufficientResources;
3981 }
3982 #endif
3983 {
3984 drv_ctx.ptr_outputbuffer[i].bufferaddr =
3985 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
3986 PROT_READ|PROT_WRITE, MAP_SHARED,
3987 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
3988 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
3989 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3990 #ifdef USE_ION
3991 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
3992 #endif
3993 DEBUG_PRINT_ERROR("Unable to mmap output buffer\n");
3994 return OMX_ErrorInsufficientResources;
3995 }
3996 }
3997 drv_ctx.ptr_outputbuffer[i].offset = 0;
3998 privateAppData = appData;
3999 }
4000 else {
4001
4002 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
4003 if (!appData || !bytes ) {
4004 if(!buffer) {
4005 DEBUG_PRINT_ERROR(" Bad parameters for use buffer in EGL image case");
4006 return OMX_ErrorBadParameter;
4007 }
4008 }
4009
4010 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
4011 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
4012 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
4013 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
4014 !pmem_list->nEntries ||
4015 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
4016 DEBUG_PRINT_ERROR(" Pmem info not valid in use buffer");
4017 return OMX_ErrorBadParameter;
4018 }
4019 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4020 pmem_list->entryList->entry;
4021 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
4022 pmem_info->pmem_fd);
4023 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
4024 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
4025 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
4026 drv_ctx.ptr_outputbuffer[i].mmaped_size =
4027 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
4028 privateAppData = appData;
4029 }
4030
4031 *bufferHdr = (m_out_mem_ptr + i );
4032
4033 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
4034 sizeof (vdpp_bufferpayload));
4035
4036 DEBUG_PRINT_HIGH(" Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
4037 drv_ctx.ptr_outputbuffer[i].bufferaddr,
4038 drv_ctx.ptr_outputbuffer[i].pmem_fd );
4039 #ifndef STUB_VPU
4040 DEBUG_PRINT_LOW("use_output_buffer: i = %d, streaming[CAPTURE_PORT] = %d ", i, streaming[CAPTURE_PORT]);
4041 // stream on output port
4042 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
4043 enum v4l2_buf_type buf_type;
4044 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4045 if (ioctl(drv_ctx.video_vpu_fd, VIDIOC_STREAMON,&buf_type)) {
4046 DEBUG_PRINT_ERROR("V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE STREAMON failed \n ");
4047 return OMX_ErrorInsufficientResources;
4048 } else {
4049 streaming[CAPTURE_PORT] = true;
4050 DEBUG_PRINT_HIGH("V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE STREAMON Successful \n ");
4051 }
4052 }
4053 #endif
4054
4055 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
4056 if (m_enable_android_native_buffers) {
4057 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
4058 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
4059 } else {
4060 (*bufferHdr)->pBuffer = buff;
4061 }
4062 (*bufferHdr)->pAppPrivate = privateAppData;
4063 BITMASK_SET(&m_out_bm_count,i);
4064 }
4065 return eRet;
4066 }
4067
4068
4069 /* ======================================================================
4070 FUNCTION
4071 omx_vdpp::use_input_heap_buffers
4072
4073 DESCRIPTION
4074 OMX Use Buffer Heap allocation method implementation.
4075
4076 PARAMETERS
4077 <TBD>.
4078
4079 RETURN VALUE
4080 OMX Error None , if everything successful.
4081
4082 ========================================================================== */
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)4083 OMX_ERRORTYPE omx_vdpp::use_input_heap_buffers(
4084 OMX_IN OMX_HANDLETYPE hComp,
4085 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4086 OMX_IN OMX_U32 port,
4087 OMX_IN OMX_PTR appData,
4088 OMX_IN OMX_U32 bytes,
4089 OMX_IN OMX_U8* buffer)
4090 {
4091 OMX_PTR privateAppData = NULL;
4092 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
4093 private_handle_t *handle = NULL;
4094 #endif
4095 OMX_U8 *buff = buffer;
4096
4097 DEBUG_PRINT_LOW("Inside %s, %p\n", __FUNCTION__, buffer);
4098 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4099 if(!m_inp_heap_ptr)
4100 {
4101 DEBUG_PRINT_LOW("Inside %s 0, %p\n", __FUNCTION__, buffer);
4102 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
4103 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4104 drv_ctx.ip_buf.actualcount);
4105 }
4106
4107 if(!m_phdr_pmem_ptr)
4108 {
4109 DEBUG_PRINT_LOW("Inside %s 0-1, %p\n", __FUNCTION__, buffer);
4110 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
4111 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4112 drv_ctx.ip_buf.actualcount);
4113 }
4114 if(!m_inp_heap_ptr || !m_phdr_pmem_ptr)
4115 {
4116 DEBUG_PRINT_ERROR("Insufficent memory");
4117 eRet = OMX_ErrorInsufficientResources;
4118 }
4119 else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount)
4120 {
4121 DEBUG_PRINT_LOW("Inside %s 2 m_in_alloc_cnt = %lu, drv_ctx.ip_buf.actualcount = %d\n", __FUNCTION__, m_in_alloc_cnt, drv_ctx.ip_buf.actualcount);
4122 input_use_buffer = true;
4123 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
4124 // update this buffer for native window buffer in etb
4125 // OMXNodeInstance::useGraphicBuffer2_l check if pBuffer and pAppPrivate are
4126 // the same value as passed in. If not, useGraphicBuffer2_l will exit on error
4127 //
4128 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
4129 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
4130 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
4131 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
4132 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
4133 // save mmapped native window buffer address to pPlatformPrivate
4134 // use this mmaped buffer address in etb_proxy
4135 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
4136 /*if(m_enable_android_native_buffers) */{
4137 if (m_use_android_native_buffers) {
4138 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
4139 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4140 handle = (private_handle_t *)nBuf->handle;
4141 privateAppData = params->pAppPrivate;
4142 } else {
4143 handle = (private_handle_t *)buff;
4144 privateAppData = appData;
4145 //DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 3\n");
4146 }
4147
4148 if(!handle) {
4149 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
4150 return OMX_ErrorBadParameter;
4151 }
4152
4153 if ((OMX_U32)handle->size < drv_ctx.ip_buf.buffer_size) {
4154 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
4155 " expected %u, got %lu",
4156 drv_ctx.ip_buf.buffer_size, (OMX_U32)handle->size);
4157 return OMX_ErrorBadParameter;
4158 }
4159
4160 if (!m_use_android_native_buffers) {
4161 buff = (OMX_U8*)mmap(0, handle->size,
4162 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4163 //DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 4 buff = %p\n", buff);
4164 if (buff == MAP_FAILED) {
4165 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4166 return OMX_ErrorInsufficientResources;
4167 }
4168 }
4169 // we only need to copy this buffer (read only), no need to preserver this handle
4170 // this handle is saved for write-unlock in use_output_buffer case
4171 #if defined(_ANDROID_ICS_)
4172 //native_buffer[i].nativehandle = handle;
4173 //native_buffer[i].privatehandle = handle;
4174 #endif
4175 m_inp_heap_ptr[m_in_alloc_cnt].pPlatformPrivate = buff;
4176 //DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 5 m_inp_heap_ptr = %p, m_inp_heap_ptr[%lu].pPlatformPrivate = %p, m_inp_heap_ptr[%lu].pBuffer = %p\n",
4177 // m_inp_heap_ptr, m_in_alloc_cnt, m_inp_heap_ptr[m_in_alloc_cnt].pPlatformPrivate, m_in_alloc_cnt, m_inp_heap_ptr[m_in_alloc_cnt].pBuffer);
4178 }
4179 #endif
4180 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
4181 // user passes buffer in, but we need ION buffer
4182 //DEBUG_PRINT_LOW("Inside %s 6 *bufferHdr = %p, byts = %lu \n", __FUNCTION__, *bufferHdr, bytes);
4183 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
4184 DEBUG_PRINT_HIGH(" Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
4185 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt],
4186 (unsigned)NULL, (unsigned)NULL))
4187 {
4188 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
4189 return OMX_ErrorInsufficientResources;
4190 }
4191 m_in_alloc_cnt++;
4192 }
4193 else
4194 {
4195 DEBUG_PRINT_ERROR("All i/p buffers have been set! m_in_alloc_cnt = %lu, drv_ctx.ip_buf.actualcount = %d", m_in_alloc_cnt, drv_ctx.ip_buf.actualcount);
4196 eRet = OMX_ErrorInsufficientResources;
4197 }
4198 return eRet;
4199 }
4200
4201
4202 /* ======================================================================
4203 FUNCTION
4204 omx_vdpp::use_input_buffers
4205
4206 DESCRIPTION
4207 OMX Use Buffer method implementation.
4208
4209 PARAMETERS
4210 <TBD>.
4211
4212 RETURN VALUE
4213 OMX Error None , if everything successful.
4214
4215 ========================================================================== */
use_input_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)4216 OMX_ERRORTYPE omx_vdpp::use_input_buffers(
4217 OMX_IN OMX_HANDLETYPE hComp,
4218 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4219 OMX_IN OMX_U32 port,
4220 OMX_IN OMX_PTR appData,
4221 OMX_IN OMX_U32 bytes,
4222 OMX_IN OMX_U8* buffer)
4223 {
4224 OMX_PTR privateAppData = NULL;
4225 OMX_BUFFERHEADERTYPE *input = NULL;
4226 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
4227 private_handle_t *handle = NULL;
4228 #endif
4229 OMX_U8 *buff = buffer;
4230 unsigned int i = 0;
4231
4232 DEBUG_PRINT_LOW("Inside %s, %p\n", __FUNCTION__, buffer);
4233 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4234
4235 if(!m_inp_heap_ptr)
4236 {
4237 DEBUG_PRINT_LOW("Inside %s 0, %p\n", __FUNCTION__, buffer);
4238 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
4239 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4240 drv_ctx.ip_buf.actualcount);
4241 }
4242
4243 if(!m_phdr_pmem_ptr)
4244 {
4245 DEBUG_PRINT_LOW("Inside %s 0-1, %p\n", __FUNCTION__, buffer);
4246 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
4247 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4248 drv_ctx.ip_buf.actualcount);
4249 }
4250
4251 if(!m_inp_heap_ptr || !m_phdr_pmem_ptr)
4252 {
4253 DEBUG_PRINT_ERROR("Insufficent memory");
4254 eRet = OMX_ErrorInsufficientResources;
4255 }
4256 else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount)
4257 {
4258 DEBUG_PRINT_LOW("Inside %s 2 m_in_alloc_cnt = %lu, drv_ctx.ip_buf.actualcount = %d\n", __FUNCTION__, m_in_alloc_cnt, drv_ctx.ip_buf.actualcount);
4259 input_use_buffer = true;
4260 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
4261 // update this buffer for native window buffer in etb
4262 // OMXNodeInstance::useGraphicBuffer2_l check if pBuffer and pAppPrivate are
4263 // the same value as passed in. If not, useGraphicBuffer2_l will exit on error
4264 //
4265 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
4266 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
4267 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
4268 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
4269 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
4270 // save mmapped native window buffer address to pPlatformPrivate
4271 // use this mmaped buffer address in etb_proxy
4272 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
4273 /*if(m_enable_android_native_buffers) */{
4274 if (m_use_android_native_buffers) {
4275 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
4276 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4277 handle = (private_handle_t *)nBuf->handle;
4278 privateAppData = params->pAppPrivate;
4279 } else {
4280 handle = (private_handle_t *)buff;
4281 privateAppData = appData;
4282 DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 3\n");
4283 }
4284
4285 if(!handle) {
4286 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
4287 return OMX_ErrorBadParameter;
4288 }
4289
4290 if ((OMX_U32)handle->size < drv_ctx.ip_buf.buffer_size) {
4291 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
4292 " expected %u, got %lu",
4293 drv_ctx.ip_buf.buffer_size, (OMX_U32)handle->size);
4294 return OMX_ErrorBadParameter;
4295 }
4296
4297 if (!m_use_android_native_buffers) {
4298 buff = (OMX_U8*)mmap(0, (handle->size - drv_ctx.ip_buf.frame_size),
4299 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, drv_ctx.ip_buf.frame_size);
4300
4301 DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 4 buff = %p, size1=%d, size2=%d\n", buff,
4302 drv_ctx.ip_buf.buffer_size,
4303 handle->size);
4304 if (buff == MAP_FAILED) {
4305 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4306 return OMX_ErrorInsufficientResources;
4307 }
4308 }
4309 // we only need to copy this buffer (read only), no need to preserver this handle
4310 // this handle is saved for write-unlock in use_output_buffer case
4311 #if defined(_ANDROID_ICS_)
4312 //native_buffer[i].nativehandle = handle;
4313 //native_buffer[i].privatehandle = handle;
4314 #endif
4315 m_inp_heap_ptr[m_in_alloc_cnt].pPlatformPrivate = buff;
4316 //DEBUG_PRINT_LOW("omx_vdpp::use_input_heap_buffers 5 m_inp_heap_ptr = %p, m_inp_heap_ptr[%lu].pPlatformPrivate = %p, m_inp_heap_ptr[%lu].pBuffer = %p\n",
4317 // m_inp_heap_ptr, m_in_alloc_cnt, m_inp_heap_ptr[m_in_alloc_cnt].pPlatformPrivate, m_in_alloc_cnt, m_inp_heap_ptr[m_in_alloc_cnt].pBuffer);
4318 }
4319 #endif
4320 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
4321
4322 if(!m_inp_mem_ptr)
4323 {
4324 DEBUG_PRINT_HIGH(" Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
4325 drv_ctx.ip_buf.actualcount,
4326 drv_ctx.ip_buf.buffer_size);
4327
4328 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4329 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4330
4331 if (m_inp_mem_ptr == NULL)
4332 {
4333 return OMX_ErrorInsufficientResources;
4334 }
4335
4336 drv_ctx.ptr_inputbuffer = (struct vdpp_bufferpayload *) \
4337 calloc ((sizeof (struct vdpp_bufferpayload)),drv_ctx.ip_buf.actualcount);
4338
4339 if (drv_ctx.ptr_inputbuffer == NULL)
4340 {
4341 return OMX_ErrorInsufficientResources;
4342 }
4343 }
4344
4345 for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
4346 {
4347 if(BITMASK_ABSENT(&m_inp_bm_count,i))
4348 {
4349 DEBUG_PRINT_LOW(" Free Input Buffer Index %d",i);
4350 break;
4351 }
4352 }
4353
4354 if(i < drv_ctx.ip_buf.actualcount)
4355 {
4356 struct v4l2_buffer buf;
4357 struct v4l2_plane plane;
4358 int rc;
4359
4360 m_phdr_pmem_ptr[m_in_alloc_cnt] = (m_inp_mem_ptr + i);
4361
4362 drv_ctx.ptr_inputbuffer [i].bufferaddr = buff;
4363 drv_ctx.ptr_inputbuffer [i].pmem_fd = handle->fd;
4364 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4365 drv_ctx.ptr_inputbuffer [i].mmaped_size = handle->size - drv_ctx.ip_buf.frame_size;
4366 drv_ctx.ptr_inputbuffer [i].offset = 0;
4367
4368 input = m_phdr_pmem_ptr[m_in_alloc_cnt];
4369 BITMASK_SET(&m_inp_bm_count,i);
4370 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer Buffer address %p of pmem",*bufferHdr);
4371
4372 input->pBuffer = (OMX_U8 *)buff;
4373 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4374 input->nVersion.nVersion = OMX_SPEC_VERSION;
4375 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4376 input->pAppPrivate = appData;
4377 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4378 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; // used in empty_this_buffer_proxy
4379
4380 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer input->pBuffer %p of pmem, input->pInputPortPrivate = %p",input->pBuffer, input->pInputPortPrivate);
4381 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer memset drv_ctx.ip_buf.buffer_size = %d\n", drv_ctx.ip_buf.buffer_size);
4382
4383 }
4384 else
4385 {
4386 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
4387 eRet = OMX_ErrorInsufficientResources;
4388 }
4389
4390 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt],
4391 (unsigned)NULL, (unsigned)NULL))
4392 {
4393 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
4394 return OMX_ErrorInsufficientResources;
4395 }
4396 m_in_alloc_cnt++;
4397 }
4398 else
4399 {
4400 DEBUG_PRINT_ERROR("All i/p buffers have been set! m_in_alloc_cnt = %lu, drv_ctx.ip_buf.actualcount = %d", m_in_alloc_cnt, drv_ctx.ip_buf.actualcount);
4401 eRet = OMX_ErrorInsufficientResources;
4402 }
4403 return eRet;
4404 }
4405
4406 /* ======================================================================
4407 FUNCTION
4408 omx_vdpp::UseBuffer
4409
4410 DESCRIPTION
4411 OMX Use Buffer method implementation.
4412
4413 PARAMETERS
4414 <TBD>.
4415
4416 RETURN VALUE
4417 OMX Error None , if everything successful.
4418
4419 ========================================================================== */
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)4420 OMX_ERRORTYPE omx_vdpp::use_buffer(
4421 OMX_IN OMX_HANDLETYPE hComp,
4422 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4423 OMX_IN OMX_U32 port,
4424 OMX_IN OMX_PTR appData,
4425 OMX_IN OMX_U32 bytes,
4426 OMX_IN OMX_U8* buffer)
4427 {
4428 OMX_ERRORTYPE error = OMX_ErrorNone;
4429 struct vdpp_setbuffer_cmd setbuffers;
4430
4431 if ((bufferHdr == NULL) || (bytes == 0) || (/*!secure_mode && */buffer == NULL))
4432 {
4433 DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer);
4434 return OMX_ErrorBadParameter;
4435 }
4436 if(m_state == OMX_StateInvalid)
4437 {
4438 DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n");
4439 return OMX_ErrorInvalidState;
4440 }
4441 if(port == OMX_CORE_INPUT_PORT_INDEX)
4442 //error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
4443 error = use_input_buffers(hComp, bufferHdr, port, appData, bytes, buffer); // option to use vdec buffer
4444
4445 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
4446 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
4447 else
4448 {
4449 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
4450 error = OMX_ErrorBadPortIndex;
4451 }
4452 DEBUG_PRINT_LOW("Use Buffer: port %lu, buffer %p, eRet %d", port, *bufferHdr, error);
4453 if(error == OMX_ErrorNone)
4454 {
4455 if(allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
4456 {
4457 // Send the callback now
4458 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4459 post_event(OMX_CommandStateSet,OMX_StateIdle,
4460 OMX_COMPONENT_GENERATE_EVENT);
4461 }
4462 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
4463 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
4464 {
4465 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4466 post_event(OMX_CommandPortEnable,
4467 OMX_CORE_INPUT_PORT_INDEX,
4468 OMX_COMPONENT_GENERATE_EVENT);
4469 }
4470 else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
4471 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
4472 {
4473 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4474 post_event(OMX_CommandPortEnable,
4475 OMX_CORE_OUTPUT_PORT_INDEX,
4476 OMX_COMPONENT_GENERATE_EVENT);
4477 }
4478 }
4479 DEBUG_PRINT_LOW("Use Buffer error = %d", error);
4480 return error;
4481 }
4482
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4483 OMX_ERRORTYPE omx_vdpp::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4484 {
4485 unsigned int index = 0;
4486 if (bufferHdr == NULL || m_inp_mem_ptr == NULL)
4487 {
4488 return OMX_ErrorBadParameter;
4489 }
4490
4491 index = bufferHdr - m_inp_mem_ptr;
4492
4493 // decrease m_in_alloc_cnt so use_input_heap_buffer can be called
4494 // again after port re-enable
4495 m_in_alloc_cnt--;
4496 DEBUG_PRINT_LOW("free_input_buffer Free Input Buffer index = %d, m_in_alloc_cnt = %lu",index, m_in_alloc_cnt);
4497
4498 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
4499 DEBUG_PRINT_LOW("Free Input ION Buffer index = %d",index);
4500 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) {
4501 struct vdpp_setbuffer_cmd setbuffers;
4502 setbuffers.buffer_type = VDPP_BUFFER_TYPE_INPUT;
4503 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
4504 sizeof (vdpp_bufferpayload));
4505 {
4506 DEBUG_PRINT_LOW(" unmap the input buffer fd=%d",
4507 drv_ctx.ptr_inputbuffer[index].pmem_fd);
4508 DEBUG_PRINT_LOW(" unmap the input buffer size=%d address = %p",
4509 drv_ctx.ptr_inputbuffer[index].mmaped_size,
4510 drv_ctx.ptr_inputbuffer[index].bufferaddr);
4511 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
4512 drv_ctx.ptr_inputbuffer[index].mmaped_size);
4513 }
4514
4515 // If drv_ctx.ip_buf_ion_info is NULL then ION buffer is passed from upper layer.
4516 // don't close fd and free this buffer, leave upper layer close and free this buffer
4517 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
4518 if(drv_ctx.ip_buf_ion_info != NULL)
4519 {
4520 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
4521 #ifdef USE_ION
4522 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
4523 #endif
4524 }
4525
4526 }
4527 }
4528 return OMX_ErrorNone;
4529 }
4530
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)4531 OMX_ERRORTYPE omx_vdpp::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4532 {
4533 unsigned int index = 0;
4534
4535 if (bufferHdr == NULL || m_out_mem_ptr == NULL)
4536 {
4537 return OMX_ErrorBadParameter;
4538 }
4539
4540 index = bufferHdr - m_out_mem_ptr;
4541 DEBUG_PRINT_LOW(" Free output Buffer index = %d",index);
4542
4543 if (index < drv_ctx.op_buf.actualcount
4544 && drv_ctx.ptr_outputbuffer)
4545 {
4546 DEBUG_PRINT_LOW(" Free output Buffer index = %d addr = %p", index,
4547 drv_ctx.ptr_outputbuffer[index].bufferaddr);
4548
4549 struct vdpp_setbuffer_cmd setbuffers;
4550 setbuffers.buffer_type = VDPP_BUFFER_TYPE_OUTPUT;
4551 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
4552 sizeof (vdpp_bufferpayload));
4553 #ifdef _ANDROID_
4554 if(m_enable_android_native_buffers) {
4555 DEBUG_PRINT_LOW(" Free output Buffer android pmem_fd=%d", drv_ctx.ptr_outputbuffer[index].pmem_fd);
4556 if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
4557 DEBUG_PRINT_LOW(" Free output Buffer android 2 bufferaddr=%p, mmaped_size=%d",
4558 drv_ctx.ptr_outputbuffer[index].bufferaddr,
4559 drv_ctx.ptr_outputbuffer[index].mmaped_size);
4560 if( NULL != drv_ctx.ptr_outputbuffer[index].bufferaddr)
4561 {
4562 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
4563 drv_ctx.ptr_outputbuffer[index].mmaped_size);
4564 }
4565 }
4566 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
4567 } else {
4568 #endif
4569 if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem)
4570 {
4571 {
4572 DEBUG_PRINT_LOW(" unmap the output buffer fd = %d",
4573 drv_ctx.ptr_outputbuffer[index].pmem_fd);
4574 DEBUG_PRINT_LOW(" unmap the ouput buffer size=%d address = %p",
4575 drv_ctx.ptr_outputbuffer[index].mmaped_size * drv_ctx.op_buf.actualcount,
4576 drv_ctx.ptr_outputbuffer[index].bufferaddr);
4577 munmap (drv_ctx.ptr_outputbuffer[index].bufferaddr,
4578 drv_ctx.ptr_outputbuffer[index].mmaped_size * drv_ctx.op_buf.actualcount);
4579 }
4580 close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
4581 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
4582 #ifdef USE_ION
4583 free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
4584 #endif
4585 }
4586 #ifdef _ANDROID_
4587 }
4588 #endif
4589 if (release_output_done()) {
4590 //free_extradata();
4591 }
4592 }
4593
4594 return OMX_ErrorNone;
4595
4596 }
4597
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)4598 OMX_ERRORTYPE omx_vdpp::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
4599 OMX_BUFFERHEADERTYPE **bufferHdr,
4600 OMX_U32 port,
4601 OMX_PTR appData,
4602 OMX_U32 bytes)
4603 {
4604 OMX_BUFFERHEADERTYPE *input = NULL;
4605 unsigned char *buf_addr = NULL;
4606 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4607 unsigned i = 0;
4608
4609 /* Sanity Check*/
4610 if (bufferHdr == NULL)
4611 {
4612 return OMX_ErrorBadParameter;
4613 }
4614
4615 if (m_inp_heap_ptr == NULL)
4616 {
4617 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
4618 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4619 drv_ctx.ip_buf.actualcount);
4620 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
4621 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4622 drv_ctx.ip_buf.actualcount);
4623
4624 if ((m_inp_heap_ptr == NULL) || (m_phdr_pmem_ptr == NULL))
4625 {
4626 DEBUG_PRINT_ERROR(" m_inp_heap_ptr Allocation failed ");
4627 return OMX_ErrorInsufficientResources;
4628 }
4629 }
4630
4631 /*Find a Free index*/
4632 for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
4633 {
4634 if(BITMASK_ABSENT(&m_heap_inp_bm_count,i))
4635 {
4636 DEBUG_PRINT_LOW(" Free Input Buffer Index %d",i);
4637 break;
4638 }
4639 }
4640
4641 if (i < drv_ctx.ip_buf.actualcount)
4642 {
4643 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
4644
4645 if (buf_addr == NULL)
4646 {
4647 return OMX_ErrorInsufficientResources;
4648 }
4649
4650 *bufferHdr = (m_inp_heap_ptr + i);
4651 input = *bufferHdr;
4652 BITMASK_SET(&m_heap_inp_bm_count,i);
4653
4654 input->pBuffer = (OMX_U8 *)buf_addr;
4655 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4656 input->nVersion.nVersion = OMX_SPEC_VERSION;
4657 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4658 input->pAppPrivate = appData;
4659 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4660 DEBUG_PRINT_LOW(" Address of Heap Buffer %p",*bufferHdr );
4661 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
4662 DEBUG_PRINT_LOW(" Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
4663 /*Add the Buffers to freeq*/
4664 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[i],
4665 (unsigned)NULL, (unsigned)NULL))
4666 {
4667 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
4668 return OMX_ErrorInsufficientResources;
4669 }
4670 }
4671 else
4672 {
4673 return OMX_ErrorBadParameter;
4674 }
4675
4676 return eRet;
4677
4678 }
4679
4680 /* ======================================================================
4681 FUNCTION
4682 omx_vdpp::AllocateInputBuffer
4683
4684 DESCRIPTION
4685 Helper function for allocate buffer in the input pin
4686
4687 PARAMETERS
4688 None.
4689
4690 RETURN VALUE
4691 true/false
4692
4693 ========================================================================== */
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)4694 OMX_ERRORTYPE omx_vdpp::allocate_input_buffer(
4695 OMX_IN OMX_HANDLETYPE hComp,
4696 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4697 OMX_IN OMX_U32 port,
4698 OMX_IN OMX_PTR appData,
4699 OMX_IN OMX_U32 bytes)
4700 {
4701
4702 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4703 struct vdpp_setbuffer_cmd setbuffers;
4704 OMX_BUFFERHEADERTYPE *input = NULL;
4705 unsigned i = 0;
4706 unsigned char *buf_addr = NULL;
4707 int pmem_fd = -1;
4708
4709 if(bytes != drv_ctx.ip_buf.buffer_size)
4710 {
4711 DEBUG_PRINT_LOW(" Requested Size is wrong %lu expected is %d",
4712 bytes, drv_ctx.ip_buf.buffer_size);
4713 return OMX_ErrorBadParameter;
4714 }
4715
4716 if(!m_inp_mem_ptr)
4717 {
4718 DEBUG_PRINT_HIGH(" Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
4719 drv_ctx.ip_buf.actualcount,
4720 drv_ctx.ip_buf.buffer_size);
4721
4722 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4723 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4724
4725 if (m_inp_mem_ptr == NULL)
4726 {
4727 return OMX_ErrorInsufficientResources;
4728 }
4729
4730 drv_ctx.ptr_inputbuffer = (struct vdpp_bufferpayload *) \
4731 calloc ((sizeof (struct vdpp_bufferpayload)),drv_ctx.ip_buf.actualcount);
4732
4733 if (drv_ctx.ptr_inputbuffer == NULL)
4734 {
4735 return OMX_ErrorInsufficientResources;
4736 }
4737 #ifdef USE_ION
4738 drv_ctx.ip_buf_ion_info = (struct vdpp_ion *) \
4739 calloc ((sizeof (struct vdpp_ion)),drv_ctx.ip_buf.actualcount);
4740
4741 if (drv_ctx.ip_buf_ion_info == NULL)
4742 {
4743 return OMX_ErrorInsufficientResources;
4744 }
4745 #endif
4746
4747 for (i=0; i < drv_ctx.ip_buf.actualcount; i++)
4748 {
4749 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
4750 #ifdef USE_ION
4751 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
4752 #endif
4753 }
4754 }
4755
4756 for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
4757 {
4758 if(BITMASK_ABSENT(&m_inp_bm_count,i))
4759 {
4760 DEBUG_PRINT_LOW(" Free Input Buffer Index %d",i);
4761 break;
4762 }
4763 }
4764
4765 if(i < drv_ctx.ip_buf.actualcount)
4766 {
4767 struct v4l2_buffer buf;
4768 struct v4l2_plane plane;
4769 int rc;
4770 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer Allocate input Buffer, drv_ctx.ip_buf.buffer_size = %d", drv_ctx.ip_buf.buffer_size);
4771 #ifdef USE_ION
4772 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
4773 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
4774 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
4775 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, 0);
4776 if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
4777 return OMX_ErrorInsufficientResources;
4778 }
4779 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
4780 #endif
4781
4782 {
4783 buf_addr = (unsigned char *)mmap(NULL,
4784 drv_ctx.ip_buf.buffer_size,
4785 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
4786
4787 if (buf_addr == MAP_FAILED)
4788 {
4789 close(pmem_fd);
4790 #ifdef USE_ION
4791 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
4792 #endif
4793 DEBUG_PRINT_ERROR(" Map Failed to allocate input buffer");
4794 return OMX_ErrorInsufficientResources;
4795 }
4796 }
4797 *bufferHdr = (m_inp_mem_ptr + i);
4798
4799 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
4800 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
4801 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4802 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
4803 drv_ctx.ptr_inputbuffer [i].offset = 0;
4804
4805 input = *bufferHdr;
4806 BITMASK_SET(&m_inp_bm_count,i);
4807 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer Buffer address %p of pmem",*bufferHdr);
4808
4809 input->pBuffer = (OMX_U8 *)buf_addr;
4810 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4811 input->nVersion.nVersion = OMX_SPEC_VERSION;
4812 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4813 input->pAppPrivate = appData;
4814 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4815 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; // used in empty_this_buffer_proxy
4816
4817 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer input->pBuffer %p of pmem, input->pInputPortPrivate = %p",input->pBuffer, input->pInputPortPrivate);
4818 memset(buf_addr, 0, drv_ctx.ip_buf.buffer_size);
4819 DEBUG_PRINT_LOW("omx_vdpp::allocate_input_buffer memset drv_ctx.ip_buf.buffer_size = %d\n", drv_ctx.ip_buf.buffer_size);
4820 }
4821 else
4822 {
4823 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
4824 eRet = OMX_ErrorInsufficientResources;
4825 }
4826 return eRet;
4827 }
4828
4829
4830 /* ======================================================================
4831 FUNCTION
4832 omx_vdpp::AllocateOutputBuffer
4833
4834 DESCRIPTION
4835 Helper fn for AllocateBuffer in the output pin
4836
4837 PARAMETERS
4838 <TBD>.
4839
4840 RETURN VALUE
4841 OMX Error None if everything went well.
4842
4843 ========================================================================== */
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)4844 OMX_ERRORTYPE omx_vdpp::allocate_output_buffer(
4845 OMX_IN OMX_HANDLETYPE hComp,
4846 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4847 OMX_IN OMX_U32 port,
4848 OMX_IN OMX_PTR appData,
4849 OMX_IN OMX_U32 bytes)
4850 {
4851 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4852 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
4853 unsigned i= 0; // Temporary counter
4854 struct vdpp_setbuffer_cmd setbuffers;
4855 int extra_idx = 0;
4856 #ifdef USE_ION
4857 int ion_device_fd =-1;
4858 struct ion_allocation_data ion_alloc_data;
4859 struct ion_fd_data fd_ion_data;
4860 #endif
4861 if(!m_out_mem_ptr)
4862 {
4863 DEBUG_PRINT_HIGH(" Allocate o/p buffer Header: Cnt(%d) Sz(%d)",
4864 drv_ctx.op_buf.actualcount,
4865 drv_ctx.op_buf.buffer_size);
4866 int nBufHdrSize = 0;
4867 int pmem_fd = -1;
4868 unsigned char *pmem_baseaddress = NULL;
4869
4870 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",
4871 drv_ctx.op_buf.actualcount);
4872 nBufHdrSize = drv_ctx.op_buf.actualcount *
4873 sizeof(OMX_BUFFERHEADERTYPE);
4874 #ifdef USE_ION
4875 ion_device_fd = alloc_map_ion_memory(
4876 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
4877 drv_ctx.op_buf.alignment,
4878 &ion_alloc_data, &fd_ion_data, 0);
4879 if (ion_device_fd < 0) {
4880 return OMX_ErrorInsufficientResources;
4881 }
4882 pmem_fd = fd_ion_data.fd;
4883 #endif
4884
4885 {
4886 pmem_baseaddress = (unsigned char *)mmap(NULL,
4887 (drv_ctx.op_buf.buffer_size *
4888 drv_ctx.op_buf.actualcount),
4889 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
4890 if (pmem_baseaddress == MAP_FAILED)
4891 {
4892 DEBUG_PRINT_ERROR(" MMAP failed for Size %d",
4893 drv_ctx.op_buf.buffer_size);
4894 close(pmem_fd);
4895 #ifdef USE_ION
4896 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
4897 #endif
4898 return OMX_ErrorInsufficientResources;
4899 }
4900 }
4901
4902 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
4903
4904 drv_ctx.ptr_outputbuffer = (struct vdpp_bufferpayload *)\
4905 calloc (sizeof(struct vdpp_bufferpayload),
4906 drv_ctx.op_buf.actualcount);
4907 drv_ctx.ptr_respbuffer = (struct vdpp_output_frameinfo *)\
4908 calloc (sizeof (struct vdpp_output_frameinfo),
4909 drv_ctx.op_buf.actualcount);
4910 #ifdef USE_ION
4911 drv_ctx.op_buf_ion_info = (struct vdpp_ion *)\
4912 calloc (sizeof(struct vdpp_ion),
4913 drv_ctx.op_buf.actualcount);
4914
4915 if (!drv_ctx.op_buf_ion_info) {
4916 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
4917 return OMX_ErrorInsufficientResources;
4918 }
4919 #endif
4920
4921 if(m_out_mem_ptr /*&& pPtr*/ && drv_ctx.ptr_outputbuffer
4922 && drv_ctx.ptr_respbuffer)
4923 {
4924 drv_ctx.ptr_outputbuffer[0].mmaped_size =
4925 (drv_ctx.op_buf.buffer_size *
4926 drv_ctx.op_buf.actualcount);
4927 bufHdr = m_out_mem_ptr;
4928
4929 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
4930
4931 for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
4932 {
4933 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4934 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
4935 // Set the values when we determine the right HxW param
4936 bufHdr->nAllocLen = bytes;
4937 bufHdr->nFilledLen = 0;
4938 bufHdr->pAppPrivate = appData;
4939 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
4940 bufHdr->pBuffer = NULL;
4941 bufHdr->nOffset = 0;
4942
4943 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
4944 #ifdef USE_ION
4945 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
4946 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
4947 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
4948 #endif
4949
4950 /*Create a mapping between buffers*/
4951 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
4952 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
4953 &drv_ctx.ptr_outputbuffer[i];
4954 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
4955 drv_ctx.ptr_outputbuffer[i].bufferaddr =
4956 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
4957
4958 DEBUG_PRINT_LOW(" pmem_fd = %d offset = %d address = %p",
4959 pmem_fd, drv_ctx.ptr_outputbuffer[i].offset,
4960 drv_ctx.ptr_outputbuffer[i].bufferaddr);
4961 // Move the buffer and buffer header pointers
4962 bufHdr++;
4963
4964 }
4965 }
4966 else
4967 {
4968 if(m_out_mem_ptr)
4969 {
4970 free(m_out_mem_ptr);
4971 m_out_mem_ptr = NULL;
4972 }
4973
4974 if(drv_ctx.ptr_outputbuffer)
4975 {
4976 free(drv_ctx.ptr_outputbuffer);
4977 drv_ctx.ptr_outputbuffer = NULL;
4978 }
4979 if(drv_ctx.ptr_respbuffer)
4980 {
4981 free(drv_ctx.ptr_respbuffer);
4982 drv_ctx.ptr_respbuffer = NULL;
4983 }
4984 #ifdef USE_ION
4985 if (drv_ctx.op_buf_ion_info) {
4986 DEBUG_PRINT_LOW(" Free o/p ion context");
4987 free(drv_ctx.op_buf_ion_info);
4988 drv_ctx.op_buf_ion_info = NULL;
4989 }
4990 #endif
4991 eRet = OMX_ErrorInsufficientResources;
4992 }
4993 }
4994
4995 for(i=0; i< drv_ctx.op_buf.actualcount; i++)
4996 {
4997 if(BITMASK_ABSENT(&m_out_bm_count,i))
4998 {
4999 DEBUG_PRINT_LOW(" Found a Free Output Buffer %d",i);
5000 break;
5001 }
5002 }
5003
5004 if (eRet == OMX_ErrorNone)
5005 {
5006 if(i < drv_ctx.op_buf.actualcount)
5007 {
5008 struct v4l2_buffer buf;
5009 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5010 int rc;
5011
5012 drv_ctx.ptr_outputbuffer[i].buffer_len =
5013 drv_ctx.op_buf.buffer_size;
5014
5015 *bufferHdr = (m_out_mem_ptr + i );
5016 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
5017
5018 #ifndef STUB_VPU
5019 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
5020 enum v4l2_buf_type buf_type;
5021 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5022 rc=ioctl(drv_ctx.video_vpu_fd, VIDIOC_STREAMON,&buf_type);
5023 if (rc) {
5024 DEBUG_PRINT_ERROR("allocate_output_buffer STREAMON failed \n ");
5025 return OMX_ErrorInsufficientResources;
5026 } else {
5027 streaming[CAPTURE_PORT] = true;
5028 DEBUG_PRINT_HIGH("allocate_output_buffer STREAMON Successful \n ");
5029 }
5030 }
5031 #endif
5032
5033 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
5034 (*bufferHdr)->pAppPrivate = appData;
5035 BITMASK_SET(&m_out_bm_count,i);
5036 }
5037 else
5038 {
5039 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient \n");
5040 eRet = OMX_ErrorInsufficientResources;
5041 }
5042 }
5043
5044 return eRet;
5045 }
5046
5047
5048 // AllocateBuffer -- API Call
5049 /* ======================================================================
5050 FUNCTION
5051 omx_vdpp::AllocateBuffer
5052
5053 DESCRIPTION
5054 Returns zero if all the buffers released..
5055
5056 PARAMETERS
5057 None.
5058
5059 RETURN VALUE
5060 true/false
5061
5062 ========================================================================== */
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)5063 OMX_ERRORTYPE omx_vdpp::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
5064 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5065 OMX_IN OMX_U32 port,
5066 OMX_IN OMX_PTR appData,
5067 OMX_IN OMX_U32 bytes)
5068 {
5069 unsigned i = 0;
5070 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
5071
5072 DEBUG_PRINT_LOW(" Allocate buffer on port %d \n", (int)port);
5073 if(m_state == OMX_StateInvalid)
5074 {
5075 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n");
5076 return OMX_ErrorInvalidState;
5077 }
5078
5079 if(port == OMX_CORE_INPUT_PORT_INDEX)
5080 {
5081 eRet = allocate_input_heap_buffer(hComp,bufferHdr,port,appData,bytes);
5082 }
5083 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
5084 {
5085 eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
5086 }
5087 else
5088 {
5089 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
5090 eRet = OMX_ErrorBadPortIndex;
5091 }
5092 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
5093 if(eRet == OMX_ErrorNone)
5094 {
5095 if(allocate_done()){
5096 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
5097 {
5098 // Send the callback now
5099 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
5100 post_event(OMX_CommandStateSet,OMX_StateIdle,
5101 OMX_COMPONENT_GENERATE_EVENT);
5102 }
5103 }
5104 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated)
5105 {
5106 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
5107 {
5108 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
5109 post_event(OMX_CommandPortEnable,
5110 OMX_CORE_INPUT_PORT_INDEX,
5111 OMX_COMPONENT_GENERATE_EVENT);
5112 }
5113 }
5114 if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated)
5115 {
5116 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
5117 {
5118 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
5119 post_event(OMX_CommandPortEnable,
5120 OMX_CORE_OUTPUT_PORT_INDEX,
5121 OMX_COMPONENT_GENERATE_EVENT);
5122 }
5123 }
5124 }
5125 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet);
5126 return eRet;
5127 }
5128
5129 // Free Buffer - API call
5130 /* ======================================================================
5131 FUNCTION
5132 omx_vdpp::FreeBuffer
5133
5134 DESCRIPTION
5135
5136 PARAMETERS
5137 None.
5138
5139 RETURN VALUE
5140 true/false
5141
5142 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5143 OMX_ERRORTYPE omx_vdpp::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
5144 OMX_IN OMX_U32 port,
5145 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5146 {
5147 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5148 unsigned int nPortIndex;
5149 DEBUG_PRINT_LOW("In for vdpp free_buffer \n");
5150
5151 if(m_state == OMX_StateIdle &&
5152 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
5153 {
5154 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n");
5155 }
5156 else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
5157 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX))
5158 {
5159 DEBUG_PRINT_LOW("Free Buffer while port %lu disabled\n", port);
5160 }
5161 else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause)
5162 {
5163 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n");
5164 post_event(OMX_EventError,
5165 OMX_ErrorPortUnpopulated,
5166 OMX_COMPONENT_GENERATE_EVENT);
5167
5168 return OMX_ErrorIncorrectStateOperation;
5169 }
5170 else if (m_state != OMX_StateInvalid)
5171 {
5172 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n");
5173 post_event(OMX_EventError,
5174 OMX_ErrorPortUnpopulated,
5175 OMX_COMPONENT_GENERATE_EVENT);
5176 }
5177
5178 if(port == OMX_CORE_INPUT_PORT_INDEX)
5179 {
5180 /*Check if arbitrary bytes*/
5181 if(!input_use_buffer)
5182 nPortIndex = buffer - m_inp_mem_ptr;
5183 else
5184 nPortIndex = buffer - m_inp_heap_ptr;
5185
5186 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex);
5187 if(nPortIndex < drv_ctx.ip_buf.actualcount)
5188 {
5189 // Clear the bit associated with it.
5190 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
5191 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
5192 if (input_use_buffer == true)
5193 {
5194
5195 DEBUG_PRINT_LOW(" Free pmem Buffer index %d",nPortIndex);
5196 if(m_phdr_pmem_ptr)
5197 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
5198 }
5199 else
5200 {
5201 free_input_buffer(buffer);
5202 }
5203 m_inp_bPopulated = OMX_FALSE;
5204 /*Free the Buffer Header*/
5205 if (release_input_done())
5206 {
5207 DEBUG_PRINT_HIGH(" ALL input buffers are freed/released");
5208 free_input_buffer_header();
5209 }
5210 }
5211 else
5212 {
5213 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid\n");
5214 eRet = OMX_ErrorBadPortIndex;
5215 }
5216
5217 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
5218 && release_input_done())
5219 {
5220 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
5221 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
5222 post_event(OMX_CommandPortDisable,
5223 OMX_CORE_INPUT_PORT_INDEX,
5224 OMX_COMPONENT_GENERATE_EVENT);
5225 }
5226 }
5227 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
5228 {
5229 // check if the buffer is valid
5230 nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
5231 if(nPortIndex < drv_ctx.op_buf.actualcount)
5232 {
5233 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex);
5234 // Clear the bit associated with it.
5235 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
5236 m_out_bPopulated = OMX_FALSE;
5237 free_output_buffer (buffer);
5238
5239 if (release_output_done())
5240 {
5241 free_output_buffer_header();
5242 }
5243 }
5244 else
5245 {
5246 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid\n");
5247 eRet = OMX_ErrorBadPortIndex;
5248 }
5249 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
5250 && release_output_done())
5251 {
5252 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n");
5253
5254 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
5255 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
5256 #ifdef _ANDROID_ICS_
5257 if (m_enable_android_native_buffers)
5258 {
5259 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
5260 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5261 }
5262 #endif
5263
5264 post_event(OMX_CommandPortDisable,
5265 OMX_CORE_OUTPUT_PORT_INDEX,
5266 OMX_COMPONENT_GENERATE_EVENT);
5267 }
5268 }
5269 else
5270 {
5271 eRet = OMX_ErrorBadPortIndex;
5272 }
5273 if((eRet == OMX_ErrorNone) &&
5274 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
5275 {
5276 if(release_done())
5277 {
5278 // Send the callback now
5279 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
5280 post_event(OMX_CommandStateSet, OMX_StateLoaded,
5281 OMX_COMPONENT_GENERATE_EVENT);
5282 }
5283 }
5284 return eRet;
5285 }
5286
5287
5288 /* ======================================================================
5289 FUNCTION
5290 omx_vdpp::EmptyThisBuffer
5291
5292 DESCRIPTION
5293 This routine is used to push the video frames to VDPP.
5294
5295 PARAMETERS
5296 None.
5297
5298 RETURN VALUE
5299 OMX Error None if everything went successful.
5300
5301 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5302 OMX_ERRORTYPE omx_vdpp::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
5303 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5304 {
5305 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
5306 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
5307
5308 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer buffer = %p, buffer->pBuffer = %p, buffer->pPlatformPrivate = %p, buffer->nFilledLen = %lu\n",
5309 // buffer, buffer->pBuffer, buffer->pPlatformPrivate, buffer->nFilledLen);
5310 if(m_state == OMX_StateInvalid)
5311 {
5312 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n");
5313 return OMX_ErrorInvalidState;
5314 }
5315
5316 if (buffer == NULL)
5317 {
5318 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
5319 return OMX_ErrorBadParameter;
5320 }
5321
5322 if (!m_inp_bEnabled)
5323 {
5324 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
5325 return OMX_ErrorIncorrectStateOperation;
5326 }
5327
5328 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX)
5329 {
5330 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %lu", buffer->nInputPortIndex);
5331 return OMX_ErrorBadPortIndex;
5332 }
5333
5334 if (input_use_buffer == true)
5335 {
5336 nBufferIndex = buffer - m_inp_heap_ptr;
5337 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
5338 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
5339 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
5340 buffer = &m_inp_mem_ptr[nBufferIndex]; // change heap buffer address to ION buffer address
5341 //DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem %p in Index %d, buffer %p of size %lu",
5342 // &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen);
5343 }
5344 else{
5345 nBufferIndex = buffer - m_inp_mem_ptr;
5346 }
5347
5348 if (nBufferIndex > drv_ctx.ip_buf.actualcount )
5349 {
5350 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
5351 return OMX_ErrorBadParameter;
5352 }
5353
5354 DEBUG_PRINT_HIGH("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)",
5355 buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen);
5356
5357 set_frame_rate(buffer->nTimeStamp);
5358 post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
5359
5360 return OMX_ErrorNone;
5361 }
5362
5363 /* ======================================================================
5364 FUNCTION
5365 omx_vdpp::empty_this_buffer_proxy
5366
5367 DESCRIPTION
5368 This routine is used to push the video decoder output frames to
5369 the VDPP.
5370
5371 PARAMETERS
5372 None.
5373
5374 RETURN VALUE
5375 OMX Error None if everything went successful.
5376
5377 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5378 OMX_ERRORTYPE omx_vdpp::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
5379 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5380 {
5381 int i=0;
5382 unsigned nPortIndex = 0;
5383 OMX_ERRORTYPE ret = OMX_ErrorNone;
5384 struct vdpp_bufferpayload *temp_buffer;
5385 unsigned p1 = 0;
5386 unsigned p2 = 0;
5387
5388 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 1\n");
5389 /*Should we generate a Aync error event*/
5390 if (buffer == NULL || buffer->pInputPortPrivate == NULL)
5391 {
5392 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
5393 return OMX_ErrorBadParameter;
5394 }
5395
5396 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
5397 DEBUG_PRINT_HIGH("omx_vdpp::empty_this_buffer_proxy 2 nPortIndex = %d, buffer->nFilledLen = %lu\n", nPortIndex, buffer->nFilledLen);
5398 if (nPortIndex > drv_ctx.ip_buf.actualcount)
5399 {
5400 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
5401 nPortIndex);
5402 return OMX_ErrorBadParameter;
5403 }
5404
5405 pending_input_buffers++;
5406 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 3 pending_input_buffers = %d\n", pending_input_buffers);
5407 /* return zero length and not an EOS buffer */
5408 if ((buffer->nFilledLen == 0) &&
5409 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5410 {
5411 DEBUG_PRINT_HIGH(" return zero legth buffer");
5412 post_event ((unsigned int)buffer,VDPP_S_SUCCESS,
5413 OMX_COMPONENT_GENERATE_EBD);
5414 return OMX_ErrorNone;
5415 }
5416
5417 // check OMX_BUFFERFLAG_EXTRADATA for interlaced information
5418 // and set it to drv_ctx.interlace if returned interlace mode
5419 // doesn't match drv_ctx.interlace.
5420 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 3 buffer->nFlags = 0x%x interlace_user_flag = %d ", buffer->nFlags, interlace_user_flag);
5421 if(((buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) != 0) && (false == interlace_user_flag))
5422 {
5423 OMX_OTHER_EXTRADATATYPE *pExtra;
5424 v4l2_field field = drv_ctx.interlace;// V4L2_FIELD_NONE;
5425 OMX_U8 *pTmp = buffer->pBuffer + buffer->nOffset + 3;
5426
5427 pExtra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U32) pTmp) & ~3);
5428 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 3 buffer->nFlags = 0x%x, pExtra->eType = 0x%x\n", buffer->nFlags, pExtra->eType);
5429 // traverset the list of extra data sections
5430 while(OMX_ExtraDataNone != pExtra->eType)
5431 {
5432 if(OMX_ExtraDataInterlaceFormat == (OMX_QCOM_EXTRADATATYPE)pExtra->eType)
5433 {
5434 OMX_STREAMINTERLACEFORMAT *interlace_format;
5435 interlace_format = (OMX_STREAMINTERLACEFORMAT *)pExtra->data;
5436
5437 switch (interlace_format->nInterlaceFormats)
5438 {
5439 case OMX_InterlaceFrameProgressive:
5440 {
5441 field = V4L2_FIELD_NONE;
5442 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy V4L2_FIELD_NONE");
5443 break;
5444 }
5445 case OMX_InterlaceInterleaveFrameTopFieldFirst:
5446 {
5447 field = V4L2_FIELD_INTERLACED_TB;
5448 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy V4L2_FIELD_INTERLACED_TB");
5449 break;
5450 }
5451 case OMX_InterlaceInterleaveFrameBottomFieldFirst:
5452 {
5453 field = V4L2_FIELD_INTERLACED_BT;
5454 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy V4L2_FIELD_INTERLACED_BT");
5455 break;
5456 }
5457 case OMX_InterlaceFrameTopFieldFirst:
5458 {
5459 field = V4L2_FIELD_SEQ_TB;
5460 break;
5461 }
5462 case OMX_InterlaceFrameBottomFieldFirst:
5463 {
5464 field = V4L2_FIELD_SEQ_BT;
5465 break;
5466 }
5467 default:
5468 break;
5469 }
5470 break;
5471 }
5472 pExtra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) pExtra) + pExtra->nSize);
5473 }
5474
5475 if(drv_ctx.interlace != field)
5476 {
5477 drv_ctx.interlace = field;
5478
5479 // set input port format based on the detected interlace mode
5480 ret = set_buffer_req(&drv_ctx.ip_buf);
5481 if(OMX_ErrorNone != ret)
5482 {
5483 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid format setting");
5484 return ret;
5485 }
5486 }
5487 }
5488
5489 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 4 \n");
5490 if(input_flush_progress == true)
5491 {
5492 DEBUG_PRINT_LOW(" Flush in progress return buffer ");
5493 post_event ((unsigned int)buffer,VDPP_S_SUCCESS,
5494 OMX_COMPONENT_GENERATE_EBD);
5495 return OMX_ErrorNone;
5496 }
5497
5498 temp_buffer = (struct vdpp_bufferpayload *)buffer->pInputPortPrivate;
5499
5500 if ((temp_buffer - drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount)
5501 {
5502 return OMX_ErrorBadParameter;
5503 }
5504
5505 //DEBUG_PRINT_LOW(" ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5506 /*for use_input_heap_buffer memcpy is used*/
5507 temp_buffer->buffer_len = buffer->nFilledLen;
5508
5509
5510 if (input_use_buffer)
5511 {
5512 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 5 \n");
5513 if (buffer->nFilledLen <= temp_buffer->buffer_len)
5514 {
5515 DEBUG_PRINT_HIGH("omx_vdpp::empty_this_buffer_proxy 5.1 temp_buffer->bufferaddr = %p, m_inp_heap_ptr[%d].pPlatformPrivate = %p, m_inp_heap_ptr[%d].nOffset = %lu\n",
5516 temp_buffer->bufferaddr, nPortIndex, m_inp_heap_ptr[nPortIndex].pPlatformPrivate, nPortIndex, m_inp_heap_ptr[nPortIndex].nOffset);
5517 //memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pPlatformPrivate + m_inp_heap_ptr[nPortIndex].nOffset),
5518 // buffer->nFilledLen);
5519 }
5520 else
5521 {
5522 return OMX_ErrorBadParameter;
5523 }
5524 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 5.2 \n");
5525 }
5526
5527 #ifdef INPUT_BUFFER_LOG
5528 if ((inputBufferFile >= 0) && (input_buffer_write_counter < 10))
5529 {
5530 int stride = drv_ctx.video_resolution_input.stride; //w
5531 int scanlines = drv_ctx.video_resolution_input.scan_lines; //h
5532 DEBUG_PRINT_HIGH("omx_vdpp::empty_buffer_done 2.5 stride = %d, scanlines = %d , frame_height = %d", stride, scanlines, drv_ctx.video_resolution_input.frame_height);
5533 char *temp = (char *)temp_buffer->bufferaddr;
5534 unsigned i;
5535 int bytes_written = 0;
5536 for (i = 0; i < drv_ctx.video_resolution_input.frame_height; i++) {
5537 bytes_written = write(inputBufferFile, temp, drv_ctx.video_resolution_input.frame_width);
5538 temp += stride;
5539 }
5540 temp = (char *)(char *)temp_buffer->bufferaddr + stride * scanlines;
5541 int stride_c = stride;
5542 for(i = 0; i < drv_ctx.video_resolution_input.frame_height/2; i++) {
5543 bytes_written += write(inputBufferFile, temp, drv_ctx.video_resolution_input.frame_width);
5544 temp += stride_c;
5545 }
5546 input_buffer_write_counter++;
5547 }
5548
5549 if(input_buffer_write_counter >= 10 )
5550 {
5551 close(inputBufferFile);
5552 }
5553 #endif
5554
5555 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 5.3 \n");
5556 if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ)
5557 {
5558 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 5.4 \n");
5559 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5560 }
5561
5562 struct v4l2_buffer buf;
5563 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5564 int extra_idx = 0;
5565 int rc;
5566 unsigned long print_count;
5567
5568 memset( (void *)&buf, 0, sizeof(buf));
5569 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
5570
5571 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS))
5572 { buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
5573 DEBUG_PRINT_HIGH("temp_buffer->buffer_len = %d, buffer->nFlags = 0x%lx \n", temp_buffer->buffer_len, buffer->nFlags) ;
5574 DEBUG_PRINT_HIGH(" INPUT EOS reached \n") ;
5575 }
5576
5577 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5578
5579 // The following fills v4l2_buffer structure
5580 buf.index = nPortIndex;
5581 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5582 buf.field = drv_ctx.interlace;
5583 buf.memory = V4L2_MEMORY_USERPTR;
5584 buf.length = drv_ctx.input_num_planes;
5585
5586 // currently V4L2 driver just passes timestamp to maple FW, and maple FW
5587 // pass the timestamp back to OMX
5588 *(uint64_t *)(&buf.timestamp) = buffer->nTimeStamp;
5589
5590 plane[0].bytesused = drv_ctx.video_resolution_input.frame_width *
5591 drv_ctx.video_resolution_input.frame_height *
5592 drv_ctx.input_bytesperpixel[0];//buffer->nFilledLen = 0 at this stage
5593 plane[0].length = paddedFrameWidth128(drv_ctx.video_resolution_input.frame_width) *
5594 drv_ctx.video_resolution_input.frame_height *
5595 drv_ctx.input_bytesperpixel[0];
5596 plane[0].m.userptr = temp_buffer->pmem_fd;
5597 plane[0].reserved[0] = 0;
5598 extra_idx = EXTRADATA_IDX(drv_ctx.input_num_planes);
5599 if ((extra_idx > 0) && (extra_idx < VIDEO_MAX_PLANES)) {
5600 plane[extra_idx].bytesused = drv_ctx.video_resolution_input.frame_width *
5601 drv_ctx.video_resolution_input.frame_height *
5602 drv_ctx.input_bytesperpixel[extra_idx];
5603 plane[extra_idx].length = paddedFrameWidth128(drv_ctx.video_resolution_input.frame_width) *
5604 drv_ctx.video_resolution_input.frame_height *
5605 drv_ctx.input_bytesperpixel[extra_idx];
5606
5607
5608 plane[extra_idx].m.userptr = temp_buffer->pmem_fd;
5609 plane[extra_idx].reserved[0] = plane[0].reserved[0] + drv_ctx.video_resolution_input.stride * drv_ctx.video_resolution_input.scan_lines;
5610 } else if (extra_idx >= VIDEO_MAX_PLANES) {
5611 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
5612 return OMX_ErrorBadParameter;
5613 }
5614 buf.m.planes = plane;
5615 buf.length = drv_ctx.input_num_planes;
5616 /*DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy: buffer->nFilledLen = %d, plane[0].bytesused = %d plane[0].length = %d,\
5617 plane[extra_idx].bytesused = %d, plane[extra_idx].length = %d, plane[extra_idx].data_offset = %d plane[0].data_offset = %d\
5618 buf.timestamp.tv_sec = 0x%08x, buf.timestamp.tv_usec = 0x%08x\n",
5619 buffer->nFilledLen, plane[0].bytesused, plane[0].length, plane[extra_idx].bytesused, plane[extra_idx].length, plane[extra_idx].data_offset, plane[0].data_offset,
5620 buf.timestamp.tv_sec, buf.timestamp.tv_usec);
5621 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy: buffer->nTimeStamp = 0x%016llx; buf.timestamp.tv_sec = 0x%08lx, buf.timestamp.tv_usec = 0x%08lx\n",
5622 buffer->nTimeStamp, buf.timestamp.tv_sec, buf.timestamp.tv_usec);*/
5623
5624 input_qbuf_count++;
5625
5626 #ifdef STUB_VPU
5627
5628 #else
5629 rc = ioctl(drv_ctx.video_vpu_fd, VIDIOC_QBUF, &buf);
5630 if(rc)
5631 {
5632 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver\n");
5633 return OMX_ErrorHardware;
5634 }
5635 #endif
5636
5637 //DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 15 \n");
5638 #ifndef STUB_VPU
5639 if(!streaming[OUTPUT_PORT])
5640 {
5641 enum v4l2_buf_type buf_type;
5642 int ret,r;
5643 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 16 \n");
5644 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5645 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
5646 ret=ioctl(drv_ctx.video_vpu_fd, VIDIOC_STREAMON,&buf_type);
5647 if(!ret) {
5648 DEBUG_PRINT_HIGH("V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE STREAMON Successful \n");
5649 streaming[OUTPUT_PORT] = true;
5650 } else{
5651 DEBUG_PRINT_ERROR(" \n Failed to call streamon on V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \n");
5652 return OMX_ErrorInsufficientResources;
5653 }
5654 }
5655 #endif
5656
5657 #ifdef STUB_VPU
5658 drv_ctx.etb_ftb_info.etb_cnt++;
5659 DEBUG_PRINT_LOW("omx_vdpp::empty_this_buffer_proxy 15 drv_ctx.etb_ftb_info.etb_cnt = %d\n", drv_ctx.etb_ftb_info.etb_cnt);
5660 m_index_q_etb.insert_entry(p1,p2,nPortIndex);
5661 //drv_ctx.etb_ftb_info.etb_index = nPortIndex;
5662 drv_ctx.etb_ftb_info.etb_len = buf.length;
5663 sem_post (&(drv_ctx.async_lock));
5664 #endif
5665 return ret;
5666 }
5667
5668 /* ======================================================================
5669 FUNCTION
5670 omx_vdpp::FillThisBuffer
5671
5672 DESCRIPTION
5673 IL client uses this method to release the frame buffer
5674 after displaying them.
5675
5676 PARAMETERS
5677 None.
5678
5679 RETURN VALUE
5680 true/false
5681
5682 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)5683 OMX_ERRORTYPE omx_vdpp::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
5684 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5685 {
5686
5687 if(m_state == OMX_StateInvalid)
5688 {
5689 DEBUG_PRINT_ERROR("FTB in Invalid State\n");
5690 return OMX_ErrorInvalidState;
5691 }
5692
5693 if (!m_out_bEnabled)
5694 {
5695 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
5696 return OMX_ErrorIncorrectStateOperation;
5697 }
5698
5699 if (buffer == NULL ||
5700 ((buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount))
5701 {
5702 return OMX_ErrorBadParameter;
5703 }
5704
5705 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX)
5706 {
5707 DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %lu", buffer->nOutputPortIndex);
5708 return OMX_ErrorBadPortIndex;
5709 }
5710 //DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p, buffer->nFilledLen = %lu", buffer, buffer->pBuffer, buffer->nFilledLen);
5711 post_event((unsigned) hComp, (unsigned)buffer, m_fill_output_msg);
5712
5713 return OMX_ErrorNone;
5714 }
5715 /* ======================================================================
5716 FUNCTION
5717 omx_vdpp::fill_this_buffer_proxy
5718
5719 DESCRIPTION
5720 IL client uses this method to release the frame buffer
5721 after displaying them.
5722
5723 PARAMETERS
5724 None.
5725
5726 RETURN VALUE
5727 true/false
5728
5729 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)5730 OMX_ERRORTYPE omx_vdpp::fill_this_buffer_proxy(
5731 OMX_IN OMX_HANDLETYPE hComp,
5732 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
5733 {
5734 OMX_ERRORTYPE nRet = OMX_ErrorNone;
5735 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
5736 unsigned nPortIndex = 0;
5737 struct vdpp_bufferpayload *ptr_outputbuffer = NULL;
5738 struct vdpp_output_frameinfo *ptr_respbuffer = NULL;
5739 private_handle_t *handle = NULL;
5740
5741 unsigned p1 = 0;
5742 unsigned p2 = 0;
5743
5744 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_out_mem_ptr);
5745
5746 if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount)
5747 return OMX_ErrorBadParameter;
5748
5749 DEBUG_PRINT_HIGH(" FTBProxy: nPortIndex = %d, bufhdr = %p, bufhdr->pBuffer = %p, buffer->nFilledLen = %lu",
5750 nPortIndex, bufferAdd, bufferAdd->pBuffer, buffer->nFilledLen);
5751
5752 /*Return back the output buffer to client*/
5753 if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true)
5754 {
5755 DEBUG_PRINT_LOW(" Output Buffers return flush/disable condition");
5756 buffer->nFilledLen = 0;
5757 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5758 return OMX_ErrorNone;
5759 }
5760 pending_output_buffers++;
5761
5762 // set from allocate_output_headers
5763 ptr_respbuffer = (struct vdpp_output_frameinfo*)buffer->pOutputPortPrivate;
5764 if (ptr_respbuffer)
5765 {
5766 ptr_outputbuffer = (struct vdpp_bufferpayload*)ptr_respbuffer->client_data;
5767 }
5768
5769 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL)
5770 {
5771 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
5772 buffer->nFilledLen = 0;
5773 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5774 pending_output_buffers--;
5775 return OMX_ErrorBadParameter;
5776 }
5777
5778 int rc = 0;
5779 struct v4l2_buffer buf;
5780 struct v4l2_plane plane[VIDEO_MAX_PLANES];
5781 int extra_idx = 0;
5782 memset( (void *)&buf, 0, sizeof(buf));
5783 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
5784
5785 buf.index = nPortIndex;
5786 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5787 buf.memory = V4L2_MEMORY_USERPTR;
5788 buf.field = V4L2_FIELD_ANY;
5789
5790 buf.length = drv_ctx.output_num_planes;
5791 plane[0].bytesused = drv_ctx.video_resolution_output.frame_width *
5792 drv_ctx.video_resolution_output.frame_height *
5793 drv_ctx.output_bytesperpixel[0];
5794 plane[0].length = paddedFrameWidth128(drv_ctx.video_resolution_output.frame_width) *
5795 drv_ctx.video_resolution_output.frame_height *
5796 drv_ctx.output_bytesperpixel[0];
5797
5798 plane[0].m.userptr = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
5799 plane[0].reserved[0] = 0;
5800 extra_idx = EXTRADATA_IDX(drv_ctx.output_num_planes);
5801 if ((extra_idx > 0) && (extra_idx < VIDEO_MAX_PLANES)) {
5802 plane[extra_idx].bytesused = drv_ctx.video_resolution_output.frame_width *
5803 drv_ctx.video_resolution_output.frame_height *
5804 drv_ctx.output_bytesperpixel[extra_idx];
5805 plane[extra_idx].length = paddedFrameWidth128(drv_ctx.video_resolution_output.frame_width) *
5806 drv_ctx.video_resolution_output.frame_height *
5807 drv_ctx.output_bytesperpixel[extra_idx];
5808 plane[extra_idx].m.userptr = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
5809 plane[extra_idx].reserved[0] = plane[0].reserved[0] + drv_ctx.video_resolution_output.stride * drv_ctx.video_resolution_output.scan_lines;// plane[0].length;
5810 } else if (extra_idx >= VIDEO_MAX_PLANES) {
5811 DEBUG_PRINT_ERROR("Extradata index higher than expected: %d\n", extra_idx);
5812 return OMX_ErrorBadParameter;
5813 }
5814 buf.m.planes = plane;
5815 // DEBUG_PRINT_LOW("omx_vdpp::fill_this_buffer_proxy: buffer->nFilledLen = %lu, plane[0].bytesused = %d plane[0].length = %d, \
5816 // plane[extra_idx].bytesused = %d, plane[extra_idx].reserved[0] = 0x%x\n", \
5817 // buffer->nFilledLen, plane[0].bytesused, plane[0].length, plane[extra_idx].bytesused, plane[extra_idx].reserved[0]);
5818 //
5819 //DEBUG_PRINT_LOW("omx_vdpp::fill_this_buffer_proxy 2 drv_ctx.ptr_outputbuffer[%d].bufferaddr = %p\n", nPortIndex,drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr);
5820 //DEBUG_PRINT_LOW("omx_vdpp::fill_this_buffer_proxy 2 drv_ctx.ptr_outputbuffer[%d].offset = %d", nPortIndex,drv_ctx.ptr_outputbuffer[nPortIndex].offset);
5821
5822 #ifdef STUB_VPU
5823
5824 #else
5825 rc = ioctl(drv_ctx.video_vpu_fd, VIDIOC_QBUF, &buf);
5826 if (rc) {
5827 DEBUG_PRINT_ERROR("Failed to qbuf to driver");
5828 return OMX_ErrorHardware;
5829 }
5830 #endif
5831
5832 output_qbuf_count++;
5833 DEBUG_PRINT_LOW("omx_vdpp::fill_this_buffer_proxy 3\n");
5834 #ifdef STUB_VPU
5835 {
5836 drv_ctx.etb_ftb_info.ftb_cnt++;
5837 m_index_q_ftb.insert_entry(p1,p2,nPortIndex);
5838 drv_ctx.etb_ftb_info.ftb_len = drv_ctx.op_buf.buffer_size;
5839 sem_post (&(drv_ctx.async_lock));
5840 DEBUG_PRINT_HIGH("omx_vdpp::fill_this_buffer_proxy 4 nPortIndex = %d, drv_ctx.etb_ftb_info.ftb_cnt = %d, drv_ctx.etb_ftb_info.ftb_len = %d\n",
5841 nPortIndex, drv_ctx.etb_ftb_info.ftb_cnt, drv_ctx.etb_ftb_info.ftb_len);
5842 }
5843 #endif
5844 return OMX_ErrorNone;
5845
5846 }
5847
5848 /* ======================================================================
5849 FUNCTION
5850 omx_vdpp::SetCallbacks
5851
5852 DESCRIPTION
5853 Set the callbacks.
5854
5855 PARAMETERS
5856 None.
5857
5858 RETURN VALUE
5859 OMX Error None if everything successful.
5860
5861 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)5862 OMX_ERRORTYPE omx_vdpp::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
5863 OMX_IN OMX_CALLBACKTYPE* callbacks,
5864 OMX_IN OMX_PTR appData)
5865 {
5866
5867 m_cb = *callbacks;
5868 DEBUG_PRINT_LOW(" Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
5869 m_cb.EventHandler,m_cb.FillBufferDone);
5870 m_app_data = appData;
5871 return OMX_ErrorNotImplemented;
5872 }
5873
5874 /* ======================================================================
5875 FUNCTION
5876 omx_vdpp::ComponentDeInit
5877
5878 DESCRIPTION
5879 Destroys the component and release memory allocated to the heap.
5880
5881 PARAMETERS
5882 <TBD>.
5883
5884 RETURN VALUE
5885 OMX Error None if everything successful.
5886
5887 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)5888 OMX_ERRORTYPE omx_vdpp::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
5889 {
5890 unsigned i = 0;
5891 DEBUG_PRINT_HIGH(" omx_vdpp::component_deinit");
5892 if (OMX_StateLoaded != m_state)
5893 {
5894 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\
5895 m_state);
5896 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
5897 }
5898 else
5899 {
5900 DEBUG_PRINT_HIGH(" Playback Ended - PASSED");
5901 }
5902
5903 /*Check if the output buffers have to be cleaned up*/
5904 if(m_out_mem_ptr)
5905 {
5906 DEBUG_PRINT_LOW("Freeing the Output Memory\n");
5907 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ )
5908 {
5909 free_output_buffer (&m_out_mem_ptr[i]);
5910 }
5911 }
5912
5913 /*Check if the input buffers have to be cleaned up*/
5914 if(m_inp_mem_ptr || m_inp_heap_ptr)
5915 {
5916 DEBUG_PRINT_LOW("Freeing the Input Memory\n");
5917 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ )
5918 {
5919 if (m_inp_mem_ptr)
5920 free_input_buffer (&m_inp_mem_ptr[i]);
5921 }
5922 }
5923 free_input_buffer_header();
5924 free_output_buffer_header();
5925
5926 // Reset counters in mesg queues
5927 m_ftb_q.m_size=0;
5928 m_cmd_q.m_size=0;
5929 m_etb_q.m_size=0;
5930 m_index_q_ftb.m_size=0;
5931 m_index_q_etb.m_size=0;
5932 m_ftb_q.m_read = m_ftb_q.m_write =0;
5933 m_cmd_q.m_read = m_cmd_q.m_write =0;
5934 m_etb_q.m_read = m_etb_q.m_write =0;
5935 m_index_q_ftb.m_read = m_index_q_ftb.m_write =0;
5936 m_index_q_etb.m_read = m_index_q_etb.m_write =0;
5937 #ifdef _ANDROID_
5938 if (m_debug_timestamp)
5939 {
5940 m_timestamp_list.reset_ts_list();
5941 }
5942 #endif
5943
5944 DEBUG_PRINT_HIGH(" Close the driver instance");
5945
5946 #ifdef INPUT_BUFFER_LOG
5947 if (inputBufferFile)
5948 close (inputBufferFile);
5949 #endif
5950 #ifdef OUTPUT_BUFFER_LOG
5951 if (outputBufferFile)
5952 close(outputBufferFile);
5953 #endif
5954 #ifdef OUTPUT_EXTRADATA_LOG
5955 if (outputExtradataFile)
5956 fclose (outputExtradataFile);
5957 #endif
5958
5959 DEBUG_PRINT_HIGH(" omx_vdpp::component_deinit() complete");
5960 return OMX_ErrorNone;
5961 }
5962 /* ======================================================================
5963 FUNCTION
5964 omx_vdpp::UseEGLImage
5965
5966 DESCRIPTION
5967 OMX Use EGL Image method implementation <TBD>.
5968
5969 PARAMETERS
5970 <TBD>.
5971
5972 RETURN VALUE
5973 Not Implemented error.
5974
5975 ========================================================================== */
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)5976 OMX_ERRORTYPE omx_vdpp::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
5977 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5978 OMX_IN OMX_U32 port,
5979 OMX_IN OMX_PTR appData,
5980 OMX_IN void* eglImage)
5981 {
5982 return OMX_ErrorNone;
5983 }
5984 /* ======================================================================
5985 FUNCTION
5986 omx_vdpp::ComponentRoleEnum
5987
5988 DESCRIPTION
5989 OMX Component Role Enum method implementation.
5990
5991 PARAMETERS
5992 <TBD>.
5993
5994 RETURN VALUE
5995 OMX Error None if everything is successful.
5996 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)5997 OMX_ERRORTYPE omx_vdpp::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
5998 OMX_OUT OMX_U8* role,
5999 OMX_IN OMX_U32 index)
6000 {
6001 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6002
6003 // no component role (TODO add it later once component role is determined)
6004 /*
6005 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.vidpp",OMX_MAX_STRINGNAME_SIZE))
6006 {
6007 if((0 == index) && role)
6008 {
6009 strlcpy((char *)role, "video.vidpp",OMX_MAX_STRINGNAME_SIZE);
6010 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
6011 }
6012 else
6013 {
6014 eRet = OMX_ErrorNoMore;
6015 }
6016 }
6017 */
6018 return eRet;
6019 }
6020
6021
6022
6023
6024 /* ======================================================================
6025 FUNCTION
6026 omx_vdpp::AllocateDone
6027
6028 DESCRIPTION
6029 Checks if entire buffer pool is allocated by IL Client or not.
6030 Need this to move to IDLE state.
6031
6032 PARAMETERS
6033 None.
6034
6035 RETURN VALUE
6036 true/false.
6037
6038 ========================================================================== */
allocate_done(void)6039 bool omx_vdpp::allocate_done(void)
6040 {
6041 bool bRet = false;
6042 bool bRet_In = false;
6043 bool bRet_Out = false;
6044
6045 //DEBUG_PRINT_LOW("omx_vdpp::allocate_done 1\n");
6046 bRet_In = allocate_input_done();
6047 bRet_Out = allocate_output_done();
6048
6049 if(bRet_In && bRet_Out)
6050 {
6051 bRet = true;
6052 //DEBUG_PRINT_LOW("omx_vdpp::allocate_done 2\n");
6053 }
6054 //DEBUG_PRINT_LOW("omx_vdpp::allocate_done 3\n");
6055 return bRet;
6056 }
6057 /* ======================================================================
6058 FUNCTION
6059 omx_vdpp::AllocateInputDone
6060
6061 DESCRIPTION
6062 Checks if I/P buffer pool is allocated by IL Client or not.
6063
6064 PARAMETERS
6065 None.
6066
6067 RETURN VALUE
6068 true/false.
6069
6070 ========================================================================== */
allocate_input_done(void)6071 bool omx_vdpp::allocate_input_done(void)
6072 {
6073 bool bRet = false;
6074 unsigned i=0;
6075 //DEBUG_PRINT_LOW("omx_vdpp::allocate_input_done 1\n");
6076 if (m_inp_mem_ptr == NULL)
6077 {
6078 //DEBUG_PRINT_LOW("omx_vdpp::allocate_input_done 2\n");
6079 return bRet;
6080 }
6081 if(m_inp_mem_ptr )
6082 {
6083 //DEBUG_PRINT_LOW("omx_vdpp::allocate_input_done 3\n");
6084 for(;i<drv_ctx.ip_buf.actualcount;i++)
6085 {
6086 if(BITMASK_ABSENT(&m_inp_bm_count,i))
6087 {
6088 break;
6089 }
6090 }
6091 }
6092 //DEBUG_PRINT_LOW("omx_vdpp::allocate_input_done 4 i = %d, drv_ctx.ip_buf.actualcount = %d\n", i, drv_ctx.ip_buf.actualcount);
6093 if(i == drv_ctx.ip_buf.actualcount)
6094 {
6095 //DEBUG_PRINT_LOW("omx_vdpp::allocate_input_done 5\n");
6096 bRet = true;
6097 //DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
6098 }
6099 if(i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled)
6100 {
6101 m_inp_bPopulated = OMX_TRUE;
6102 }
6103 return bRet;
6104 }
6105 /* ======================================================================
6106 FUNCTION
6107 omx_vdpp::AllocateOutputDone
6108
6109 DESCRIPTION
6110 Checks if entire O/P buffer pool is allocated by IL Client or not.
6111
6112 PARAMETERS
6113 None.
6114
6115 RETURN VALUE
6116 true/false.
6117
6118 ========================================================================== */
allocate_output_done(void)6119 bool omx_vdpp::allocate_output_done(void)
6120 {
6121 bool bRet = false;
6122 unsigned j=0;
6123
6124 if (m_out_mem_ptr == NULL)
6125 {
6126 return bRet;
6127 }
6128
6129 if (m_out_mem_ptr)
6130 {
6131 for(;j < drv_ctx.op_buf.actualcount;j++)
6132 {
6133 if(BITMASK_ABSENT(&m_out_bm_count,j))
6134 {
6135 break;
6136 }
6137 }
6138 }
6139
6140 if(j == drv_ctx.op_buf.actualcount)
6141 {
6142 bRet = true;
6143 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
6144 if(m_out_bEnabled)
6145 m_out_bPopulated = OMX_TRUE;
6146 }
6147
6148 return bRet;
6149 }
6150
6151 /* ======================================================================
6152 FUNCTION
6153 omx_vdpp::ReleaseDone
6154
6155 DESCRIPTION
6156 Checks if IL client has released all the buffers.
6157
6158 PARAMETERS
6159 None.
6160
6161 RETURN VALUE
6162 true/false
6163
6164 ========================================================================== */
release_done(void)6165 bool omx_vdpp::release_done(void)
6166 {
6167 bool bRet = false;
6168
6169 if(release_input_done())
6170 {
6171 if(release_output_done())
6172 {
6173 bRet = true;
6174 }
6175 }
6176 return bRet;
6177 }
6178
6179
6180 /* ======================================================================
6181 FUNCTION
6182 omx_vdpp::ReleaseOutputDone
6183
6184 DESCRIPTION
6185 Checks if IL client has released all the buffers.
6186
6187 PARAMETERS
6188 None.
6189
6190 RETURN VALUE
6191 true/false
6192
6193 ========================================================================== */
release_output_done(void)6194 bool omx_vdpp::release_output_done(void)
6195 {
6196 bool bRet = false;
6197 unsigned i=0,j=0;
6198
6199 DEBUG_PRINT_LOW("omx_vdpp::release_output_done Value of m_out_mem_ptr %p",m_inp_mem_ptr);
6200 if(m_out_mem_ptr)
6201 {
6202 for(;j < drv_ctx.op_buf.actualcount ; j++)
6203 {
6204 if(BITMASK_PRESENT(&m_out_bm_count,j))
6205 {
6206 break;
6207 }
6208 }
6209 if(j == drv_ctx.op_buf.actualcount)
6210 {
6211 m_out_bm_count = 0;
6212 bRet = true;
6213 }
6214 }
6215 else
6216 {
6217 m_out_bm_count = 0;
6218 bRet = true;
6219 }
6220 return bRet;
6221 }
6222 /* ======================================================================
6223 FUNCTION
6224 omx_vdpp::ReleaseInputDone
6225
6226 DESCRIPTION
6227 Checks if IL client has released all the buffers.
6228
6229 PARAMETERS
6230 None.
6231
6232 RETURN VALUE
6233 true/false
6234
6235 ========================================================================== */
release_input_done(void)6236 bool omx_vdpp::release_input_done(void)
6237 {
6238 bool bRet = false;
6239 unsigned i=0,j=0;
6240
6241 DEBUG_PRINT_LOW("omx_vdpp::release_input_done Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
6242 if(m_inp_mem_ptr)
6243 {
6244 for(;j<drv_ctx.ip_buf.actualcount;j++)
6245 {
6246 if( BITMASK_PRESENT(&m_inp_bm_count,j))
6247 {
6248 break;
6249 }
6250 }
6251 if(j==drv_ctx.ip_buf.actualcount)
6252 {
6253 bRet = true;
6254 }
6255 }
6256 else
6257 {
6258 bRet = true;
6259 }
6260 return bRet;
6261 }
6262
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6263 OMX_ERRORTYPE omx_vdpp::fill_buffer_done(OMX_HANDLETYPE hComp,
6264 OMX_BUFFERHEADERTYPE * buffer)
6265 {
6266 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
6267 //DEBUG_PRINT_LOW(" fill_buffer_done 1 : bufhdr = %p, bufhdr->pBuffer = %p, buffer->nFilledLen = %lu",
6268 // buffer, buffer->pBuffer, buffer->nFilledLen);
6269
6270 if (!buffer || (buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount)
6271 {
6272 DEBUG_PRINT_ERROR(" [FBD] ERROR in ptr(%p)", buffer);
6273 return OMX_ErrorBadParameter;
6274 }
6275 else if (output_flush_progress)
6276 {
6277 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
6278 buffer->nFilledLen = 0;
6279 buffer->nTimeStamp = 0;
6280 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
6281 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6282 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
6283 }
6284
6285 DEBUG_PRINT_HIGH(" fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, buffer->nFilledLen = %lu, buffer->nFlags = 0x%x",
6286 buffer, buffer->pBuffer, buffer->nFilledLen, buffer->nFlags);
6287 pending_output_buffers --;
6288 output_dqbuf_count++;
6289 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
6290 {
6291 DEBUG_PRINT_HIGH(" Output EOS has been reached");
6292 if (!output_flush_progress)
6293 post_event((unsigned)NULL, (unsigned)NULL,
6294 OMX_COMPONENT_GENERATE_EOS_DONE);
6295
6296 if (psource_frame)
6297 {
6298 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
6299 psource_frame = NULL;
6300 }
6301 if (pdest_frame)
6302 {
6303 pdest_frame->nFilledLen = 0;
6304 m_input_free_q.insert_entry((unsigned) pdest_frame,(unsigned)NULL,
6305 (unsigned)NULL);
6306 pdest_frame = NULL;
6307 }
6308 }
6309
6310 //DEBUG_PRINT_LOW(" In fill Buffer done call address %p , buffer->nFilledLen = %lu",buffer, buffer->nFilledLen);
6311 #ifdef OUTPUT_BUFFER_LOG
6312 DEBUG_PRINT_LOW("omx_vdpp::fill_buffer_done 1.5, output_buffer_write_counter = %d", output_buffer_write_counter);
6313 if(outputBufferFile < 0)
6314 {
6315 DEBUG_PRINT_ERROR(" Failed to create outputBufferFile \n");
6316 }
6317 if (outputBufferFile && buffer->nFilledLen && (output_buffer_write_counter <= 10))
6318 {
6319 DEBUG_PRINT_LOW("omx_vdpp::fill_buffer_done 2");
6320 int buf_index = buffer - m_out_mem_ptr;
6321 int stride = drv_ctx.video_resolution_output.stride; //w
6322 int scanlines = drv_ctx.video_resolution_output.scan_lines; //h
6323 char *temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr; // mmap ION buffer addr
6324 unsigned i;
6325 int bytes_written = 0;
6326 for (i = 0; i < drv_ctx.video_resolution_output.frame_height; i++) {
6327 bytes_written = write(outputBufferFile, temp, drv_ctx.video_resolution_output.frame_width);
6328 temp += stride;
6329 }
6330 temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
6331 int stride_c = stride;
6332 for(i = 0; i < drv_ctx.video_resolution_output.frame_height/2; i++) {
6333 bytes_written += write(outputBufferFile, temp, drv_ctx.video_resolution_output.frame_width);
6334 temp += stride_c;
6335 }
6336 output_buffer_write_counter++;
6337
6338 if(output_buffer_write_counter > 10)
6339 {
6340 close(outputBufferFile);
6341 DEBUG_PRINT_LOW("omx_vdpp::fill_buffer_done 2.9 close ");
6342 }
6343 }
6344 #endif
6345 //DEBUG_PRINT_LOW("omx_vdpp::fill_buffer_done 3");
6346
6347 if (m_cb.FillBufferDone)
6348 {
6349 //DEBUG_PRINT_LOW("omx_vdpp::fill_buffer_done 4");
6350
6351 if (buffer->nFlags & OMX_BUFFERFLAG_EOS){
6352 prev_ts = LLONG_MAX;
6353 rst_prev_ts = true;
6354 }
6355
6356 DEBUG_PRINT_HIGH("omx_vdpp::fill_buffer_done 5 ");
6357 m_cb.FillBufferDone (hComp,m_app_data, buffer);
6358 DEBUG_PRINT_HIGH(" After Fill Buffer Done callback");
6359
6360 }
6361 else
6362 {
6363 return OMX_ErrorBadParameter;
6364 }
6365
6366 return OMX_ErrorNone;
6367 }
6368
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)6369 OMX_ERRORTYPE omx_vdpp::empty_buffer_done(OMX_HANDLETYPE hComp,
6370 OMX_BUFFERHEADERTYPE* buffer)
6371 {
6372 if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount))
6373 {
6374 DEBUG_PRINT_ERROR(" empty_buffer_done: ERROR bufhdr = %p", buffer);
6375 return OMX_ErrorBadParameter;
6376 }
6377
6378 DEBUG_PRINT_LOW(" empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
6379 buffer, buffer->pBuffer);
6380 pending_input_buffers--;
6381 input_dqbuf_count++;
6382
6383 if(m_cb.EmptyBufferDone)
6384 {
6385 buffer->nFilledLen = 0;
6386 if (input_use_buffer == true){
6387 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
6388 }
6389 DEBUG_PRINT_HIGH("!!! empty_buffer_done before callback: buffer = %p\n", buffer);
6390 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
6391 }
6392 return OMX_ErrorNone;
6393 }
6394
async_message_process(void * context,void * message)6395 int omx_vdpp::async_message_process (void *context, void* message)
6396 {
6397 omx_vdpp* omx = NULL;
6398 struct vdpp_msginfo *vdpp_msg = NULL;
6399 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
6400 struct v4l2_buffer *v4l2_buf_ptr = NULL;
6401 struct vdpp_output_frameinfo *output_respbuf = NULL;
6402 int rc=1;
6403 //DEBUG_PRINT_LOW("async_message_process 0\n");
6404 if (context == NULL || message == NULL)
6405 {
6406 DEBUG_PRINT_ERROR(" FATAL ERROR in omx_vdpp::async_message_process NULL Check");
6407 return -1;
6408 }
6409 //DEBUG_PRINT_LOW("async_message_process 1\n");
6410 vdpp_msg = (struct vdpp_msginfo *)message;
6411
6412 omx = reinterpret_cast<omx_vdpp*>(context);
6413
6414 switch (vdpp_msg->msgcode)
6415 {
6416
6417 case VDPP_MSG_EVT_HW_ERROR:
6418 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6419 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6420 break;
6421
6422 case VDPP_MSG_RESP_START_DONE:
6423 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6424 OMX_COMPONENT_GENERATE_START_DONE);
6425 break;
6426
6427 case VDPP_MSG_RESP_STOP_DONE:
6428 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6429 OMX_COMPONENT_GENERATE_STOP_DONE);
6430 break;
6431
6432 case VDPP_MSG_RESP_RESUME_DONE:
6433 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6434 OMX_COMPONENT_GENERATE_RESUME_DONE);
6435 break;
6436
6437 case VDPP_MSG_RESP_PAUSE_DONE:
6438 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6439 OMX_COMPONENT_GENERATE_PAUSE_DONE);
6440 break;
6441
6442 case VDPP_MSG_RESP_FLUSH_INPUT_DONE:
6443 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6444 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
6445 break;
6446 case VDPP_MSG_RESP_FLUSH_OUTPUT_DONE:
6447 omx->post_event ((unsigned)NULL, vdpp_msg->status_code,\
6448 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
6449 break;
6450 case VDPP_MSG_RESP_INPUT_FLUSHED:
6451 case VDPP_MSG_RESP_INPUT_BUFFER_DONE:
6452 //DEBUG_PRINT_LOW(" VDPP_MSG_RESP_INPUT_BUFFER_DONE 0");
6453 v4l2_buf_ptr = (v4l2_buffer*)vdpp_msg->msgdata.input_frame_clientdata;
6454 // Use v4l2_buf_ptr->index returned by VPU V4L2 driver to index into
6455 // m_inp_mem_ptr. v4l2 driver right now returns the same index used in QBUF
6456 // In the future the returned ION handle could be used in empty_buffer_done.
6457 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index;
6458 DEBUG_PRINT_LOW(" VDPP_MSG_RESP_INPUT_BUFFER_DONE 1 v4l2_buf_ptr->index = %d", v4l2_buf_ptr->index);
6459 if (omxhdr == NULL ||
6460 ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) )
6461 {
6462 //DEBUG_PRINT_ERROR(" VDPP_MSG_RESP_INPUT_BUFFER_DONE 2");
6463 omxhdr = NULL;
6464 vdpp_msg->status_code = VDPP_S_EFATAL;
6465 }
6466 //DEBUG_PRINT_LOW(" VDPP_MSG_RESP_INPUT_BUFFER_DONE 3");
6467 // No need to update the omxhdr->nFilledLen using the plane[0].len + plane[1].len here.
6468 // based on OMX 3.1.2.9.2, nFilledLen = 0 if input buffer is completely consumed in ebd.
6469 // also refer to ebd code
6470 omx->post_event ((unsigned int)omxhdr,vdpp_msg->status_code,
6471 OMX_COMPONENT_GENERATE_EBD);
6472 break;
6473 case VDPP_MSG_RESP_OUTPUT_FLUSHED:
6474 case VDPP_MSG_RESP_OUTPUT_BUFFER_DONE:
6475
6476 v4l2_buf_ptr = (v4l2_buffer*)vdpp_msg->msgdata.output_frame.client_data;
6477 omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index;
6478 DEBUG_PRINT_LOW("VDPP_MSG_RESP_OUTPUT_BUFFER_DONE 1 v4l2_buf_ptr->index = %d\n", v4l2_buf_ptr->index);
6479
6480 if (omxhdr && omxhdr->pOutputPortPrivate &&
6481 ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) &&
6482 (((struct vdpp_output_frameinfo *)omxhdr->pOutputPortPrivate
6483 - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount))
6484 {
6485 if ( vdpp_msg->msgdata.output_frame.len <= omxhdr->nAllocLen)
6486 {
6487 //DEBUG_PRINT_LOW("VDPP_MSG_RESP_OUTPUT_BUFFER_DONE 2, vdpp_msg->msgdata.output_frame.len = %d, omxhdr->nAllocLen = %ld\n", vdpp_msg->msgdata.output_frame.len, omxhdr->nAllocLen);
6488 omxhdr->nFilledLen = vdpp_msg->msgdata.output_frame.len;
6489 omxhdr->nOffset = vdpp_msg->msgdata.output_frame.offset;
6490 omxhdr->nTimeStamp = vdpp_msg->msgdata.output_frame.time_stamp;
6491 omxhdr->nFlags = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nFlags;
6492
6493 //DEBUG_PRINT_LOW("VDPP_MSG_RESP_OUTPUT_BUFFER_DONE 2.5 omxhdr->nFilledLen = %ld\n", omxhdr->nFilledLen);
6494 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)
6495 {
6496 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
6497 //rc = -1;
6498 }
6499
6500 // use mmaped ION buffer address
6501 vdpp_msg->msgdata.output_frame.bufferaddr =
6502 omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
6503
6504 output_respbuf = (struct vdpp_output_frameinfo *)\
6505 omxhdr->pOutputPortPrivate;
6506 output_respbuf->len = vdpp_msg->msgdata.output_frame.len;
6507 output_respbuf->offset = vdpp_msg->msgdata.output_frame.offset;
6508
6509 if (omx->output_use_buffer)
6510 memcpy ( omxhdr->pBuffer, (void *)
6511 ((unsigned long)vdpp_msg->msgdata.output_frame.bufferaddr +
6512 (unsigned long)vdpp_msg->msgdata.output_frame.offset),
6513 vdpp_msg->msgdata.output_frame.len);
6514 }
6515 else
6516 omxhdr->nFilledLen = 0;
6517
6518 //DEBUG_PRINT_HIGH("VDPP_MSG_RESP_OUTPUT_BUFFER_DONE 4 omxhdr->nFilledLen = %ld, OMX_COMPONENT_GENERATE_FBD = %d\n", omxhdr->nFilledLen, OMX_COMPONENT_GENERATE_FBD);
6519
6520 omx->post_event ((unsigned int)omxhdr, vdpp_msg->status_code,
6521 OMX_COMPONENT_GENERATE_FBD);
6522 }
6523 else if (vdpp_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS)
6524 omx->post_event ((unsigned int)NULL, vdpp_msg->status_code,
6525 OMX_COMPONENT_GENERATE_EOS_DONE);
6526 else
6527 omx->post_event ((unsigned int)NULL, vdpp_msg->status_code,
6528 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6529 break;
6530 case VDPP_MSG_EVT_CONFIG_CHANGED:
6531 DEBUG_PRINT_HIGH(" Port settings changed");
6532 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
6533 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6534 break;
6535 case VDPP_MSG_EVT_ACTIVE_REGION_DETECTION_STATUS:
6536 {
6537 struct v4l2_rect * p_ar_result = &(vdpp_msg->msgdata.ar_result);
6538 DEBUG_PRINT_HIGH(" Active Region Detection Status");
6539 omx->post_event ((unsigned int)p_ar_result,
6540 vdpp_msg->status_code,
6541 OMX_COMPONENT_GENERATE_ACTIVE_REGION_DETECTION_STATUS);
6542 break;
6543 }
6544 default:
6545 break;
6546 }
6547
6548
6549 return rc;
6550 }
6551
6552 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)6553 bool omx_vdpp::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
6554 OMX_U32 alignment)
6555 {
6556 struct pmem_allocation allocation;
6557 allocation.size = buffer_size;
6558 allocation.align = clip2(alignment);
6559 if (allocation.align < 4096)
6560 {
6561 allocation.align = 4096;
6562 }
6563 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0)
6564 {
6565 DEBUG_PRINT_ERROR(" Aligment(%u) failed with pmem driver Sz(%lu)",
6566 allocation.align, allocation.size);
6567 return false;
6568 }
6569 return true;
6570 }
6571 #endif
6572 #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)6573 int omx_vdpp::alloc_map_ion_memory(OMX_U32 buffer_size,
6574 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
6575 struct ion_fd_data *fd_data, int flag)
6576 {
6577 int fd = -EINVAL;
6578 int rc = -EINVAL;
6579 int ion_dev_flag;
6580 struct vdpp_ion ion_buf_info;
6581 if (!alloc_data || buffer_size <= 0 || !fd_data) {
6582 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory\n");
6583 return -EINVAL;
6584 }
6585 ion_dev_flag = (O_RDONLY | O_DSYNC);
6586 fd = open (MEM_DEVICE, ion_dev_flag);
6587 if (fd < 0) {
6588 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d\n", fd);
6589 return fd;
6590 }
6591
6592 alloc_data->len = buffer_size;
6593
6594 // the following settings are from vpu_test.c
6595 alloc_data->align = 16;
6596 alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
6597 alloc_data->flags = 0;
6598
6599 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
6600 if (rc || !alloc_data->handle) {
6601 DEBUG_PRINT_ERROR(" ION ALLOC memory failed ");
6602 alloc_data->handle = NULL;
6603 close(fd);
6604 fd = -ENOMEM;
6605 return fd;
6606 }
6607 fd_data->handle = alloc_data->handle;
6608 rc = ioctl(fd,ION_IOC_MAP,fd_data);
6609 if (rc) {
6610 DEBUG_PRINT_ERROR(" ION MAP failed ");
6611 ion_buf_info.ion_alloc_data = *alloc_data;
6612 ion_buf_info.ion_device_fd = fd;
6613 ion_buf_info.fd_ion_data = *fd_data;
6614 free_ion_memory(&ion_buf_info);
6615 fd_data->fd =-1;
6616 close(fd);
6617 fd = -ENOMEM;
6618 }
6619
6620 return fd;
6621 }
6622
free_ion_memory(struct vdpp_ion * buf_ion_info)6623 void omx_vdpp::free_ion_memory(struct vdpp_ion *buf_ion_info) {
6624
6625 if(!buf_ion_info) {
6626 DEBUG_PRINT_ERROR(" ION: free called with invalid fd/allocdata");
6627 return;
6628 }
6629 if(ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
6630 &buf_ion_info->ion_alloc_data.handle)) {
6631 DEBUG_PRINT_ERROR(" ION: free failed" );
6632 }
6633 close(buf_ion_info->ion_device_fd);
6634 buf_ion_info->ion_device_fd = -1;
6635 buf_ion_info->ion_alloc_data.handle = NULL;
6636 buf_ion_info->fd_ion_data.fd = -1;
6637 }
6638 #endif
free_output_buffer_header()6639 void omx_vdpp::free_output_buffer_header()
6640 {
6641 DEBUG_PRINT_HIGH(" ALL output buffers are freed/released");
6642 output_use_buffer = false;
6643 ouput_egl_buffers = false;
6644
6645 if (m_out_mem_ptr)
6646 {
6647 free (m_out_mem_ptr);
6648 m_out_mem_ptr = NULL;
6649 }
6650
6651 if(m_platform_list)
6652 {
6653 free(m_platform_list);
6654 m_platform_list = NULL;
6655 }
6656
6657 if (drv_ctx.ptr_respbuffer)
6658 {
6659 free (drv_ctx.ptr_respbuffer);
6660 drv_ctx.ptr_respbuffer = NULL;
6661 }
6662 if (drv_ctx.ptr_outputbuffer)
6663 {
6664 free (drv_ctx.ptr_outputbuffer);
6665 drv_ctx.ptr_outputbuffer = NULL;
6666 }
6667 #ifdef USE_ION
6668 if (drv_ctx.op_buf_ion_info) {
6669 DEBUG_PRINT_LOW(" Free o/p ion context");
6670 free(drv_ctx.op_buf_ion_info);
6671 drv_ctx.op_buf_ion_info = NULL;
6672 }
6673 #endif
6674 }
6675
free_input_buffer_header()6676 void omx_vdpp::free_input_buffer_header()
6677 {
6678 input_use_buffer = false;
6679
6680 if (m_inp_heap_ptr)
6681 {
6682 DEBUG_PRINT_LOW(" Free input Heap Pointer");
6683 free (m_inp_heap_ptr);
6684 m_inp_heap_ptr = NULL;
6685 }
6686
6687 if (m_phdr_pmem_ptr)
6688 {
6689 DEBUG_PRINT_LOW(" Free input pmem header Pointer");
6690 free (m_phdr_pmem_ptr);
6691 m_phdr_pmem_ptr = NULL;
6692 }
6693
6694 if (m_inp_mem_ptr)
6695 {
6696 DEBUG_PRINT_LOW(" Free input pmem Pointer area");
6697 free (m_inp_mem_ptr);
6698 m_inp_mem_ptr = NULL;
6699 }
6700
6701 if (drv_ctx.ptr_inputbuffer)
6702 {
6703 DEBUG_PRINT_LOW(" Free Driver Context pointer");
6704 free (drv_ctx.ptr_inputbuffer);
6705 drv_ctx.ptr_inputbuffer = NULL;
6706 }
6707 #ifdef USE_ION
6708 if (drv_ctx.ip_buf_ion_info) {
6709 DEBUG_PRINT_LOW(" Free ion context");
6710 free(drv_ctx.ip_buf_ion_info);
6711 drv_ctx.ip_buf_ion_info = NULL;
6712 }
6713 #endif
6714 }
6715
stream_off(OMX_U32 port)6716 int omx_vdpp::stream_off(OMX_U32 port)
6717 {
6718 enum v4l2_buf_type btype;
6719 int rc = 0;
6720 enum v4l2_ports v4l2_port = OUTPUT_PORT;
6721
6722 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6723 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6724 v4l2_port = OUTPUT_PORT;
6725 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6726 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6727 v4l2_port = CAPTURE_PORT;
6728 } else if (port == OMX_ALL) {
6729 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
6730 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
6731
6732 if (!rc_input)
6733 return rc_input;
6734 else
6735 return rc_output;
6736 }
6737
6738 if (!streaming[v4l2_port]) {
6739 // already streamed off, warn and move on
6740 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
6741 " which is already streamed off", v4l2_port);
6742 return 0;
6743 }
6744
6745 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
6746 #ifndef STUB_VPU
6747 rc = ioctl(drv_ctx.video_vpu_fd, VIDIOC_STREAMOFF, &btype);
6748 if (rc) {
6749 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port \n", v4l2_port);
6750 } else {
6751 streaming[v4l2_port] = false;
6752 }
6753 #endif
6754
6755 return rc;
6756 }
6757
6758 // return buffer_prop->actualcount and buffer_prop->buffer_size
6759 // based on ip/op format
6760 #ifdef STUB_VPU
get_buffer_req(vdpp_allocatorproperty * buffer_prop)6761 OMX_ERRORTYPE omx_vdpp::get_buffer_req(vdpp_allocatorproperty *buffer_prop)
6762 {
6763 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6764 struct v4l2_requestbuffers bufreq;
6765 unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
6766 struct v4l2_format fmt;
6767
6768 int ret = 0;
6769
6770 DEBUG_PRINT_HIGH("omx_vdpp::get_buffer_req GetBufReq IN: ActCnt(%d) Size(%d)",
6771 buffer_prop->actualcount, buffer_prop->buffer_size);
6772
6773 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT){
6774
6775 bufreq.count = VP_INPUT_BUFFER_COUNT_INTERLACE;
6776 }else if (buffer_prop->buffer_type == VDPP_BUFFER_TYPE_OUTPUT){
6777
6778 bufreq.count = VP_OUTPUT_BUFFER_COUNT;
6779 }else
6780 {
6781 DEBUG_PRINT_HIGH("omx_vdpp:: wrong buffer type");
6782 }
6783
6784 {
6785 buffer_prop->actualcount = bufreq.count;
6786 buffer_prop->mincount = bufreq.count;
6787 DEBUG_PRINT_HIGH("Count = %d \n ",bufreq.count);
6788 }
6789
6790 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)",
6791 buffer_prop->actualcount, buffer_prop->buffer_size);
6792 {
6793 buffer_prop->buffer_size = drv_ctx.video_resolution_input.frame_height *
6794 paddedFrameWidth128(drv_ctx.video_resolution_input.frame_width) *
6795 3 / 2; // hardcoded size for stub NV12
6796 }
6797 buf_size = buffer_prop->buffer_size;
6798
6799 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
6800 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)",
6801 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size);
6802 if (in_reconfig) // BufReq will be set to driver when port is disabled
6803 buffer_prop->buffer_size = buf_size;
6804 else if (buf_size != buffer_prop->buffer_size)
6805 {
6806 buffer_prop->buffer_size = buf_size;
6807 eRet = set_buffer_req(buffer_prop);
6808 }
6809 //}
6810 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)",
6811 buffer_prop->actualcount, buffer_prop->buffer_size);
6812 return eRet;
6813 }
6814
6815 // set buffer_prop->actualcount through VIDIOC_REQBUFS
set_buffer_req(vdpp_allocatorproperty * buffer_prop)6816 OMX_ERRORTYPE omx_vdpp::set_buffer_req(vdpp_allocatorproperty *buffer_prop)
6817 {
6818 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6819 unsigned buf_size = 0;
6820 struct v4l2_format fmt;
6821 struct v4l2_requestbuffers bufreq;
6822 int ret;
6823 DEBUG_PRINT_HIGH("omx_vdpp::set_buffer_req SetBufReq IN: ActCnt(%d) Size(%d)",
6824 buffer_prop->actualcount, buffer_prop->buffer_size);
6825 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
6826 if (buf_size != buffer_prop->buffer_size)
6827 {
6828 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
6829 buffer_prop->buffer_size, buf_size);
6830 eRet = OMX_ErrorBadParameter;
6831 }
6832
6833 return eRet;
6834 }
6835 #else
6836 // call VIDIOC_REQBUFS to set the initial number of buffers that app wants to
6837 // use in streaming
6838 // return buffer_prop->buffer_size and ip/op resolution based on ip/op format
get_buffer_req(vdpp_allocatorproperty * buffer_prop)6839 OMX_ERRORTYPE omx_vdpp::get_buffer_req(vdpp_allocatorproperty *buffer_prop)
6840 {
6841 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6842 struct v4l2_requestbuffers bufreq;
6843 unsigned int buf_size = 0, extra_data_size = 0, client_extra_data_size = 0;
6844 struct v4l2_format fmt;
6845 int ret = 0;
6846
6847 memset((void *)&fmt, 0, sizeof(v4l2_format));
6848 memset((void *)&bufreq, 0, sizeof(v4l2_requestbuffers));
6849 DEBUG_PRINT_HIGH("GetBufReq IN: ActCnt(%d) Size(%d) buffer_prop->buffer_type (%d), streaming[OUTPUT_PORT] (%d), streaming[CAPTURE_PORT] (%d)",
6850 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type, streaming[OUTPUT_PORT], streaming[CAPTURE_PORT]);
6851 bufreq.memory = V4L2_MEMORY_USERPTR;
6852 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT){
6853 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6854 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6855 fmt.fmt.pix_mp.pixelformat = output_capability;
6856 bufreq.count = VP_INPUT_BUFFER_COUNT_INTERLACE;
6857 }else if (buffer_prop->buffer_type == VDPP_BUFFER_TYPE_OUTPUT){
6858 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6859 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6860 fmt.fmt.pix_mp.pixelformat = capture_capability;
6861 bufreq.count = VP_OUTPUT_BUFFER_COUNT;
6862 }else {eRet = OMX_ErrorBadParameter;}
6863 if(eRet==OMX_ErrorNone){
6864 ret = ioctl(drv_ctx.video_vpu_fd,VIDIOC_REQBUFS, &bufreq);
6865 }
6866 if(ret)
6867 {
6868 DEBUG_PRINT_ERROR("GetBufReq Requesting buffer requirements failed 1");
6869 eRet = OMX_ErrorInsufficientResources;
6870 return eRet;
6871 }
6872 else
6873 {
6874 buffer_prop->actualcount = bufreq.count;
6875 buffer_prop->mincount = bufreq.count;
6876 DEBUG_PRINT_HIGH("Count = %d \n ",bufreq.count);
6877 }
6878 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d), buffer_prop->buffer_type(%d) fmt.fmt.pix_mp.pixelformat (0x%08x)",
6879 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type, fmt.fmt.pix_mp.pixelformat);
6880
6881 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT)
6882 {
6883 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_input.frame_height;
6884 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_input.frame_width;
6885 if (V4L2_FIELD_NONE == drv_ctx.interlace)
6886 {
6887 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
6888 }
6889 else
6890 {
6891 fmt.fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
6892 }
6893
6894 }
6895 else
6896 {
6897 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_output.frame_height;
6898 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_output.frame_width;
6899 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
6900 }
6901
6902 //ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_G_FMT, &fmt);
6903 // S_FMT is always called before get_buffer_req
6904 // we should be able to use G_FMT to get fmt info.
6905 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_TRY_FMT, &fmt);
6906 //ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_G_FMT, &fmt);
6907
6908 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT)
6909 {
6910 drv_ctx.input_num_planes = fmt.fmt.pix_mp.num_planes;
6911 drv_ctx.video_resolution_input.frame_height = fmt.fmt.pix_mp.height;
6912 drv_ctx.video_resolution_input.frame_width = fmt.fmt.pix_mp.width;
6913 DEBUG_PRINT_HIGH("GetBufReq drv_ctx.video_resolution_input.frame_height = %d, drv_ctx.video_resolution_input.frame_width = %d ",
6914 drv_ctx.video_resolution_input.frame_height, drv_ctx.video_resolution_input.frame_width);
6915 }
6916 else
6917 {
6918 drv_ctx.output_num_planes = fmt.fmt.pix_mp.num_planes;
6919 drv_ctx.video_resolution_output.frame_height = fmt.fmt.pix_mp.height;
6920 drv_ctx.video_resolution_output.frame_width = fmt.fmt.pix_mp.width;
6921 DEBUG_PRINT_HIGH("GetBufReq drv_ctx.video_resolution_output.frame_height = %d, drv_ctx.video_resolution_output.frame_width = %d ",
6922 drv_ctx.video_resolution_output.frame_height, drv_ctx.video_resolution_output.frame_width);
6923 }
6924
6925 buffer_prop->frame_size = paddedFrameWidth32(fmt.fmt.pix_mp.height) *
6926 paddedFrameWidth128(fmt.fmt.pix_mp.width) *
6927 3 / 2;
6928 DEBUG_PRINT_HIGH("GetBufReq fmt.fmt.pix_mp.num_planes = %d, fmt.fmt.pix_mp.height = %d, fmt.fmt.pix_mp.width = %d, buffer_prop->frame_size = %d \n",
6929 fmt.fmt.pix_mp.num_planes, fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width, buffer_prop->frame_size);
6930
6931
6932 if(ret)
6933 {
6934 DEBUG_PRINT_ERROR("GetBufReq Requesting buffer requirements failed 2");
6935 eRet = OMX_ErrorInsufficientResources;
6936 }
6937 else
6938 {
6939 int extra_idx = 0;
6940 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
6941 buf_size = buffer_prop->buffer_size;
6942 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT)
6943 {
6944 extra_idx = EXTRADATA_IDX(drv_ctx.input_num_planes);
6945 }
6946 else
6947 {
6948 extra_idx = EXTRADATA_IDX(drv_ctx.output_num_planes);
6949 }
6950
6951 if ((extra_idx > 0) && (extra_idx < VIDEO_MAX_PLANES)) {
6952 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
6953 DEBUG_PRINT_HIGH("omx_vdpp::get_buffer_req extra_data_size: %d\n", extra_data_size);
6954 } else if (extra_idx >= VIDEO_MAX_PLANES) {
6955 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d\n", extra_idx);
6956 return OMX_ErrorBadParameter;
6957 }
6958 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6959 {
6960 DEBUG_PRINT_HIGH("Frame info extra data enabled!");
6961 client_extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
6962 }
6963 if (client_extradata & OMX_INTERLACE_EXTRADATA)
6964 {
6965 DEBUG_PRINT_HIGH("Interlace extra data enabled!");
6966 client_extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE;
6967 }
6968 if (client_extradata & OMX_PORTDEF_EXTRADATA)
6969 {
6970 client_extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE;
6971 DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d\n",
6972 client_extra_data_size);
6973 }
6974 if (client_extra_data_size)
6975 {
6976 client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
6977 buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
6978 }
6979 // update buffer_prop->buffer_size to include plane 1 buffer size
6980 // so only 1 ION buffer will be allocated for each input/output buffer
6981 if (extra_data_size > 0)
6982 {
6983 buf_size += extra_data_size;
6984 }
6985
6986 drv_ctx.extradata_info.size = buffer_prop->actualcount * extra_data_size;
6987 drv_ctx.extradata_info.count = buffer_prop->actualcount;
6988 drv_ctx.extradata_info.buffer_size = extra_data_size;
6989 buf_size += client_extra_data_size; // client_extra_data_size defaults to 0
6990 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
6991 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)",
6992 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size);
6993 if (in_reconfig) // BufReq will be set to driver when port is disabled
6994 buffer_prop->buffer_size = buf_size;
6995 else if (buf_size != buffer_prop->buffer_size)
6996 {
6997 buffer_prop->buffer_size = buf_size;
6998 eRet = set_buffer_req(buffer_prop);
6999 }
7000 }
7001 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d) buffer_prop->buffer_type(%d)",
7002 buffer_prop->actualcount, buffer_prop->buffer_size, buffer_prop->buffer_type);
7003 return eRet;
7004 }
7005
7006 // set buffer_prop->actualcount through VIDIOC_REQBUFS
set_buffer_req(vdpp_allocatorproperty * buffer_prop)7007 OMX_ERRORTYPE omx_vdpp::set_buffer_req(vdpp_allocatorproperty *buffer_prop)
7008 {
7009 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7010 unsigned buf_size = 0;
7011 unsigned i = 0;
7012 struct v4l2_format fmt;
7013 struct v4l2_requestbuffers bufreq;
7014 int ret;
7015 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)",
7016 buffer_prop->actualcount, buffer_prop->buffer_size);
7017 memset((void *)&fmt, 0, sizeof(v4l2_format));
7018 memset((void *)&bufreq, 0, sizeof(v4l2_requestbuffers));
7019 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7020 if (buf_size != buffer_prop->buffer_size)
7021 {
7022 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
7023 buffer_prop->buffer_size, buf_size);
7024 eRet = OMX_ErrorBadParameter;
7025 }
7026 else
7027 {
7028
7029 if (buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT){
7030 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7031 fmt.fmt.pix_mp.pixelformat = output_capability;
7032
7033 if (V4L2_FIELD_NONE == drv_ctx.interlace)
7034 {
7035 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
7036 }
7037 else
7038 {
7039 fmt.fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
7040 }
7041 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_input.frame_height;
7042 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_input.frame_width;
7043
7044 setFormatParams(output_capability, drv_ctx.input_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
7045 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
7046 {
7047 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width *
7048 drv_ctx.input_bytesperpixel[i] *
7049 fmt.fmt.pix_mp.height);
7050 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.input_bytesperpixel[0]); // both plane have the same plane stride
7051 }
7052 } else if (buffer_prop->buffer_type == VDPP_BUFFER_TYPE_OUTPUT) {
7053 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7054 fmt.fmt.pix_mp.pixelformat = capture_capability;
7055 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
7056 fmt.fmt.pix_mp.height = drv_ctx.video_resolution_output.frame_height;
7057 fmt.fmt.pix_mp.width = drv_ctx.video_resolution_output.frame_width;
7058
7059 setFormatParams(capture_capability, drv_ctx.output_bytesperpixel, &(fmt.fmt.pix_mp.num_planes));
7060 for( i=0; i<fmt.fmt.pix_mp.num_planes; i++ )
7061 {
7062 fmt.fmt.pix_mp.plane_fmt[i].sizeimage = paddedFrameWidth128(fmt.fmt.pix_mp.width *
7063 drv_ctx.output_bytesperpixel[i] *
7064 fmt.fmt.pix_mp.height);
7065 fmt.fmt.pix_mp.plane_fmt[i].bytesperline = paddedFrameWidth128(fmt.fmt.pix_mp.width * drv_ctx.output_bytesperpixel[0]);
7066 DEBUG_PRINT_HIGH("set_buffer_req fmt.fmt.pix_mp.plane_fmt[%d].sizeimage = %d \n ", i, fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
7067 }
7068 } else {eRet = OMX_ErrorBadParameter;}
7069
7070 ret = ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_FMT, &fmt);
7071 if (ret)
7072 {
7073 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
7074 eRet = OMX_ErrorInsufficientResources;
7075 }
7076 else
7077 {
7078 DEBUG_PRINT_HIGH("set_buffer_req drv_ctx.interlace = %d", drv_ctx.interlace);
7079 }
7080
7081 bufreq.memory = V4L2_MEMORY_USERPTR;
7082 bufreq.count = buffer_prop->actualcount;
7083 if(buffer_prop->buffer_type == VDPP_BUFFER_TYPE_INPUT) {
7084 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7085 } else if (buffer_prop->buffer_type == VDPP_BUFFER_TYPE_OUTPUT) {
7086 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7087 } else {eRet = OMX_ErrorBadParameter;}
7088
7089 if (eRet==OMX_ErrorNone) {
7090 ret = ioctl(drv_ctx.video_vpu_fd,VIDIOC_REQBUFS, &bufreq);
7091 }
7092
7093 if (ret)
7094 {
7095 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
7096 eRet = OMX_ErrorInsufficientResources;
7097 } else if (bufreq.count < buffer_prop->actualcount) {
7098 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
7099 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
7100 buffer_prop->actualcount, bufreq.count);
7101 eRet = OMX_ErrorInsufficientResources;
7102 }
7103
7104 }
7105 return eRet;
7106 }
7107 #endif
7108
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)7109 OMX_ERRORTYPE omx_vdpp::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
7110 {
7111 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7112 if (!portDefn)
7113 {
7114 return OMX_ErrorBadParameter;
7115 }
7116 DEBUG_PRINT_LOW("omx_vdpp::update_portdef\n");
7117 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
7118 portDefn->nSize = sizeof(portDefn);
7119 portDefn->eDomain = OMX_PortDomainVideo;
7120 if (drv_ctx.frame_rate.fps_denominator > 0)
7121 portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator /
7122 drv_ctx.frame_rate.fps_denominator;
7123 else {
7124 DEBUG_PRINT_ERROR("Error: Divide by zero \n");
7125 return OMX_ErrorBadParameter;
7126 }
7127 if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex)
7128 {
7129 portDefn->eDir = OMX_DirInput;
7130 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
7131 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
7132 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
7133 portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;//OMX_COLOR_FormatYUV420Planar;//OMX_COLOR_FormatUnused;
7134 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7135 portDefn->bEnabled = m_inp_bEnabled;
7136 portDefn->bPopulated = m_inp_bPopulated;
7137 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution_input.frame_height;
7138 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution_input.frame_width;
7139 portDefn->format.video.nStride = drv_ctx.video_resolution_input.stride;
7140 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution_input.scan_lines;
7141 }
7142 else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex)
7143 {
7144 portDefn->eDir = OMX_DirOutput;
7145 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
7146 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
7147 portDefn->nBufferSize = drv_ctx.op_buf.buffer_size;
7148 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7149 portDefn->bEnabled = m_out_bEnabled;
7150 portDefn->bPopulated = m_out_bPopulated;
7151 portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
7152
7153 // video_resolution_output.frame_height is retrieved from get_bufreq
7154 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution_output.frame_height;
7155 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution_output.frame_width;
7156 portDefn->format.video.nStride = drv_ctx.video_resolution_output.stride;
7157 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution_output.scan_lines;
7158 }
7159 else
7160 {
7161 portDefn->eDir = OMX_DirMax;
7162 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
7163 (int)portDefn->nPortIndex);
7164 eRet = OMX_ErrorBadPortIndex;
7165 }
7166
7167 DEBUG_PRINT_HIGH("update_portdef for %lu Width = %lu Height = %lu Stride = %ld SliceHeight = %lu portDefn->format.video.eColorFormat = %d \n", portDefn->nPortIndex,
7168 portDefn->format.video.nFrameWidth,
7169 portDefn->format.video.nFrameHeight,
7170 portDefn->format.video.nStride,
7171 portDefn->format.video.nSliceHeight,
7172 portDefn->format.video.eColorFormat);
7173 return eRet;
7174
7175 }
7176
allocate_output_headers()7177 OMX_ERRORTYPE omx_vdpp::allocate_output_headers()
7178 {
7179 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7180 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
7181 unsigned i= 0;
7182
7183 if(!m_out_mem_ptr) {
7184 DEBUG_PRINT_HIGH(" Use o/p buffer case - Header List allocation");
7185 int nBufHdrSize = 0;
7186 int nPlatformEntrySize = 0;
7187 int nPlatformListSize = 0;
7188 int nPMEMInfoSize = 0;
7189 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
7190 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
7191 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
7192
7193 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)\n",
7194 drv_ctx.op_buf.actualcount);
7195 nBufHdrSize = drv_ctx.op_buf.actualcount *
7196 sizeof(OMX_BUFFERHEADERTYPE);
7197
7198 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d \n",nBufHdrSize,
7199 sizeof(OMX_BUFFERHEADERTYPE));
7200
7201 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
7202
7203 drv_ctx.ptr_outputbuffer = (struct vdpp_bufferpayload *) \
7204 calloc (sizeof(struct vdpp_bufferpayload),
7205 drv_ctx.op_buf.actualcount);
7206 drv_ctx.ptr_respbuffer = (struct vdpp_output_frameinfo *)\
7207 calloc (sizeof (struct vdpp_output_frameinfo),
7208 drv_ctx.op_buf.actualcount);
7209 #ifdef USE_ION
7210 drv_ctx.op_buf_ion_info = (struct vdpp_ion * ) \
7211 calloc (sizeof(struct vdpp_ion),drv_ctx.op_buf.actualcount);
7212
7213 if (!drv_ctx.op_buf_ion_info) {
7214 DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
7215 return OMX_ErrorInsufficientResources;
7216 }
7217 #endif
7218
7219 if(m_out_mem_ptr && drv_ctx.ptr_outputbuffer
7220 && drv_ctx.ptr_respbuffer)
7221 {
7222 bufHdr = m_out_mem_ptr;
7223 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
7224
7225 for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
7226 {
7227 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
7228 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
7229 // Set the values when we determine the right HxW param
7230 bufHdr->nAllocLen = 0;
7231 bufHdr->nFilledLen = 0;
7232 bufHdr->pAppPrivate = NULL;
7233 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7234 bufHdr->pBuffer = NULL; // since no buffer is allocated
7235
7236 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
7237 #ifdef USE_ION
7238 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
7239 #endif
7240 /*Create a mapping between buffers*/
7241 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7242 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
7243 &drv_ctx.ptr_outputbuffer[i];
7244 // Move the buffer and buffer header pointers
7245 bufHdr++;
7246 }
7247 }
7248 else
7249 {
7250 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p]\n",\
7251 m_out_mem_ptr);
7252 if(m_out_mem_ptr)
7253 {
7254 free(m_out_mem_ptr);
7255 m_out_mem_ptr = NULL;
7256 }
7257
7258 if(drv_ctx.ptr_outputbuffer)
7259 {
7260 free(drv_ctx.ptr_outputbuffer);
7261 drv_ctx.ptr_outputbuffer = NULL;
7262 }
7263 if(drv_ctx.ptr_respbuffer)
7264 {
7265 free(drv_ctx.ptr_respbuffer);
7266 drv_ctx.ptr_respbuffer = NULL;
7267 }
7268 #ifdef USE_ION
7269 if (drv_ctx.op_buf_ion_info) {
7270 DEBUG_PRINT_LOW(" Free o/p ion context");
7271 free(drv_ctx.op_buf_ion_info);
7272 drv_ctx.op_buf_ion_info = NULL;
7273 }
7274 #endif
7275 eRet = OMX_ErrorInsufficientResources;
7276 }
7277 } else {
7278 eRet = OMX_ErrorInsufficientResources;
7279 }
7280 return eRet;
7281 }
7282
complete_pending_buffer_done_cbs()7283 void omx_vdpp::complete_pending_buffer_done_cbs()
7284 {
7285 unsigned p1;
7286 unsigned p2;
7287 unsigned ident;
7288 omx_cmd_queue tmp_q, pending_bd_q;
7289 pthread_mutex_lock(&m_lock);
7290 // pop all pending GENERATE FDB from ftb queue
7291 while (m_ftb_q.m_size)
7292 {
7293 m_ftb_q.pop_entry(&p1,&p2,&ident);
7294 if(ident == OMX_COMPONENT_GENERATE_FBD)
7295 {
7296 pending_bd_q.insert_entry(p1,p2,ident);
7297 }
7298 else
7299 {
7300 tmp_q.insert_entry(p1,p2,ident);
7301 }
7302 }
7303 //return all non GENERATE FDB to ftb queue
7304 while(tmp_q.m_size)
7305 {
7306 tmp_q.pop_entry(&p1,&p2,&ident);
7307 m_ftb_q.insert_entry(p1,p2,ident);
7308 }
7309 // pop all pending GENERATE EDB from etb queue
7310 while (m_etb_q.m_size)
7311 {
7312 m_etb_q.pop_entry(&p1,&p2,&ident);
7313 if(ident == OMX_COMPONENT_GENERATE_EBD)
7314 {
7315 pending_bd_q.insert_entry(p1,p2,ident);
7316 }
7317 else
7318 {
7319 tmp_q.insert_entry(p1,p2,ident);
7320 }
7321 }
7322 //return all non GENERATE FDB to etb queue
7323 while(tmp_q.m_size)
7324 {
7325 tmp_q.pop_entry(&p1,&p2,&ident);
7326 m_etb_q.insert_entry(p1,p2,ident);
7327 }
7328 pthread_mutex_unlock(&m_lock);
7329 // process all pending buffer dones
7330 while(pending_bd_q.m_size)
7331 {
7332 pending_bd_q.pop_entry(&p1,&p2,&ident);
7333 switch(ident)
7334 {
7335 case OMX_COMPONENT_GENERATE_EBD:
7336 if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
7337 {
7338 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!\n");
7339 omx_report_error ();
7340 }
7341 break;
7342
7343 case OMX_COMPONENT_GENERATE_FBD:
7344 if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
7345 {
7346 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!\n");
7347 omx_report_error ();
7348 }
7349 break;
7350 }
7351 }
7352 }
7353
set_frame_rate(OMX_S64 act_timestamp)7354 void omx_vdpp::set_frame_rate(OMX_S64 act_timestamp)
7355 {
7356 // No framerate control on 8084 VPU. This API is for 8092.
7357 #ifdef FRC_ENABLE
7358 OMX_U32 new_frame_interval = 0;
7359 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
7360 && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000))
7361 {
7362 new_frame_interval = (act_timestamp > prev_ts)?
7363 act_timestamp - prev_ts :
7364 prev_ts - act_timestamp;
7365 if (new_frame_interval < frm_int || frm_int == 0)
7366 {
7367 frm_int = new_frame_interval;
7368 if(frm_int)
7369 {
7370 drv_ctx.frame_rate.fps_numerator = 1e6;
7371 drv_ctx.frame_rate.fps_denominator = frm_int;
7372 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%lu) fps(%f)",
7373 frm_int, drv_ctx.frame_rate.fps_numerator /
7374 (float)drv_ctx.frame_rate.fps_denominator);
7375
7376 /* We need to report the difference between this FBD and the previous FBD
7377 * back to the driver for clock scaling purposes. */
7378 struct v4l2_outputparm oparm;
7379 /*XXX: we're providing timing info as seconds per frame rather than frames
7380 * per second.*/
7381 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
7382 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
7383
7384 struct v4l2_streamparm sparm;
7385 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7386 sparm.parm.output = oparm;
7387 if (ioctl(drv_ctx.video_vpu_fd, VIDIOC_S_PARM, &sparm))
7388 {
7389 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
7390 performance might be affected");
7391 }
7392
7393 }
7394 }
7395 }
7396 prev_ts = act_timestamp;
7397 #endif
7398 }
7399
adjust_timestamp(OMX_S64 & act_timestamp)7400 void omx_vdpp::adjust_timestamp(OMX_S64 &act_timestamp)
7401 {
7402 if (rst_prev_ts && VALID_TS(act_timestamp))
7403 {
7404 prev_ts = act_timestamp;
7405 rst_prev_ts = false;
7406 }
7407 else if (VALID_TS(prev_ts))
7408 {
7409 bool codec_cond = (drv_ctx.timestamp_adjust)?
7410 (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)?
7411 (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)):
7412 (!VALID_TS(act_timestamp) || act_timestamp == prev_ts);
7413 if(frm_int > 0 && codec_cond)
7414 {
7415 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
7416 act_timestamp = prev_ts + frm_int;
7417 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
7418 prev_ts = act_timestamp;
7419 }
7420 else
7421 set_frame_rate(act_timestamp);
7422 }
7423 else if (frm_int > 0) // In this case the frame rate was set along
7424 { // with the port definition, start ts with 0
7425 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
7426 rst_prev_ts = true;
7427 }
7428 }
7429
enable_extradata(OMX_U32 requested_extradata,bool enable)7430 OMX_ERRORTYPE omx_vdpp::enable_extradata(OMX_U32 requested_extradata, bool enable)
7431 {
7432 OMX_ERRORTYPE ret = OMX_ErrorNone;
7433 if(m_state != OMX_StateLoaded)
7434 {
7435 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
7436 return OMX_ErrorIncorrectStateOperation;
7437 }
7438 DEBUG_PRINT_ERROR("enable_extradata: actual[%lx] requested[%lx] enable[%d]",
7439 client_extradata, requested_extradata, enable);
7440
7441 if (enable)
7442 client_extradata |= requested_extradata;
7443 else
7444 client_extradata = client_extradata & ~requested_extradata;
7445
7446 return ret;
7447 }
7448
setFormatParams(int pixelFormat,double bytesperpixel[],unsigned char * planesCount)7449 void omx_vdpp::setFormatParams(int pixelFormat, double bytesperpixel[], unsigned char *planesCount)
7450 {
7451 /*24 RGB-8-8-8 */
7452 switch (pixelFormat)
7453 {
7454 case V4L2_PIX_FMT_RGB24:
7455 *planesCount = 0;
7456 bytesperpixel[0] = 3;
7457 break;
7458
7459 /*32 ARGB-8-8-8-8 */
7460 case V4L2_PIX_FMT_RGB32:
7461 *planesCount = 0;
7462 bytesperpixel[0] = 4;
7463 break;
7464
7465 /*32 ARGB-2-10-10-10*/
7466 case V4L2_PIX_FMT_XRGB2:
7467 *planesCount = 0;
7468 bytesperpixel[0] = 4;
7469 break;
7470
7471 /*24 BGR-8-8-8 */
7472 case V4L2_PIX_FMT_BGR24:
7473 *planesCount = 0;
7474 bytesperpixel[0] = 3;
7475 break;
7476
7477 /*32 BGRX-8-8-8-8 */
7478 case V4L2_PIX_FMT_BGR32:
7479 *planesCount = 0;
7480 bytesperpixel[0] = 4;
7481 break;
7482
7483 /*32 XBGR-2-10-10-10*/
7484 case V4L2_PIX_FMT_XBGR2:
7485 *planesCount = 0;
7486 bytesperpixel[0] = 4;
7487 break;
7488
7489 /*12 YUV 4:2:0 semi-planar*/
7490 case V4L2_PIX_FMT_NV12:
7491 *planesCount = 2;
7492 bytesperpixel[0] = 1;
7493 bytesperpixel[1] = 0.5;
7494 break;
7495
7496 /*12 YVU 4:2:0 semi-planar*/
7497 case V4L2_PIX_FMT_NV21:
7498 *planesCount = 2;
7499 bytesperpixel[0] = 1;
7500 bytesperpixel[1] = 0.5;
7501 break;
7502
7503 /* 16 YUYV 4:2:2 interleaved*/
7504 case V4L2_PIX_FMT_YUYV:
7505 *planesCount = 2;
7506 bytesperpixel[0] = 2;
7507 bytesperpixel[1] = 0.5;
7508 break;
7509
7510 /* 16 YVYU 4:2:2 interleaved*/
7511 case V4L2_PIX_FMT_YVYU:
7512 *planesCount = 1;
7513 bytesperpixel[0] = 2;
7514 break;
7515
7516 /* 16 VYUY 4:2:2 interleaved*/
7517 case V4L2_PIX_FMT_VYUY:
7518 *planesCount = 1;
7519 bytesperpixel[0] = 2;
7520 break;
7521
7522 /* 16 UYVY 4:2:2 interleaved*/
7523 case V4L2_PIX_FMT_UYVY:
7524 *planesCount = 1;
7525 bytesperpixel[0] = 2;
7526 break;
7527
7528 default:
7529 DEBUG_PRINT_ERROR("%s: ERROR: pixel format %d is not supported!\n",
7530 __func__, pixelFormat);
7531 }
7532
7533 }
7534
openInput(const char * inputName)7535 int omx_vdpp::openInput(const char* inputName)
7536 {
7537 int fd = -1;
7538 const char *dirname = "/sys/class/video4linux";
7539 char devname[PATH_MAX];
7540 char dev[PATH_MAX];
7541 char *filename;
7542 DIR *dir;
7543 struct dirent *de;
7544 dir = opendir(dirname);
7545 if(dir == NULL)
7546 return -1;
7547 strlcpy(dev, dirname, sizeof(dev));
7548 filename = dev + strlen(dev);
7549 *filename++ = '/';
7550 while((de = readdir(dir)))
7551 {
7552 if(de->d_name[0] == '.' &&
7553 (de->d_name[1] == '\0' ||
7554 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
7555 continue;
7556 strlcpy(filename, de->d_name, PATH_MAX - sizeof(dev) - 1);
7557 /*DEBUG_PRINT_LOW("Filename found: %s\n", filename);*/
7558 char name[80];
7559 int fd_devname;
7560 int result;
7561 strlcpy(devname, dev, sizeof(devname));
7562 strlcat(devname, "/name", sizeof(devname));
7563 /*DEBUG_PRINT_LOW("opening name file: %s\n", devname);*/
7564 /* find and read device node names from sys/conf/video4linux dir*/
7565 fd_devname = open(devname,O_RDONLY);
7566 if(fd_devname < 0)
7567 DEBUG_PRINT_ERROR("openInput: could not find device name.\n");
7568 result = read(fd_devname, name, strlen(inputName));
7569 if(result < 0)
7570 {
7571 DEBUG_PRINT_ERROR("openInput: could not read device name.\n");
7572 }
7573 else
7574 {
7575 if(!strcmp(name, inputName))
7576 {
7577 close(fd_devname);
7578 /* open the vpu driver node found from /dev dir */
7579 char temp[80];
7580 strlcpy(temp, "/dev/", sizeof(temp));
7581 strlcat(temp, filename, sizeof(temp));
7582 DEBUG_PRINT_LOW("openInput: opening device: %s\n", temp);
7583 fd = open(temp, O_RDWR | O_NONBLOCK);
7584 if(fd < 0)
7585 DEBUG_PRINT_ERROR("openInput: Error opening device %s\n", temp);
7586 else
7587 break;
7588 }
7589 }
7590 close(fd_devname);
7591 }
7592 closedir(dir);
7593 ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
7594 return fd;
7595 }
7596