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