blob: 1350cb889d9ef576db5fd96765ec4f1dbb7a5bbd [file] [log] [blame]
Shalaj Jain273b3e02012-06-22 19:08:03 -07001/*--------------------------------------------------------------------------
2Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, 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 Code Aurora 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27--------------------------------------------------------------------------*/
28
29/*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33*//** @file omx_vdec.cpp
34 This module contains the implementation of the OpenMAX core & component.
35
36*//*========================================================================*/
37
38//////////////////////////////////////////////////////////////////////////////
39// Include Files
40//////////////////////////////////////////////////////////////////////////////
41
42#include <string.h>
43#include <pthread.h>
44#include <sys/prctl.h>
45#include <stdlib.h>
46#include <unistd.h>
47#include <errno.h>
48#include "omx_vdec.h"
49#include <fcntl.h>
50#include <limits.h>
51
52#ifndef _ANDROID_
53#include <sys/ioctl.h>
54#include <sys/mman.h>
55#endif //_ANDROID_
56
57#ifdef _ANDROID_
58#include <cutils/properties.h>
59#undef USE_EGL_IMAGE_GPU
60#endif
61
62#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
63#include <gralloc_priv.h>
64#endif
65
66#if defined (_ANDROID_ICS_)
67#include <genlock.h>
68#endif
69
70#ifdef _ANDROID_
71#include "DivXDrmDecrypt.h"
72#endif //_ANDROID_
73
74#ifdef USE_EGL_IMAGE_GPU
75#include <EGL/egl.h>
76#include <EGL/eglQCOM.h>
77#define EGL_BUFFER_HANDLE_QCOM 0x4F00
78#define EGL_BUFFER_OFFSET_QCOM 0x4F01
79#endif
80
81#ifdef INPUT_BUFFER_LOG
82#define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0"
83#define INPUT_BUFFER_FILE_NAME_LEN 30
84FILE *inputBufferFile1;
85char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0";
86#endif
87#ifdef OUTPUT_BUFFER_LOG
88FILE *outputBufferFile1;
89char outputfilename [] = "/data/output.yuv";
90#endif
91#ifdef OUTPUT_EXTRADATA_LOG
92FILE *outputExtradataFile;
93char ouputextradatafilename [] = "/data/extradata";
94#endif
95
96#define DEFAULT_FPS 30
97#define MAX_INPUT_ERROR DEFAULT_FPS
98#define MAX_SUPPORTED_FPS 120
99
100#define VC1_SP_MP_START_CODE 0xC5000000
101#define VC1_SP_MP_START_CODE_MASK 0xFF000000
102#define VC1_AP_SEQ_START_CODE 0x0F010000
103#define VC1_STRUCT_C_PROFILE_MASK 0xF0
104#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
105#define VC1_SIMPLE_PROFILE 0
106#define VC1_MAIN_PROFILE 1
107#define VC1_ADVANCE_PROFILE 3
108#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
109#define VC1_SIMPLE_PROFILE_MED_LEVEL 2
110#define VC1_STRUCT_C_LEN 4
111#define VC1_STRUCT_C_POS 8
112#define VC1_STRUCT_A_POS 12
113#define VC1_STRUCT_B_POS 24
114#define VC1_SEQ_LAYER_SIZE 36
115
116#define MEM_DEVICE "/dev/ion"
117#define MEM_HEAP_ID ION_CP_MM_HEAP_ID
118
119#ifdef _ANDROID_
120 extern "C"{
121 #include<utils/Log.h>
122 }
123#endif//_ANDROID_
124
125#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
126#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
127
128void* async_message_thread (void *input)
129{
130 struct vdec_ioctl_msg ioctl_msg;
Shalaj Jain273b3e02012-06-22 19:08:03 -0700131 OMX_BUFFERHEADERTYPE *buffer;
132 struct v4l2_plane plane;
133 struct pollfd pfd;
134 struct v4l2_buffer v4l2_buf ={0};
135 struct v4l2_event dqevent;
136 pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
137 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
138 pfd.fd = omx->drv_ctx.video_driver_fd;
139 int error_code = 0,rc=0;
140 DEBUG_PRINT_HIGH("omx_vdec: Async thread start\n");
141 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
142 while (1)
143 {
144 rc = poll(&pfd, 1, TIMEOUT);
145 if (!rc) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -0700146 DEBUG_PRINT_ERROR("Poll timedout\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -0700147 break;
148 } else if (rc < 0) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -0700149 DEBUG_PRINT_ERROR("Error while polling: %d\n", rc);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700150 break;
151 }
Vinay Kalia85793762012-06-14 19:12:34 -0700152 if (pfd.revents & POLLERR){
153 printf("\n async_message_thread Exited \n");
154 break;
155 }
156 if (pfd.revents & POLLPRI){
157 rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent);
158 if(dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT) {
159 DEBUG_PRINT_HIGH("\n VIDC Sufficinet resources recieved \n");
160 continue;
161 } else if(dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT) {
162 struct vdec_msginfo vdec_msg;
163 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
164 vdec_msg.status_code=VDEC_S_SUCCESS;
165 printf("\n VIDC Port Reconfig recieved \n");
166 if (omx->async_message_process(input,&vdec_msg) < 0) {
167 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
168 break;
169 }
170 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
171 struct vdec_msginfo vdec_msg;
172 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
173 vdec_msg.status_code=VDEC_S_SUCCESS;
174 DEBUG_PRINT_HIGH("\n VIDC Flush Done Recieved \n");
175 if (omx->async_message_process(input,&vdec_msg) < 0) {
176 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
177 break;
178 }
179 } else {
180 DEBUG_PRINT_HIGH("\n VIDC Some Event recieved \n");
181 continue;
182 }
183 }
Shalaj Jain273b3e02012-06-22 19:08:03 -0700184 if ((pfd.revents & POLLIN) || (pfd.revents & POLLRDNORM)) {
Vinay Kalia85793762012-06-14 19:12:34 -0700185 struct vdec_msginfo vdec_msg;
Shalaj Jain273b3e02012-06-22 19:08:03 -0700186 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
187 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
188 v4l2_buf.length = 1;
189 v4l2_buf.m.planes = &plane;
190 rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf);
191 if (rc) {
192 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -0700193 DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from capture capability\n", rc);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700194 break;
195 }
196 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
197 vdec_msg.status_code=VDEC_S_SUCCESS;
198 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
199 vdec_msg.msgdata.output_frame.len=plane.bytesused;
200 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane.m.userptr;
Vinay Kalia85793762012-06-14 19:12:34 -0700201 if (omx->async_message_process(input,&vdec_msg) < 0) {
202 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
203 break;
204 }
Shalaj Jain273b3e02012-06-22 19:08:03 -0700205 }
Vinay Kalia85793762012-06-14 19:12:34 -0700206 if((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) {
207 struct vdec_msginfo vdec_msg;
Shalaj Jain273b3e02012-06-22 19:08:03 -0700208 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
209 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
210 v4l2_buf.m.planes = &plane;
211 rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf);
212 if (rc) {
213 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -0700214 DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from output capability\n", rc);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700215 break;
216 }
Vinay Kalia85793762012-06-14 19:12:34 -0700217 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
Shalaj Jain273b3e02012-06-22 19:08:03 -0700218 vdec_msg.status_code=VDEC_S_SUCCESS;
219 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
Vinay Kalia85793762012-06-14 19:12:34 -0700220 if (omx->async_message_process(input,&vdec_msg) < 0) {
221 DEBUG_PRINT_HIGH("\n async_message_thread Exited \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -0700222 break;
Vinay Kalia85793762012-06-14 19:12:34 -0700223 }
Shalaj Jain273b3e02012-06-22 19:08:03 -0700224 }
225 }
226 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop\n");
227 return NULL;
228}
229
230void* message_thread(void *input)
231{
232 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
233 unsigned char id;
234 int n;
235
236 DEBUG_PRINT_HIGH("omx_vdec: message thread start\n");
237 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
238 while (1)
239 {
240
241 n = read(omx->m_pipe_in, &id, 1);
242
243 if(0 == n)
244 {
245 break;
246 }
247
248 if (1 == n)
249 {
250 omx->process_event_cb(omx, id);
251 }
252 if ((n < 0) && (errno != EINTR))
253 {
254 DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno);
255 break;
256 }
257 }
258 DEBUG_PRINT_HIGH("omx_vdec: message thread stop\n");
259 return 0;
260}
261
262void post_message(omx_vdec *omx, unsigned char id)
263{
264 int ret_value;
265 DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d\n", id,omx->m_pipe_out);
266 ret_value = write(omx->m_pipe_out, &id, 1);
267 DEBUG_PRINT_LOW("post_message to pipe done %d\n",ret_value);
268}
269
270// omx_cmd_queue destructor
271omx_vdec::omx_cmd_queue::~omx_cmd_queue()
272{
273 // Nothing to do
274}
275
276// omx cmd queue constructor
277omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
278{
279 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
280}
281
282// omx cmd queue insert
283bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
284{
285 bool ret = true;
286 if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE)
287 {
288 m_q[m_write].id = id;
289 m_q[m_write].param1 = p1;
290 m_q[m_write].param2 = p2;
291 m_write++;
292 m_size ++;
293 if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE)
294 {
295 m_write = 0;
296 }
297 }
298 else
299 {
300 ret = false;
301 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full\n", __func__);
302 }
303 return ret;
304}
305
306// omx cmd queue pop
307bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
308{
309 bool ret = true;
310 if (m_size > 0)
311 {
312 *id = m_q[m_read].id;
313 *p1 = m_q[m_read].param1;
314 *p2 = m_q[m_read].param2;
315 // Move the read pointer ahead
316 ++m_read;
317 --m_size;
318 if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE)
319 {
320 m_read = 0;
321 }
322 }
323 else
324 {
325 ret = false;
326 }
327 return ret;
328}
329
330// Retrieve the first mesg type in the queue
331unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
332{
333 return m_q[m_read].id;
334}
335
336#ifdef _ANDROID_
337omx_vdec::ts_arr_list::ts_arr_list()
338{
339 //initialize timestamps array
340 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
341}
342omx_vdec::ts_arr_list::~ts_arr_list()
343{
344 //free m_ts_arr_list?
345}
346
347bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
348{
349 bool ret = true;
350 bool duplicate_ts = false;
351 int idx = 0;
352
353 //insert at the first available empty location
354 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
355 {
356 if (!m_ts_arr_list[idx].valid)
357 {
358 //found invalid or empty entry, save timestamp
359 m_ts_arr_list[idx].valid = true;
360 m_ts_arr_list[idx].timestamp = ts;
361 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
362 ts, idx);
363 break;
364 }
365 }
366
367 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS)
368 {
369 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
370 ret = false;
371 }
372 return ret;
373}
374
375bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
376{
377 bool ret = true;
378 int min_idx = -1;
379 OMX_TICKS min_ts = 0;
380 int idx = 0;
381
382 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
383 {
384
385 if (m_ts_arr_list[idx].valid)
386 {
387 //found valid entry, save index
388 if (min_idx < 0)
389 {
390 //first valid entry
391 min_ts = m_ts_arr_list[idx].timestamp;
392 min_idx = idx;
393 }
394 else if (m_ts_arr_list[idx].timestamp < min_ts)
395 {
396 min_ts = m_ts_arr_list[idx].timestamp;
397 min_idx = idx;
398 }
399 }
400
401 }
402
403 if (min_idx < 0)
404 {
405 //no valid entries found
406 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
407 ts = 0;
408 ret = false;
409 }
410 else
411 {
412 ts = m_ts_arr_list[min_idx].timestamp;
413 m_ts_arr_list[min_idx].valid = false;
414 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
415 ts, min_idx);
416 }
417
418 return ret;
419
420}
421
422
423bool omx_vdec::ts_arr_list::reset_ts_list()
424{
425 bool ret = true;
426 int idx = 0;
427
428 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
429 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
430 {
431 m_ts_arr_list[idx].valid = false;
432 }
433 return ret;
434}
435#endif
436
437// factory function executed by the core to create instances
438void *get_omx_component_factory_fn(void)
439{
440 return (new omx_vdec);
441}
442
443#ifdef _ANDROID_
444#ifdef USE_ION
445VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
446 struct ion_handle *handle, int ionMapfd)
447{
448 ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
449}
450#else
451VideoHeap::VideoHeap(int fd, size_t size, void* base)
452{
453 // dup file descriptor, map once, use pmem
454 init(dup(fd), base, size, 0 , MEM_DEVICE);
455}
456#endif
457#endif // _ANDROID_
458/* ======================================================================
459FUNCTION
460 omx_vdec::omx_vdec
461
462DESCRIPTION
463 Constructor
464
465PARAMETERS
466 None
467
468RETURN VALUE
469 None.
470========================================================================== */
471omx_vdec::omx_vdec(): m_state(OMX_StateInvalid),
472 m_app_data(NULL),
473 m_inp_mem_ptr(NULL),
474 m_out_mem_ptr(NULL),
475 m_phdr_pmem_ptr(NULL),
476 pending_input_buffers(0),
477 pending_output_buffers(0),
478 m_out_bm_count(0),
479 m_inp_bm_count(0),
480 m_inp_bPopulated(OMX_FALSE),
481 m_out_bPopulated(OMX_FALSE),
482 m_flags(0),
483 m_inp_bEnabled(OMX_TRUE),
484 m_out_bEnabled(OMX_TRUE),
485 m_platform_list(NULL),
486 m_platform_entry(NULL),
487 m_pmem_info(NULL),
488 output_flush_progress (false),
489 input_flush_progress (false),
490 input_use_buffer (false),
491 output_use_buffer (false),
492 arbitrary_bytes (true),
493 psource_frame (NULL),
494 pdest_frame (NULL),
495 m_inp_heap_ptr (NULL),
496 m_heap_inp_bm_count (0),
497 codec_type_parse ((codec_type)0),
498 first_frame_meta (true),
499 frame_count (0),
500 nal_length(0),
501 nal_count (0),
502 look_ahead_nal (false),
503 first_frame(0),
504 first_buffer(NULL),
505 first_frame_size (0),
506 m_error_propogated(false),
507 m_device_file_ptr(NULL),
508 m_vc1_profile((vc1_profile_type)0),
509 prev_ts(LLONG_MAX),
510 rst_prev_ts(true),
511 frm_int(0),
512 m_in_alloc_cnt(0),
513 m_display_id(NULL),
514 ouput_egl_buffers(false),
515 h264_parser(NULL),
516 client_extradata(0),
517 h264_last_au_ts(LLONG_MAX),
518 h264_last_au_flags(0),
519 m_inp_err_count(0),
520#ifdef _ANDROID_
521 m_heap_ptr(NULL),
522 m_enable_android_native_buffers(OMX_FALSE),
523 m_use_android_native_buffers(OMX_FALSE),
524#endif
525 in_reconfig(false),
526 m_use_output_pmem(OMX_FALSE),
527 m_out_mem_region_smi(OMX_FALSE),
528 m_out_pvt_entry_pmem(OMX_FALSE),
529 secure_mode(false)
530#ifdef _ANDROID_
531 ,iDivXDrmDecrypt(NULL)
532#endif
533 ,m_desc_buffer_ptr(NULL)
534 ,streaming({false, false})
535{
536 /* Assumption is that , to begin with , we have all the frames with decoder */
537 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
538#ifdef _ANDROID_
539 char property_value[PROPERTY_VALUE_MAX] = {0};
540 property_get("vidc.dec.debug.perf", property_value, "0");
541 perf_flag = atoi(property_value);
542 if (perf_flag)
543 {
544 DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
545 dec_time.start();
546 proc_frms = latency = 0;
547 }
548 property_value[0] = NULL;
549 property_get("vidc.dec.debug.ts", property_value, "0");
550 m_debug_timestamp = atoi(property_value);
551 DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
552 if (m_debug_timestamp)
553 {
554 time_stamp_dts.set_timestamp_reorder_mode(true);
555 }
556
557 property_value[0] = NULL;
558 property_get("vidc.dec.debug.concealedmb", property_value, "0");
559 m_debug_concealedmb = atoi(property_value);
560 DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);
561
562#endif
563 memset(&m_cmp,0,sizeof(m_cmp));
564 memset(&m_cb,0,sizeof(m_cb));
565 memset (&drv_ctx,0,sizeof(drv_ctx));
566 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
567 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
568 memset(&op_buf_rcnfg, 0 ,sizeof(vdec_allocatorproperty));
569 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
570 m_demux_entries = 0;
571#ifdef _ANDROID_ICS_
572 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
573#endif
574 drv_ctx.timestamp_adjust = false;
575 drv_ctx.video_driver_fd = -1;
576 m_vendor_config.pData = NULL;
577 pthread_mutex_init(&m_lock, NULL);
578 sem_init(&m_cmd_lock,0,0);
579#ifdef _ANDROID_
580 char extradata_value[PROPERTY_VALUE_MAX] = {0};
581 property_get("vidc.dec.debug.extradata", extradata_value, "0");
582 m_debug_extradata = atoi(extradata_value);
583 DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
584#endif
585
586}
587
Vinay Kalia85793762012-06-14 19:12:34 -0700588static const int event_type[] = {
589 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
590 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
591 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
592};
593
594static OMX_ERRORTYPE subscribe_to_events(int fd)
595{
596 OMX_ERRORTYPE eRet = OMX_ErrorNone;
597 struct v4l2_event_subscription sub;
598 int array_sz = sizeof(event_type)/sizeof(int);
599 int i,rc;
600 if (fd < 0) {
601 printf("Invalid input: %d\n", fd);
602 return OMX_ErrorBadParameter;
603 }
604
605 for (i = 0; i < array_sz; ++i) {
606 memset(&sub, 0, sizeof(sub));
607 sub.type = event_type[i];
608 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
609 if (rc) {
610 printf("Failed to subscribe event: 0x%x\n", sub.type);
611 break;
612 }
613 }
614 if (i < array_sz) {
615 for (--i; i >=0 ; i--) {
616 memset(&sub, 0, sizeof(sub));
617 sub.type = event_type[i];
618 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
619 if (rc)
620 printf("Failed to unsubscribe event: 0x%x\n", sub.type);
621 }
622 eRet = OMX_ErrorNotImplemented;
623 }
624 return eRet;
625}
626
627
628static OMX_ERRORTYPE unsubscribe_to_events(int fd)
629{
630 OMX_ERRORTYPE eRet = OMX_ErrorNone;
631 struct v4l2_event_subscription sub;
632 int array_sz = sizeof(event_type)/sizeof(int);
633 int i,rc;
634 if (fd < 0) {
635 printf("Invalid input: %d\n", fd);
636 return OMX_ErrorBadParameter;
637 }
638
639 for (i = 0; i < array_sz; ++i) {
640 memset(&sub, 0, sizeof(sub));
641 sub.type = event_type[i];
642 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
643 if (rc) {
644 printf("Failed to unsubscribe event: 0x%x\n", sub.type);
645 break;
646 }
647 }
648 return eRet;
649}
Shalaj Jain273b3e02012-06-22 19:08:03 -0700650
651/* ======================================================================
652FUNCTION
653 omx_vdec::~omx_vdec
654
655DESCRIPTION
656 Destructor
657
658PARAMETERS
659 None
660
661RETURN VALUE
662 None.
663========================================================================== */
664omx_vdec::~omx_vdec()
665{
666 m_pmem_info = NULL;
667 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
668 if(m_pipe_in) close(m_pipe_in);
669 if(m_pipe_out) close(m_pipe_out);
670 m_pipe_in = -1;
671 m_pipe_out = -1;
672 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
673 pthread_join(msg_thread_id,NULL);
674 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
675 pthread_join(async_thread_id,NULL);
Vinay Kalia85793762012-06-14 19:12:34 -0700676 unsubscribe_to_events(drv_ctx.video_driver_fd);
Shalaj Jain273b3e02012-06-22 19:08:03 -0700677 close(drv_ctx.video_driver_fd);
678 pthread_mutex_destroy(&m_lock);
679 sem_destroy(&m_cmd_lock);
680 if (perf_flag)
681 {
682 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
683 dec_time.end();
684 }
685 DEBUG_PRINT_HIGH("Exit OMX vdec Destructor");
686}
687
688/* ======================================================================
689FUNCTION
690 omx_vdec::OMXCntrlProcessMsgCb
691
692DESCRIPTION
693 IL Client callbacks are generated through this routine. The decoder
694 provides the thread context for this routine.
695
696PARAMETERS
697 ctxt -- Context information related to the self.
698 id -- Event identifier. This could be any of the following:
699 1. Command completion event
700 2. Buffer done callback event
701 3. Frame done callback event
702
703RETURN VALUE
704 None.
705
706========================================================================== */
707void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
708{
709 unsigned p1; // Parameter - 1
710 unsigned p2; // Parameter - 2
711 unsigned ident;
712 unsigned qsize=0; // qsize
713 omx_vdec *pThis = (omx_vdec *) ctxt;
714
715 if(!pThis)
716 {
717 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n",
718 __func__);
719 return;
720 }
721
722 // Protect the shared queue data structure
723 do
724 {
725 /*Read the message id's from the queue*/
726 pthread_mutex_lock(&pThis->m_lock);
727 qsize = pThis->m_cmd_q.m_size;
728 if(qsize)
729 {
730 pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
731 }
732
733 if (qsize == 0 && pThis->m_state != OMX_StatePause)
734 {
735 qsize = pThis->m_ftb_q.m_size;
736 if (qsize)
737 {
738 pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
739 }
740 }
741
742 if (qsize == 0 && pThis->m_state != OMX_StatePause)
743 {
744 qsize = pThis->m_etb_q.m_size;
745 if (qsize)
746 {
747 pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
748 }
749 }
750 pthread_mutex_unlock(&pThis->m_lock);
751
752 /*process message if we have one*/
753 if(qsize > 0)
754 {
755 id = ident;
756 switch (id)
757 {
758 case OMX_COMPONENT_GENERATE_EVENT:
759 if (pThis->m_cb.EventHandler)
760 {
761 switch (p1)
762 {
763 case OMX_CommandStateSet:
764 pThis->m_state = (OMX_STATETYPE) p2;
765 DEBUG_PRINT_HIGH("\n OMX_CommandStateSet complete, m_state = %d",
766 pThis->m_state);
767 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
768 OMX_EventCmdComplete, p1, p2, NULL);
769 break;
770
771 case OMX_EventError:
772 if(p2 == OMX_StateInvalid)
773 {
774 DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid");
775 pThis->m_state = (OMX_STATETYPE) p2;
776 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
777 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
778 }
779 else if (p2 == OMX_ErrorHardware)
780 {
781 pThis->omx_report_error();
782 }
783 else
784 {
785 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
786 OMX_EventError, p2, NULL, NULL );
787 }
788 break;
789
790 case OMX_CommandPortDisable:
791 DEBUG_PRINT_HIGH("\n OMX_CommandPortDisable complete for port [%d]", p2);
792 if (BITMASK_PRESENT(&pThis->m_flags,
793 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
794 {
795 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
796 break;
797 }
798 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig)
799 {
800 pThis->op_buf_rcnfg.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
801 OMX_ERRORTYPE eRet = OMX_ErrorNone;
802 pThis->stream_off();
803 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->op_buf_rcnfg);
804 pThis->in_reconfig = false;
805 if(eRet != OMX_ErrorNone)
806 {
807 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
808 pThis->omx_report_error();
809 break;
810 }
811 }
812 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
813 OMX_EventCmdComplete, p1, p2, NULL );
814 break;
815 case OMX_CommandPortEnable:
816 DEBUG_PRINT_HIGH("\n OMX_CommandPortEnable complete for port [%d]", p2);
817 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
818 OMX_EventCmdComplete, p1, p2, NULL );
819 break;
820
821 default:
822 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
823 OMX_EventCmdComplete, p1, p2, NULL );
824 break;
825
826 }
827 }
828 else
829 {
830 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__);
831 }
832 break;
833 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
834 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
835 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
836 {
837 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
838 pThis->omx_report_error ();
839 }
840 break;
841 case OMX_COMPONENT_GENERATE_ETB:
842 if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
843 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
844 {
845 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
846 pThis->omx_report_error ();
847 }
848 break;
849
850 case OMX_COMPONENT_GENERATE_FTB:
851 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
852 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
853 {
854 DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
855 pThis->omx_report_error ();
856 }
857 break;
858
859 case OMX_COMPONENT_GENERATE_COMMAND:
860 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
861 (OMX_U32)p2,(OMX_PTR)NULL);
862 break;
863
864 case OMX_COMPONENT_GENERATE_EBD:
865
866 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR)
867 {
868 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure");
869 pThis->omx_report_error ();
870 }
871 else
872 {
873 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1)
874 {
875 pThis->m_inp_err_count++;
876 pThis->time_stamp_dts.remove_time_stamp(
877 ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp,
878 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
879 ?true:false);
880 }
881 else
882 {
883 pThis->m_inp_err_count = 0;
884 }
885 if ( pThis->empty_buffer_done(&pThis->m_cmp,
886 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
887 {
888 DEBUG_PRINT_ERROR("\n empty_buffer_done failure");
889 pThis->omx_report_error ();
890 }
891 if(pThis->m_inp_err_count >= MAX_INPUT_ERROR)
892 {
893 DEBUG_PRINT_ERROR("\n Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR);
894 pThis->omx_report_error ();
895 }
896 }
897 break;
898 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED:
899 {
900 int64_t *timestamp = (int64_t *)p1;
901 if (p1)
902 {
903 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
904 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
905 ?true:false);
906 free(timestamp);
907 }
908 }
909 break;
910 case OMX_COMPONENT_GENERATE_FBD:
911 if (p2 != VDEC_S_SUCCESS)
912 {
913 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure");
914 pThis->omx_report_error ();
915 }
916 else if ( pThis->fill_buffer_done(&pThis->m_cmp,
917 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
918 {
919 DEBUG_PRINT_ERROR("\n fill_buffer_done failure");
920 pThis->omx_report_error ();
921 }
922 break;
923
924 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
925 DEBUG_PRINT_HIGH("\n Driver flush i/p Port complete");
926 if (!pThis->input_flush_progress)
927 {
928 DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver");
929 }
930 else
931 {
932 pThis->execute_input_flush();
933 if (pThis->m_cb.EventHandler)
934 {
935 if (p2 != VDEC_S_SUCCESS)
936 {
937 DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
938 pThis->omx_report_error ();
939 }
940 else
941 {
942 /*Check if we need generate event for Flush done*/
943 if(BITMASK_PRESENT(&pThis->m_flags,
944 OMX_COMPONENT_INPUT_FLUSH_PENDING))
945 {
946 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
947 DEBUG_PRINT_LOW("\n Input Flush completed - Notify Client");
948 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
949 OMX_EventCmdComplete,OMX_CommandFlush,
950 OMX_CORE_INPUT_PORT_INDEX,NULL );
951 }
952 if (BITMASK_PRESENT(&pThis->m_flags,
953 OMX_COMPONENT_IDLE_PENDING))
954 {
955 if (!pThis->output_flush_progress)
956 {
957 DEBUG_PRINT_LOW("\n Output flush done hence issue stop");
958 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
959 VDEC_IOCTL_CMD_STOP,NULL ) < 0*/0)
960 {
961 DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
962 pThis->omx_report_error ();
963 }
964 }
965 }
966 }
967 }
968 else
969 {
970 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
971 }
972 }
973 break;
974
975 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
976 DEBUG_PRINT_HIGH("\n Driver flush o/p Port complete");
977 if (!pThis->output_flush_progress)
978 {
979 DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver");
980 }
981 else
982 {
983 pThis->execute_output_flush();
984 if (pThis->m_cb.EventHandler)
985 {
986 if (p2 != VDEC_S_SUCCESS)
987 {
988 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
989 pThis->omx_report_error ();
990 }
991 else
992 {
993 /*Check if we need generate event for Flush done*/
994 if(BITMASK_PRESENT(&pThis->m_flags,
995 OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
996 {
997 DEBUG_PRINT_LOW("\n Notify Output Flush done");
998 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
999 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1000 OMX_EventCmdComplete,OMX_CommandFlush,
1001 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
1002 }
1003 if(BITMASK_PRESENT(&pThis->m_flags,
1004 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
1005 {
1006 DEBUG_PRINT_LOW("\n Internal flush complete");
1007 BITMASK_CLEAR (&pThis->m_flags,
1008 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1009 if (BITMASK_PRESENT(&pThis->m_flags,
1010 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED))
1011 {
1012 pThis->post_event(OMX_CommandPortDisable,
1013 OMX_CORE_OUTPUT_PORT_INDEX,
1014 OMX_COMPONENT_GENERATE_EVENT);
1015 BITMASK_CLEAR (&pThis->m_flags,
1016 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1017
1018 }
1019 }
1020
1021 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING))
1022 {
1023 if (!pThis->input_flush_progress)
1024 {
1025 DEBUG_PRINT_LOW("\n Input flush done hence issue stop");
1026 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1027 VDEC_IOCTL_CMD_STOP,NULL ) < */0)
1028 {
1029 DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
1030 pThis->omx_report_error ();
1031 }
1032 }
1033 }
1034 }
1035 }
1036 else
1037 {
1038 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1039 }
1040 }
1041 break;
1042
1043 case OMX_COMPONENT_GENERATE_START_DONE:
1044 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_START_DONE");
1045
1046 if (pThis->m_cb.EventHandler)
1047 {
1048 if (p2 != VDEC_S_SUCCESS)
1049 {
1050 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure");
1051 pThis->omx_report_error ();
1052 }
1053 else
1054 {
1055 DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success");
1056 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
1057 {
1058 DEBUG_PRINT_LOW("\n Move to executing");
1059 // Send the callback now
1060 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1061 pThis->m_state = OMX_StateExecuting;
1062 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1063 OMX_EventCmdComplete,OMX_CommandStateSet,
1064 OMX_StateExecuting, NULL);
1065 }
1066 else if (BITMASK_PRESENT(&pThis->m_flags,
1067 OMX_COMPONENT_PAUSE_PENDING))
1068 {
1069 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1070 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0)
1071 {
1072 DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed");
1073 pThis->omx_report_error ();
1074 }
1075 }
1076 }
1077 }
1078 else
1079 {
1080 DEBUG_PRINT_LOW("\n Event Handler callback is NULL");
1081 }
1082 break;
1083
1084 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1085 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1086 if (pThis->m_cb.EventHandler)
1087 {
1088 if (p2 != VDEC_S_SUCCESS)
1089 {
1090 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1091 pThis->omx_report_error ();
1092 }
1093 else
1094 {
1095 pThis->complete_pending_buffer_done_cbs();
1096 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING))
1097 {
1098 DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1099 //Send the callback now
1100 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1101 pThis->m_state = OMX_StatePause;
1102 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1103 OMX_EventCmdComplete,OMX_CommandStateSet,
1104 OMX_StatePause, NULL);
1105 }
1106 }
1107 }
1108 else
1109 {
1110 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1111 }
1112
1113 break;
1114
1115 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1116 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1117 if (pThis->m_cb.EventHandler)
1118 {
1119 if (p2 != VDEC_S_SUCCESS)
1120 {
1121 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1122 pThis->omx_report_error ();
1123 }
1124 else
1125 {
1126 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
1127 {
1128 DEBUG_PRINT_LOW("\n Moving the decoder to execute state");
1129 // Send the callback now
1130 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1131 pThis->m_state = OMX_StateExecuting;
1132 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1133 OMX_EventCmdComplete,OMX_CommandStateSet,
1134 OMX_StateExecuting,NULL);
1135 }
1136 }
1137 }
1138 else
1139 {
1140 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1141 }
1142
1143 break;
1144
1145 case OMX_COMPONENT_GENERATE_STOP_DONE:
1146 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1147 if (pThis->m_cb.EventHandler)
1148 {
1149 if (p2 != VDEC_S_SUCCESS)
1150 {
1151 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1152 pThis->omx_report_error ();
1153 }
1154 else
1155 {
1156 pThis->complete_pending_buffer_done_cbs();
1157 if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING))
1158 {
1159 DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE Success");
1160 // Send the callback now
1161 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1162 pThis->m_state = OMX_StateIdle;
1163 DEBUG_PRINT_LOW("\n Move to Idle State");
1164 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1165 OMX_EventCmdComplete,OMX_CommandStateSet,
1166 OMX_StateIdle,NULL);
1167 }
1168 }
1169 }
1170 else
1171 {
1172 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1173 }
1174
1175 break;
1176
1177 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1178 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG");
1179 if (pThis->start_port_reconfig() != OMX_ErrorNone)
1180 pThis->omx_report_error();
1181 else
1182 {
1183 if (pThis->in_reconfig)
1184 {
1185 if (pThis->m_cb.EventHandler) {
1186 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1187 OMX_EventPortSettingsChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
1188 } else {
1189 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1190 }
1191 }
1192 if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1193 {
1194 OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1;
1195 OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged;
1196 if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
1197 format = OMX_InterlaceInterleaveFrameTopFieldFirst;
1198 else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
1199 format = OMX_InterlaceInterleaveFrameBottomFieldFirst;
1200 else //unsupported interlace format; raise a error
1201 event = OMX_EventError;
1202 if (pThis->m_cb.EventHandler) {
1203 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1204 event, format, 0, NULL );
1205 } else {
1206 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1207 }
1208 }
1209 }
1210 break;
1211
1212 case OMX_COMPONENT_GENERATE_EOS_DONE:
1213 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1214 if (pThis->m_cb.EventHandler) {
1215 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1216 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1217 } else {
1218 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1219 }
1220 pThis->prev_ts = LLONG_MAX;
1221 pThis->rst_prev_ts = true;
1222 break;
1223
1224 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1225 DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1226 pThis->omx_report_error ();
1227 break;
1228 case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG:
1229 {
1230 DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG");
1231 if (pThis->m_cb.EventHandler) {
1232 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1233 (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
1234 } else {
1235 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1236 }
1237 }
1238 default:
1239 break;
1240 }
1241 }
1242 pthread_mutex_lock(&pThis->m_lock);
1243 qsize = pThis->m_cmd_q.m_size;
1244 if (pThis->m_state != OMX_StatePause)
1245 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1246 pthread_mutex_unlock(&pThis->m_lock);
1247 }
1248 while(qsize>0);
1249
1250}
1251
Shalaj Jain273b3e02012-06-22 19:08:03 -07001252/* ======================================================================
1253FUNCTION
1254 omx_vdec::ComponentInit
1255
1256DESCRIPTION
1257 Initialize the component.
1258
1259PARAMETERS
1260 ctxt -- Context information related to the self.
1261 id -- Event identifier. This could be any of the following:
1262 1. Command completion event
1263 2. Buffer done callback event
1264 3. Frame done callback event
1265
1266RETURN VALUE
1267 None.
1268
1269========================================================================== */
1270OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
1271{
1272
1273 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1274 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
1275 struct v4l2_fmtdesc fdesc;
1276 struct v4l2_format fmt;
1277 struct v4l2_requestbuffers bufreq;
1278 unsigned int alignment = 0,buffer_size = 0;
1279 int fds[2];
1280 int r,ret=0;
1281 bool codec_ambiguous = false;
1282 OMX_STRING device_name = "/dev/video32";
1283
1284 drv_ctx.video_driver_fd = open("/dev/video32", O_RDWR);
1285
1286 DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Open returned fd %d, errno %d",
1287 drv_ctx.video_driver_fd, errno);
1288
1289 if(drv_ctx.video_driver_fd == 0){
1290 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
1291 }
1292
1293 if(drv_ctx.video_driver_fd < 0)
1294 {
1295 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d\n", errno);
1296 return OMX_ErrorInsufficientResources;
1297 }
1298 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
1299 drv_ctx.frame_rate.fps_denominator = 1;
1300
1301
1302#ifdef INPUT_BUFFER_LOG
1303 strcpy(inputfilename, INPUT_BUFFER_FILE_NAME);
1304#endif
1305#ifdef OUTPUT_BUFFER_LOG
1306 outputBufferFile1 = fopen (outputfilename, "ab");
1307#endif
1308#ifdef OUTPUT_EXTRADATA_LOG
1309 outputExtradataFile = fopen (ouputextradatafilename, "ab");
1310#endif
1311
1312 // Copy the role information which provides the decoder kind
1313 strlcpy(drv_ctx.kind,role,128);
1314 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
1315 OMX_MAX_STRINGNAME_SIZE))
1316 {
1317 strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
1318 OMX_MAX_STRINGNAME_SIZE);
1319 drv_ctx.timestamp_adjust = true;
1320 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
1321 eCompressionFormat = OMX_VIDEO_CodingMPEG4;
1322 /*Initialize Start Code for MPEG4*/
1323 codec_type_parse = CODEC_TYPE_MPEG4;
1324 m_frame_parser.init_start_codes (codec_type_parse);
1325#ifdef INPUT_BUFFER_LOG
1326 strcat(inputfilename, "m4v");
1327#endif
1328 }
1329 else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
1330 OMX_MAX_STRINGNAME_SIZE))
1331 {
1332 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
1333 OMX_MAX_STRINGNAME_SIZE);
1334 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
1335 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
1336 /*Initialize Start Code for MPEG2*/
1337 codec_type_parse = CODEC_TYPE_MPEG2;
1338 m_frame_parser.init_start_codes (codec_type_parse);
1339#ifdef INPUT_BUFFER_LOG
1340 strcat(inputfilename, "mpg");
1341#endif
1342 }
1343 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
1344 OMX_MAX_STRINGNAME_SIZE))
1345 {
1346 strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
1347 DEBUG_PRINT_LOW("\n H263 Decoder selected");
1348 drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
1349 eCompressionFormat = OMX_VIDEO_CodingH263;
1350 codec_type_parse = CODEC_TYPE_H263;
1351 m_frame_parser.init_start_codes (codec_type_parse);
1352#ifdef INPUT_BUFFER_LOG
1353 strcat(inputfilename, "263");
1354#endif
1355 }
1356 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
1357 OMX_MAX_STRINGNAME_SIZE))
1358 {
1359 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1360 DEBUG_PRINT_LOW ("\n DIVX 311 Decoder selected");
1361 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
1362 output_capability = V4L2_PIX_FMT_DIVX_311;
1363 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1364 codec_type_parse = CODEC_TYPE_DIVX;
1365 m_frame_parser.init_start_codes (codec_type_parse);
1366
1367 }
1368 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
1369 OMX_MAX_STRINGNAME_SIZE))
1370 {
1371 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1372 DEBUG_PRINT_ERROR ("\n DIVX 4 Decoder selected");
1373 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
1374 output_capability = V4L2_PIX_FMT_DIVX;
1375 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1376 codec_type_parse = CODEC_TYPE_DIVX;
1377 codec_ambiguous = true;
1378 m_frame_parser.init_start_codes (codec_type_parse);
1379
1380 }
1381 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
1382 OMX_MAX_STRINGNAME_SIZE))
1383 {
1384 strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
1385 DEBUG_PRINT_ERROR ("\n DIVX 5/6 Decoder selected");
1386 drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
1387 output_capability = V4L2_PIX_FMT_DIVX;
1388 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
1389 codec_type_parse = CODEC_TYPE_DIVX;
1390 codec_ambiguous = true;
1391 m_frame_parser.init_start_codes (codec_type_parse);
1392
1393 }
1394 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
1395 OMX_MAX_STRINGNAME_SIZE))
1396 {
1397 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
1398 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
1399 output_capability=V4L2_PIX_FMT_H264;
1400 eCompressionFormat = OMX_VIDEO_CodingAVC;
1401 codec_type_parse = CODEC_TYPE_H264;
1402 m_frame_parser.init_start_codes (codec_type_parse);
1403 m_frame_parser.init_nal_length(nal_length);
1404#ifdef INPUT_BUFFER_LOG
1405 strcat(inputfilename, "264");
1406#endif
1407 }
1408 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
1409 OMX_MAX_STRINGNAME_SIZE))
1410 {
1411 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1412 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
1413 eCompressionFormat = OMX_VIDEO_CodingWMV;
1414 codec_type_parse = CODEC_TYPE_VC1;
1415 m_frame_parser.init_start_codes (codec_type_parse);
1416#ifdef INPUT_BUFFER_LOG
1417 strcat(inputfilename, "vc1");
1418#endif
1419 }
1420 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
1421 OMX_MAX_STRINGNAME_SIZE))
1422 {
1423 strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
1424 drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
1425 eCompressionFormat = OMX_VIDEO_CodingWMV;
1426 codec_type_parse = CODEC_TYPE_VC1;
1427 m_frame_parser.init_start_codes (codec_type_parse);
1428#ifdef INPUT_BUFFER_LOG
1429 strcat(inputfilename, "vc1");
1430#endif
1431 }
1432 else
1433 {
1434 DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n");
1435 eRet = OMX_ErrorInvalidComponentName;
1436 }
1437#ifdef INPUT_BUFFER_LOG
1438 inputBufferFile1 = fopen (inputfilename, "ab");
1439#endif
1440 if (eRet == OMX_ErrorNone)
1441 {
1442
1443 drv_ctx.output_format = VDEC_YUV_FORMAT_TILE_4x2;
1444 capture_capability= V4L2_PIX_FMT_NV12;
Vinay Kalia85793762012-06-14 19:12:34 -07001445 ret = subscribe_to_events(drv_ctx.video_driver_fd);
Shalaj Jain273b3e02012-06-22 19:08:03 -07001446 if (ret) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001447 DEBUG_PRINT_ERROR("\n Subscribe Event Failed \n");
1448 return OMX_ErrorInsufficientResources;
Shalaj Jain273b3e02012-06-22 19:08:03 -07001449 }
1450
1451 struct v4l2_capability cap;
1452 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
1453 if (ret) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001454 DEBUG_PRINT_ERROR("Failed to query capabilities\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001455 /*TODO: How to handle this case */
1456 } else {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001457 DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
Shalaj Jain273b3e02012-06-22 19:08:03 -07001458 " version = %d, capabilities = %x\n", cap.driver, cap.card,
1459 cap.bus_info, cap.version, cap.capabilities);
1460 }
1461 ret=0;
1462 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1463 fdesc.index=0;
1464 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001465 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description,
Shalaj Jain273b3e02012-06-22 19:08:03 -07001466 fdesc.pixelformat, fdesc.flags);
1467 fdesc.index++;
1468 }
1469 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1470 fdesc.index=0;
1471 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
1472
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001473 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description,
Shalaj Jain273b3e02012-06-22 19:08:03 -07001474 fdesc.pixelformat, fdesc.flags);
1475 fdesc.index++;
1476 }
1477
1478 drv_ctx.video_resolution.frame_height=drv_ctx.video_resolution.scan_lines=240;
1479 drv_ctx.video_resolution.frame_width=drv_ctx.video_resolution.stride=320;
1480 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1481 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1482 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1483 fmt.fmt.pix_mp.pixelformat = output_capability;
1484 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1485 if (ret) {
1486 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001487 DEBUG_PRINT_ERROR("Failed to set format on output port\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001488 }
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001489 DEBUG_PRINT_HIGH("\n Set Format was successful \n ");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001490 if (codec_ambiguous) {
1491 if (output_capability == V4L2_PIX_FMT_DIVX) {
1492 struct v4l2_control divx_ctrl;
1493
1494 if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
1495 divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
1496 } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
1497 divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
1498 } else {
1499 divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
1500 }
1501
1502 divx_ctrl.value = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
1503 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &fmt);
1504 if (ret) {
1505 DEBUG_PRINT_ERROR("Failed to set divx version\n");
1506 }
1507 } else {
1508 DEBUG_PRINT_ERROR("Codec should not be ambiguous");
1509 }
1510 }
1511
1512 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1513 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
1514 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
1515 fmt.fmt.pix_mp.pixelformat = output_capability;
1516 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1517 if (ret) {
1518 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001519 DEBUG_PRINT_ERROR("Failed to set format on capture port\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001520 }
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001521 DEBUG_PRINT_HIGH("\n Set Format was successful \n ");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001522
1523 /*Get the Buffer requirements for input and output ports*/
1524 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
1525 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
1526 drv_ctx.op_buf.alignment=4096;
1527 drv_ctx.ip_buf.alignment=4096;
1528 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
1529 drv_ctx.extradata = 0;
1530 drv_ctx.picture_order = VDEC_ORDER_DECODE;
1531 drv_ctx.idr_only_decoding = 0;
1532
1533 m_state = OMX_StateLoaded;
1534 eRet=get_buffer_req(&drv_ctx.ip_buf);
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001535 DEBUG_PRINT_HIGH("Input Buffer Size =%d \n ",drv_ctx.ip_buf.buffer_size);
Shalaj Jain273b3e02012-06-22 19:08:03 -07001536
1537#ifdef DEFAULT_EXTRADATA
1538 if (eRet == OMX_ErrorNone && !secure_mode)
1539 eRet = enable_extradata(DEFAULT_EXTRADATA);
1540#endif
1541 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
1542 {
1543 if (m_frame_parser.mutils == NULL)
1544 {
1545 m_frame_parser.mutils = new H264_Utils();
1546
1547 if (m_frame_parser.mutils == NULL)
1548 {
1549 DEBUG_PRINT_ERROR("\n parser utils Allocation failed ");
1550 eRet = OMX_ErrorInsufficientResources;
1551 }
1552 else
1553 {
1554 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
1555 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
1556 h264_scratch.nFilledLen = 0;
1557 h264_scratch.nOffset = 0;
1558
1559 if (h264_scratch.pBuffer == NULL)
1560 {
1561 DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed ");
1562 return OMX_ErrorInsufficientResources;
1563 }
1564 m_frame_parser.mutils->initialize_frame_checking_environment();
1565 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
1566 }
1567 }
1568
1569 h264_parser = new h264_stream_parser();
1570 if (!h264_parser)
1571 {
1572 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
1573 eRet = OMX_ErrorInsufficientResources;
1574 }
1575 }
1576
1577 if(pipe(fds))
1578 {
1579 DEBUG_PRINT_ERROR("pipe creation failed\n");
1580 eRet = OMX_ErrorInsufficientResources;
1581 }
1582 else
1583 {
1584 int temp1[2];
1585 if(fds[0] == 0 || fds[1] == 0)
1586 {
1587 if (pipe (temp1))
1588 {
1589 DEBUG_PRINT_ERROR("pipe creation failed\n");
1590 return OMX_ErrorInsufficientResources;
1591 }
1592 //close (fds[0]);
1593 //close (fds[1]);
1594 fds[0] = temp1 [0];
1595 fds[1] = temp1 [1];
1596 }
1597 m_pipe_in = fds[0];
1598 m_pipe_out = fds[1];
1599 r = pthread_create(&msg_thread_id,0,message_thread,this);
1600
1601 if(r < 0)
1602 {
1603 DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed");
1604 eRet = OMX_ErrorInsufficientResources;
1605 }
1606 }
1607 }
1608
1609 if (eRet != OMX_ErrorNone)
1610 {
1611 DEBUG_PRINT_ERROR("\n Component Init Failed");
1612 DEBUG_PRINT_HIGH("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
1613 (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
1614 NULL);
1615 DEBUG_PRINT_HIGH("\n Calling close() on Video Driver");
1616 close (drv_ctx.video_driver_fd);
1617 drv_ctx.video_driver_fd = -1;
1618 }
1619 else
1620 {
1621 DEBUG_PRINT_HIGH("\n omx_vdec::component_init() success");
1622 }
1623
1624 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
1625 return eRet;
1626}
1627
1628/* ======================================================================
1629FUNCTION
1630 omx_vdec::GetComponentVersion
1631
1632DESCRIPTION
1633 Returns the component version.
1634
1635PARAMETERS
1636 TBD.
1637
1638RETURN VALUE
1639 OMX_ErrorNone.
1640
1641========================================================================== */
1642OMX_ERRORTYPE omx_vdec::get_component_version
1643 (
1644 OMX_IN OMX_HANDLETYPE hComp,
1645 OMX_OUT OMX_STRING componentName,
1646 OMX_OUT OMX_VERSIONTYPE* componentVersion,
1647 OMX_OUT OMX_VERSIONTYPE* specVersion,
1648 OMX_OUT OMX_UUIDTYPE* componentUUID
1649 )
1650{
1651 if(m_state == OMX_StateInvalid)
1652 {
1653 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n");
1654 return OMX_ErrorInvalidState;
1655 }
1656 /* TBD -- Return the proper version */
1657 if (specVersion)
1658 {
1659 specVersion->nVersion = OMX_SPEC_VERSION;
1660 }
1661 return OMX_ErrorNone;
1662}
1663/* ======================================================================
1664FUNCTION
1665 omx_vdec::SendCommand
1666
1667DESCRIPTION
1668 Returns zero if all the buffers released..
1669
1670PARAMETERS
1671 None.
1672
1673RETURN VALUE
1674 true/false
1675
1676========================================================================== */
1677OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
1678 OMX_IN OMX_COMMANDTYPE cmd,
1679 OMX_IN OMX_U32 param1,
1680 OMX_IN OMX_PTR cmdData
1681 )
1682{
1683 DEBUG_PRINT_LOW("\n send_command: Recieved a Command from Client");
1684 if(m_state == OMX_StateInvalid)
1685 {
1686 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
1687 return OMX_ErrorInvalidState;
1688 }
1689 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
1690 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL)
1691 {
1692 DEBUG_PRINT_ERROR("\n send_command(): ERROR OMX_CommandFlush "
1693 "to invalid port: %d", param1);
1694 return OMX_ErrorBadPortIndex;
1695 }
1696 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
1697 sem_wait(&m_cmd_lock);
1698 DEBUG_PRINT_LOW("\n send_command: Command Processed\n");
1699 return OMX_ErrorNone;
1700}
1701
1702/* ======================================================================
1703FUNCTION
1704 omx_vdec::SendCommand
1705
1706DESCRIPTION
1707 Returns zero if all the buffers released..
1708
1709PARAMETERS
1710 None.
1711
1712RETURN VALUE
1713 true/false
1714
1715========================================================================== */
1716OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
1717 OMX_IN OMX_COMMANDTYPE cmd,
1718 OMX_IN OMX_U32 param1,
1719 OMX_IN OMX_PTR cmdData
1720 )
1721{
1722 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1723 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
1724 int bFlag = 1,sem_posted = 0,ret=0;
1725
1726 DEBUG_PRINT_LOW("\n send_command_proxy(): cmd = %d", cmd);
1727 DEBUG_PRINT_HIGH("\n send_command_proxy(): Current State %d, Expected State %d",
1728 m_state, eState);
1729
1730 if(cmd == OMX_CommandStateSet)
1731 {
1732 DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandStateSet issued");
1733 DEBUG_PRINT_HIGH("\n Current State %d, Expected State %d", m_state, eState);
1734 /***************************/
1735 /* Current State is Loaded */
1736 /***************************/
1737 if(m_state == OMX_StateLoaded)
1738 {
1739 if(eState == OMX_StateIdle)
1740 {
1741 //if all buffers are allocated or all ports disabled
1742 if(allocate_done() ||
1743 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE))
1744 {
1745 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n");
1746 }
1747 else
1748 {
1749 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending\n");
1750 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
1751 // Skip the event notification
1752 bFlag = 0;
1753 }
1754 }
1755 /* Requesting transition from Loaded to Loaded */
1756 else if(eState == OMX_StateLoaded)
1757 {
1758 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded\n");
1759 post_event(OMX_EventError,OMX_ErrorSameState,\
1760 OMX_COMPONENT_GENERATE_EVENT);
1761 eRet = OMX_ErrorSameState;
1762 }
1763 /* Requesting transition from Loaded to WaitForResources */
1764 else if(eState == OMX_StateWaitForResources)
1765 {
1766 /* Since error is None , we will post an event
1767 at the end of this function definition */
1768 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources\n");
1769 }
1770 /* Requesting transition from Loaded to Executing */
1771 else if(eState == OMX_StateExecuting)
1772 {
1773 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n");
1774 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1775 OMX_COMPONENT_GENERATE_EVENT);
1776 eRet = OMX_ErrorIncorrectStateTransition;
1777 }
1778 /* Requesting transition from Loaded to Pause */
1779 else if(eState == OMX_StatePause)
1780 {
1781 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n");
1782 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1783 OMX_COMPONENT_GENERATE_EVENT);
1784 eRet = OMX_ErrorIncorrectStateTransition;
1785 }
1786 /* Requesting transition from Loaded to Invalid */
1787 else if(eState == OMX_StateInvalid)
1788 {
1789 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n");
1790 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1791 eRet = OMX_ErrorInvalidState;
1792 }
1793 else
1794 {
1795 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\
1796 eState);
1797 eRet = OMX_ErrorBadParameter;
1798 }
1799 }
1800
1801 /***************************/
1802 /* Current State is IDLE */
1803 /***************************/
1804 else if(m_state == OMX_StateIdle)
1805 {
1806 if(eState == OMX_StateLoaded)
1807 {
1808 if(release_done())
1809 {
1810 /*
1811 Since error is None , we will post an event at the end
1812 of this function definition
1813 */
1814 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded\n");
1815 }
1816 else
1817 {
1818 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending\n");
1819 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
1820 // Skip the event notification
1821 bFlag = 0;
1822 }
1823 }
1824 /* Requesting transition from Idle to Executing */
1825 else if(eState == OMX_StateExecuting)
1826 {
1827 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
1828 //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
1829 bFlag = 1;
1830 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
1831 m_state=OMX_StateExecuting;
Ashray Kulkarni46373df2012-06-05 20:11:31 -07001832 DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07001833 }
1834 /* Requesting transition from Idle to Idle */
1835 else if(eState == OMX_StateIdle)
1836 {
1837 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n");
1838 post_event(OMX_EventError,OMX_ErrorSameState,\
1839 OMX_COMPONENT_GENERATE_EVENT);
1840 eRet = OMX_ErrorSameState;
1841 }
1842 /* Requesting transition from Idle to WaitForResources */
1843 else if(eState == OMX_StateWaitForResources)
1844 {
1845 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n");
1846 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1847 OMX_COMPONENT_GENERATE_EVENT);
1848 eRet = OMX_ErrorIncorrectStateTransition;
1849 }
1850 /* Requesting transition from Idle to Pause */
1851 else if(eState == OMX_StatePause)
1852 {
1853 /*To pause the Video core we need to start the driver*/
1854 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
1855 NULL) < */0)
1856 {
1857 DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED");
1858 omx_report_error ();
1859 eRet = OMX_ErrorHardware;
1860 }
1861 else
1862 {
1863 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
1864 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n");
1865 bFlag = 0;
1866 }
1867 }
1868 /* Requesting transition from Idle to Invalid */
1869 else if(eState == OMX_StateInvalid)
1870 {
1871 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n");
1872 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1873 eRet = OMX_ErrorInvalidState;
1874 }
1875 else
1876 {
1877 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState);
1878 eRet = OMX_ErrorBadParameter;
1879 }
1880 }
1881
1882 /******************************/
1883 /* Current State is Executing */
1884 /******************************/
1885 else if(m_state == OMX_StateExecuting)
1886 {
1887 DEBUG_PRINT_LOW("\n Command Recieved in OMX_StateExecuting");
1888 /* Requesting transition from Executing to Idle */
1889 if(eState == OMX_StateIdle)
Vinay Kalia85793762012-06-14 19:12:34 -07001890 {
1891 /* Since error is None , we will post an event
1892 at the end of this function definition
1893 */
1894 DEBUG_PRINT_LOW("\n send_command_proxy(): Executing --> Idle \n");
1895 //BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
1896 if(!sem_posted)
1897 {
1898 sem_posted = 1;
1899 sem_post (&m_cmd_lock);
1900 execute_omx_flush(OMX_ALL);
1901 }
1902 bFlag = 1;
1903 int rc=0;
1904 enum v4l2_buf_type btype;
1905 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1906 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
1907 if (rc) {
1908 /*TODO: How to handle this case */
1909 DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n");
1910 } else {
1911 streaming[OUTPUT_PORT] = false;
1912 }
1913 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1914 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
1915 if (rc) {
1916 /*TODO: How to handle this case */
1917 DEBUG_PRINT_ERROR("\n Failed to call streamoff on CAPTURE Port \n");
1918 } else {
1919 streaming[CAPTURE_PORT] = false;
1920 }
1921 m_state = OMX_StateIdle;
1922 }
Shalaj Jain273b3e02012-06-22 19:08:03 -07001923 /* Requesting transition from Executing to Paused */
1924 else if(eState == OMX_StatePause)
1925 {
1926 DEBUG_PRINT_LOW("\n PAUSE Command Issued");
1927 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_PAUSE,
1928 NULL) < */0)
1929 {
1930 DEBUG_PRINT_ERROR("\n Error In Pause State");
1931 post_event(OMX_EventError,OMX_ErrorHardware,\
1932 OMX_COMPONENT_GENERATE_EVENT);
1933 eRet = OMX_ErrorHardware;
1934 }
1935 else
1936 {
1937 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
1938 DEBUG_PRINT_LOW("send_command_proxy(): Executing-->Pause\n");
1939 bFlag = 0;
1940 }
1941 }
1942 /* Requesting transition from Executing to Loaded */
1943 else if(eState == OMX_StateLoaded)
1944 {
1945 DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Loaded \n");
1946 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1947 OMX_COMPONENT_GENERATE_EVENT);
1948 eRet = OMX_ErrorIncorrectStateTransition;
1949 }
1950 /* Requesting transition from Executing to WaitForResources */
1951 else if(eState == OMX_StateWaitForResources)
1952 {
1953 DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> WaitForResources \n");
1954 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
1955 OMX_COMPONENT_GENERATE_EVENT);
1956 eRet = OMX_ErrorIncorrectStateTransition;
1957 }
1958 /* Requesting transition from Executing to Executing */
1959 else if(eState == OMX_StateExecuting)
1960 {
1961 DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Executing \n");
1962 post_event(OMX_EventError,OMX_ErrorSameState,\
1963 OMX_COMPONENT_GENERATE_EVENT);
1964 eRet = OMX_ErrorSameState;
1965 }
1966 /* Requesting transition from Executing to Invalid */
1967 else if(eState == OMX_StateInvalid)
1968 {
1969 DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Invalid \n");
1970 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
1971 eRet = OMX_ErrorInvalidState;
1972 }
1973 else
1974 {
1975 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState);
1976 eRet = OMX_ErrorBadParameter;
1977 }
1978 }
1979 /***************************/
1980 /* Current State is Pause */
1981 /***************************/
1982 else if(m_state == OMX_StatePause)
1983 {
1984 /* Requesting transition from Pause to Executing */
1985 if(eState == OMX_StateExecuting)
1986 {
1987 DEBUG_PRINT_LOW("\n Pause --> Executing \n");
1988 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_RESUME,
1989 NULL) < */0)
1990 {
1991 DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed");
1992 post_event(OMX_EventError,OMX_ErrorHardware,\
1993 OMX_COMPONENT_GENERATE_EVENT);
1994 eRet = OMX_ErrorHardware;
1995 }
1996 else
1997 {
1998 BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
1999 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
2000 post_event (NULL,VDEC_S_SUCCESS,\
2001 OMX_COMPONENT_GENERATE_RESUME_DONE);
2002 bFlag = 0;
2003 }
2004 }
2005 /* Requesting transition from Pause to Idle */
2006 else if(eState == OMX_StateIdle)
2007 {
2008 /* Since error is None , we will post an event
2009 at the end of this function definition */
2010 DEBUG_PRINT_LOW("\n Pause --> Idle \n");
2011 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2012 if(!sem_posted)
2013 {
2014 sem_posted = 1;
2015 sem_post (&m_cmd_lock);
2016 execute_omx_flush(OMX_ALL);
2017 }
2018 bFlag = 0;
2019 }
2020 /* Requesting transition from Pause to loaded */
2021 else if(eState == OMX_StateLoaded)
2022 {
2023 DEBUG_PRINT_ERROR("\n Pause --> loaded \n");
2024 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2025 OMX_COMPONENT_GENERATE_EVENT);
2026 eRet = OMX_ErrorIncorrectStateTransition;
2027 }
2028 /* Requesting transition from Pause to WaitForResources */
2029 else if(eState == OMX_StateWaitForResources)
2030 {
2031 DEBUG_PRINT_ERROR("\n Pause --> WaitForResources \n");
2032 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2033 OMX_COMPONENT_GENERATE_EVENT);
2034 eRet = OMX_ErrorIncorrectStateTransition;
2035 }
2036 /* Requesting transition from Pause to Pause */
2037 else if(eState == OMX_StatePause)
2038 {
2039 DEBUG_PRINT_ERROR("\n Pause --> Pause \n");
2040 post_event(OMX_EventError,OMX_ErrorSameState,\
2041 OMX_COMPONENT_GENERATE_EVENT);
2042 eRet = OMX_ErrorSameState;
2043 }
2044 /* Requesting transition from Pause to Invalid */
2045 else if(eState == OMX_StateInvalid)
2046 {
2047 DEBUG_PRINT_ERROR("\n Pause --> Invalid \n");
2048 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2049 eRet = OMX_ErrorInvalidState;
2050 }
2051 else
2052 {
2053 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState);
2054 eRet = OMX_ErrorBadParameter;
2055 }
2056 }
2057 /***************************/
2058 /* Current State is WaitForResources */
2059 /***************************/
2060 else if(m_state == OMX_StateWaitForResources)
2061 {
2062 /* Requesting transition from WaitForResources to Loaded */
2063 if(eState == OMX_StateLoaded)
2064 {
2065 /* Since error is None , we will post an event
2066 at the end of this function definition */
2067 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded\n");
2068 }
2069 /* Requesting transition from WaitForResources to WaitForResources */
2070 else if (eState == OMX_StateWaitForResources)
2071 {
2072 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n");
2073 post_event(OMX_EventError,OMX_ErrorSameState,
2074 OMX_COMPONENT_GENERATE_EVENT);
2075 eRet = OMX_ErrorSameState;
2076 }
2077 /* Requesting transition from WaitForResources to Executing */
2078 else if(eState == OMX_StateExecuting)
2079 {
2080 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n");
2081 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2082 OMX_COMPONENT_GENERATE_EVENT);
2083 eRet = OMX_ErrorIncorrectStateTransition;
2084 }
2085 /* Requesting transition from WaitForResources to Pause */
2086 else if(eState == OMX_StatePause)
2087 {
2088 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n");
2089 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2090 OMX_COMPONENT_GENERATE_EVENT);
2091 eRet = OMX_ErrorIncorrectStateTransition;
2092 }
2093 /* Requesting transition from WaitForResources to Invalid */
2094 else if(eState == OMX_StateInvalid)
2095 {
2096 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n");
2097 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2098 eRet = OMX_ErrorInvalidState;
2099 }
2100 /* Requesting transition from WaitForResources to Loaded -
2101 is NOT tested by Khronos TS */
2102
2103 }
2104 else
2105 {
2106 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState);
2107 eRet = OMX_ErrorBadParameter;
2108 }
2109 }
2110 /********************************/
2111 /* Current State is Invalid */
2112 /*******************************/
2113 else if(m_state == OMX_StateInvalid)
2114 {
2115 /* State Transition from Inavlid to any state */
2116 if(eState == (OMX_StateLoaded || OMX_StateWaitForResources
2117 || OMX_StateIdle || OMX_StateExecuting
2118 || OMX_StatePause || OMX_StateInvalid))
2119 {
2120 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n");
2121 post_event(OMX_EventError,OMX_ErrorInvalidState,\
2122 OMX_COMPONENT_GENERATE_EVENT);
2123 eRet = OMX_ErrorInvalidState;
2124 }
2125 }
2126 else if (cmd == OMX_CommandFlush)
2127 {
2128 DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued"
2129 "with param1: %d", param1);
2130 if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1)
2131 {
2132 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
2133 }
2134 if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1)
2135 {
2136 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
2137 }
2138 if (!sem_posted){
2139 sem_posted = 1;
2140 DEBUG_PRINT_LOW("\n Set the Semaphore");
2141 sem_post (&m_cmd_lock);
2142 execute_omx_flush(param1);
2143 }
2144 bFlag = 0;
2145 }
2146 else if ( cmd == OMX_CommandPortEnable)
2147 {
2148 DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortEnable issued"
2149 "with param1: %d", param1);
2150 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
2151 {
2152 m_inp_bEnabled = OMX_TRUE;
2153
2154 if( (m_state == OMX_StateLoaded &&
2155 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2156 || allocate_input_done())
2157 {
2158 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
2159 OMX_COMPONENT_GENERATE_EVENT);
2160 }
2161 else
2162 {
2163 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
2164 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
2165 // Skip the event notification
2166 bFlag = 0;
2167 }
2168 }
2169 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
2170 {
2171 DEBUG_PRINT_LOW("\n Enable output Port command recieved");
2172 m_out_bEnabled = OMX_TRUE;
2173
2174 if( (m_state == OMX_StateLoaded &&
2175 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
2176 || (allocate_output_done()))
2177 {
2178 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
2179 OMX_COMPONENT_GENERATE_EVENT);
2180
2181 }
2182 else
2183 {
2184 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
2185 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
2186 // Skip the event notification
2187 bFlag = 0;
2188 }
2189 }
2190 }
2191 else if (cmd == OMX_CommandPortDisable)
2192 {
2193 DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued"
2194 "with param1: %d", param1);
2195 if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
2196 {
2197 m_inp_bEnabled = OMX_FALSE;
2198 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2199 && release_input_done())
2200 {
2201 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
2202 OMX_COMPONENT_GENERATE_EVENT);
2203 }
2204 else
2205 {
2206 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
2207 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
2208 {
2209 if(!sem_posted)
2210 {
2211 sem_posted = 1;
2212 sem_post (&m_cmd_lock);
2213 }
2214 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
2215 }
2216
2217 // Skip the event notification
2218 bFlag = 0;
2219 }
2220 }
2221 if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
2222 {
2223 m_out_bEnabled = OMX_FALSE;
2224 DEBUG_PRINT_LOW("\n Disable output Port command recieved");
2225 if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
2226 && release_output_done())
2227 {
2228 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
2229 OMX_COMPONENT_GENERATE_EVENT);
2230 }
2231 else
2232 {
2233 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
2234 if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
2235 {
2236 if (!sem_posted)
2237 {
2238 sem_posted = 1;
2239 sem_post (&m_cmd_lock);
2240 }
2241 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
2242 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
2243 }
2244 // Skip the event notification
2245 bFlag = 0;
2246
2247 }
2248 }
2249 }
2250 else
2251 {
2252 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd);
2253 eRet = OMX_ErrorNotImplemented;
2254 }
2255 if(eRet == OMX_ErrorNone && bFlag)
2256 {
2257 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
2258 }
2259 if(!sem_posted)
2260 {
2261 sem_post(&m_cmd_lock);
2262 }
2263
2264 return eRet;
2265}
2266
2267/* ======================================================================
2268FUNCTION
2269 omx_vdec::ExecuteOmxFlush
2270
2271DESCRIPTION
2272 Executes the OMX flush.
2273
2274PARAMETERS
2275 flushtype - input flush(1)/output flush(0)/ both.
2276
2277RETURN VALUE
2278 true/false
2279
2280========================================================================== */
2281bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
2282{
2283 struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
2284 enum vdec_bufferflush flush_dir;
2285 bool bRet = false;
2286 switch (flushType)
2287 {
2288 case OMX_CORE_INPUT_PORT_INDEX:
2289 input_flush_progress = true;
2290 flush_dir = VDEC_FLUSH_TYPE_INPUT;
2291 break;
2292 case OMX_CORE_OUTPUT_PORT_INDEX:
2293 output_flush_progress = true;
2294 flush_dir = VDEC_FLUSH_TYPE_OUTPUT;
2295 break;
2296 default:
2297 input_flush_progress = true;
2298 output_flush_progress = true;
2299 flush_dir = VDEC_FLUSH_TYPE_ALL;
2300 }
2301 ioctl_msg.in = &flush_dir;
2302 ioctl_msg.out = NULL;
2303 if (/*ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_CMD_FLUSH, &ioctl_msg) < */0)
2304 {
2305 DEBUG_PRINT_ERROR("\n Flush Port (%d) Failed ", (int)flush_dir);
2306 bRet = false;
2307 }
2308 return bRet;
2309}
2310/*=========================================================================
2311FUNCTION : execute_output_flush
2312
2313DESCRIPTION
2314 Executes the OMX flush at OUTPUT PORT.
2315
2316PARAMETERS
2317 None.
2318
2319RETURN VALUE
2320 true/false
2321==========================================================================*/
2322bool omx_vdec::execute_output_flush()
2323{
2324 unsigned p1 = 0; // Parameter - 1
2325 unsigned p2 = 0; // Parameter - 2
2326 unsigned ident = 0;
2327 bool bRet = true;
2328
2329 /*Generate FBD for all Buffers in the FTBq*/
2330 pthread_mutex_lock(&m_lock);
2331 DEBUG_PRINT_LOW("\n Initiate Output Flush");
2332 while (m_ftb_q.m_size)
2333 {
2334 DEBUG_PRINT_LOW("\n Buffer queue size %d pending buf cnt %d",
2335 m_ftb_q.m_size,pending_output_buffers);
2336 m_ftb_q.pop_entry(&p1,&p2,&ident);
2337 DEBUG_PRINT_LOW("\n ID(%x) P1(%x) P2(%x)", ident, p1, p2);
2338 if(ident == OMX_COMPONENT_GENERATE_FTB )
2339 {
2340 pending_output_buffers++;
2341 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2342 }
2343 else if (ident == OMX_COMPONENT_GENERATE_FBD)
2344 {
2345 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2346 }
2347 }
2348 pthread_mutex_unlock(&m_lock);
2349 output_flush_progress = false;
2350
2351 if (arbitrary_bytes)
2352 {
2353 prev_ts = LLONG_MAX;
2354 rst_prev_ts = true;
2355 }
2356 DEBUG_PRINT_HIGH("\n OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
2357 return bRet;
2358}
2359/*=========================================================================
2360FUNCTION : execute_input_flush
2361
2362DESCRIPTION
2363 Executes the OMX flush at INPUT PORT.
2364
2365PARAMETERS
2366 None.
2367
2368RETURN VALUE
2369 true/false
2370==========================================================================*/
2371bool omx_vdec::execute_input_flush()
2372{
2373 unsigned i =0;
2374 unsigned p1 = 0; // Parameter - 1
2375 unsigned p2 = 0; // Parameter - 2
2376 unsigned ident = 0;
2377 bool bRet = true;
2378
2379 /*Generate EBD for all Buffers in the ETBq*/
2380 DEBUG_PRINT_LOW("\n Initiate Input Flush \n");
2381
2382 pthread_mutex_lock(&m_lock);
2383 DEBUG_PRINT_LOW("\n Check if the Queue is empty \n");
2384 while (m_etb_q.m_size)
2385 {
2386 m_etb_q.pop_entry(&p1,&p2,&ident);
2387
2388 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
2389 {
2390 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
2391 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
2392 }
2393 else if(ident == OMX_COMPONENT_GENERATE_ETB)
2394 {
2395 pending_input_buffers++;
2396 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
2397 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
2398 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
2399 }
2400 else if (ident == OMX_COMPONENT_GENERATE_EBD)
2401 {
2402 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
2403 (OMX_BUFFERHEADERTYPE *)p1);
2404 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
2405 }
2406 }
2407 time_stamp_dts.flush_timestamp();
2408 /*Check if Heap Buffers are to be flushed*/
2409 if (arbitrary_bytes)
2410 {
2411 DEBUG_PRINT_LOW("\n Reset all the variables before flusing");
2412 h264_scratch.nFilledLen = 0;
2413 nal_count = 0;
2414 look_ahead_nal = false;
2415 frame_count = 0;
2416 h264_last_au_ts = LLONG_MAX;
2417 h264_last_au_flags = 0;
2418 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
2419 m_demux_entries = 0;
2420 DEBUG_PRINT_LOW("\n Initialize parser");
2421 if (m_frame_parser.mutils)
2422 {
2423 m_frame_parser.mutils->initialize_frame_checking_environment();
2424 }
2425
2426 while (m_input_pending_q.m_size)
2427 {
2428 m_input_pending_q.pop_entry(&p1,&p2,&ident);
2429 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
2430 }
2431
2432 if (psource_frame)
2433 {
2434 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
2435 psource_frame = NULL;
2436 }
2437
2438 if (pdest_frame)
2439 {
2440 pdest_frame->nFilledLen = 0;
2441 m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
2442 pdest_frame = NULL;
2443 }
2444 m_frame_parser.flush();
2445 }
2446 pthread_mutex_unlock(&m_lock);
2447 input_flush_progress = false;
2448 if (!arbitrary_bytes)
2449 {
2450 prev_ts = LLONG_MAX;
2451 rst_prev_ts = true;
2452 }
2453#ifdef _ANDROID_
2454 if (m_debug_timestamp)
2455 {
2456 m_timestamp_list.reset_ts_list();
2457 }
2458#endif
2459 DEBUG_PRINT_HIGH("\n OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
2460 return bRet;
2461}
2462
2463
2464/* ======================================================================
2465FUNCTION
2466 omx_vdec::SendCommandEvent
2467
2468DESCRIPTION
2469 Send the event to decoder pipe. This is needed to generate the callbacks
2470 in decoder thread context.
2471
2472PARAMETERS
2473 None.
2474
2475RETURN VALUE
2476 true/false
2477
2478========================================================================== */
2479bool omx_vdec::post_event(unsigned int p1,
2480 unsigned int p2,
2481 unsigned int id)
2482{
2483 bool bRet = false;
2484
2485
2486 pthread_mutex_lock(&m_lock);
2487
2488 if (id == OMX_COMPONENT_GENERATE_FTB ||
2489 id == OMX_COMPONENT_GENERATE_FBD)
2490 {
2491 m_ftb_q.insert_entry(p1,p2,id);
2492 }
2493 else if (id == OMX_COMPONENT_GENERATE_ETB ||
2494 id == OMX_COMPONENT_GENERATE_EBD ||
2495 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
2496 {
2497 m_etb_q.insert_entry(p1,p2,id);
2498 }
2499 else
2500 {
2501 m_cmd_q.insert_entry(p1,p2,id);
2502 }
2503
2504 bRet = true;
2505 DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this);
2506 post_message(this, id);
2507
2508 pthread_mutex_unlock(&m_lock);
2509
2510 return bRet;
2511}
2512
2513OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
2514{
2515 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2516 if(!profileLevelType)
2517 return OMX_ErrorBadParameter;
2518
2519 if(profileLevelType->nPortIndex == 0) {
2520 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
2521 {
2522 if (profileLevelType->nProfileIndex == 0)
2523 {
2524 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
2525 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2526
2527 }
2528 else if (profileLevelType->nProfileIndex == 1)
2529 {
2530 profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
2531 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2532 }
2533 else if(profileLevelType->nProfileIndex == 2)
2534 {
2535 profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
2536 profileLevelType->eLevel = OMX_VIDEO_AVCLevel4;
2537 }
2538 else
2539 {
2540 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
2541 profileLevelType->nProfileIndex);
2542 eRet = OMX_ErrorNoMore;
2543 }
2544 }
2545 else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)))
2546 {
2547 if (profileLevelType->nProfileIndex == 0)
2548 {
2549 profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
2550 profileLevelType->eLevel = OMX_VIDEO_H263Level70;
2551 }
2552 else
2553 {
2554 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
2555 eRet = OMX_ErrorNoMore;
2556 }
2557 }
2558 else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
2559 {
2560 if (profileLevelType->nProfileIndex == 0)
2561 {
2562 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2563 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2564 }
2565 else if(profileLevelType->nProfileIndex == 1)
2566 {
2567 profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2568 profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
2569 }
2570 else
2571 {
2572 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
2573 eRet = OMX_ErrorNoMore;
2574 }
2575 }
2576 else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
2577 {
2578 if (profileLevelType->nProfileIndex == 0)
2579 {
2580 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
2581 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2582 }
2583 else if(profileLevelType->nProfileIndex == 1)
2584 {
2585 profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
2586 profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL;
2587 }
2588 else
2589 {
2590 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
2591 eRet = OMX_ErrorNoMore;
2592 }
2593 }
2594 }
2595 else
2596 {
2597 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex);
2598 eRet = OMX_ErrorBadPortIndex;
2599 }
2600 return eRet;
2601}
2602
2603/* ======================================================================
2604FUNCTION
2605 omx_vdec::GetParameter
2606
2607DESCRIPTION
2608 OMX Get Parameter method implementation
2609
2610PARAMETERS
2611 <TBD>.
2612
2613RETURN VALUE
2614 Error None if successful.
2615
2616========================================================================== */
2617OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
2618 OMX_IN OMX_INDEXTYPE paramIndex,
2619 OMX_INOUT OMX_PTR paramData)
2620{
2621 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2622
2623 DEBUG_PRINT_LOW("get_parameter: \n");
2624 if(m_state == OMX_StateInvalid)
2625 {
2626 DEBUG_PRINT_ERROR("Get Param in Invalid State\n");
2627 return OMX_ErrorInvalidState;
2628 }
2629 if(paramData == NULL)
2630 {
2631 DEBUG_PRINT_LOW("Get Param in Invalid paramData \n");
2632 return OMX_ErrorBadParameter;
2633 }
2634 switch(paramIndex)
2635 {
2636 case OMX_IndexParamPortDefinition:
2637 {
2638 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
2639 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2640 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
2641 eRet = update_portdef(portDefn);
2642 if (eRet == OMX_ErrorNone)
2643 m_port_def = *portDefn;
2644 break;
2645 }
2646 case OMX_IndexParamVideoInit:
2647 {
2648 OMX_PORT_PARAM_TYPE *portParamType =
2649 (OMX_PORT_PARAM_TYPE *) paramData;
2650 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");
2651
2652 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2653 portParamType->nSize = sizeof(portParamType);
2654 portParamType->nPorts = 2;
2655 portParamType->nStartPortNumber = 0;
2656 break;
2657 }
2658 case OMX_IndexParamVideoPortFormat:
2659 {
2660 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
2661 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
2662 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n");
2663
2664 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
2665 portFmt->nSize = sizeof(portFmt);
2666
2667 if (0 == portFmt->nPortIndex)
2668 {
2669 if (0 == portFmt->nIndex)
2670 {
2671 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
2672 portFmt->eCompressionFormat = eCompressionFormat;
2673 }
2674 else
2675 {
2676 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
2677 " NoMore compression formats\n");
2678 eRet = OMX_ErrorNoMore;
2679 }
2680 }
2681 else if (1 == portFmt->nPortIndex)
2682 {
2683 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
2684
2685 if(0 == portFmt->nIndex)
2686 portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
2687 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
2688 else
2689 {
2690 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
2691 " NoMore Color formats\n");
2692 eRet = OMX_ErrorNoMore;
2693 }
2694 portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2695 }
2696 else
2697 {
2698 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n",
2699 (int)portFmt->nPortIndex);
2700 eRet = OMX_ErrorBadPortIndex;
2701 }
2702 break;
2703 }
2704 /*Component should support this port definition*/
2705 case OMX_IndexParamAudioInit:
2706 {
2707 OMX_PORT_PARAM_TYPE *audioPortParamType =
2708 (OMX_PORT_PARAM_TYPE *) paramData;
2709 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n");
2710 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2711 audioPortParamType->nSize = sizeof(audioPortParamType);
2712 audioPortParamType->nPorts = 0;
2713 audioPortParamType->nStartPortNumber = 0;
2714 break;
2715 }
2716 /*Component should support this port definition*/
2717 case OMX_IndexParamImageInit:
2718 {
2719 OMX_PORT_PARAM_TYPE *imagePortParamType =
2720 (OMX_PORT_PARAM_TYPE *) paramData;
2721 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n");
2722 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
2723 imagePortParamType->nSize = sizeof(imagePortParamType);
2724 imagePortParamType->nPorts = 0;
2725 imagePortParamType->nStartPortNumber = 0;
2726 break;
2727
2728 }
2729 /*Component should support this port definition*/
2730 case OMX_IndexParamOtherInit:
2731 {
2732 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n",
2733 paramIndex);
2734 eRet =OMX_ErrorUnsupportedIndex;
2735 break;
2736 }
2737 case OMX_IndexParamStandardComponentRole:
2738 {
2739 OMX_PARAM_COMPONENTROLETYPE *comp_role;
2740 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
2741 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
2742 comp_role->nSize = sizeof(*comp_role);
2743
2744 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",
2745 paramIndex);
2746 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
2747 OMX_MAX_STRINGNAME_SIZE);
2748 break;
2749 }
2750 /* Added for parameter test */
2751 case OMX_IndexParamPriorityMgmt:
2752 {
2753
2754 OMX_PRIORITYMGMTTYPE *priorityMgmType =
2755 (OMX_PRIORITYMGMTTYPE *) paramData;
2756 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
2757 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
2758 priorityMgmType->nSize = sizeof(priorityMgmType);
2759
2760 break;
2761 }
2762 /* Added for parameter test */
2763 case OMX_IndexParamCompBufferSupplier:
2764 {
2765 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
2766 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
2767 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");
2768
2769 bufferSupplierType->nSize = sizeof(bufferSupplierType);
2770 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
2771 if(0 == bufferSupplierType->nPortIndex)
2772 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2773 else if (1 == bufferSupplierType->nPortIndex)
2774 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
2775 else
2776 eRet = OMX_ErrorBadPortIndex;
2777
2778
2779 break;
2780 }
2781 case OMX_IndexParamVideoAvc:
2782 {
2783 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n",
2784 paramIndex);
2785 break;
2786 }
2787 case OMX_IndexParamVideoH263:
2788 {
2789 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n",
2790 paramIndex);
2791 break;
2792 }
2793 case OMX_IndexParamVideoMpeg4:
2794 {
2795 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x\n",
2796 paramIndex);
2797 break;
2798 }
2799 case OMX_IndexParamVideoMpeg2:
2800 {
2801 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x\n",
2802 paramIndex);
2803 break;
2804 }
2805 case OMX_IndexParamVideoProfileLevelQuerySupported:
2806 {
2807 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n", paramIndex);
2808 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
2809 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
2810 eRet = get_supported_profile_level_for_1080p(profileLevelType);
2811 break;
2812 }
2813#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
2814 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
2815 {
2816 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage\n");
2817 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
2818 if(nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
2819
2820 if(secure_mode) {
2821 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
2822 GRALLOC_USAGE_PRIVATE_UNCACHED);
2823 } else {
2824 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
2825 }
2826 } else {
2827 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!\n");
2828 eRet = OMX_ErrorBadParameter;
2829 }
2830 }
2831 break;
2832#endif
2833
2834 default:
2835 {
2836 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex);
2837 eRet =OMX_ErrorUnsupportedIndex;
2838 }
2839
2840 }
2841
2842 DEBUG_PRINT_LOW("\n get_parameter returning WxH(%d x %d) SxSH(%d x %d)\n",
2843 drv_ctx.video_resolution.frame_width,
2844 drv_ctx.video_resolution.frame_height,
2845 drv_ctx.video_resolution.stride,
2846 drv_ctx.video_resolution.scan_lines);
2847
2848 return eRet;
2849}
2850
2851#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
2852OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
2853{
2854 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
2855 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2856 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
2857
2858 if((params == NULL) ||
2859 (params->nativeBuffer == NULL) ||
2860 (params->nativeBuffer->handle == NULL) ||
2861 !m_enable_android_native_buffers)
2862 return OMX_ErrorBadParameter;
2863 m_use_android_native_buffers = OMX_TRUE;
2864 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
2865 private_handle_t *handle = (private_handle_t *)nBuf->handle;
2866 if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
2867 OMX_U8 *buffer = NULL;
2868 if(!secure_mode) {
2869 buffer = (OMX_U8*)mmap(0, handle->size,
2870 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
2871 if(buffer == MAP_FAILED) {
2872 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
2873 return OMX_ErrorInsufficientResources;
2874 }
2875 }
2876 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
2877 } else {
2878 eRet = OMX_ErrorBadParameter;
2879 }
2880 return eRet;
2881}
2882#endif
2883/* ======================================================================
2884FUNCTION
2885 omx_vdec::Setparameter
2886
2887DESCRIPTION
2888 OMX Set Parameter method implementation.
2889
2890PARAMETERS
2891 <TBD>.
2892
2893RETURN VALUE
2894 OMX Error None if successful.
2895
2896========================================================================== */
2897OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
2898 OMX_IN OMX_INDEXTYPE paramIndex,
2899 OMX_IN OMX_PTR paramData)
2900{
2901 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2902 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
2903
2904 if(m_state == OMX_StateInvalid)
2905 {
2906 DEBUG_PRINT_ERROR("Set Param in Invalid State\n");
2907 return OMX_ErrorInvalidState;
2908 }
2909 if(paramData == NULL)
2910 {
2911 DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n");
2912 return OMX_ErrorBadParameter;
2913 }
2914 if((m_state != OMX_StateLoaded) &&
2915 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
2916 (m_out_bEnabled == OMX_TRUE) &&
2917 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
2918 (m_inp_bEnabled == OMX_TRUE)) {
2919 DEBUG_PRINT_ERROR("Set Param in Invalid State \n");
2920 return OMX_ErrorIncorrectStateOperation;
2921 }
2922 switch(paramIndex)
2923 {
2924 case OMX_IndexParamPortDefinition:
2925 {
2926 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
2927 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
2928 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
2929 //been called.
2930 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
2931 (int)portDefn->format.video.nFrameHeight,
2932 (int)portDefn->format.video.nFrameWidth);
2933 if(OMX_DirOutput == portDefn->eDir)
2934 {
2935 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port\n");
2936 m_display_id = portDefn->format.video.pNativeWindow;
2937 if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
2938 portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size )
2939 {
2940 drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
2941 drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
2942 eRet = set_buffer_req(&drv_ctx.op_buf);
2943 if (eRet == OMX_ErrorNone)
2944 m_port_def = *portDefn;
2945 }
2946 else
2947 {
2948 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%d: %u)\n",
2949 drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size,
2950 portDefn->nBufferCountActual, portDefn->nBufferSize);
2951 eRet = OMX_ErrorBadParameter;
2952 }
2953 }
2954 else if(OMX_DirInput == portDefn->eDir)
2955 {
2956 if((portDefn->format.video.xFramerate >> 16) > 0 &&
2957 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS)
2958 {
2959 // Frame rate only should be set if this is a "known value" or to
2960 // activate ts prediction logic (arbitrary mode only) sending input
2961 // timestamps with max value (LLONG_MAX).
2962 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %d",
2963 portDefn->format.video.xFramerate >> 16);
2964 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
2965 drv_ctx.frame_rate.fps_denominator);
2966 if(!drv_ctx.frame_rate.fps_numerator)
2967 {
2968 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
2969 drv_ctx.frame_rate.fps_numerator = 30;
2970 }
2971 if(drv_ctx.frame_rate.fps_denominator)
2972 drv_ctx.frame_rate.fps_numerator = (int)
2973 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
2974 drv_ctx.frame_rate.fps_denominator = 1;
2975 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
2976 drv_ctx.frame_rate.fps_numerator;
2977 ioctl_msg.in = &drv_ctx.frame_rate;
2978 if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE,
2979 (void*)&ioctl_msg) < */0)
2980 {
2981 DEBUG_PRINT_ERROR("Setting frame rate to driver failed");
2982 }
2983 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
2984 frm_int, drv_ctx.frame_rate.fps_numerator /
2985 (float)drv_ctx.frame_rate.fps_denominator);
2986 }
2987 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port\n");
2988 if(drv_ctx.video_resolution.frame_height !=
2989 portDefn->format.video.nFrameHeight ||
2990 drv_ctx.video_resolution.frame_width !=
2991 portDefn->format.video.nFrameWidth)
2992 {
2993 DEBUG_PRINT_LOW("\n SetParam IP: WxH(%d x %d)\n",
2994 portDefn->format.video.nFrameWidth,
2995 portDefn->format.video.nFrameHeight);
2996 if (portDefn->format.video.nFrameHeight != 0x0 &&
2997 portDefn->format.video.nFrameWidth != 0x0)
2998 {
2999 drv_ctx.video_resolution.frame_height =
3000 drv_ctx.video_resolution.scan_lines =
3001 portDefn->format.video.nFrameHeight;
3002 drv_ctx.video_resolution.frame_width =
3003 drv_ctx.video_resolution.stride =
3004 portDefn->format.video.nFrameWidth;
3005 ioctl_msg.in = &drv_ctx.video_resolution;
3006 ioctl_msg.out = NULL;
3007 if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICRES,
3008 (void*)&ioctl_msg) < */0)
3009 {
3010 DEBUG_PRINT_ERROR("\n Set Resolution failed");
3011 eRet = OMX_ErrorUnsupportedSetting;
3012 }
3013 else
3014 eRet = get_buffer_req(&drv_ctx.op_buf);
3015 }
3016 }
3017 else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
3018 && portDefn->nBufferSize == drv_ctx.ip_buf.buffer_size)
3019 {
3020 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
3021 drv_ctx.ip_buf.buffer_size = portDefn->nBufferSize;
3022 eRet = set_buffer_req(&drv_ctx.ip_buf);
3023 }
3024 else
3025 {
3026 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%d: %u)\n",
3027 drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size,
3028 portDefn->nBufferCountActual, portDefn->nBufferSize);
3029 eRet = OMX_ErrorBadParameter;
3030 }
3031 }
3032 else if (portDefn->eDir == OMX_DirMax)
3033 {
3034 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
3035 (int)portDefn->nPortIndex);
3036 eRet = OMX_ErrorBadPortIndex;
3037 }
3038 }
3039 break;
3040 case OMX_IndexParamVideoPortFormat:
3041 {
3042 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3043 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3044 int ret=0;
3045 struct v4l2_format fmt;
3046 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
3047 portFmt->eColorFormat);
3048
3049 if(1 == portFmt->nPortIndex)
3050 {
3051 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3052 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
3053 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
3054 fmt.fmt.pix_mp.pixelformat = capture_capability;
3055 enum vdec_output_fromat op_format;
3056 if(portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
3057 op_format = VDEC_YUV_FORMAT_NV12;
3058 else if(portFmt->eColorFormat ==
3059 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka)
3060 op_format = VDEC_YUV_FORMAT_TILE_4x2;
3061 else
3062 eRet = OMX_ErrorBadParameter;
3063
3064 if(eRet == OMX_ErrorNone)
3065 {
3066 drv_ctx.output_format = op_format;
3067 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
3068 if(ret)
3069 {
3070 DEBUG_PRINT_ERROR("\n Set output format failed");
3071 eRet = OMX_ErrorUnsupportedSetting;
3072 /*TODO: How to handle this case */
3073 }
3074 else
3075 {
3076 eRet = get_buffer_req(&drv_ctx.op_buf);
3077 }
3078 }
3079 }
3080 }
3081 break;
3082
3083 case OMX_QcomIndexPortDefn:
3084 {
3085 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
3086 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
3087 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n",
3088 portFmt->nFramePackingFormat);
3089
3090 /* Input port */
3091 if (portFmt->nPortIndex == 0)
3092 {
3093 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary)
3094 {
3095 if(secure_mode) {
3096 arbitrary_bytes = false;
3097 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session");
3098 eRet = OMX_ErrorUnsupportedSetting;
3099 } else {
3100 arbitrary_bytes = true;
3101 }
3102 }
3103 else if (portFmt->nFramePackingFormat ==
3104 OMX_QCOM_FramePacking_OnlyOneCompleteFrame)
3105 {
3106 arbitrary_bytes = false;
3107 }
3108 else
3109 {
3110 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %d\n",
3111 portFmt->nFramePackingFormat);
3112 eRet = OMX_ErrorUnsupportedSetting;
3113 }
3114 }
3115 else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX)
3116 {
3117 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port\n");
3118 if( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
3119 portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
3120 portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone)
3121 {
3122 m_out_mem_region_smi = OMX_TRUE;
3123 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem))
3124 {
3125 DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set\n");
3126 m_use_output_pmem = OMX_TRUE;
3127 }
3128 }
3129 }
3130 }
3131 break;
3132
3133 case OMX_IndexParamStandardComponentRole:
3134 {
3135 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3136 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3137 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n",
3138 comp_role->cRole);
3139
3140 if((m_state == OMX_StateLoaded)&&
3141 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3142 {
3143 DEBUG_PRINT_LOW("Set Parameter called in valid state");
3144 }
3145 else
3146 {
3147 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
3148 return OMX_ErrorIncorrectStateOperation;
3149 }
3150
3151 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
3152 {
3153 if(!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE))
3154 {
3155 strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
3156 }
3157 else
3158 {
3159 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3160 eRet =OMX_ErrorUnsupportedSetting;
3161 }
3162 }
3163 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
3164 {
3165 if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
3166 {
3167 strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
3168 }
3169 else
3170 {
3171 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3172 eRet = OMX_ErrorUnsupportedSetting;
3173 }
3174 }
3175 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
3176 {
3177 if(!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE))
3178 {
3179 strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
3180 }
3181 else
3182 {
3183 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3184 eRet =OMX_ErrorUnsupportedSetting;
3185 }
3186 }
3187 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
3188 {
3189 if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
3190 {
3191 strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
3192 }
3193 else
3194 {
3195 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3196 eRet = OMX_ErrorUnsupportedSetting;
3197 }
3198 }
3199 else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
3200 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
3201 )
3202 {
3203 if(!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE))
3204 {
3205 strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
3206 }
3207 else
3208 {
3209 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3210 eRet =OMX_ErrorUnsupportedSetting;
3211 }
3212 }
3213 else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
3214 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
3215 )
3216 {
3217 if(!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
3218 {
3219 strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
3220 }
3221 else
3222 {
3223 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
3224 eRet =OMX_ErrorUnsupportedSetting;
3225 }
3226 }
3227 else
3228 {
3229 DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", drv_ctx.kind);
3230 eRet = OMX_ErrorInvalidComponentName;
3231 }
3232 break;
3233 }
3234
3235 case OMX_IndexParamPriorityMgmt:
3236 {
3237 if(m_state != OMX_StateLoaded)
3238 {
3239 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
3240 return OMX_ErrorIncorrectStateOperation;
3241 }
3242 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
3243 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n",
3244 priorityMgmtype->nGroupID);
3245
3246 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n",
3247 priorityMgmtype->nGroupPriority);
3248
3249 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
3250 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
3251
3252 break;
3253 }
3254
3255 case OMX_IndexParamCompBufferSupplier:
3256 {
3257 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3258 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
3259 bufferSupplierType->eBufferSupplier);
3260 if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
3261 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
3262
3263 else
3264
3265 eRet = OMX_ErrorBadPortIndex;
3266
3267 break;
3268
3269 }
3270 case OMX_IndexParamVideoAvc:
3271 {
3272 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d\n",
3273 paramIndex);
3274 break;
3275 }
3276 case OMX_IndexParamVideoH263:
3277 {
3278 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d\n",
3279 paramIndex);
3280 break;
3281 }
3282 case OMX_IndexParamVideoMpeg4:
3283 {
3284 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d\n",
3285 paramIndex);
3286 break;
3287 }
3288 case OMX_IndexParamVideoMpeg2:
3289 {
3290 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d\n",
3291 paramIndex);
3292 break;
3293 }
3294 case OMX_QcomIndexParamVideoDecoderPictureOrder:
3295 {
3296 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
3297 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
3298 enum vdec_output_order pic_order = VDEC_ORDER_DISPLAY;
3299 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d\n",
3300 pictureOrder->eOutputPictureOrder);
3301 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER)
3302 pic_order = VDEC_ORDER_DISPLAY;
3303 else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER){
3304 pic_order = VDEC_ORDER_DECODE;
3305 time_stamp_dts.set_timestamp_reorder_mode(false);
3306 }
3307 else
3308 eRet = OMX_ErrorBadParameter;
3309
3310 if (eRet == OMX_ErrorNone && pic_order != drv_ctx.picture_order)
3311 {
3312 drv_ctx.picture_order = pic_order;
3313 // ioctl_msg.in = &drv_ctx.picture_order;
3314 //ioctl_msg.out = NULL;
3315 if (/*ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICTURE_ORDER,
3316 (void*)&ioctl_msg) < */0)
3317 {
3318 DEBUG_PRINT_ERROR("\n Set picture order failed");
3319 eRet = OMX_ErrorUnsupportedSetting;
3320 }
3321 }
3322 break;
3323 }
3324 case OMX_QcomIndexParamConcealMBMapExtraData:
3325 if(!secure_mode)
3326 eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP,
3327 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3328 else {
3329 DEBUG_PRINT_ERROR("\n secure mode setting not supported");
3330 eRet = OMX_ErrorUnsupportedSetting;
3331 }
3332 break;
3333 case OMX_QcomIndexParamFrameInfoExtraData:
3334 {
3335 if(!secure_mode)
3336 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA,
3337 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3338 else {
3339 DEBUG_PRINT_ERROR("\n secure mode setting not supported");
3340 eRet = OMX_ErrorUnsupportedSetting;
3341 }
3342 break;
3343 }
3344 case OMX_QcomIndexParamInterlaceExtraData:
3345 if(!secure_mode)
3346 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA,
3347 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3348 else {
3349 DEBUG_PRINT_ERROR("\n secure mode setting not supported");
3350 eRet = OMX_ErrorUnsupportedSetting;
3351 }
3352 break;
3353 case OMX_QcomIndexParamH264TimeInfo:
3354 if(!secure_mode)
3355 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA,
3356 ((QOMX_ENABLETYPE *)paramData)->bEnable);
3357 else {
3358 DEBUG_PRINT_ERROR("\n secure mode setting not supported");
3359 eRet = OMX_ErrorUnsupportedSetting;
3360 }
3361 break;
3362 case OMX_QcomIndexParamVideoDivx:
3363 {
3364 QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
3365
3366#if 0
3367 createDivxDrmContext( divXType->pDrmHandle );
3368#endif
3369 }
3370 break;
3371 case OMX_QcomIndexPlatformPvt:
3372 {
3373 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port\n");
3374 OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
3375 if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM)
3376 {
3377 DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
3378 eRet = OMX_ErrorUnsupportedSetting;
3379 }
3380 else
3381 {
3382 m_out_pvt_entry_pmem = OMX_TRUE;
3383 if ((m_out_mem_region_smi && m_out_pvt_entry_pmem))
3384 {
3385 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set\n");
3386 m_use_output_pmem = OMX_TRUE;
3387 }
3388 }
3389
3390 }
3391 break;
3392 case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
3393 {
3394 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
3395 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
3396 drv_ctx.idr_only_decoding = 1;
3397 int rc; //= ioctl(drv_ctx.video_driver_fd,
3398 // VDEC_IOCTL_SET_IDR_ONLY_DECODING);
3399 if(rc < 0) {
3400 DEBUG_PRINT_ERROR("Failed to set IDR only decoding on driver.");
3401 eRet = OMX_ErrorHardware;
3402 }
3403 }
3404 break;
3405
3406 case OMX_QcomIndexParamIndexExtraDataType:
3407 {
3408 if(!secure_mode) {
3409 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
3410 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
3411 (extradataIndexType->bEnabled == OMX_TRUE) &&
3412 (extradataIndexType->nPortIndex == 1))
3413 {
3414 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming\n");
3415 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, extradataIndexType->bEnabled);
3416 // Set smooth streaming parameter
3417 int rc;// = ioctl(drv_ctx.video_driver_fd,
3418 // VDEC_IOCTL_SET_CONT_ON_RECONFIG);
3419 if(rc < 0) {
3420 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
3421 eRet = OMX_ErrorHardware;
3422 }
3423 }
3424 }
3425 }
3426 break;
3427
3428#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3429 /* Need to allow following two set_parameters even in Idle
3430 * state. This is ANDROID architecture which is not in sync
3431 * with openmax standard. */
3432 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
3433 {
3434 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
3435 if(enableNativeBuffers) {
3436 m_enable_android_native_buffers = enableNativeBuffers->enable;
3437 }
3438 }
3439 break;
3440 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
3441 {
3442 eRet = use_android_native_buffer(hComp, paramData);
3443 }
3444 break;
3445#endif
3446 case OMX_QcomIndexParamEnableTimeStampReorder:
3447 {
3448 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
3449 if (drv_ctx.picture_order == QOMX_VIDEO_DISPLAY_ORDER) {
3450 if (reorder->bEnable == OMX_TRUE) {
3451 frm_int =0;
3452 time_stamp_dts.set_timestamp_reorder_mode(true);
3453 }
3454 else
3455 time_stamp_dts.set_timestamp_reorder_mode(false);
3456 } else {
3457 time_stamp_dts.set_timestamp_reorder_mode(false);
3458 if (reorder->bEnable == OMX_TRUE)
3459 {
3460 eRet = OMX_ErrorUnsupportedSetting;
3461 }
3462 }
3463 }
3464 break;
3465 default:
3466 {
3467 DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex);
3468 eRet = OMX_ErrorUnsupportedIndex;
3469 }
3470 }
3471 return eRet;
3472}
3473
3474/* ======================================================================
3475FUNCTION
3476 omx_vdec::GetConfig
3477
3478DESCRIPTION
3479 OMX Get Config Method implementation.
3480
3481PARAMETERS
3482 <TBD>.
3483
3484RETURN VALUE
3485 OMX Error None if successful.
3486
3487========================================================================== */
3488OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
3489 OMX_IN OMX_INDEXTYPE configIndex,
3490 OMX_INOUT OMX_PTR configData)
3491{
3492 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3493
3494 if (m_state == OMX_StateInvalid)
3495 {
3496 DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
3497 return OMX_ErrorInvalidState;
3498 }
3499
3500 switch (configIndex)
3501 {
3502 case OMX_QcomIndexConfigInterlaced:
3503 {
3504 OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
3505 (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
3506 if (configFmt->nPortIndex == 1)
3507 {
3508 if (configFmt->nIndex == 0)
3509 {
3510 configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
3511 }
3512 else if (configFmt->nIndex == 1)
3513 {
3514 configFmt->eInterlaceType =
3515 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
3516 }
3517 else if (configFmt->nIndex == 2)
3518 {
3519 configFmt->eInterlaceType =
3520 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
3521 }
3522 else
3523 {
3524 DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
3525 " NoMore Interlaced formats\n");
3526 eRet = OMX_ErrorNoMore;
3527 }
3528
3529 }
3530 else
3531 {
3532 DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port\n",
3533 (int)configFmt->nPortIndex);
3534 eRet = OMX_ErrorBadPortIndex;
3535 }
3536 break;
3537 }
3538 case OMX_QcomIndexQueryNumberOfVideoDecInstance:
3539 {
3540 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
3541 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
3542 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
3543 //ioctl_msg.out = (void*)&decoderinstances->nNumOfInstances;
3544 //(void)(ioctl(drv_ctx.video_driver_fd,
3545 //VDEC_IOCTL_GET_NUMBER_INSTANCES,&ioctl_msg));
3546
3547 decoderinstances->nNumOfInstances = 16;
3548 /*TODO: How to handle this case */
3549 break;
3550 }
3551 case OMX_QcomIndexConfigVideoFramePackingArrangement:
3552 {
3553 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
3554 {
3555 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
3556 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
3557 h264_parser->get_frame_pack_data(configFmt);
3558 }
3559 else
3560 {
3561 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
3562 }
3563 break;
3564 }
3565 default:
3566 {
3567 DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex);
3568 eRet = OMX_ErrorBadParameter;
3569 }
3570
3571 }
3572
3573 return eRet;
3574}
3575
3576/* ======================================================================
3577FUNCTION
3578 omx_vdec::SetConfig
3579
3580DESCRIPTION
3581 OMX Set Config method implementation
3582
3583PARAMETERS
3584 <TBD>.
3585
3586RETURN VALUE
3587 OMX Error None if successful.
3588========================================================================== */
3589OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
3590 OMX_IN OMX_INDEXTYPE configIndex,
3591 OMX_IN OMX_PTR configData)
3592{
3593 if(m_state == OMX_StateInvalid)
3594 {
3595 DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
3596 return OMX_ErrorInvalidState;
3597 }
3598
3599 OMX_ERRORTYPE ret = OMX_ErrorNone;
3600 OMX_VIDEO_CONFIG_NALSIZE *pNal;
3601
3602 DEBUG_PRINT_LOW("\n Set Config Called");
3603
3604 if (m_state == OMX_StateExecuting)
3605 {
3606 DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n");
3607 return ret;
3608 }
3609
3610 if (configIndex == OMX_IndexVendorVideoExtraData)
3611 {
3612 OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData;
3613 DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData called");
3614 if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc"))
3615 {
3616 DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData AVC");
3617 OMX_U32 extra_size;
3618 // Parsing done here for the AVC atom is definitely not generic
3619 // Currently this piece of code is working, but certainly
3620 // not tested with all .mp4 files.
3621 // Incase of failure, we might need to revisit this
3622 // for a generic piece of code.
3623
3624 // Retrieve size of NAL length field
3625 // byte #4 contains the size of NAL lenght field
3626 nal_length = (config->pData[4] & 0x03) + 1;
3627
3628 extra_size = 0;
3629 if (nal_length > 2)
3630 {
3631 /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
3632 extra_size = (nal_length - 2) * 2;
3633 }
3634
3635 // SPS starts from byte #6
3636 OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
3637 OMX_U8 *pDestBuf;
3638 m_vendor_config.nPortIndex = config->nPortIndex;
3639
3640 // minus 6 --> SPS starts from byte #6
3641 // minus 1 --> picture param set byte to be ignored from avcatom
3642 m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size;
3643 m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize);
3644 OMX_U32 len;
3645 OMX_U8 index = 0;
3646 // case where SPS+PPS is sent as part of set_config
3647 pDestBuf = m_vendor_config.pData;
3648
3649 DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n",
3650 m_vendor_config.nPortIndex,
3651 m_vendor_config.nDataSize,
3652 m_vendor_config.pData);
3653 while (index < 2)
3654 {
3655 uint8 *psize;
3656 len = *pSrcBuf;
3657 len = len << 8;
3658 len |= *(pSrcBuf + 1);
3659 psize = (uint8 *) & len;
3660 memcpy(pDestBuf + nal_length, pSrcBuf + 2,len);
3661 for (int i = 0; i < nal_length; i++)
3662 {
3663 pDestBuf[i] = psize[nal_length - 1 - i];
3664 }
3665 //memcpy(pDestBuf,pSrcBuf,(len+2));
3666 pDestBuf += len + nal_length;
3667 pSrcBuf += len + 2;
3668 index++;
3669 pSrcBuf++; // skip picture param set
3670 len = 0;
3671 }
3672 }
3673 else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") ||
3674 !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2"))
3675 {
3676 m_vendor_config.nPortIndex = config->nPortIndex;
3677 m_vendor_config.nDataSize = config->nDataSize;
3678 m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize));
3679 memcpy(m_vendor_config.pData, config->pData,config->nDataSize);
3680 }
3681 else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1"))
3682 {
3683 if(m_vendor_config.pData)
3684 {
3685 free(m_vendor_config.pData);
3686 m_vendor_config.pData = NULL;
3687 m_vendor_config.nDataSize = 0;
3688 }
3689
3690 if (((*((OMX_U32 *) config->pData)) &
3691 VC1_SP_MP_START_CODE_MASK) ==
3692 VC1_SP_MP_START_CODE)
3693 {
3694 DEBUG_PRINT_LOW("set_config - VC1 simple/main profile\n");
3695 m_vendor_config.nPortIndex = config->nPortIndex;
3696 m_vendor_config.nDataSize = config->nDataSize;
3697 m_vendor_config.pData =
3698 (OMX_U8 *) malloc(config->nDataSize);
3699 memcpy(m_vendor_config.pData, config->pData,
3700 config->nDataSize);
3701 m_vc1_profile = VC1_SP_MP_RCV;
3702 }
3703 else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE)
3704 {
3705 DEBUG_PRINT_LOW("set_config - VC1 Advance profile\n");
3706 m_vendor_config.nPortIndex = config->nPortIndex;
3707 m_vendor_config.nDataSize = config->nDataSize;
3708 m_vendor_config.pData =
3709 (OMX_U8 *) malloc((config->nDataSize));
3710 memcpy(m_vendor_config.pData, config->pData,
3711 config->nDataSize);
3712 m_vc1_profile = VC1_AP;
3713 }
3714 else if ((config->nDataSize == VC1_STRUCT_C_LEN))
3715 {
3716 DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only\n");
3717 m_vendor_config.nPortIndex = config->nPortIndex;
3718 m_vendor_config.nDataSize = config->nDataSize;
3719 m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
3720 memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
3721 m_vc1_profile = VC1_SP_MP_RCV;
3722 }
3723 else
3724 {
3725 DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile\n");
3726 }
3727 }
3728 return ret;
3729 }
3730 else if (configIndex == OMX_IndexConfigVideoNalSize)
3731 {
3732
3733 pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
3734 nal_length = pNal->nNaluBytes;
3735 m_frame_parser.init_nal_length(nal_length);
3736 DEBUG_PRINT_LOW("\n OMX_IndexConfigVideoNalSize called with Size %d",nal_length);
3737 return ret;
3738 }
3739
3740 return OMX_ErrorNotImplemented;
3741}
3742
3743/* ======================================================================
3744FUNCTION
3745 omx_vdec::GetExtensionIndex
3746
3747DESCRIPTION
3748 OMX GetExtensionIndex method implementaion. <TBD>
3749
3750PARAMETERS
3751 <TBD>.
3752
3753RETURN VALUE
3754 OMX Error None if everything successful.
3755
3756========================================================================== */
3757OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
3758 OMX_IN OMX_STRING paramName,
3759 OMX_OUT OMX_INDEXTYPE* indexType)
3760{
3761 if(m_state == OMX_StateInvalid)
3762 {
3763 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n");
3764 return OMX_ErrorInvalidState;
3765 }
3766 else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) {
3767 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
3768 }
3769 else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1))
3770 {
3771 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
3772 }
3773#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3774 else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
3775 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
3776 }
3777 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
3778 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
3779 }
3780 else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
3781 DEBUG_PRINT_ERROR("Extension: %s is supported\n", paramName);
3782 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
3783 }
3784 else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
3785 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
3786 }
3787#endif
3788 else {
3789 DEBUG_PRINT_ERROR("Extension: %s not implemented\n", paramName);
3790 return OMX_ErrorNotImplemented;
3791 }
3792 return OMX_ErrorNone;
3793}
3794
3795/* ======================================================================
3796FUNCTION
3797 omx_vdec::GetState
3798
3799DESCRIPTION
3800 Returns the state information back to the caller.<TBD>
3801
3802PARAMETERS
3803 <TBD>.
3804
3805RETURN VALUE
3806 Error None if everything is successful.
3807========================================================================== */
3808OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
3809 OMX_OUT OMX_STATETYPE* state)
3810{
3811 *state = m_state;
3812 DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state);
3813 return OMX_ErrorNone;
3814}
3815
3816/* ======================================================================
3817FUNCTION
3818 omx_vdec::ComponentTunnelRequest
3819
3820DESCRIPTION
3821 OMX Component Tunnel Request method implementation. <TBD>
3822
3823PARAMETERS
3824 None.
3825
3826RETURN VALUE
3827 OMX Error None if everything successful.
3828
3829========================================================================== */
3830OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
3831 OMX_IN OMX_U32 port,
3832 OMX_IN OMX_HANDLETYPE peerComponent,
3833 OMX_IN OMX_U32 peerPort,
3834 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
3835{
3836 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n");
3837 return OMX_ErrorNotImplemented;
3838}
3839
3840/* ======================================================================
3841FUNCTION
3842 omx_vdec::UseOutputBuffer
3843
3844DESCRIPTION
3845 Helper function for Use buffer in the input pin
3846
3847PARAMETERS
3848 None.
3849
3850RETURN VALUE
3851 true/false
3852
3853========================================================================== */
3854OMX_ERRORTYPE omx_vdec::use_output_buffer(
3855 OMX_IN OMX_HANDLETYPE hComp,
3856 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
3857 OMX_IN OMX_U32 port,
3858 OMX_IN OMX_PTR appData,
3859 OMX_IN OMX_U32 bytes,
3860 OMX_IN OMX_U8* buffer)
3861{
3862 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3863 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
3864 unsigned i= 0; // Temporary counter
3865 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
3866 struct vdec_setbuffer_cmd setbuffers;
3867 OMX_PTR privateAppData = NULL;
3868 private_handle_t *handle = NULL;
3869 OMX_U8 *buff = buffer;
3870 if (!m_out_mem_ptr) {
3871 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
3872 eRet = allocate_output_headers();
3873 }
3874
3875 if (eRet == OMX_ErrorNone) {
3876 for(i=0; i< drv_ctx.op_buf.actualcount; i++) {
3877 if(BITMASK_ABSENT(&m_out_bm_count,i))
3878 {
3879 break;
3880 }
3881 }
3882 }
3883
3884 if(i >= drv_ctx.op_buf.actualcount) {
3885 eRet = OMX_ErrorInsufficientResources;
3886 }
3887
3888 if (eRet == OMX_ErrorNone) {
3889#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
3890 if(m_enable_android_native_buffers) {
3891 if(m_use_android_native_buffers) {
3892 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
3893 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
3894 handle = (private_handle_t *)nBuf->handle;
3895 privateAppData = params->pAppPrivate;
3896 }
3897 else {
3898 handle = (private_handle_t *)buff;
3899 if(!secure_mode) {
3900 buff = (OMX_U8*)mmap(0, handle->size,
3901 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3902 if (buff == MAP_FAILED) {
3903 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
3904 return OMX_ErrorInsufficientResources;
3905 }
3906 }
3907 privateAppData = appData;
3908 }
3909#if defined(_ANDROID_ICS_)
3910 native_buffer[i].nativehandle = handle;
3911#endif
3912 if(!handle) {
3913 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
3914 return OMX_ErrorBadParameter;
3915 }
3916 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
3917 drv_ctx.ptr_outputbuffer[i].offset = 0;
3918 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
3919 drv_ctx.ptr_outputbuffer[i].mmaped_size =
3920 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
3921 } else
3922#endif
3923
3924 if (!ouput_egl_buffers && !m_use_output_pmem) {
3925#ifdef USE_ION
3926 drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
3927 drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
3928 &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
3929 &drv_ctx.op_buf_ion_info[i].fd_ion_data, 0);
3930 if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
3931 return OMX_ErrorInsufficientResources;
3932 }
3933 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3934 drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
3935#else
3936 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3937 open (MEM_DEVICE,O_RDWR);
3938
3939 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3940 return OMX_ErrorInsufficientResources;
3941 }
3942
3943 if(drv_ctx.ptr_outputbuffer[i].pmem_fd == 0)
3944 {
3945 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
3946 open (MEM_DEVICE,O_RDWR);
3947 if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
3948 return OMX_ErrorInsufficientResources;
3949 }
3950 }
3951
3952 if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
3953 drv_ctx.op_buf.buffer_size,
3954 drv_ctx.op_buf.alignment))
3955 {
3956 DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
3957 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3958 return OMX_ErrorInsufficientResources;
3959 }
3960#endif
3961 if(!secure_mode) {
3962 drv_ctx.ptr_outputbuffer[i].bufferaddr =
3963 (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
3964 PROT_READ|PROT_WRITE, MAP_SHARED,
3965 drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
3966 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
3967 close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
3968#ifdef USE_ION
3969 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
3970#endif
3971 return OMX_ErrorInsufficientResources;
3972 }
3973 }
3974 drv_ctx.ptr_outputbuffer[i].offset = 0;
3975 privateAppData = appData;
3976 }
3977 else {
3978
3979 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
3980 if (!appData || !bytes ) {
3981 if(!secure_mode && !buffer) {
3982 DEBUG_PRINT_ERROR("\n Bad parameters for use buffer in EGL image case");
3983 return OMX_ErrorBadParameter;
3984 }
3985 }
3986
3987 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
3988 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
3989 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
3990 if (!pmem_list->entryList || !pmem_list->entryList->entry ||
3991 !pmem_list->nEntries ||
3992 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
3993 DEBUG_PRINT_ERROR("\n Pmem info not valid in use buffer");
3994 return OMX_ErrorBadParameter;
3995 }
3996 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
3997 pmem_list->entryList->entry;
3998 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x",
3999 pmem_info->pmem_fd);
4000 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
4001 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
4002 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
4003 drv_ctx.ptr_outputbuffer[i].mmaped_size =
4004 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
4005 privateAppData = appData;
4006 }
4007 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
4008 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
4009
4010 *bufferHdr = (m_out_mem_ptr + i );
4011 if(secure_mode)
4012 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
4013 //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
4014 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
4015 sizeof (vdec_bufferpayload));
4016
4017 // ioctl_msg.in = &setbuffers;
4018 // ioctl_msg.out = NULL;
4019
4020 DEBUG_PRINT_HIGH("\n Set the Output Buffer Idx: %d Addr: %x, pmem_fd=%0x%x", i,
4021 drv_ctx.ptr_outputbuffer[i],drv_ctx.ptr_outputbuffer[i].pmem_fd );
4022 // if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
4023 // &ioctl_msg) < 0)
4024 // {
4025 // DEBUG_PRINT_ERROR("\n Set output buffer failed");
4026 // return OMX_ErrorInsufficientResources;
4027 // }
4028 // found an empty buffer at i
4029 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
4030 (*bufferHdr)->pBuffer = buff;
4031 (*bufferHdr)->pAppPrivate = privateAppData;
4032 BITMASK_SET(&m_out_bm_count,i);
4033 }
4034 return eRet;
4035}
4036
4037/* ======================================================================
4038FUNCTION
4039 omx_vdec::use_input_heap_buffers
4040
4041DESCRIPTION
4042 OMX Use Buffer Heap allocation method implementation.
4043
4044PARAMETERS
4045 <TBD>.
4046
4047RETURN VALUE
4048 OMX Error None , if everything successful.
4049
4050========================================================================== */
4051OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
4052 OMX_IN OMX_HANDLETYPE hComp,
4053 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4054 OMX_IN OMX_U32 port,
4055 OMX_IN OMX_PTR appData,
4056 OMX_IN OMX_U32 bytes,
4057 OMX_IN OMX_U8* buffer)
4058{
4059 DEBUG_PRINT_LOW("Inside %s, %p\n", __FUNCTION__, buffer);
4060 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4061 if(!m_inp_heap_ptr)
4062 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
4063 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4064 drv_ctx.ip_buf.actualcount);
4065 if(!m_phdr_pmem_ptr)
4066 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
4067 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4068 drv_ctx.ip_buf.actualcount);
4069 if(!m_inp_heap_ptr || !m_phdr_pmem_ptr)
4070 {
4071 DEBUG_PRINT_ERROR("Insufficent memory");
4072 eRet = OMX_ErrorInsufficientResources;
4073 }
4074 else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount)
4075 {
4076 input_use_buffer = true;
4077 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
4078 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
4079 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
4080 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
4081 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
4082 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
4083 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
4084 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
4085 DEBUG_PRINT_HIGH("\n Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
4086 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt], NULL, NULL))
4087 {
4088 DEBUG_PRINT_ERROR("\nERROR:Free_q is full");
4089 return OMX_ErrorInsufficientResources;
4090 }
4091 m_in_alloc_cnt++;
4092 }
4093 else
4094 {
4095 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
4096 eRet = OMX_ErrorInsufficientResources;
4097 }
4098 return eRet;
4099}
4100
4101/* ======================================================================
4102FUNCTION
4103 omx_vdec::UseBuffer
4104
4105DESCRIPTION
4106 OMX Use Buffer method implementation.
4107
4108PARAMETERS
4109 <TBD>.
4110
4111RETURN VALUE
4112 OMX Error None , if everything successful.
4113
4114========================================================================== */
4115OMX_ERRORTYPE omx_vdec::use_buffer(
4116 OMX_IN OMX_HANDLETYPE hComp,
4117 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4118 OMX_IN OMX_U32 port,
4119 OMX_IN OMX_PTR appData,
4120 OMX_IN OMX_U32 bytes,
4121 OMX_IN OMX_U8* buffer)
4122{
4123 OMX_ERRORTYPE error = OMX_ErrorNone;
4124 struct vdec_setbuffer_cmd setbuffers;
4125 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
4126
4127 if (bufferHdr == NULL || bytes == 0)
4128 {
4129 if(!secure_mode && buffer == NULL) {
4130 DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer);
4131 return OMX_ErrorBadParameter;
4132 }
4133 }
4134 if(m_state == OMX_StateInvalid)
4135 {
4136 DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n");
4137 return OMX_ErrorInvalidState;
4138 }
4139 if(port == OMX_CORE_INPUT_PORT_INDEX)
4140 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
4141 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
4142 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
4143 else
4144 {
4145 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
4146 error = OMX_ErrorBadPortIndex;
4147 }
4148 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error);
4149 if(error == OMX_ErrorNone)
4150 {
4151 if(allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
4152 {
4153 // Send the callback now
4154 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4155 post_event(OMX_CommandStateSet,OMX_StateIdle,
4156 OMX_COMPONENT_GENERATE_EVENT);
4157 }
4158 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
4159 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
4160 {
4161 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4162 post_event(OMX_CommandPortEnable,
4163 OMX_CORE_INPUT_PORT_INDEX,
4164 OMX_COMPONENT_GENERATE_EVENT);
4165 }
4166 else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
4167 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
4168 {
4169 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4170 post_event(OMX_CommandPortEnable,
4171 OMX_CORE_OUTPUT_PORT_INDEX,
4172 OMX_COMPONENT_GENERATE_EVENT);
4173 }
4174 }
4175 return error;
4176}
4177
4178OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
4179 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
4180{
4181 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes)
4182 {
4183 if(m_inp_heap_ptr[bufferindex].pBuffer)
4184 free(m_inp_heap_ptr[bufferindex].pBuffer);
4185 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
4186 }
4187 if (pmem_bufferHdr)
4188 free_input_buffer(pmem_bufferHdr);
4189 return OMX_ErrorNone;
4190}
4191
4192OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4193{
4194 unsigned int index = 0;
4195 if (bufferHdr == NULL || m_inp_mem_ptr == NULL)
4196 {
4197 return OMX_ErrorBadParameter;
4198 }
4199
4200 index = bufferHdr - m_inp_mem_ptr;
4201 DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);
4202
4203 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer)
4204 {
4205 DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);
4206 if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0)
4207 {
4208 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
4209 struct vdec_setbuffer_cmd setbuffers;
4210 setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
4211 memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
4212 sizeof (vdec_bufferpayload));
4213 ioctl_msg.in = &setbuffers;
4214 ioctl_msg.out = NULL;
4215 int ioctl_r; //= ioctl (drv_ctx.video_driver_fd,
4216 // VDEC_IOCTL_FREE_BUFFER, &ioctl_msg);
4217 if (ioctl_r < 0)
4218 {
4219 DEBUG_PRINT_ERROR("\nVDEC_IOCTL_FREE_BUFFER returned error %d", ioctl_r);
4220 }
4221
4222 DEBUG_PRINT_LOW("\n unmap the input buffer fd=%d",
4223 drv_ctx.ptr_inputbuffer[index].pmem_fd);
4224 DEBUG_PRINT_LOW("\n unmap the input buffer size=%d address = %d",
4225 drv_ctx.ptr_inputbuffer[index].mmaped_size,
4226 drv_ctx.ptr_inputbuffer[index].bufferaddr);
4227 munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
4228 drv_ctx.ptr_inputbuffer[index].mmaped_size);
4229 close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
4230 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
4231 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr)
4232 {
4233 free(m_desc_buffer_ptr[index].buf_addr);
4234 m_desc_buffer_ptr[index].buf_addr = NULL;
4235 m_desc_buffer_ptr[index].desc_data_size = 0;
4236 }
4237#ifdef USE_ION
4238 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
4239#endif
4240 }
4241 }
4242
4243 return OMX_ErrorNone;
4244}
4245
4246OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
4247{
4248 unsigned int index = 0;
4249
4250 if (bufferHdr == NULL || m_out_mem_ptr == NULL)
4251 {
4252 return OMX_ErrorBadParameter;
4253 }
4254
4255 index = bufferHdr - m_out_mem_ptr;
4256 DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d",index);
4257
4258 if (index < drv_ctx.op_buf.actualcount
4259 && drv_ctx.ptr_outputbuffer)
4260 {
4261 DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d addr = %x", index,
4262 drv_ctx.ptr_outputbuffer[index].bufferaddr);
4263
4264 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
4265 struct vdec_setbuffer_cmd setbuffers;
4266 setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
4267 memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
4268 sizeof (vdec_bufferpayload));
4269 ioctl_msg.in = &setbuffers;
4270 ioctl_msg.out = NULL;
4271 DEBUG_PRINT_LOW("\nRelease the Output Buffer");
4272 if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_BUFFER,
4273 &ioctl_msg) < */0)
4274 DEBUG_PRINT_ERROR("\nRelease output buffer failed in VCD");
4275
4276#ifdef _ANDROID_
4277 if(m_enable_android_native_buffers) {
4278 if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
4279 munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
4280 drv_ctx.ptr_outputbuffer[index].mmaped_size);
4281 }
4282 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
4283 } else {
4284#endif
4285 if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem)
4286 {
4287 DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d",
4288 drv_ctx.ptr_outputbuffer[0].pmem_fd);
4289 DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %d",
4290 drv_ctx.ptr_outputbuffer[0].mmaped_size,
4291 drv_ctx.ptr_outputbuffer[0].bufferaddr);
4292 munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
4293 drv_ctx.ptr_outputbuffer[0].mmaped_size);
4294 close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
4295 drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
4296#ifdef USE_ION
4297 free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
4298#endif
4299 }
4300#ifdef _ANDROID_
4301 }
4302#endif
4303 }
4304
4305 return OMX_ErrorNone;
4306
4307}
4308
4309OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
4310 OMX_BUFFERHEADERTYPE **bufferHdr,
4311 OMX_U32 port,
4312 OMX_PTR appData,
4313 OMX_U32 bytes)
4314{
4315 OMX_BUFFERHEADERTYPE *input = NULL;
4316 unsigned char *buf_addr = NULL;
4317 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4318 unsigned i = 0;
4319
4320 /* Sanity Check*/
4321 if (bufferHdr == NULL)
4322 {
4323 return OMX_ErrorBadParameter;
4324 }
4325
4326 if (m_inp_heap_ptr == NULL)
4327 {
4328 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
4329 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
4330 drv_ctx.ip_buf.actualcount);
4331 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
4332 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
4333 drv_ctx.ip_buf.actualcount);
4334
4335 if (m_inp_heap_ptr == NULL)
4336 {
4337 DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed ");
4338 return OMX_ErrorInsufficientResources;
4339 }
4340 }
4341
4342 /*Find a Free index*/
4343 for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
4344 {
4345 if(BITMASK_ABSENT(&m_heap_inp_bm_count,i))
4346 {
4347 DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
4348 break;
4349 }
4350 }
4351
4352 if (i < drv_ctx.ip_buf.actualcount)
4353 {
4354 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
4355
4356 if (buf_addr == NULL)
4357 {
4358 return OMX_ErrorInsufficientResources;
4359 }
4360
4361 *bufferHdr = (m_inp_heap_ptr + i);
4362 input = *bufferHdr;
4363 BITMASK_SET(&m_heap_inp_bm_count,i);
4364
4365 input->pBuffer = (OMX_U8 *)buf_addr;
4366 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4367 input->nVersion.nVersion = OMX_SPEC_VERSION;
4368 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4369 input->pAppPrivate = appData;
4370 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4371 DEBUG_PRINT_LOW("\n Address of Heap Buffer %p",*bufferHdr );
4372 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
4373 DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",m_phdr_pmem_ptr [i] );
4374 /*Add the Buffers to freeq*/
4375 if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr [i],NULL,NULL))
4376 {
4377 DEBUG_PRINT_ERROR("\nERROR:Free_q is full");
4378 return OMX_ErrorInsufficientResources;
4379 }
4380 }
4381 else
4382 {
4383 return OMX_ErrorBadParameter;
4384 }
4385
4386 return eRet;
4387
4388}
4389
4390
4391/* ======================================================================
4392FUNCTION
4393 omx_vdec::AllocateInputBuffer
4394
4395DESCRIPTION
4396 Helper function for allocate buffer in the input pin
4397
4398PARAMETERS
4399 None.
4400
4401RETURN VALUE
4402 true/false
4403
4404========================================================================== */
4405OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
4406 OMX_IN OMX_HANDLETYPE hComp,
4407 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4408 OMX_IN OMX_U32 port,
4409 OMX_IN OMX_PTR appData,
4410 OMX_IN OMX_U32 bytes)
4411{
4412
4413 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4414 struct vdec_setbuffer_cmd setbuffers;
4415 OMX_BUFFERHEADERTYPE *input = NULL;
4416 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
4417 unsigned i = 0;
4418 unsigned char *buf_addr = NULL;
4419 int pmem_fd = -1;
4420
4421 if(bytes != drv_ctx.ip_buf.buffer_size)
4422 {
4423 DEBUG_PRINT_LOW("\n Requested Size is wrong %d epected is %d",
4424 bytes, drv_ctx.ip_buf.buffer_size);
4425 return OMX_ErrorBadParameter;
4426 }
4427
4428 if(!m_inp_mem_ptr)
4429 {
4430 DEBUG_PRINT_HIGH("\n Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
4431 drv_ctx.ip_buf.actualcount,
4432 drv_ctx.ip_buf.buffer_size);
4433
4434 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
4435 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
4436
4437 if (m_inp_mem_ptr == NULL)
4438 {
4439 return OMX_ErrorInsufficientResources;
4440 }
4441
4442 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
4443 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
4444
4445 if (drv_ctx.ptr_inputbuffer == NULL)
4446 {
4447 return OMX_ErrorInsufficientResources;
4448 }
4449#ifdef USE_ION
4450 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
4451 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
4452
4453 if (drv_ctx.ip_buf_ion_info == NULL)
4454 {
4455 return OMX_ErrorInsufficientResources;
4456 }
4457#endif
4458
4459 for (i=0; i < drv_ctx.ip_buf.actualcount; i++)
4460 {
4461 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
4462#ifdef USE_ION
4463 drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
4464#endif
4465 }
4466 }
4467
4468 for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
4469 {
4470 if(BITMASK_ABSENT(&m_inp_bm_count,i))
4471 {
4472 DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
4473 break;
4474 }
4475 }
4476
4477 if(i < drv_ctx.ip_buf.actualcount)
4478 {
4479 struct v4l2_buffer buf;
4480 struct v4l2_plane plane;
4481 int rc;
4482 DEBUG_PRINT_LOW("\n Allocate input Buffer");
4483#ifdef USE_ION
4484 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
4485 drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
4486 &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
4487 &drv_ctx.ip_buf_ion_info[i].fd_ion_data, 0);
4488 if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
4489 return OMX_ErrorInsufficientResources;
4490 }
4491 pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
4492#else
4493 pmem_fd = open (MEM_DEVICE,O_RDWR);
4494
4495 if (pmem_fd < 0)
4496 {
4497 DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
4498 return OMX_ErrorInsufficientResources;
4499 }
4500
4501 if (pmem_fd == 0)
4502 {
4503 pmem_fd = open (MEM_DEVICE,O_RDWR);
4504
4505 if (pmem_fd < 0)
4506 {
4507 DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
4508 return OMX_ErrorInsufficientResources;
4509 }
4510 }
4511
4512 if(!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
4513 drv_ctx.ip_buf.alignment))
4514 {
4515 DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
4516 close(pmem_fd);
4517 return OMX_ErrorInsufficientResources;
4518 }
4519#endif
4520 if (!secure_mode) {
4521 buf_addr = (unsigned char *)mmap(NULL,
4522 drv_ctx.ip_buf.buffer_size,
4523 PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
4524
4525 if (buf_addr == MAP_FAILED)
4526 {
4527 close(pmem_fd);
4528#ifdef USE_ION
4529 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
4530#endif
4531 DEBUG_PRINT_ERROR("\n Map Failed to allocate input buffer");
4532 return OMX_ErrorInsufficientResources;
4533 }
4534 }
4535 *bufferHdr = (m_inp_mem_ptr + i);
4536 if (secure_mode)
4537 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
4538 else
4539 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
4540 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
4541 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
4542 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
4543 drv_ctx.ptr_inputbuffer [i].offset = 0;
4544
4545
4546 buf.index = i;
4547 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4548 buf.memory = V4L2_MEMORY_USERPTR;
4549 plane.bytesused = 0;
4550 plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
4551 plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
4552 plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
4553 plane.reserved[1] = 0;
4554 plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
4555 buf.m.planes = &plane;
4556 buf.length = 1;
4557
4558 DEBUG_PRINT_LOW("\n Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_inputbuffer[i]);
4559
4560 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4561
4562 if (rc) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07004563 DEBUG_PRINT_ERROR("Failed to prepare bufs\n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07004564 /*TODO: How to handle this case */
4565 return OMX_ErrorInsufficientResources;
4566 }
4567
4568 input = *bufferHdr;
4569 BITMASK_SET(&m_inp_bm_count,i);
4570 DEBUG_PRINT_LOW("\n Buffer address %p of pmem",*bufferHdr);
4571 if (secure_mode)
4572 input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd;
4573 else
4574 input->pBuffer = (OMX_U8 *)buf_addr;
4575 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4576 input->nVersion.nVersion = OMX_SPEC_VERSION;
4577 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
4578 input->pAppPrivate = appData;
4579 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
4580 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
4581
4582 if (drv_ctx.disable_dmx)
4583 {
4584 eRet = allocate_desc_buffer(i);
4585 }
4586 }
4587 else
4588 {
4589 DEBUG_PRINT_ERROR("\nERROR:Input Buffer Index not found");
4590 eRet = OMX_ErrorInsufficientResources;
4591 }
4592 return eRet;
4593}
4594
4595
4596/* ======================================================================
4597FUNCTION
4598 omx_vdec::AllocateOutputBuffer
4599
4600DESCRIPTION
4601 Helper fn for AllocateBuffer in the output pin
4602
4603PARAMETERS
4604 <TBD>.
4605
4606RETURN VALUE
4607 OMX Error None if everything went well.
4608
4609========================================================================== */
4610OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
4611 OMX_IN OMX_HANDLETYPE hComp,
4612 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4613 OMX_IN OMX_U32 port,
4614 OMX_IN OMX_PTR appData,
4615 OMX_IN OMX_U32 bytes)
4616{
4617 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4618 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
4619 unsigned i= 0; // Temporary counter
4620 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
4621 struct vdec_setbuffer_cmd setbuffers;
4622#ifdef USE_ION
4623 int ion_device_fd =-1;
4624 struct ion_allocation_data ion_alloc_data;
4625 struct ion_fd_data fd_ion_data;
4626#endif
4627 if(!m_out_mem_ptr)
4628 {
4629 DEBUG_PRINT_HIGH("\n Allocate o/p buffer Header: Cnt(%d) Sz(%d)",
4630 drv_ctx.op_buf.actualcount,
4631 drv_ctx.op_buf.buffer_size);
4632 int nBufHdrSize = 0;
4633 int nPlatformEntrySize = 0;
4634 int nPlatformListSize = 0;
4635 int nPMEMInfoSize = 0;
4636 int pmem_fd = -1;
4637 unsigned char *pmem_baseaddress = NULL;
4638
4639 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
4640 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
4641 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
4642
4643 DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",
4644 drv_ctx.op_buf.actualcount);
4645 nBufHdrSize = drv_ctx.op_buf.actualcount *
4646 sizeof(OMX_BUFFERHEADERTYPE);
4647
4648 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
4649 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
4650 nPlatformListSize = drv_ctx.op_buf.actualcount *
4651 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
4652 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
4653 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
4654
4655 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
4656 sizeof(OMX_BUFFERHEADERTYPE),
4657 nPMEMInfoSize,
4658 nPlatformListSize);
4659 DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d \n",nPlatformEntrySize,
4660 drv_ctx.op_buf.actualcount);
4661#ifdef USE_ION
4662 ion_device_fd = alloc_map_ion_memory(
4663 drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
4664 drv_ctx.op_buf.alignment,
4665 &ion_alloc_data, &fd_ion_data, 0);
4666 if (ion_device_fd < 0) {
4667 return OMX_ErrorInsufficientResources;
4668 }
4669 pmem_fd = fd_ion_data.fd;
4670#else
4671 pmem_fd = open (MEM_DEVICE,O_RDWR);
4672
4673 if (pmem_fd < 0)
4674 {
4675 DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",
4676 drv_ctx.op_buf.buffer_size);
4677 return OMX_ErrorInsufficientResources;
4678 }
4679
4680 if(pmem_fd == 0)
4681 {
4682 pmem_fd = open (MEM_DEVICE,O_RDWR);
4683
4684 if (pmem_fd < 0)
4685 {
4686 DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",
4687 drv_ctx.op_buf.buffer_size);
4688 return OMX_ErrorInsufficientResources;
4689 }
4690 }
4691
4692 if(!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
4693 drv_ctx.op_buf.actualcount,
4694 drv_ctx.op_buf.alignment))
4695 {
4696 DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
4697 close(pmem_fd);
4698 return OMX_ErrorInsufficientResources;
4699 }
4700#endif
4701 if (!secure_mode) {
4702 pmem_baseaddress = (unsigned char *)mmap(NULL,
4703 (drv_ctx.op_buf.buffer_size *
4704 drv_ctx.op_buf.actualcount),
4705 PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
4706 if (pmem_baseaddress == MAP_FAILED)
4707 {
4708 DEBUG_PRINT_ERROR("\n MMAP failed for Size %d",
4709 drv_ctx.op_buf.buffer_size);
4710 close(pmem_fd);
4711#ifdef USE_ION
4712 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
4713#endif
4714 return OMX_ErrorInsufficientResources;
4715 }
4716 }
4717 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
4718 // Alloc mem for platform specific info
4719 char *pPtr=NULL;
4720 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
4721 nPMEMInfoSize,1);
4722 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
4723 calloc (sizeof(struct vdec_bufferpayload),
4724 drv_ctx.op_buf.actualcount);
4725 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
4726 calloc (sizeof (struct vdec_output_frameinfo),
4727 drv_ctx.op_buf.actualcount);
4728#ifdef USE_ION
4729 drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
4730 calloc (sizeof(struct vdec_ion),
4731 drv_ctx.op_buf.actualcount);
4732#endif
4733
4734 if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
4735 && drv_ctx.ptr_respbuffer)
4736 {
4737 drv_ctx.ptr_outputbuffer[0].mmaped_size =
4738 (drv_ctx.op_buf.buffer_size *
4739 drv_ctx.op_buf.actualcount);
4740 bufHdr = m_out_mem_ptr;
4741 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
4742 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
4743 (((char *) m_platform_list) + nPlatformListSize);
4744 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
4745 (((char *) m_platform_entry) + nPlatformEntrySize);
4746 pPlatformList = m_platform_list;
4747 pPlatformEntry = m_platform_entry;
4748 pPMEMInfo = m_pmem_info;
4749
4750 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
4751
4752 // Settting the entire storage nicely
4753 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, m_out_mem_ptr,pPlatformEntry);
4754 DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
4755 for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
4756 {
4757 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
4758 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
4759 // Set the values when we determine the right HxW param
4760 bufHdr->nAllocLen = bytes;
4761 bufHdr->nFilledLen = 0;
4762 bufHdr->pAppPrivate = appData;
4763 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
4764 // Platform specific PMEM Information
4765 // Initialize the Platform Entry
4766 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d\n",i);
4767 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
4768 pPlatformEntry->entry = pPMEMInfo;
4769 // Initialize the Platform List
4770 pPlatformList->nEntries = 1;
4771 pPlatformList->entryList = pPlatformEntry;
4772 // Keep pBuffer NULL till vdec is opened
4773 bufHdr->pBuffer = NULL;
4774 bufHdr->nOffset = 0;
4775
4776 pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
4777 pPMEMInfo->pmem_fd = 0;
4778 bufHdr->pPlatformPrivate = pPlatformList;
4779
4780 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
4781#ifdef USE_ION
4782 drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
4783 drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
4784 drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
4785#endif
4786
4787 /*Create a mapping between buffers*/
4788 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
4789 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
4790 &drv_ctx.ptr_outputbuffer[i];
4791 drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
4792 drv_ctx.ptr_outputbuffer[i].bufferaddr =
4793 pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
4794
4795 DEBUG_PRINT_LOW("\n pmem_fd = %d offset = %d address = %p",
4796 pmem_fd, drv_ctx.ptr_outputbuffer[i].offset,
4797 drv_ctx.ptr_outputbuffer[i].bufferaddr);
4798 // Move the buffer and buffer header pointers
4799 bufHdr++;
4800 pPMEMInfo++;
4801 pPlatformEntry++;
4802 pPlatformList++;
4803 }
4804 }
4805 else
4806 {
4807 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
4808 m_out_mem_ptr, pPtr);
4809 if(m_out_mem_ptr)
4810 {
4811 free(m_out_mem_ptr);
4812 m_out_mem_ptr = NULL;
4813 }
4814 if(pPtr)
4815 {
4816 free(pPtr);
4817 pPtr = NULL;
4818 }
4819 if(drv_ctx.ptr_outputbuffer)
4820 {
4821 free(drv_ctx.ptr_outputbuffer);
4822 drv_ctx.ptr_outputbuffer = NULL;
4823 }
4824 if(drv_ctx.ptr_respbuffer)
4825 {
4826 free(drv_ctx.ptr_respbuffer);
4827 drv_ctx.ptr_respbuffer = NULL;
4828 }
4829#ifdef USE_ION
4830 if (drv_ctx.op_buf_ion_info) {
4831 DEBUG_PRINT_LOW("\n Free o/p ion context");
4832 free(drv_ctx.op_buf_ion_info);
4833 drv_ctx.op_buf_ion_info = NULL;
4834 }
4835#endif
4836 eRet = OMX_ErrorInsufficientResources;
4837 }
4838 }
4839
4840 for(i=0; i< drv_ctx.op_buf.actualcount; i++)
4841 {
4842 if(BITMASK_ABSENT(&m_out_bm_count,i))
4843 {
4844 DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i);
4845 break;
4846 }
4847 }
4848
4849 if (eRet == OMX_ErrorNone)
4850 {
4851 if(i < drv_ctx.op_buf.actualcount)
4852 {
4853 struct v4l2_buffer buf;
4854 struct v4l2_plane plane;
4855 int rc;
4856 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
4857
4858 drv_ctx.ptr_outputbuffer[i].buffer_len =
4859 drv_ctx.op_buf.buffer_size;
4860
4861 *bufferHdr = (m_out_mem_ptr + i );
4862 if (secure_mode) {
4863 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
4864 }
4865 drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
4866
4867 buf.index = i;
4868 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4869 buf.memory = V4L2_MEMORY_USERPTR;
4870 plane.length = drv_ctx.op_buf.buffer_size;
4871 plane.m.userptr = (unsigned long)(drv_ctx.ptr_outputbuffer[i].bufferaddr-drv_ctx.ptr_outputbuffer[i].offset);
4872#ifdef USE_ION
4873 plane.reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
4874#endif
4875 plane.reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
4876 plane.data_offset = 0;
4877 buf.m.planes = &plane;
4878 buf.length = 1;
4879
4880 DEBUG_PRINT_LOW("\n Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
4881 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
4882 if (rc) {
4883 /*TODO: How to handle this case */
4884 return OMX_ErrorInsufficientResources;
4885 }
4886
4887 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
4888 enum v4l2_buf_type buf_type;
4889 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4890 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
4891 if (rc) {
4892 return OMX_ErrorInsufficientResources;
4893 } else {
4894 streaming[CAPTURE_PORT] = true;
4895 DEBUG_PRINT_LOW("\n STREAMON Successful \n ");
4896 }
4897 }
4898
4899 (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
4900 (*bufferHdr)->pAppPrivate = appData;
4901 BITMASK_SET(&m_out_bm_count,i);
4902 }
4903 else
4904 {
4905 DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient \n");
4906 eRet = OMX_ErrorInsufficientResources;
4907 }
4908 }
4909
4910 return eRet;
4911}
4912
4913
4914// AllocateBuffer -- API Call
4915/* ======================================================================
4916FUNCTION
4917 omx_vdec::AllocateBuffer
4918
4919DESCRIPTION
4920 Returns zero if all the buffers released..
4921
4922PARAMETERS
4923 None.
4924
4925RETURN VALUE
4926 true/false
4927
4928========================================================================== */
4929OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
4930 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
4931 OMX_IN OMX_U32 port,
4932 OMX_IN OMX_PTR appData,
4933 OMX_IN OMX_U32 bytes)
4934{
4935 unsigned i = 0;
4936 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
4937
4938 DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port);
4939 if(m_state == OMX_StateInvalid)
4940 {
4941 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n");
4942 return OMX_ErrorInvalidState;
4943 }
4944
4945 if(port == OMX_CORE_INPUT_PORT_INDEX)
4946 {
4947 if (arbitrary_bytes)
4948 {
4949 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
4950 }
4951 else
4952 {
4953 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
4954 }
4955 }
4956 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
4957 {
4958 eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
4959 }
4960 else
4961 {
4962 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
4963 eRet = OMX_ErrorBadPortIndex;
4964 }
4965 DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
4966 if(eRet == OMX_ErrorNone)
4967 {
4968 if(allocate_done()){
4969 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
4970 {
4971 // Send the callback now
4972 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
4973 post_event(OMX_CommandStateSet,OMX_StateIdle,
4974 OMX_COMPONENT_GENERATE_EVENT);
4975 }
4976 }
4977 if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated)
4978 {
4979 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
4980 {
4981 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
4982 post_event(OMX_CommandPortEnable,
4983 OMX_CORE_INPUT_PORT_INDEX,
4984 OMX_COMPONENT_GENERATE_EVENT);
4985 }
4986 }
4987 if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated)
4988 {
4989 if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
4990 {
4991 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
4992 post_event(OMX_CommandPortEnable,
4993 OMX_CORE_OUTPUT_PORT_INDEX,
4994 OMX_COMPONENT_GENERATE_EVENT);
4995 }
4996 }
4997 }
4998 DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet);
4999 return eRet;
5000}
5001
5002// Free Buffer - API call
5003/* ======================================================================
5004FUNCTION
5005 omx_vdec::FreeBuffer
5006
5007DESCRIPTION
5008
5009PARAMETERS
5010 None.
5011
5012RETURN VALUE
5013 true/false
5014
5015========================================================================== */
5016OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
5017 OMX_IN OMX_U32 port,
5018 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5019{
5020 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5021 unsigned int nPortIndex;
5022 DEBUG_PRINT_LOW("In for decoder free_buffer \n");
5023
5024 if(m_state == OMX_StateIdle &&
5025 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
5026 {
5027 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n");
5028 }
5029 else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
5030 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX))
5031 {
5032 DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port);
5033 }
5034 else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause)
5035 {
5036 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n");
5037 post_event(OMX_EventError,
5038 OMX_ErrorPortUnpopulated,
5039 OMX_COMPONENT_GENERATE_EVENT);
5040
5041 return OMX_ErrorIncorrectStateOperation;
5042 }
5043 else if (m_state != OMX_StateInvalid)
5044 {
5045 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n");
5046 post_event(OMX_EventError,
5047 OMX_ErrorPortUnpopulated,
5048 OMX_COMPONENT_GENERATE_EVENT);
5049 }
5050
5051 if(port == OMX_CORE_INPUT_PORT_INDEX)
5052 {
5053 /*Check if arbitrary bytes*/
5054 if(!arbitrary_bytes && !input_use_buffer)
5055 nPortIndex = buffer - m_inp_mem_ptr;
5056 else
5057 nPortIndex = buffer - m_inp_heap_ptr;
5058
5059 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex);
5060 if(nPortIndex < drv_ctx.ip_buf.actualcount)
5061 {
5062 // Clear the bit associated with it.
5063 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
5064 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
5065 if (input_use_buffer == true)
5066 {
5067
5068 DEBUG_PRINT_LOW("\n Free pmem Buffer index %d",nPortIndex);
5069 if(m_phdr_pmem_ptr)
5070 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
5071 }
5072 else
5073 {
5074 if (arbitrary_bytes)
5075 {
5076 if(m_phdr_pmem_ptr)
5077 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
5078 else
5079 free_input_buffer(nPortIndex,NULL);
5080 }
5081 else
5082 free_input_buffer(buffer);
5083 }
5084 m_inp_bPopulated = OMX_FALSE;
5085 /*Free the Buffer Header*/
5086 if (release_input_done())
5087 {
5088 DEBUG_PRINT_HIGH("\n ALL input buffers are freed/released");
5089 free_input_buffer_header();
5090 }
5091 }
5092 else
5093 {
5094 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid\n");
5095 eRet = OMX_ErrorBadPortIndex;
5096 }
5097
5098 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
5099 && release_input_done())
5100 {
5101 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
5102 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
5103 post_event(OMX_CommandPortDisable,
5104 OMX_CORE_INPUT_PORT_INDEX,
5105 OMX_COMPONENT_GENERATE_EVENT);
5106 }
5107 }
5108 else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
5109 {
5110 // check if the buffer is valid
5111 nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
5112 if(nPortIndex < drv_ctx.op_buf.actualcount)
5113 {
5114 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex);
5115 // Clear the bit associated with it.
5116 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
5117 m_out_bPopulated = OMX_FALSE;
5118 free_output_buffer (buffer);
5119
5120 if (release_output_done())
5121 {
5122 free_output_buffer_header();
5123 }
5124 }
5125 else
5126 {
5127 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid\n");
5128 eRet = OMX_ErrorBadPortIndex;
5129 }
5130 if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
5131 && release_output_done())
5132 {
5133 DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n");
5134
5135 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
5136 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
5137#ifdef _ANDROID_ICS_
5138 if (m_enable_android_native_buffers)
5139 {
5140 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
5141 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5142 }
5143#endif
5144
5145 post_event(OMX_CommandPortDisable,
5146 OMX_CORE_OUTPUT_PORT_INDEX,
5147 OMX_COMPONENT_GENERATE_EVENT);
5148 }
5149 }
5150 else
5151 {
5152 eRet = OMX_ErrorBadPortIndex;
5153 }
5154 if((eRet == OMX_ErrorNone) &&
5155 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
5156 {
5157 if(release_done())
5158 {
5159 // Send the callback now
5160 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
5161 post_event(OMX_CommandStateSet, OMX_StateLoaded,
5162 OMX_COMPONENT_GENERATE_EVENT);
5163 }
5164 }
5165 return eRet;
5166}
5167
5168
5169/* ======================================================================
5170FUNCTION
5171 omx_vdec::EmptyThisBuffer
5172
5173DESCRIPTION
5174 This routine is used to push the encoded video frames to
5175 the video decoder.
5176
5177PARAMETERS
5178 None.
5179
5180RETURN VALUE
5181 OMX Error None if everything went successful.
5182
5183========================================================================== */
5184OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
5185 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5186{
5187 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
5188 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
5189
5190 if(m_state == OMX_StateInvalid)
5191 {
5192 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n");
5193 return OMX_ErrorInvalidState;
5194 }
5195
5196 if (buffer == NULL)
5197 {
5198 DEBUG_PRINT_ERROR("\nERROR:ETB Buffer is NULL");
5199 return OMX_ErrorBadParameter;
5200 }
5201
5202 if (!m_inp_bEnabled)
5203 {
5204 DEBUG_PRINT_ERROR("\nERROR:ETB incorrect state operation, input port is disabled.");
5205 return OMX_ErrorIncorrectStateOperation;
5206 }
5207
5208 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX)
5209 {
5210 DEBUG_PRINT_ERROR("\nERROR:ETB invalid port in header %d", buffer->nInputPortIndex);
5211 return OMX_ErrorBadPortIndex;
5212 }
5213
5214#ifdef _ANDROID_
5215 if(iDivXDrmDecrypt)
5216 {
5217 OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer);
5218 if(drmErr != OMX_ErrorNone) {
5219 // this error can be ignored
5220 DEBUG_PRINT_LOW("\nERROR:iDivXDrmDecrypt->Decrypt %d", drmErr);
5221 }
5222 }
5223#endif //_ANDROID_
5224 if (perf_flag)
5225 {
5226 if (!latency)
5227 {
5228 dec_time.stop();
5229 latency = dec_time.processing_time_us();
5230 dec_time.start();
5231 }
5232 }
5233
5234 if (arbitrary_bytes)
5235 {
5236 nBufferIndex = buffer - m_inp_heap_ptr;
5237 }
5238 else
5239 {
5240 if (input_use_buffer == true)
5241 {
5242 nBufferIndex = buffer - m_inp_heap_ptr;
5243 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
5244 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
5245 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
5246 buffer = &m_inp_mem_ptr[nBufferIndex];
5247 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d",
5248 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen);
5249 }
5250 else{
5251 nBufferIndex = buffer - m_inp_mem_ptr;
5252 }
5253 }
5254
5255 if (nBufferIndex > drv_ctx.ip_buf.actualcount )
5256 {
5257 DEBUG_PRINT_ERROR("\nERROR:ETB nBufferIndex is invalid");
5258 return OMX_ErrorBadParameter;
5259 }
5260
5261 DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)",
5262 buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen);
5263 if (arbitrary_bytes)
5264 {
5265 post_event ((unsigned)hComp,(unsigned)buffer,
5266 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
5267 }
5268 else
5269 {
5270 if (!(client_extradata & OMX_TIMEINFO_EXTRADATA))
5271 set_frame_rate(buffer->nTimeStamp);
5272 post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
5273 }
5274 return OMX_ErrorNone;
5275}
5276
5277/* ======================================================================
5278FUNCTION
5279 omx_vdec::empty_this_buffer_proxy
5280
5281DESCRIPTION
5282 This routine is used to push the encoded video frames to
5283 the video decoder.
5284
5285PARAMETERS
5286 None.
5287
5288RETURN VALUE
5289 OMX Error None if everything went successful.
5290
5291========================================================================== */
5292OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
5293 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5294{
5295 int push_cnt = 0,i=0;
5296 unsigned nPortIndex = 0;
5297 OMX_ERRORTYPE ret = OMX_ErrorNone;
5298 struct vdec_input_frameinfo frameinfo;
5299 struct vdec_bufferpayload *temp_buffer;
5300 struct vdec_ioctl_msg ioctl_msg;
5301 struct vdec_seqheader seq_header;
5302 bool port_setting_changed = true;
5303 bool not_coded_vop = false;
5304
5305 /*Should we generate a Aync error event*/
5306 if (buffer == NULL || buffer->pInputPortPrivate == NULL)
5307 {
5308 DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy is invalid");
5309 return OMX_ErrorBadParameter;
5310 }
5311
5312 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
5313
5314 if (nPortIndex > drv_ctx.ip_buf.actualcount)
5315 {
5316 DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
5317 nPortIndex);
5318 return OMX_ErrorBadParameter;
5319 }
5320
5321 pending_input_buffers++;
5322
5323 /* return zero length and not an EOS buffer */
5324 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
5325 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5326 {
5327 DEBUG_PRINT_HIGH("\n return zero legth buffer");
5328 post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5329 OMX_COMPONENT_GENERATE_EBD);
5330 return OMX_ErrorNone;
5331 }
5332
5333
5334 if(codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX){
5335 mp4StreamType psBits;
5336 psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset);
5337 psBits.numBytes = buffer->nFilledLen;
5338 mp4_headerparser.parseHeader(&psBits);
5339 not_coded_vop = mp4_headerparser.is_notcodec_vop(
5340 (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5341 if(not_coded_vop) {
5342 DEBUG_PRINT_HIGH("\n Found Not coded vop len %d frame number %d",
5343 buffer->nFilledLen,frame_count);
5344 if(buffer->nFlags & OMX_BUFFERFLAG_EOS){
5345 DEBUG_PRINT_HIGH("\n Eos and Not coded Vop set len to zero");
5346 not_coded_vop = false;
5347 buffer->nFilledLen = 0;
5348 }
5349 }
5350 }
5351
5352 if(input_flush_progress == true
5353
5354 || not_coded_vop
5355
5356 )
5357 {
5358 DEBUG_PRINT_LOW("\n Flush in progress return buffer ");
5359 post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
5360 OMX_COMPONENT_GENERATE_EBD);
5361 return OMX_ErrorNone;
5362 }
5363
5364 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
5365
5366 if ((temp_buffer - drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount)
5367 {
5368 return OMX_ErrorBadParameter;
5369 }
5370
5371 DEBUG_PRINT_LOW("\n ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5372 /*for use buffer we need to memcpy the data*/
5373 temp_buffer->buffer_len = buffer->nFilledLen;
5374
5375 if (input_use_buffer)
5376 {
5377 if (buffer->nFilledLen <= temp_buffer->buffer_len)
5378 {
5379 if(arbitrary_bytes)
5380 {
5381 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
5382 }
5383 else
5384 {
5385 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
5386 buffer->nFilledLen);
5387 }
5388 }
5389 else
5390 {
5391 return OMX_ErrorBadParameter;
5392 }
5393
5394 }
5395
5396 frameinfo.bufferaddr = temp_buffer->bufferaddr;
5397 frameinfo.client_data = (void *) buffer;
5398 frameinfo.datalen = temp_buffer->buffer_len;
5399 frameinfo.flags = 0;
5400 frameinfo.offset = buffer->nOffset;
5401 frameinfo.pmem_fd = temp_buffer->pmem_fd;
5402 frameinfo.pmem_offset = temp_buffer->offset;
5403 frameinfo.timestamp = buffer->nTimeStamp;
5404 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr)
5405 {
5406 DEBUG_PRINT_LOW("ETB: dmx enabled");
5407 if (m_demux_entries == 0)
5408 {
5409 extract_demux_addr_offsets(buffer);
5410 }
5411
5412 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries);
5413 handle_demux_data(buffer);
5414 frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
5415 frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
5416 }
5417 else
5418 {
5419 frameinfo.desc_addr = NULL;
5420 frameinfo.desc_size = 0;
5421 }
5422 if(!arbitrary_bytes)
5423 {
5424 frameinfo.flags |= buffer->nFlags;
5425 }
5426
5427#ifdef _ANDROID_
5428 if (m_debug_timestamp)
5429 {
5430 if(arbitrary_bytes)
5431 {
5432 DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5433 m_timestamp_list.insert_ts(buffer->nTimeStamp);
5434 }
5435 else if(!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG))
5436 {
5437 DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
5438 m_timestamp_list.insert_ts(buffer->nTimeStamp);
5439 }
5440 }
5441#endif
5442
5443#ifdef INPUT_BUFFER_LOG
5444 if (inputBufferFile1)
5445 {
5446 fwrite((const char *)temp_buffer->bufferaddr,
5447 temp_buffer->buffer_len,1,inputBufferFile1);
5448 }
5449#endif
5450
5451 if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ)
5452 {
5453 frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5454 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
5455 }
5456
5457 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS))
5458 {
5459 DEBUG_PRINT_HIGH("\n Rxd i/p EOS, Notify Driver that EOS has been reached");
5460 frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
5461 h264_scratch.nFilledLen = 0;
5462 nal_count = 0;
5463 look_ahead_nal = false;
5464 frame_count = 0;
5465 if (m_frame_parser.mutils)
5466 m_frame_parser.mutils->initialize_frame_checking_environment();
5467 m_frame_parser.flush();
5468 h264_last_au_ts = LLONG_MAX;
5469 h264_last_au_flags = 0;
5470 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
5471 m_demux_entries = 0;
5472 }
5473 struct v4l2_buffer buf = {0};
5474 struct v4l2_plane plane;
5475 int rc;
5476 unsigned long print_count;
5477 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS))
5478 { buf.flags = V4L2_BUF_FLAG_EOS;
Ashray Kulkarni46373df2012-06-05 20:11:31 -07005479 DEBUG_PRINT_HIGH("\n INPUT EOS reached \n") ;
Shalaj Jain273b3e02012-06-22 19:08:03 -07005480 }
5481 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5482 buf.index = nPortIndex;
5483 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5484 buf.memory = V4L2_MEMORY_USERPTR;
5485 plane.bytesused = temp_buffer->buffer_len;
5486 plane.length = drv_ctx.ip_buf.buffer_size;
5487 plane.m.userptr = (unsigned long)(temp_buffer->bufferaddr-temp_buffer->offset);
5488 plane.reserved[0] = temp_buffer->pmem_fd;
5489 plane.reserved[1] = temp_buffer->offset;
5490 plane.data_offset = 0;
5491 buf.m.planes = &plane;
5492 buf.length = 1;
5493 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5494 if(!streaming[OUTPUT_PORT])
5495 {
5496 enum v4l2_buf_type buf_type;
5497 int ret,r;
Vinay Kalia85793762012-06-14 19:12:34 -07005498
5499 struct v4l2_control control;
5500 control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
5501 control.value = 1;
5502 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
5503 if(ret)
5504 printf("\n Continue data Xfer failed \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07005505 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5506 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
5507 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
5508 if(!ret) {
Ashray Kulkarni46373df2012-06-05 20:11:31 -07005509 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07005510 streaming[OUTPUT_PORT] = true;
5511 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
5512 if(ret < 0)
Ashray Kulkarni46373df2012-06-05 20:11:31 -07005513 DEBUG_PRINT_ERROR("\n Failed to create async_message_thread \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07005514 } else{
5515 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -07005516 DEBUG_PRINT_ERROR(" \n Failed to call streamon on OUTPUT \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07005517 }
5518}
5519 DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)",
5520 frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen);
5521 time_stamp_dts.insert_timestamp(buffer);
5522
5523 return ret;
5524}
5525
5526/* ======================================================================
5527FUNCTION
5528 omx_vdec::FillThisBuffer
5529
5530DESCRIPTION
5531 IL client uses this method to release the frame buffer
5532 after displaying them.
5533
5534PARAMETERS
5535 None.
5536
5537RETURN VALUE
5538 true/false
5539
5540========================================================================== */
5541OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
5542 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
5543{
5544
5545 if(m_state == OMX_StateInvalid)
5546 {
5547 DEBUG_PRINT_ERROR("FTB in Invalid State\n");
5548 return OMX_ErrorInvalidState;
5549 }
5550
5551 if (!m_out_bEnabled)
5552 {
5553 DEBUG_PRINT_ERROR("\nERROR:FTB incorrect state operation, output port is disabled.");
5554 return OMX_ErrorIncorrectStateOperation;
5555 }
5556
5557 if (buffer == NULL || ((buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount))
5558 {
5559 return OMX_ErrorBadParameter;
5560 }
5561
5562 if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX)
5563 {
5564 DEBUG_PRINT_ERROR("\nERROR:FTB invalid port in header %d", buffer->nOutputPortIndex);
5565 return OMX_ErrorBadPortIndex;
5566 }
5567
5568 DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
5569 post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB);
5570 return OMX_ErrorNone;
5571}
5572/* ======================================================================
5573FUNCTION
5574 omx_vdec::fill_this_buffer_proxy
5575
5576DESCRIPTION
5577 IL client uses this method to release the frame buffer
5578 after displaying them.
5579
5580PARAMETERS
5581 None.
5582
5583RETURN VALUE
5584 true/false
5585
5586========================================================================== */
5587OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
5588 OMX_IN OMX_HANDLETYPE hComp,
5589 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
5590{
5591 OMX_ERRORTYPE nRet = OMX_ErrorNone;
5592 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
5593 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
5594 unsigned nPortIndex = 0;
5595 struct vdec_fillbuffer_cmd fillbuffer;
5596 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
5597 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
5598
5599 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_out_mem_ptr);
5600
5601 if (bufferAdd == NULL || ((buffer - m_out_mem_ptr) >
5602 drv_ctx.op_buf.actualcount) )
5603 return OMX_ErrorBadParameter;
5604
5605 DEBUG_PRINT_LOW("\n FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
5606 bufferAdd, bufferAdd->pBuffer);
5607 /*Return back the output buffer to client*/
5608 if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true)
5609 {
5610 DEBUG_PRINT_LOW("\n Output Buffers return flush/disable condition");
5611 buffer->nFilledLen = 0;
5612 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5613 return OMX_ErrorNone;
5614 }
5615 pending_output_buffers++;
5616 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
5617 if (ptr_respbuffer)
5618 {
5619 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
5620 }
5621
5622 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL)
5623 {
5624 DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
5625 buffer->nFilledLen = 0;
5626 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5627 pending_output_buffers--;
5628 return OMX_ErrorBadParameter;
5629 }
5630
5631 // memcpy (&fillbuffer.buffer,ptr_outputbuffer,\
5632 sizeof(struct vdec_bufferpayload));
5633 // fillbuffer.client_data = bufferAdd;
5634
5635#ifdef _ANDROID_ICS_
5636 if (m_enable_android_native_buffers)
5637 {
5638 // Acquire a write lock on this buffer.
5639 if (GENLOCK_NO_ERROR != genlock_lock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle,
5640 GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
5641 DEBUG_PRINT_ERROR("Failed to acquire genlock");
5642 buffer->nFilledLen = 0;
5643 m_cb.FillBufferDone (hComp,m_app_data,buffer);
5644 pending_output_buffers--;
5645 return OMX_ErrorInsufficientResources;
5646 } else {
5647 native_buffer[buffer - m_out_mem_ptr].inuse = true;
5648 }
5649 }
5650#endif
5651 int rc = 0;
5652 struct v4l2_buffer buf={0};
5653 struct v4l2_plane plane;
5654
5655 buf.index = nPortIndex;
5656 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5657 buf.memory = V4L2_MEMORY_USERPTR;
5658 plane.bytesused = buffer->nFilledLen;
5659 plane.length = drv_ctx.op_buf.buffer_size;
5660 plane.m.userptr = (unsigned long)(drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr-drv_ctx.ptr_outputbuffer[nPortIndex].offset);
5661 plane.reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
5662 plane.reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
5663 plane.data_offset = 0;
5664 buf.m.planes = &plane;
5665 buf.length = 1;
5666
5667 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
5668 if (rc) {
5669 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -07005670 DEBUG_PRINT_ERROR("Failed to qbuf to driver");
Shalaj Jain273b3e02012-06-22 19:08:03 -07005671 }
5672//#ifdef _ANDROID_ICS_
5673 // if (m_enable_android_native_buffers)
5674 // {
5675 // Unlock the buffer
5676 // if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) {
5677 // DEBUG_PRINT_ERROR("Releasing genlock failed");
5678 // return OMX_ErrorInsufficientResources;
5679 /// } else {
5680 // native_buffer[buffer - m_out_mem_ptr].inuse = false;
5681 // }
5682 // }
5683//#endif
5684 //m_cb.FillBufferDone (hComp,m_app_data,buffer);
5685 // pending_output_buffers--;
5686 // return OMX_ErrorBadParameter;
5687 //}
5688 return OMX_ErrorNone;
5689}
5690
5691/* ======================================================================
5692FUNCTION
5693 omx_vdec::SetCallbacks
5694
5695DESCRIPTION
5696 Set the callbacks.
5697
5698PARAMETERS
5699 None.
5700
5701RETURN VALUE
5702 OMX Error None if everything successful.
5703
5704========================================================================== */
5705OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
5706 OMX_IN OMX_CALLBACKTYPE* callbacks,
5707 OMX_IN OMX_PTR appData)
5708{
5709
5710 m_cb = *callbacks;
5711 DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
5712 m_cb.EventHandler,m_cb.FillBufferDone);
5713 m_app_data = appData;
5714 return OMX_ErrorNotImplemented;
5715}
5716
5717/* ======================================================================
5718FUNCTION
5719 omx_vdec::ComponentDeInit
5720
5721DESCRIPTION
5722 Destroys the component and release memory allocated to the heap.
5723
5724PARAMETERS
5725 <TBD>.
5726
5727RETURN VALUE
5728 OMX Error None if everything successful.
5729
5730========================================================================== */
5731OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
5732{
5733#ifdef _ANDROID_
5734 if(iDivXDrmDecrypt)
5735 {
5736 delete iDivXDrmDecrypt;
5737 iDivXDrmDecrypt=NULL;
5738 }
5739#endif //_ANDROID_
5740
5741 int i = 0;
5742 if (OMX_StateLoaded != m_state)
5743 {
5744 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\
5745 m_state);
5746 DEBUG_PRINT_ERROR("\nPlayback Ended - FAILED");
5747 }
5748 else
5749 {
5750 DEBUG_PRINT_HIGH("\n Playback Ended - PASSED");
5751 }
5752
5753 /*Check if the output buffers have to be cleaned up*/
5754 if(m_out_mem_ptr)
5755 {
5756 DEBUG_PRINT_LOW("Freeing the Output Memory\n");
5757 for (i=0; i < drv_ctx.op_buf.actualcount; i++ )
5758 {
5759 free_output_buffer (&m_out_mem_ptr[i]);
5760#ifdef _ANDROID_ICS_
5761 if (m_enable_android_native_buffers)
5762 {
5763 if (native_buffer[i].inuse)
5764 {
5765 if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[i].nativehandle)) {
5766 DEBUG_PRINT_ERROR("Unlocking genlock failed");
5767 }
5768 native_buffer[i].inuse = false;
5769 }
5770 }
5771#endif
5772 }
5773#ifdef _ANDROID_ICS_
5774 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
5775#endif
5776 }
5777
5778 /*Check if the input buffers have to be cleaned up*/
5779 if(m_inp_mem_ptr || m_inp_heap_ptr)
5780 {
5781 DEBUG_PRINT_LOW("Freeing the Input Memory\n");
5782 for (i=0; i<drv_ctx.ip_buf.actualcount; i++ )
5783 {
5784 if (m_inp_mem_ptr)
5785 free_input_buffer (i,&m_inp_mem_ptr[i]);
5786 else
5787 free_input_buffer (i,NULL);
5788 }
5789 }
5790 free_input_buffer_header();
5791 free_output_buffer_header();
5792 if(h264_scratch.pBuffer)
5793 {
5794 free(h264_scratch.pBuffer);
5795 h264_scratch.pBuffer = NULL;
5796 }
5797
5798 if (h264_parser)
5799 {
5800 delete h264_parser;
5801 h264_parser = NULL;
5802 }
5803
5804 if(m_platform_list)
5805 {
5806 free(m_platform_list);
5807 m_platform_list = NULL;
5808 }
5809 if(m_vendor_config.pData)
5810 {
5811 free(m_vendor_config.pData);
5812 m_vendor_config.pData = NULL;
5813 }
5814
5815 // Reset counters in mesg queues
5816 m_ftb_q.m_size=0;
5817 m_cmd_q.m_size=0;
5818 m_etb_q.m_size=0;
5819 m_ftb_q.m_read = m_ftb_q.m_write =0;
5820 m_cmd_q.m_read = m_cmd_q.m_write =0;
5821 m_etb_q.m_read = m_etb_q.m_write =0;
5822#ifdef _ANDROID_
5823 if (m_debug_timestamp)
5824 {
5825 m_timestamp_list.reset_ts_list();
5826 }
5827#endif
5828
5829 DEBUG_PRINT_LOW("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
5830 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
5831 // NULL);
5832 DEBUG_PRINT_HIGH("\n Close the driver instance");
5833
5834#ifdef INPUT_BUFFER_LOG
5835 fclose (inputBufferFile1);
5836#endif
5837#ifdef OUTPUT_BUFFER_LOG
5838 fclose (outputBufferFile1);
5839#endif
5840#ifdef OUTPUT_EXTRADATA_LOG
5841 fclose (outputExtradataFile);
5842#endif
5843 DEBUG_PRINT_HIGH("\n omx_vdec::component_deinit() complete");
5844 return OMX_ErrorNone;
5845}
5846
5847/* ======================================================================
5848FUNCTION
5849 omx_vdec::UseEGLImage
5850
5851DESCRIPTION
5852 OMX Use EGL Image method implementation <TBD>.
5853
5854PARAMETERS
5855 <TBD>.
5856
5857RETURN VALUE
5858 Not Implemented error.
5859
5860========================================================================== */
5861OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
5862 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5863 OMX_IN OMX_U32 port,
5864 OMX_IN OMX_PTR appData,
5865 OMX_IN void* eglImage)
5866{
5867 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
5868 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
5869 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
5870
5871#ifdef USE_EGL_IMAGE_GPU
5872 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
5873 EGLint fd = -1, offset = 0,pmemPtr = 0;
5874#else
5875 int fd = -1, offset = 0;
5876#endif
5877 DEBUG_PRINT_HIGH("\nuse EGL image support for decoder");
5878 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
5879 DEBUG_PRINT_ERROR("\n ");
5880 }
5881#ifdef USE_EGL_IMAGE_GPU
5882 if(m_display_id == NULL) {
5883 DEBUG_PRINT_ERROR("Display ID is not set by IL client \n");
5884 return OMX_ErrorInsufficientResources;
5885 }
5886 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
5887 eglGetProcAddress("eglQueryImageKHR");
5888 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd);
5889 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset);
5890 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr);
5891#else //with OMX test app
5892 struct temp_egl {
5893 int pmem_fd;
5894 int offset;
5895 };
5896 struct temp_egl *temp_egl_id = NULL;
5897 void * pmemPtr = (void *) eglImage;
5898 temp_egl_id = (struct temp_egl *)eglImage;
5899 if (temp_egl_id != NULL)
5900 {
5901 fd = temp_egl_id->pmem_fd;
5902 offset = temp_egl_id->offset;
5903 }
5904#endif
5905 if (fd < 0) {
5906 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d \n",fd);
5907 return OMX_ErrorInsufficientResources;
5908 }
5909 pmem_info.pmem_fd = (OMX_U32) fd;
5910 pmem_info.offset = (OMX_U32) offset;
5911 pmem_entry.entry = (void *) &pmem_info;
5912 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
5913 pmem_list.entryList = &pmem_entry;
5914 pmem_list.nEntries = 1;
5915 ouput_egl_buffers = true;
5916 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
5917 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
5918 (OMX_U8 *)pmemPtr)) {
5919 DEBUG_PRINT_ERROR("use buffer call failed for egl image\n");
5920 return OMX_ErrorInsufficientResources;
5921 }
5922 return OMX_ErrorNone;
5923}
5924
5925/* ======================================================================
5926FUNCTION
5927 omx_vdec::ComponentRoleEnum
5928
5929DESCRIPTION
5930 OMX Component Role Enum method implementation.
5931
5932PARAMETERS
5933 <TBD>.
5934
5935RETURN VALUE
5936 OMX Error None if everything is successful.
5937========================================================================== */
5938OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
5939 OMX_OUT OMX_U8* role,
5940 OMX_IN OMX_U32 index)
5941{
5942 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5943
5944 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
5945 {
5946 if((0 == index) && role)
5947 {
5948 strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
5949 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
5950 }
5951 else
5952 {
5953 eRet = OMX_ErrorNoMore;
5954 }
5955 }
5956 if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
5957 {
5958 if((0 == index) && role)
5959 {
5960 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
5961 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
5962 }
5963 else
5964 {
5965 eRet = OMX_ErrorNoMore;
5966 }
5967 }
5968 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
5969 {
5970 if((0 == index) && role)
5971 {
5972 strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
5973 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
5974 }
5975 else
5976 {
5977 DEBUG_PRINT_LOW("\n No more roles \n");
5978 eRet = OMX_ErrorNoMore;
5979 }
5980 }
5981
5982 else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
5983 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
5984 )
5985
5986 {
5987 if((0 == index) && role)
5988 {
5989 strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
5990 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
5991 }
5992 else
5993 {
5994 DEBUG_PRINT_LOW("\n No more roles \n");
5995 eRet = OMX_ErrorNoMore;
5996 }
5997 }
5998 else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
5999 {
6000 if((0 == index) && role)
6001 {
6002 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
6003 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
6004 }
6005 else
6006 {
6007 DEBUG_PRINT_LOW("\n No more roles \n");
6008 eRet = OMX_ErrorNoMore;
6009 }
6010 }
6011 else if( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
6012 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
6013 )
6014 {
6015 if((0 == index) && role)
6016 {
6017 strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
6018 DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
6019 }
6020 else
6021 {
6022 DEBUG_PRINT_LOW("\n No more roles \n");
6023 eRet = OMX_ErrorNoMore;
6024 }
6025 }
6026 else
6027 {
6028 DEBUG_PRINT_ERROR("\nERROR:Querying Role on Unknown Component\n");
6029 eRet = OMX_ErrorInvalidComponentName;
6030 }
6031 return eRet;
6032}
6033
6034
6035
6036
6037/* ======================================================================
6038FUNCTION
6039 omx_vdec::AllocateDone
6040
6041DESCRIPTION
6042 Checks if entire buffer pool is allocated by IL Client or not.
6043 Need this to move to IDLE state.
6044
6045PARAMETERS
6046 None.
6047
6048RETURN VALUE
6049 true/false.
6050
6051========================================================================== */
6052bool omx_vdec::allocate_done(void)
6053{
6054 bool bRet = false;
6055 bool bRet_In = false;
6056 bool bRet_Out = false;
6057
6058 bRet_In = allocate_input_done();
6059 bRet_Out = allocate_output_done();
6060
6061 if(bRet_In && bRet_Out)
6062 {
6063 bRet = true;
6064 }
6065
6066 return bRet;
6067}
6068/* ======================================================================
6069FUNCTION
6070 omx_vdec::AllocateInputDone
6071
6072DESCRIPTION
6073 Checks if I/P buffer pool is allocated by IL Client or not.
6074
6075PARAMETERS
6076 None.
6077
6078RETURN VALUE
6079 true/false.
6080
6081========================================================================== */
6082bool omx_vdec::allocate_input_done(void)
6083{
6084 bool bRet = false;
6085 unsigned i=0;
6086
6087 if (m_inp_mem_ptr == NULL)
6088 {
6089 return bRet;
6090 }
6091 if(m_inp_mem_ptr )
6092 {
6093 for(;i<drv_ctx.ip_buf.actualcount;i++)
6094 {
6095 if(BITMASK_ABSENT(&m_inp_bm_count,i))
6096 {
6097 break;
6098 }
6099 }
6100 }
6101 if(i == drv_ctx.ip_buf.actualcount)
6102 {
6103 bRet = true;
6104 DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
6105 }
6106 if(i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled)
6107 {
6108 m_inp_bPopulated = OMX_TRUE;
6109 }
6110 return bRet;
6111}
6112/* ======================================================================
6113FUNCTION
6114 omx_vdec::AllocateOutputDone
6115
6116DESCRIPTION
6117 Checks if entire O/P buffer pool is allocated by IL Client or not.
6118
6119PARAMETERS
6120 None.
6121
6122RETURN VALUE
6123 true/false.
6124
6125========================================================================== */
6126bool omx_vdec::allocate_output_done(void)
6127{
6128 bool bRet = false;
6129 unsigned j=0;
6130
6131 if (m_out_mem_ptr == NULL)
6132 {
6133 return bRet;
6134 }
6135
6136 if (m_out_mem_ptr)
6137 {
6138 for(;j < drv_ctx.op_buf.actualcount;j++)
6139 {
6140 if(BITMASK_ABSENT(&m_out_bm_count,j))
6141 {
6142 break;
6143 }
6144 }
6145 }
6146
6147 if(j == drv_ctx.op_buf.actualcount)
6148 {
6149 bRet = true;
6150 DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
6151 if(m_out_bEnabled)
6152 m_out_bPopulated = OMX_TRUE;
6153 }
6154
6155 return bRet;
6156}
6157
6158/* ======================================================================
6159FUNCTION
6160 omx_vdec::ReleaseDone
6161
6162DESCRIPTION
6163 Checks if IL client has released all the buffers.
6164
6165PARAMETERS
6166 None.
6167
6168RETURN VALUE
6169 true/false
6170
6171========================================================================== */
6172bool omx_vdec::release_done(void)
6173{
6174 bool bRet = false;
6175
6176 if(release_input_done())
6177 {
6178 if(release_output_done())
6179 {
6180 bRet = true;
6181 }
6182 }
6183 return bRet;
6184}
6185
6186
6187/* ======================================================================
6188FUNCTION
6189 omx_vdec::ReleaseOutputDone
6190
6191DESCRIPTION
6192 Checks if IL client has released all the buffers.
6193
6194PARAMETERS
6195 None.
6196
6197RETURN VALUE
6198 true/false
6199
6200========================================================================== */
6201bool omx_vdec::release_output_done(void)
6202{
6203 bool bRet = false;
6204 unsigned i=0,j=0;
6205
6206 DEBUG_PRINT_LOW("\n Value of m_out_mem_ptr %p",m_inp_mem_ptr);
6207 if(m_out_mem_ptr)
6208 {
6209 for(;j < drv_ctx.op_buf.actualcount ; j++)
6210 {
6211 if(BITMASK_PRESENT(&m_out_bm_count,j))
6212 {
6213 break;
6214 }
6215 }
6216 if(j == drv_ctx.op_buf.actualcount)
6217 {
6218 m_out_bm_count = 0;
6219 bRet = true;
6220 }
6221 }
6222 else
6223 {
6224 m_out_bm_count = 0;
6225 bRet = true;
6226 }
6227 return bRet;
6228}
6229/* ======================================================================
6230FUNCTION
6231 omx_vdec::ReleaseInputDone
6232
6233DESCRIPTION
6234 Checks if IL client has released all the buffers.
6235
6236PARAMETERS
6237 None.
6238
6239RETURN VALUE
6240 true/false
6241
6242========================================================================== */
6243bool omx_vdec::release_input_done(void)
6244{
6245 bool bRet = false;
6246 unsigned i=0,j=0;
6247
6248 DEBUG_PRINT_LOW("\n Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
6249 if(m_inp_mem_ptr)
6250 {
6251 for(;j<drv_ctx.ip_buf.actualcount;j++)
6252 {
6253 if( BITMASK_PRESENT(&m_inp_bm_count,j))
6254 {
6255 break;
6256 }
6257 }
6258 if(j==drv_ctx.ip_buf.actualcount)
6259 {
6260 bRet = true;
6261 }
6262 }
6263 else
6264 {
6265 bRet = true;
6266 }
6267 return bRet;
6268}
6269
6270OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
6271 OMX_BUFFERHEADERTYPE * buffer)
6272{
6273 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
6274 if (!buffer || (buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount)
6275 {
6276 DEBUG_PRINT_ERROR("\n [FBD] ERROR in ptr(%p)", buffer);
6277 return OMX_ErrorBadParameter;
6278 }
6279 else if (output_flush_progress)
6280 {
6281 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
6282 buffer->nFilledLen = 0;
6283 buffer->nTimeStamp = 0;
6284 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
6285 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
6286 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
6287 }
6288
6289 DEBUG_PRINT_LOW("\n fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
6290 buffer, buffer->pBuffer);
6291 pending_output_buffers --;
6292
6293 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
6294 {
6295 DEBUG_PRINT_HIGH("\n Output EOS has been reached");
6296 if (!output_flush_progress)
6297 post_event(NULL,NULL,OMX_COMPONENT_GENERATE_EOS_DONE);
6298
6299 if (psource_frame)
6300 {
6301 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
6302 psource_frame = NULL;
6303 }
6304 if (pdest_frame)
6305 {
6306 pdest_frame->nFilledLen = 0;
6307 m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
6308 pdest_frame = NULL;
6309 }
6310 }
6311
6312 DEBUG_PRINT_LOW("\n In fill Buffer done call address %p ",buffer);
6313#ifdef OUTPUT_BUFFER_LOG
6314 if (outputBufferFile1)
6315 {
6316 fwrite (buffer->pBuffer,1,buffer->nFilledLen,
6317 outputBufferFile1);
6318 }
6319#endif
6320
6321 /* For use buffer we need to copy the data */
6322 if (!output_flush_progress)
6323 {
6324 time_stamp_dts.get_next_timestamp(buffer,
6325 (drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
6326 ?true:false);
6327 }
6328 if (m_cb.FillBufferDone)
6329 {
6330 if (buffer->nFilledLen > 0)
6331 {
6332 if (client_extradata)
6333 handle_extradata(buffer);
6334 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
6335 // Keep min timestamp interval to handle corrupted bit stream scenario
6336 set_frame_rate(buffer->nTimeStamp);
6337 else if (arbitrary_bytes)
6338 adjust_timestamp(buffer->nTimeStamp);
6339 if (perf_flag)
6340 {
6341 if (!proc_frms)
6342 {
6343 dec_time.stop();
6344 latency = dec_time.processing_time_us() - latency;
6345 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
6346 dec_time.start();
6347 fps_metrics.start();
6348 }
6349 proc_frms++;
6350 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
6351 {
6352 OMX_U64 proc_time = 0;
6353 fps_metrics.stop();
6354 proc_time = fps_metrics.processing_time_us();
6355 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)",
6356 proc_frms, (float)proc_time / 1e6,
6357 (float)(1e6 * proc_frms) / proc_time);
6358 proc_frms = 0;
6359 }
6360 }
6361
6362#ifdef OUTPUT_EXTRADATA_LOG
6363 if (outputExtradataFile)
6364 {
6365
6366 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
6367 p_extra = (OMX_OTHER_EXTRADATATYPE *)
6368 ((unsigned)(buffer->pBuffer + buffer->nOffset +
6369 buffer->nFilledLen + 3)&(~3));
6370 while(p_extra &&
6371 (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) )
6372 {
6373 DEBUG_PRINT_LOW("\nWRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType);
6374 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
6375 if (p_extra->eType == OMX_ExtraDataNone)
6376 {
6377 break;
6378 }
6379 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
6380 }
6381 }
6382#endif
6383 }
6384 if (buffer->nFlags & OMX_BUFFERFLAG_EOS){
6385 prev_ts = LLONG_MAX;
6386 rst_prev_ts = true;
6387 }
6388
6389 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6390 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
6391 buffer->pPlatformPrivate)->entryList->entry;
6392 DEBUG_PRINT_LOW("\n Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd);
6393#ifdef _ANDROID_ICS_
6394 if (m_enable_android_native_buffers)
6395 {
6396 if (native_buffer[buffer - m_out_mem_ptr].inuse) {
6397 if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) {
6398 DEBUG_PRINT_ERROR("Unlocking genlock failed");
6399 return OMX_ErrorInsufficientResources;
6400 }
6401 else {
6402 native_buffer[buffer - m_out_mem_ptr].inuse = false;
6403 }
6404 }
6405 }
6406#endif
6407 m_cb.FillBufferDone (hComp,m_app_data,buffer);
6408 DEBUG_PRINT_LOW("\n After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd);
6409 }
6410 else
6411 {
6412 return OMX_ErrorBadParameter;
6413 }
6414
6415 return OMX_ErrorNone;
6416}
6417
6418OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
6419 OMX_BUFFERHEADERTYPE* buffer)
6420{
6421
6422 if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount))
6423 {
6424 DEBUG_PRINT_ERROR("\n empty_buffer_done: ERROR bufhdr = %p", buffer);
6425 return OMX_ErrorBadParameter;
6426 }
6427
6428 DEBUG_PRINT_LOW("\n empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
6429 buffer, buffer->pBuffer);
6430 pending_input_buffers--;
6431
6432 if (arbitrary_bytes)
6433 {
6434 if (pdest_frame == NULL && input_flush_progress == false)
6435 {
6436 DEBUG_PRINT_LOW("\n Push input from buffer done address of Buffer %p",buffer);
6437 pdest_frame = buffer;
6438 buffer->nFilledLen = 0;
6439 buffer->nTimeStamp = LLONG_MAX;
6440 push_input_buffer (hComp);
6441 }
6442 else
6443 {
6444 DEBUG_PRINT_LOW("\n Push buffer into freeq address of Buffer %p",buffer);
6445 buffer->nFilledLen = 0;
6446 if (!m_input_free_q.insert_entry((unsigned)buffer,NULL,NULL))
6447 {
6448 DEBUG_PRINT_ERROR("\nERROR:i/p free Queue is FULL Error");
6449 }
6450 }
6451 }
6452 else if(m_cb.EmptyBufferDone)
6453 {
6454 buffer->nFilledLen = 0;
6455 if (input_use_buffer == true){
6456 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
6457 }
6458 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
6459 }
6460 return OMX_ErrorNone;
6461}
6462
6463
6464int omx_vdec::async_message_process (void *context, void* message)
6465{
6466 omx_vdec* omx = NULL;
6467 struct vdec_msginfo *vdec_msg = NULL;
6468 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
6469 struct v4l2_buffer *v4l2_buf_ptr=NULL;
6470 struct vdec_output_frameinfo *output_respbuf = NULL;
6471 int rc=1;
6472 if (context == NULL || message == NULL)
6473 {
6474 DEBUG_PRINT_ERROR("\n FATAL ERROR in omx_vdec::async_message_process NULL Check");
6475 return -1;
6476 }
6477 vdec_msg = (struct vdec_msginfo *)message;
6478
6479 omx = reinterpret_cast<omx_vdec*>(context);
6480
6481#ifdef _ANDROID_
6482 if (omx->m_debug_timestamp)
6483 {
6484 if ( (vdec_msg->msgcode == VDEC_MSG_RESP_OUTPUT_BUFFER_DONE) &&
6485 !(omx->output_flush_progress) )
6486 {
6487 OMX_TICKS expected_ts = 0;
6488 omx->m_timestamp_list.pop_min_ts(expected_ts);
6489 DEBUG_PRINT_LOW("\n Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
6490 vdec_msg->msgdata.output_frame.time_stamp, expected_ts);
6491
6492 if (vdec_msg->msgdata.output_frame.time_stamp != expected_ts)
6493 {
6494 DEBUG_PRINT_ERROR("\n ERROR in omx_vdec::async_message_process timestamp Check");
6495 }
6496 }
6497 }
6498#endif
6499
6500 switch (vdec_msg->msgcode)
6501 {
6502
6503 case VDEC_MSG_EVT_HW_ERROR:
6504 omx->post_event (NULL,vdec_msg->status_code,\
6505 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6506 break;
6507
6508 case VDEC_MSG_RESP_START_DONE:
6509 omx->post_event (NULL,vdec_msg->status_code,\
6510 OMX_COMPONENT_GENERATE_START_DONE);
6511 break;
6512
6513 case VDEC_MSG_RESP_STOP_DONE:
6514 omx->post_event (NULL,vdec_msg->status_code,\
6515 OMX_COMPONENT_GENERATE_STOP_DONE);
6516 break;
6517
6518 case VDEC_MSG_RESP_RESUME_DONE:
6519 omx->post_event (NULL,vdec_msg->status_code,\
6520 OMX_COMPONENT_GENERATE_RESUME_DONE);
6521 break;
6522
6523 case VDEC_MSG_RESP_PAUSE_DONE:
6524 omx->post_event (NULL,vdec_msg->status_code,\
6525 OMX_COMPONENT_GENERATE_PAUSE_DONE);
6526 break;
6527
6528 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
6529 omx->post_event (NULL,vdec_msg->status_code,\
6530 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
6531 break;
6532 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
6533 omx->post_event (NULL,vdec_msg->status_code,\
6534 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
6535 break;
6536 case VDEC_MSG_RESP_INPUT_FLUSHED:
6537 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
6538
6539 // omxhdr = (OMX_BUFFERHEADERTYPE* ) \
6540 // vdec_msg->msgdata.input_frame_clientdata;
6541
6542 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
6543 omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index;
6544 if (omxhdr == NULL ||
6545 ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) )
6546 {
6547 omxhdr = NULL;
6548 vdec_msg->status_code = VDEC_S_EFATAL;
6549 }
6550
6551 omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
6552 OMX_COMPONENT_GENERATE_EBD);
6553 break;
6554 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
6555 int64_t *timestamp;
6556 timestamp = (int64_t *) malloc(sizeof(int64_t));
6557 if (timestamp) {
6558 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
6559 omx->post_event ((unsigned int)timestamp, vdec_msg->status_code,
6560 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
6561 DEBUG_PRINT_HIGH("\nField dropped time stamp is %lld",
6562 vdec_msg->msgdata.output_frame.time_stamp);
6563 }
6564 break;
6565 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
6566 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
6567
6568 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
6569 omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index;
6570 DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)",
6571 omxhdr, vdec_msg->msgdata.output_frame.time_stamp,
6572 vdec_msg->msgdata.output_frame.pic_type);
6573
6574 if (omxhdr && omxhdr->pOutputPortPrivate &&
6575 ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) &&
6576 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
6577 - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount))
6578 {
6579 if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen)
6580 {
6581 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
6582 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
6583 omxhdr->nTimeStamp = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nTimeStamp;
6584 omxhdr->nFlags = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nFlags;
6585
6586 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_EOS)
6587 {
6588 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
6589 //rc = -1;
6590 }
6591 vdec_msg->msgdata.output_frame.bufferaddr=omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
6592 output_respbuf = (struct vdec_output_frameinfo *)\
6593 omxhdr->pOutputPortPrivate;
6594 // output_respbuf->framesize.bottom =
6595 // vdec_msg->msgdata.output_frame.framesize.bottom;
6596 // output_respbuf->framesize.left =
6597 // vdec_msg->msgdata.output_frame.framesize.left;
6598 // output_respbuf->framesize.right =
6599 // vdec_msg->msgdata.output_frame.framesize.right;
6600 // output_respbuf->framesize.top =
6601 // vdec_msg->msgdata.output_frame.framesize.top;
6602 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
6603 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
6604 // output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp;
6605 // output_respbuf->flags = vdec_msg->msgdata.output_frame.flags;
6606 // output_respbuf->pic_type = vdec_msg->msgdata.output_frame.pic_type;
6607 // output_respbuf->interlaced_format = vdec_msg->msgdata.output_frame.interlaced_format;
6608
6609 if (omx->output_use_buffer)
6610 memcpy ( omxhdr->pBuffer,
6611 (vdec_msg->msgdata.output_frame.bufferaddr +
6612 vdec_msg->msgdata.output_frame.offset),
6613 vdec_msg->msgdata.output_frame.len );
6614 }
6615 else
6616 omxhdr->nFilledLen = 0;
6617 omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code,
6618 OMX_COMPONENT_GENERATE_FBD);
6619 }
6620 else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS)
6621 omx->post_event (NULL, vdec_msg->status_code,
6622 OMX_COMPONENT_GENERATE_EOS_DONE);
6623 else
6624 omx->post_event (NULL, vdec_msg->status_code,
6625 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
6626 break;
6627 case VDEC_MSG_EVT_CONFIG_CHANGED:
6628 DEBUG_PRINT_HIGH("\n Port settings changed");
6629 omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
6630 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
6631 break;
6632 case VDEC_MSG_EVT_INFO_CONFIG_CHANGED:
6633 {
6634 DEBUG_PRINT_HIGH("\n Port settings changed info");
6635 // get_buffer_req and populate port defn structure
6636 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6637 omx->m_port_def.nPortIndex = 1;
6638 eRet = omx->update_portdef(&(omx->m_port_def));
6639 omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
6640 OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG);
6641 break;
6642 }
6643 default:
6644 break;
6645 }
6646 return rc;
6647}
6648
6649OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
6650 OMX_HANDLETYPE hComp,
6651 OMX_BUFFERHEADERTYPE *buffer
6652 )
6653{
6654 unsigned address,p2,id;
6655 DEBUG_PRINT_LOW("\n Empty this arbitrary");
6656
6657 if (buffer == NULL)
6658 {
6659 return OMX_ErrorBadParameter;
6660 }
6661 DEBUG_PRINT_LOW("\n ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
6662 DEBUG_PRINT_LOW("\n ETBProxyArb: nFilledLen %u, flags %d, timestamp %u",
6663 buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp);
6664
6665 /* return zero length and not an EOS buffer */
6666 /* return buffer if input flush in progress */
6667 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
6668 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)))
6669 {
6670 DEBUG_PRINT_HIGH("\n return zero legth buffer or flush in progress");
6671 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
6672 return OMX_ErrorNone;
6673 }
6674
6675 if (psource_frame == NULL)
6676 {
6677 DEBUG_PRINT_LOW("\n Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp);
6678 psource_frame = buffer;
6679 DEBUG_PRINT_LOW("\n Try to Push One Input Buffer ");
6680 push_input_buffer (hComp);
6681 }
6682 else
6683 {
6684 DEBUG_PRINT_LOW("\n Push the source buffer into pendingq %p",buffer);
6685 if (!m_input_pending_q.insert_entry((unsigned)buffer,NULL,NULL))
6686 {
6687 return OMX_ErrorBadParameter;
6688 }
6689 }
6690
6691
6692 return OMX_ErrorNone;
6693}
6694
6695OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
6696{
6697 unsigned address,p2,id;
6698 OMX_ERRORTYPE ret = OMX_ErrorNone;
6699
6700 if (pdest_frame == NULL || psource_frame == NULL)
6701 {
6702 /*Check if we have a destination buffer*/
6703 if (pdest_frame == NULL)
6704 {
6705 DEBUG_PRINT_LOW("\n Get a Destination buffer from the queue");
6706 if (m_input_free_q.m_size)
6707 {
6708 m_input_free_q.pop_entry(&address,&p2,&id);
6709 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
6710 pdest_frame->nFilledLen = 0;
6711 pdest_frame->nTimeStamp = LLONG_MAX;
6712 DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",pdest_frame);
6713 }
6714 }
6715
6716 /*Check if we have a destination buffer*/
6717 if (psource_frame == NULL)
6718 {
6719 DEBUG_PRINT_LOW("\n Get a source buffer from the queue");
6720 if (m_input_pending_q.m_size)
6721 {
6722 m_input_pending_q.pop_entry(&address,&p2,&id);
6723 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
6724 DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
6725 psource_frame->nTimeStamp);
6726 DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
6727 psource_frame->nFlags,psource_frame->nFilledLen);
6728
6729 }
6730 }
6731
6732 }
6733
6734 while ((pdest_frame != NULL) && (psource_frame != NULL))
6735 {
6736 switch (codec_type_parse)
6737 {
6738 case CODEC_TYPE_MPEG4:
6739 case CODEC_TYPE_H263:
6740 case CODEC_TYPE_MPEG2:
6741 ret = push_input_sc_codec(hComp);
6742 break;
6743 case CODEC_TYPE_H264:
6744 ret = push_input_h264(hComp);
6745 break;
6746 case CODEC_TYPE_VC1:
6747 ret = push_input_vc1(hComp);
6748 break;
6749 }
6750 if (ret != OMX_ErrorNone)
6751 {
6752 DEBUG_PRINT_ERROR("\n Pushing input Buffer Failed");
6753 omx_report_error ();
6754 break;
6755 }
6756 }
6757
6758 return ret;
6759}
6760
6761OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
6762{
6763 OMX_U32 partial_frame = 1;
6764 OMX_BOOL generate_ebd = OMX_TRUE;
6765 unsigned address,p2,id;
6766
6767 DEBUG_PRINT_LOW("\n Start Parsing the bit stream address %p TimeStamp %d",
6768 psource_frame,psource_frame->nTimeStamp);
6769 if (m_frame_parser.parse_sc_frame(psource_frame,
6770 pdest_frame,&partial_frame) == -1)
6771 {
6772 DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
6773 return OMX_ErrorBadParameter;
6774 }
6775
6776 if (partial_frame == 0)
6777 {
6778 DEBUG_PRINT_LOW("\n Frame size %d source %p frame count %d",
6779 pdest_frame->nFilledLen,psource_frame,frame_count);
6780
6781
6782 DEBUG_PRINT_LOW("\n TimeStamp updated %d",pdest_frame->nTimeStamp);
6783 /*First Parsed buffer will have only header Hence skip*/
6784 if (frame_count == 0)
6785 {
6786 DEBUG_PRINT_LOW("\n H263/MPEG4 Codec First Frame ");
6787
6788 if(codec_type_parse == CODEC_TYPE_MPEG4 ||
6789 codec_type_parse == CODEC_TYPE_DIVX) {
6790 mp4StreamType psBits;
6791 psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
6792 psBits.numBytes = pdest_frame->nFilledLen;
6793 mp4_headerparser.parseHeader(&psBits);
6794 }
6795
6796 frame_count++;
6797 }
6798 else
6799 {
6800 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
6801 if(pdest_frame->nFilledLen)
6802 {
6803 /*Push the frame to the Decoder*/
6804 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
6805 {
6806 return OMX_ErrorBadParameter;
6807 }
6808 frame_count++;
6809 pdest_frame = NULL;
6810
6811 if (m_input_free_q.m_size)
6812 {
6813 m_input_free_q.pop_entry(&address,&p2,&id);
6814 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
6815 pdest_frame->nFilledLen = 0;
6816 }
6817 }
6818 else if(!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS))
6819 {
6820 DEBUG_PRINT_ERROR("\nZero len buffer return back to POOL");
6821 m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
6822 pdest_frame = NULL;
6823 }
6824 }
6825 }
6826 else
6827 {
6828 DEBUG_PRINT_LOW("\n Not a Complete Frame %d",pdest_frame->nFilledLen);
6829 /*Check if Destination Buffer is full*/
6830 if (pdest_frame->nAllocLen ==
6831 pdest_frame->nFilledLen + pdest_frame->nOffset)
6832 {
6833 DEBUG_PRINT_ERROR("\nERROR:Frame Not found though Destination Filled");
6834 return OMX_ErrorStreamCorrupt;
6835 }
6836 }
6837
6838 if (psource_frame->nFilledLen == 0)
6839 {
6840 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)
6841 {
6842 if (pdest_frame)
6843 {
6844 pdest_frame->nFlags |= psource_frame->nFlags;
6845 DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
6846 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
6847 DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
6848 pdest_frame->nFilledLen,frame_count++);
6849 /*Push the frame to the Decoder*/
6850 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
6851 {
6852 return OMX_ErrorBadParameter;
6853 }
6854 frame_count++;
6855 pdest_frame = NULL;
6856 }
6857 else
6858 {
6859 DEBUG_PRINT_LOW("\n Last frame in else dest addr") ;
6860 generate_ebd = OMX_FALSE;
6861 }
6862 }
6863 if(generate_ebd)
6864 {
6865 DEBUG_PRINT_LOW("\n Buffer Consumed return back to client %p",psource_frame);
6866 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
6867 psource_frame = NULL;
6868
6869 if (m_input_pending_q.m_size)
6870 {
6871 DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
6872 m_input_pending_q.pop_entry(&address,&p2,&id);
6873 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
6874 DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
6875 psource_frame->nTimeStamp);
6876 DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
6877 psource_frame->nFlags,psource_frame->nFilledLen);
6878 }
6879 }
6880 }
6881 return OMX_ErrorNone;
6882}
6883
6884OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
6885{
6886 OMX_U32 partial_frame = 1;
6887 unsigned address,p2,id;
6888 OMX_BOOL isNewFrame = OMX_FALSE;
6889 OMX_BOOL generate_ebd = OMX_TRUE;
6890
6891 if (h264_scratch.pBuffer == NULL)
6892 {
6893 DEBUG_PRINT_ERROR("\nERROR:H.264 Scratch Buffer not allocated");
6894 return OMX_ErrorBadParameter;
6895 }
6896 DEBUG_PRINT_LOW("\n Pending h264_scratch.nFilledLen %d "
6897 "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal);
6898 DEBUG_PRINT_LOW("\n Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
6899 if (h264_scratch.nFilledLen && look_ahead_nal)
6900 {
6901 look_ahead_nal = false;
6902 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6903 h264_scratch.nFilledLen)
6904 {
6905 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6906 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6907 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6908 DEBUG_PRINT_LOW("\n Copy the previous NAL (h264 scratch) into Dest frame");
6909 h264_scratch.nFilledLen = 0;
6910 }
6911 else
6912 {
6913 DEBUG_PRINT_ERROR("\n Error:1: Destination buffer overflow for H264");
6914 return OMX_ErrorBadParameter;
6915 }
6916 }
6917 if (nal_length == 0)
6918 {
6919 DEBUG_PRINT_LOW("\n Zero NAL, hence parse using start code");
6920 if (m_frame_parser.parse_sc_frame(psource_frame,
6921 &h264_scratch,&partial_frame) == -1)
6922 {
6923 DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
6924 return OMX_ErrorBadParameter;
6925 }
6926 }
6927 else
6928 {
6929 DEBUG_PRINT_LOW("\n Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
6930 if (m_frame_parser.parse_h264_nallength(psource_frame,
6931 &h264_scratch,&partial_frame) == -1)
6932 {
6933 DEBUG_PRINT_ERROR("\n Error In Parsing NAL size, Return Error");
6934 return OMX_ErrorBadParameter;
6935 }
6936 }
6937
6938 if (partial_frame == 0)
6939 {
6940 if (nal_count == 0 && h264_scratch.nFilledLen == 0)
6941 {
6942 DEBUG_PRINT_LOW("\n First NAL with Zero Length, hence Skip");
6943 nal_count++;
6944 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
6945 h264_scratch.nFlags = psource_frame->nFlags;
6946 }
6947 else
6948 {
6949 DEBUG_PRINT_LOW("\n Parsed New NAL Length = %d",h264_scratch.nFilledLen);
6950 if(h264_scratch.nFilledLen)
6951 {
6952 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
6953 NALU_TYPE_SPS);
6954#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6955 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
6956 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6957 h264_scratch.nFilledLen, NALU_TYPE_SEI);
6958 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6959 // If timeinfo is present frame info from SEI is already processed
6960 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
6961 h264_scratch.nFilledLen, NALU_TYPE_SEI);
6962#endif
6963 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
6964 nal_count++;
6965 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
6966 pdest_frame->nTimeStamp = h264_last_au_ts;
6967 pdest_frame->nFlags = h264_last_au_flags;
6968#ifdef PANSCAN_HDLR
6969 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
6970 h264_parser->update_panscan_data(h264_last_au_ts);
6971#endif
6972 }
6973 if(m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
6974 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
6975 h264_last_au_ts = h264_scratch.nTimeStamp;
6976 h264_last_au_flags = h264_scratch.nFlags;
6977#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
6978 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
6979 {
6980 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
6981 if (!VALID_TS(h264_last_au_ts))
6982 h264_last_au_ts = ts_in_sei;
6983 }
6984#endif
6985 } else
6986 h264_last_au_ts = LLONG_MAX;
6987 }
6988
6989 if (!isNewFrame)
6990 {
6991 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
6992 h264_scratch.nFilledLen)
6993 {
6994 DEBUG_PRINT_LOW("\n Not a NewFrame Copy into Dest len %d",
6995 h264_scratch.nFilledLen);
6996 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
6997 h264_scratch.pBuffer,h264_scratch.nFilledLen);
6998 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
6999 if(m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
7000 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7001 h264_scratch.nFilledLen = 0;
7002 }
7003 else
7004 {
7005 DEBUG_PRINT_LOW("\n Error:2: Destination buffer overflow for H264");
7006 return OMX_ErrorBadParameter;
7007 }
7008 }
7009 else
7010 {
7011 look_ahead_nal = true;
7012 DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
7013 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
7014 DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
7015 pdest_frame->nFilledLen,frame_count++);
7016
7017 if (pdest_frame->nFilledLen == 0)
7018 {
7019 DEBUG_PRINT_LOW("\n Copy the Current Frame since and push it");
7020 look_ahead_nal = false;
7021 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
7022 h264_scratch.nFilledLen)
7023 {
7024 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
7025 h264_scratch.pBuffer,h264_scratch.nFilledLen);
7026 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
7027 h264_scratch.nFilledLen = 0;
7028 }
7029 else
7030 {
7031 DEBUG_PRINT_ERROR("\n Error:3: Destination buffer overflow for H264");
7032 return OMX_ErrorBadParameter;
7033 }
7034 }
7035 else
7036 {
7037 if(psource_frame->nFilledLen || h264_scratch.nFilledLen)
7038 {
7039 DEBUG_PRINT_LOW("\n Reset the EOS Flag");
7040 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
7041 }
7042 /*Push the frame to the Decoder*/
7043 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
7044 {
7045 return OMX_ErrorBadParameter;
7046 }
7047 //frame_count++;
7048 pdest_frame = NULL;
7049 if (m_input_free_q.m_size)
7050 {
7051 m_input_free_q.pop_entry(&address,&p2,&id);
7052 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
7053 DEBUG_PRINT_LOW("\n Pop the next pdest_buffer %p",pdest_frame);
7054 pdest_frame->nFilledLen = 0;
7055 pdest_frame->nFlags = 0;
7056 pdest_frame->nTimeStamp = LLONG_MAX;
7057 }
7058 }
7059 }
7060 }
7061 }
7062 else
7063 {
7064 DEBUG_PRINT_LOW("\n Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
7065 /*Check if Destination Buffer is full*/
7066 if (h264_scratch.nAllocLen ==
7067 h264_scratch.nFilledLen + h264_scratch.nOffset)
7068 {
7069 DEBUG_PRINT_ERROR("\nERROR: Frame Not found though Destination Filled");
7070 return OMX_ErrorStreamCorrupt;
7071 }
7072 }
7073
7074 if (!psource_frame->nFilledLen)
7075 {
7076 DEBUG_PRINT_LOW("\n Buffer Consumed return source %p back to client",psource_frame);
7077
7078 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)
7079 {
7080 if (pdest_frame)
7081 {
7082 DEBUG_PRINT_LOW("\n EOS Reached Pass Last Buffer");
7083 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
7084 h264_scratch.nFilledLen)
7085 {
7086 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
7087 h264_scratch.pBuffer,h264_scratch.nFilledLen);
7088 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
7089 h264_scratch.nFilledLen = 0;
7090 }
7091 else
7092 {
7093 DEBUG_PRINT_ERROR("\nERROR:4: Destination buffer overflow for H264");
7094 return OMX_ErrorBadParameter;
7095 }
7096 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
7097 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
7098
7099 DEBUG_PRINT_LOW("\n pdest_frame->nFilledLen =%d TimeStamp = %x",
7100 pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
7101 DEBUG_PRINT_LOW("\n Push AU frame number %d to driver", frame_count++);
7102#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
7103 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
7104 {
7105 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
7106 if (!VALID_TS(pdest_frame->nTimeStamp))
7107 pdest_frame->nTimeStamp = ts_in_sei;
7108 }
7109#endif
7110 /*Push the frame to the Decoder*/
7111 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
7112 {
7113 return OMX_ErrorBadParameter;
7114 }
7115 frame_count++;
7116 pdest_frame = NULL;
7117 }
7118 else
7119 {
7120 DEBUG_PRINT_LOW("\n Last frame in else dest addr %p size %d",
7121 pdest_frame,h264_scratch.nFilledLen);
7122 generate_ebd = OMX_FALSE;
7123 }
7124 }
7125 }
7126 if(generate_ebd && !psource_frame->nFilledLen)
7127 {
7128 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
7129 psource_frame = NULL;
7130 if (m_input_pending_q.m_size)
7131 {
7132 DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
7133 m_input_pending_q.pop_entry(&address,&p2,&id);
7134 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
7135 DEBUG_PRINT_LOW("\nNext source Buffer flag %d src length %d",
7136 psource_frame->nFlags,psource_frame->nFilledLen);
7137 }
7138 }
7139 return OMX_ErrorNone;
7140}
7141
7142OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
7143{
7144 OMX_U8 *buf, *pdest;
7145 OMX_U32 partial_frame = 1;
7146 OMX_U32 buf_len, dest_len;
7147
7148 if(first_frame == 0)
7149 {
7150 first_frame = 1;
7151 DEBUG_PRINT_LOW("\nFirst i/p buffer for VC1 arbitrary bytes\n");
7152 if(!m_vendor_config.pData)
7153 {
7154 DEBUG_PRINT_LOW("\nCheck profile type in 1st source buffer\n");
7155 buf = psource_frame->pBuffer;
7156 buf_len = psource_frame->nFilledLen;
7157
7158 if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
7159 VC1_SP_MP_START_CODE)
7160 {
7161 m_vc1_profile = VC1_SP_MP_RCV;
7162 }
7163 else if(*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE)
7164 {
7165 m_vc1_profile = VC1_AP;
7166 }
7167 else
7168 {
7169 DEBUG_PRINT_ERROR("\nInvalid sequence layer in first buffer\n");
7170 return OMX_ErrorStreamCorrupt;
7171 }
7172 }
7173 else
7174 {
7175 pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
7176 pdest_frame->nOffset;
7177 dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
7178 pdest_frame->nOffset);
7179
7180 if(dest_len < m_vendor_config.nDataSize)
7181 {
7182 DEBUG_PRINT_ERROR("\nDestination buffer full\n");
7183 return OMX_ErrorBadParameter;
7184 }
7185 else
7186 {
7187 memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
7188 pdest_frame->nFilledLen += m_vendor_config.nDataSize;
7189 }
7190 }
7191 }
7192
7193 switch(m_vc1_profile)
7194 {
7195 case VC1_AP:
7196 DEBUG_PRINT_LOW("\n VC1 AP, hence parse using frame start code");
7197 if (push_input_sc_codec(hComp) != OMX_ErrorNone)
7198 {
7199 DEBUG_PRINT_ERROR("\n Error In Parsing VC1 AP start code");
7200 return OMX_ErrorBadParameter;
7201 }
7202 break;
7203
7204 case VC1_SP_MP_RCV:
7205 default:
7206 DEBUG_PRINT_ERROR("\n Unsupported VC1 profile in ArbitraryBytes Mode\n");
7207 return OMX_ErrorBadParameter;
7208 }
7209 return OMX_ErrorNone;
7210}
7211
7212bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
7213 OMX_U32 alignment)
7214{
7215 struct pmem_allocation allocation;
7216 allocation.size = buffer_size;
7217 allocation.align = clip2(alignment);
7218 if (allocation.align < 4096)
7219 {
7220 allocation.align = 4096;
7221 }
7222 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0)
7223 {
7224 DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)",
7225 allocation.align, allocation.size);
7226 return false;
7227 }
7228 return true;
7229}
7230#ifdef USE_ION
7231int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
7232 OMX_U32 alignment, struct ion_allocation_data *alloc_data,
7233 struct ion_fd_data *fd_data, int flag)
7234{
7235 int fd = -EINVAL;
7236 int rc = -EINVAL;
7237 int ion_dev_flag;
7238 struct vdec_ion ion_buf_info;
7239 if (!alloc_data || buffer_size <= 0 || !fd_data) {
7240 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory\n");
7241 return -EINVAL;
7242 }
7243 if(!secure_mode && flag == CACHED)
7244 {
7245 ion_dev_flag = O_RDONLY;
7246 } else {
7247 ion_dev_flag = (O_RDONLY | O_DSYNC);
7248 }
7249 fd = open (MEM_DEVICE, ion_dev_flag);
7250 if (fd < 0) {
7251 DEBUG_PRINT_ERROR("opening ion device failed with fd = %d\n", fd);
7252 return fd;
7253 }
7254 alloc_data->len = buffer_size;
7255 alloc_data->align = clip2(alignment);
7256 if (alloc_data->align < 4096)
7257 {
7258 alloc_data->align = 4096;
7259 }
7260 if(secure_mode) {
7261 alloc_data->flags = (ION_HEAP(MEM_HEAP_ID) | ION_SECURE);
7262 } else {
7263 alloc_data->flags = ION_HEAP(MEM_HEAP_ID);
7264 }
7265 rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
7266 if (rc || !alloc_data->handle) {
7267 DEBUG_PRINT_ERROR("\n ION ALLOC memory failed ");
7268 alloc_data->handle = NULL;
7269 close(fd);
7270 fd = -ENOMEM;
7271 return fd;
7272 }
7273 fd_data->handle = alloc_data->handle;
7274 rc = ioctl(fd,ION_IOC_MAP,fd_data);
7275 if (rc) {
7276 DEBUG_PRINT_ERROR("\n ION MAP failed ");
7277 ion_buf_info.ion_alloc_data = *alloc_data;
7278 ion_buf_info.ion_device_fd = fd;
7279 ion_buf_info.fd_ion_data = *fd_data;
7280 free_ion_memory(&ion_buf_info);
7281 fd_data->fd =-1;
7282 close(fd);
7283 fd = -ENOMEM;
7284 }
7285
7286 return fd;
7287}
7288
7289void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) {
7290
7291 if(!buf_ion_info) {
7292 DEBUG_PRINT_ERROR("\n ION: free called with invalid fd/allocdata");
7293 return;
7294 }
7295 if(ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
7296 &buf_ion_info->ion_alloc_data.handle)) {
7297 DEBUG_PRINT_ERROR("\n ION: free failed" );
7298 }
7299 close(buf_ion_info->ion_device_fd);
7300 buf_ion_info->ion_device_fd = -1;
7301 buf_ion_info->ion_alloc_data.handle = NULL;
7302 buf_ion_info->fd_ion_data.fd = -1;
7303}
7304#endif
7305void omx_vdec::free_output_buffer_header()
7306{
7307 DEBUG_PRINT_HIGH("\n ALL output buffers are freed/released");
7308 output_use_buffer = false;
7309 ouput_egl_buffers = false;
7310
7311 if (m_out_mem_ptr)
7312 {
7313 free (m_out_mem_ptr);
7314 m_out_mem_ptr = NULL;
7315 }
7316
7317 if(m_platform_list)
7318 {
7319 free(m_platform_list);
7320 m_platform_list = NULL;
7321 }
7322
7323 if (drv_ctx.ptr_respbuffer)
7324 {
7325 free (drv_ctx.ptr_respbuffer);
7326 drv_ctx.ptr_respbuffer = NULL;
7327 }
7328 if (drv_ctx.ptr_outputbuffer)
7329 {
7330 free (drv_ctx.ptr_outputbuffer);
7331 drv_ctx.ptr_outputbuffer = NULL;
7332 }
7333#ifdef USE_ION
7334 if (drv_ctx.op_buf_ion_info) {
7335 DEBUG_PRINT_LOW("\n Free o/p ion context");
7336 free(drv_ctx.op_buf_ion_info);
7337 drv_ctx.op_buf_ion_info = NULL;
7338 }
7339#endif
7340}
7341
7342void omx_vdec::free_input_buffer_header()
7343{
7344 input_use_buffer = false;
7345 if (arbitrary_bytes)
7346 {
7347 if (m_frame_parser.mutils)
7348 {
7349 DEBUG_PRINT_LOW("\n Free utils parser");
7350 delete (m_frame_parser.mutils);
7351 m_frame_parser.mutils = NULL;
7352 }
7353
7354 if (m_inp_heap_ptr)
7355 {
7356 DEBUG_PRINT_LOW("\n Free input Heap Pointer");
7357 free (m_inp_heap_ptr);
7358 m_inp_heap_ptr = NULL;
7359 }
7360
7361 if (m_phdr_pmem_ptr)
7362 {
7363 DEBUG_PRINT_LOW("\n Free input pmem header Pointer");
7364 free (m_phdr_pmem_ptr);
7365 m_phdr_pmem_ptr = NULL;
7366 }
7367 }
7368 if (m_inp_mem_ptr)
7369 {
7370 DEBUG_PRINT_LOW("\n Free input pmem Pointer area");
7371 free (m_inp_mem_ptr);
7372 m_inp_mem_ptr = NULL;
7373 }
7374 if (drv_ctx.ptr_inputbuffer)
7375 {
7376 DEBUG_PRINT_LOW("\n Free Driver Context pointer");
7377 free (drv_ctx.ptr_inputbuffer);
7378 drv_ctx.ptr_inputbuffer = NULL;
7379 }
7380#ifdef USE_ION
7381 if (drv_ctx.ip_buf_ion_info) {
7382 DEBUG_PRINT_LOW("\n Free ion context");
7383 free(drv_ctx.ip_buf_ion_info);
7384 drv_ctx.ip_buf_ion_info = NULL;
7385 }
7386#endif
7387}
7388void omx_vdec::stream_off()
7389{
7390 int rc=0;
7391 enum v4l2_buf_type btype;
7392 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7393 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
7394 if (rc) {
7395 /*TODO: How to handle this case */
Ashray Kulkarni46373df2012-06-05 20:11:31 -07007396 DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n");
Shalaj Jain273b3e02012-06-22 19:08:03 -07007397 } else {
7398 streaming[CAPTURE_PORT] = false;
7399 }
7400}
7401
7402OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
7403{
7404 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7405 struct v4l2_requestbuffers bufreq;
7406 unsigned int buf_size = 0, extra_data_size = 0;
7407 struct v4l2_format fmt;
7408 int ret;
7409 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)",
7410 buffer_prop->actualcount, buffer_prop->buffer_size);
7411 bufreq.memory = V4L2_MEMORY_USERPTR;
7412 if(in_reconfig == true)
7413 bufreq.count = 0;
7414 else
7415 bufreq.count = 2;
7416 if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){
7417 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7418 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7419 fmt.fmt.pix_mp.pixelformat = output_capability;
7420 }else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT){
7421 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7422 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7423 fmt.fmt.pix_mp.pixelformat = capture_capability;
7424 }else {eRet = OMX_ErrorBadParameter;}
7425 if(eRet==OMX_ErrorNone){
7426 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
7427 }
7428 if(ret)
7429 {
7430 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7431 /*TODO: How to handle this case */
7432 eRet = OMX_ErrorInsufficientResources;
7433 return eRet;
7434 }
7435 else
7436 {
7437 buffer_prop->actualcount = bufreq.count;
7438 buffer_prop->mincount = bufreq.count;
Ashray Kulkarni46373df2012-06-05 20:11:31 -07007439 DEBUG_PRINT_HIGH("Count = %d \n ",bufreq.count);
Shalaj Jain273b3e02012-06-22 19:08:03 -07007440 }
7441 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)",
7442 buffer_prop->actualcount, buffer_prop->buffer_size);
7443
7444 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7445 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7446
7447 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
7448
7449 drv_ctx.video_resolution.frame_height = fmt.fmt.pix_mp.height;
7450 drv_ctx.video_resolution.frame_width = fmt.fmt.pix_mp.width;
7451
Ashray Kulkarni46373df2012-06-05 20:11:31 -07007452 DEBUG_PRINT_HIGH("Buffer Size = %d \n ",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
Shalaj Jain273b3e02012-06-22 19:08:03 -07007453
7454 if(ret)
7455 {
7456 /*TODO: How to handle this case */
7457 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
7458 eRet = OMX_ErrorInsufficientResources;
7459 }
7460 else
7461 {
7462 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
7463 buf_size = buffer_prop->buffer_size;
7464 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
7465 {
7466 DEBUG_PRINT_HIGH("Frame info extra data enabled!");
7467 extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
7468 }
7469 if (client_extradata & OMX_INTERLACE_EXTRADATA)
7470 {
7471 DEBUG_PRINT_HIGH("Interlace extra data enabled!");
7472 extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE;
7473 }
7474 if (client_extradata & OMX_PORTDEF_EXTRADATA)
7475 {
7476 extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE;
7477 DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d\n",
7478 extra_data_size);
7479 }
7480 if (extra_data_size)
7481 {
7482 extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
7483 buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
7484 }
7485 buf_size += extra_data_size;
7486 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7487 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)",
7488 buffer_prop->actualcount, buffer_prop->buffer_size, buf_size);
7489 if (in_reconfig) // BufReq will be set to driver when port is disabled
7490 buffer_prop->buffer_size = buf_size;
7491 else if (buf_size != buffer_prop->buffer_size)
7492 {
7493 buffer_prop->buffer_size = buf_size;
7494 eRet = set_buffer_req(buffer_prop);
7495 }
7496 }
7497 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)",
7498 buffer_prop->actualcount, buffer_prop->buffer_size);
7499 return eRet;
7500}
7501
7502OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
7503{
7504 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7505 unsigned buf_size = 0;
7506 struct v4l2_format fmt;
7507 int ret;
7508 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)",
7509 buffer_prop->actualcount, buffer_prop->buffer_size);
7510 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
7511 if (buf_size != buffer_prop->buffer_size)
7512 {
7513 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
7514 buffer_prop->buffer_size, buf_size);
7515 eRet = OMX_ErrorBadParameter;
7516 }
7517 else
7518 {
7519 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
7520 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
7521 if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){
7522 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7523 fmt.fmt.pix_mp.pixelformat = output_capability;
7524 }else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT){
7525fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7526 fmt.fmt.pix_mp.pixelformat = capture_capability;
7527} else {eRet = OMX_ErrorBadParameter;}
7528 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
7529 if(ret)
7530 {
7531 /*TODO: How to handle this case */
7532 DEBUG_PRINT_ERROR("Setting buffer requirements failed");
7533 eRet = OMX_ErrorInsufficientResources;
7534 }
7535 }
7536 return eRet;
7537}
7538
7539OMX_ERRORTYPE omx_vdec::start_port_reconfig()
7540{
7541 struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
7542 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7543 enum v4l2_buf_type btype;
7544 int rc = 0,i;
7545 struct v4l2_plane plane;
7546 struct v4l2_buffer v4l2_buf ={0};
7547 struct v4l2_decoder_cmd dec;
7548 dec.cmd = V4L2_DEC_CMD_STOP;
7549 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec);
7550 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7551 in_reconfig = true;
7552 return eRet;
7553}
7554
7555OMX_ERRORTYPE omx_vdec::update_picture_resolution()
7556{
7557 struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
7558 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7559 ioctl_msg.in = NULL;
7560 ioctl_msg.out = &drv_ctx.video_resolution;
7561 if (/*ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_PICRES, &ioctl_msg)*/0)
7562 {
7563 DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_PICRES");
7564 eRet = OMX_ErrorHardware;
7565 }
7566 return eRet;
7567}
7568
7569OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
7570{
7571 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7572 if (!portDefn)
7573 {
7574 return OMX_ErrorBadParameter;
7575 }
7576 DEBUG_PRINT_LOW("omx_vdec::update_portdef\n");
7577 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
7578 portDefn->nSize = sizeof(portDefn);
7579 portDefn->eDomain = OMX_PortDomainVideo;
7580 if (drv_ctx.frame_rate.fps_denominator > 0)
7581 portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator /
7582 drv_ctx.frame_rate.fps_denominator;
7583 else {
7584 DEBUG_PRINT_ERROR("Error: Divide by zero \n");
7585 return OMX_ErrorBadParameter;
7586 }
7587 if (0 == portDefn->nPortIndex)
7588 {
7589 portDefn->eDir = OMX_DirInput;
7590 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
7591 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
7592 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
7593 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
7594 portDefn->format.video.eCompressionFormat = eCompressionFormat;
7595 portDefn->bEnabled = m_inp_bEnabled;
7596 portDefn->bPopulated = m_inp_bPopulated;
7597 }
7598 else if (1 == portDefn->nPortIndex)
7599 {
7600 portDefn->eDir = OMX_DirOutput;
7601 eRet=get_buffer_req(&drv_ctx.op_buf);
7602 if (in_reconfig)
7603 {
7604 portDefn->nBufferCountActual = op_buf_rcnfg.actualcount;
7605 portDefn->nBufferCountMin = op_buf_rcnfg.mincount;
7606 portDefn->nBufferSize = op_buf_rcnfg.buffer_size;
7607 }
7608 else
7609 {
7610 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
7611 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
7612 portDefn->nBufferSize = drv_ctx.op_buf.buffer_size;
7613 }
7614 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
7615 portDefn->bEnabled = m_out_bEnabled;
7616 portDefn->bPopulated = m_out_bPopulated;
7617 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
7618 portDefn->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
7619 else if (drv_ctx.output_format == VDEC_YUV_FORMAT_TILE_4x2)
7620 portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)
7621 QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
7622 else
7623 {
7624 DEBUG_PRINT_ERROR("ERROR: Color format unknown: %x\n", drv_ctx.output_format);
7625 }
7626 }
7627 else
7628 {
7629 portDefn->eDir = OMX_DirMax;
7630 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
7631 (int)portDefn->nPortIndex);
7632 eRet = OMX_ErrorBadPortIndex;
7633 }
7634 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
7635 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
7636 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
7637 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
7638 DEBUG_PRINT_LOW("update_portdef Width = %d Height = %d Stride = %u"
7639 "SliceHeight = %u \n", portDefn->format.video.nFrameHeight,
7640 portDefn->format.video.nFrameWidth,
7641 portDefn->format.video.nStride,
7642 portDefn->format.video.nSliceHeight);
7643 return eRet;
7644
7645}
7646
7647OMX_ERRORTYPE omx_vdec::allocate_output_headers()
7648{
7649 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7650 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
7651 unsigned i= 0;
7652
7653 if(!m_out_mem_ptr) {
7654 DEBUG_PRINT_HIGH("\n Use o/p buffer case - Header List allocation");
7655 int nBufHdrSize = 0;
7656 int nPlatformEntrySize = 0;
7657 int nPlatformListSize = 0;
7658 int nPMEMInfoSize = 0;
7659 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
7660 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
7661 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
7662
7663 DEBUG_PRINT_LOW("Setting First Output Buffer(%d)\n",
7664 drv_ctx.op_buf.actualcount);
7665 nBufHdrSize = drv_ctx.op_buf.actualcount *
7666 sizeof(OMX_BUFFERHEADERTYPE);
7667
7668 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
7669 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
7670 nPlatformListSize = drv_ctx.op_buf.actualcount *
7671 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
7672 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
7673 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
7674
7675 DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
7676 sizeof(OMX_BUFFERHEADERTYPE),
7677 nPMEMInfoSize,
7678 nPlatformListSize);
7679 DEBUG_PRINT_LOW("PE %d bmSize %d \n",nPlatformEntrySize,
7680 m_out_bm_count);
7681 m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
7682 // Alloc mem for platform specific info
7683 char *pPtr=NULL;
7684 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
7685 nPMEMInfoSize,1);
7686 drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
7687 calloc (sizeof(struct vdec_bufferpayload),
7688 drv_ctx.op_buf.actualcount);
7689 drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
7690 calloc (sizeof (struct vdec_output_frameinfo),
7691 drv_ctx.op_buf.actualcount);
7692#ifdef USE_ION
7693 drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
7694 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
7695#endif
7696
7697 if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
7698 && drv_ctx.ptr_respbuffer)
7699 {
7700 bufHdr = m_out_mem_ptr;
7701 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
7702 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
7703 (((char *) m_platform_list) + nPlatformListSize);
7704 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
7705 (((char *) m_platform_entry) + nPlatformEntrySize);
7706 pPlatformList = m_platform_list;
7707 pPlatformEntry = m_platform_entry;
7708 pPMEMInfo = m_pmem_info;
7709
7710 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
7711
7712 // Settting the entire storage nicely
7713 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr,
7714 m_out_mem_ptr,pPlatformEntry);
7715 DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
7716 for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
7717 {
7718 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
7719 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
7720 // Set the values when we determine the right HxW param
7721 bufHdr->nAllocLen = 0;
7722 bufHdr->nFilledLen = 0;
7723 bufHdr->pAppPrivate = NULL;
7724 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
7725 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
7726 pPlatformEntry->entry = pPMEMInfo;
7727 // Initialize the Platform List
7728 pPlatformList->nEntries = 1;
7729 pPlatformList->entryList = pPlatformEntry;
7730 // Keep pBuffer NULL till vdec is opened
7731 bufHdr->pBuffer = NULL;
7732 pPMEMInfo->offset = 0;
7733 pPMEMInfo->pmem_fd = 0;
7734 bufHdr->pPlatformPrivate = pPlatformList;
7735 drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
7736#ifdef USE_ION
7737 drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
7738#endif
7739 /*Create a mapping between buffers*/
7740 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
7741 drv_ctx.ptr_respbuffer[i].client_data = (void *) \
7742 &drv_ctx.ptr_outputbuffer[i];
7743 // Move the buffer and buffer header pointers
7744 bufHdr++;
7745 pPMEMInfo++;
7746 pPlatformEntry++;
7747 pPlatformList++;
7748 }
7749 }
7750 else
7751 {
7752 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
7753 m_out_mem_ptr, pPtr);
7754 if(m_out_mem_ptr)
7755 {
7756 free(m_out_mem_ptr);
7757 m_out_mem_ptr = NULL;
7758 }
7759 if(pPtr)
7760 {
7761 free(pPtr);
7762 pPtr = NULL;
7763 }
7764 if(drv_ctx.ptr_outputbuffer)
7765 {
7766 free(drv_ctx.ptr_outputbuffer);
7767 drv_ctx.ptr_outputbuffer = NULL;
7768 }
7769 if(drv_ctx.ptr_respbuffer)
7770 {
7771 free(drv_ctx.ptr_respbuffer);
7772 drv_ctx.ptr_respbuffer = NULL;
7773 }
7774#ifdef USE_ION
7775 if (drv_ctx.op_buf_ion_info) {
7776 DEBUG_PRINT_LOW("\n Free o/p ion context");
7777 free(drv_ctx.op_buf_ion_info);
7778 drv_ctx.op_buf_ion_info = NULL;
7779 }
7780#endif
7781 eRet = OMX_ErrorInsufficientResources;
7782 }
7783 } else {
7784 eRet = OMX_ErrorInsufficientResources;
7785 }
7786 return eRet;
7787}
7788
7789void omx_vdec::complete_pending_buffer_done_cbs()
7790{
7791 unsigned p1;
7792 unsigned p2;
7793 unsigned ident;
7794 omx_cmd_queue tmp_q, pending_bd_q;
7795 pthread_mutex_lock(&m_lock);
7796 // pop all pending GENERATE FDB from ftb queue
7797 while (m_ftb_q.m_size)
7798 {
7799 m_ftb_q.pop_entry(&p1,&p2,&ident);
7800 if(ident == OMX_COMPONENT_GENERATE_FBD)
7801 {
7802 pending_bd_q.insert_entry(p1,p2,ident);
7803 }
7804 else
7805 {
7806 tmp_q.insert_entry(p1,p2,ident);
7807 }
7808 }
7809 //return all non GENERATE FDB to ftb queue
7810 while(tmp_q.m_size)
7811 {
7812 tmp_q.pop_entry(&p1,&p2,&ident);
7813 m_ftb_q.insert_entry(p1,p2,ident);
7814 }
7815 // pop all pending GENERATE EDB from etb queue
7816 while (m_etb_q.m_size)
7817 {
7818 m_etb_q.pop_entry(&p1,&p2,&ident);
7819 if(ident == OMX_COMPONENT_GENERATE_EBD)
7820 {
7821 pending_bd_q.insert_entry(p1,p2,ident);
7822 }
7823 else
7824 {
7825 tmp_q.insert_entry(p1,p2,ident);
7826 }
7827 }
7828 //return all non GENERATE FDB to etb queue
7829 while(tmp_q.m_size)
7830 {
7831 tmp_q.pop_entry(&p1,&p2,&ident);
7832 m_etb_q.insert_entry(p1,p2,ident);
7833 }
7834 pthread_mutex_unlock(&m_lock);
7835 // process all pending buffer dones
7836 while(pending_bd_q.m_size)
7837 {
7838 pending_bd_q.pop_entry(&p1,&p2,&ident);
7839 switch(ident)
7840 {
7841 case OMX_COMPONENT_GENERATE_EBD:
7842 if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
7843 {
7844 DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n");
7845 omx_report_error ();
7846 }
7847 break;
7848
7849 case OMX_COMPONENT_GENERATE_FBD:
7850 if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
7851 {
7852 DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n");
7853 omx_report_error ();
7854 }
7855 break;
7856 }
7857 }
7858}
7859
7860void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
7861{
7862 OMX_U32 new_frame_interval = 0;
7863 struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
7864 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
7865 && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000))
7866 {
7867 new_frame_interval = (act_timestamp > prev_ts)?
7868 act_timestamp - prev_ts :
7869 prev_ts - act_timestamp;
7870 if (new_frame_interval < frm_int || frm_int == 0)
7871 {
7872 frm_int = new_frame_interval;
7873 if(frm_int)
7874 {
7875 drv_ctx.frame_rate.fps_numerator = 1e6;
7876 drv_ctx.frame_rate.fps_denominator = frm_int;
7877 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
7878 frm_int, drv_ctx.frame_rate.fps_numerator /
7879 (float)drv_ctx.frame_rate.fps_denominator);
7880 ioctl_msg.in = &drv_ctx.frame_rate;
7881 if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE,
7882 (void*)&ioctl_msg) < */0)
7883 {
7884 DEBUG_PRINT_ERROR("Setting frame rate failed");
7885 }
7886 }
7887 }
7888 }
7889 prev_ts = act_timestamp;
7890}
7891
7892void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
7893{
7894 if (rst_prev_ts && VALID_TS(act_timestamp))
7895 {
7896 prev_ts = act_timestamp;
7897 rst_prev_ts = false;
7898 }
7899 else if (VALID_TS(prev_ts))
7900 {
7901 bool codec_cond = (drv_ctx.timestamp_adjust)?
7902 (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)?
7903 (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)):
7904 (!VALID_TS(act_timestamp) || act_timestamp == prev_ts);
7905 if(frm_int > 0 && codec_cond)
7906 {
7907 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
7908 act_timestamp = prev_ts + frm_int;
7909 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
7910 prev_ts = act_timestamp;
7911 }
7912 else
7913 set_frame_rate(act_timestamp);
7914 }
7915 else if (frm_int > 0) // In this case the frame rate was set along
7916 { // with the port definition, start ts with 0
7917 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
7918 rst_prev_ts = true;
7919 }
7920}
7921
7922void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
7923{
7924 OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
7925 OMX_U32 num_conceal_MB = 0;
7926 OMX_S64 ts_in_sei = 0;
7927 OMX_U32 frame_rate = 0;
7928 p_extra = (OMX_OTHER_EXTRADATATYPE *)
7929 ((unsigned)(p_buf_hdr->pBuffer + p_buf_hdr->nOffset +
7930 p_buf_hdr->nFilledLen + 3)&(~3));
7931 if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen))
7932 p_extra = NULL;
7933 if (drv_ctx.extradata && (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA))
7934 {
7935 // Process driver extradata
7936 while(p_extra && p_extra->eType != VDEC_EXTRADATA_NONE)
7937 {
7938 DEBUG_PRINT_LOW("handle_extradata : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)",
7939 p_buf_hdr, p_buf_hdr->nTimeStamp, p_extra->eType, p_extra->nDataSize);
7940 if (p_extra->nSize < p_extra->nDataSize)
7941 {
7942 DEBUG_PRINT_ERROR(" \n Corrupt metadata Buffer size %d payload size %d",
7943 p_extra->nSize, p_extra->nDataSize);
7944 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7945 if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen) ||
7946 p_extra->nDataSize == 0)
7947 p_extra = NULL;
7948 continue;
7949 }
7950 if (p_extra->eType == VDEC_EXTRADATA_MB_ERROR_MAP)
7951 {
7952 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
7953 num_conceal_MB = count_MB_in_extradata(p_extra);
7954 if (client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP)
7955 // Map driver extradata to corresponding OMX type
7956 p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataConcealMB;
7957 else
7958 p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
7959 if (m_debug_concealedmb) {
7960 DEBUG_PRINT_HIGH("Concealed MB percentage is %u", num_conceal_MB);
7961 }
7962 }
7963 else if (p_extra->eType == VDEC_EXTRADATA_SEI)
7964 {
7965 p_sei = p_extra;
7966
7967 h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
7968
7969 p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
7970 }
7971 else if (p_extra->eType == VDEC_EXTRADATA_VUI)
7972 {
7973 p_vui = p_extra;
7974
7975 h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false);
7976
7977 p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
7978 }
7979 print_debug_extradata(p_extra);
7980 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
7981 if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen) ||
7982 p_extra->nDataSize == 0)
7983 p_extra = NULL;
7984 }
7985 if (!(client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP))
7986 {
7987 // Driver extradata is only exposed if MB map is requested by client,
7988 // otherwise can be overwritten by omx extradata.
7989 p_extra = (OMX_OTHER_EXTRADATATYPE *)
7990 ((unsigned)(p_buf_hdr->pBuffer + p_buf_hdr->nOffset +
7991 p_buf_hdr->nFilledLen + 3)&(~3));
7992 p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
7993 }
7994 }
7995
7996#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT
7997 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
7998 {
7999 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
8000 {
8001 if (p_vui)
8002 h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false);
8003 if (p_sei)
8004 h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
8005 ts_in_sei = h264_parser->process_ts_with_sei_vui(p_buf_hdr->nTimeStamp);
8006 if (!VALID_TS(p_buf_hdr->nTimeStamp))
8007 p_buf_hdr->nTimeStamp = ts_in_sei;
8008 }
8009 else if ((client_extradata & OMX_FRAMEINFO_EXTRADATA) && p_sei)
8010 // If timeinfo is present frame info from SEI is already processed
8011 h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
8012 }
8013#endif
8014 if ((client_extradata & OMX_INTERLACE_EXTRADATA) && p_extra &&
8015 ((OMX_U8*)p_extra + OMX_INTERLACE_EXTRADATA_SIZE) <
8016 (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen))
8017 {
8018 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
8019 append_interlace_extradata(p_extra,
8020 ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->interlaced_format);
8021 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8022 }
8023 if (client_extradata & OMX_FRAMEINFO_EXTRADATA && p_extra &&
8024 ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) <
8025 (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen))
8026 {
8027 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
8028 /* vui extra data (frame_rate) information */
8029 if (h264_parser)
8030 h264_parser->get_frame_rate(&frame_rate);
8031 append_frame_info_extradata(p_extra, num_conceal_MB,
8032 ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type,
8033 p_buf_hdr->nTimeStamp, frame_rate, NULL);
8034 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8035 }
8036 if ((client_extradata & OMX_PORTDEF_EXTRADATA) &&
8037 p_extra != NULL &&
8038 ((OMX_U8*)p_extra + OMX_PORTDEF_EXTRADATA_SIZE) <
8039 (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen))
8040 {
8041 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
8042 append_portdef_extradata(p_extra);
8043 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8044 }
8045 if (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA)
8046 if (p_extra &&
8047 ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) <
8048 (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen))
8049 append_terminator_extradata(p_extra);
8050 else
8051 {
8052 DEBUG_PRINT_ERROR("ERROR: Terminator extradata cannot be added");
8053 p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8054 }
8055}
8056
8057OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, bool enable)
8058{
8059 OMX_ERRORTYPE ret = OMX_ErrorNone;
8060 OMX_U32 driver_extradata = 0, extradata_size = 0;
8061 struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
8062 if(m_state != OMX_StateLoaded)
8063 {
8064 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
8065 return OMX_ErrorIncorrectStateOperation;
8066 }
8067 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA)
8068 extradata_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
8069 if (requested_extradata & OMX_INTERLACE_EXTRADATA)
8070 extradata_size += OMX_INTERLACE_EXTRADATA_SIZE;
8071 if (requested_extradata & OMX_PORTDEF_EXTRADATA)
8072 {
8073 extradata_size += OMX_PORTDEF_EXTRADATA_SIZE;
8074 }
8075 DEBUG_PRINT_ERROR("enable_extradata: actual[%x] requested[%x] enable[%d]",
8076 client_extradata, requested_extradata, enable);
8077
8078 if (enable)
8079 requested_extradata |= client_extradata;
8080 else
8081 {
8082 requested_extradata = client_extradata & ~requested_extradata;
8083 extradata_size *= -1;
8084 }
8085
8086 driver_extradata = requested_extradata & DRIVER_EXTRADATA_MASK;
8087 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA)
8088 driver_extradata |= VDEC_EXTRADATA_MB_ERROR_MAP; // Required for conceal MB frame info
8089#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT
8090 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
8091 {
8092 driver_extradata |= ((requested_extradata & OMX_FRAMEINFO_EXTRADATA)?
8093 VDEC_EXTRADATA_SEI : 0); // Required for pan scan frame info
8094 driver_extradata |= ((requested_extradata & OMX_TIMEINFO_EXTRADATA)?
8095 VDEC_EXTRADATA_VUI | VDEC_EXTRADATA_SEI : 0); //Required for time info
8096 }
8097
8098#endif
8099 if (driver_extradata != drv_ctx.extradata)
8100 {
8101 client_extradata = requested_extradata;
8102 drv_ctx.extradata = driver_extradata;
8103 //ioctl_msg.in = &drv_ctx.extradata;
8104 //ioctl_msg.out = NULL;
8105 //if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_EXTRADATA,
8106 // (void*)&ioctl_msg) < 0)
8107 //{
8108 // DEBUG_PRINT_ERROR("\nSet extradata failed");
8109 // ret = OMX_ErrorUnsupportedSetting;
8110 //} // else
8111 // ret = get_buffer_req(&drv_ctx.op_buf);
8112 }
8113 else if ((client_extradata & ~DRIVER_EXTRADATA_MASK) != (requested_extradata & ~DRIVER_EXTRADATA_MASK))
8114 {
8115 client_extradata = requested_extradata;
8116 drv_ctx.op_buf.buffer_size += extradata_size;
8117 // align the buffer size
8118 drv_ctx.op_buf.buffer_size = (drv_ctx.op_buf.buffer_size + drv_ctx.op_buf.alignment - 1)&(~(drv_ctx.op_buf.alignment - 1));
8119 DEBUG_PRINT_LOW("Aligned buffer size with exreadata = %d\n", drv_ctx.op_buf.buffer_size);
8120 if (!(client_extradata & ~DRIVER_EXTRADATA_MASK)) // If no omx extradata is required remove space for terminator
8121 drv_ctx.op_buf.buffer_size -= sizeof(OMX_OTHER_EXTRADATATYPE);
8122 ret = set_buffer_req(&drv_ctx.op_buf);
8123 }
8124 return ret;
8125}
8126
8127OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
8128{
8129 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
8130 OMX_U8 *data_ptr = extra->data, data = 0;
8131 while (byte_count < extra->nDataSize)
8132 {
8133 data = *data_ptr;
8134 while (data)
8135 {
8136 num_MB += (data&0x01);
8137 data >>= 1;
8138 }
8139 data_ptr++;
8140 byte_count++;
8141 }
8142 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
8143 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
8144 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
8145}
8146
8147void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
8148{
8149 if (!m_debug_extradata)
8150 return;
8151
8152 DEBUG_PRINT_HIGH(
8153 "============== Extra Data ==============\n"
8154 " Size: %u \n"
8155 " Version: %u \n"
8156 " PortIndex: %u \n"
8157 " Type: %x \n"
8158 " DataSize: %u \n",
8159 extra->nSize, extra->nVersion.nVersion,
8160 extra->nPortIndex, extra->eType, extra->nDataSize);
8161
8162 if (extra->eType == OMX_ExtraDataInterlaceFormat)
8163 {
8164 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data;
8165 DEBUG_PRINT_HIGH(
8166 "------ Interlace Format ------\n"
8167 " Size: %u \n"
8168 " Version: %u \n"
8169 " PortIndex: %u \n"
8170 " Is Interlace Format: %u \n"
8171 " Interlace Formats: %u \n"
8172 "=========== End of Interlace ===========\n",
8173 intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex,
8174 intfmt->bInterlaceFormat, intfmt->nInterlaceFormats);
8175 }
8176 else if (extra->eType == OMX_ExtraDataFrameInfo)
8177 {
8178 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
8179
8180 DEBUG_PRINT_HIGH(
8181 "-------- Frame Format --------\n"
8182 " Picture Type: %u \n"
8183 " Interlace Type: %u \n"
8184 " Pan Scan Total Frame Num: %u \n"
8185 " Concealed Macro Blocks: %u \n"
8186 " frame rate: %u \n"
8187 " Aspect Ratio X: %u \n"
8188 " Aspect Ratio Y: %u \n",
8189 fminfo->ePicType,
8190 fminfo->interlaceType,
8191 fminfo->panScan.numWindows,
8192 fminfo->nConcealedMacroblocks,
8193 fminfo->nFrameRate,
8194 fminfo->aspectRatio.aspectRatioX,
8195 fminfo->aspectRatio.aspectRatioY);
8196
8197 for (int i = 0; i < fminfo->panScan.numWindows; i++)
8198 {
8199 DEBUG_PRINT_HIGH(
8200 "------------------------------\n"
8201 " Pan Scan Frame Num: %d \n"
8202 " Rectangle x: %d \n"
8203 " Rectangle y: %d \n"
8204 " Rectangle dx: %d \n"
8205 " Rectangle dy: %d \n",
8206 i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y,
8207 fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy);
8208 }
8209
8210 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
8211 }
8212 else if (extra->eType == OMX_ExtraDataNone)
8213 {
8214 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
8215 }
8216 else
8217 {
8218 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
8219 }
8220}
8221
8222void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
8223 OMX_U32 interlaced_format_type)
8224{
8225 OMX_STREAMINTERLACEFORMAT *interlace_format;
8226 OMX_U32 mbaff = 0;
8227 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
8228 extra->nVersion.nVersion = OMX_SPEC_VERSION;
8229 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8230 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
8231 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
8232 interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data;
8233 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
8234 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
8235 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8236 mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
8237 if ((interlaced_format_type == VDEC_InterlaceFrameProgressive) && !mbaff)
8238 {
8239 interlace_format->bInterlaceFormat = OMX_FALSE;
8240 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
8241 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
8242 }
8243 else
8244 {
8245 interlace_format->bInterlaceFormat = OMX_TRUE;
8246 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
8247 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
8248 }
8249 print_debug_extradata(extra);
8250}
8251
8252
8253void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
8254 OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_S64 timestamp, OMX_U32 frame_rate,
8255 vdec_aspectratioinfo *aspect_ratio_info)
8256{
8257 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
8258 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
8259 extra->nVersion.nVersion = OMX_SPEC_VERSION;
8260 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8261 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
8262 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
8263 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;
8264 switch (picture_type)
8265 {
8266 case PICTURE_TYPE_I:
8267 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
8268 break;
8269 case PICTURE_TYPE_P:
8270 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
8271 break;
8272 case PICTURE_TYPE_B:
8273 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
8274 break;
8275 default:
8276 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
8277 }
8278 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
8279 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
8280 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
8281 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
8282 else
8283 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
8284 memset(&frame_info->panScan,0,sizeof(frame_info->panScan));
8285 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
8286 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
8287 {
8288 h264_parser->fill_pan_scan_data(&frame_info->panScan, timestamp);
8289 h264_parser->fill_aspect_ratio_info(&frame_info->aspectRatio);
8290 }
8291 frame_info->nConcealedMacroblocks = num_conceal_mb;
8292 frame_info->nFrameRate = frame_rate;
8293 print_debug_extradata(extra);
8294}
8295
8296void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
8297{
8298 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
8299 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
8300 extra->nVersion.nVersion = OMX_SPEC_VERSION;
8301 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
8302 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
8303 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
8304 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data;
8305 *portDefn = m_port_def;
8306 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u"
8307 "sliceheight = %u \n",portDefn->format.video.nFrameHeight,
8308 portDefn->format.video.nFrameWidth,
8309 portDefn->format.video.nStride,
8310 portDefn->format.video.nSliceHeight);
8311}
8312
8313void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
8314{
8315 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
8316 extra->nVersion.nVersion = OMX_SPEC_VERSION;
8317 extra->eType = OMX_ExtraDataNone;
8318 extra->nDataSize = 0;
8319 extra->data[0] = 0;
8320
8321 print_debug_extradata(extra);
8322}
8323
8324OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
8325{
8326 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8327 if (index >= drv_ctx.ip_buf.actualcount)
8328 {
8329 DEBUG_PRINT_ERROR("\nERROR:Desc Buffer Index not found");
8330 return OMX_ErrorInsufficientResources;
8331 }
8332 if (m_desc_buffer_ptr == NULL)
8333 {
8334 m_desc_buffer_ptr = (desc_buffer_hdr*) \
8335 calloc( (sizeof(desc_buffer_hdr)),
8336 drv_ctx.ip_buf.actualcount);
8337 if (m_desc_buffer_ptr == NULL)
8338 {
8339 DEBUG_PRINT_ERROR("\n m_desc_buffer_ptr Allocation failed ");
8340 return OMX_ErrorInsufficientResources;
8341 }
8342 }
8343
8344 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
8345 if (m_desc_buffer_ptr[index].buf_addr == NULL)
8346 {
8347 DEBUG_PRINT_ERROR("\ndesc buffer Allocation failed ");
8348 return OMX_ErrorInsufficientResources;
8349 }
8350
8351 return eRet;
8352}
8353
8354void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
8355{
8356 DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries);
8357 if (m_demux_entries < 8192)
8358 {
8359 m_demux_offsets[m_demux_entries++] = address_offset;
8360 }
8361 return;
8362}
8363
8364void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
8365{
8366 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
8367 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
8368 OMX_U32 index = 0;
8369
8370 m_demux_entries = 0;
8371
8372 while (index < bytes_to_parse)
8373 {
8374 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8375 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
8376 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
8377 (buf[index+2] == 0x01)) )
8378 {
8379 //Found start code, insert address offset
8380 insert_demux_addr_offset(index);
8381 if (buf[index+2] == 0x01) // 3 byte start code
8382 index += 3;
8383 else //4 byte start code
8384 index += 4;
8385 }
8386 else
8387 index++;
8388 }
8389 DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries);
8390 return;
8391}
8392
8393OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
8394{
8395 //fix this, handle 3 byte start code, vc1 terminator entry
8396 OMX_U8 *p_demux_data = NULL;
8397 OMX_U32 desc_data = 0;
8398 OMX_U32 start_addr = 0;
8399 OMX_U32 nal_size = 0;
8400 OMX_U32 suffix_byte = 0;
8401 OMX_U32 demux_index = 0;
8402 OMX_U32 buffer_index = 0;
8403
8404 if (m_desc_buffer_ptr == NULL)
8405 {
8406 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
8407 return OMX_ErrorBadParameter;
8408 }
8409
8410 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
8411 if (buffer_index > drv_ctx.ip_buf.actualcount)
8412 {
8413 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%d)", buffer_index);
8414 return OMX_ErrorBadParameter;
8415 }
8416
8417 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
8418
8419 if ( ((OMX_U8*)p_demux_data == NULL) ||
8420 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE)
8421 {
8422 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
8423 return OMX_ErrorBadParameter;
8424 }
8425 else
8426 {
8427 for (; demux_index < m_demux_entries; demux_index++)
8428 {
8429 desc_data = 0;
8430 start_addr = m_demux_offsets[demux_index];
8431 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01)
8432 {
8433 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
8434 }
8435 else
8436 {
8437 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
8438 }
8439 if (demux_index < (m_demux_entries - 1))
8440 {
8441 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
8442 }
8443 else
8444 {
8445 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
8446 }
8447 DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)",
8448 start_addr,
8449 suffix_byte,
8450 nal_size,
8451 demux_index);
8452 desc_data = (start_addr >> 3) << 1;
8453 desc_data |= (start_addr & 7) << 21;
8454 desc_data |= suffix_byte << 24;
8455
8456 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8457 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
8458 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8459 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8460
8461 p_demux_data += 16;
8462 }
8463 if (codec_type_parse == CODEC_TYPE_VC1)
8464 {
8465 DEBUG_PRINT_LOW("VC1 terminator entry");
8466 desc_data = 0;
8467 desc_data = 0x82 << 24;
8468 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
8469 memset(p_demux_data + 4, 0, sizeof(OMX_U32));
8470 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
8471 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
8472 p_demux_data += 16;
8473 m_demux_entries++;
8474 }
8475 //Add zero word to indicate end of descriptors
8476 memset(p_demux_data, 0, sizeof(OMX_U32));
8477
8478 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
8479 DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size);
8480 }
8481 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
8482 m_demux_entries = 0;
8483 DEBUG_PRINT_LOW("Demux table complete!");
8484 return OMX_ErrorNone;
8485}
8486
8487#if 0
8488OMX_ERRORTYPE omx_vdec::createDivxDrmContext( OMX_PTR drmHandle )
8489{
8490 OMX_ERRORTYPE err = OMX_ErrorNone;
8491 if( drmHandle == NULL ) {
8492 DEBUG_PRINT_HIGH("\n This clip is not DRM encrypted");
8493 iDivXDrmDecrypt = NULL;
8494 return err;
8495 }
8496
8497 iDivXDrmDecrypt = DivXDrmDecrypt::Create( drmHandle );
8498 if (iDivXDrmDecrypt) {
8499 DEBUG_PRINT_LOW("\nCreated DIVX DRM, now calling Init");
8500 OMX_ERRORTYPE err = iDivXDrmDecrypt->Init();
8501 if(err!=OMX_ErrorNone) {
8502 DEBUG_PRINT_ERROR("\nERROR:iDivXDrmDecrypt->Init %d", err);
8503 delete iDivXDrmDecrypt;
8504 iDivXDrmDecrypt = NULL;
8505 }
8506 }
8507 else {
8508 DEBUG_PRINT_ERROR("\nUnable to Create DIVX DRM");
8509 return OMX_ErrorUndefined;
8510 }
8511 return err;
8512}
8513#endif
8514