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