1 /**
2  * @copyright
3  *
4  *   Copyright (c) 2015, The Linux Foundation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions are met:
8  *
9  *   * Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *   * Redistributions in binary form must reproduce the above copyright notice,
12  *     this list of conditions and the following disclaimer in the documentation
13  *     and/or other materials provided with the distribution.
14  *   * Neither the name of The Linux Foundation nor the names of its
15  *     contributors may be used to endorse or promote products derived from
16  *     this software without specific prior written permission.
17  *
18  *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
20  *   FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED.
21  *   IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
22  *   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  *   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28  *   DAMAGE.
29  *
30  * @file
31  *
32  *   omx_swvdec.cpp
33  *
34  * @brief
35  *
36  *   OMX software video decoder component source.
37  */
38 
39 #include <assert.h>
40 #include <fcntl.h>
41 #include <sys/mman.h>
42 
43 #include <media/hardware/HardwareAPI.h>
44 #include <gralloc_priv.h>
45 
46 #include "OMX_QCOMExtns.h"
47 
48 #include "omx_swvdec.h"
49 
50 #include "swvdec_api.h"
51 
52 /**
53  * ----------------
54  * PUBLIC FUNCTIONS
55  * ----------------
56  */
57 
58 /**
59  * @brief Create & return component class instance.
60  *
61  * @retval Pointer to new component class instance.
62  */
get_omx_component_factory_fn(void)63 void *get_omx_component_factory_fn(void)
64 {
65     return new omx_swvdec;
66 }
67 
68 /**
69  * @brief Component constructor.
70  */
omx_swvdec()71 omx_swvdec::omx_swvdec():
72     m_state(OMX_StateInvalid),
73     m_status_flags(0),
74     m_swvdec_codec(SWVDEC_CODEC_INVALID),
75     m_swvdec_handle(NULL),
76     m_swvdec_created(false),
77     m_omx_video_codingtype(OMX_VIDEO_CodingUnused),
78     m_omx_color_formattype(OMX_COLOR_FormatUnused),
79     m_sync_frame_decoding_mode(false),
80     m_android_native_buffers(false),
81     m_meta_buffer_mode(false),
82     m_port_reconfig_inprogress(false),
83     m_buffer_array_ip(NULL),
84     m_buffer_array_op(NULL),
85     m_meta_buffer_array(NULL)
86 {
87     // memset all member variables that are composite structures
88     memset(&m_cmp,                     0, sizeof(m_cmp)); // part of base class
89     memset(&m_cmp_name[0],             0, sizeof(m_cmp_name));
90     memset(&m_role_name[0],            0, sizeof(m_role_name));
91     memset(&m_frame_rate,              0, sizeof(m_frame_rate));
92     memset(&m_frame_dimensions,        0, sizeof(m_frame_dimensions));
93     memset(&m_frame_attributes,        0, sizeof(m_frame_attributes));
94     memset(&m_async_thread,            0, sizeof(m_async_thread));
95     memset(&m_port_ip,                 0, sizeof(m_port_ip));
96     memset(&m_port_op,                 0, sizeof(m_port_op));
97     memset(&m_callback,                0, sizeof(m_callback));
98     memset(&m_app_data,                0, sizeof(m_app_data));
99     memset(&m_prio_mgmt,               0, sizeof(m_prio_mgmt));
100     memset(&m_sem_cmd,                 0, sizeof(m_sem_cmd));
101     memset(&m_meta_buffer_array_mutex, 0, sizeof(m_meta_buffer_array_mutex));
102 
103     // null-terminate component name & role name strings
104     m_cmp_name[0]  = '\0';
105     m_role_name[0] = '\0';
106 
107     // ports are enabled & unpopulated by default
108     m_port_ip.enabled     = OMX_TRUE;
109     m_port_op.enabled     = OMX_TRUE;
110     m_port_ip.unpopulated = OMX_TRUE;
111     m_port_op.unpopulated = OMX_TRUE;
112 }
113 
114 /**
115  * @brief Component destructor.
116  */
~omx_swvdec()117 omx_swvdec::~omx_swvdec()
118 {
119 }
120 
121 /**
122  * @brief Initialize component.
123  *
124  * @param[in] cmp_name: Component name string.
125  *
126  * @retval OMX_ERRORTYPE
127  */
component_init(OMX_STRING cmp_name)128 OMX_ERRORTYPE omx_swvdec::component_init(OMX_STRING cmp_name)
129 {
130     OMX_ERRORTYPE retval = OMX_ErrorNone;
131 
132     OMX_SWVDEC_LOG_API("'%s', version date: %s",
133                        cmp_name,
134                        OMX_SWVDEC_VERSION_DATE);
135 
136     omx_swvdec_log_init();
137 
138     if (m_state != OMX_StateInvalid)
139     {
140         OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
141                              OMX_STATETYPE_STRING(m_state));
142         retval = OMX_ErrorIncorrectStateOperation;
143         goto component_init_exit;
144     }
145 
146     // set up codec type variables based on component name string
147 
148     if (!strncmp(cmp_name,
149                  "OMX.qti.video.decoder.mpeg4sw",
150                  OMX_MAX_STRINGNAME_SIZE))
151     {
152         OMX_SWVDEC_LOG_LOW("'video_decoder.mpeg4'");
153 
154         strlcpy(m_cmp_name,               cmp_name, OMX_MAX_STRINGNAME_SIZE);
155         strlcpy(m_role_name, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
156 
157         m_swvdec_codec         = SWVDEC_CODEC_MPEG4;
158         m_omx_video_codingtype = OMX_VIDEO_CodingMPEG4;
159     }
160     else if (!strncmp(cmp_name,
161                       "OMX.qti.video.decoder.h263sw",
162                       OMX_MAX_STRINGNAME_SIZE))
163     {
164         OMX_SWVDEC_LOG_LOW("video_decoder.h263");
165 
166         strlcpy(m_cmp_name,              cmp_name, OMX_MAX_STRINGNAME_SIZE);
167         strlcpy(m_role_name, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
168 
169         m_swvdec_codec         = SWVDEC_CODEC_H263;
170         m_omx_video_codingtype = OMX_VIDEO_CodingH263;
171     }
172     else if (((!strncmp(cmp_name,
173                         "OMX.qti.video.decoder.divxsw",
174                         OMX_MAX_STRINGNAME_SIZE))) ||
175              ((!strncmp(cmp_name,
176                         "OMX.qti.video.decoder.divx4sw",
177                         OMX_MAX_STRINGNAME_SIZE))))
178     {
179         OMX_SWVDEC_LOG_LOW("video_decoder.divx");
180 
181         strlcpy(m_cmp_name,              cmp_name, OMX_MAX_STRINGNAME_SIZE);
182         strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
183 
184         m_swvdec_codec         = SWVDEC_CODEC_MPEG4;
185         m_omx_video_codingtype = ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx);
186     }
187     else
188     {
189         OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
190         retval = OMX_ErrorInvalidComponentName;
191         goto component_init_exit;
192     }
193 
194     m_omx_color_formattype =
195         (OMX_COLOR_FORMATTYPE) OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
196 
197     m_frame_rate.fps_numerator   = DEFAULT_FPS_NUMERATOR;
198     m_frame_rate.fps_denominator = DEFAULT_FPS_DENOMINATOR;
199 
200     {
201         SWVDEC_CALLBACK callback;
202 
203         SWVDEC_STATUS retval_swvdec;
204 
205         // initialize SwVdec core library
206 
207         callback.pfn_empty_buffer_done  = swvdec_empty_buffer_done_callback;
208         callback.pfn_fill_buffer_done   = swvdec_fill_buffer_done_callback;
209         callback.pfn_event_notification = swvdec_event_handler_callback;
210         callback.p_client               = this;
211 
212         if ((retval_swvdec = swvdec_init(&m_swvdec_handle,
213                                          m_swvdec_codec,
214                                          &callback)) !=
215             SWVDEC_STATUS_SUCCESS)
216         {
217             retval = retval_swvdec2omx(retval_swvdec);
218             goto component_init_exit;
219         }
220 
221         m_swvdec_created = true;
222 
223         // set frame dimensions for OMX component & SwVdec core
224         if ((retval = set_frame_dimensions(DEFAULT_FRAME_WIDTH,
225                                            DEFAULT_FRAME_HEIGHT)) !=
226             OMX_ErrorNone)
227         {
228             goto component_init_exit;
229         }
230 
231         // set frame attributes for OMX component & SwVdec core
232         if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
233                                            DEFAULT_ALIGNMENT_SCANLINES_Y,
234                                            DEFAULT_ALIGNMENT_SCANLINES_UV,
235                                            DEFAULT_ALIGNMENT_SIZE)) !=
236             OMX_ErrorNone)
237         {
238             goto component_init_exit;
239         }
240     }
241 
242     // get SwVdec buffer requirements for input port; set m_port_ip
243     if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
244         OMX_ErrorNone)
245     {
246         goto component_init_exit;
247     }
248 
249     // get SwVdec buffer requirements for output port; set m_port_op
250     if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
251         OMX_ErrorNone)
252     {
253         goto component_init_exit;
254     }
255 
256     // create callback thread's mutex & condition variable
257     if ((retval = async_thread_create()) != OMX_ErrorNone)
258     {
259         goto component_init_exit;
260     }
261 
262     // create semaphore for command processing
263     if (sem_init(&m_sem_cmd, 0, 0))
264     {
265         OMX_SWVDEC_LOG_ERROR("failed to create command processing semaphore");
266         retval = OMX_ErrorInsufficientResources;
267         goto component_init_exit;
268     }
269 
270     // create mutex for meta buffer info array
271     if (pthread_mutex_init(&m_meta_buffer_array_mutex, NULL))
272     {
273         OMX_SWVDEC_LOG_ERROR("failed to create meta buffer info array mutex");
274         retval = OMX_ErrorInsufficientResources;
275         goto component_init_exit;
276     }
277 
278     // move to 'loaded' state
279     OMX_SWVDEC_LOG_HIGH("OMX_StateInvalid -> OMX_StateLoaded");
280     m_state = OMX_StateLoaded;
281 
282 component_init_exit:
283     return retval;
284 }
285 
286 /**
287  * @brief De-initialize component.
288  *
289  * @param[in] cmp_handle: Component handle.
290  *
291  * @retval OMX_ERRORTYPE
292  */
component_deinit(OMX_HANDLETYPE cmp_handle)293 OMX_ERRORTYPE omx_swvdec::component_deinit(OMX_HANDLETYPE cmp_handle)
294 {
295     OMX_SWVDEC_LOG_API("");
296 
297     if (cmp_handle == NULL)
298     {
299         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
300     }
301 
302     pthread_mutex_destroy(&m_meta_buffer_array_mutex);
303 
304     sem_destroy(&m_sem_cmd);
305 
306     async_thread_destroy();
307 
308     if (m_swvdec_created)
309     {
310         swvdec_deinit(m_swvdec_handle);
311         m_swvdec_handle = NULL;
312     }
313 
314     OMX_SWVDEC_LOG_HIGH("all done, goodbye!");
315 
316     return OMX_ErrorNone;
317 }
318 
319 /**
320  * @brief Get component version.
321  *
322  * @param[in]     cmp_handle:     Component handle.
323  * @param[in]     cmp_name:       Component name string.
324  * @param[in,out] p_cmp_version:  Pointer to component version variable.
325  * @param[in,out] p_spec_version: Pointer to OMX spec version variable.
326  * @param[in,out] p_cmp_UUID:     Pointer to component UUID variable.
327  *
328  * @retval OMX_ERRORTYPE
329  */
get_component_version(OMX_HANDLETYPE cmp_handle,OMX_STRING cmp_name,OMX_VERSIONTYPE * p_cmp_version,OMX_VERSIONTYPE * p_spec_version,OMX_UUIDTYPE * p_cmp_UUID)330 OMX_ERRORTYPE omx_swvdec::get_component_version(OMX_HANDLETYPE   cmp_handle,
331                                                 OMX_STRING       cmp_name,
332                                                 OMX_VERSIONTYPE *p_cmp_version,
333                                                 OMX_VERSIONTYPE *p_spec_version,
334                                                 OMX_UUIDTYPE    *p_cmp_UUID)
335 {
336     OMX_ERRORTYPE retval = OMX_ErrorNone;
337 
338     (void) p_cmp_UUID;
339 
340     OMX_SWVDEC_LOG_API("");
341 
342     if (m_state == OMX_StateInvalid)
343     {
344         OMX_SWVDEC_LOG_ERROR("in invalid state");
345         retval = OMX_ErrorInvalidState;
346     }
347     else if (cmp_handle == NULL)
348     {
349         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
350         retval = OMX_ErrorInvalidComponent;
351     }
352     else if (strncmp(cmp_name, m_cmp_name, sizeof(m_cmp_name)))
353     {
354         OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
355         retval = OMX_ErrorInvalidComponentName;
356     }
357     else if (p_cmp_version == NULL)
358     {
359         OMX_SWVDEC_LOG_ERROR("p_cmp_version = NULL");
360         retval = OMX_ErrorBadParameter;
361     }
362     else if (p_spec_version == NULL)
363     {
364         OMX_SWVDEC_LOG_ERROR("p_spec_version = NULL");
365         retval = OMX_ErrorBadParameter;
366     }
367     else
368     {
369         p_spec_version->nVersion = OMX_SPEC_VERSION;
370     }
371 
372 get_component_version_exit:
373     return retval;
374 }
375 
376 /**
377  * @brief Send command to component.
378  *
379  * @param[in] cmp_handle: Component handle.
380  * @param[in] cmd:        Command.
381  * @param[in] param:      Command parameter.
382  * @param[in] p_cmd_data: Pointer to command data.
383  *
384  * @retval OMX_ERRORTYPE
385  */
send_command(OMX_HANDLETYPE cmp_handle,OMX_COMMANDTYPE cmd,OMX_U32 param,OMX_PTR p_cmd_data)386 OMX_ERRORTYPE omx_swvdec::send_command(OMX_HANDLETYPE  cmp_handle,
387                                        OMX_COMMANDTYPE cmd,
388                                        OMX_U32         param,
389                                        OMX_PTR         p_cmd_data)
390 {
391     OMX_ERRORTYPE retval = OMX_ErrorNone;
392 
393     (void) p_cmd_data; // prevent warning for unused function argument
394 
395     if (m_state == OMX_StateInvalid)
396     {
397         OMX_SWVDEC_LOG_ERROR("in invalid state");
398         retval = OMX_ErrorInvalidState;
399         goto send_command_exit;
400     }
401     else if (cmp_handle == NULL)
402     {
403         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
404         retval = OMX_ErrorInvalidComponent;
405         goto send_command_exit;
406     }
407 
408     switch (cmd)
409     {
410 
411     case OMX_CommandStateSet:
412     {
413         OMX_SWVDEC_LOG_API("%s, %s",
414                            OMX_COMMANDTYPE_STRING(cmd),
415                            OMX_STATETYPE_STRING((OMX_STATETYPE) param));
416         break;
417     }
418 
419     case OMX_CommandFlush:
420     case OMX_CommandPortDisable:
421     case OMX_CommandPortEnable:
422     {
423         OMX_SWVDEC_LOG_API("%s, port index %d",
424                            OMX_COMMANDTYPE_STRING(cmd),
425                            param);
426 
427         if ((param != OMX_CORE_PORT_INDEX_IP) &&
428             (param != OMX_CORE_PORT_INDEX_OP) &&
429             (param != OMX_ALL))
430         {
431             OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", param);
432             retval = OMX_ErrorBadPortIndex;
433         }
434         break;
435     }
436 
437     default:
438     {
439         OMX_SWVDEC_LOG_API("cmd %d, param %d", cmd, param);
440 
441         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", cmd);
442         retval = OMX_ErrorBadParameter;
443         break;
444     }
445 
446     } // switch (cmd)
447 
448     if (retval == OMX_ErrorNone)
449     {
450         if (cmp_handle == NULL)
451         {
452             OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
453             retval = OMX_ErrorInvalidComponent;
454         }
455         else if (m_state == OMX_StateInvalid)
456         {
457             OMX_SWVDEC_LOG_ERROR("in invalid state");
458             retval = OMX_ErrorInvalidState;
459         }
460     }
461 
462     if (retval != OMX_ErrorNone)
463     {
464         // command not processed; return error code via event handler callback
465         async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
466     }
467     else
468     {
469         // post command event
470         async_post_event(OMX_SWVDEC_EVENT_CMD, cmd, param);
471 
472         // wait on command semaphore
473         sem_wait(&m_sem_cmd);
474     }
475 
476 send_command_exit:
477     return retval;
478 }
479 
480 /**
481  * @brief Get a parameter from component.
482  *
483  * @param[in]     cmp_handle:   Component handle.
484  * @param[in]     param_index:  Parameter index.
485  * @param[in,out] p_param_data: Pointer to parameter data.
486  *
487  * @retval OMX_ERRORTYPE
488  */
get_parameter(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE param_index,OMX_PTR p_param_data)489 OMX_ERRORTYPE omx_swvdec::get_parameter(OMX_HANDLETYPE cmp_handle,
490                                         OMX_INDEXTYPE  param_index,
491                                         OMX_PTR        p_param_data)
492 {
493     OMX_ERRORTYPE retval = OMX_ErrorNone;
494 
495     if (m_state == OMX_StateInvalid)
496     {
497         OMX_SWVDEC_LOG_ERROR("in invalid state");
498         retval = OMX_ErrorInvalidState;
499     }
500     else if (cmp_handle == NULL)
501     {
502         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
503         retval = OMX_ErrorInvalidComponent;
504     }
505     else if (p_param_data == NULL)
506     {
507         OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
508         retval = OMX_ErrorBadParameter;
509     }
510 
511     if (retval != OMX_ErrorNone)
512     {
513         goto get_parameter_exit;
514     }
515 
516     switch (param_index)
517     {
518 
519     case OMX_IndexParamAudioInit:
520     {
521         OMX_PORT_PARAM_TYPE *p_port_param =
522             (OMX_PORT_PARAM_TYPE *) p_param_data;
523 
524         p_port_param->nPorts           = 0;
525         p_port_param->nStartPortNumber = 0;
526 
527         OMX_SWVDEC_LOG_API("OMX_IndexParamAudioInit: "
528                            "%d port(s), start port %d",
529                            p_port_param->nPorts,
530                            p_port_param->nStartPortNumber);
531         break;
532     }
533 
534     case OMX_IndexParamImageInit:
535     {
536         OMX_PORT_PARAM_TYPE *p_port_param =
537             (OMX_PORT_PARAM_TYPE *) p_param_data;
538 
539         p_port_param->nPorts           = 0;
540         p_port_param->nStartPortNumber = 0;
541 
542         OMX_SWVDEC_LOG_API("OMX_IndexParamImageInit: "
543                            "%d port(s), start port %d",
544                            p_port_param->nPorts,
545                            p_port_param->nStartPortNumber);
546         break;
547     }
548 
549     case OMX_IndexParamVideoInit:
550     {
551         OMX_PORT_PARAM_TYPE *p_port_param =
552             (OMX_PORT_PARAM_TYPE *) p_param_data;
553 
554         p_port_param->nPorts           = 2;
555         p_port_param->nStartPortNumber = 0;
556 
557         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoInit: "
558                            "%d port(s), start port %d",
559                            p_port_param->nPorts,
560                            p_port_param->nStartPortNumber);
561         break;
562     }
563 
564     case OMX_IndexParamOtherInit:
565     {
566         OMX_PORT_PARAM_TYPE *p_port_param =
567             (OMX_PORT_PARAM_TYPE *) p_param_data;
568 
569         p_port_param->nPorts           = 0;
570         p_port_param->nStartPortNumber = 0;
571 
572         OMX_SWVDEC_LOG_API("OMX_IndexParamOtherInit: "
573                            "%d port(s), start port %d",
574                            p_port_param->nPorts,
575                            p_port_param->nStartPortNumber);
576         break;
577     }
578 
579     case OMX_IndexConfigPriorityMgmt:
580     {
581         OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
582             (OMX_PRIORITYMGMTTYPE *) p_param_data;
583 
584         OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt");
585 
586         memcpy(p_prio_mgmt, &m_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
587         break;
588     }
589 
590     case OMX_IndexParamStandardComponentRole:
591     {
592         OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
593             (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
594 
595         strlcpy((char *) p_cmp_role->cRole,
596                 m_role_name,
597                 OMX_MAX_STRINGNAME_SIZE);
598 
599         OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole: %s",
600                            p_cmp_role->cRole);
601         break;
602     }
603 
604     case OMX_IndexParamPortDefinition:
605     {
606         OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
607             (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
608 
609         OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
610                            p_port_def->nPortIndex);
611 
612         retval = get_port_definition(p_port_def);
613         break;
614     }
615 
616     case OMX_IndexParamCompBufferSupplier:
617     {
618         OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
619             (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
620 
621         OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier, port index %d",
622                            p_buffer_supplier->nPortIndex);
623 
624         if ((p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_IP) ||
625             (p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_OP))
626         {
627             p_buffer_supplier->eBufferSupplier = OMX_BufferSupplyUnspecified;
628         }
629         else
630         {
631             OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
632                                  p_buffer_supplier->nPortIndex);
633             retval = OMX_ErrorBadPortIndex;
634         }
635 
636         break;
637     }
638 
639     case OMX_IndexParamVideoPortFormat:
640     {
641         OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
642             (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
643 
644         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, "
645                            "port index %d, index %d",
646                            p_port_format->nPortIndex,
647                            p_port_format->nIndex);
648 
649         retval = get_video_port_format(p_port_format);
650         break;
651     }
652 
653     case OMX_IndexParamVideoMpeg2:
654     {
655         OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2: unsupported");
656         retval = OMX_ErrorUnsupportedIndex;
657         break;
658     }
659 
660     case OMX_IndexParamVideoMpeg4:
661     {
662         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4: unsupported");
663         retval = OMX_ErrorUnsupportedIndex;
664         break;
665     }
666 
667     case OMX_IndexParamVideoAvc:
668     {
669         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc: unsupported");
670         retval = OMX_ErrorUnsupportedIndex;
671         break;
672     }
673 
674     case OMX_IndexParamVideoH263:
675     {
676         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263: unsupported");
677         retval = OMX_ErrorUnsupportedIndex;
678         break;
679     }
680 
681     case OMX_IndexParamVideoProfileLevelQuerySupported:
682     {
683         OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel =
684             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) p_param_data;
685 
686         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoProfileLevelQuerySupported, "
687                            "port index %d, profile index %d",
688                            p_profilelevel->nPortIndex,
689                            p_profilelevel->nProfileIndex);
690 
691         retval = get_supported_profilelevel(p_profilelevel);
692         break;
693     }
694 
695     default:
696     {
697         /**
698          * Vendor-specific extension indices checked here since they are not
699          * part of the OMX_INDEXTYPE enumerated type.
700          */
701 
702         switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
703         {
704 
705         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
706         {
707             GetAndroidNativeBufferUsageParams *p_buffer_usage =
708                 (GetAndroidNativeBufferUsageParams *) p_param_data;
709 
710             OMX_SWVDEC_LOG_API(
711                 "OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage, "
712                 "port index %d", p_buffer_usage->nPortIndex);
713 
714             if (p_buffer_usage->nPortIndex == OMX_CORE_PORT_INDEX_OP)
715             {
716                 p_buffer_usage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
717                                           GRALLOC_USAGE_SW_READ_OFTEN |
718                                           GRALLOC_USAGE_SW_WRITE_OFTEN);
719             }
720             else
721             {
722                 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
723                                      p_buffer_usage->nPortIndex);
724                 retval = OMX_ErrorBadPortIndex;
725             }
726             break;
727         }
728 
729         case OMX_QcomIndexFlexibleYUVDescription:
730         {
731             OMX_SWVDEC_LOG_API("OMX_QcomIndexFlexibleYUVDescription");
732 
733             retval = describe_color_format((DescribeColorFormatParams *)
734                                            p_param_data);
735             break;
736         }
737 
738         default:
739         {
740             OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
741             retval = OMX_ErrorBadParameter;
742             break;
743         }
744 
745         } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
746 
747     } // default case
748 
749     } // switch (param_index)
750 
751 get_parameter_exit:
752     return retval;
753 }
754 
755 /**
756  * @brief Set a parameter to component.
757  *
758  * @param[in] cmp_handle:   Component handle.
759  * @param[in] param_index:  Parameter index.
760  * @param[in] p_param_data: Pointer to parameter data.
761  *
762  * @retval OMX_ERRORTYPE
763  */
set_parameter(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE param_index,OMX_PTR p_param_data)764 OMX_ERRORTYPE omx_swvdec::set_parameter(OMX_HANDLETYPE cmp_handle,
765                                         OMX_INDEXTYPE  param_index,
766                                         OMX_PTR        p_param_data)
767 {
768     OMX_ERRORTYPE retval = OMX_ErrorNone;
769 
770     if (m_state == OMX_StateInvalid)
771     {
772         OMX_SWVDEC_LOG_ERROR("in invalid state");
773         retval = OMX_ErrorInvalidState;
774     }
775     else if (cmp_handle == NULL)
776     {
777         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
778         retval = OMX_ErrorInvalidComponent;
779     }
780     else if (p_param_data == NULL)
781     {
782         OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
783         retval = OMX_ErrorBadParameter;
784     }
785     else if ((m_state != OMX_StateLoaded) &&
786              (m_port_reconfig_inprogress == false))
787     {
788         OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
789                              OMX_STATETYPE_STRING(m_state));
790         retval = OMX_ErrorIncorrectStateOperation;
791     }
792 
793     if (retval != OMX_ErrorNone)
794     {
795         goto set_parameter_exit;
796     }
797 
798     switch (param_index)
799     {
800 
801     case OMX_IndexParamPriorityMgmt:
802     {
803         OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
804             (OMX_PRIORITYMGMTTYPE *) p_param_data;
805 
806         OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt: "
807                            "group ID %d, group priority %d",
808                            p_prio_mgmt->nGroupID,
809                            p_prio_mgmt->nGroupPriority);
810 
811         if (m_state != OMX_StateLoaded)
812         {
813             OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
814                                  "should be in loaded state",
815                                  m_state);
816             retval = OMX_ErrorIncorrectStateOperation;
817         }
818         else
819         {
820             memcpy(&m_prio_mgmt, p_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
821         }
822 
823         break;
824     }
825 
826     case OMX_IndexParamStandardComponentRole:
827     {
828         OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
829             (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
830 
831         OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole '%s'",
832                            p_cmp_role->cRole);
833 
834         if (m_state != OMX_StateLoaded)
835         {
836             OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
837                                  "should be in loaded state",
838                                  m_state);
839             retval = OMX_ErrorIncorrectStateOperation;
840         }
841         else
842         {
843             if (strncmp((char *) p_cmp_role->cRole,
844                         m_role_name,
845                         OMX_MAX_STRINGNAME_SIZE))
846             {
847                 OMX_SWVDEC_LOG_ERROR("'%s': invalid component role name",
848                                      p_cmp_role->cRole);
849                 retval = OMX_ErrorBadParameter;
850             }
851         }
852 
853         break;
854     }
855 
856     case OMX_IndexParamPortDefinition:
857     {
858         OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
859             (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
860 
861         OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
862                            p_port_def->nPortIndex);
863 
864         if ((m_state != OMX_StateLoaded) &&
865             (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
866               (m_port_ip.enabled      == OMX_TRUE) &&
867               (m_port_ip.populated    == OMX_TRUE)) ||
868              ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
869               (m_port_op.enabled      == OMX_TRUE) &&
870               (m_port_op.populated    == OMX_TRUE))))
871         {
872             OMX_SWVDEC_LOG_ERROR("OMX_IndexParamPortDefinition "
873                                  "disallowed in state %s "
874                                  "while port %d is enabled & populated",
875                                  OMX_STATETYPE_STRING(m_state),
876                                  p_port_def->nPortIndex);
877 
878             retval = OMX_ErrorIncorrectStateOperation;
879         }
880         else
881         {
882             retval = set_port_definition(p_port_def);
883         }
884 
885         break;
886     }
887 
888     case OMX_IndexParamCompBufferSupplier:
889     {
890         OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
891             (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
892 
893         OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier: "
894                            "port index %d, buffer supplier %d",
895                            p_buffer_supplier->nPortIndex,
896                            (int) p_buffer_supplier->eBufferSupplier);
897 
898         if ((p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_IP) &&
899             (p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_OP))
900         {
901             OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
902                                  p_buffer_supplier->nPortIndex);
903             retval = OMX_ErrorBadPortIndex;
904         }
905 
906         break;
907     }
908 
909     case OMX_IndexParamVideoPortFormat:
910     {
911         OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
912             (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
913 
914         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, port index %d",
915                            p_port_format->nPortIndex);
916 
917         if ((m_state != OMX_StateLoaded) &&
918             (((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
919               (m_port_ip.enabled         == OMX_TRUE) &&
920               (m_port_ip.populated       == OMX_TRUE)) ||
921              ((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
922               (m_port_op.enabled         == OMX_TRUE) &&
923               (m_port_op.populated       == OMX_TRUE))))
924         {
925             OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoPortFormat "
926                                  "disallowed in state %s "
927                                  "while port %d is enabled & populated",
928                                  OMX_STATETYPE_STRING(m_state),
929                                  p_port_format->nPortIndex);
930 
931             retval = OMX_ErrorIncorrectStateOperation;
932         }
933         else
934         {
935             retval = set_video_port_format(p_port_format);
936         }
937 
938         break;
939     }
940 
941     case OMX_IndexParamVideoMpeg2:
942     {
943         OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2 unsupported");
944         retval = OMX_ErrorUnsupportedIndex;
945         break;
946     }
947 
948     case OMX_IndexParamVideoMpeg4:
949     {
950         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4 unsupported");
951         retval = OMX_ErrorUnsupportedIndex;
952         break;
953     }
954 
955     case OMX_IndexParamVideoAvc:
956     {
957         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc unsupported");
958         retval = OMX_ErrorUnsupportedIndex;
959         break;
960     }
961 
962     case OMX_IndexParamVideoH263:
963     {
964         OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263 unsupported");
965         retval = OMX_ErrorUnsupportedIndex;
966         break;
967     }
968 
969     default:
970     {
971         /**
972          * Vendor-specific extension indices checked here since they are not
973          * part of the OMX_INDEXTYPE enumerated type.
974          */
975 
976         switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
977         {
978 
979         case OMX_QcomIndexPortDefn:
980         {
981             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def =
982                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) p_param_data;
983 
984             OMX_SWVDEC_LOG_API("OMX_QcomIndexPortDefn, port index %d",
985                                p_port_def->nPortIndex);
986 
987             if ((m_state != OMX_StateLoaded) &&
988                 (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
989                   (m_port_ip.enabled      == OMX_TRUE) &&
990                   (m_port_ip.populated    == OMX_TRUE)) ||
991                  ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
992                   (m_port_op.enabled      == OMX_TRUE) &&
993                   (m_port_op.populated    == OMX_TRUE))))
994             {
995                 OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexPortDefn "
996                                      "disallowed in state %s "
997                                      "while port %d is enabled & populated",
998                                      OMX_STATETYPE_STRING(m_state),
999                                      p_port_def->nPortIndex);
1000 
1001                 retval = OMX_ErrorIncorrectStateOperation;
1002             }
1003             else
1004             {
1005                 retval = set_port_definition_qcom(p_port_def);
1006             }
1007 
1008             break;
1009         }
1010 
1011         case OMX_QcomIndexParamVideoDivx:
1012         {
1013             OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoDivx");
1014             OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexParamVideoDivx unsupported");
1015             retval = OMX_ErrorUnsupportedIndex;
1016             break;
1017         }
1018 
1019         case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
1020         {
1021             OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoSyncFrameDecodingMode");
1022             m_sync_frame_decoding_mode = true;
1023             break;
1024         }
1025 
1026         case OMX_QcomIndexParamVideoDecoderPictureOrder:
1027         {
1028             QOMX_VIDEO_DECODER_PICTURE_ORDER *p_picture_order =
1029                 (QOMX_VIDEO_DECODER_PICTURE_ORDER *) p_param_data;
1030 
1031             switch (p_picture_order->eOutputPictureOrder)
1032             {
1033 
1034             case QOMX_VIDEO_DISPLAY_ORDER:
1035             {
1036                 OMX_SWVDEC_LOG_API(
1037                     "OMX_QcomIndexParamVideoDecoderPictureOrder, "
1038                     "QOMX_VIDEO_DISPLAY_ORDER");
1039                 break;
1040             }
1041 
1042             case QOMX_VIDEO_DECODE_ORDER:
1043             {
1044                 OMX_SWVDEC_LOG_ERROR(
1045                     "OMX_QcomIndexParamVideoDecoderPictureOrder, "
1046                     "QOMX_VIDEO_DECODE_ORDER; unsupported");
1047 
1048                 retval = OMX_ErrorUnsupportedSetting;
1049                 break;
1050             }
1051 
1052             default:
1053             {
1054                 OMX_SWVDEC_LOG_ERROR(
1055                     "OMX_QcomIndexParamVideoDecoderPictureOrder, %d; invalid");
1056 
1057                 retval = OMX_ErrorBadParameter;
1058                 break;
1059             }
1060 
1061             }
1062             break;
1063         }
1064 
1065         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
1066         {
1067             OMX_SWVDEC_LOG_API(
1068                 "OMX_GoogleAndroidIndexEnableAndroidNativeBuffers, %s",
1069                 (((EnableAndroidNativeBuffersParams *) p_param_data)->enable ?
1070                  "enable" :
1071                  "disable"));
1072 
1073             m_android_native_buffers =
1074                 (bool) (((EnableAndroidNativeBuffersParams *)
1075                          p_param_data)->enable);
1076 
1077             break;
1078         }
1079 
1080         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
1081         {
1082             OMX_SWVDEC_LOG_ERROR("OMX_GoogleAndroidIndexUseAndroidNativeBuffer "
1083                                  "unsupported");
1084 
1085             retval = OMX_ErrorUnsupportedIndex;
1086             break;
1087         }
1088 
1089         case OMX_QcomIndexParamEnableTimeStampReorder:
1090         {
1091             OMX_SWVDEC_LOG_API(
1092                 "OMX_QcomIndexParamEnableTimeStampReorder, %s",
1093                 (((QOMX_INDEXTIMESTAMPREORDER *) p_param_data)->bEnable ?
1094                  "enable" :
1095                  "disable"));
1096 
1097             break;
1098         }
1099 
1100         case OMX_QcomIndexParamVideoMetaBufferMode:
1101         {
1102             StoreMetaDataInBuffersParams *p_meta_data =
1103                 (StoreMetaDataInBuffersParams *) p_param_data;
1104 
1105             OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoMetaBufferMode, "
1106                                "port index %d, %s",
1107                                p_meta_data->nPortIndex,
1108                                (p_meta_data->bStoreMetaData ?
1109                                 "enabled" :
1110                                 "disabled"));
1111 
1112             if (p_meta_data->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1113             {
1114                 m_meta_buffer_mode = (bool) p_meta_data->bStoreMetaData;
1115             }
1116             else
1117             {
1118                 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1119                                      p_meta_data->nPortIndex);
1120                 retval = OMX_ErrorBadPortIndex;
1121             }
1122 
1123             break;
1124         }
1125 
1126         default:
1127         {
1128             OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
1129             retval = OMX_ErrorBadParameter;
1130             break;
1131         }
1132 
1133         } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
1134 
1135         break;
1136     } // default case
1137 
1138     } // switch (param_index)
1139 
1140 set_parameter_exit:
1141     return retval;
1142 }
1143 
1144 /**
1145  * @brief Get a configuration from component.
1146  *
1147  * @param[in] cmp_handle:    Component handle.
1148  * @param[in] config_index:  Configuration index.
1149  * @param[in] p_config_data: Pointer to configuration data.
1150  *
1151  * @retval OMX_ERRORTYPE
1152  */
get_config(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE config_index,OMX_PTR p_config_data)1153 OMX_ERRORTYPE omx_swvdec::get_config(OMX_HANDLETYPE cmp_handle,
1154                                      OMX_INDEXTYPE  config_index,
1155                                      OMX_PTR        p_config_data)
1156 {
1157     OMX_ERRORTYPE retval = OMX_ErrorNone;
1158 
1159     if (m_state == OMX_StateInvalid)
1160     {
1161         OMX_SWVDEC_LOG_ERROR("in invalid state");
1162         retval = OMX_ErrorInvalidState;
1163         goto get_config_exit;
1164     }
1165     else if (cmp_handle == NULL)
1166     {
1167         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1168         retval = OMX_ErrorInvalidComponent;
1169         goto get_config_exit;
1170     }
1171     else if (p_config_data == NULL)
1172     {
1173         OMX_SWVDEC_LOG_ERROR("p_config_data = NULL");
1174         retval = OMX_ErrorBadParameter;
1175         goto get_config_exit;
1176     }
1177 
1178     switch (config_index)
1179     {
1180 
1181     case OMX_IndexConfigCommonOutputCrop:
1182     {
1183         OMX_CONFIG_RECTTYPE *p_recttype = (OMX_CONFIG_RECTTYPE *) p_config_data;
1184 
1185         OMX_SWVDEC_LOG_API("OMX_IndexConfigCommonOutputCrop, port index %d",
1186                            p_recttype->nPortIndex);
1187 
1188         if (p_recttype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1189         {
1190             p_recttype->nLeft   = 0;
1191             p_recttype->nTop    = 0;
1192             p_recttype->nWidth  = m_frame_dimensions.width;
1193             p_recttype->nHeight = m_frame_dimensions.height;
1194         }
1195         else
1196         {
1197             OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1198                                  p_recttype->nPortIndex);
1199             retval = OMX_ErrorBadPortIndex;
1200         }
1201 
1202         break;
1203     }
1204 
1205     default:
1206     {
1207         switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
1208         {
1209 
1210         case OMX_QcomIndexConfigInterlaced:
1211         {
1212             OMX_QCOM_CONFIG_INTERLACETYPE *p_config_interlacetype =
1213                 (OMX_QCOM_CONFIG_INTERLACETYPE *) p_config_data;
1214 
1215             OMX_SWVDEC_LOG_API("OMX_QcomIndexConfigInterlaced, "
1216                                "port index %d, index %d",
1217                                p_config_interlacetype->nPortIndex,
1218                                p_config_interlacetype->nIndex);
1219 
1220             if (p_config_interlacetype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
1221             {
1222                 if (p_config_interlacetype->nIndex == 0)
1223                 {
1224                     p_config_interlacetype->eInterlaceType =
1225                         OMX_QCOM_InterlaceFrameProgressive;
1226                 }
1227                 else if (p_config_interlacetype->nIndex == 1)
1228                 {
1229                     p_config_interlacetype->eInterlaceType =
1230                         OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
1231                 }
1232                 else if (p_config_interlacetype->nIndex == 2)
1233                 {
1234                     p_config_interlacetype->eInterlaceType =
1235                         OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
1236                 }
1237                 else
1238                 {
1239                     OMX_SWVDEC_LOG_ERROR("index '%d' unsupported; "
1240                                          "no more interlaced types",
1241                                          p_config_interlacetype->nIndex);
1242                     retval = OMX_ErrorNoMore;
1243                 }
1244             }
1245             else
1246             {
1247                 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1248                                      p_config_interlacetype->nPortIndex);
1249                 retval = OMX_ErrorBadPortIndex;
1250             }
1251 
1252             break;
1253         }
1254 
1255         case OMX_QcomIndexQueryNumberOfVideoDecInstance:
1256         {
1257             QOMX_VIDEO_QUERY_DECODER_INSTANCES *p_decoder_instances =
1258                 (QOMX_VIDEO_QUERY_DECODER_INSTANCES *) p_config_data;
1259 
1260             OMX_SWVDEC_LOG_API("OMX_QcomIndexQueryNumberOfVideoDecInstance");
1261 
1262             p_decoder_instances->nNumOfInstances = OMX_SWVDEC_NUM_INSTANCES;
1263             break;
1264         }
1265 
1266         case OMX_QcomIndexConfigVideoFramePackingArrangement:
1267         {
1268             OMX_SWVDEC_LOG_API(
1269                 "OMX_QcomIndexConfigVideoFramePackingArrangement");
1270 
1271             OMX_SWVDEC_LOG_ERROR(
1272                 "OMX_QcomIndexConfigVideoFramePackingArrangement unsupported");
1273 
1274             retval = OMX_ErrorUnsupportedIndex;
1275             break;
1276         }
1277 
1278         default:
1279         {
1280             OMX_SWVDEC_LOG_ERROR("config index '%d' invalid", config_index);
1281             retval = OMX_ErrorBadParameter;
1282             break;
1283         }
1284 
1285         } // switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
1286 
1287         break;
1288     }
1289 
1290     } // switch (config_index)
1291 
1292 get_config_exit:
1293     return retval;
1294 }
1295 
1296 /**
1297  * @brief Set a configuration to component.
1298  *
1299  * @retval OMX_ERRORTYPE
1300  */
set_config(OMX_HANDLETYPE cmp_handle,OMX_INDEXTYPE config_index,OMX_PTR p_config_data)1301 OMX_ERRORTYPE omx_swvdec::set_config(OMX_HANDLETYPE cmp_handle,
1302                                      OMX_INDEXTYPE  config_index,
1303                                      OMX_PTR        p_config_data)
1304 {
1305     (void) cmp_handle;
1306     (void) config_index;
1307     (void) p_config_data;
1308 
1309     OMX_SWVDEC_LOG_ERROR("not implemented");
1310 
1311     return OMX_ErrorNotImplemented;
1312 }
1313 
1314 /**
1315  * @brief Translate a vendor-specific extension string to a standard index type.
1316  *
1317  * @param[in]     cmp_handle:   Component handle.
1318  * @param[in]     param_name:   Parameter name (extension string).
1319  * @param[in,out] p_index_type: Pointer to extension string's index type.
1320  *
1321  * @retval OMX_ERRORTYPE
1322  */
get_extension_index(OMX_HANDLETYPE cmp_handle,OMX_STRING param_name,OMX_INDEXTYPE * p_index_type)1323 OMX_ERRORTYPE omx_swvdec::get_extension_index(OMX_HANDLETYPE cmp_handle,
1324                                               OMX_STRING     param_name,
1325                                               OMX_INDEXTYPE *p_index_type)
1326 {
1327     OMX_ERRORTYPE retval = OMX_ErrorNone;
1328 
1329     if (m_state == OMX_StateInvalid)
1330     {
1331         OMX_SWVDEC_LOG_ERROR("in invalid state");
1332         retval = OMX_ErrorInvalidState;
1333     }
1334     else if (cmp_handle == NULL)
1335     {
1336         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1337         retval = OMX_ErrorInvalidComponent;
1338     }
1339     else if (p_index_type == NULL)
1340     {
1341         OMX_SWVDEC_LOG_ERROR("p_index_type = NULL");
1342         retval = OMX_ErrorBadParameter;
1343     }
1344 
1345     if (retval != OMX_ErrorNone)
1346         goto get_extension_index_exit;
1347 
1348     OMX_SWVDEC_LOG_API("'%s'", param_name);
1349 
1350     if (!strncmp(param_name,
1351                  "OMX.QCOM.index.param.video.SyncFrameDecodingMode",
1352                  OMX_MAX_STRINGNAME_SIZE))
1353     {
1354         *p_index_type =
1355             (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyncFrameDecodingMode;
1356     }
1357     else if (!strncmp(param_name,
1358                       "OMX.QCOM.index.param.IndexExtraData",
1359                       OMX_MAX_STRINGNAME_SIZE))
1360     {
1361         *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamIndexExtraDataType;
1362     }
1363     else if (!strncmp(param_name,
1364                       "OMX.google.android.index.enableAndroidNativeBuffers",
1365                       OMX_MAX_STRINGNAME_SIZE))
1366     {
1367         *p_index_type =
1368             (OMX_INDEXTYPE) OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
1369     }
1370     else if (!strncmp(param_name,
1371                       "OMX.google.android.index.useAndroidNativeBuffer2",
1372                       OMX_MAX_STRINGNAME_SIZE))
1373     {
1374         *p_index_type =
1375             (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
1376     }
1377     else if (!strncmp(param_name,
1378                       "OMX.google.android.index.useAndroidNativeBuffer",
1379                       OMX_MAX_STRINGNAME_SIZE))
1380     {
1381         *p_index_type =
1382             (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
1383     }
1384     else if (!strncmp(param_name,
1385                       "OMX.google.android.index.getAndroidNativeBufferUsage",
1386                       OMX_MAX_STRINGNAME_SIZE))
1387     {
1388         *p_index_type =
1389             (OMX_INDEXTYPE) OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
1390     }
1391     else if (!strncmp(param_name,
1392                       "OMX.google.android.index.storeMetaDataInBuffers",
1393                       OMX_MAX_STRINGNAME_SIZE))
1394     {
1395         *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamVideoMetaBufferMode;
1396     }
1397     else if (!strncmp(param_name,
1398                       "OMX.google.android.index.describeColorFormat",
1399                       OMX_MAX_STRINGNAME_SIZE))
1400     {
1401         *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexFlexibleYUVDescription;
1402     }
1403     else
1404     {
1405         OMX_SWVDEC_LOG_ERROR("'%s': not implemented", param_name);
1406         retval = OMX_ErrorNotImplemented;
1407     }
1408 
1409 get_extension_index_exit:
1410     return retval;
1411 }
1412 
1413 /**
1414  * @brief Get component state.
1415  *
1416  * @param[in]     cmp_handle: Component handle.
1417  * @param[in,out] p_state:    Pointer to state variable.
1418  *
1419  * @retval OMX_ERRORTYPE
1420  */
get_state(OMX_HANDLETYPE cmp_handle,OMX_STATETYPE * p_state)1421 OMX_ERRORTYPE omx_swvdec::get_state(OMX_HANDLETYPE cmp_handle,
1422                                     OMX_STATETYPE *p_state)
1423 {
1424     OMX_ERRORTYPE retval = OMX_ErrorNone;
1425 
1426     if (cmp_handle == NULL)
1427     {
1428         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1429         retval = OMX_ErrorInvalidComponent;
1430     }
1431     else
1432     {
1433         OMX_SWVDEC_LOG_API("%s", OMX_STATETYPE_STRING(m_state));
1434         *p_state = m_state;
1435     }
1436 
1437     return retval;
1438 }
1439 
1440 /**
1441  * @brief Component tunnel request.
1442  *
1443  * @retval OMX_ErrorNotImplemented
1444  */
component_tunnel_request(OMX_HANDLETYPE cmp_handle,OMX_U32 port,OMX_HANDLETYPE peer_component,OMX_U32 peer_port,OMX_TUNNELSETUPTYPE * p_tunnel_setup)1445 OMX_ERRORTYPE omx_swvdec::component_tunnel_request(
1446     OMX_HANDLETYPE       cmp_handle,
1447     OMX_U32              port,
1448     OMX_HANDLETYPE       peer_component,
1449     OMX_U32              peer_port,
1450     OMX_TUNNELSETUPTYPE *p_tunnel_setup)
1451 {
1452     (void) cmp_handle;
1453     (void) port;
1454     (void) peer_component;
1455     (void) peer_port;
1456     (void) p_tunnel_setup;
1457 
1458     OMX_SWVDEC_LOG_API("");
1459 
1460     OMX_SWVDEC_LOG_ERROR("not implemented");
1461 
1462     return OMX_ErrorNotImplemented;
1463 }
1464 
1465 /**
1466  * @brief Use buffer.
1467  *
1468  * @param[in]     cmp_handle:    Component handle.
1469  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
1470  *                               structure.
1471  * @param[in]     port:          Port index.
1472  * @param[in]     p_app_data:    Pointer to IL client app data.
1473  * @param[in]     bytes:         Size of buffer to be allocated in bytes.
1474  * @param[in]     p_buffer:      Pointer to buffer to be used.
1475  *
1476  * @retval OMX_ERRORTYPE
1477  */
use_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,OMX_U32 bytes,OMX_U8 * p_buffer)1478 OMX_ERRORTYPE omx_swvdec::use_buffer(OMX_HANDLETYPE         cmp_handle,
1479                                      OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
1480                                      OMX_U32                port,
1481                                      OMX_PTR                p_app_data,
1482                                      OMX_U32                bytes,
1483                                      OMX_U8                *p_buffer)
1484 {
1485     OMX_ERRORTYPE retval = OMX_ErrorNone;
1486 
1487     if (m_state == OMX_StateInvalid)
1488     {
1489         OMX_SWVDEC_LOG_ERROR("in invalid state");
1490         retval = OMX_ErrorInvalidState;
1491     }
1492     else if (cmp_handle == NULL)
1493     {
1494         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1495         retval = OMX_ErrorInvalidComponent;
1496     }
1497     else if (pp_buffer_hdr == NULL)
1498     {
1499         OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
1500         retval = OMX_ErrorBadParameter;
1501     }
1502     else
1503     {
1504         OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer);
1505 
1506         if (port == OMX_CORE_PORT_INDEX_OP)
1507         {
1508             retval = buffer_use_op(pp_buffer_hdr, p_app_data, bytes, p_buffer);
1509 
1510             if (retval == OMX_ErrorNone)
1511             {
1512                 SWVDEC_STATUS retval_swvdec;
1513 
1514                 if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
1515                     (m_port_ip.populated == OMX_TRUE) &&
1516                     (m_port_op.populated == OMX_TRUE))
1517                 {
1518                     // start SwVdec
1519                     if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1520                         SWVDEC_STATUS_SUCCESS)
1521                     {
1522                         OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1523                         retval = retval_swvdec2omx(retval_swvdec);
1524                         goto use_buffer_exit;
1525                     }
1526 
1527                     m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
1528 
1529                     async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1530                                      OMX_CommandStateSet,
1531                                      OMX_StateIdle);
1532                 }
1533 
1534                 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
1535                     (m_port_op.populated == OMX_TRUE))
1536                 {
1537                     if (m_port_reconfig_inprogress)
1538                     {
1539                         // start SwVdec
1540                         if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1541                             SWVDEC_STATUS_SUCCESS)
1542                         {
1543                             OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1544                             retval = retval_swvdec2omx(retval_swvdec);
1545                         }
1546                     }
1547 
1548                     m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
1549 
1550                     async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1551                                      OMX_CommandPortEnable,
1552                                      OMX_CORE_PORT_INDEX_OP);
1553                 }
1554             }
1555         }
1556         else
1557         {
1558             OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
1559             retval = OMX_ErrorBadPortIndex;
1560         }
1561     }
1562 
1563 use_buffer_exit:
1564     return retval;
1565 }
1566 
1567 /**
1568  * @brief Allocate new buffer & associated header.
1569  *
1570  * @param[in]     cmp_handle:    Component handle.
1571  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
1572  *                               structure.
1573  * @param[in]     port:          Port index.
1574  * @param[in]     p_app_data:    Pointer to IL client app data.
1575  * @param[in]     bytes:         Size of buffer to be allocated in bytes.
1576  *
1577  * @retval OMX_ERRORTYPE
1578  */
allocate_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,OMX_U32 bytes)1579 OMX_ERRORTYPE omx_swvdec::allocate_buffer(OMX_HANDLETYPE         cmp_handle,
1580                                           OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
1581                                           OMX_U32                port,
1582                                           OMX_PTR                p_app_data,
1583                                           OMX_U32                bytes)
1584 {
1585     OMX_ERRORTYPE retval = OMX_ErrorNone;
1586 
1587     if (m_state == OMX_StateInvalid)
1588     {
1589         OMX_SWVDEC_LOG_ERROR("in invalid state");
1590         retval = OMX_ErrorInvalidState;
1591     }
1592     else if (cmp_handle == NULL)
1593     {
1594         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1595         retval = OMX_ErrorInvalidComponent;
1596     }
1597     else if (pp_buffer_hdr == NULL)
1598     {
1599         OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
1600         retval = OMX_ErrorBadParameter;
1601     }
1602     else
1603     {
1604         OMX_SWVDEC_LOG_API("port index %d, %d bytes", port, bytes);
1605 
1606         if (port == OMX_CORE_PORT_INDEX_IP)
1607         {
1608             retval = buffer_allocate_ip(pp_buffer_hdr,
1609                                         p_app_data,
1610                                         bytes);
1611         }
1612         else if (port == OMX_CORE_PORT_INDEX_OP)
1613         {
1614             if (m_meta_buffer_mode == true)
1615             {
1616                 OMX_SWVDEC_LOG_ERROR("'meta buffer mode' enabled");
1617                 retval = OMX_ErrorBadParameter;
1618             }
1619             else if (m_android_native_buffers == true)
1620             {
1621                 OMX_SWVDEC_LOG_ERROR("'android native buffers' enabled");
1622                 retval = OMX_ErrorBadParameter;
1623             }
1624             else
1625             {
1626                 retval = buffer_allocate_op(pp_buffer_hdr,
1627                                             p_app_data,
1628                                             bytes);
1629             }
1630         }
1631         else
1632         {
1633             OMX_SWVDEC_LOG_ERROR("port index %d invalid", port);
1634             retval = OMX_ErrorBadPortIndex;
1635         }
1636 
1637         if (retval == OMX_ErrorNone)
1638         {
1639             SWVDEC_STATUS retval_swvdec;
1640 
1641             if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
1642                 (m_port_ip.populated == OMX_TRUE) &&
1643                 (m_port_op.populated == OMX_TRUE))
1644             {
1645                 // start SwVdec
1646                 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1647                     SWVDEC_STATUS_SUCCESS)
1648                 {
1649                     OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1650                     retval = retval_swvdec2omx(retval_swvdec);
1651                     goto allocate_buffer_exit;
1652                 }
1653 
1654                 m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
1655 
1656                 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1657                                  OMX_CommandStateSet,
1658                                  OMX_StateIdle);
1659             }
1660 
1661             if ((m_status_flags & (1 << PENDING_PORT_ENABLE_IP)) &&
1662                 (m_port_ip.populated == OMX_TRUE))
1663             {
1664                 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_IP);
1665 
1666                 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1667                                  OMX_CommandPortEnable,
1668                                  OMX_CORE_PORT_INDEX_IP);
1669             }
1670 
1671             if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
1672                 (m_port_op.populated == OMX_TRUE))
1673             {
1674                 if (m_port_reconfig_inprogress)
1675                 {
1676                     // start SwVdec
1677                     if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
1678                         SWVDEC_STATUS_SUCCESS)
1679                     {
1680                         OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
1681                         retval = retval_swvdec2omx(retval_swvdec);
1682                     }
1683                 }
1684 
1685                 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
1686 
1687                 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1688                                  OMX_CommandPortEnable,
1689                                  OMX_CORE_PORT_INDEX_OP);
1690             }
1691         }
1692     }
1693 
1694 allocate_buffer_exit:
1695     return retval;
1696 }
1697 
1698 /**
1699  * @brief Release buffer & associated header.
1700  *
1701  * @param[in] cmp_handle:   Component handle.
1702  * @param[in] port:         Port index.
1703  * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1704  *
1705  * @retval OMX_ERRORTYPE
1706  */
free_buffer(OMX_HANDLETYPE cmp_handle,OMX_U32 port,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1707 OMX_ERRORTYPE omx_swvdec::free_buffer(OMX_HANDLETYPE        cmp_handle,
1708                                       OMX_U32               port,
1709                                       OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1710 {
1711     OMX_ERRORTYPE retval = OMX_ErrorNone;
1712 
1713     if (cmp_handle == NULL)
1714     {
1715         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1716         retval = OMX_ErrorInvalidComponent;
1717     }
1718     else if (p_buffer_hdr == NULL)
1719     {
1720         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1721         retval = OMX_ErrorBadParameter;
1722     }
1723     else if ((port != OMX_CORE_PORT_INDEX_IP) &&
1724              (port != OMX_CORE_PORT_INDEX_OP))
1725     {
1726         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
1727         retval = OMX_ErrorBadPortIndex;
1728     }
1729     else if (m_state != OMX_StateIdle)
1730     {
1731         if (m_state != OMX_StateExecuting)
1732         {
1733             OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
1734                                  OMX_STATETYPE_STRING(m_state));
1735             retval = OMX_ErrorIncorrectStateOperation;
1736         }
1737         else
1738         {
1739             if (((port == OMX_CORE_PORT_INDEX_IP) && m_port_ip.enabled) ||
1740                 ((port == OMX_CORE_PORT_INDEX_OP) && m_port_op.enabled))
1741             {
1742                 OMX_SWVDEC_LOG_ERROR("port index %d not disabled", port);
1743                 retval = OMX_ErrorBadPortIndex;
1744             }
1745         }
1746     }
1747 
1748     if (retval == OMX_ErrorNone)
1749     {
1750         OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer_hdr);
1751 
1752         if (port == OMX_CORE_PORT_INDEX_IP)
1753         {
1754             retval = buffer_deallocate_ip(p_buffer_hdr);
1755         }
1756         else
1757         {
1758             retval = buffer_deallocate_op(p_buffer_hdr);
1759         }
1760     }
1761 
1762     if ((retval == OMX_ErrorNone) &&
1763         (m_status_flags & (1 << PENDING_STATE_IDLE_TO_LOADED)))
1764     {
1765         if ((m_port_ip.unpopulated == OMX_TRUE) &&
1766             (m_port_op.unpopulated == OMX_TRUE))
1767         {
1768             SWVDEC_STATUS retval_swvdec;
1769 
1770             // stop SwVdec
1771             if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
1772                 SWVDEC_STATUS_SUCCESS)
1773             {
1774                 m_status_flags &= ~(1 << PENDING_STATE_IDLE_TO_LOADED);
1775 
1776                 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1777                                  OMX_CommandStateSet,
1778                                  OMX_StateLoaded);
1779             }
1780             else
1781             {
1782                 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
1783                 retval = retval_swvdec2omx(retval_swvdec);
1784             }
1785         }
1786     }
1787 
1788     if ((retval == OMX_ErrorNone) &&
1789         (m_status_flags & (1 << PENDING_PORT_DISABLE_IP)) &&
1790         m_port_ip.unpopulated)
1791     {
1792         m_status_flags &= ~(1 << PENDING_PORT_DISABLE_IP);
1793 
1794         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1795                          OMX_CommandPortDisable,
1796                          OMX_CORE_PORT_INDEX_IP);
1797     }
1798 
1799     if ((retval == OMX_ErrorNone) &&
1800         (m_status_flags & (1 << PENDING_PORT_DISABLE_OP)) &&
1801         m_port_op.unpopulated)
1802     {
1803         if (m_port_reconfig_inprogress)
1804         {
1805             SWVDEC_STATUS retval_swvdec;
1806 
1807             if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) !=
1808                 SWVDEC_STATUS_SUCCESS)
1809             {
1810                 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
1811                 retval = retval_swvdec2omx(retval_swvdec);
1812             }
1813         }
1814 
1815         m_status_flags &= ~(1 << PENDING_PORT_DISABLE_OP);
1816 
1817         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
1818                          OMX_CommandPortDisable,
1819                          OMX_CORE_PORT_INDEX_OP);
1820     }
1821 
1822     return retval;
1823 }
1824 
1825 /**
1826  * @brief Send a buffer to component's input port to be emptied.
1827  *
1828  * @param[in] cmp_handle:   Component handle.
1829  * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1830  *
1831  * @retval OMX_ERRORTYPE
1832  */
empty_this_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1833 OMX_ERRORTYPE omx_swvdec::empty_this_buffer(OMX_HANDLETYPE        cmp_handle,
1834                                             OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1835 {
1836     OMX_ERRORTYPE retval = OMX_ErrorNone;
1837 
1838     unsigned int ii;
1839 
1840     if (m_state == OMX_StateInvalid)
1841     {
1842         OMX_SWVDEC_LOG_ERROR("in invalid state");
1843         retval = OMX_ErrorInvalidState;
1844     }
1845     else if (cmp_handle == NULL)
1846     {
1847         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1848         retval = OMX_ErrorInvalidComponent;
1849     }
1850     else if (p_buffer_hdr == NULL)
1851     {
1852         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1853         retval = OMX_ErrorBadParameter;
1854     }
1855     else if (p_buffer_hdr->pBuffer == NULL)
1856     {
1857         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
1858         retval = OMX_ErrorBadParameter;
1859     }
1860     else if (p_buffer_hdr->pInputPortPrivate == NULL)
1861     {
1862         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pInputPortPrivate = NULL");
1863         retval = OMX_ErrorBadParameter;
1864     }
1865     else if (m_port_ip.enabled == OMX_FALSE)
1866     {
1867         OMX_SWVDEC_LOG_ERROR("ip port disabled");
1868         retval = OMX_ErrorIncorrectStateOperation;
1869     }
1870     else if (p_buffer_hdr->nInputPortIndex != OMX_CORE_PORT_INDEX_IP)
1871     {
1872         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1873                              p_buffer_hdr->nInputPortIndex);
1874         retval = OMX_ErrorBadPortIndex;
1875     }
1876 
1877     if (retval != OMX_ErrorNone)
1878     {
1879         goto empty_this_buffer_exit;
1880     }
1881 
1882     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
1883     {
1884         if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
1885         {
1886             OMX_SWVDEC_LOG_LOW("ip buffer %p has index %d",
1887                                p_buffer_hdr->pBuffer,
1888                                ii);
1889             break;
1890         }
1891     }
1892 
1893     if (ii == m_port_ip.def.nBufferCountActual)
1894     {
1895         OMX_SWVDEC_LOG_ERROR("ip buffer %p not found",
1896                              p_buffer_hdr->pBuffer);
1897         retval = OMX_ErrorBadParameter;
1898         goto empty_this_buffer_exit;
1899     }
1900 
1901     if (m_sync_frame_decoding_mode &&
1902         ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
1903     {
1904         p_buffer_hdr->nFlags |= OMX_BUFFERFLAG_EOS;
1905     }
1906 
1907     OMX_SWVDEC_LOG_API("%p: buffer %p, flags 0x%08x, filled length %d, "
1908                        "timestamp %lld",
1909                        p_buffer_hdr,
1910                        p_buffer_hdr->pBuffer,
1911                        p_buffer_hdr->nFlags,
1912                        p_buffer_hdr->nFilledLen,
1913                        p_buffer_hdr->nTimeStamp);
1914 
1915     async_post_event(OMX_SWVDEC_EVENT_ETB,
1916                      (unsigned long) p_buffer_hdr,
1917                      (unsigned long) ii);
1918 
1919 empty_this_buffer_exit:
1920     return retval;
1921 }
1922 
1923 /**
1924  * @brief Send a buffer to component's output port to be filled.
1925  *
1926  * @param[in] cmp_handle:   Component handle.
1927  * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
1928  *
1929  * @retval OMX_ERRORTYPE
1930  */
fill_this_buffer(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE * p_buffer_hdr)1931 OMX_ERRORTYPE omx_swvdec::fill_this_buffer(OMX_HANDLETYPE        cmp_handle,
1932                                            OMX_BUFFERHEADERTYPE *p_buffer_hdr)
1933 {
1934     OMX_ERRORTYPE retval = OMX_ErrorNone;
1935 
1936     unsigned int ii;
1937 
1938     SWVDEC_BUFFER *p_buffer_swvdec;
1939 
1940     if (m_state == OMX_StateInvalid)
1941     {
1942         OMX_SWVDEC_LOG_ERROR("in invalid state");
1943         retval = OMX_ErrorInvalidState;
1944     }
1945     else if (cmp_handle == NULL)
1946     {
1947         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
1948         retval = OMX_ErrorInvalidComponent;
1949     }
1950     else if (p_buffer_hdr == NULL)
1951     {
1952         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
1953         retval = OMX_ErrorBadParameter;
1954     }
1955     else if (p_buffer_hdr->pBuffer == NULL)
1956     {
1957         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
1958         retval = OMX_ErrorBadParameter;
1959     }
1960     else if (p_buffer_hdr->pOutputPortPrivate == NULL)
1961     {
1962         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pOutputPortPrivate = NULL");
1963         retval = OMX_ErrorBadParameter;
1964     }
1965     else if (m_port_op.enabled == OMX_FALSE)
1966     {
1967         OMX_SWVDEC_LOG_ERROR("op port disabled");
1968         retval = OMX_ErrorIncorrectStateOperation;
1969     }
1970     else if (p_buffer_hdr->nOutputPortIndex != OMX_CORE_PORT_INDEX_OP)
1971     {
1972         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
1973                              p_buffer_hdr->nOutputPortIndex);
1974         retval = OMX_ErrorBadPortIndex;
1975     }
1976 
1977     if (retval != OMX_ErrorNone)
1978     {
1979         goto fill_this_buffer_exit;
1980     }
1981 
1982     OMX_SWVDEC_LOG_API("%p", p_buffer_hdr);
1983 
1984     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
1985     {
1986         if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
1987         {
1988             OMX_SWVDEC_LOG_LOW("op buffer %p has index %d",
1989                                p_buffer_hdr->pBuffer,
1990                                ii);
1991             break;
1992         }
1993     }
1994 
1995     if (ii == m_port_op.def.nBufferCountActual)
1996     {
1997         OMX_SWVDEC_LOG_ERROR("op buffer %p not found",
1998                              p_buffer_hdr->pBuffer);
1999         retval = OMX_ErrorBadParameter;
2000         goto fill_this_buffer_exit;
2001     }
2002 
2003     p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec;
2004 
2005     if (m_meta_buffer_mode)
2006     {
2007         struct VideoDecoderOutputMetaData *p_meta_data;
2008 
2009         private_handle_t *p_private_handle;
2010 
2011         struct vdec_bufferpayload *p_buffer_payload;
2012 
2013         p_meta_data =
2014             (struct VideoDecoderOutputMetaData *) p_buffer_hdr->pBuffer;
2015 
2016         p_private_handle = (private_handle_t *) (p_meta_data->pHandle);
2017 
2018         p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
2019 
2020         if (p_private_handle == NULL)
2021         {
2022             OMX_SWVDEC_LOG_ERROR(
2023                 "p_buffer_hdr->pBuffer->pHandle = NULL");
2024 
2025             retval = OMX_ErrorBadParameter;
2026             goto fill_this_buffer_exit;
2027         }
2028 
2029         pthread_mutex_lock(&m_meta_buffer_array_mutex);
2030 
2031         if (m_meta_buffer_array[ii].ref_count == 0)
2032         {
2033             unsigned char *bufferaddr;
2034 
2035             bufferaddr = (unsigned char *) mmap(NULL,
2036                                                 m_port_op.def.nBufferSize,
2037                                                 PROT_READ | PROT_WRITE,
2038                                                 MAP_SHARED,
2039                                                 p_private_handle->fd,
2040                                                 0);
2041 
2042             if (bufferaddr == MAP_FAILED)
2043             {
2044                 OMX_SWVDEC_LOG_ERROR("mmap() failed for "
2045                                      "fd %d of size %d",
2046                                      p_private_handle->fd,
2047                                      m_port_op.def.nBufferSize);
2048 
2049                 retval = OMX_ErrorInsufficientResources;
2050                 goto fill_this_buffer_exit;
2051             }
2052 
2053             p_buffer_payload->bufferaddr  = bufferaddr;
2054             p_buffer_payload->pmem_fd     = p_private_handle->fd;
2055             p_buffer_payload->buffer_len  = m_port_op.def.nBufferSize;
2056             p_buffer_payload->mmaped_size = m_port_op.def.nBufferSize;
2057 
2058             p_buffer_swvdec->p_buffer      = bufferaddr;
2059             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
2060             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
2061         }
2062 
2063         pthread_mutex_unlock(&m_meta_buffer_array_mutex);
2064 
2065         meta_buffer_ref_add(ii,
2066                             p_buffer_payload->pmem_fd,
2067                             p_buffer_payload->offset);
2068     }
2069 
2070     OMX_SWVDEC_LOG_LOW("%p: buffer %p",
2071                        p_buffer_hdr,
2072                        p_buffer_swvdec->p_buffer);
2073 
2074     async_post_event(OMX_SWVDEC_EVENT_FTB,
2075                      (unsigned long) p_buffer_hdr,
2076                      (unsigned long) ii);
2077 
2078 fill_this_buffer_exit:
2079     return retval;
2080 }
2081 
2082 /**
2083  * @brief Set component's callback structure.
2084  *
2085  * @param[in] cmp_handle:  Component handle.
2086  * @param[in] p_callbacks: Pointer to callback structure.
2087  * @param[in] p_app_data:  Pointer to IL client app data.
2088  *
2089  * @retval OMX_ERRORTYPE
2090  */
set_callbacks(OMX_HANDLETYPE cmp_handle,OMX_CALLBACKTYPE * p_callbacks,OMX_PTR p_app_data)2091 OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE    cmp_handle,
2092                                         OMX_CALLBACKTYPE *p_callbacks,
2093                                         OMX_PTR           p_app_data)
2094 {
2095     OMX_ERRORTYPE retval = OMX_ErrorNone;
2096 
2097     OMX_SWVDEC_LOG_API("");
2098 
2099     if (m_state == OMX_StateInvalid)
2100     {
2101         OMX_SWVDEC_LOG_ERROR("in invalid state");
2102         retval = OMX_ErrorInvalidState;
2103     }
2104     else if (cmp_handle == NULL)
2105     {
2106         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2107         retval = OMX_ErrorInvalidComponent;
2108     }
2109     else if (p_callbacks->EventHandler == NULL)
2110     {
2111         OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL");
2112         retval = OMX_ErrorBadParameter;
2113     }
2114     else if (p_callbacks->EmptyBufferDone == NULL)
2115     {
2116         OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL");
2117         retval = OMX_ErrorBadParameter;
2118     }
2119     else if (p_callbacks->FillBufferDone == NULL)
2120     {
2121         OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL");
2122         retval = OMX_ErrorBadParameter;
2123     }
2124     else
2125     {
2126         m_callback = *p_callbacks;
2127         m_app_data = p_app_data;
2128     }
2129 
2130     return retval;
2131 }
2132 
2133 /**
2134  * @brief Use EGL image.
2135  *
2136  * @retval OMX_ErrorNotImplemented
2137  */
use_EGL_image(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,void * egl_image)2138 OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE         cmp_handle,
2139                                         OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
2140                                         OMX_U32                port,
2141                                         OMX_PTR                p_app_data,
2142                                         void                  *egl_image)
2143 {
2144     (void) cmp_handle;
2145     (void) pp_buffer_hdr;
2146     (void) port;
2147     (void) p_app_data;
2148     (void) egl_image;
2149 
2150     OMX_SWVDEC_LOG_API("");
2151 
2152     OMX_SWVDEC_LOG_ERROR("not implemented");
2153 
2154     return OMX_ErrorNotImplemented;
2155 }
2156 
2157 /**
2158  * @brief Enumerate component role.
2159  *
2160  * @param[in]     cmp_handle: Component handle.
2161  * @param[in,out] p_role:     Pointer to component role string.
2162  * @param[in]     index:      Role index being queried.
2163  *
2164  * @retval OMX_ERRORTYPE
2165  */
component_role_enum(OMX_HANDLETYPE cmp_handle,OMX_U8 * p_role,OMX_U32 index)2166 OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle,
2167                                               OMX_U8        *p_role,
2168                                               OMX_U32        index)
2169 {
2170     OMX_ERRORTYPE retval = OMX_ErrorNone;
2171 
2172     if (m_state == OMX_StateInvalid)
2173     {
2174         OMX_SWVDEC_LOG_ERROR("in invalid state");
2175         retval = OMX_ErrorInvalidState;
2176     }
2177     else if (cmp_handle == NULL)
2178     {
2179         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2180         retval = OMX_ErrorInvalidComponent;
2181     }
2182     else if (index > 0)
2183     {
2184         OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index);
2185         retval = OMX_ErrorNoMore;
2186     }
2187     else
2188     {
2189         memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE);
2190         OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role);
2191     }
2192 
2193     return retval;
2194 }
2195 
2196 /**
2197  * -------------------------
2198  * SwVdec callback functions
2199  * -------------------------
2200  */
2201 
2202 /**
2203  * @brief SwVdec empty buffer done callback.
2204  *
2205  * @param[in] swvdec_handle:   SwVdec handle.
2206  * @param[in] p_buffer_ip:     Pointer to input buffer structure.
2207  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2208  *
2209  * @retval SWVDEC_STATUS_SUCCESS
2210  * @retval SWVDEC_STATUS_NULL_POINTER
2211  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2212  */
swvdec_empty_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_ip,void * p_client_handle)2213 SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback(
2214     SWVDEC_HANDLE  swvdec_handle,
2215     SWVDEC_BUFFER *p_buffer_ip,
2216     void          *p_client_handle)
2217 {
2218     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2219 
2220     if (p_buffer_ip == NULL)
2221     {
2222         OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL");
2223         retval = SWVDEC_STATUS_NULL_POINTER;
2224     }
2225     else if (p_client_handle == NULL)
2226     {
2227         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2228         retval = SWVDEC_STATUS_NULL_POINTER;
2229     }
2230     else
2231     {
2232         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2233 
2234         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2235         {
2236             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2237             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2238         }
2239         else
2240         {
2241             p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip);
2242         }
2243     }
2244 
2245     return retval;
2246 }
2247 
2248 /**
2249  * @brief SwVdec fill buffer done callback.
2250  *
2251  * @param[in] swvdec_handle:   SwVdec handle.
2252  * @param[in] p_buffer_op:     Pointer to output buffer structure.
2253  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2254  *
2255  * @retval SWVDEC_STATUS_SUCCESS
2256  * @retval SWVDEC_STATUS_NULL_POINTER
2257  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2258  */
swvdec_fill_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_op,void * p_client_handle)2259 SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback(
2260     SWVDEC_HANDLE  swvdec_handle,
2261     SWVDEC_BUFFER *p_buffer_op,
2262     void          *p_client_handle)
2263 {
2264     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2265 
2266     if (p_buffer_op == NULL)
2267     {
2268         OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL");
2269         retval = SWVDEC_STATUS_NULL_POINTER;
2270     }
2271     else if (p_client_handle == NULL)
2272     {
2273         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2274         retval = SWVDEC_STATUS_NULL_POINTER;
2275     }
2276     else
2277     {
2278         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2279 
2280         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2281         {
2282             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2283             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2284         }
2285         else
2286         {
2287             p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op);
2288         }
2289     }
2290 
2291     return retval;
2292 }
2293 
2294 /**
2295  * @brief SwVdec event handler callback.
2296  *
2297  * @param[in] swvdec_handle:   SwVdec handle.
2298  * @param[in] event:           Event.
2299  * @param[in] p_data:          Pointer to event-specific data.
2300  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2301  *
2302  * @retval SWVDEC_STATUS_SUCCESS
2303  * @retval SWVDEC_STATUS_NULL_POINTER
2304  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2305  */
swvdec_event_handler_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_EVENT event,void * p_data,void * p_client_handle)2306 SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback(
2307     SWVDEC_HANDLE swvdec_handle,
2308     SWVDEC_EVENT  event,
2309     void         *p_data,
2310     void         *p_client_handle)
2311 {
2312     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2313 
2314     if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL))
2315     {
2316         OMX_SWVDEC_LOG_ERROR("p_data = NULL");
2317         retval = SWVDEC_STATUS_NULL_POINTER;
2318     }
2319     else if (p_client_handle == NULL)
2320     {
2321         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2322         retval = SWVDEC_STATUS_NULL_POINTER;
2323     }
2324     else
2325     {
2326         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2327 
2328         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2329         {
2330             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2331             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2332         }
2333         else
2334         {
2335             p_omx_swvdec->swvdec_event_handler(event, p_data);
2336         }
2337     }
2338 
2339     return retval;
2340 }
2341 
2342 /**
2343  * -----------------
2344  * PRIVATE FUNCTIONS
2345  * -----------------
2346  */
2347 
2348 /**
2349  * @brief Set frame dimensions for OMX component & SwVdec core.
2350  *
2351  * @param[in] width:  Frame width.
2352  * @param[in] height: Frame height.
2353  *
2354  * @retval OMX_ERRORTYPE
2355  */
set_frame_dimensions(unsigned int width,unsigned int height)2356 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width,
2357                                                unsigned int height)
2358 {
2359     OMX_ERRORTYPE retval;
2360 
2361     m_frame_dimensions.width  = width;
2362     m_frame_dimensions.height = height;
2363 
2364     OMX_SWVDEC_LOG_HIGH("%d x %d",
2365                         m_frame_dimensions.width,
2366                         m_frame_dimensions.height);
2367 
2368     retval = set_frame_dimensions_swvdec();
2369 
2370     return retval;
2371 }
2372 
2373 /**
2374  * @brief Set frame attributes for OMX component & SwVdec core, based on
2375  *        frame dimensions & alignment factors.
2376  *
2377  * @param[in] alignment_stride:       Frame stride alignment factor.
2378  * @param[in] alignment_scanlines_y:  Frame   luma scanlines alignment factor.
2379  * @param[in] alignment_scanlines_uv: Frame chroma scanlines alignment factor.
2380  * @param[in] alignment_size:         Frame size alignment factor.
2381  *
2382  * @retval OMX_ERRORTYPE
2383  */
set_frame_attributes(unsigned int alignment_stride,unsigned int alignment_scanlines_y,unsigned int alignment_scanlines_uv,unsigned int alignment_size)2384 OMX_ERRORTYPE omx_swvdec::set_frame_attributes(
2385     unsigned int alignment_stride,
2386     unsigned int alignment_scanlines_y,
2387     unsigned int alignment_scanlines_uv,
2388     unsigned int alignment_size)
2389 {
2390     OMX_ERRORTYPE retval;
2391 
2392     unsigned int width  = m_frame_dimensions.width;
2393     unsigned int height = m_frame_dimensions.height;
2394 
2395     unsigned int scanlines_uv;
2396 
2397     unsigned int plane_size_y;
2398     unsigned int plane_size_uv;
2399 
2400     m_frame_attributes.stride    = ALIGN(width,  alignment_stride);
2401     m_frame_attributes.scanlines = ALIGN(height, alignment_scanlines_y);
2402 
2403     scanlines_uv = ALIGN(height / 2, alignment_scanlines_uv);
2404 
2405     plane_size_y  = m_frame_attributes.stride * m_frame_attributes.scanlines;
2406     plane_size_uv = m_frame_attributes.stride * scanlines_uv;
2407 
2408     m_frame_attributes.size =
2409         ALIGN(plane_size_y + plane_size_uv, alignment_size);
2410 
2411     OMX_SWVDEC_LOG_HIGH("stride %d, scanlines %d, size %d",
2412                         m_frame_attributes.stride,
2413                         m_frame_attributes.scanlines,
2414                         m_frame_attributes.size);
2415 
2416     retval = set_frame_attributes_swvdec();
2417 
2418     return retval;
2419 }
2420 
2421 /**
2422  * @brief Get video port format for input or output port.
2423  *
2424  * @param[in,out] p_port_format: Pointer to video port format type.
2425  *
2426  * @retval OMX_ERRORTYPE
2427  */
get_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2428 OMX_ERRORTYPE omx_swvdec::get_video_port_format(
2429     OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2430 {
2431     OMX_ERRORTYPE retval = OMX_ErrorNone;
2432 
2433     if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2434     {
2435         if (p_port_format->nIndex == 0)
2436         {
2437             p_port_format->eColorFormat       = OMX_COLOR_FormatUnused;
2438             p_port_format->eCompressionFormat = m_omx_video_codingtype;
2439 
2440             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2441                                 "compression format 0x%08x",
2442                                 p_port_format->eColorFormat,
2443                                 p_port_format->eCompressionFormat);
2444         }
2445         else
2446         {
2447             OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; "
2448                                 "no more compression formats",
2449                                 p_port_format->nIndex);
2450             retval = OMX_ErrorNoMore;
2451         }
2452     }
2453     else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2454     {
2455         if (p_port_format->nIndex == 0)
2456         {
2457             p_port_format->eColorFormat =
2458                 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
2459             p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2460 
2461             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2462                                 "compression format 0x%08x",
2463                                 p_port_format->eColorFormat,
2464                                 p_port_format->eCompressionFormat);
2465         }
2466         else if (p_port_format->nIndex == 1)
2467         {
2468             p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2469             p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2470 
2471             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2472                                 "compression format 0x%08x",
2473                                 p_port_format->eColorFormat,
2474                                 p_port_format->eCompressionFormat);
2475         }
2476         // Here, add additional supported color formats as necessary.
2477         else
2478         {
2479             OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats",
2480                                 p_port_format->nIndex);
2481             retval = OMX_ErrorNoMore;
2482         }
2483     }
2484     else
2485     {
2486         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2487                              p_port_format->nPortIndex);
2488         retval = OMX_ErrorBadPortIndex;
2489     }
2490 
2491     return retval;
2492 }
2493 
2494 /**
2495  * @brief Set video port format for input or output port.
2496  *
2497  * @param[in] p_port_format: Pointer to video port format type.
2498  *
2499  * @retval OMX_ERRORTYPE
2500  */
set_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2501 OMX_ERRORTYPE omx_swvdec::set_video_port_format(
2502     OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2503 {
2504     OMX_ERRORTYPE retval = OMX_ErrorNone;
2505 
2506     if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2507     {
2508         // do nothing
2509         OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; "
2510                             "doing nothing");
2511     }
2512     else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2513     {
2514         /**
2515          * If color format specified by IL client is different from default,
2516          * set alignment factors for new color format and call
2517          * set_frame_attributes().
2518          */
2519         switch (p_port_format->eColorFormat)
2520         {
2521 
2522         case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m:
2523         {
2524             // do nothing; this is the default color format
2525             OMX_SWVDEC_LOG_HIGH(
2526                 "'0x%08x': OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m",
2527                 p_port_format->eColorFormat);
2528             break;
2529         }
2530 
2531         case OMX_COLOR_FormatYUV420SemiPlanar:
2532         {
2533             OMX_SWVDEC_LOG_HIGH("'0x%08x': OMX_COLOR_FormatYUV420SemiPlanar",
2534                                 p_port_format->eColorFormat);
2535 
2536             retval = set_frame_attributes(16,    //       stride alignment
2537                                           1,     //  Y scanlines alignment
2538                                           1,     // UV scanlines alignment
2539                                           4096); //         size alignment
2540             break;
2541         }
2542 
2543         default:
2544         {
2545             OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid or unsupported",
2546                                  p_port_format->eColorFormat);
2547             retval = OMX_ErrorBadParameter;
2548             break;
2549         }
2550 
2551         }
2552     }
2553     else
2554     {
2555         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2556                              p_port_format->nPortIndex);
2557         retval = OMX_ErrorBadPortIndex;
2558     }
2559 
2560 set_video_port_format_exit:
2561     return retval;
2562 }
2563 
2564 /**
2565  * @brief Get port definition for input or output port.
2566  *
2567  * @param[in,out] p_port_def: Pointer to port definition type.
2568  *
2569  * @retval OMX_ERRORTYPE
2570  */
get_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2571 OMX_ERRORTYPE omx_swvdec::get_port_definition(
2572     OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2573 {
2574     OMX_ERRORTYPE retval = OMX_ErrorNone;
2575 
2576     p_port_def->eDomain = OMX_PortDomainVideo;
2577 
2578     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2579     {
2580         if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
2581             OMX_ErrorNone)
2582         {
2583             goto get_port_definition_exit;
2584         }
2585 
2586         p_port_def->eDir               = OMX_DirInput;
2587         p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual;
2588         p_port_def->nBufferCountMin    = m_port_ip.def.nBufferCountMin;
2589         p_port_def->nBufferSize        = m_port_ip.def.nBufferSize;
2590         p_port_def->bEnabled           = m_port_ip.enabled;
2591         p_port_def->bPopulated         = m_port_ip.populated;
2592 
2593         OMX_SWVDEC_LOG_HIGH("port index %d: "
2594                             "count actual %d, count min %d, size %d",
2595                             p_port_def->nPortIndex,
2596                             p_port_def->nBufferCountActual,
2597                             p_port_def->nBufferCountMin,
2598                             p_port_def->nBufferSize);
2599 
2600         // frame dimensions & attributes don't apply to input port
2601 
2602         p_port_def->format.video.eColorFormat       = OMX_COLOR_FormatUnused;
2603         p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype;
2604     }
2605     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2606     {
2607         unsigned int frame_width  = m_frame_dimensions.width;
2608         unsigned int frame_height = m_frame_dimensions.height;
2609 
2610         if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone)
2611         {
2612             goto get_port_definition_exit;
2613         }
2614 
2615         p_port_def->format.video.nFrameWidth  = m_frame_dimensions.width;
2616         p_port_def->format.video.nFrameHeight = m_frame_dimensions.height;
2617 
2618         // if frame dimensions have changed, update frame attributes
2619         if ((frame_width  != m_frame_dimensions.width) ||
2620             (frame_height != m_frame_dimensions.height))
2621         {
2622             if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
2623                                                DEFAULT_ALIGNMENT_SCANLINES_Y,
2624                                                DEFAULT_ALIGNMENT_SCANLINES_UV,
2625                                                DEFAULT_ALIGNMENT_SIZE)) !=
2626                 OMX_ErrorNone)
2627             {
2628                 goto get_port_definition_exit;
2629             }
2630         }
2631 
2632         if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone)
2633         {
2634             goto get_port_definition_exit;
2635         }
2636 
2637         p_port_def->format.video.nStride      = m_frame_attributes.stride;
2638         p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines;
2639 
2640         OMX_SWVDEC_LOG_HIGH("port index %d: "
2641                             "%d x %d, stride %d, sliceheight %d",
2642                             p_port_def->nPortIndex,
2643                             p_port_def->format.video.nFrameWidth,
2644                             p_port_def->format.video.nFrameHeight,
2645                             p_port_def->format.video.nStride,
2646                             p_port_def->format.video.nSliceHeight);
2647 
2648         /**
2649          * Query to SwVdec core for buffer requirements is not allowed in
2650          * executing state since it will overwrite the component's buffer
2651          * requirements updated via the most recent set_parameter().
2652          *
2653          * Buffer requirements communicated to component via set_parameter() are
2654          * not propagated to SwVdec core.
2655          *
2656          * The only execption is if port reconfiguration is in progress, in
2657          * which case the query to SwVdec core is required since buffer
2658          * requirements can change based on new dimensions.
2659          */
2660         if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress)
2661         {
2662             if ((retval =
2663                  get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
2664                 OMX_ErrorNone)
2665             {
2666                 goto get_port_definition_exit;
2667             }
2668         }
2669 
2670         p_port_def->eDir               = OMX_DirOutput;
2671         p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual;
2672         p_port_def->nBufferCountMin    = m_port_op.def.nBufferCountMin;
2673         p_port_def->nBufferSize        = m_port_op.def.nBufferSize;
2674         p_port_def->bEnabled           = m_port_op.enabled;
2675         p_port_def->bPopulated         = m_port_op.populated;
2676 
2677         OMX_SWVDEC_LOG_HIGH("port index %d: "
2678                             "count actual %d, count min %d, size %d",
2679                             p_port_def->nPortIndex,
2680                             p_port_def->nBufferCountActual,
2681                             p_port_def->nBufferCountMin,
2682                             p_port_def->nBufferSize);
2683 
2684         p_port_def->format.video.eColorFormat       = m_omx_color_formattype;
2685         p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
2686     }
2687     else
2688     {
2689         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
2690         retval = OMX_ErrorBadPortIndex;
2691     }
2692 
2693 get_port_definition_exit:
2694     return retval;
2695 }
2696 
2697 /**
2698  * @brief Set port definition for input or output port.
2699  *
2700  * @param[in] p_port_def: Pointer to port definition type.
2701  *
2702  * @retval OMX_ERRORTYPE
2703  */
set_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2704 OMX_ERRORTYPE omx_swvdec::set_port_definition(
2705     OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2706 {
2707     OMX_ERRORTYPE retval = OMX_ErrorNone;
2708 
2709     OMX_SWVDEC_LOG_HIGH("port index %d: "
2710                         "count actual %d, count min %d, size %d",
2711                         p_port_def->nPortIndex,
2712                         p_port_def->nBufferCountActual,
2713                         p_port_def->nBufferCountMin,
2714                         p_port_def->nBufferSize);
2715 
2716     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2717     {
2718         m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual;
2719         m_port_ip.def.nBufferCountMin    = p_port_def->nBufferCountMin;
2720         m_port_ip.def.nBufferSize        = p_port_def->nBufferSize;
2721     }
2722     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2723     {
2724         OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d",
2725                             p_port_def->nPortIndex,
2726                             p_port_def->format.video.nFrameWidth,
2727                             p_port_def->format.video.nFrameHeight);
2728 
2729         m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual;
2730         m_port_op.def.nBufferCountMin    = p_port_def->nBufferCountMin;
2731         m_port_op.def.nBufferSize        = p_port_def->nBufferSize;
2732 
2733         retval = set_frame_dimensions(p_port_def->format.video.nFrameWidth,
2734                                       p_port_def->format.video.nFrameHeight);
2735         if (retval != OMX_ErrorNone)
2736             goto set_port_definition_exit;
2737 
2738         m_frame_attributes.stride    = p_port_def->format.video.nStride;
2739         m_frame_attributes.scanlines = p_port_def->format.video.nSliceHeight;
2740         m_frame_attributes.size      = p_port_def->nBufferSize;
2741 
2742         retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
2743                                       DEFAULT_ALIGNMENT_SCANLINES_Y,
2744                                       DEFAULT_ALIGNMENT_SCANLINES_UV,
2745                                       DEFAULT_ALIGNMENT_SIZE);
2746     }
2747     else
2748     {
2749         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
2750         retval = OMX_ErrorBadPortIndex;
2751     }
2752 
2753 set_port_definition_exit:
2754     return retval;
2755 }
2756 
2757 /**
2758  * @brief Get supported profile & level.
2759  *
2760  * The supported profiles & levels are not queried from SwVdec core, but
2761  * hard-coded. This should ideally be replaced with a query to SwVdec core.
2762  *
2763  * @param[in,out] p_profilelevel: Pointer to video profile & level type.
2764  *
2765  * @retval OMX_ERRORTYPE
2766  */
get_supported_profilelevel(OMX_VIDEO_PARAM_PROFILELEVELTYPE * p_profilelevel)2767 OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel(
2768     OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel)
2769 {
2770     OMX_ERRORTYPE retval = OMX_ErrorNone;
2771 
2772     if (p_profilelevel == NULL)
2773     {
2774         OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL");
2775         retval = OMX_ErrorBadParameter;
2776         goto get_supported_profilelevel_exit;
2777     }
2778 
2779     if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP)
2780     {
2781         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2782                              p_profilelevel->nPortIndex);
2783         retval = OMX_ErrorBadPortIndex;
2784         goto get_supported_profilelevel_exit;
2785     }
2786 
2787     if (m_omx_video_codingtype == OMX_VIDEO_CodingH263)
2788     {
2789         if (p_profilelevel->nProfileIndex == 0)
2790         {
2791             p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
2792             p_profilelevel->eLevel   = OMX_VIDEO_H263Level70;
2793             OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70");
2794         }
2795         else
2796         {
2797             OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
2798                                 "no more profiles",
2799                                 p_profilelevel->nProfileIndex);
2800             retval = OMX_ErrorNoMore;
2801         }
2802     }
2803     else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) ||
2804              (m_omx_video_codingtype ==
2805               ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)))
2806     {
2807         if (p_profilelevel->nProfileIndex == 0)
2808         {
2809             p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2810             p_profilelevel->eLevel   = OMX_VIDEO_MPEG4Level5;
2811             OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 5");
2812         }
2813         else if (p_profilelevel->nProfileIndex == 1)
2814         {
2815             p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2816             p_profilelevel->eLevel   = OMX_VIDEO_MPEG4Level5;
2817             OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5");
2818         }
2819         else
2820         {
2821             OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
2822                                 "no more profiles",
2823                                 p_profilelevel->nProfileIndex);
2824             retval = OMX_ErrorNoMore;
2825         }
2826     }
2827     else
2828     {
2829         assert(0);
2830         retval = OMX_ErrorUndefined;
2831     }
2832 
2833 get_supported_profilelevel_exit:
2834     return retval;
2835 }
2836 
2837 /**
2838  * @brief Describe color format.
2839  *
2840  * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure.
2841  *
2842  * @retval OMX_ERRORTYPE
2843  */
describe_color_format(DescribeColorFormatParams * p_params)2844 OMX_ERRORTYPE omx_swvdec::describe_color_format(
2845     DescribeColorFormatParams *p_params)
2846 {
2847     OMX_ERRORTYPE retval = OMX_ErrorNone;
2848 
2849     if (p_params == NULL)
2850     {
2851         OMX_SWVDEC_LOG_ERROR("p_params = NULL");
2852         retval = OMX_ErrorBadParameter;
2853     }
2854     else
2855     {
2856         MediaImage *p_img = &p_params->sMediaImage;
2857 
2858         switch (p_params->eColorFormat)
2859         {
2860 
2861         case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
2862         {
2863             size_t stride, scanlines;
2864 
2865             p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2866             p_img->mNumPlanes = 3;
2867 
2868             p_img->mWidth  = p_params->nFrameWidth;
2869             p_img->mHeight = p_params->nFrameHeight;
2870 
2871             stride    = ALIGN(p_img->mWidth,  DEFAULT_ALIGNMENT_STRIDE);
2872             scanlines = ALIGN(p_img->mHeight, DEFAULT_ALIGNMENT_SCANLINES_Y);
2873 
2874             p_img->mBitDepth = 8;
2875 
2876             // plane 0 (Y)
2877             p_img->mPlane[MediaImage::Y].mOffset = 0;
2878             p_img->mPlane[MediaImage::Y].mColInc = 1;
2879             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2880             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
2881             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 1;
2882 
2883             // plane 1 (U)
2884             p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
2885             p_img->mPlane[MediaImage::Y].mColInc = 2;
2886             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2887             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2888             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 2;
2889 
2890             // plane 2 (V)
2891             p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
2892             p_img->mPlane[MediaImage::Y].mColInc = 2;
2893             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2894             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2895             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 2;
2896 
2897             break;
2898         }
2899 
2900         case OMX_COLOR_FormatYUV420SemiPlanar:
2901         {
2902             size_t stride, scanlines;
2903 
2904             p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2905             p_img->mNumPlanes = 3;
2906 
2907             p_img->mWidth  = p_params->nFrameWidth;
2908             p_img->mHeight = p_params->nFrameHeight;
2909 
2910             stride    = ALIGN(p_img->mWidth,  16);
2911             scanlines = ALIGN(p_img->mHeight,  1);
2912 
2913             p_img->mBitDepth = 8;
2914 
2915             // plane 0 (Y)
2916             p_img->mPlane[MediaImage::Y].mOffset = 0;
2917             p_img->mPlane[MediaImage::Y].mColInc = 1;
2918             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2919             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
2920             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 1;
2921 
2922             // plane 1 (U)
2923             p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
2924             p_img->mPlane[MediaImage::Y].mColInc = 2;
2925             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2926             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2927             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 2;
2928 
2929             // plane 2 (V)
2930             p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
2931             p_img->mPlane[MediaImage::Y].mColInc = 2;
2932             p_img->mPlane[MediaImage::Y].mRowInc = stride;
2933             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
2934             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 2;
2935 
2936             break;
2937         }
2938 
2939         default:
2940         {
2941             OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported",
2942                                  p_params->eColorFormat);
2943 
2944             p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
2945 
2946             retval = OMX_ErrorBadParameter;
2947             break;
2948         }
2949 
2950         } // switch (p_params->eColorFormat)
2951     }
2952 
2953     return retval;
2954 }
2955 
2956 /**
2957  * @brief Set QTI vendor-specific port definition for input or output port.
2958  *
2959  * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type.
2960  *
2961  * @retval OMX_ERRORTYPE
2962  */
set_port_definition_qcom(OMX_QCOM_PARAM_PORTDEFINITIONTYPE * p_port_def)2963 OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom(
2964     OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def)
2965 {
2966     OMX_ERRORTYPE retval = OMX_ErrorNone;
2967 
2968     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2969     {
2970         switch (p_port_def->nFramePackingFormat)
2971         {
2972 
2973         case OMX_QCOM_FramePacking_Arbitrary:
2974         {
2975             OMX_SWVDEC_LOG_ERROR("OMX_QCOM_FramePacking_Arbitrary unsupported");
2976             retval = OMX_ErrorUnsupportedSetting;
2977             break;
2978         }
2979 
2980         case OMX_QCOM_FramePacking_OnlyOneCompleteFrame:
2981         {
2982             OMX_SWVDEC_LOG_HIGH(
2983                 "OMX_QCOM_FramePacking_OnlyOneCompleteFrame");
2984             break;
2985         }
2986 
2987         default:
2988         {
2989             OMX_SWVDEC_LOG_ERROR(
2990                 "frame packing format '%d' unsupported");
2991             retval = OMX_ErrorUnsupportedSetting;
2992             break;
2993         }
2994 
2995         }
2996     }
2997     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2998     {
2999         OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d",
3000                             p_port_def->nMemRegion,
3001                             p_port_def->nCacheAttr);
3002     }
3003     else
3004     {
3005         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
3006                              p_port_def->nPortIndex);
3007         retval = OMX_ErrorBadPortIndex;
3008     }
3009 
3010     return retval;
3011 }
3012 
3013 /**
3014  * @brief Set SwVdec frame dimensions based on OMX component frame dimensions.
3015  *
3016  * @retval OMX_ERRORTYPE
3017  */
set_frame_dimensions_swvdec()3018 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec()
3019 {
3020     OMX_ERRORTYPE retval = OMX_ErrorNone;
3021 
3022     SWVDEC_PROPERTY property;
3023 
3024     SWVDEC_STATUS retval_swvdec;
3025 
3026     property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3027 
3028     property.info.frame_dimensions.width  = m_frame_dimensions.width;
3029     property.info.frame_dimensions.height = m_frame_dimensions.height;
3030 
3031     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3032         SWVDEC_STATUS_SUCCESS)
3033     {
3034         retval = retval_swvdec2omx(retval_swvdec);
3035     }
3036 
3037     return retval;
3038 }
3039 
3040 /**
3041  * @brief Set SwVdec frame attributes based on OMX component frame attributes.
3042  *
3043  * @retval OMX_ERRORTYPE
3044  */
set_frame_attributes_swvdec()3045 OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec()
3046 {
3047     OMX_ERRORTYPE retval = OMX_ErrorNone;
3048 
3049     SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes;
3050 
3051     SWVDEC_PROPERTY property;
3052 
3053     SWVDEC_STATUS retval_swvdec;
3054 
3055     p_frame_attributes = &property.info.frame_attributes;
3056 
3057     property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3058 
3059     p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12;
3060 
3061     p_frame_attributes->semiplanar.stride    = m_frame_attributes.stride;
3062     p_frame_attributes->semiplanar.offset_uv = (m_frame_attributes.stride *
3063                                                 m_frame_attributes.scanlines);
3064 
3065     p_frame_attributes->size = m_frame_attributes.size;
3066 
3067     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3068         SWVDEC_STATUS_SUCCESS)
3069     {
3070         retval = retval_swvdec2omx(retval_swvdec);
3071     }
3072 
3073     return retval;
3074 }
3075 
3076 /**
3077  * @brief Get SwVdec frame dimensions and set OMX component frame dimensions.
3078  *
3079  * @retval OMX_ERRORTYPE
3080  */
get_frame_dimensions_swvdec()3081 OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec()
3082 {
3083     OMX_ERRORTYPE retval = OMX_ErrorNone;
3084 
3085     SWVDEC_PROPERTY property;
3086 
3087     SWVDEC_STATUS retval_swvdec;
3088 
3089     property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3090 
3091     if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3092         SWVDEC_STATUS_SUCCESS)
3093     {
3094         retval = retval_swvdec2omx(retval_swvdec);
3095     }
3096     else
3097     {
3098         m_frame_dimensions.width  = property.info.frame_dimensions.width;
3099         m_frame_dimensions.height = property.info.frame_dimensions.height;
3100     }
3101 
3102     return retval;
3103 }
3104 
3105 /**
3106  * @brief Get SwVdec frame attributes and set OMX component frame attributes.
3107  *
3108  * @retval OMX_ERRORTYPE
3109  */
get_frame_attributes_swvdec()3110 OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec()
3111 {
3112     OMX_ERRORTYPE retval = OMX_ErrorNone;
3113 
3114     SWVDEC_PROPERTY property;
3115 
3116     SWVDEC_STATUS retval_swvdec;
3117 
3118     property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3119 
3120     if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3121         SWVDEC_STATUS_SUCCESS)
3122     {
3123         retval = retval_swvdec2omx(retval_swvdec);
3124     }
3125     else
3126     {
3127         m_frame_attributes.stride =
3128             property.info.frame_attributes.semiplanar.stride;
3129 
3130         m_frame_attributes.scanlines =
3131             (property.info.frame_attributes.semiplanar.offset_uv /
3132              property.info.frame_attributes.semiplanar.stride);
3133 
3134         m_frame_attributes.size = property.info.frame_attributes.size;
3135     }
3136 
3137     return retval;
3138 }
3139 
3140 /**
3141  * @brief Get SwVdec buffer requirements; set input or output port definitions.
3142  *
3143  * @param[in] port_index: Port index.
3144  *
3145  * @retval OMX_ERRORTYPE
3146  */
get_buffer_requirements_swvdec(unsigned int port_index)3147 OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec(
3148     unsigned int port_index)
3149 {
3150     OMX_ERRORTYPE retval = OMX_ErrorNone;
3151 
3152     SWVDEC_PROPERTY property;
3153 
3154     SWVDEC_STATUS retval_swvdec;
3155 
3156     SWVDEC_BUFFER_REQ *p_buffer_req;
3157 
3158     if (port_index == OMX_CORE_PORT_INDEX_IP)
3159     {
3160         property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP;
3161 
3162         p_buffer_req = &property.info.buffer_req_ip;
3163 
3164         if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3165             SWVDEC_STATUS_SUCCESS)
3166         {
3167             retval = retval_swvdec2omx(retval_swvdec);
3168             goto get_buffer_requirements_swvdec_exit;
3169         }
3170 
3171         m_port_ip.def.nBufferSize        = p_buffer_req->size;
3172         m_port_ip.def.nBufferCountMin    = p_buffer_req->mincount;
3173         m_port_ip.def.nBufferCountActual = MAX(p_buffer_req->mincount,
3174                                                OMX_SWVDEC_IP_BUFFER_COUNT);
3175         m_port_ip.def.nBufferAlignment   = p_buffer_req->alignment;
3176 
3177         OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned",
3178                             m_port_ip.def.nBufferSize,
3179                             m_port_ip.def.nBufferCountActual,
3180                             m_port_ip.def.nBufferAlignment);
3181     }
3182     else if (port_index == OMX_CORE_PORT_INDEX_OP)
3183     {
3184         property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP;
3185 
3186         p_buffer_req = &property.info.buffer_req_op;
3187 
3188         if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3189             SWVDEC_STATUS_SUCCESS)
3190         {
3191             retval = retval_swvdec2omx(retval_swvdec);
3192             goto get_buffer_requirements_swvdec_exit;
3193         }
3194 
3195         if (m_sync_frame_decoding_mode)
3196         {
3197             // only 1 output buffer for sync frame decoding mode
3198             p_buffer_req->mincount = 1;
3199         }
3200 
3201         m_port_op.def.nBufferSize        = p_buffer_req->size;
3202         m_port_op.def.nBufferCountMin    = p_buffer_req->mincount;
3203         m_port_op.def.nBufferCountActual = p_buffer_req->mincount;
3204         m_port_op.def.nBufferAlignment   = p_buffer_req->alignment;
3205 
3206         OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned",
3207                             m_port_op.def.nBufferSize,
3208                             m_port_op.def.nBufferCountActual,
3209                             m_port_op.def.nBufferAlignment);
3210     }
3211     else
3212     {
3213         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index);
3214         retval = OMX_ErrorBadPortIndex;
3215     }
3216 
3217 get_buffer_requirements_swvdec_exit:
3218     return retval;
3219 }
3220 
3221 /**
3222  * @brief Allocate input buffer, and input buffer info array if ncessary.
3223  *
3224  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3225  *                               structure.
3226  * @param[in]     p_app_data:    Pointer to IL client app data.
3227  * @param[in]     size:          Size of buffer to be allocated in bytes.
3228  *
3229  * @retval OMX_ERRORTYPE
3230  */
buffer_allocate_ip(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3231 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip(
3232     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3233     OMX_PTR                p_app_data,
3234     OMX_U32                size)
3235 {
3236     OMX_ERRORTYPE retval = OMX_ErrorNone;
3237 
3238     unsigned int ii;
3239 
3240     if (size != m_port_ip.def.nBufferSize)
3241     {
3242         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3243                              "configured size (%d bytes)",
3244                              size,
3245                              m_port_ip.def.nBufferSize);
3246         retval = OMX_ErrorBadParameter;
3247         goto buffer_allocate_ip_exit;
3248     }
3249 
3250     if (m_buffer_array_ip == NULL)
3251     {
3252         // input buffer info array not allocated; allocate here
3253 
3254         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3255                             m_port_ip.def.nBufferCountActual,
3256                             (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3257 
3258         if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone)
3259         {
3260             goto buffer_allocate_ip_exit;
3261         }
3262     }
3263 
3264     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3265     {
3266         if (m_buffer_array_ip[ii].buffer_populated == false)
3267         {
3268             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3269             break;
3270         }
3271     }
3272 
3273     if (ii < m_port_ip.def.nBufferCountActual)
3274     {
3275         int pmem_fd = -1;
3276 
3277         unsigned char *bufferaddr;
3278 
3279         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated",
3280                             ii,
3281                             size);
3282 
3283         m_buffer_array_ip[ii].ion_info.ion_fd_device =
3284             ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info.ion_alloc_data,
3285                                  &m_buffer_array_ip[ii].ion_info.ion_fd_data,
3286                                  size,
3287                                  m_port_ip.def.nBufferAlignment);
3288 
3289         if (m_buffer_array_ip[ii].ion_info.ion_fd_device < 0)
3290         {
3291             retval = OMX_ErrorInsufficientResources;
3292             goto buffer_allocate_ip_exit;
3293         }
3294 
3295         pmem_fd = m_buffer_array_ip[ii].ion_info.ion_fd_data.fd;
3296 
3297         bufferaddr = (unsigned char *) mmap(NULL,
3298                                             size,
3299                                             PROT_READ | PROT_WRITE,
3300                                             MAP_SHARED,
3301                                             pmem_fd,
3302                                             0);
3303 
3304         if (bufferaddr == MAP_FAILED)
3305         {
3306             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3307                                  pmem_fd,
3308                                  size);
3309             close(pmem_fd);
3310             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3311             retval = OMX_ErrorInsufficientResources;
3312             goto buffer_allocate_ip_exit;
3313         }
3314 
3315         *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3316 
3317         m_buffer_array_ip[ii].buffer_payload.bufferaddr  = bufferaddr;
3318         m_buffer_array_ip[ii].buffer_payload.pmem_fd     = pmem_fd;
3319         m_buffer_array_ip[ii].buffer_payload.buffer_len  = size;
3320         m_buffer_array_ip[ii].buffer_payload.mmaped_size = size;
3321         m_buffer_array_ip[ii].buffer_payload.offset      = 0;
3322 
3323         m_buffer_array_ip[ii].buffer_swvdec.p_buffer      = bufferaddr;
3324         m_buffer_array_ip[ii].buffer_swvdec.size          = size;
3325         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3326             (void *) ((unsigned long) ii);
3327 
3328         m_buffer_array_ip[ii].buffer_populated = true;
3329 
3330         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, %d bytes",
3331                             ii,
3332                             bufferaddr,
3333                             size);
3334 
3335         (*pp_buffer_hdr)->pBuffer           = (OMX_U8 *) bufferaddr;
3336         (*pp_buffer_hdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
3337         (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
3338         (*pp_buffer_hdr)->nAllocLen         = size;
3339         (*pp_buffer_hdr)->pAppPrivate       = p_app_data;
3340         (*pp_buffer_hdr)->nInputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3341         (*pp_buffer_hdr)->pInputPortPrivate =
3342             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3343 
3344         m_port_ip.populated   = port_ip_populated();
3345         m_port_ip.unpopulated = OMX_FALSE;
3346     }
3347     else
3348     {
3349         OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated",
3350                              m_port_ip.def.nBufferCountActual);
3351         retval = OMX_ErrorInsufficientResources;
3352     }
3353 
3354 buffer_allocate_ip_exit:
3355     return retval;
3356 }
3357 
3358 /**
3359  * @brief Allocate output buffer, and output buffer info array if necessary.
3360  *
3361  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3362  *                               structure.
3363  * @param[in]     p_app_data:    Pointer to IL client app data.
3364  * @param[in]     size:          Size of buffer to be allocated in bytes.
3365  *
3366  * @retval OMX_ERRORTYPE
3367  */
buffer_allocate_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3368 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op(
3369     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3370     OMX_PTR                p_app_data,
3371     OMX_U32                size)
3372 {
3373     OMX_ERRORTYPE retval = OMX_ErrorNone;
3374 
3375     unsigned int ii;
3376 
3377     if (size != m_port_op.def.nBufferSize)
3378     {
3379         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3380                              "configured size (%d bytes)",
3381                              size,
3382                              m_port_op.def.nBufferSize);
3383         retval = OMX_ErrorBadParameter;
3384         goto buffer_allocate_op_exit;
3385     }
3386 
3387     if (m_buffer_array_op == NULL)
3388     {
3389         // output buffer info array not allocated; allocate here
3390 
3391         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3392                             m_port_op.def.nBufferCountActual,
3393                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3394 
3395         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3396         {
3397             goto buffer_allocate_op_exit;
3398         }
3399     }
3400 
3401     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3402     {
3403         if (m_buffer_array_op[ii].buffer_populated == false)
3404         {
3405             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3406             break;
3407         }
3408     }
3409 
3410     if (ii < m_port_op.def.nBufferCountActual)
3411     {
3412         int pmem_fd = -1;
3413 
3414         unsigned char *bufferaddr;
3415 
3416         OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated",
3417                             ii,
3418                             size);
3419 
3420         m_buffer_array_op[ii].ion_info.ion_fd_device =
3421             ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info.ion_alloc_data,
3422                                  &m_buffer_array_op[ii].ion_info.ion_fd_data,
3423                                  size,
3424                                  m_port_op.def.nBufferAlignment);
3425 
3426         if (m_buffer_array_op[ii].ion_info.ion_fd_device < 0)
3427         {
3428             retval = OMX_ErrorInsufficientResources;
3429             goto buffer_allocate_op_exit;
3430         }
3431 
3432         pmem_fd = m_buffer_array_op[ii].ion_info.ion_fd_data.fd;
3433 
3434         bufferaddr = (unsigned char *) mmap(NULL,
3435                                             size,
3436                                             PROT_READ | PROT_WRITE,
3437                                             MAP_SHARED,
3438                                             pmem_fd,
3439                                             0);
3440 
3441         if (bufferaddr == MAP_FAILED)
3442         {
3443             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3444                                  pmem_fd,
3445                                  size);
3446             close(pmem_fd);
3447             ion_memory_free(&m_buffer_array_op[ii].ion_info);
3448             retval = OMX_ErrorInsufficientResources;
3449             goto buffer_allocate_op_exit;
3450         }
3451 
3452         *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3453 
3454         m_buffer_array_op[ii].buffer_payload.bufferaddr  = bufferaddr;
3455         m_buffer_array_op[ii].buffer_payload.pmem_fd     = pmem_fd;
3456         m_buffer_array_op[ii].buffer_payload.buffer_len  = size;
3457         m_buffer_array_op[ii].buffer_payload.mmaped_size = size;
3458         m_buffer_array_op[ii].buffer_payload.offset      = 0;
3459 
3460         m_buffer_array_op[ii].buffer_swvdec.p_buffer      = bufferaddr;
3461         m_buffer_array_op[ii].buffer_swvdec.size          = size;
3462         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3463             (void *) ((unsigned long) ii);
3464 
3465         m_buffer_array_op[ii].buffer_populated = true;
3466 
3467         OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, %d bytes",
3468                             ii,
3469                             bufferaddr,
3470                             size);
3471 
3472         (*pp_buffer_hdr)->pBuffer            = (OMX_U8 *) bufferaddr;
3473         (*pp_buffer_hdr)->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3474         (*pp_buffer_hdr)->nVersion.nVersion  = OMX_SPEC_VERSION;
3475         (*pp_buffer_hdr)->nAllocLen          = size;
3476         (*pp_buffer_hdr)->pAppPrivate        = p_app_data;
3477         (*pp_buffer_hdr)->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3478         (*pp_buffer_hdr)->pOutputPortPrivate =
3479             (void *) &(m_buffer_array_op[ii].buffer_payload);
3480 
3481         m_port_op.populated   = port_op_populated();
3482         m_port_op.unpopulated = OMX_FALSE;
3483     }
3484     else
3485     {
3486         OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated",
3487                              m_port_op.def.nBufferCountActual);
3488         retval = OMX_ErrorInsufficientResources;
3489     }
3490 
3491 buffer_allocate_op_exit:
3492     return retval;
3493 }
3494 
3495 /**
3496  * @brief Allocate input buffer info array.
3497  */
buffer_allocate_ip_info_array()3498 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array()
3499 {
3500     OMX_ERRORTYPE retval = OMX_ErrorNone;
3501 
3502     unsigned int ii;
3503 
3504     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3505 
3506     if (m_buffer_array_ip != NULL)
3507     {
3508         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3509         retval = OMX_ErrorInsufficientResources;
3510         goto buffer_allocate_ip_hdr_exit;
3511     }
3512 
3513     // input buffer info array not allocated; allocate here
3514 
3515     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3516                         m_port_ip.def.nBufferCountActual,
3517                         (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3518 
3519     m_buffer_array_ip =
3520         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3521                                           m_port_ip.def.nBufferCountActual);
3522 
3523     if (m_buffer_array_ip == NULL)
3524     {
3525         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3526                              "%d element%s, %d bytes requested",
3527                              m_port_ip.def.nBufferCountActual,
3528                              (m_port_ip.def.nBufferCountActual > 1) ? "s" : "",
3529                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3530                              m_port_ip.def.nBufferCountActual);
3531         retval = OMX_ErrorInsufficientResources;
3532         goto buffer_allocate_ip_hdr_exit;
3533     }
3534 
3535     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3536     {
3537         p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3538 
3539         // reset file descriptors
3540 
3541         m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3542         m_buffer_array_ip[ii].ion_info.ion_fd_device = -1;
3543 
3544         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3545             (void *) ((unsigned long) ii);
3546 
3547         p_buffer_hdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3548         p_buffer_hdr->nVersion.nVersion  = OMX_SPEC_VERSION;
3549         p_buffer_hdr->nOutputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3550         p_buffer_hdr->pOutputPortPrivate =
3551             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3552     }
3553 
3554 buffer_allocate_ip_hdr_exit:
3555     return retval;
3556 }
3557 
3558 /**
3559  * @brief Allocate output buffer info array.
3560  */
buffer_allocate_op_info_array()3561 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array()
3562 {
3563     OMX_ERRORTYPE retval = OMX_ErrorNone;
3564 
3565     unsigned int ii;
3566 
3567     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3568 
3569     if (m_buffer_array_op != NULL)
3570     {
3571         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3572         retval = OMX_ErrorInsufficientResources;
3573         goto buffer_allocate_op_hdr_exit;
3574     }
3575 
3576     // output buffer info array not allocated; allocate here
3577 
3578     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3579                         m_port_op.def.nBufferCountActual,
3580                         (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3581 
3582     m_buffer_array_op =
3583         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3584                                           m_port_op.def.nBufferCountActual);
3585 
3586     if (m_buffer_array_op == NULL)
3587     {
3588         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3589                              "%d element%s, %d bytes requested",
3590                              m_port_op.def.nBufferCountActual,
3591                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
3592                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3593                              m_port_op.def.nBufferCountActual);
3594         retval = OMX_ErrorInsufficientResources;
3595         goto buffer_allocate_op_hdr_exit;
3596     }
3597 
3598     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3599     {
3600         p_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3601 
3602         // reset file descriptors
3603 
3604         m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3605         m_buffer_array_op[ii].ion_info.ion_fd_device = -1;
3606 
3607         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3608             (void *) ((unsigned long) ii);
3609 
3610         p_buffer_hdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3611         p_buffer_hdr->nVersion.nVersion  = OMX_SPEC_VERSION;
3612         p_buffer_hdr->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3613         p_buffer_hdr->pOutputPortPrivate =
3614             (void *) &(m_buffer_array_op[ii].buffer_payload);
3615     }
3616 
3617 buffer_allocate_op_hdr_exit:
3618     return retval;
3619 }
3620 
3621 /**
3622  * @brief Use buffer allocated by IL client; allocate output buffer info array
3623  *        if necessary.
3624  *
3625  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3626  *                               structure.
3627  * @param[in]     p_app_data:    Pointer to IL client app data.
3628  * @param[in]     size:          Size of buffer to be allocated in bytes.
3629  * @param[in]     p_buffer:      Pointer to buffer to be used.
3630  *
3631  * @retval OMX_ERRORTYPE
3632  */
buffer_use_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size,OMX_U8 * p_buffer)3633 OMX_ERRORTYPE omx_swvdec::buffer_use_op(
3634     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3635     OMX_PTR                p_app_data,
3636     OMX_U32                size,
3637     OMX_U8                *p_buffer)
3638 {
3639     OMX_ERRORTYPE retval = OMX_ErrorNone;
3640 
3641     unsigned int ii;
3642 
3643     (void) size;
3644 
3645     if (m_buffer_array_op == NULL)
3646     {
3647         // output buffer info array not allocated; allocate here
3648 
3649         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3650                             m_port_op.def.nBufferCountActual,
3651                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3652 
3653         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3654         {
3655             goto buffer_use_op_exit;
3656         }
3657     }
3658 
3659     if (m_meta_buffer_mode && (m_meta_buffer_array == NULL))
3660     {
3661         // meta buffer info array not allocated; allocate here
3662 
3663         OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s",
3664                             m_port_op.def.nBufferCountActual,
3665                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3666 
3667         if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone)
3668         {
3669             goto buffer_use_op_exit;
3670         }
3671     }
3672 
3673     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3674     {
3675         if (m_buffer_array_op[ii].buffer_populated == false)
3676         {
3677             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3678             break;
3679         }
3680     }
3681 
3682     if (ii < m_port_op.def.nBufferCountActual)
3683     {
3684         struct vdec_bufferpayload *p_buffer_payload;
3685 
3686         SWVDEC_BUFFER *p_buffer_swvdec;
3687 
3688         *pp_buffer_hdr   = &m_buffer_array_op[ii].buffer_header;
3689         p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
3690         p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
3691 
3692         if (m_meta_buffer_mode)
3693         {
3694             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
3695             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
3696 
3697             m_buffer_array_op[ii].buffer_populated = true;
3698 
3699             (*pp_buffer_hdr)->pBuffer     = p_buffer;
3700             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3701             (*pp_buffer_hdr)->nAllocLen   =
3702                 sizeof(struct VideoDecoderOutputMetaData);
3703 
3704             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)",
3705                                 ii,
3706                                 *pp_buffer_hdr);
3707 
3708             m_port_op.populated   = port_op_populated();
3709             m_port_op.unpopulated = OMX_FALSE;
3710         }
3711         else if (m_android_native_buffers)
3712         {
3713             private_handle_t *p_handle;
3714 
3715             OMX_U8 *p_buffer_mapped;
3716 
3717             p_handle = (private_handle_t *) p_buffer;
3718 
3719             if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize)
3720             {
3721                 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3722                                      "configured size (%d bytes)",
3723                                      p_handle->size,
3724                                      m_port_op.def.nBufferSize);
3725 
3726                 retval = OMX_ErrorBadParameter;
3727                 goto buffer_use_op_exit;
3728             }
3729 
3730             m_port_op.def.nBufferSize = p_handle->size;
3731 
3732             p_buffer_mapped = (OMX_U8 *) mmap(NULL,
3733                                               p_handle->size,
3734                                               PROT_READ | PROT_WRITE,
3735                                               MAP_SHARED,
3736                                               p_handle->fd,
3737                                               0);
3738 
3739             if (p_buffer_mapped == MAP_FAILED)
3740             {
3741                 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3742                                      p_handle->fd,
3743                                      p_handle->size);
3744 
3745                 retval = OMX_ErrorInsufficientResources;
3746                 goto buffer_use_op_exit;
3747             }
3748 
3749             p_buffer_payload->bufferaddr  = p_buffer_mapped;
3750             p_buffer_payload->pmem_fd     = p_handle->fd;
3751             p_buffer_payload->buffer_len  = p_handle->size;
3752             p_buffer_payload->mmaped_size = p_handle->size;
3753             p_buffer_payload->offset      = 0;
3754 
3755             p_buffer_swvdec->p_buffer      = p_buffer_mapped;
3756             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
3757             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
3758 
3759             m_buffer_array_op[ii].buffer_populated = true;
3760 
3761             (*pp_buffer_hdr)->pBuffer     = (m_android_native_buffers ?
3762                                              ((OMX_U8 *) p_handle) :
3763                                              p_buffer_mapped);
3764             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
3765             (*pp_buffer_hdr)->nAllocLen   = m_port_op.def.nBufferSize;
3766 
3767             m_buffer_array_op[ii].ion_info.ion_fd_data.fd = p_handle->fd;
3768 
3769             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p",
3770                                 ii,
3771                                 *pp_buffer_hdr);
3772 
3773             m_port_op.populated   = port_op_populated();
3774             m_port_op.unpopulated = OMX_FALSE;
3775         }
3776         else
3777         {
3778             OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor "
3779                                  "'android native buffers' enabled");
3780             retval = OMX_ErrorBadParameter;
3781         }
3782     }
3783     else
3784     {
3785         OMX_SWVDEC_LOG_ERROR("all %d op buffers populated",
3786                              m_port_op.def.nBufferCountActual);
3787         retval = OMX_ErrorInsufficientResources;
3788     }
3789 
3790 buffer_use_op_exit:
3791     return retval;
3792 }
3793 
3794 /**
3795  * @brief De-allocate input buffer.
3796  *
3797  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
3798  *
3799  * @retval OMX_ERRORTYPE
3800  */
buffer_deallocate_ip(OMX_BUFFERHEADERTYPE * p_buffer_hdr)3801 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip(
3802     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
3803 {
3804     OMX_ERRORTYPE retval = OMX_ErrorNone;
3805 
3806     unsigned int ii;
3807 
3808     if (p_buffer_hdr == NULL)
3809     {
3810         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
3811         retval = OMX_ErrorBadParameter;
3812         goto buffer_deallocate_ip_exit;
3813     }
3814     else if (m_buffer_array_ip == NULL)
3815     {
3816         OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated");
3817         retval = OMX_ErrorBadParameter;
3818         goto buffer_deallocate_ip_exit;
3819     }
3820 
3821     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3822     {
3823         if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
3824         {
3825             OMX_SWVDEC_LOG_LOW("%p has index %d",
3826                                p_buffer_hdr->pBuffer,
3827                                ii);
3828             break;
3829         }
3830     }
3831 
3832     if (ii < m_port_ip.def.nBufferCountActual)
3833     {
3834         if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0)
3835         {
3836             m_buffer_array_ip[ii].buffer_populated = false;
3837 
3838             m_port_ip.populated = OMX_FALSE;
3839 
3840             munmap(m_buffer_array_ip[ii].buffer_payload.bufferaddr,
3841                    m_buffer_array_ip[ii].buffer_payload.mmaped_size);
3842 
3843             close(m_buffer_array_ip[ii].buffer_payload.pmem_fd);
3844             m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3845 
3846             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3847 
3848             // check if all buffers are unpopulated
3849             for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3850             {
3851                 if (m_buffer_array_ip[ii].buffer_populated)
3852                     break;
3853             }
3854 
3855             // if no buffers are populated, de-allocate input buffer info array
3856             if (ii == m_port_ip.def.nBufferCountActual)
3857             {
3858                 buffer_deallocate_ip_info_array();
3859                 m_port_ip.unpopulated = OMX_TRUE;
3860             }
3861         }
3862         else
3863         {
3864             OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d",
3865                                  p_buffer_hdr->pBuffer,
3866                                  m_buffer_array_ip[ii].buffer_payload.pmem_fd);
3867         }
3868     }
3869     else
3870     {
3871         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
3872         retval = OMX_ErrorBadParameter;
3873     }
3874 
3875 buffer_deallocate_ip_exit:
3876     return retval;
3877 }
3878 
3879 /**
3880  * @brief De-allocate output buffer.
3881  *
3882  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
3883  *
3884  * @retval OMX_ERRORTYPE
3885  */
buffer_deallocate_op(OMX_BUFFERHEADERTYPE * p_buffer_hdr)3886 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op(
3887     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
3888 {
3889     OMX_ERRORTYPE retval = OMX_ErrorNone;
3890 
3891     unsigned int ii;
3892 
3893     if (p_buffer_hdr == NULL)
3894     {
3895         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
3896         retval = OMX_ErrorBadParameter;
3897         goto buffer_deallocate_op_exit;
3898     }
3899     else if (m_buffer_array_op == NULL)
3900     {
3901         OMX_SWVDEC_LOG_ERROR("op buffer array not allocated");
3902         retval = OMX_ErrorBadParameter;
3903         goto buffer_deallocate_op_exit;
3904     }
3905 
3906     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3907     {
3908         if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
3909         {
3910             OMX_SWVDEC_LOG_LOW("%p has index %d",
3911                                p_buffer_hdr->pBuffer,
3912                                ii);
3913             break;
3914         }
3915     }
3916 
3917     if (ii < m_port_op.def.nBufferCountActual)
3918     {
3919         assert(m_buffer_array_op[ii].buffer_payload.pmem_fd > 0);
3920 
3921         if (m_meta_buffer_mode)
3922         {
3923             // do nothing; munmap() & close() done in FBD or RR
3924         }
3925         else if (m_android_native_buffers)
3926         {
3927             munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
3928                    m_buffer_array_op[ii].buffer_payload.mmaped_size);
3929             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3930         }
3931         else if (m_sync_frame_decoding_mode)
3932         {
3933             munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
3934                    m_buffer_array_op[ii].buffer_payload.mmaped_size);
3935             close(m_buffer_array_op[ii].buffer_payload.pmem_fd);
3936             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3937             ion_memory_free(&m_buffer_array_op[ii].ion_info);
3938         }
3939         else
3940         {
3941             assert(0);
3942         }
3943 
3944         m_buffer_array_op[ii].buffer_populated = false;
3945 
3946         m_port_op.populated = OMX_FALSE;
3947 
3948         // check if all buffers are unpopulated
3949         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3950         {
3951             if (m_buffer_array_op[ii].buffer_populated)
3952                 break;
3953         }
3954 
3955         // if no buffers are populated, de-allocate output buffer info array
3956         if (ii == m_port_op.def.nBufferCountActual)
3957         {
3958             buffer_deallocate_op_info_array();
3959             m_port_op.unpopulated = OMX_TRUE;
3960 
3961             if (m_meta_buffer_mode)
3962             {
3963                 meta_buffer_array_deallocate();
3964             }
3965         }
3966     }
3967     else
3968     {
3969         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
3970         retval = OMX_ErrorBadParameter;
3971     }
3972 
3973 buffer_deallocate_op_exit:
3974     return retval;
3975 }
3976 
3977 /**
3978  * @brief De-allocate input buffer info array.
3979  */
buffer_deallocate_ip_info_array()3980 void omx_swvdec::buffer_deallocate_ip_info_array()
3981 {
3982     assert(m_buffer_array_ip != NULL);
3983 
3984     free(m_buffer_array_ip);
3985     m_buffer_array_ip = NULL;
3986 }
3987 
3988 /**
3989  * @brief De-allocate output buffer info array.
3990  */
buffer_deallocate_op_info_array()3991 void omx_swvdec::buffer_deallocate_op_info_array()
3992 {
3993     assert(m_buffer_array_op != NULL);
3994 
3995     free(m_buffer_array_op);
3996     m_buffer_array_op = NULL;
3997 }
3998 
3999 /**
4000  * @brief Allocate meta buffer info array.
4001  *
4002  * @retval OMX_ERRORTYPE
4003  */
meta_buffer_array_allocate()4004 OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate()
4005 {
4006     OMX_ERRORTYPE retval = OMX_ErrorNone;
4007 
4008     m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *)
4009                            calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO),
4010                                   m_port_op.def.nBufferCountActual));
4011 
4012     if (m_meta_buffer_array == NULL)
4013     {
4014         OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; "
4015                              "%d element%s, %d bytes requested",
4016                              m_port_op.def.nBufferCountActual,
4017                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
4018                              sizeof(OMX_SWVDEC_META_BUFFER_INFO) *
4019                              m_port_op.def.nBufferCountActual);
4020 
4021         retval = OMX_ErrorInsufficientResources;
4022     }
4023 
4024     return retval;
4025 }
4026 
4027 /**
4028  * @brief De-allocate meta buffer info array.
4029  */
meta_buffer_array_deallocate()4030 void omx_swvdec::meta_buffer_array_deallocate()
4031 {
4032     assert(m_meta_buffer_array != NULL);
4033 
4034     free(m_meta_buffer_array);
4035     m_meta_buffer_array = NULL;
4036 }
4037 
4038 /**
4039  * @brief Add meta buffer reference.
4040  *
4041  * @param[in] index:
4042  * @param[in] fd:
4043  * @param[in] offset:
4044  */
meta_buffer_ref_add(unsigned int index,unsigned int fd,unsigned int offset)4045 void omx_swvdec::meta_buffer_ref_add(unsigned int index,
4046                                      unsigned int fd,
4047                                      unsigned int offset)
4048 {
4049     pthread_mutex_lock(&m_meta_buffer_array_mutex);
4050 
4051     if ((m_meta_buffer_array[index].dup_fd != 0) &&
4052         (m_meta_buffer_array[index].fd     != fd) &&
4053         (m_meta_buffer_array[index].offset != offset))
4054     {
4055         OMX_SWVDEC_LOG_LOW("index %d taken by fd %d, offset %d",
4056                            index,
4057                            m_meta_buffer_array[index].fd,
4058                            m_meta_buffer_array[index].offset);
4059     }
4060     else
4061     {
4062         if (m_meta_buffer_array[index].dup_fd == 0)
4063         {
4064             m_meta_buffer_array[index].fd     = fd;
4065             m_meta_buffer_array[index].dup_fd = dup(fd);
4066             m_meta_buffer_array[index].offset = offset;
4067         }
4068 
4069         m_meta_buffer_array[index].ref_count++;
4070     }
4071 
4072     pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4073 }
4074 
4075 /**
4076  * @brief Remove meta buffer reference.
4077  *
4078  * @param[in] fd:
4079  * @param[in] offset:
4080  */
meta_buffer_ref_remove(unsigned int fd,unsigned int offset)4081 void omx_swvdec::meta_buffer_ref_remove(unsigned int fd,
4082                                         unsigned int offset)
4083 {
4084     unsigned int ii;
4085 
4086     pthread_mutex_lock(&m_meta_buffer_array_mutex);
4087 
4088     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4089     {
4090         if ((m_meta_buffer_array[ii].fd     == fd) &&
4091             (m_meta_buffer_array[ii].offset == offset))
4092         {
4093             m_meta_buffer_array[ii].ref_count--;
4094 
4095             if (m_meta_buffer_array[ii].ref_count == 0)
4096             {
4097                 close(m_meta_buffer_array[ii].dup_fd);
4098 
4099                 m_meta_buffer_array[ii].fd = 0;
4100                 m_meta_buffer_array[ii].dup_fd = 0;
4101                 m_meta_buffer_array[ii].offset = 0;
4102 
4103                 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
4104                        m_buffer_array_op[ii].buffer_payload.mmaped_size);
4105 
4106                 m_buffer_array_op[ii].buffer_payload.bufferaddr  = NULL;
4107                 m_buffer_array_op[ii].buffer_payload.offset      = 0;
4108                 m_buffer_array_op[ii].buffer_payload.mmaped_size = 0;
4109 
4110                 m_buffer_array_op[ii].buffer_swvdec.p_buffer = NULL;
4111                 m_buffer_array_op[ii].buffer_swvdec.size     = 0;
4112             }
4113 
4114             break;
4115         }
4116     }
4117 
4118     assert(ii < m_port_op.def.nBufferCountActual);
4119 
4120     pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4121 }
4122 
4123 /**
4124  * @brief Check if ip port is populated, i.e., if all ip buffers are populated.
4125  *
4126  * @retval  true
4127  * @retval false
4128  */
port_ip_populated()4129 OMX_BOOL omx_swvdec::port_ip_populated()
4130 {
4131     OMX_BOOL retval = OMX_FALSE;
4132 
4133     if (m_buffer_array_ip != NULL)
4134     {
4135         unsigned int ii;
4136 
4137         for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4138         {
4139             if (m_buffer_array_ip[ii].buffer_populated == false)
4140             {
4141                 break;
4142             }
4143         }
4144 
4145         if (ii == m_port_ip.def.nBufferCountActual)
4146         {
4147             retval = OMX_TRUE;
4148         }
4149     }
4150 
4151     return retval;
4152 }
4153 
4154 /**
4155  * @brief Check if op port is populated, i.e., if all op buffers are populated.
4156  *
4157  * @retval  true
4158  * @retval false
4159  */
port_op_populated()4160 OMX_BOOL omx_swvdec::port_op_populated()
4161 {
4162     OMX_BOOL retval = OMX_FALSE;
4163 
4164     if (m_buffer_array_op != NULL)
4165     {
4166         unsigned int ii;
4167 
4168         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4169         {
4170             if (m_buffer_array_op[ii].buffer_populated == false)
4171             {
4172                 break;
4173             }
4174         }
4175 
4176         if (ii == m_port_op.def.nBufferCountActual)
4177         {
4178             retval = OMX_TRUE;
4179         }
4180     }
4181 
4182     return retval;
4183 }
4184 
4185 /**
4186  * @brief Flush input, output, or both input & output ports.
4187  *
4188  * @param[in] port_index: Index of port to flush.
4189  *
4190  * @retval OMX_ERRORTYPE
4191  */
flush(unsigned int port_index)4192 OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index)
4193 {
4194     OMX_ERRORTYPE retval = OMX_ErrorNone;
4195 
4196     if (((port_index == OMX_CORE_PORT_INDEX_IP) &&
4197          m_port_ip.flush_inprogress) ||
4198         ((port_index == OMX_CORE_PORT_INDEX_OP) &&
4199          m_port_op.flush_inprogress) ||
4200         ((port_index == OMX_ALL) &&
4201          m_port_ip.flush_inprogress &&
4202          m_port_op.flush_inprogress))
4203     {
4204         OMX_SWVDEC_LOG_HIGH("flush port %d already in progress", port_index);
4205     }
4206     else
4207     {
4208         SWVDEC_FLUSH_TYPE swvdec_flush_type;
4209 
4210         SWVDEC_STATUS retval_swvdec;
4211 
4212         if (port_index == OMX_CORE_PORT_INDEX_IP)
4213         {
4214             m_port_ip.flush_inprogress = OMX_TRUE;
4215 
4216             // no separate SwVdec flush type for input
4217         }
4218         else if (port_index == OMX_CORE_PORT_INDEX_OP)
4219         {
4220             m_port_op.flush_inprogress = OMX_TRUE;
4221 
4222             swvdec_flush_type = (m_port_ip.flush_inprogress ?
4223                                  SWVDEC_FLUSH_TYPE_ALL :
4224                                  SWVDEC_FLUSH_TYPE_OP);
4225 
4226             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4227                                               swvdec_flush_type)) !=
4228                 SWVDEC_STATUS_SUCCESS)
4229             {
4230                 retval = retval_swvdec2omx(retval_swvdec);
4231             }
4232         }
4233         else if (port_index == OMX_ALL)
4234         {
4235             m_port_ip.flush_inprogress = OMX_TRUE;
4236             m_port_op.flush_inprogress = OMX_TRUE;
4237 
4238             swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4239 
4240             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4241                                               swvdec_flush_type)) !=
4242                 SWVDEC_STATUS_SUCCESS)
4243             {
4244                 retval = retval_swvdec2omx(retval_swvdec);
4245             }
4246         }
4247         else
4248         {
4249             assert(0);
4250         }
4251     }
4252 
4253     return retval;
4254 }
4255 
4256 /**
4257  * @brief Allocate & map ION memory.
4258  */
ion_memory_alloc_map(struct ion_allocation_data * p_alloc_data,struct ion_fd_data * p_fd_data,OMX_U32 size,OMX_U32 alignment)4259 int omx_swvdec::ion_memory_alloc_map(struct ion_allocation_data *p_alloc_data,
4260                                      struct ion_fd_data         *p_fd_data,
4261                                      OMX_U32                     size,
4262                                      OMX_U32                     alignment)
4263 {
4264     int fd = -EINVAL;
4265     int rc = -EINVAL;
4266 
4267     if ((p_alloc_data == NULL) || (p_fd_data == NULL) || (size == 0))
4268     {
4269         OMX_SWVDEC_LOG_ERROR("invalid arguments");
4270         goto ion_memory_alloc_map_exit;
4271     }
4272 
4273     if ((fd = open("/dev/ion", O_RDONLY)) < 0)
4274     {
4275         OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", fd);
4276         goto ion_memory_alloc_map_exit;
4277     }
4278 
4279     p_alloc_data->len   = size;
4280     p_alloc_data->align = (alignment < 4096) ? 4096 : alignment;
4281     p_alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
4282     p_alloc_data->flags = 0;
4283 
4284     OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %d, align %d",
4285                        p_alloc_data->heap_id_mask,
4286                        p_alloc_data->len,
4287                        p_alloc_data->align);
4288 
4289     rc = ioctl(fd, ION_IOC_ALLOC, p_alloc_data);
4290 
4291     if (rc || (p_alloc_data->handle == 0))
4292     {
4293         OMX_SWVDEC_LOG_ERROR("ioctl() for allocation failed");
4294         close(fd);
4295         fd = -ENOMEM;
4296         goto ion_memory_alloc_map_exit;
4297     }
4298 
4299     p_fd_data->handle = p_alloc_data->handle;
4300 
4301     if (ioctl(fd, ION_IOC_MAP, p_fd_data))
4302     {
4303         struct vdec_ion ion_buf_info;
4304 
4305         OMX_SWVDEC_LOG_ERROR("ioctl() for mapping failed");
4306 
4307         ion_buf_info.ion_alloc_data = *p_alloc_data;
4308         ion_buf_info.ion_fd_device  = fd;
4309         ion_buf_info.ion_fd_data    = *p_fd_data;
4310 
4311         ion_memory_free(&ion_buf_info);
4312 
4313         p_fd_data->fd = -1;
4314         close(fd);
4315         fd = -ENOMEM;
4316         goto ion_memory_alloc_map_exit;
4317     }
4318 
4319 ion_memory_alloc_map_exit:
4320     return fd;
4321 }
4322 
4323 /**
4324  * @brief Free ION memory.
4325  */
ion_memory_free(struct vdec_ion * p_ion_buf_info)4326 void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info)
4327 {
4328     if (p_ion_buf_info == NULL)
4329     {
4330         OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL");
4331         goto ion_memory_free_exit;
4332     }
4333 
4334     if (ioctl(p_ion_buf_info->ion_fd_device,
4335               ION_IOC_FREE,
4336               &p_ion_buf_info->ion_alloc_data.handle))
4337     {
4338         OMX_SWVDEC_LOG_ERROR("ioctl() for freeing failed");
4339     }
4340 
4341     close(p_ion_buf_info->ion_fd_device);
4342 
4343     p_ion_buf_info->ion_fd_device         = -1;
4344     p_ion_buf_info->ion_alloc_data.handle =  0;
4345     p_ion_buf_info->ion_fd_data.fd        = -1;
4346 
4347 ion_memory_free_exit:
4348     return;
4349 }
4350 
4351 /**
4352  * ----------------------------
4353  * component callback functions
4354  * ----------------------------
4355  */
4356 
4357 /**
4358  * @brief Empty buffer done callback.
4359  *
4360  * @param[in] p_buffer_ip: Pointer to input buffer structure.
4361  */
swvdec_empty_buffer_done(SWVDEC_BUFFER * p_buffer_ip)4362 void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip)
4363 {
4364     unsigned long index = (unsigned long) p_buffer_ip->p_client_data;
4365 
4366     async_post_event(OMX_SWVDEC_EVENT_EBD,
4367                      (unsigned long) &m_buffer_array_ip[index].buffer_header,
4368                      index);
4369 }
4370 
4371 /**
4372  * @brief Fill buffer done callback.
4373  *
4374  * @param[in] p_buffer_op: Pointer to output buffer structure.
4375  */
swvdec_fill_buffer_done(SWVDEC_BUFFER * p_buffer_op)4376 void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op)
4377 {
4378     unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4379 
4380     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
4381 
4382     if (index < ((unsigned long) m_port_op.def.nBufferCountActual))
4383     {
4384         p_buffer_hdr = &m_buffer_array_op[index].buffer_header;
4385 
4386         p_buffer_hdr->nFlags     = p_buffer_op->flags;
4387         p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp;
4388         p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode &&
4389                                      p_buffer_op->filled_length) ?
4390                                     p_buffer_hdr->nAllocLen :
4391                                     p_buffer_op->filled_length);
4392     }
4393 
4394     async_post_event(OMX_SWVDEC_EVENT_FBD,
4395                      (unsigned long) &m_buffer_array_op[index].buffer_header,
4396                      index);
4397 }
4398 
4399 /**
4400  * @brief Event handler callback.
4401  *
4402  * @param[in] event:  Event.
4403  * @param[in] p_data: Pointer to event-specific data.
4404  */
swvdec_event_handler(SWVDEC_EVENT event,void * p_data)4405 void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data)
4406 {
4407     switch (event)
4408     {
4409 
4410     case SWVDEC_EVENT_FLUSH_ALL_DONE:
4411     {
4412         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0);
4413         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4414         break;
4415     }
4416 
4417     case SWVDEC_EVENT_FLUSH_OP_DONE:
4418     {
4419         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4420         break;
4421     }
4422 
4423     case SWVDEC_EVENT_RELEASE_REFERENCE:
4424     {
4425         SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data;
4426 
4427         unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4428 
4429         OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer);
4430 
4431         assert(index < ((unsigned long) m_port_op.def.nBufferCountActual));
4432 
4433         if (m_meta_buffer_mode)
4434         {
4435             meta_buffer_ref_remove(
4436                 m_buffer_array_op[index].buffer_payload.pmem_fd,
4437                 m_buffer_array_op[index].buffer_payload.offset);
4438         }
4439 
4440         break;
4441     }
4442 
4443     case SWVDEC_EVENT_RECONFIG_REQUIRED:
4444     {
4445         async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0);
4446         break;
4447     }
4448 
4449     case SWVDEC_EVENT_FATAL_ERROR:
4450     default:
4451     {
4452         async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0);
4453         break;
4454     }
4455 
4456     }
4457 }
4458 
4459 /**
4460  * @brief Translate SwVdec status return value to OMX error type return value.
4461  *
4462  * @param[in] retval_swvdec: SwVdec status return value.
4463  *
4464  * @retval OMX_ERRORTYPE
4465  */
retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)4466 OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)
4467 {
4468     OMX_ERRORTYPE retval_omx;
4469 
4470     switch (retval_swvdec)
4471     {
4472 
4473     SWVDEC_STATUS_SUCCESS:
4474         retval_omx = OMX_ErrorNone;
4475         break;
4476 
4477     SWVDEC_STATUS_FAILURE:
4478         retval_omx = OMX_ErrorUndefined;
4479         break;
4480 
4481     SWVDEC_STATUS_NULL_POINTER:
4482     SWVDEC_STATUS_INVALID_PARAMETERS:
4483         retval_omx = OMX_ErrorBadParameter;
4484         break;
4485 
4486     SWVDEC_STATUS_INVALID_STATE:
4487         retval_omx = OMX_ErrorInvalidState;
4488         break;
4489 
4490     SWVDEC_STATUS_INSUFFICIENT_RESOURCES:
4491         retval_omx = OMX_ErrorInsufficientResources;
4492         break;
4493 
4494     SWVDEC_STATUS_UNSUPPORTED:
4495         retval_omx = OMX_ErrorUnsupportedSetting;
4496         break;
4497 
4498     SWVDEC_STATUS_NOT_IMPLEMENTED:
4499         retval_omx = OMX_ErrorNotImplemented;
4500         break;
4501 
4502     default:
4503         retval_omx = OMX_ErrorUndefined;
4504         break;
4505 
4506     }
4507 
4508     return retval_omx;
4509 }
4510 
4511 /**
4512  * @brief Create asynchronous thread.
4513  *
4514  * @retval OMX_ERRORTYPE
4515  */
async_thread_create()4516 OMX_ERRORTYPE omx_swvdec::async_thread_create()
4517 {
4518     OMX_ERRORTYPE retval = OMX_ErrorNone;
4519 
4520     pthread_attr_t thread_attributes;
4521 
4522     if (sem_init(&m_async_thread.sem_thread_created, 0, 0))
4523     {
4524         OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore");
4525         retval = OMX_ErrorInsufficientResources;
4526     }
4527     else if (sem_init(&m_async_thread.sem_event, 0, 0))
4528     {
4529         OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore");
4530         retval = OMX_ErrorInsufficientResources;
4531     }
4532     else if (pthread_attr_init(&thread_attributes))
4533     {
4534         OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object");
4535         retval = OMX_ErrorInsufficientResources;
4536     }
4537     else if (pthread_attr_setdetachstate(&thread_attributes,
4538                                          PTHREAD_CREATE_JOINABLE))
4539     {
4540         OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute");
4541         retval = OMX_ErrorInsufficientResources;
4542 
4543         pthread_attr_destroy(&thread_attributes);
4544     }
4545     else
4546     {
4547         m_async_thread.created = false;
4548         m_async_thread.exit    = false;
4549 
4550         if (pthread_create(&m_async_thread.handle,
4551                            &thread_attributes,
4552                            (void *(*)(void *)) async_thread,
4553                            this))
4554         {
4555             OMX_SWVDEC_LOG_ERROR("failed to create async thread");
4556             retval = OMX_ErrorInsufficientResources;
4557 
4558             pthread_attr_destroy(&thread_attributes);
4559         }
4560         else
4561         {
4562             if (pthread_setname_np(m_async_thread.handle, "swvdec_async"))
4563             {
4564                 // don't return error
4565                 OMX_SWVDEC_LOG_ERROR("failed to set async thread name");
4566             }
4567 
4568             sem_wait(&m_async_thread.sem_thread_created);
4569             m_async_thread.created = true;
4570         }
4571     }
4572 
4573     return retval;
4574 }
4575 
4576 /**
4577  * @brief Destroy asynchronous thread.
4578  */
async_thread_destroy()4579 void omx_swvdec::async_thread_destroy()
4580 {
4581     if (m_async_thread.created)
4582     {
4583         m_async_thread.exit = true;
4584         sem_post(&m_async_thread.sem_event);
4585 
4586         pthread_join(m_async_thread.handle, NULL);
4587         m_async_thread.created = false;
4588     }
4589 
4590     m_async_thread.exit = false;
4591 
4592     sem_destroy(&m_async_thread.sem_event);
4593     sem_destroy(&m_async_thread.sem_thread_created);
4594 }
4595 
4596 /**
4597  * @brief Post event to appropriate queue.
4598  *
4599  * @param[in] event_id:     Event ID.
4600  * @param[in] event_param1: Event parameter 1.
4601  * @param[in] event_param2: Event parameter 2.
4602  *
4603  * @retval  true if post event successful
4604  * @retval false if post event unsuccessful
4605  */
async_post_event(unsigned long event_id,unsigned long event_param1,unsigned long event_param2)4606 bool omx_swvdec::async_post_event(unsigned long event_id,
4607                                   unsigned long event_param1,
4608                                   unsigned long event_param2)
4609 {
4610     OMX_SWVDEC_EVENT_INFO event_info;
4611 
4612     bool retval = true;
4613 
4614     event_info.event_id     = event_id;
4615     event_info.event_param1 = event_param1;
4616     event_info.event_param2 = event_param2;
4617 
4618     switch (event_id)
4619     {
4620 
4621     case OMX_SWVDEC_EVENT_ETB:
4622     case OMX_SWVDEC_EVENT_EBD:
4623     {
4624         retval = m_queue_port_ip.push(&event_info);
4625         break;
4626     }
4627 
4628     case OMX_SWVDEC_EVENT_FTB:
4629     case OMX_SWVDEC_EVENT_FBD:
4630     {
4631         retval = m_queue_port_op.push(&event_info);
4632         break;
4633     }
4634 
4635     default:
4636     {
4637         retval = m_queue_command.push(&event_info);
4638         break;
4639     }
4640 
4641     }
4642 
4643     if (retval == true)
4644     {
4645         sem_post(&m_async_thread.sem_event);
4646     }
4647 
4648     return retval;
4649 }
4650 
4651 /**
4652  * @brief Asynchronous thread.
4653  *
4654  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
4655  */
async_thread(void * p_cmp)4656 void omx_swvdec::async_thread(void *p_cmp)
4657 {
4658     if (p_cmp == NULL)
4659     {
4660         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
4661     }
4662     else
4663     {
4664         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp;
4665 
4666         ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread;
4667 
4668         OMX_SWVDEC_LOG_HIGH("created");
4669 
4670         sem_post(&p_async_thread->sem_thread_created);
4671 
4672         while (p_async_thread->exit == false)
4673         {
4674             sem_wait(&p_async_thread->sem_event);
4675 
4676             if (p_async_thread->exit == true)
4677             {
4678                 break;
4679             }
4680 
4681             p_omx_swvdec->async_process_event(p_cmp);
4682         }
4683     }
4684 
4685     OMX_SWVDEC_LOG_HIGH("exiting");
4686 }
4687 
4688 /**
4689  * @brief Process event.
4690  *
4691  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
4692  */
async_process_event(void * p_cmp)4693 void omx_swvdec::async_process_event(void *p_cmp)
4694 {
4695     omx_swvdec *p_omx_swvdec;
4696 
4697     OMX_SWVDEC_EVENT_INFO event_info;
4698 
4699     OMX_ERRORTYPE retval = OMX_ErrorNone;
4700 
4701     if (p_cmp == NULL)
4702     {
4703         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
4704         goto async_process_event_exit;
4705     }
4706 
4707     p_omx_swvdec = (omx_swvdec *) p_cmp;
4708 
4709     // NOTE: queues popped in order of priority; do not change!
4710 
4711     if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) &&
4712         (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) &&
4713         (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false))
4714     {
4715         OMX_SWVDEC_LOG_LOW("no event popped");
4716         goto async_process_event_exit;
4717     }
4718 
4719     switch (event_info.event_id)
4720     {
4721 
4722     case OMX_SWVDEC_EVENT_CMD:
4723     {
4724         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
4725         OMX_U32         param = (OMX_U32)         event_info.event_param2;
4726 
4727         retval = p_omx_swvdec->async_process_event_cmd(cmd, param);
4728         break;
4729     }
4730 
4731     case OMX_SWVDEC_EVENT_CMD_ACK:
4732     {
4733         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
4734         OMX_U32         param = (OMX_U32)         event_info.event_param2;
4735 
4736         retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param);
4737         break;
4738     }
4739 
4740     case OMX_SWVDEC_EVENT_ERROR:
4741     {
4742         OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1;
4743 
4744         retval = p_omx_swvdec->async_process_event_error(error_code);
4745         break;
4746     }
4747 
4748     case OMX_SWVDEC_EVENT_ETB:
4749     {
4750         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4751             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4752 
4753         unsigned int index = event_info.event_param2;
4754 
4755         retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index);
4756         break;
4757     }
4758 
4759     case OMX_SWVDEC_EVENT_FTB:
4760     {
4761         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4762             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4763 
4764         unsigned int index = event_info.event_param2;
4765 
4766         retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index);
4767         break;
4768     }
4769 
4770     case OMX_SWVDEC_EVENT_EBD:
4771     {
4772         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4773             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4774 
4775         unsigned int index = event_info.event_param2;
4776 
4777         retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index);
4778         break;
4779     }
4780 
4781     case OMX_SWVDEC_EVENT_FBD:
4782     {
4783         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
4784             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
4785 
4786         unsigned int index = event_info.event_param2;
4787 
4788         retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index);
4789         break;
4790     }
4791 
4792     case OMX_SWVDEC_EVENT_EOS:
4793     {
4794         retval = p_omx_swvdec->async_process_event_eos();
4795         break;
4796     }
4797 
4798     case OMX_SWVDEC_EVENT_FLUSH_PORT_IP:
4799     {
4800         retval = p_omx_swvdec->async_process_event_flush_port_ip();
4801         break;
4802     }
4803 
4804     case OMX_SWVDEC_EVENT_FLUSH_PORT_OP:
4805     {
4806         retval = p_omx_swvdec->async_process_event_flush_port_op();
4807         break;
4808     }
4809 
4810     case OMX_SWVDEC_EVENT_PORT_RECONFIG:
4811     {
4812         retval = p_omx_swvdec->async_process_event_port_reconfig();
4813         break;
4814     }
4815 
4816     default:
4817     {
4818         assert(0);
4819         retval = OMX_ErrorUndefined;
4820         break;
4821     }
4822 
4823     }
4824 
4825     if (retval != OMX_ErrorNone)
4826     {
4827         p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
4828     }
4829 
4830 async_process_event_exit:
4831     return;
4832 }
4833 
4834 /**
4835  * @brief Process command event.
4836  *
4837  * @param[in] cmd:   Command.
4838  * @param[in] param: Command parameter.
4839  *
4840  * @retval OMX_ERRORTYPE
4841  */
async_process_event_cmd(OMX_COMMANDTYPE cmd,OMX_U32 param)4842 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd,
4843                                                   OMX_U32         param)
4844 {
4845     OMX_ERRORTYPE retval = OMX_ErrorNone;
4846 
4847     bool cmd_ack = false; // set to 'true' if command is to be acknowledged
4848 
4849     SWVDEC_STATUS retval_swvdec;
4850 
4851     switch (cmd)
4852     {
4853 
4854     case OMX_CommandStateSet:
4855     {
4856         retval = async_process_event_cmd_state_set(&cmd_ack,
4857                                                    (OMX_STATETYPE) param);
4858         break;
4859     }
4860 
4861     case OMX_CommandFlush:
4862     {
4863         retval = async_process_event_cmd_flush((unsigned int) param);
4864         break;
4865     }
4866 
4867     case OMX_CommandPortDisable:
4868     {
4869         retval = async_process_event_cmd_port_disable(&cmd_ack,
4870                                                       (unsigned int) param);
4871         break;
4872     }
4873 
4874     case OMX_CommandPortEnable:
4875     {
4876         retval = async_process_event_cmd_port_enable(&cmd_ack,
4877                                                      (unsigned int) param);
4878         break;
4879     }
4880 
4881     default:
4882     {
4883         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
4884 
4885         retval = OMX_ErrorBadParameter;
4886         break;
4887     }
4888 
4889     } // switch (cmd)
4890 
4891     // post appropriate event
4892 
4893     if (retval != OMX_ErrorNone)
4894     {
4895         async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
4896     }
4897     else if (cmd_ack)
4898     {
4899         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param);
4900     }
4901 
4902     // post to command semaphore
4903     sem_post(&m_sem_cmd);
4904 
4905     return retval;
4906 }
4907 
4908 /**
4909  * @brief Process command acknowledgement event.
4910  *
4911  * @param[in] cmd:   Command.
4912  * @param[in] param: Command parameter.
4913  *
4914  * @retval OMX_ERRORTYPE
4915  */
async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,OMX_U32 param)4916 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,
4917                                                       OMX_U32         param)
4918 {
4919     OMX_ERRORTYPE retval = OMX_ErrorNone;
4920 
4921     switch (cmd)
4922     {
4923 
4924     case OMX_CommandStateSet:
4925     {
4926         m_state = (OMX_STATETYPE) param;
4927 
4928         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
4929                                 "OMX_CommandStateSet, %s",
4930                                 OMX_STATETYPE_STRING(m_state));
4931 
4932         m_callback.EventHandler(&m_cmp,
4933                                 m_app_data,
4934                                 OMX_EventCmdComplete,
4935                                 OMX_CommandStateSet,
4936                                 (OMX_U32) m_state,
4937                                 NULL);
4938         break;
4939     }
4940 
4941     case OMX_CommandFlush:
4942     case OMX_CommandPortEnable:
4943     case OMX_CommandPortDisable:
4944     {
4945         if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress)
4946         {
4947             m_port_reconfig_inprogress = false;
4948         }
4949 
4950         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
4951                                 "%s, port index %d",
4952                                 OMX_COMMANDTYPE_STRING(cmd),
4953                                 param);
4954 
4955         m_callback.EventHandler(&m_cmp,
4956                                 m_app_data,
4957                                 OMX_EventCmdComplete,
4958                                 cmd,
4959                                 param,
4960                                 NULL);
4961         break;
4962     }
4963 
4964     default:
4965     {
4966         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
4967         retval = OMX_ErrorBadParameter;
4968         break;
4969     }
4970 
4971     } // switch (cmd)
4972 
4973     return retval;
4974 }
4975 
4976 /**
4977  * @brief Process error event.
4978  *
4979  * @param[in] error_code: Error code.
4980  *
4981  * @retval OMX_ErrorNone
4982  */
async_process_event_error(OMX_ERRORTYPE error_code)4983 OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code)
4984 {
4985     if (error_code == OMX_ErrorInvalidState)
4986     {
4987         m_state = OMX_StateInvalid;
4988     }
4989 
4990     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x",
4991                             error_code);
4992 
4993     m_callback.EventHandler(&m_cmp,
4994                             m_app_data,
4995                             OMX_EventError,
4996                             (OMX_U32) error_code,
4997                             0,
4998                             NULL);
4999 
5000     return OMX_ErrorNone;
5001 }
5002 
5003 /**
5004  * @brief Process OMX_CommandStateSet.
5005  *
5006  * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5007  * @param[in]     state_new: New state to which transition is requested.
5008  *
5009  * @retval OMX_ERRORTYPE
5010  */
async_process_event_cmd_state_set(bool * p_cmd_ack,OMX_STATETYPE state_new)5011 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set(
5012     bool         *p_cmd_ack,
5013     OMX_STATETYPE state_new)
5014 {
5015     OMX_ERRORTYPE retval = OMX_ErrorNone;
5016 
5017     SWVDEC_STATUS retval_swvdec;
5018 
5019     OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested",
5020                         OMX_STATETYPE_STRING(m_state),
5021                         OMX_STATETYPE_STRING(state_new));
5022 
5023     /**
5024      * Only the following state transitions are allowed via CommandStateSet:
5025      *
5026      * LOADED -> IDLE -> EXECUTING
5027      * LOADED <- IDLE <- EXECUTING
5028      */
5029 
5030     if (m_state == OMX_StateInvalid)
5031     {
5032         OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state));
5033         retval = OMX_ErrorInvalidState;
5034     }
5035     else if (state_new == OMX_StateInvalid)
5036     {
5037         OMX_SWVDEC_LOG_ERROR("requested transition to state %s",
5038                              OMX_STATETYPE_STRING(state_new));
5039         retval = OMX_ErrorInvalidState;
5040     }
5041     else if ((m_state   == OMX_StateLoaded) &&
5042              (state_new == OMX_StateIdle))
5043     {
5044         if ((m_port_ip.populated == OMX_TRUE) &&
5045             (m_port_op.populated == OMX_TRUE))
5046         {
5047             // start SwVdec
5048             if ((retval_swvdec = swvdec_start(m_swvdec_handle)) ==
5049                 SWVDEC_STATUS_SUCCESS)
5050             {
5051                 *p_cmd_ack = true;
5052             }
5053             else
5054             {
5055                 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
5056                 retval = retval_swvdec2omx(retval_swvdec);
5057             }
5058         }
5059         else
5060         {
5061             m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE);
5062 
5063             OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending");
5064         }
5065     }
5066     else if ((m_state   == OMX_StateIdle) &&
5067              (state_new == OMX_StateExecuting))
5068     {
5069         *p_cmd_ack = true;
5070     }
5071     else if ((m_state   == OMX_StateExecuting) &&
5072              (state_new == OMX_StateIdle))
5073     {
5074         m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE);
5075 
5076         OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending");
5077 
5078         retval = flush(OMX_ALL);
5079     }
5080     else if ((m_state   == OMX_StateIdle) &&
5081              (state_new == OMX_StateLoaded))
5082     {
5083         if ((m_port_ip.unpopulated == OMX_TRUE) &&
5084             (m_port_op.unpopulated == OMX_TRUE))
5085         {
5086             // stop SwVdec
5087             if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
5088                 SWVDEC_STATUS_SUCCESS)
5089             {
5090                 *p_cmd_ack = true;
5091             }
5092             else
5093             {
5094                 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
5095                 retval = retval_swvdec2omx(retval_swvdec);
5096             }
5097         }
5098         else
5099         {
5100             m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED);
5101 
5102             OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending");
5103         }
5104     }
5105     else
5106     {
5107         OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal",
5108                              OMX_STATETYPE_STRING(m_state),
5109                              OMX_STATETYPE_STRING(state_new));
5110 
5111         retval = ((state_new == m_state) ?
5112                   OMX_ErrorSameState :
5113                   OMX_ErrorIncorrectStateTransition);
5114     }
5115 
5116     return retval;
5117 }
5118 
5119 /**
5120  * @brief Process OMX_CommandFlush.
5121  *
5122  * @param[in] port_index: Index of port to flush.
5123  *
5124  * @retval OMX_ERRORTYPE
5125  */
async_process_event_cmd_flush(unsigned int port_index)5126 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index)
5127 {
5128     OMX_ERRORTYPE retval = OMX_ErrorNone;
5129 
5130     OMX_SWVDEC_LOG_HIGH("flush port %d requested", port_index);
5131 
5132     if (port_index == OMX_CORE_PORT_INDEX_IP)
5133     {
5134         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5135 
5136         OMX_SWVDEC_LOG_LOW("ip port flush pending");
5137     }
5138     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5139     {
5140         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5141 
5142         OMX_SWVDEC_LOG_LOW("op port flush pending");
5143     }
5144     else if (port_index == OMX_ALL)
5145     {
5146         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5147         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5148 
5149         OMX_SWVDEC_LOG_LOW("ip & op ports flush pending");
5150     }
5151 
5152     retval = flush(port_index);
5153 
5154     return retval;
5155 }
5156 
5157 /**
5158  * @brief Process OMX_CommandPortDisable.
5159  *
5160  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5161  * @param[in]     port_index: Index of port to disable.
5162  *
5163  * @retval OMX_ERRORTYPE
5164  */
async_process_event_cmd_port_disable(bool * p_cmd_ack,unsigned int port_index)5165 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable(
5166     bool         *p_cmd_ack,
5167     unsigned int  port_index)
5168 {
5169     OMX_ERRORTYPE retval = OMX_ErrorNone;
5170 
5171     OMX_SWVDEC_LOG_HIGH("disable port %d requested", port_index);
5172 
5173     if (port_index == OMX_CORE_PORT_INDEX_IP)
5174     {
5175         if (m_port_ip.enabled == OMX_FALSE)
5176         {
5177             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5178             retval = OMX_ErrorBadPortIndex;
5179         }
5180         else
5181         {
5182             m_port_ip.enabled = OMX_FALSE;
5183 
5184             if (m_port_ip.unpopulated)
5185             {
5186                 *p_cmd_ack = true;
5187             }
5188             else
5189             {
5190                 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5191 
5192                 OMX_SWVDEC_LOG_LOW("ip port disable pending");
5193 
5194                 if (m_port_ip.num_pending_buffers)
5195                 {
5196                     retval = flush(port_index);
5197                 }
5198             }
5199         }
5200     }
5201     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5202     {
5203         if (m_port_op.enabled == OMX_FALSE)
5204         {
5205             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5206             retval = OMX_ErrorBadPortIndex;
5207         }
5208         else
5209         {
5210             m_port_op.enabled = OMX_FALSE;
5211 
5212             if (m_port_op.unpopulated)
5213             {
5214                 *p_cmd_ack = true;
5215             }
5216             else
5217             {
5218                 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5219 
5220                 OMX_SWVDEC_LOG_LOW("op port disable pending");
5221 
5222                 if (m_port_op.num_pending_buffers)
5223                 {
5224                     retval = flush(port_index);
5225                 }
5226             }
5227         }
5228     }
5229     else if (port_index == OMX_ALL)
5230     {
5231         if (m_port_ip.enabled == OMX_FALSE)
5232         {
5233             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5234             retval = OMX_ErrorBadPortIndex;
5235         }
5236         else if (m_port_op.enabled == OMX_FALSE)
5237         {
5238             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5239             retval = OMX_ErrorBadPortIndex;
5240         }
5241         else
5242         {
5243             if (m_port_ip.unpopulated && m_port_op.unpopulated)
5244             {
5245                 *p_cmd_ack = true;
5246             }
5247             else
5248             {
5249                 m_port_ip.enabled = OMX_FALSE;
5250                 m_port_op.enabled = OMX_FALSE;
5251 
5252                 if (m_port_ip.unpopulated == OMX_FALSE)
5253                 {
5254                     m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5255 
5256                     OMX_SWVDEC_LOG_LOW("ip port disable pending");
5257 
5258                     if (m_port_ip.num_pending_buffers)
5259                     {
5260                         retval = flush(port_index);
5261                     }
5262                 }
5263 
5264                 if ((retval == OMX_ErrorNone) &&
5265                     (m_port_op.unpopulated == OMX_FALSE))
5266                 {
5267                     m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5268 
5269                     OMX_SWVDEC_LOG_LOW("op port disable pending");
5270 
5271                     if (m_port_op.num_pending_buffers)
5272                     {
5273                         retval = flush(port_index);
5274                     }
5275                 }
5276             }
5277         }
5278     }
5279     else
5280     {
5281         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
5282         retval = OMX_ErrorBadPortIndex;
5283     }
5284 
5285     return retval;
5286 }
5287 
5288 /**
5289  * @brief Process OMX_CommandPortEnable.
5290  *
5291  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5292  * @param[in]     port_index: Index of port to enable.
5293  *
5294  * @retval OMX_ERRORTYPE
5295  */
async_process_event_cmd_port_enable(bool * p_cmd_ack,unsigned int port_index)5296 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable(
5297     bool         *p_cmd_ack,
5298     unsigned int  port_index)
5299 {
5300     OMX_ERRORTYPE retval = OMX_ErrorNone;
5301 
5302     OMX_SWVDEC_LOG_HIGH("enable port %d requested", port_index);
5303 
5304     if (port_index == OMX_CORE_PORT_INDEX_IP)
5305     {
5306         if (m_port_ip.enabled)
5307         {
5308             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5309             retval = OMX_ErrorBadPortIndex;
5310         }
5311         else
5312         {
5313             m_port_ip.enabled = OMX_TRUE;
5314 
5315             if (m_port_ip.populated)
5316             {
5317                 *p_cmd_ack = true;
5318             }
5319             else
5320             {
5321                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5322 
5323                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5324             }
5325         }
5326     }
5327     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5328     {
5329         if (m_port_op.enabled)
5330         {
5331             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5332             retval = OMX_ErrorBadPortIndex;
5333         }
5334         else
5335         {
5336             m_port_op.enabled = OMX_TRUE;
5337 
5338             if (m_port_op.populated)
5339             {
5340                 *p_cmd_ack = true;
5341             }
5342             else
5343             {
5344                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5345 
5346                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5347             }
5348         }
5349     }
5350     else if (port_index == OMX_ALL)
5351     {
5352         if (m_port_ip.enabled)
5353         {
5354             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5355             retval = OMX_ErrorBadPortIndex;
5356         }
5357         else if (m_port_op.enabled)
5358         {
5359             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5360             retval = OMX_ErrorBadPortIndex;
5361         }
5362         else
5363         {
5364             m_port_ip.enabled = OMX_TRUE;
5365             m_port_op.enabled = OMX_TRUE;
5366 
5367             if (m_port_ip.populated && m_port_op.populated)
5368             {
5369                 *p_cmd_ack = true;
5370             }
5371             else if (m_port_ip.populated == false)
5372             {
5373                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5374 
5375                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5376             }
5377             else if (m_port_op.populated == false)
5378             {
5379                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5380 
5381                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5382             }
5383         }
5384     }
5385     else
5386     {
5387         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
5388         retval = OMX_ErrorBadPortIndex;
5389     }
5390 
5391     return retval;
5392 }
5393 
5394 /**
5395  * @brief Process ETB event.
5396  *
5397  * @param[in] p_buffer_hdr: Pointer to buffer header.
5398  * @param[in] index:        Index of buffer in input buffer info array.
5399  *
5400  * @retval OMX_ERRORTYPE
5401  */
async_process_event_etb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5402 OMX_ERRORTYPE omx_swvdec::async_process_event_etb(
5403     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5404     unsigned int          index)
5405 {
5406     OMX_ERRORTYPE retval = OMX_ErrorNone;
5407 
5408     m_port_ip.num_pending_buffers++;
5409 
5410     if ((p_buffer_hdr->nFilledLen == 0) &&
5411         ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5412     {
5413         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5414                             "zero length & no EOS flag",
5415                             p_buffer_hdr,
5416                             p_buffer_hdr->pBuffer);
5417 
5418         async_post_event(OMX_SWVDEC_EVENT_EBD,
5419                          (unsigned long) p_buffer_hdr,
5420                          (unsigned long) index);
5421     }
5422     else if (m_port_ip.flush_inprogress)
5423     {
5424         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5425                             "ip port flush in progress",
5426                             p_buffer_hdr,
5427                             p_buffer_hdr->pBuffer);
5428 
5429         async_post_event(OMX_SWVDEC_EVENT_EBD,
5430                          (unsigned long) p_buffer_hdr,
5431                          (unsigned long) index);
5432     }
5433     else
5434     {
5435         SWVDEC_STATUS retval_swvdec;
5436 
5437         SWVDEC_BUFFER *p_buffer_swvdec =
5438             &(m_buffer_array_ip[index].buffer_swvdec);
5439 
5440         if (p_buffer_hdr->nFilledLen &&
5441             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5442         {
5443             m_ts_list.push(p_buffer_hdr->nTimeStamp);
5444         }
5445 
5446         assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer);
5447 
5448         p_buffer_swvdec->flags         = p_buffer_hdr->nFlags;
5449         p_buffer_swvdec->timestamp     = p_buffer_hdr->nTimeStamp;
5450         p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
5451 
5452         m_diag.dump_ip(p_buffer_swvdec->p_buffer,
5453                        p_buffer_swvdec->filled_length);
5454 
5455         retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
5456                                                p_buffer_swvdec);
5457 
5458         if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
5459         {
5460             retval = retval_swvdec2omx(retval_swvdec);
5461         }
5462     }
5463 
5464     return retval;
5465 }
5466 
5467 /**
5468  * @brief Process FTB event.
5469  *
5470  * @param[in] p_buffer_hdr: Pointer to buffer header.
5471  * @param[in] index:        Index of buffer in output buffer info array.
5472  *
5473  * @retval OMX_ERRORTYPE
5474  */
async_process_event_ftb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5475 OMX_ERRORTYPE omx_swvdec::async_process_event_ftb(
5476     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5477     unsigned int          index)
5478 {
5479     OMX_ERRORTYPE retval = OMX_ErrorNone;
5480 
5481     m_port_op.num_pending_buffers++;
5482 
5483     if (m_port_op.flush_inprogress)
5484     {
5485         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5486                             "op port flush in progress",
5487                             p_buffer_hdr,
5488                             m_buffer_array_op[index].buffer_swvdec.p_buffer);
5489 
5490         async_post_event(OMX_SWVDEC_EVENT_FBD,
5491                          (unsigned long) p_buffer_hdr,
5492                          (unsigned long) index);
5493     }
5494     else
5495     {
5496         SWVDEC_STATUS retval_swvdec;
5497 
5498         SWVDEC_BUFFER *p_buffer_swvdec =
5499             &(m_buffer_array_op[index].buffer_swvdec);
5500 
5501         retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec);
5502 
5503         if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
5504         {
5505             retval = retval_swvdec2omx(retval_swvdec);
5506         }
5507     }
5508 
5509     return retval;
5510 }
5511 
5512 /**
5513  * @brief Process EBD event.
5514  *
5515  * @param[in] p_buffer_hdr: Pointer to buffer header.
5516  * @param[in] index:        Index of buffer in output buffer info array.
5517  *
5518  * @retval OMX_ERRORTYPE
5519  */
async_process_event_ebd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5520 OMX_ERRORTYPE omx_swvdec::async_process_event_ebd(
5521     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5522     unsigned int          index)
5523 {
5524     OMX_ERRORTYPE retval = OMX_ErrorNone;
5525 
5526     if (index < m_port_ip.def.nBufferCountActual)
5527     {
5528         m_port_ip.num_pending_buffers--;
5529 
5530         // should ideally be set in swvdec_empty_buffer_done()
5531         p_buffer_hdr->nFilledLen = 0;
5532 
5533         OMX_SWVDEC_LOG_CALLBACK(
5534             "EmptyBufferDone(): %p, buffer %p",
5535             p_buffer_hdr,
5536             m_buffer_array_ip[index].buffer_swvdec.p_buffer);
5537 
5538         m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
5539     }
5540     else
5541     {
5542         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
5543         retval = OMX_ErrorBadParameter;
5544     }
5545 
5546     return retval;
5547 }
5548 
5549 /**
5550  * @brief Process FBD event.
5551  *
5552  * @param[in] p_buffer_hdr: Pointer to buffer header.
5553  * @param[in] index:        Index of buffer in output buffer info array.
5554  *
5555  * @retval OMX_ERRORTYPE
5556  */
async_process_event_fbd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5557 OMX_ERRORTYPE omx_swvdec::async_process_event_fbd(
5558     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5559     unsigned int          index)
5560 {
5561     OMX_ERRORTYPE retval = OMX_ErrorNone;
5562 
5563     if (index < m_port_op.def.nBufferCountActual)
5564     {
5565         OMX_U8 *p_buffer;
5566 
5567         p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer;
5568 
5569         m_port_op.num_pending_buffers--;
5570 
5571         if (m_port_op.flush_inprogress)
5572         {
5573             p_buffer_hdr->nFilledLen = 0;
5574             p_buffer_hdr->nTimeStamp = 0;
5575             p_buffer_hdr->nFlags    &= ~OMX_BUFFERFLAG_DATACORRUPT;
5576         }
5577 
5578         if (p_buffer_hdr->nFilledLen)
5579         {
5580             if (m_sync_frame_decoding_mode)
5581             {
5582                 p_buffer_hdr->nTimeStamp = 0;
5583             }
5584             else
5585             {
5586                 if (m_ts_list.pop(&p_buffer_hdr->nTimeStamp) == false)
5587                 {
5588                     OMX_SWVDEC_LOG_ERROR("failed to pop timestamp from list");
5589                 }
5590             }
5591 
5592             m_diag.dump_op(p_buffer,
5593                            m_frame_dimensions.width,
5594                            m_frame_dimensions.height,
5595                            m_frame_attributes.stride,
5596                            m_frame_attributes.scanlines);
5597         }
5598 
5599         if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS)
5600         {
5601             async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0);
5602 
5603             m_ts_list.reset();
5604         }
5605 
5606         if (m_meta_buffer_mode &&
5607             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0)
5608         {
5609             meta_buffer_ref_remove(
5610                 m_buffer_array_op[index].buffer_payload.pmem_fd,
5611                 m_buffer_array_op[index].buffer_payload.offset);
5612         }
5613 
5614         OMX_SWVDEC_LOG_CALLBACK(
5615             "FillBufferDone(): %p, buffer %p, "
5616             "flags 0x%08x, timestamp %lld",
5617             p_buffer_hdr,
5618             p_buffer,
5619             p_buffer_hdr->nFlags,
5620             p_buffer_hdr->nTimeStamp);
5621 
5622         m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
5623     }
5624     else
5625     {
5626         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
5627         retval = OMX_ErrorBadParameter;
5628     }
5629 
5630 async_process_event_fbd_exit:
5631     return retval;
5632 }
5633 
5634 /**
5635  * @brief Process EOS event.
5636  *
5637  * @retval OMX_ErrorNone
5638  */
async_process_event_eos()5639 OMX_ERRORTYPE omx_swvdec::async_process_event_eos()
5640 {
5641     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
5642                             "OMX_EventBufferFlag, port %d, EOS",
5643                             OMX_CORE_PORT_INDEX_OP);
5644 
5645     m_callback.EventHandler(&m_cmp,
5646                             m_app_data,
5647                             OMX_EventBufferFlag,
5648                             OMX_CORE_PORT_INDEX_OP,
5649                             OMX_BUFFERFLAG_EOS,
5650                             NULL);
5651 
5652     return OMX_ErrorNone;
5653 }
5654 
5655 /**
5656  * @brief Process input port flush event.
5657  *
5658  * @retval OMX_ERRORTYPE
5659  */
async_process_event_flush_port_ip()5660 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip()
5661 {
5662     OMX_ERRORTYPE retval = OMX_ErrorNone;
5663 
5664     OMX_SWVDEC_EVENT_INFO event_info;
5665 
5666     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
5667 
5668     unsigned int index;
5669 
5670     while (m_queue_port_ip.pop(&event_info))
5671     {
5672         switch (event_info.event_id)
5673         {
5674 
5675         case OMX_SWVDEC_EVENT_ETB:
5676         {
5677             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5678             index = event_info.event_param2;
5679 
5680             // compensate decrement in async_process_event_ebd()
5681             m_port_ip.num_pending_buffers++;
5682 
5683             retval = async_process_event_ebd(p_buffer_hdr, index);
5684             break;
5685         }
5686 
5687         case OMX_SWVDEC_EVENT_EBD:
5688         {
5689             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5690             index = event_info.event_param2;
5691 
5692             retval = async_process_event_ebd(p_buffer_hdr, index);
5693             break;
5694         }
5695 
5696         default:
5697         {
5698             assert(0);
5699             break;
5700         }
5701 
5702         }
5703     }
5704 
5705     assert(m_port_ip.num_pending_buffers == 0);
5706 
5707     if ((retval == OMX_ErrorNone) &&
5708         (m_status_flags & (1 << PENDING_PORT_FLUSH_IP)))
5709     {
5710         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP);
5711 
5712         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5713                          OMX_CommandFlush,
5714                          OMX_CORE_PORT_INDEX_IP);
5715     }
5716 
5717     m_port_ip.flush_inprogress = OMX_FALSE;
5718 
5719     return retval;
5720 }
5721 
5722 /**
5723  * @brief Process output port flush event.
5724  *
5725  * @retval OMX_ERRORTYPE
5726  */
async_process_event_flush_port_op()5727 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op()
5728 {
5729     OMX_ERRORTYPE retval = OMX_ErrorNone;
5730 
5731     OMX_SWVDEC_EVENT_INFO event_info;
5732 
5733     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
5734 
5735     unsigned int index;
5736 
5737     while (m_queue_port_op.pop(&event_info))
5738     {
5739         switch (event_info.event_id)
5740         {
5741 
5742         case OMX_SWVDEC_EVENT_FTB:
5743         {
5744             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5745             index = event_info.event_param2;
5746 
5747             // compensate decrement in async_process_event_fbd()
5748             m_port_op.num_pending_buffers++;
5749 
5750             retval = async_process_event_fbd(p_buffer_hdr, index);
5751             break;
5752         }
5753 
5754         case OMX_SWVDEC_EVENT_FBD:
5755         {
5756             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5757             index = event_info.event_param2;
5758 
5759             retval = async_process_event_fbd(p_buffer_hdr, index);
5760             break;
5761         }
5762 
5763         default:
5764         {
5765             assert(0);
5766             break;
5767         }
5768 
5769         }
5770     }
5771 
5772     assert(m_port_op.num_pending_buffers == 0);
5773 
5774     if ((retval == OMX_ErrorNone) &&
5775         (m_status_flags & (1 << PENDING_PORT_FLUSH_OP)))
5776     {
5777         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP);
5778 
5779         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5780                          OMX_CommandFlush,
5781                          OMX_CORE_PORT_INDEX_OP);
5782     }
5783 
5784     if ((retval == OMX_ErrorNone) &&
5785         (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE)))
5786     {
5787         m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE);
5788 
5789         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
5790                          OMX_CommandStateSet,
5791                          OMX_StateIdle);
5792     }
5793 
5794     if (m_port_reconfig_inprogress == false)
5795     {
5796         m_ts_list.reset();
5797     }
5798 
5799     m_port_op.flush_inprogress = OMX_FALSE;
5800 
5801     return retval;
5802 }
5803 
5804 /**
5805  * @brief Process port reconfiguration event.
5806  *
5807  * @retval OMX_ERRORTYPE
5808  */
async_process_event_port_reconfig()5809 OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig()
5810 {
5811     OMX_ERRORTYPE retval = OMX_ErrorNone;
5812 
5813     if (m_port_reconfig_inprogress)
5814     {
5815         OMX_SWVDEC_LOG_ERROR("port reconfiguration in progress");
5816         retval = OMX_ErrorIncorrectStateOperation;
5817     }
5818     else
5819     {
5820         m_port_reconfig_inprogress = true;
5821 
5822         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
5823                                 "OMX_EventPortSettingsChanged, port %d",
5824                                 OMX_CORE_PORT_INDEX_OP);
5825 
5826         m_callback.EventHandler(&m_cmp,
5827                                 m_app_data,
5828                                 OMX_EventPortSettingsChanged,
5829                                 OMX_CORE_PORT_INDEX_OP,
5830                                 0,
5831                                 NULL);
5832     }
5833 
5834     return retval;
5835 }
5836