1 /**
2  * @copyright
3  *
4  *   Copyright (c) 2015-2020, 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.vc1sw",
196                       OMX_MAX_STRINGNAME_SIZE)))||
197               ((!strncmp(cmp_name,
198                       "OMX.qti.video.decoder.wmvsw",
199                       OMX_MAX_STRINGNAME_SIZE))))
200     {
201         char platform_name[PROP_VALUE_MAX] = {0};
202         char version[PROP_VALUE_MAX] = {0};
203         property_get("ro.board.platform", platform_name, "0");  //HW ID
204         if (!strcmp(platform_name, "sm6150"))
205         {
206             if (property_get("vendor.media.target.version", version, "0") &&
207                     (atoi(version) == 0))
208             {
209                 //Sku version, VC1 is disabled on this target
210                 OMX_SWVDEC_LOG_ERROR("VC1 decoder not supported on this target");
211                 retval = OMX_ErrorInvalidComponentName;
212                 goto component_init_exit;
213             }
214         }
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 && !(m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)))
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 = ion_map(p_private_handle->fd,p_private_handle->size);
2221 
2222             if (bufferaddr == MAP_FAILED)
2223             {
2224                 OMX_SWVDEC_LOG_ERROR("mmap() failed for "
2225                                      "fd %d of size %d",
2226                                      p_private_handle->fd,
2227                                      p_private_handle->size);
2228 
2229                 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
2230 
2231                 retval = OMX_ErrorInsufficientResources;
2232                 goto fill_this_buffer_exit;
2233             }
2234 
2235             p_buffer_payload->bufferaddr  = bufferaddr;
2236             p_buffer_payload->pmem_fd     = p_private_handle->fd;
2237             p_buffer_payload->buffer_len  = p_private_handle->size;
2238             p_buffer_payload->mmaped_size = p_private_handle->size;
2239 
2240             p_buffer_swvdec->p_buffer      = bufferaddr;
2241             p_buffer_swvdec->size          = p_private_handle->size;
2242             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
2243         }
2244 
2245         meta_buffer_ref_add(ii, p_buffer_payload->pmem_fd);
2246 
2247         pthread_mutex_unlock(&m_meta_buffer_array_mutex);
2248     }
2249 
2250     OMX_SWVDEC_LOG_LOW("%p: buffer %p",
2251                        p_buffer_hdr,
2252                        p_buffer_swvdec->p_buffer);
2253 
2254     async_post_event(OMX_SWVDEC_EVENT_FTB,
2255                      (unsigned long) p_buffer_hdr,
2256                      (unsigned long) ii);
2257 
2258 fill_this_buffer_exit:
2259     return retval;
2260 }
2261 
2262 /**
2263  * @brief Set component's callback structure.
2264  *
2265  * @param[in] cmp_handle:  Component handle.
2266  * @param[in] p_callbacks: Pointer to callback structure.
2267  * @param[in] p_app_data:  Pointer to IL client app data.
2268  *
2269  * @retval OMX_ERRORTYPE
2270  */
set_callbacks(OMX_HANDLETYPE cmp_handle,OMX_CALLBACKTYPE * p_callbacks,OMX_PTR p_app_data)2271 OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE    cmp_handle,
2272                                         OMX_CALLBACKTYPE *p_callbacks,
2273                                         OMX_PTR           p_app_data)
2274 {
2275     OMX_ERRORTYPE retval = OMX_ErrorNone;
2276 
2277     OMX_SWVDEC_LOG_API("");
2278 
2279     if (m_state == OMX_StateInvalid)
2280     {
2281         OMX_SWVDEC_LOG_ERROR("in invalid state");
2282 
2283         retval = OMX_ErrorInvalidState;
2284     }
2285     else if (cmp_handle == NULL)
2286     {
2287         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2288 
2289         retval = OMX_ErrorInvalidComponent;
2290     }
2291     else if (p_callbacks->EventHandler == NULL)
2292     {
2293         OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL");
2294 
2295         retval = OMX_ErrorBadParameter;
2296     }
2297     else if (p_callbacks->EmptyBufferDone == NULL)
2298     {
2299         OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL");
2300 
2301         retval = OMX_ErrorBadParameter;
2302     }
2303     else if (p_callbacks->FillBufferDone == NULL)
2304     {
2305         OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL");
2306 
2307         retval = OMX_ErrorBadParameter;
2308     }
2309     else
2310     {
2311         m_callback = *p_callbacks;
2312         m_app_data = p_app_data;
2313     }
2314 
2315     return retval;
2316 }
2317 
2318 /**
2319  * @brief Use EGL image.
2320  *
2321  * @retval OMX_ErrorNotImplemented
2322  */
use_EGL_image(OMX_HANDLETYPE cmp_handle,OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_U32 port,OMX_PTR p_app_data,void * egl_image)2323 OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE         cmp_handle,
2324                                         OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
2325                                         OMX_U32                port,
2326                                         OMX_PTR                p_app_data,
2327                                         void                  *egl_image)
2328 {
2329     (void) cmp_handle;
2330     (void) pp_buffer_hdr;
2331     (void) port;
2332     (void) p_app_data;
2333     (void) egl_image;
2334 
2335     OMX_SWVDEC_LOG_API("");
2336 
2337     OMX_SWVDEC_LOG_ERROR("not implemented");
2338 
2339     return OMX_ErrorNotImplemented;
2340 }
2341 
2342 /**
2343  * @brief Enumerate component role.
2344  *
2345  * @param[in]     cmp_handle: Component handle.
2346  * @param[in,out] p_role:     Pointer to component role string.
2347  * @param[in]     index:      Role index being queried.
2348  *
2349  * @retval OMX_ERRORTYPE
2350  */
component_role_enum(OMX_HANDLETYPE cmp_handle,OMX_U8 * p_role,OMX_U32 index)2351 OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle,
2352                                               OMX_U8        *p_role,
2353                                               OMX_U32        index)
2354 {
2355     OMX_ERRORTYPE retval = OMX_ErrorNone;
2356 
2357     if (m_state == OMX_StateInvalid)
2358     {
2359         OMX_SWVDEC_LOG_ERROR("in invalid state");
2360 
2361         retval = OMX_ErrorInvalidState;
2362     }
2363     else if (cmp_handle == NULL)
2364     {
2365         OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
2366 
2367         retval = OMX_ErrorInvalidComponent;
2368     }
2369     else if (index > 0)
2370     {
2371         OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index);
2372 
2373         retval = OMX_ErrorNoMore;
2374     }
2375     else
2376     {
2377         memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE);
2378 
2379         OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role);
2380     }
2381 
2382     return retval;
2383 }
2384 
2385 /**
2386  * -------------------------
2387  * SwVdec callback functions
2388  * -------------------------
2389  */
2390 
2391 /**
2392  * @brief SwVdec empty buffer done callback.
2393  *
2394  * @param[in] swvdec_handle:   SwVdec handle.
2395  * @param[in] p_buffer_ip:     Pointer to input buffer structure.
2396  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2397  *
2398  * @retval SWVDEC_STATUS_SUCCESS
2399  * @retval SWVDEC_STATUS_NULL_POINTER
2400  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2401  */
swvdec_empty_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_ip,void * p_client_handle)2402 SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback(
2403     SWVDEC_HANDLE  swvdec_handle,
2404     SWVDEC_BUFFER *p_buffer_ip,
2405     void          *p_client_handle)
2406 {
2407     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2408 
2409     if (p_buffer_ip == NULL)
2410     {
2411         OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL");
2412 
2413         retval = SWVDEC_STATUS_NULL_POINTER;
2414     }
2415     else if (p_client_handle == NULL)
2416     {
2417         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2418 
2419         retval = SWVDEC_STATUS_NULL_POINTER;
2420     }
2421     else
2422     {
2423         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2424 
2425         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2426         {
2427             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2428 
2429             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2430         }
2431         else
2432         {
2433             p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip);
2434         }
2435     }
2436 
2437     return retval;
2438 }
2439 
2440 /**
2441  * @brief SwVdec fill buffer done callback.
2442  *
2443  * @param[in] swvdec_handle:   SwVdec handle.
2444  * @param[in] p_buffer_op:     Pointer to output buffer structure.
2445  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2446  *
2447  * @retval SWVDEC_STATUS_SUCCESS
2448  * @retval SWVDEC_STATUS_NULL_POINTER
2449  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2450  */
swvdec_fill_buffer_done_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_BUFFER * p_buffer_op,void * p_client_handle)2451 SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback(
2452     SWVDEC_HANDLE  swvdec_handle,
2453     SWVDEC_BUFFER *p_buffer_op,
2454     void          *p_client_handle)
2455 {
2456     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2457 
2458     if (p_buffer_op == NULL)
2459     {
2460         OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL");
2461 
2462         retval = SWVDEC_STATUS_NULL_POINTER;
2463     }
2464     else if (p_client_handle == NULL)
2465     {
2466         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2467 
2468         retval = SWVDEC_STATUS_NULL_POINTER;
2469     }
2470     else
2471     {
2472         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2473 
2474         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2475         {
2476             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2477 
2478             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2479         }
2480         else
2481         {
2482             p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op);
2483         }
2484     }
2485 
2486     return retval;
2487 }
2488 
2489 /**
2490  * @brief SwVdec event handler callback.
2491  *
2492  * @param[in] swvdec_handle:   SwVdec handle.
2493  * @param[in] event:           Event.
2494  * @param[in] p_data:          Pointer to event-specific data.
2495  * @param[in] p_client_handle: Pointer to SwVdec's client handle.
2496  *
2497  * @retval SWVDEC_STATUS_SUCCESS
2498  * @retval SWVDEC_STATUS_NULL_POINTER
2499  * @retval SWVDEC_STATUS_INVALID_PARAMETERS
2500  */
swvdec_event_handler_callback(SWVDEC_HANDLE swvdec_handle,SWVDEC_EVENT event,void * p_data,void * p_client_handle)2501 SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback(
2502     SWVDEC_HANDLE swvdec_handle,
2503     SWVDEC_EVENT  event,
2504     void         *p_data,
2505     void         *p_client_handle)
2506 {
2507     SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
2508 
2509     if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL))
2510     {
2511         OMX_SWVDEC_LOG_ERROR("p_data = NULL");
2512 
2513         retval = SWVDEC_STATUS_NULL_POINTER;
2514     }
2515     else if (p_client_handle == NULL)
2516     {
2517         OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
2518 
2519         retval = SWVDEC_STATUS_NULL_POINTER;
2520     }
2521     else
2522     {
2523         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
2524 
2525         if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
2526         {
2527             OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
2528 
2529             retval = SWVDEC_STATUS_INVALID_PARAMETERS;
2530         }
2531         else
2532         {
2533             p_omx_swvdec->swvdec_event_handler(event, p_data);
2534         }
2535     }
2536 
2537     return retval;
2538 }
2539 
2540 /**
2541  * -----------------
2542  * PRIVATE FUNCTIONS
2543  * -----------------
2544  */
2545 
2546 /**
2547  * @brief Set frame dimensions for OMX component & SwVdec core.
2548  *
2549  * @param[in] width:  Frame width.
2550  * @param[in] height: Frame height.
2551  *
2552  * @retval OMX_ERRORTYPE
2553  */
set_frame_dimensions(unsigned int width,unsigned int height)2554 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width,
2555                                                unsigned int height)
2556 {
2557     OMX_ERRORTYPE retval;
2558 
2559     m_frame_dimensions.width  = width;
2560     m_frame_dimensions.height = height;
2561 
2562     OMX_SWVDEC_LOG_HIGH("%d x %d",
2563                         m_frame_dimensions.width,
2564                         m_frame_dimensions.height);
2565 
2566     retval = set_frame_dimensions_swvdec();
2567 
2568     return retval;
2569 }
2570 
2571 /**
2572  * @brief Set frame attributes for OMX component & SwVdec core, based on
2573  *        frame dimensions & color format.
2574  *
2575  * @param[in] color_format: Color format.
2576  *
2577  * @retval OMX_ERRORTYPE
2578  */
set_frame_attributes(OMX_COLOR_FORMATTYPE color_format)2579 OMX_ERRORTYPE omx_swvdec::set_frame_attributes(
2580     OMX_COLOR_FORMATTYPE color_format)
2581 {
2582     OMX_ERRORTYPE retval = OMX_ErrorNone;
2583 
2584     unsigned int width  = m_frame_dimensions.width;
2585     unsigned int height = m_frame_dimensions.height;
2586 
2587     unsigned int scanlines_uv;
2588 
2589     unsigned int plane_size_y;
2590     unsigned int plane_size_uv;
2591 
2592     switch (color_format)
2593     {
2594 
2595     case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m:
2596     {
2597         /**
2598          * alignment factors:
2599          *
2600          * - stride:        128
2601          * - scanlines_y:    32
2602          * - scanlines_uv:   16
2603          * - size:         4096
2604          */
2605 
2606         m_frame_attributes.stride    = ALIGN(width, 128);
2607         m_frame_attributes.scanlines = ALIGN(height, 32);
2608 
2609         scanlines_uv = ALIGN(height / 2, 16);
2610 
2611         plane_size_y  = (m_frame_attributes.stride *
2612                          m_frame_attributes.scanlines);
2613 
2614         plane_size_uv = m_frame_attributes.stride * scanlines_uv;
2615 
2616         m_frame_attributes.size = ALIGN(plane_size_y + plane_size_uv, 4096);
2617 
2618         OMX_SWVDEC_LOG_HIGH("'OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m': "
2619                             "stride %d, scanlines %d, size %d",
2620                             m_frame_attributes.stride,
2621                             m_frame_attributes.scanlines,
2622                             m_frame_attributes.size);
2623 
2624         break;
2625     }
2626 
2627     case OMX_COLOR_FormatYUV420SemiPlanar:
2628     {
2629         /**
2630          * alignment factors:
2631          *
2632          * - stride:         16
2633          * - scanlines_y:    16
2634          * - scanlines_uv:   16
2635          * - size:         4096
2636          */
2637 
2638         m_frame_attributes.stride    = ALIGN(width,  16);
2639         m_frame_attributes.scanlines = ALIGN(height, 16);
2640 
2641         scanlines_uv = ALIGN(height / 2, 16);
2642 
2643         plane_size_y  = (m_frame_attributes.stride *
2644                          m_frame_attributes.scanlines);
2645 
2646         plane_size_uv = m_frame_attributes.stride * scanlines_uv;
2647 
2648         m_frame_attributes.size = ALIGN(plane_size_y + plane_size_uv, 4096);
2649 
2650         OMX_SWVDEC_LOG_HIGH("'OMX_COLOR_FormatYUV420SemiPlanar': "
2651                             "stride %d, scanlines %d, size %d",
2652                             m_frame_attributes.stride,
2653                             m_frame_attributes.scanlines,
2654                             m_frame_attributes.size);
2655 
2656         break;
2657     }
2658 
2659     default:
2660     {
2661         OMX_SWVDEC_LOG_ERROR("'0x%08x' color format invalid or unsupported",
2662                              color_format);
2663 
2664         retval = OMX_ErrorBadParameter;
2665         break;
2666     }
2667 
2668     } // switch (color_format)
2669 
2670     if (retval == OMX_ErrorNone)
2671     {
2672         m_omx_color_formattype = color_format;
2673 
2674         retval = set_frame_attributes_swvdec();
2675     }
2676 
2677     return retval;
2678 }
2679 
2680 /**
2681  * @brief Set maximum adaptive playback frame dimensions for OMX component &
2682  *        SwVdec core.
2683  *
2684  * @param[in] width:  Max adaptive playback frame width.
2685  * @param[in] height: Max adaptive playback frame height.
2686  *
2687  * @retval OMX_ERRORTYPE
2688  */
set_adaptive_playback(unsigned int max_width,unsigned int max_height)2689 OMX_ERRORTYPE omx_swvdec::set_adaptive_playback(unsigned int max_width,
2690                                                 unsigned int max_height)
2691 {
2692     OMX_ERRORTYPE retval;
2693 
2694     m_frame_dimensions_max.width  = max_width;
2695     m_frame_dimensions_max.height = max_height;
2696 
2697     OMX_SWVDEC_LOG_HIGH("%d x %d",
2698                         m_frame_dimensions_max.width,
2699                         m_frame_dimensions_max.height);
2700 
2701     retval = set_adaptive_playback_swvdec();
2702 
2703     if (retval == OMX_ErrorNone)
2704     {
2705         retval = set_frame_dimensions(max_width, max_height);
2706     }
2707 
2708     if (retval == OMX_ErrorNone)
2709     {
2710         retval = set_frame_attributes(m_omx_color_formattype);
2711     }
2712 
2713     return retval;
2714 }
2715 
2716 /**
2717  * @brief Get video port format for input or output port.
2718  *
2719  * @param[in,out] p_port_format: Pointer to video port format type.
2720  *
2721  * @retval OMX_ERRORTYPE
2722  */
get_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2723 OMX_ERRORTYPE omx_swvdec::get_video_port_format(
2724     OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2725 {
2726     OMX_ERRORTYPE retval = OMX_ErrorNone;
2727 
2728     if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2729     {
2730         if (p_port_format->nIndex == 0)
2731         {
2732             p_port_format->eColorFormat = OMX_COLOR_FormatUnused;
2733 
2734             p_port_format->eCompressionFormat = m_omx_video_codingtype;
2735 
2736             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2737                                 "compression format 0x%08x",
2738                                 p_port_format->eColorFormat,
2739                                 p_port_format->eCompressionFormat);
2740         }
2741         else
2742         {
2743             OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; "
2744                                 "no more compression formats",
2745                                 p_port_format->nIndex);
2746 
2747             retval = OMX_ErrorNoMore;
2748         }
2749     }
2750     else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2751     {
2752         if (p_port_format->nIndex == 0)
2753         {
2754             p_port_format->eColorFormat =
2755                 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
2756 
2757             p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2758 
2759             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2760                                 "compression format 0x%08x",
2761                                 p_port_format->eColorFormat,
2762                                 p_port_format->eCompressionFormat);
2763         }
2764         else if (p_port_format->nIndex == 1)
2765         {
2766             p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2767 
2768             p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
2769 
2770             OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
2771                                 "compression format 0x%08x",
2772                                 p_port_format->eColorFormat,
2773                                 p_port_format->eCompressionFormat);
2774         }
2775         else
2776         {
2777             OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats",
2778                                 p_port_format->nIndex);
2779 
2780             retval = OMX_ErrorNoMore;
2781         }
2782     }
2783     else
2784     {
2785         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2786                              p_port_format->nPortIndex);
2787 
2788         retval = OMX_ErrorBadPortIndex;
2789     }
2790 
2791     return retval;
2792 }
2793 
2794 /**
2795  * @brief Set video port format for input or output port.
2796  *
2797  * @param[in] p_port_format: Pointer to video port format type.
2798  *
2799  * @retval OMX_ERRORTYPE
2800  */
set_video_port_format(OMX_VIDEO_PARAM_PORTFORMATTYPE * p_port_format)2801 OMX_ERRORTYPE omx_swvdec::set_video_port_format(
2802     OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
2803 {
2804     OMX_ERRORTYPE retval = OMX_ErrorNone;
2805 
2806     if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2807     {
2808         OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; "
2809                             "doing nothing");
2810     }
2811     else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2812     {
2813         retval = set_frame_attributes(p_port_format->eColorFormat);
2814     }
2815     else
2816     {
2817         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
2818                              p_port_format->nPortIndex);
2819 
2820         retval = OMX_ErrorBadPortIndex;
2821     }
2822 
2823     return retval;
2824 }
2825 
2826 /**
2827  * @brief Get port definition for input or output port.
2828  *
2829  * @param[in,out] p_port_def: Pointer to port definition type.
2830  *
2831  * @retval OMX_ERRORTYPE
2832  */
get_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2833 OMX_ERRORTYPE omx_swvdec::get_port_definition(
2834     OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2835 {
2836     OMX_ERRORTYPE retval = OMX_ErrorNone;
2837 
2838     p_port_def->eDomain = OMX_PortDomainVideo;
2839 
2840     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
2841     {
2842         if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
2843             OMX_ErrorNone)
2844         {
2845             goto get_port_definition_exit;
2846         }
2847 
2848         p_port_def->eDir               = OMX_DirInput;
2849         p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual;
2850         p_port_def->nBufferCountMin    = m_port_ip.def.nBufferCountMin;
2851         p_port_def->nBufferSize        = m_port_ip.def.nBufferSize;
2852         p_port_def->bEnabled           = m_port_ip.enabled;
2853         p_port_def->bPopulated         = m_port_ip.populated;
2854 
2855         // VTS uses input port dimensions to set OP dimensions
2856         if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone)
2857         {
2858             goto get_port_definition_exit;
2859         }
2860 
2861         p_port_def->format.video.nFrameWidth  = m_frame_dimensions.width;
2862         p_port_def->format.video.nFrameHeight = m_frame_dimensions.height;
2863 
2864         OMX_SWVDEC_LOG_HIGH("port index %d: "
2865                             "count actual %d, count min %d, size %d, %d x %d",
2866                             p_port_def->nPortIndex,
2867                             p_port_def->nBufferCountActual,
2868                             p_port_def->nBufferCountMin,
2869                             p_port_def->nBufferSize,
2870                             p_port_def->format.video.nFrameWidth,
2871                             p_port_def->format.video.nFrameHeight);
2872 
2873         p_port_def->format.video.eColorFormat       = OMX_COLOR_FormatUnused;
2874         p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype;
2875     }
2876     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
2877     {
2878         if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone)
2879         {
2880             goto get_port_definition_exit;
2881         }
2882 
2883         p_port_def->format.video.nFrameWidth  = m_frame_dimensions.width;
2884         p_port_def->format.video.nFrameHeight = m_frame_dimensions.height;
2885 
2886         if (m_port_reconfig_inprogress)
2887         {
2888             if ((retval = set_frame_attributes(m_omx_color_formattype)) !=
2889                 OMX_ErrorNone)
2890             {
2891                 goto get_port_definition_exit;
2892             }
2893         }
2894 
2895         if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone)
2896         {
2897             goto get_port_definition_exit;
2898         }
2899 
2900         p_port_def->format.video.nStride      = m_frame_attributes.stride;
2901         p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines;
2902 
2903         OMX_SWVDEC_LOG_HIGH("port index %d: "
2904                             "%d x %d, stride %d, sliceheight %d",
2905                             p_port_def->nPortIndex,
2906                             p_port_def->format.video.nFrameWidth,
2907                             p_port_def->format.video.nFrameHeight,
2908                             p_port_def->format.video.nStride,
2909                             p_port_def->format.video.nSliceHeight);
2910 
2911         /**
2912          * Query to SwVdec core for buffer requirements is not allowed in
2913          * executing state since it will overwrite the component's buffer
2914          * requirements updated via the most recent set_parameter().
2915          *
2916          * Buffer requirements communicated to component via set_parameter() are
2917          * not propagated to SwVdec core.
2918          *
2919          * The only execption is if port reconfiguration is in progress, in
2920          * which case the query to SwVdec core is required since buffer
2921          * requirements can change based on new dimensions.
2922          */
2923         if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress)
2924         {
2925             if ((retval =
2926                  get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
2927                 OMX_ErrorNone)
2928             {
2929                 goto get_port_definition_exit;
2930             }
2931         }
2932 
2933         p_port_def->eDir               = OMX_DirOutput;
2934         p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual;
2935         p_port_def->nBufferCountMin    = m_port_op.def.nBufferCountMin;
2936         p_port_def->nBufferSize        = m_port_op.def.nBufferSize;
2937         p_port_def->bEnabled           = m_port_op.enabled;
2938         p_port_def->bPopulated         = m_port_op.populated;
2939 
2940         OMX_SWVDEC_LOG_HIGH("port index %d: "
2941                             "count actual %d, count min %d, size %d",
2942                             p_port_def->nPortIndex,
2943                             p_port_def->nBufferCountActual,
2944                             p_port_def->nBufferCountMin,
2945                             p_port_def->nBufferSize);
2946 
2947         p_port_def->format.video.eColorFormat       = m_omx_color_formattype;
2948         p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
2949 
2950         if (m_omx_color_formattype ==
2951             OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m)
2952         {
2953             OMX_SWVDEC_LOG_HIGH(
2954                 "port index %d: color format '0x%08x': "
2955                 "OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m",
2956                 p_port_def->nPortIndex,
2957                 p_port_def->format.video.eColorFormat);
2958         }
2959         else if (m_omx_color_formattype == OMX_COLOR_FormatYUV420SemiPlanar)
2960         {
2961             OMX_SWVDEC_LOG_HIGH("port index %d: color format '0x%08x': "
2962                                 "OMX_COLOR_FormatYUV420SemiPlanar",
2963                                 p_port_def->nPortIndex,
2964                                 p_port_def->format.video.eColorFormat);
2965         }
2966         else
2967         {
2968             assert(0);
2969             retval = OMX_ErrorUndefined;
2970         }
2971     }
2972     else
2973     {
2974         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
2975 
2976         retval = OMX_ErrorBadPortIndex;
2977     }
2978 
2979 get_port_definition_exit:
2980     return retval;
2981 }
2982 
2983 /**
2984  * @brief Set port definition for input or output port.
2985  *
2986  * @param[in] p_port_def: Pointer to port definition type.
2987  *
2988  * @retval OMX_ERRORTYPE
2989  */
set_port_definition(OMX_PARAM_PORTDEFINITIONTYPE * p_port_def)2990 OMX_ERRORTYPE omx_swvdec::set_port_definition(
2991     OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
2992 {
2993     OMX_ERRORTYPE retval = OMX_ErrorNone;
2994 
2995     OMX_SWVDEC_LOG_HIGH("port index %d: "
2996                         "count actual %d, count min %d, size %d",
2997                         p_port_def->nPortIndex,
2998                         p_port_def->nBufferCountActual,
2999                         p_port_def->nBufferCountMin,
3000                         p_port_def->nBufferSize);
3001 
3002     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
3003     {
3004         m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual;
3005         m_port_ip.def.nBufferCountMin    = p_port_def->nBufferCountMin;
3006         m_port_ip.def.nBufferSize        = p_port_def->nBufferSize;
3007     }
3008     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
3009     {
3010         /**
3011          * OMX component's output port nBufferSize is not updated based on what
3012          * IL client sends; instead it is updated based on the possibly updated
3013          * frame attributes.
3014          *
3015          * This is because set_parameter() for output port definition only has
3016          * updates to buffer counts or frame dimensions.
3017          */
3018 
3019         m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual;
3020 
3021         OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d",
3022                             p_port_def->nPortIndex,
3023                             p_port_def->format.video.nFrameWidth,
3024                             p_port_def->format.video.nFrameHeight);
3025 
3026         /**
3027          * Update frame dimensions & attributes if:
3028          *
3029          * 1. not in adaptive playback mode
3030          *    OR
3031          * 2. new frame dimensions greater than adaptive playback mode's
3032          *    max frame dimensions
3033          */
3034 
3035         if ((m_adaptive_playback_mode == false) ||
3036             (p_port_def->format.video.nFrameWidth >
3037              m_frame_dimensions_max.width) ||
3038             (p_port_def->format.video.nFrameHeight >
3039              m_frame_dimensions_max.height))
3040         {
3041             OMX_SWVDEC_LOG_HIGH("updating frame dimensions & attributes");
3042 
3043             if ((retval =
3044                  set_frame_dimensions(p_port_def->format.video.nFrameWidth,
3045                                       p_port_def->format.video.nFrameHeight)) !=
3046                 OMX_ErrorNone)
3047             {
3048                 goto set_port_definition_exit;
3049             }
3050 
3051             if ((retval = set_frame_attributes(m_omx_color_formattype)) !=
3052                 OMX_ErrorNone)
3053             {
3054                 goto set_port_definition_exit;
3055             }
3056 
3057             // nBufferSize updated based on (possibly new) frame attributes
3058 
3059             m_port_op.def.nBufferSize = m_frame_attributes.size;
3060         }
3061         else
3062         {
3063             OMX_SWVDEC_LOG_HIGH("not updating frame dimensions & attributes");
3064         }
3065     }
3066     else
3067     {
3068         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
3069 
3070         retval = OMX_ErrorBadPortIndex;
3071     }
3072 
3073 set_port_definition_exit:
3074     return retval;
3075 }
3076 
3077 /**
3078  * @brief Get supported profile & level.
3079  *
3080  * The supported profiles & levels are not queried from SwVdec core, but
3081  * hard-coded. This should ideally be replaced with a query to SwVdec core.
3082  *
3083  * @param[in,out] p_profilelevel: Pointer to video profile & level type.
3084  *
3085  * @retval OMX_ERRORTYPE
3086  */
get_supported_profilelevel(OMX_VIDEO_PARAM_PROFILELEVELTYPE * p_profilelevel)3087 OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel(
3088     OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel)
3089 {
3090     OMX_ERRORTYPE retval = OMX_ErrorNone;
3091 
3092     if (p_profilelevel == NULL)
3093     {
3094         OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL");
3095 
3096         retval = OMX_ErrorBadParameter;
3097         goto get_supported_profilelevel_exit;
3098     }
3099 
3100     if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP)
3101     {
3102         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
3103                              p_profilelevel->nPortIndex);
3104 
3105         retval = OMX_ErrorBadPortIndex;
3106         goto get_supported_profilelevel_exit;
3107     }
3108 
3109     if (m_omx_video_codingtype == OMX_VIDEO_CodingH263)
3110     {
3111         if (p_profilelevel->nProfileIndex == 0)
3112         {
3113             p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
3114             p_profilelevel->eLevel   = OMX_VIDEO_H263Level70;
3115 
3116             OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70");
3117         }
3118         else
3119         {
3120             OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
3121                                 "no more profiles",
3122                                 p_profilelevel->nProfileIndex);
3123 
3124             retval = OMX_ErrorNoMore;
3125         }
3126     }
3127     else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) ||
3128              (m_omx_video_codingtype ==
3129               ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)))
3130     {
3131         if (p_profilelevel->nProfileIndex == 0)
3132         {
3133             p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
3134             p_profilelevel->eLevel   = OMX_VIDEO_MPEG4Level6;
3135 
3136             OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 6");
3137         }
3138         else if (p_profilelevel->nProfileIndex == 1)
3139         {
3140             p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
3141             p_profilelevel->eLevel   = OMX_VIDEO_MPEG4Level5;
3142 
3143             OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5");
3144         }
3145         else
3146         {
3147             OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
3148                                 "no more profiles",
3149                                 p_profilelevel->nProfileIndex);
3150 
3151             retval = OMX_ErrorNoMore;
3152         }
3153     }
3154     else
3155     {
3156         assert(0);
3157         retval = OMX_ErrorUndefined;
3158     }
3159 
3160 get_supported_profilelevel_exit:
3161     return retval;
3162 }
3163 
3164 /**
3165  * @brief Describe color format.
3166  *
3167  * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure.
3168  *
3169  * @retval OMX_ERRORTYPE
3170  */
describe_color_format(DescribeColorFormatParams * p_params)3171 OMX_ERRORTYPE omx_swvdec::describe_color_format(
3172     DescribeColorFormatParams *p_params)
3173 {
3174     OMX_ERRORTYPE retval = OMX_ErrorNone;
3175 
3176     if (p_params == NULL)
3177     {
3178         OMX_SWVDEC_LOG_ERROR("p_params = NULL");
3179 
3180         retval = OMX_ErrorBadParameter;
3181     }
3182     else
3183     {
3184         MediaImage *p_img = &p_params->sMediaImage;
3185 
3186         switch (p_params->eColorFormat)
3187         {
3188 
3189         case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m:
3190         {
3191             size_t stride, scanlines;
3192 
3193             p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3194             p_img->mNumPlanes = 3;
3195 
3196             p_img->mWidth  = p_params->nFrameWidth;
3197             p_img->mHeight = p_params->nFrameHeight;
3198 
3199             /**
3200              * alignment factors:
3201              *
3202              * - stride:    128
3203              * - scanlines:  32
3204              */
3205             stride    = ALIGN(p_img->mWidth,  128);
3206             scanlines = ALIGN(p_img->mHeight,  32);
3207 
3208             p_img->mBitDepth = 8;
3209 
3210             // plane 0 (Y)
3211             p_img->mPlane[MediaImage::Y].mOffset = 0;
3212             p_img->mPlane[MediaImage::Y].mColInc = 1;
3213             p_img->mPlane[MediaImage::Y].mRowInc = stride;
3214             p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
3215             p_img->mPlane[MediaImage::Y].mVertSubsampling  = 1;
3216 
3217             // plane 1 (U)
3218             p_img->mPlane[MediaImage::U].mOffset = stride * scanlines;
3219             p_img->mPlane[MediaImage::U].mColInc = 2;
3220             p_img->mPlane[MediaImage::U].mRowInc = stride;
3221             p_img->mPlane[MediaImage::U].mHorizSubsampling = 2;
3222             p_img->mPlane[MediaImage::U].mVertSubsampling  = 2;
3223 
3224             // plane 2 (V)
3225             p_img->mPlane[MediaImage::V].mOffset = stride * scanlines + 1;
3226             p_img->mPlane[MediaImage::V].mColInc = 2;
3227             p_img->mPlane[MediaImage::V].mRowInc = stride;
3228             p_img->mPlane[MediaImage::V].mHorizSubsampling = 2;
3229             p_img->mPlane[MediaImage::V].mVertSubsampling  = 2;
3230 
3231             break;
3232         }
3233 
3234         case OMX_COLOR_FormatYUV420SemiPlanar:
3235         {
3236             // do nothing; standard OMX color formats should not be described
3237             retval = OMX_ErrorUnsupportedSetting;
3238             break;
3239         }
3240 
3241         default:
3242         {
3243             OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported",
3244                                  p_params->eColorFormat);
3245 
3246             p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3247 
3248             retval = OMX_ErrorBadParameter;
3249             break;
3250         }
3251 
3252         } // switch (p_params->eColorFormat)
3253     }
3254 
3255     return retval;
3256 }
3257 
3258 /**
3259  * @brief Set QTI vendor-specific port definition for input or output port.
3260  *
3261  * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type.
3262  *
3263  * @retval OMX_ERRORTYPE
3264  */
set_port_definition_qcom(OMX_QCOM_PARAM_PORTDEFINITIONTYPE * p_port_def)3265 OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom(
3266     OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def)
3267 {
3268     OMX_ERRORTYPE retval = OMX_ErrorNone;
3269 
3270     if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
3271     {
3272         switch (p_port_def->nFramePackingFormat)
3273         {
3274 
3275         case OMX_QCOM_FramePacking_Arbitrary:
3276         {
3277             OMX_SWVDEC_LOG_HIGH("OMX_QCOM_FramePacking_Arbitrary");
3278 
3279             m_arbitrary_bytes_mode = true;
3280 
3281             break;
3282         }
3283 
3284         case OMX_QCOM_FramePacking_OnlyOneCompleteFrame:
3285         {
3286             OMX_SWVDEC_LOG_HIGH(
3287                 "OMX_QCOM_FramePacking_OnlyOneCompleteFrame");
3288 
3289             break;
3290         }
3291 
3292         default:
3293         {
3294             OMX_SWVDEC_LOG_ERROR(
3295                 "frame packing format '%d' unsupported",
3296                 p_port_def->nFramePackingFormat);
3297 
3298             retval = OMX_ErrorUnsupportedSetting;
3299             break;
3300         }
3301 
3302         }
3303     }
3304     else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
3305     {
3306         OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d",
3307                             p_port_def->nMemRegion,
3308                             p_port_def->nCacheAttr);
3309     }
3310     else
3311     {
3312         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
3313                              p_port_def->nPortIndex);
3314 
3315         retval = OMX_ErrorBadPortIndex;
3316     }
3317 
3318     return retval;
3319 }
3320 
3321 /**
3322  * @brief Set SwVdec frame dimensions based on OMX component frame dimensions.
3323  *
3324  * @retval OMX_ERRORTYPE
3325  */
set_frame_dimensions_swvdec()3326 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec()
3327 {
3328     OMX_ERRORTYPE retval = OMX_ErrorNone;
3329 
3330     SWVDEC_PROPERTY property;
3331 
3332     SWVDEC_STATUS retval_swvdec;
3333 
3334     property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3335 
3336     property.info.frame_dimensions.width  = m_frame_dimensions.width;
3337     property.info.frame_dimensions.height = m_frame_dimensions.height;
3338 
3339     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3340         SWVDEC_STATUS_SUCCESS)
3341     {
3342         retval = retval_swvdec2omx(retval_swvdec);
3343     }
3344 
3345     return retval;
3346 }
3347 
3348 /**
3349  * @brief Set SwVdec frame attributes based on OMX component frame attributes.
3350  *
3351  * @retval OMX_ERRORTYPE
3352  */
set_frame_attributes_swvdec()3353 OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec()
3354 {
3355     OMX_ERRORTYPE retval = OMX_ErrorNone;
3356 
3357     SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes;
3358 
3359     SWVDEC_PROPERTY property;
3360 
3361     SWVDEC_STATUS retval_swvdec;
3362 
3363     p_frame_attributes = &property.info.frame_attributes;
3364 
3365     property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3366 
3367     if(m_omx_color_formattype == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m)
3368         p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12_32;
3369     else
3370         p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12;
3371 
3372     p_frame_attributes->stride    = m_frame_attributes.stride;
3373     p_frame_attributes->scanlines = m_frame_attributes.scanlines;
3374     p_frame_attributes->size      = m_frame_attributes.size;
3375 
3376     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3377         SWVDEC_STATUS_SUCCESS)
3378     {
3379         retval = retval_swvdec2omx(retval_swvdec);
3380     }
3381 
3382     return retval;
3383 }
3384 
3385 /**
3386  * @brief Set maximum adaptive playback frame dimensions for SwVdec core.
3387  */
set_adaptive_playback_swvdec()3388 OMX_ERRORTYPE omx_swvdec::set_adaptive_playback_swvdec()
3389 {
3390     OMX_ERRORTYPE retval = OMX_ErrorNone;
3391 
3392     SWVDEC_PROPERTY property;
3393 
3394     SWVDEC_STATUS retval_swvdec;
3395 
3396     property.id = SWVDEC_PROPERTY_ID_ADAPTIVE_PLAYBACK;
3397 
3398     property.info.frame_dimensions.width  = m_frame_dimensions_max.width;
3399     property.info.frame_dimensions.height = m_frame_dimensions_max.height;
3400 
3401     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3402         SWVDEC_STATUS_SUCCESS)
3403     {
3404         retval = retval_swvdec2omx(retval_swvdec);
3405     }
3406 
3407     return retval;
3408 }
3409 
3410 /**
3411  * @brief Set thumbnail mode for SwVdec core.
3412  */
set_thumbnail_mode_swvdec()3413 OMX_ERRORTYPE omx_swvdec::set_thumbnail_mode_swvdec()
3414 {
3415     OMX_ERRORTYPE retval = OMX_ErrorNone;
3416 
3417     SWVDEC_PROPERTY property;
3418 
3419     SWVDEC_STATUS retval_swvdec;
3420 
3421     property.id = SWVDEC_PROPERTY_ID_THUMBNAIL_MODE;
3422 
3423     if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
3424         SWVDEC_STATUS_SUCCESS)
3425     {
3426         retval = retval_swvdec2omx(retval_swvdec);
3427     }
3428 
3429     return retval;
3430 }
3431 
3432 /**
3433  * @brief Get SwVdec frame dimensions and set OMX component frame dimensions.
3434  *
3435  * @retval OMX_ERRORTYPE
3436  */
get_frame_dimensions_swvdec()3437 OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec()
3438 {
3439     OMX_ERRORTYPE retval = OMX_ErrorNone;
3440 
3441     SWVDEC_PROPERTY property;
3442 
3443     SWVDEC_STATUS retval_swvdec;
3444 
3445     property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
3446 
3447     if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3448         SWVDEC_STATUS_SUCCESS)
3449     {
3450         retval = retval_swvdec2omx(retval_swvdec);
3451     }
3452     else
3453     {
3454         m_frame_dimensions.width  = property.info.frame_dimensions.width;
3455         m_frame_dimensions.height = property.info.frame_dimensions.height;
3456     }
3457 
3458     return retval;
3459 }
3460 
3461 /**
3462  * @brief Get SwVdec frame attributes and set OMX component frame attributes.
3463  *
3464  * @retval OMX_ERRORTYPE
3465  */
get_frame_attributes_swvdec()3466 OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec()
3467 {
3468     OMX_ERRORTYPE retval = OMX_ErrorNone;
3469 
3470     SWVDEC_PROPERTY property;
3471 
3472     SWVDEC_STATUS retval_swvdec;
3473 
3474     property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
3475 
3476     if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3477         SWVDEC_STATUS_SUCCESS)
3478     {
3479         retval = retval_swvdec2omx(retval_swvdec);
3480     }
3481     else
3482     {
3483         m_frame_attributes.stride    = property.info.frame_attributes.stride;
3484         m_frame_attributes.scanlines = property.info.frame_attributes.scanlines;
3485         m_frame_attributes.size      = property.info.frame_attributes.size;
3486     }
3487 
3488     return retval;
3489 }
3490 
3491 /**
3492  * @brief Get SwVdec buffer requirements; set input or output port definitions.
3493  *
3494  * @param[in] port_index: Port index.
3495  *
3496  * @retval OMX_ERRORTYPE
3497  */
get_buffer_requirements_swvdec(unsigned int port_index)3498 OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec(
3499     unsigned int port_index)
3500 {
3501     OMX_ERRORTYPE retval = OMX_ErrorNone;
3502 
3503     SWVDEC_PROPERTY property;
3504 
3505     SWVDEC_STATUS retval_swvdec;
3506 
3507     SWVDEC_BUFFER_REQ *p_buffer_req;
3508 
3509     if (port_index == OMX_CORE_PORT_INDEX_IP)
3510     {
3511         property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP;
3512 
3513         p_buffer_req = &property.info.buffer_req_ip;
3514 
3515         if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3516             SWVDEC_STATUS_SUCCESS)
3517         {
3518             retval = retval_swvdec2omx(retval_swvdec);
3519             goto get_buffer_requirements_swvdec_exit;
3520         }
3521 
3522         m_port_ip.def.nBufferSize        = p_buffer_req->size;
3523         m_port_ip.def.nBufferCountMin    = p_buffer_req->mincount;
3524         m_port_ip.def.nBufferCountActual = MAX((MAX(p_buffer_req->mincount,
3525                                                OMX_SWVDEC_IP_BUFFER_COUNT_MIN)),
3526                                                m_port_ip.def.nBufferCountActual);
3527         m_port_ip.def.nBufferAlignment   = p_buffer_req->alignment;
3528 
3529         OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned",
3530                             m_port_ip.def.nBufferSize,
3531                             m_port_ip.def.nBufferCountActual,
3532                             m_port_ip.def.nBufferAlignment);
3533     }
3534     else if (port_index == OMX_CORE_PORT_INDEX_OP)
3535     {
3536         property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP;
3537 
3538         p_buffer_req = &property.info.buffer_req_op;
3539 
3540         if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
3541             SWVDEC_STATUS_SUCCESS)
3542         {
3543             retval = retval_swvdec2omx(retval_swvdec);
3544             goto get_buffer_requirements_swvdec_exit;
3545         }
3546 
3547         if (m_sync_frame_decoding_mode)
3548         {
3549             p_buffer_req->mincount = 1;
3550         }
3551 
3552         m_port_op.def.nBufferSize        = p_buffer_req->size;
3553         m_port_op.def.nBufferCountMin    = p_buffer_req->mincount;
3554         m_port_op.def.nBufferCountActual = MAX(p_buffer_req->mincount,
3555                                                m_port_op.def.nBufferCountActual);
3556         m_port_op.def.nBufferAlignment   = p_buffer_req->alignment;
3557 
3558         OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned",
3559                             m_port_op.def.nBufferSize,
3560                             m_port_op.def.nBufferCountActual,
3561                             m_port_op.def.nBufferAlignment);
3562     }
3563     else
3564     {
3565         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index);
3566 
3567         retval = OMX_ErrorBadPortIndex;
3568     }
3569 
3570 get_buffer_requirements_swvdec_exit:
3571     return retval;
3572 }
3573 
3574 /**
3575  * @brief Allocate input buffer, and input buffer info array if ncessary.
3576  *
3577  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3578  *                               structure.
3579  * @param[in]     p_app_data:    Pointer to IL client app data.
3580  * @param[in]     size:          Size of buffer to be allocated in bytes.
3581  *
3582  * @retval OMX_ERRORTYPE
3583  */
buffer_allocate_ip(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3584 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip(
3585     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3586     OMX_PTR                p_app_data,
3587     OMX_U32                size)
3588 {
3589     OMX_ERRORTYPE retval = OMX_ErrorNone;
3590     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
3591 
3592     unsigned int ii;
3593 
3594     if (size != m_port_ip.def.nBufferSize)
3595     {
3596         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3597                              "configured size (%d bytes)",
3598                              size,
3599                              m_port_ip.def.nBufferSize);
3600 
3601         return OMX_ErrorBadParameter;
3602     }
3603 
3604     if (m_buffer_array_ip == NULL)
3605     {
3606         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3607                             m_port_ip.def.nBufferCountActual,
3608                             (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3609 
3610         if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone)
3611         {
3612             return retval;
3613         }
3614     }
3615 
3616     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3617     {
3618         if (m_buffer_array_ip[ii].buffer_populated == false)
3619         {
3620             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3621             break;
3622         }
3623     }
3624 
3625     if (ii < m_port_ip.def.nBufferCountActual)
3626     {
3627         int pmem_fd = -1;
3628 
3629         unsigned char *bufferaddr;
3630 
3631         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated",
3632                             ii,
3633                             size);
3634 
3635         m_buffer_array_ip[ii].ion_info.dev_fd=
3636             ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info,size,
3637                                   m_port_ip.def.nBufferAlignment);
3638 
3639         if (m_buffer_array_ip[ii].ion_info.dev_fd< 0)
3640         {
3641             return OMX_ErrorInsufficientResources;
3642         }
3643 
3644         pmem_fd = m_buffer_array_ip[ii].ion_info.data_fd;
3645 
3646         bufferaddr = ion_map(pmem_fd,size);
3647 
3648         if (bufferaddr == MAP_FAILED)
3649         {
3650             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d error %s",
3651                                  pmem_fd,
3652                                  size, strerror(errno));
3653 
3654             close(pmem_fd);
3655             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3656 
3657             return OMX_ErrorInsufficientResources;
3658         }
3659 
3660         *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3661 
3662         m_buffer_array_ip[ii].buffer_payload.bufferaddr  = bufferaddr;
3663         m_buffer_array_ip[ii].buffer_payload.pmem_fd     = pmem_fd;
3664         m_buffer_array_ip[ii].buffer_payload.buffer_len  = size;
3665         m_buffer_array_ip[ii].buffer_payload.mmaped_size = size;
3666         m_buffer_array_ip[ii].buffer_payload.offset      = 0;
3667 
3668         m_buffer_array_ip[ii].buffer_swvdec.p_buffer      = bufferaddr;
3669         m_buffer_array_ip[ii].buffer_swvdec.size          = size;
3670         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3671             (void *) ((unsigned long) ii);
3672         m_buffer_array_ip[ii].buffer_swvdec.fd = pmem_fd;
3673 
3674         m_buffer_array_ip[ii].buffer_populated = true;
3675 
3676         if(m_swvdec_codec == SWVDEC_CODEC_VC1)
3677         {
3678             OMX_SWVDEC_LOG_LOW("map ip buffer");
3679 
3680             if((retval_swvdec = swvdec_register_buffer(m_swvdec_handle,
3681                                                        &m_buffer_array_ip[ii].buffer_swvdec))
3682                != SWVDEC_STATUS_SUCCESS)
3683             {
3684                 OMX_SWVDEC_LOG_ERROR("swvdec_map failed for ip buffer %d: %p",ii,bufferaddr);
3685 
3686                 close(pmem_fd);
3687                 ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3688 
3689                 return retval_swvdec2omx(retval_swvdec);
3690             }
3691         }
3692 
3693         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, fd = %d %d bytes",
3694                             ii,
3695                             bufferaddr,
3696                             pmem_fd,
3697                             size);
3698 
3699         (*pp_buffer_hdr)->pBuffer           = (OMX_U8 *) bufferaddr;
3700         (*pp_buffer_hdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
3701         (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
3702         (*pp_buffer_hdr)->nAllocLen         = size;
3703         (*pp_buffer_hdr)->pAppPrivate       = p_app_data;
3704         (*pp_buffer_hdr)->nInputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3705         (*pp_buffer_hdr)->pInputPortPrivate =
3706             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3707 
3708         m_port_ip.populated   = port_ip_populated();
3709         m_port_ip.unpopulated = OMX_FALSE;
3710     }
3711     else
3712     {
3713         OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated",
3714                              m_port_ip.def.nBufferCountActual);
3715 
3716         return OMX_ErrorInsufficientResources;
3717     }
3718 
3719     return retval;
3720 }
3721 
3722 /**
3723  * @brief Allocate output buffer, and output buffer info array if necessary.
3724  *
3725  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3726  *                               structure.
3727  * @param[in]     p_app_data:    Pointer to IL client app data.
3728  * @param[in]     size:          Size of buffer to be allocated in bytes.
3729  *
3730  * @retval OMX_ERRORTYPE
3731  */
buffer_allocate_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3732 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op(
3733     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3734     OMX_PTR                p_app_data,
3735     OMX_U32                size)
3736 {
3737     OMX_ERRORTYPE retval = OMX_ErrorNone;
3738     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
3739     unsigned int ii;
3740 
3741     if (size != m_port_op.def.nBufferSize)
3742     {
3743         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3744                              "configured size (%d bytes)",
3745                              size,
3746                              m_port_op.def.nBufferSize);
3747 
3748         return OMX_ErrorBadParameter;
3749     }
3750 
3751     if (m_buffer_array_op == NULL)
3752     {
3753         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3754                             m_port_op.def.nBufferCountActual,
3755                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3756 
3757         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3758         {
3759             return retval;
3760         }
3761     }
3762 
3763     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3764     {
3765         if (m_buffer_array_op[ii].buffer_populated == false)
3766         {
3767             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3768             break;
3769         }
3770     }
3771 
3772     if (ii < m_port_op.def.nBufferCountActual)
3773     {
3774         int pmem_fd = -1;
3775 
3776         unsigned char *bufferaddr;
3777 
3778         OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated",
3779                             ii,
3780                             size);
3781 
3782         m_buffer_array_op[ii].ion_info.dev_fd=
3783             ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info,size,
3784                                  m_port_op.def.nBufferAlignment);
3785 
3786         if (m_buffer_array_op[ii].ion_info.dev_fd < 0)
3787         {
3788             return OMX_ErrorInsufficientResources;
3789         }
3790 
3791         pmem_fd = m_buffer_array_op[ii].ion_info.data_fd;
3792 
3793         bufferaddr = ion_map(pmem_fd,size);
3794 
3795         if (bufferaddr == MAP_FAILED)
3796         {
3797             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3798                                  pmem_fd,
3799                                  size);
3800 
3801             close(pmem_fd);
3802             ion_memory_free(&m_buffer_array_op[ii].ion_info);
3803 
3804             return OMX_ErrorInsufficientResources;
3805         }
3806 
3807         *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3808 
3809         m_buffer_array_op[ii].buffer_payload.bufferaddr  = bufferaddr;
3810         m_buffer_array_op[ii].buffer_payload.pmem_fd     = pmem_fd;
3811         m_buffer_array_op[ii].buffer_payload.buffer_len  = size;
3812         m_buffer_array_op[ii].buffer_payload.mmaped_size = size;
3813         m_buffer_array_op[ii].buffer_payload.offset      = 0;
3814 
3815         m_buffer_array_op[ii].buffer_swvdec.p_buffer      = bufferaddr;
3816         m_buffer_array_op[ii].buffer_swvdec.size          = size;
3817         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3818             (void *) ((unsigned long) ii);
3819 
3820         m_buffer_array_op[ii].buffer_populated = true;
3821 
3822         m_buffer_array_op[ii].buffer_swvdec.fd            = pmem_fd ;
3823 
3824         if(m_swvdec_codec == SWVDEC_CODEC_VC1)
3825         {
3826             OMX_SWVDEC_LOG_LOW("map op buffer");
3827 
3828             if((retval_swvdec = swvdec_map(m_swvdec_handle,&m_buffer_array_op[ii].buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
3829             {
3830                 OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,bufferaddr);
3831 
3832                 close(pmem_fd);
3833                 ion_memory_free(&m_buffer_array_op[ii].ion_info);
3834 
3835                 return retval_swvdec2omx(retval_swvdec);
3836             }
3837         }
3838         OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, fd = %d %d bytes",
3839                             ii,
3840                             bufferaddr,
3841                             pmem_fd,
3842                             size);
3843 
3844         (*pp_buffer_hdr)->pBuffer            = (OMX_U8 *) bufferaddr;
3845         (*pp_buffer_hdr)->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3846         (*pp_buffer_hdr)->nVersion.nVersion  = OMX_SPEC_VERSION;
3847         (*pp_buffer_hdr)->nAllocLen          = size;
3848         (*pp_buffer_hdr)->pAppPrivate        = p_app_data;
3849         (*pp_buffer_hdr)->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3850         (*pp_buffer_hdr)->pOutputPortPrivate =
3851             (void *) &(m_buffer_array_op[ii].buffer_payload);
3852 
3853         m_port_op.populated   = port_op_populated();
3854         m_port_op.unpopulated = OMX_FALSE;
3855     }
3856     else
3857     {
3858         OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated",
3859                              m_port_op.def.nBufferCountActual);
3860 
3861         retval = OMX_ErrorInsufficientResources;
3862     }
3863 
3864     return retval;
3865 }
3866 
3867 /**
3868  * @brief Allocate input buffer info array.
3869  */
buffer_allocate_ip_info_array()3870 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array()
3871 {
3872     OMX_ERRORTYPE retval = OMX_ErrorNone;
3873 
3874     unsigned int ii;
3875 
3876     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3877 
3878     if (m_buffer_array_ip != NULL)
3879     {
3880         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3881 
3882         retval = OMX_ErrorInsufficientResources;
3883         goto buffer_allocate_ip_info_array_exit;
3884     }
3885 
3886     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3887                         m_port_ip.def.nBufferCountActual,
3888                         (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3889 
3890     m_buffer_array_ip =
3891         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3892                                           m_port_ip.def.nBufferCountActual);
3893 
3894     if (m_buffer_array_ip == NULL)
3895     {
3896         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3897                              "%d element%s, %zu bytes requested",
3898                              m_port_ip.def.nBufferCountActual,
3899                              (m_port_ip.def.nBufferCountActual > 1) ? "s" : "",
3900                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3901                              m_port_ip.def.nBufferCountActual);
3902 
3903         retval = OMX_ErrorInsufficientResources;
3904         goto buffer_allocate_ip_info_array_exit;
3905     }
3906 
3907     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3908     {
3909         p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3910 
3911         // reset file descriptors
3912 
3913         m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3914         m_buffer_array_ip[ii].ion_info.dev_fd= -1;
3915 
3916         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3917             (void *) ((unsigned long) ii);
3918 
3919         p_buffer_hdr->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
3920         p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
3921         p_buffer_hdr->nInputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3922         p_buffer_hdr->pInputPortPrivate =
3923             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3924     }
3925 
3926 buffer_allocate_ip_info_array_exit:
3927     return retval;
3928 }
3929 
3930 /**
3931  * @brief Allocate output buffer info array.
3932  */
buffer_allocate_op_info_array()3933 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array()
3934 {
3935     OMX_ERRORTYPE retval = OMX_ErrorNone;
3936 
3937     unsigned int ii;
3938 
3939     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3940 
3941     if (m_buffer_array_op != NULL)
3942     {
3943         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3944 
3945         retval = OMX_ErrorInsufficientResources;
3946         goto buffer_allocate_op_info_array_exit;
3947     }
3948 
3949     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3950                         m_port_op.def.nBufferCountActual,
3951                         (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3952 
3953     m_buffer_array_op =
3954         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3955                                           m_port_op.def.nBufferCountActual);
3956 
3957     if (m_buffer_array_op == NULL)
3958     {
3959         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3960                              "%d element%s, %zu bytes requested",
3961                              m_port_op.def.nBufferCountActual,
3962                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
3963                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3964                              m_port_op.def.nBufferCountActual);
3965 
3966         retval = OMX_ErrorInsufficientResources;
3967         goto buffer_allocate_op_info_array_exit;
3968     }
3969 
3970     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3971     {
3972         p_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3973 
3974         // reset file descriptors
3975 
3976         m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3977         m_buffer_array_op[ii].ion_info.dev_fd = -1;
3978 
3979         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3980             (void *) ((unsigned long) ii);
3981 
3982         p_buffer_hdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3983         p_buffer_hdr->nVersion.nVersion  = OMX_SPEC_VERSION;
3984         p_buffer_hdr->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3985         p_buffer_hdr->pOutputPortPrivate =
3986             (void *) &(m_buffer_array_op[ii].buffer_payload);
3987     }
3988 
3989 buffer_allocate_op_info_array_exit:
3990     return retval;
3991 }
3992 
3993 /**
3994  * @brief Use buffer allocated by IL client; allocate output buffer info array
3995  *        if necessary.
3996  *
3997  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3998  *                               structure.
3999  * @param[in]     p_app_data:    Pointer to IL client app data.
4000  * @param[in]     size:          Size of buffer to be allocated in bytes.
4001  * @param[in]     p_buffer:      Pointer to buffer to be used.
4002  *
4003  * @retval OMX_ERRORTYPE
4004  */
buffer_use_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size,OMX_U8 * p_buffer)4005 OMX_ERRORTYPE omx_swvdec::buffer_use_op(
4006     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
4007     OMX_PTR                p_app_data,
4008     OMX_U32                size,
4009     OMX_U8                *p_buffer)
4010 {
4011     OMX_ERRORTYPE retval = OMX_ErrorNone;
4012     SWVDEC_STATUS retval_swvdec;
4013     unsigned int ii;
4014 
4015     (void) size;
4016 
4017     if (m_buffer_array_op == NULL)
4018     {
4019         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
4020                             m_port_op.def.nBufferCountActual,
4021                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
4022 
4023         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
4024         {
4025             goto buffer_use_op_exit;
4026         }
4027     }
4028 
4029     if (m_meta_buffer_mode && (m_meta_buffer_array == NULL))
4030     {
4031         OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s",
4032                             m_port_op.def.nBufferCountActual,
4033                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
4034 
4035         if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone)
4036         {
4037             goto buffer_use_op_exit;
4038         }
4039     }
4040 
4041     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4042     {
4043         if (m_buffer_array_op[ii].buffer_populated == false)
4044         {
4045             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
4046             break;
4047         }
4048     }
4049 
4050     if (ii < m_port_op.def.nBufferCountActual)
4051     {
4052         struct vdec_bufferpayload *p_buffer_payload;
4053 
4054         SWVDEC_BUFFER *p_buffer_swvdec;
4055 
4056         *pp_buffer_hdr   = &m_buffer_array_op[ii].buffer_header;
4057         p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
4058         p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4059 
4060         if (m_meta_buffer_mode)
4061         {
4062             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
4063             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
4064 
4065             m_buffer_array_op[ii].buffer_populated = true;
4066 
4067             (*pp_buffer_hdr)->pBuffer     = p_buffer;
4068             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
4069             (*pp_buffer_hdr)->nAllocLen   =
4070                 sizeof(struct VideoDecoderOutputMetaData);
4071 
4072             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)",
4073                                 ii,
4074                                 *pp_buffer_hdr);
4075 
4076             m_port_op.populated   = port_op_populated();
4077             m_port_op.unpopulated = OMX_FALSE;
4078         }
4079         else if (m_android_native_buffers)
4080         {
4081             private_handle_t *p_handle;
4082 
4083             OMX_U8 *p_buffer_mapped;
4084 
4085             p_handle = (private_handle_t *) p_buffer;
4086 
4087             if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize)
4088             {
4089                 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
4090                                      "configured size (%d bytes)",
4091                                      p_handle->size,
4092                                      m_port_op.def.nBufferSize);
4093 
4094                 retval = OMX_ErrorBadParameter;
4095                 goto buffer_use_op_exit;
4096             }
4097 
4098             m_port_op.def.nBufferSize = p_handle->size;
4099 
4100             p_buffer_mapped = ion_map(p_handle->fd,p_handle->size);
4101 
4102             if (p_buffer_mapped == MAP_FAILED)
4103             {
4104                 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
4105                                      p_handle->fd,
4106                                      p_handle->size);
4107 
4108                 retval = OMX_ErrorInsufficientResources;
4109                 goto buffer_use_op_exit;
4110             }
4111 
4112             p_buffer_payload->bufferaddr  = p_buffer_mapped;
4113             p_buffer_payload->pmem_fd     = p_handle->fd;
4114             p_buffer_payload->buffer_len  = p_handle->size;
4115             p_buffer_payload->mmaped_size = p_handle->size;
4116             p_buffer_payload->offset      = 0;
4117 
4118             p_buffer_swvdec->p_buffer      = p_buffer_mapped;
4119             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
4120             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
4121             p_buffer_swvdec->fd            = p_buffer_payload->pmem_fd ;
4122 
4123             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4124             {
4125                 OMX_SWVDEC_LOG_LOW("map op buffer");
4126 
4127                 if((retval_swvdec = swvdec_map(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4128                 {
4129                     OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,p_buffer_mapped);
4130                     retval = retval_swvdec2omx(retval_swvdec);;
4131                     goto buffer_use_op_exit;
4132                 }
4133             }
4134             m_buffer_array_op[ii].buffer_populated = true;
4135 
4136             (*pp_buffer_hdr)->pBuffer     = (m_android_native_buffers ?
4137                                              ((OMX_U8 *) p_handle) :
4138                                              p_buffer_mapped);
4139             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
4140             (*pp_buffer_hdr)->nAllocLen   = m_port_op.def.nBufferSize;
4141 
4142             m_buffer_array_op[ii].ion_info.data_fd = p_handle->fd;
4143 
4144             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p",
4145                                 ii,
4146                                 *pp_buffer_hdr);
4147 
4148             m_port_op.populated   = port_op_populated();
4149             m_port_op.unpopulated = OMX_FALSE;
4150         }
4151         else
4152         {
4153             OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor "
4154                                  "'android native buffers' enabled");
4155 
4156             retval = OMX_ErrorBadParameter;
4157         }
4158     }
4159     else
4160     {
4161         OMX_SWVDEC_LOG_ERROR("all %d op buffers populated",
4162                              m_port_op.def.nBufferCountActual);
4163 
4164         retval = OMX_ErrorInsufficientResources;
4165     }
4166 
4167 buffer_use_op_exit:
4168     return retval;
4169 }
4170 
4171 /**
4172  * @brief De-allocate input buffer.
4173  *
4174  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
4175  *
4176  * @retval OMX_ERRORTYPE
4177  */
buffer_deallocate_ip(OMX_BUFFERHEADERTYPE * p_buffer_hdr)4178 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip(
4179     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4180 {
4181     OMX_ERRORTYPE retval = OMX_ErrorNone;
4182     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
4183 
4184     unsigned int ii;
4185 
4186     if (p_buffer_hdr == NULL)
4187     {
4188         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
4189 
4190         retval = OMX_ErrorBadParameter;
4191         goto buffer_deallocate_ip_exit;
4192     }
4193     else if (m_buffer_array_ip == NULL)
4194     {
4195         OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated");
4196 
4197         retval = OMX_ErrorBadParameter;
4198         goto buffer_deallocate_ip_exit;
4199     }
4200 
4201     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4202     {
4203         if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
4204         {
4205             OMX_SWVDEC_LOG_LOW("%p has index %d",
4206                                p_buffer_hdr->pBuffer,
4207                                ii);
4208             break;
4209         }
4210     }
4211 
4212     if (ii < m_port_ip.def.nBufferCountActual)
4213     {
4214         if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0)
4215         {
4216 
4217            if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4218             {
4219                 SWVDEC_BUFFER *p_buffer_swvdec;
4220                 p_buffer_swvdec  = &m_buffer_array_ip[ii].buffer_swvdec;
4221                 OMX_SWVDEC_LOG_LOW("unmap ip buffer");
4222 
4223                 if((retval_swvdec = swvdec_unregister_buffer(m_swvdec_handle,p_buffer_swvdec))
4224                    != SWVDEC_STATUS_SUCCESS)
4225                 {
4226                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for ip buffer %d: %p",
4227                                          ii,p_buffer_swvdec->p_buffer);
4228                     retval = retval_swvdec2omx(retval_swvdec);;
4229                 }
4230             }
4231 
4232             m_buffer_array_ip[ii].buffer_populated = false;
4233 
4234             m_port_ip.populated = OMX_FALSE;
4235 
4236             ion_unmap(m_buffer_array_ip[ii].buffer_payload.pmem_fd,
4237                       m_buffer_array_ip[ii].buffer_payload.bufferaddr,
4238                       m_buffer_array_ip[ii].buffer_payload.mmaped_size);
4239 
4240             close(m_buffer_array_ip[ii].buffer_payload.pmem_fd);
4241             m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
4242 
4243             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
4244 
4245             for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4246             {
4247                 if (m_buffer_array_ip[ii].buffer_populated)
4248                 {
4249                     break;
4250                 }
4251             }
4252 
4253             if (ii == m_port_ip.def.nBufferCountActual)
4254             {
4255                 buffer_deallocate_ip_info_array();
4256 
4257                 m_port_ip.unpopulated = OMX_TRUE;
4258             }
4259         }
4260         else
4261         {
4262             OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d",
4263                                  p_buffer_hdr->pBuffer,
4264                                  m_buffer_array_ip[ii].buffer_payload.pmem_fd);
4265         }
4266     }
4267     else
4268     {
4269         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
4270 
4271         retval = OMX_ErrorBadParameter;
4272     }
4273 
4274 buffer_deallocate_ip_exit:
4275     return retval;
4276 }
4277 
4278 /**
4279  * @brief De-allocate output buffer.
4280  *
4281  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
4282  *
4283  * @retval OMX_ERRORTYPE
4284  */
buffer_deallocate_op(OMX_BUFFERHEADERTYPE * p_buffer_hdr)4285 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op(
4286     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4287 {
4288     OMX_ERRORTYPE retval = OMX_ErrorNone;
4289     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
4290     unsigned int ii;
4291 
4292     if (p_buffer_hdr == NULL)
4293     {
4294         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
4295 
4296         retval = OMX_ErrorBadParameter;
4297         goto buffer_deallocate_op_exit;
4298     }
4299     else if (m_buffer_array_op == NULL)
4300     {
4301         OMX_SWVDEC_LOG_ERROR("op buffer array not allocated");
4302 
4303         retval = OMX_ErrorBadParameter;
4304         goto buffer_deallocate_op_exit;
4305     }
4306 
4307     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4308     {
4309         if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
4310         {
4311             OMX_SWVDEC_LOG_LOW("%p has index %d",
4312                                p_buffer_hdr->pBuffer,
4313                                ii);
4314             break;
4315         }
4316     }
4317 
4318     if (ii < m_port_op.def.nBufferCountActual)
4319     {
4320         if (m_meta_buffer_mode)
4321         {
4322             // do nothing; munmap() & FD reset done in FBD or RR
4323         }
4324         else if (m_android_native_buffers)
4325         {
4326 
4327             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4328             {
4329                 SWVDEC_BUFFER *p_buffer_swvdec;
4330                 p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4331                 OMX_SWVDEC_LOG_LOW("unmap op buffer");
4332 
4333                 if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4334                 {
4335                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer);
4336                     retval = retval_swvdec2omx(retval_swvdec);;
4337                 }
4338             }
4339             ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd ,
4340                       m_buffer_array_op[ii].buffer_payload.bufferaddr,
4341                       m_buffer_array_op[ii].buffer_payload.mmaped_size);
4342 
4343             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
4344         }
4345         else
4346         {
4347             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4348             {
4349                 SWVDEC_BUFFER *p_buffer_swvdec;
4350                 p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4351                 OMX_SWVDEC_LOG_LOW("unmap op buffer");
4352 
4353                 if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4354                 {
4355                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer);
4356                     retval = retval_swvdec2omx(retval_swvdec);;
4357                 }
4358             }
4359             ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd,
4360                       m_buffer_array_op[ii].buffer_payload.bufferaddr,
4361                       m_buffer_array_op[ii].buffer_payload.mmaped_size);
4362 
4363             close(m_buffer_array_op[ii].buffer_payload.pmem_fd);
4364 
4365             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
4366 
4367             ion_memory_free(&m_buffer_array_op[ii].ion_info);
4368         }
4369 
4370         m_buffer_array_op[ii].buffer_populated = false;
4371 
4372         m_port_op.populated = OMX_FALSE;
4373 
4374         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4375         {
4376             if (m_buffer_array_op[ii].buffer_populated)
4377             {
4378                 break;
4379             }
4380         }
4381 
4382         if (ii == m_port_op.def.nBufferCountActual)
4383         {
4384             buffer_deallocate_op_info_array();
4385 
4386             m_port_op.unpopulated = OMX_TRUE;
4387 
4388             if (m_meta_buffer_mode)
4389             {
4390                 meta_buffer_array_deallocate();
4391             }
4392         }
4393     }
4394     else
4395     {
4396         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
4397 
4398         retval = OMX_ErrorBadParameter;
4399     }
4400 
4401 buffer_deallocate_op_exit:
4402     return retval;
4403 }
4404 
4405 /**
4406  * @brief De-allocate input buffer info array.
4407  */
buffer_deallocate_ip_info_array()4408 void omx_swvdec::buffer_deallocate_ip_info_array()
4409 {
4410     assert(m_buffer_array_ip != NULL);
4411 
4412     free(m_buffer_array_ip);
4413 
4414     m_buffer_array_ip = NULL;
4415 }
4416 
4417 /**
4418  * @brief De-allocate output buffer info array.
4419  */
buffer_deallocate_op_info_array()4420 void omx_swvdec::buffer_deallocate_op_info_array()
4421 {
4422     assert(m_buffer_array_op != NULL);
4423 
4424     free(m_buffer_array_op);
4425 
4426     m_buffer_array_op = NULL;
4427 }
4428 
4429 /**
4430  * @brief Allocate meta buffer info array.
4431  *
4432  * @retval OMX_ERRORTYPE
4433  */
meta_buffer_array_allocate()4434 OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate()
4435 {
4436     OMX_ERRORTYPE retval = OMX_ErrorNone;
4437 
4438     m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *)
4439                            calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO),
4440                                   m_port_op.def.nBufferCountActual));
4441 
4442     if (m_meta_buffer_array == NULL)
4443     {
4444         OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; "
4445                              "%d element%s, %zu bytes requested",
4446                              m_port_op.def.nBufferCountActual,
4447                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
4448                              sizeof(OMX_SWVDEC_META_BUFFER_INFO) *
4449                              m_port_op.def.nBufferCountActual);
4450 
4451         retval = OMX_ErrorInsufficientResources;
4452     }
4453     else
4454     {
4455         unsigned int ii;
4456 
4457         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4458         {
4459             m_meta_buffer_array[ii].fd = -1;
4460         }
4461     }
4462 
4463     return retval;
4464 }
4465 
4466 /**
4467  * @brief De-allocate meta buffer info array.
4468  */
meta_buffer_array_deallocate()4469 void omx_swvdec::meta_buffer_array_deallocate()
4470 {
4471     assert(m_meta_buffer_array != NULL);
4472 
4473     free(m_meta_buffer_array);
4474 
4475     m_meta_buffer_array = NULL;
4476 }
4477 
4478 /**
4479  * @brief Add meta buffer reference.
4480  *
4481  * @param[in] index: Buffer index.
4482  * @param[in] fd:    File descriptor.
4483  */
meta_buffer_ref_add(unsigned int index,int fd)4484 void omx_swvdec::meta_buffer_ref_add(unsigned int index, int fd)
4485 {
4486     if (m_meta_buffer_array[index].ref_count == 0)
4487     {
4488         m_meta_buffer_array[index].fd = fd;
4489     }
4490 
4491     m_meta_buffer_array[index].ref_count++;
4492 }
4493 
4494 /**
4495  * @brief Remove meta buffer reference.
4496  *
4497  * @param[in] index: Buffer index.
4498  */
meta_buffer_ref_remove(unsigned int index)4499 void omx_swvdec::meta_buffer_ref_remove(unsigned int index)
4500 {
4501     pthread_mutex_lock(&m_meta_buffer_array_mutex);
4502 
4503     m_meta_buffer_array[index].ref_count--;
4504 
4505     if (m_meta_buffer_array[index].ref_count == 0)
4506     {
4507         ion_unmap(m_meta_buffer_array[index].fd,
4508                   m_buffer_array_op[index].buffer_payload.bufferaddr,
4509                   m_buffer_array_op[index].buffer_payload.mmaped_size);
4510 
4511         m_meta_buffer_array[index].fd = -1;
4512         m_buffer_array_op[index].buffer_payload.bufferaddr  = NULL;
4513         m_buffer_array_op[index].buffer_payload.offset      = 0;
4514         m_buffer_array_op[index].buffer_payload.mmaped_size = 0;
4515 
4516         m_buffer_array_op[index].buffer_swvdec.p_buffer = NULL;
4517         m_buffer_array_op[index].buffer_swvdec.size     = 0;
4518     }
4519 
4520     pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4521 }
4522 
4523 /**
4524  * @brief Split MPEG-4 bitstream buffer into multiple frames (if they exist).
4525  *
4526  * @param[in,out] offset_array: Array of offsets to frame headers.
4527  * @param[in]     p_buffer_hdr: Pointer to buffer header.
4528  *
4529  * @retval Number of frames in buffer.
4530  */
split_buffer_mpeg4(unsigned int * offset_array,OMX_BUFFERHEADERTYPE * p_buffer_hdr)4531 unsigned int split_buffer_mpeg4(unsigned int         *offset_array,
4532                                 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4533 {
4534     unsigned char *p_buffer = p_buffer_hdr->pBuffer;
4535 
4536     unsigned int byte_count = 0;
4537 
4538     unsigned int num_frame_headers = 0;
4539 
4540     unsigned int next_4bytes;
4541 
4542     while ((byte_count < p_buffer_hdr->nFilledLen) &&
4543            (num_frame_headers < OMX_SWVDEC_MAX_FRAMES_PER_ETB))
4544     {
4545         next_4bytes = *((unsigned int *) p_buffer);
4546 
4547         next_4bytes = __builtin_bswap32(next_4bytes);
4548 
4549         if (next_4bytes == 0x000001B6)
4550         {
4551             OMX_SWVDEC_LOG_HIGH("%p, buffer %p: "
4552                                 "frame header at %d bytes offset",
4553                                 p_buffer_hdr,
4554                                 p_buffer_hdr->pBuffer,
4555                                 byte_count);
4556 
4557             offset_array[num_frame_headers] = byte_count;
4558 
4559             num_frame_headers++;
4560 
4561             p_buffer   += 4;
4562             byte_count += 4;
4563         }
4564         else
4565         {
4566             p_buffer++;
4567             byte_count++;
4568         }
4569     }
4570 
4571     return num_frame_headers;
4572 }
4573 
4574 /**
4575  * @brief Check if ip port is populated, i.e., if all ip buffers are populated.
4576  *
4577  * @retval  true
4578  * @retval false
4579  */
port_ip_populated()4580 OMX_BOOL omx_swvdec::port_ip_populated()
4581 {
4582     OMX_BOOL retval = OMX_FALSE;
4583 
4584     if (m_buffer_array_ip != NULL)
4585     {
4586         unsigned int ii;
4587 
4588         for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4589         {
4590             if (m_buffer_array_ip[ii].buffer_populated == false)
4591             {
4592                 break;
4593             }
4594         }
4595 
4596         if (ii == m_port_ip.def.nBufferCountActual)
4597         {
4598             retval = OMX_TRUE;
4599         }
4600     }
4601 
4602     return retval;
4603 }
4604 
4605 /**
4606  * @brief Check if op port is populated, i.e., if all op buffers are populated.
4607  *
4608  * @retval  true
4609  * @retval false
4610  */
port_op_populated()4611 OMX_BOOL omx_swvdec::port_op_populated()
4612 {
4613     OMX_BOOL retval = OMX_FALSE;
4614 
4615     if (m_buffer_array_op != NULL)
4616     {
4617         unsigned int ii;
4618 
4619         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4620         {
4621             if (m_buffer_array_op[ii].buffer_populated == false)
4622             {
4623                 break;
4624             }
4625         }
4626 
4627         if (ii == m_port_op.def.nBufferCountActual)
4628         {
4629             retval = OMX_TRUE;
4630         }
4631     }
4632 
4633     return retval;
4634 }
4635 
4636 /**
4637  * @brief Flush input, output, or both input & output ports.
4638  *
4639  * @param[in] port_index: Index of port to flush.
4640  *
4641  * @retval OMX_ERRORTYPE
4642  */
flush(unsigned int port_index)4643 OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index)
4644 {
4645     OMX_ERRORTYPE retval = OMX_ErrorNone;
4646 
4647     if (((port_index == OMX_CORE_PORT_INDEX_IP) &&
4648          m_port_ip.flush_inprogress) ||
4649         ((port_index == OMX_CORE_PORT_INDEX_OP) &&
4650          m_port_op.flush_inprogress) ||
4651         ((port_index == OMX_ALL) &&
4652          m_port_ip.flush_inprogress &&
4653          m_port_op.flush_inprogress))
4654     {
4655         OMX_SWVDEC_LOG_HIGH("flush port index %d already in progress",
4656                             port_index);
4657     }
4658     else
4659     {
4660         SWVDEC_FLUSH_TYPE swvdec_flush_type;
4661 
4662         SWVDEC_STATUS retval_swvdec;
4663 
4664         if (port_index == OMX_CORE_PORT_INDEX_IP)
4665         {
4666             m_port_ip.flush_inprogress = OMX_TRUE;
4667 
4668             //for VTS test case IP flush , trigger flush all
4669             // for IP flush, similar behavior is for hwcodecs
4670             m_port_ip.flush_inprogress = OMX_TRUE;
4671             m_port_op.flush_inprogress = OMX_TRUE;
4672 
4673             swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4674 
4675             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4676                                               swvdec_flush_type)) !=
4677                 SWVDEC_STATUS_SUCCESS)
4678             {
4679                 retval = retval_swvdec2omx(retval_swvdec);
4680             }
4681         }
4682         else if (port_index == OMX_CORE_PORT_INDEX_OP)
4683         {
4684             m_port_op.flush_inprogress = OMX_TRUE;
4685 
4686             swvdec_flush_type = (m_port_ip.flush_inprogress ?
4687                                  SWVDEC_FLUSH_TYPE_ALL :
4688                                  SWVDEC_FLUSH_TYPE_OP);
4689 
4690             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4691                                               swvdec_flush_type)) !=
4692                 SWVDEC_STATUS_SUCCESS)
4693             {
4694                 retval = retval_swvdec2omx(retval_swvdec);
4695             }
4696         }
4697         else if (port_index == OMX_ALL)
4698         {
4699             m_port_ip.flush_inprogress = OMX_TRUE;
4700             m_port_op.flush_inprogress = OMX_TRUE;
4701 
4702             swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4703 
4704             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4705                                               swvdec_flush_type)) !=
4706                 SWVDEC_STATUS_SUCCESS)
4707             {
4708                 retval = retval_swvdec2omx(retval_swvdec);
4709             }
4710         }
4711         else
4712         {
4713             assert(0);
4714         }
4715     }
4716 
4717     return retval;
4718 }
4719 
4720 /**
4721  * @brief Allocate & map ION memory.
4722  */
ion_memory_alloc_map(vdec_ion * p_ion_info,OMX_U32 size,OMX_U32 alignment)4723 int omx_swvdec::ion_memory_alloc_map(vdec_ion *p_ion_info, OMX_U32 size, OMX_U32 alignment)
4724 {
4725     int rc = -EINVAL;
4726 
4727     if((!p_ion_info) || (size == 0))
4728     {
4729         OMX_SWVDEC_LOG_ERROR("invalid arguments");
4730         goto ion_memory_alloc_map_exit;
4731     }
4732 
4733     p_ion_info->dev_fd = -EINVAL;
4734 
4735     if ((p_ion_info->dev_fd = ion_open()) < 0)
4736     {
4737         OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", p_ion_info->dev_fd);
4738         goto ion_memory_alloc_map_exit;
4739     }
4740 
4741     p_ion_info->alloc_data.len = size;
4742     p_ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
4743     p_ion_info->alloc_data.flags        = 0;//check if ION_FLAG_CACHED need to be set;
4744     alignment = ALIGN(alignment,4096);
4745 
4746     OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %zu",
4747                        p_ion_info->alloc_data.heap_id_mask,
4748                        p_ion_info->alloc_data.len);
4749 
4750     rc = ion_alloc_fd(p_ion_info->dev_fd, p_ion_info->alloc_data.len, alignment,
4751                       p_ion_info->alloc_data.heap_id_mask, p_ion_info->alloc_data.flags,
4752                       &p_ion_info->data_fd);
4753 
4754     if (rc || p_ion_info->data_fd == 0)
4755     {
4756         OMX_SWVDEC_LOG_ERROR("ion_alloc_fd() for allocation failed");
4757         ion_close(p_ion_info->dev_fd);
4758         p_ion_info->data_fd = -1;
4759         p_ion_info->dev_fd = -1;
4760         goto ion_memory_alloc_map_exit;
4761     }
4762 
4763 
4764     OMX_SWVDEC_LOG_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
4765                         p_ion_info->dev_fd, p_ion_info->data_fd, (unsigned int)p_ion_info->alloc_data.len,
4766                      (unsigned int)p_ion_info->alloc_data.flags,
4767                      (unsigned int)p_ion_info->alloc_data.heap_id_mask);
4768 
4769 ion_memory_alloc_map_exit:
4770     return (p_ion_info == nullptr) ? -EINVAL : p_ion_info->dev_fd;
4771 }
4772 
4773 /**
4774  * @brief Free ION memory.
4775  */
ion_memory_free(struct vdec_ion * p_ion_buf_info)4776 void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info)
4777 {
4778     if (p_ion_buf_info == NULL)
4779     {
4780         OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL");
4781         goto ion_memory_free_exit;
4782     }
4783 
4784     OMX_SWVDEC_LOG_HIGH("Free ion memory: map fd %d ion_dev fd %d len %d flags %#x mask %#x",
4785         p_ion_buf_info->data_fd, p_ion_buf_info->dev_fd,
4786         (unsigned int)p_ion_buf_info->alloc_data.len,
4787         (unsigned int)p_ion_buf_info->alloc_data.flags,
4788         (unsigned int)p_ion_buf_info->alloc_data.heap_id_mask);
4789 
4790     if (p_ion_buf_info->data_fd >= 0) {
4791         close(p_ion_buf_info->data_fd);
4792         p_ion_buf_info->data_fd = -1;
4793     }
4794 
4795     if (p_ion_buf_info->dev_fd >= 0) {
4796         ion_close(p_ion_buf_info->dev_fd);
4797         p_ion_buf_info->dev_fd = -1;
4798     }
4799 
4800 ion_memory_free_exit:
4801     return;
4802 }
4803 
4804 /**
4805  * @brief Flush cached ION output buffer.
4806  *
4807  * @param[in] index: Index of buffer in output buffer info array.
4808  */
ion_flush_op(unsigned int index)4809 void omx_swvdec::ion_flush_op(unsigned int index)
4810 {
4811     if (index < m_port_op.def.nBufferCountActual)
4812     {
4813 #ifdef USE_ION
4814         struct dma_buf_sync dma_buf_sync_data[2];
4815         dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE;
4816         dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE;
4817 
4818         for (unsigned int i=0; i<2; i++)
4819         {
4820             int ret = ioctl(m_buffer_array_op[index].buffer_swvdec.fd,
4821                       DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]);
4822             if (ret < 0)
4823             {
4824                 OMX_SWVDEC_LOG_ERROR("Cache %s failed for fd %d : %s\n",
4825                                   (i==0) ? "START" : "END",
4826                                   m_buffer_array_op[index].buffer_swvdec.fd,
4827                                   strerror(errno));
4828                 goto ion_flush_op_exit;
4829             }
4830        }
4831 #endif
4832     }
4833     else
4834     {
4835         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
4836     }
4837 
4838 ion_flush_op_exit:
4839     return;
4840 }
4841 
4842 
4843 /**
4844  * ----------------------------
4845  * component callback functions
4846  * ----------------------------
4847  */
4848 
4849 /**
4850  * @brief Empty buffer done callback.
4851  *
4852  * @param[in] p_buffer_ip: Pointer to input buffer structure.
4853  */
swvdec_empty_buffer_done(SWVDEC_BUFFER * p_buffer_ip)4854 void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip)
4855 {
4856     unsigned long index = (unsigned long) p_buffer_ip->p_client_data;
4857 
4858     m_buffer_array_ip[index].buffer_header.nFilledLen =
4859         p_buffer_ip->filled_length;
4860 
4861     async_post_event(OMX_SWVDEC_EVENT_EBD,
4862                      (unsigned long) &m_buffer_array_ip[index].buffer_header,
4863                      index);
4864 }
4865 
4866 /**
4867  * @brief Fill buffer done callback.
4868  *
4869  * @param[in] p_buffer_op: Pointer to output buffer structure.
4870  */
swvdec_fill_buffer_done(SWVDEC_BUFFER * p_buffer_op)4871 void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op)
4872 {
4873     unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4874 
4875     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
4876 
4877     if (index < ((unsigned long) m_port_op.def.nBufferCountActual))
4878     {
4879         p_buffer_hdr = &m_buffer_array_op[index].buffer_header;
4880 
4881         p_buffer_hdr->nFlags     = p_buffer_op->flags;
4882         p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp;
4883         p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode &&
4884                                      p_buffer_op->filled_length) ?
4885                                     p_buffer_hdr->nAllocLen :
4886                                     p_buffer_op->filled_length);
4887     }
4888 
4889     async_post_event(OMX_SWVDEC_EVENT_FBD,
4890                      (unsigned long) &m_buffer_array_op[index].buffer_header,
4891                      index);
4892 }
4893 
4894 /**
4895  * @brief Event handler callback.
4896  *
4897  * @param[in] event:  Event.
4898  * @param[in] p_data: Pointer to event-specific data.
4899  */
swvdec_event_handler(SWVDEC_EVENT event,void * p_data)4900 void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data)
4901 {
4902     switch (event)
4903     {
4904 
4905     case SWVDEC_EVENT_FLUSH_ALL_DONE:
4906     {
4907         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0);
4908         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4909 
4910         break;
4911     }
4912 
4913     case SWVDEC_EVENT_FLUSH_OP_DONE:
4914     {
4915         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4916 
4917         break;
4918     }
4919 
4920     case SWVDEC_EVENT_RELEASE_REFERENCE:
4921     {
4922         SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data;
4923 
4924         unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4925 
4926         OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer);
4927 
4928         assert(index < ((unsigned long) m_port_op.def.nBufferCountActual));
4929 
4930         if (m_meta_buffer_mode)
4931         {
4932             meta_buffer_ref_remove(index);
4933         }
4934 
4935         break;
4936     }
4937 
4938     case SWVDEC_EVENT_RECONFIG_REQUIRED:
4939     {
4940         async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0);
4941 
4942         break;
4943     }
4944 
4945     case SWVDEC_EVENT_DIMENSIONS_UPDATED:
4946     {
4947         async_post_event(OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED, 0, 0);
4948 
4949         break;
4950     }
4951 
4952     case SWVDEC_EVENT_FATAL_ERROR:
4953     default:
4954     {
4955         async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0);
4956 
4957         break;
4958     }
4959 
4960     }
4961 }
4962 
4963 /**
4964  * @brief Translate SwVdec status return value to OMX error type return value.
4965  *
4966  * @param[in] retval_swvdec: SwVdec status return value.
4967  *
4968  * @retval OMX_ERRORTYPE
4969  */
retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)4970 OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)
4971 {
4972     OMX_ERRORTYPE retval_omx;
4973 
4974     switch (retval_swvdec) {
4975         case SWVDEC_STATUS_SUCCESS:
4976             retval_omx = OMX_ErrorNone;
4977             break;
4978 
4979         case SWVDEC_STATUS_FAILURE:
4980             retval_omx = OMX_ErrorUndefined;
4981             break;
4982 
4983         case SWVDEC_STATUS_NULL_POINTER:
4984         case SWVDEC_STATUS_INVALID_PARAMETERS:
4985             retval_omx = OMX_ErrorBadParameter;
4986             break;
4987 
4988         case SWVDEC_STATUS_INVALID_STATE:
4989             retval_omx = OMX_ErrorInvalidState;
4990             break;
4991 
4992         case SWVDEC_STATUS_INSUFFICIENT_RESOURCES:
4993             retval_omx = OMX_ErrorInsufficientResources;
4994             break;
4995 
4996         case SWVDEC_STATUS_UNSUPPORTED:
4997             retval_omx = OMX_ErrorUnsupportedSetting;
4998             break;
4999 
5000         case SWVDEC_STATUS_NOT_IMPLEMENTED:
5001             retval_omx = OMX_ErrorNotImplemented;
5002             break;
5003 
5004         default:
5005             retval_omx = OMX_ErrorUndefined;
5006             break;
5007     }
5008 
5009     return retval_omx;
5010 }
5011 
5012 /**
5013  * @brief Create asynchronous thread.
5014  *
5015  * @retval OMX_ERRORTYPE
5016  */
async_thread_create()5017 OMX_ERRORTYPE omx_swvdec::async_thread_create()
5018 {
5019     OMX_ERRORTYPE retval = OMX_ErrorNone;
5020 
5021     pthread_attr_t thread_attributes;
5022 
5023     if (sem_init(&m_async_thread.sem_thread_created, 0, 0))
5024     {
5025         OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore");
5026 
5027         retval = OMX_ErrorInsufficientResources;
5028     }
5029     else if (sem_init(&m_async_thread.sem_event, 0, 0))
5030     {
5031         OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore");
5032 
5033         retval = OMX_ErrorInsufficientResources;
5034     }
5035     else if (pthread_attr_init(&thread_attributes))
5036     {
5037         OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object");
5038 
5039         retval = OMX_ErrorInsufficientResources;
5040     }
5041     else if (pthread_attr_setdetachstate(&thread_attributes,
5042                                          PTHREAD_CREATE_JOINABLE))
5043     {
5044         OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute");
5045 
5046         retval = OMX_ErrorInsufficientResources;
5047 
5048         pthread_attr_destroy(&thread_attributes);
5049     }
5050     else
5051     {
5052         m_async_thread.created = false;
5053         m_async_thread.exit    = false;
5054 
5055         if (pthread_create(&m_async_thread.handle,
5056                            &thread_attributes,
5057                            (void *(*)(void *)) async_thread,
5058                            this))
5059         {
5060             OMX_SWVDEC_LOG_ERROR("failed to create async thread");
5061 
5062             retval = OMX_ErrorInsufficientResources;
5063 
5064             pthread_attr_destroy(&thread_attributes);
5065         }
5066         else
5067         {
5068             if (pthread_setname_np(m_async_thread.handle, "swvdec_async"))
5069             {
5070                 // don't return error
5071                 OMX_SWVDEC_LOG_ERROR("failed to set async thread name");
5072             }
5073 
5074             sem_wait(&m_async_thread.sem_thread_created);
5075 
5076             m_async_thread.created = true;
5077         }
5078     }
5079 
5080     return retval;
5081 }
5082 
5083 /**
5084  * @brief Destroy asynchronous thread.
5085  */
async_thread_destroy()5086 void omx_swvdec::async_thread_destroy()
5087 {
5088     if (m_async_thread.created)
5089     {
5090         m_async_thread.exit = true;
5091 
5092         sem_post(&m_async_thread.sem_event);
5093 
5094         pthread_join(m_async_thread.handle, NULL);
5095 
5096         m_async_thread.created = false;
5097     }
5098 
5099     m_async_thread.exit = false;
5100 
5101     sem_destroy(&m_async_thread.sem_event);
5102     sem_destroy(&m_async_thread.sem_thread_created);
5103 }
5104 
5105 /**
5106  * @brief Post event to appropriate queue.
5107  *
5108  * @param[in] event_id:     Event ID.
5109  * @param[in] event_param1: Event parameter 1.
5110  * @param[in] event_param2: Event parameter 2.
5111  */
async_post_event(unsigned long event_id,unsigned long event_param1,unsigned long event_param2)5112 void omx_swvdec::async_post_event(unsigned long event_id,
5113                                   unsigned long event_param1,
5114                                   unsigned long event_param2)
5115 {
5116     OMX_SWVDEC_EVENT_INFO event_info;
5117 
5118     event_info.event_id     = event_id;
5119     event_info.event_param1 = event_param1;
5120     event_info.event_param2 = event_param2;
5121 
5122     switch (event_id)
5123     {
5124 
5125     case OMX_SWVDEC_EVENT_ETB:
5126     case OMX_SWVDEC_EVENT_EBD:
5127     {
5128         m_queue_port_ip.push(&event_info);
5129         break;
5130     }
5131 
5132     case OMX_SWVDEC_EVENT_FTB:
5133     case OMX_SWVDEC_EVENT_FBD:
5134     {
5135         m_queue_port_op.push(&event_info);
5136         break;
5137     }
5138 
5139     default:
5140     {
5141         m_queue_command.push(&event_info);
5142         break;
5143     }
5144 
5145     }
5146 
5147     sem_post(&m_async_thread.sem_event);
5148 }
5149 
5150 /**
5151  * @brief Asynchronous thread.
5152  *
5153  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
5154  */
async_thread(void * p_cmp)5155 void omx_swvdec::async_thread(void *p_cmp)
5156 {
5157     if (p_cmp == NULL)
5158     {
5159         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
5160     }
5161     else
5162     {
5163         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp;
5164 
5165         ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread;
5166 
5167         OMX_SWVDEC_LOG_HIGH("created");
5168 
5169         sem_post(&p_async_thread->sem_thread_created);
5170 
5171         while (p_async_thread->exit == false)
5172         {
5173             sem_wait(&p_async_thread->sem_event);
5174 
5175             if (p_async_thread->exit == true)
5176             {
5177                 break;
5178             }
5179 
5180             p_omx_swvdec->async_process_event(p_cmp);
5181         }
5182     }
5183 
5184     OMX_SWVDEC_LOG_HIGH("exiting");
5185 }
5186 
5187 /**
5188  * @brief Process event.
5189  *
5190  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
5191  */
async_process_event(void * p_cmp)5192 void omx_swvdec::async_process_event(void *p_cmp)
5193 {
5194     omx_swvdec *p_omx_swvdec;
5195 
5196     OMX_SWVDEC_EVENT_INFO event_info;
5197 
5198     OMX_ERRORTYPE retval = OMX_ErrorNone;
5199 
5200     if (p_cmp == NULL)
5201     {
5202         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
5203 
5204         goto async_process_event_exit;
5205     }
5206 
5207     p_omx_swvdec = (omx_swvdec *) p_cmp;
5208 
5209     // NOTE: queues popped in order of priority; do not change!
5210 
5211     if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) &&
5212         (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) &&
5213         (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false))
5214     {
5215         OMX_SWVDEC_LOG_LOW("no event popped");
5216 
5217         goto async_process_event_exit;
5218     }
5219 
5220     switch (event_info.event_id)
5221     {
5222 
5223     case OMX_SWVDEC_EVENT_CMD:
5224     {
5225         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
5226         OMX_U32         param = (OMX_U32)         event_info.event_param2;
5227 
5228         retval = p_omx_swvdec->async_process_event_cmd(cmd, param);
5229         break;
5230     }
5231 
5232     case OMX_SWVDEC_EVENT_CMD_ACK:
5233     {
5234         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
5235         OMX_U32         param = (OMX_U32)         event_info.event_param2;
5236 
5237         retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param);
5238         break;
5239     }
5240 
5241     case OMX_SWVDEC_EVENT_ERROR:
5242     {
5243         OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1;
5244 
5245         retval = p_omx_swvdec->async_process_event_error(error_code);
5246         break;
5247     }
5248 
5249     case OMX_SWVDEC_EVENT_ETB:
5250     {
5251         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5252             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5253 
5254         unsigned int index = event_info.event_param2;
5255 
5256         retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index);
5257         break;
5258     }
5259 
5260     case OMX_SWVDEC_EVENT_FTB:
5261     {
5262         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5263             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5264 
5265         unsigned int index = event_info.event_param2;
5266 
5267         retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index);
5268         break;
5269     }
5270 
5271     case OMX_SWVDEC_EVENT_EBD:
5272     {
5273         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5274             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5275 
5276         unsigned int index = event_info.event_param2;
5277 
5278         retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index);
5279         break;
5280     }
5281 
5282     case OMX_SWVDEC_EVENT_FBD:
5283     {
5284         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5285             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5286 
5287         unsigned int index = event_info.event_param2;
5288 
5289         retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index);
5290         break;
5291     }
5292 
5293     case OMX_SWVDEC_EVENT_EOS:
5294     {
5295         retval = p_omx_swvdec->async_process_event_eos();
5296         break;
5297     }
5298 
5299     case OMX_SWVDEC_EVENT_FLUSH_PORT_IP:
5300     {
5301         retval = p_omx_swvdec->async_process_event_flush_port_ip();
5302         break;
5303     }
5304 
5305     case OMX_SWVDEC_EVENT_FLUSH_PORT_OP:
5306     {
5307         retval = p_omx_swvdec->async_process_event_flush_port_op();
5308         break;
5309     }
5310 
5311     case OMX_SWVDEC_EVENT_PORT_RECONFIG:
5312     {
5313         retval = p_omx_swvdec->async_process_event_port_reconfig();
5314         break;
5315     }
5316 
5317     case OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED:
5318     {
5319         retval = p_omx_swvdec->async_process_event_dimensions_updated();
5320         break;
5321     }
5322 
5323     default:
5324     {
5325         assert(0);
5326 
5327         retval = OMX_ErrorUndefined;
5328         break;
5329     }
5330 
5331     }
5332 
5333     if (retval != OMX_ErrorNone)
5334     {
5335         p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
5336     }
5337 
5338 async_process_event_exit:
5339     return;
5340 }
5341 
5342 /**
5343  * @brief Process command event.
5344  *
5345  * @param[in] cmd:   Command.
5346  * @param[in] param: Command parameter.
5347  *
5348  * @retval OMX_ERRORTYPE
5349  */
async_process_event_cmd(OMX_COMMANDTYPE cmd,OMX_U32 param)5350 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd,
5351                                                   OMX_U32         param)
5352 {
5353     OMX_ERRORTYPE retval = OMX_ErrorNone;
5354 
5355     bool cmd_ack = false;
5356 
5357     switch (cmd)
5358     {
5359 
5360     case OMX_CommandStateSet:
5361     {
5362         retval = async_process_event_cmd_state_set(&cmd_ack,
5363                                                    (OMX_STATETYPE) param);
5364         break;
5365     }
5366 
5367     case OMX_CommandFlush:
5368     {
5369         retval = async_process_event_cmd_flush((unsigned int) param);
5370         break;
5371     }
5372 
5373     case OMX_CommandPortDisable:
5374     {
5375         retval = async_process_event_cmd_port_disable(&cmd_ack,
5376                                                       (unsigned int) param);
5377         break;
5378     }
5379 
5380     case OMX_CommandPortEnable:
5381     {
5382         retval = async_process_event_cmd_port_enable(&cmd_ack,
5383                                                      (unsigned int) param);
5384         break;
5385     }
5386 
5387     default:
5388     {
5389         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
5390 
5391         retval = OMX_ErrorBadParameter;
5392         break;
5393     }
5394 
5395     } // switch (cmd)
5396 
5397     if (retval != OMX_ErrorNone)
5398     {
5399         async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
5400     }
5401     else if (cmd_ack)
5402     {
5403         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param);
5404     }
5405 
5406     sem_post(&m_sem_cmd);
5407 
5408     return retval;
5409 }
5410 
5411 /**
5412  * @brief Process command acknowledgement event.
5413  *
5414  * @param[in] cmd:   Command.
5415  * @param[in] param: Command parameter.
5416  *
5417  * @retval OMX_ERRORTYPE
5418  */
async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,OMX_U32 param)5419 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,
5420                                                       OMX_U32         param)
5421 {
5422     OMX_ERRORTYPE retval = OMX_ErrorNone;
5423 
5424     switch (cmd)
5425     {
5426 
5427     case OMX_CommandStateSet:
5428     {
5429         OMX_SWVDEC_LOG_HIGH("%s -> %s",
5430                             OMX_STATETYPE_STRING(m_state),
5431                             OMX_STATETYPE_STRING((OMX_STATETYPE) param));
5432 
5433         m_state = (OMX_STATETYPE) param;
5434 
5435         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
5436                                 "OMX_CommandStateSet, %s",
5437                                 OMX_STATETYPE_STRING(m_state));
5438 
5439         m_callback.EventHandler(&m_cmp,
5440                                 m_app_data,
5441                                 OMX_EventCmdComplete,
5442                                 OMX_CommandStateSet,
5443                                 (OMX_U32) m_state,
5444                                 NULL);
5445         break;
5446     }
5447 
5448     case OMX_CommandFlush:
5449     case OMX_CommandPortEnable:
5450     case OMX_CommandPortDisable:
5451     {
5452         if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress)
5453         {
5454             m_port_reconfig_inprogress = false;
5455         }
5456 
5457         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
5458                                 "%s, port index %d",
5459                                 OMX_COMMANDTYPE_STRING(cmd),
5460                                 param);
5461 
5462         m_callback.EventHandler(&m_cmp,
5463                                 m_app_data,
5464                                 OMX_EventCmdComplete,
5465                                 cmd,
5466                                 param,
5467                                 NULL);
5468         break;
5469     }
5470 
5471     default:
5472     {
5473         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
5474 
5475         retval = OMX_ErrorBadParameter;
5476         break;
5477     }
5478 
5479     } // switch (cmd)
5480 
5481     return retval;
5482 }
5483 
5484 /**
5485  * @brief Process error event.
5486  *
5487  * @param[in] error_code: Error code.
5488  *
5489  * @retval OMX_ErrorNone
5490  */
async_process_event_error(OMX_ERRORTYPE error_code)5491 OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code)
5492 {
5493     if (error_code == OMX_ErrorInvalidState)
5494     {
5495         OMX_SWVDEC_LOG_HIGH("%s -> OMX_StateInvalid",
5496                             OMX_STATETYPE_STRING(m_state));
5497 
5498         m_state = OMX_StateInvalid;
5499     }
5500 
5501     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x",
5502                             error_code);
5503 
5504     m_callback.EventHandler(&m_cmp,
5505                             m_app_data,
5506                             OMX_EventError,
5507                             (OMX_U32) error_code,
5508                             0,
5509                             NULL);
5510 
5511     return OMX_ErrorNone;
5512 }
5513 
5514 /**
5515  * @brief Process OMX_CommandStateSet.
5516  *
5517  * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5518  * @param[in]     state_new: New state to which transition is requested.
5519  *
5520  * @retval OMX_ERRORTYPE
5521  */
async_process_event_cmd_state_set(bool * p_cmd_ack,OMX_STATETYPE state_new)5522 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set(
5523     bool         *p_cmd_ack,
5524     OMX_STATETYPE state_new)
5525 {
5526     OMX_ERRORTYPE retval = OMX_ErrorNone;
5527 
5528     SWVDEC_STATUS retval_swvdec;
5529 
5530     OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested",
5531                         OMX_STATETYPE_STRING(m_state),
5532                         OMX_STATETYPE_STRING(state_new));
5533 
5534     /**
5535      * Only the following state transitions are allowed via CommandStateSet:
5536      *
5537      * LOADED -> IDLE -> EXECUTING
5538      * LOADED <- IDLE <- EXECUTING
5539      */
5540 
5541     if (m_state == OMX_StateInvalid)
5542     {
5543         OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state));
5544 
5545         retval = OMX_ErrorInvalidState;
5546     }
5547     else if (state_new == OMX_StateInvalid)
5548     {
5549         OMX_SWVDEC_LOG_ERROR("requested transition to state %s",
5550                              OMX_STATETYPE_STRING(state_new));
5551 
5552         retval = OMX_ErrorInvalidState;
5553     }
5554     else if ((m_state   == OMX_StateLoaded) &&
5555              (state_new == OMX_StateIdle))
5556     {
5557         if ((m_port_ip.populated == OMX_TRUE) &&
5558             (m_port_op.populated == OMX_TRUE))
5559         {
5560             if ((retval_swvdec = swvdec_start(m_swvdec_handle)) ==
5561                 SWVDEC_STATUS_SUCCESS)
5562             {
5563                 *p_cmd_ack = true;
5564             }
5565             else
5566             {
5567                 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
5568 
5569                 retval = retval_swvdec2omx(retval_swvdec);
5570             }
5571         }
5572         else
5573         {
5574             m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE);
5575 
5576             OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending");
5577         }
5578     }
5579     else if ((m_state   == OMX_StateIdle) &&
5580              (state_new == OMX_StateExecuting))
5581     {
5582         *p_cmd_ack = true;
5583     }
5584     else if ((m_state   == OMX_StateExecuting) &&
5585              (state_new == OMX_StateIdle))
5586     {
5587         m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE);
5588 
5589         OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending");
5590 
5591         retval = flush(OMX_ALL);
5592     }
5593     else if ((m_state   == OMX_StateIdle) &&
5594              (state_new == OMX_StateLoaded))
5595     {
5596         if ((m_port_ip.unpopulated == OMX_TRUE) &&
5597             (m_port_op.unpopulated == OMX_TRUE))
5598         {
5599             if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
5600                 SWVDEC_STATUS_SUCCESS)
5601             {
5602                 *p_cmd_ack = true;
5603             }
5604             else
5605             {
5606                 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
5607 
5608                 retval = retval_swvdec2omx(retval_swvdec);
5609             }
5610         }
5611         else
5612         {
5613             m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED);
5614 
5615             OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending");
5616         }
5617     }
5618     else
5619     {
5620         OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal",
5621                              OMX_STATETYPE_STRING(m_state),
5622                              OMX_STATETYPE_STRING(state_new));
5623 
5624         retval = ((state_new == m_state) ?
5625                   OMX_ErrorSameState :
5626                   OMX_ErrorIncorrectStateTransition);
5627     }
5628 
5629     return retval;
5630 }
5631 
5632 /**
5633  * @brief Process OMX_CommandFlush.
5634  *
5635  * @param[in] port_index: Index of port to flush.
5636  *
5637  * @retval OMX_ERRORTYPE
5638  */
async_process_event_cmd_flush(unsigned int port_index)5639 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index)
5640 {
5641     OMX_ERRORTYPE retval = OMX_ErrorNone;
5642 
5643     OMX_SWVDEC_LOG_HIGH("flush port index %d requested", port_index);
5644 
5645     if (port_index == OMX_CORE_PORT_INDEX_IP)
5646     {
5647         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5648 
5649         OMX_SWVDEC_LOG_LOW("ip port flush pending");
5650     }
5651     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5652     {
5653         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5654 
5655         OMX_SWVDEC_LOG_LOW("op port flush pending");
5656     }
5657     else if (port_index == OMX_ALL)
5658     {
5659         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5660         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5661 
5662         OMX_SWVDEC_LOG_LOW("ip & op ports flush pending");
5663     }
5664 
5665     retval = flush(port_index);
5666 
5667     return retval;
5668 }
5669 
5670 /**
5671  * @brief Process OMX_CommandPortDisable.
5672  *
5673  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5674  * @param[in]     port_index: Index of port to disable.
5675  *
5676  * @retval OMX_ERRORTYPE
5677  */
async_process_event_cmd_port_disable(bool * p_cmd_ack,unsigned int port_index)5678 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable(
5679     bool         *p_cmd_ack,
5680     unsigned int  port_index)
5681 {
5682     OMX_ERRORTYPE retval = OMX_ErrorNone;
5683 
5684     OMX_SWVDEC_LOG_HIGH("disable port index %d requested", port_index);
5685 
5686     if (port_index == OMX_CORE_PORT_INDEX_IP)
5687     {
5688         if (m_port_ip.enabled == OMX_FALSE)
5689         {
5690             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5691 
5692             retval = OMX_ErrorBadPortIndex;
5693         }
5694         else
5695         {
5696             m_port_ip.enabled = OMX_FALSE;
5697 
5698             if (m_port_ip.unpopulated)
5699             {
5700                 *p_cmd_ack = true;
5701             }
5702             else
5703             {
5704                 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5705 
5706                 OMX_SWVDEC_LOG_LOW("ip port disable pending");
5707 
5708                 if (m_port_ip.num_pending_buffers)
5709                 {
5710                     retval = flush(port_index);
5711                 }
5712             }
5713         }
5714     }
5715     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5716     {
5717         if (m_port_op.enabled == OMX_FALSE)
5718         {
5719             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5720 
5721             retval = OMX_ErrorBadPortIndex;
5722         }
5723         else
5724         {
5725             m_port_op.enabled = OMX_FALSE;
5726 
5727             if (m_port_op.unpopulated)
5728             {
5729                 *p_cmd_ack = true;
5730             }
5731             else
5732             {
5733                 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5734 
5735                 OMX_SWVDEC_LOG_LOW("op port disable pending");
5736 
5737                 if (m_port_op.num_pending_buffers)
5738                 {
5739                     retval = flush(port_index);
5740                 }
5741             }
5742         }
5743     }
5744     else if (port_index == OMX_ALL)
5745     {
5746         if (m_port_ip.enabled == OMX_FALSE)
5747         {
5748             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5749 
5750             retval = OMX_ErrorBadPortIndex;
5751         }
5752         else if (m_port_op.enabled == OMX_FALSE)
5753         {
5754             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5755 
5756             retval = OMX_ErrorBadPortIndex;
5757         }
5758         else
5759         {
5760             if (m_port_ip.unpopulated && m_port_op.unpopulated)
5761             {
5762                 *p_cmd_ack = true;
5763             }
5764             else
5765             {
5766                 m_port_ip.enabled = OMX_FALSE;
5767                 m_port_op.enabled = OMX_FALSE;
5768 
5769                 if (m_port_ip.unpopulated == OMX_FALSE)
5770                 {
5771                     m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5772 
5773                     OMX_SWVDEC_LOG_LOW("ip port disable pending");
5774 
5775                     if (m_port_ip.num_pending_buffers)
5776                     {
5777                         retval = flush(port_index);
5778                     }
5779                 }
5780 
5781                 if ((retval == OMX_ErrorNone) &&
5782                     (m_port_op.unpopulated == OMX_FALSE))
5783                 {
5784                     m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5785 
5786                     OMX_SWVDEC_LOG_LOW("op port disable pending");
5787 
5788                     if (m_port_op.num_pending_buffers)
5789                     {
5790                         retval = flush(port_index);
5791                     }
5792                 }
5793             }
5794         }
5795     }
5796     else
5797     {
5798         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
5799                              port_index);
5800 
5801         retval = OMX_ErrorBadPortIndex;
5802     }
5803 
5804     return retval;
5805 }
5806 
5807 /**
5808  * @brief Process OMX_CommandPortEnable.
5809  *
5810  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5811  * @param[in]     port_index: Index of port to enable.
5812  *
5813  * @retval OMX_ERRORTYPE
5814  */
async_process_event_cmd_port_enable(bool * p_cmd_ack,unsigned int port_index)5815 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable(
5816     bool        *p_cmd_ack,
5817     unsigned int port_index)
5818 {
5819     OMX_ERRORTYPE retval = OMX_ErrorNone;
5820 
5821     OMX_SWVDEC_LOG_HIGH("enable port index %d requested", port_index);
5822 
5823     if (port_index == OMX_CORE_PORT_INDEX_IP)
5824     {
5825         if (m_port_ip.enabled)
5826         {
5827             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5828 
5829             retval = OMX_ErrorBadPortIndex;
5830         }
5831         else
5832         {
5833             m_port_ip.enabled = OMX_TRUE;
5834 
5835             if (m_port_ip.populated)
5836             {
5837                 *p_cmd_ack = true;
5838             }
5839             else
5840             {
5841                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5842 
5843                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5844             }
5845         }
5846     }
5847     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5848     {
5849         if (m_port_op.enabled)
5850         {
5851             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5852 
5853             retval = OMX_ErrorBadPortIndex;
5854         }
5855         else
5856         {
5857             m_port_op.enabled = OMX_TRUE;
5858 
5859             if (m_port_op.populated)
5860             {
5861                 *p_cmd_ack = true;
5862             }
5863             else
5864             {
5865                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5866 
5867                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5868             }
5869         }
5870     }
5871     else if (port_index == OMX_ALL)
5872     {
5873         if (m_port_ip.enabled)
5874         {
5875             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5876 
5877             retval = OMX_ErrorBadPortIndex;
5878         }
5879         else if (m_port_op.enabled)
5880         {
5881             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5882 
5883             retval = OMX_ErrorBadPortIndex;
5884         }
5885         else
5886         {
5887             m_port_ip.enabled = OMX_TRUE;
5888             m_port_op.enabled = OMX_TRUE;
5889 
5890             if (m_port_ip.populated && m_port_op.populated)
5891             {
5892                 *p_cmd_ack = true;
5893             }
5894             else if (m_port_ip.populated == false)
5895             {
5896                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5897 
5898                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5899             }
5900             else if (m_port_op.populated == false)
5901             {
5902                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5903 
5904                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5905             }
5906         }
5907     }
5908     else
5909     {
5910         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
5911                              port_index);
5912 
5913         retval = OMX_ErrorBadPortIndex;
5914     }
5915 
5916     return retval;
5917 }
5918 
5919 /**
5920  * @brief Process ETB event.
5921  *
5922  * @param[in] p_buffer_hdr: Pointer to buffer header.
5923  * @param[in] index:        Index of buffer in input buffer info array.
5924  *
5925  * @retval OMX_ERRORTYPE
5926  */
async_process_event_etb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5927 OMX_ERRORTYPE omx_swvdec::async_process_event_etb(
5928     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5929     unsigned int          index)
5930 {
5931     OMX_ERRORTYPE retval = OMX_ErrorNone;
5932 
5933     m_port_ip.num_pending_buffers++;
5934 
5935     if ((p_buffer_hdr->nFilledLen == 0) &&
5936         ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5937     {
5938         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p,"
5939                             "zero length & no EOS flag",
5940                             p_buffer_hdr,
5941                             p_buffer_hdr->pBuffer);
5942 
5943         async_post_event(OMX_SWVDEC_EVENT_EBD,
5944                          (unsigned long) p_buffer_hdr,
5945                          (unsigned long) index);
5946     }
5947     else if (m_port_ip.flush_inprogress)
5948     {
5949         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5950                             "ip port flush in progress",
5951                             p_buffer_hdr,
5952                             p_buffer_hdr->pBuffer);
5953 
5954         async_post_event(OMX_SWVDEC_EVENT_EBD,
5955                          (unsigned long) p_buffer_hdr,
5956                          (unsigned long) index);
5957     }
5958     else
5959     {
5960         SWVDEC_STATUS retval_swvdec;
5961 
5962         SWVDEC_BUFFER *p_buffer_swvdec =
5963             &(m_buffer_array_ip[index].buffer_swvdec);
5964 
5965         if (p_buffer_hdr->nFilledLen &&
5966             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5967         {
5968             m_queue_timestamp.push(p_buffer_hdr->nTimeStamp);
5969         }
5970 
5971         assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer);
5972         //sending the fd info
5973         p_buffer_swvdec->fd = m_buffer_array_ip[index].buffer_payload.pmem_fd;
5974         if (m_arbitrary_bytes_mode &&
5975             p_buffer_hdr->nFilledLen &&
5976             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5977         {
5978             unsigned int offset_array[OMX_SWVDEC_MAX_FRAMES_PER_ETB] = {0};
5979 
5980             unsigned int num_frame_headers = 1;
5981 
5982             if ((m_omx_video_codingtype ==
5983                  ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)) ||
5984                 (m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4))
5985             {
5986                 num_frame_headers = split_buffer_mpeg4(offset_array,
5987                                                        p_buffer_hdr);
5988             }
5989             else
5990             {
5991                 assert(0);
5992             }
5993 
5994             if(num_frame_headers > 1)
5995             {
5996                 m_buffer_array_ip[index].split_count = num_frame_headers - 1;
5997 
5998                 for (unsigned int ii = 0; ii < num_frame_headers; ii++)
5999                 {
6000                     p_buffer_swvdec->flags     = p_buffer_hdr->nFlags;
6001                     p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp;
6002 
6003                     if (ii == 0)
6004                     {
6005                         p_buffer_swvdec->offset        = 0;
6006                         p_buffer_swvdec->filled_length = (offset_array[ii + 1] ?
6007                                                           offset_array[ii + 1] :
6008                                                           p_buffer_hdr->nFilledLen);
6009                     }
6010                     else
6011                     {
6012                         p_buffer_swvdec->offset        = offset_array[ii];
6013                         p_buffer_swvdec->filled_length =
6014                             p_buffer_hdr->nFilledLen - offset_array[ii];
6015                     }
6016 
6017                     m_diag.dump_ip(p_buffer_swvdec->p_buffer +
6018                                    p_buffer_swvdec->offset,
6019                                    p_buffer_swvdec->filled_length);
6020 
6021                     retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6022                                                            p_buffer_swvdec);
6023 
6024                     if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6025                     {
6026                         retval = retval_swvdec2omx(retval_swvdec);
6027                         break;
6028                     }
6029                 }
6030             }
6031             else
6032             {
6033                 OMX_SWVDEC_LOG_HIGH("No frame detected for Buffer %p, with TS %lld",
6034                                     p_buffer_hdr->pBuffer, p_buffer_hdr->nTimeStamp );
6035 
6036                 p_buffer_swvdec->flags         = p_buffer_hdr->nFlags;
6037                 p_buffer_swvdec->offset        = 0;
6038                 p_buffer_swvdec->timestamp     = p_buffer_hdr->nTimeStamp;
6039                 p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
6040 
6041                 m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset,
6042                                p_buffer_swvdec->filled_length);
6043 
6044                 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6045                                                        p_buffer_swvdec);
6046 
6047                 if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6048                 {
6049                     retval = retval_swvdec2omx(retval_swvdec);
6050                 }
6051             }
6052         }
6053         else
6054         {
6055             p_buffer_swvdec->flags         = p_buffer_hdr->nFlags;
6056             p_buffer_swvdec->offset        = 0;
6057             p_buffer_swvdec->timestamp     = p_buffer_hdr->nTimeStamp;
6058             p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
6059 
6060             m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset,
6061                            p_buffer_swvdec->filled_length);
6062 
6063             retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6064                                                    p_buffer_swvdec);
6065 
6066             if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6067             {
6068                 retval = retval_swvdec2omx(retval_swvdec);
6069             }
6070         }
6071     }
6072     return retval;
6073 }
6074 
6075 /**
6076  * @brief Process FTB event.
6077  *
6078  * @param[in] p_buffer_hdr: Pointer to buffer header.
6079  * @param[in] index:        Index of buffer in output buffer info array.
6080  *
6081  * @retval OMX_ERRORTYPE
6082  */
async_process_event_ftb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6083 OMX_ERRORTYPE omx_swvdec::async_process_event_ftb(
6084     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6085     unsigned int          index)
6086 {
6087     OMX_ERRORTYPE retval = OMX_ErrorNone;
6088 
6089     m_port_op.num_pending_buffers++;
6090 
6091     if (m_port_op.flush_inprogress)
6092     {
6093         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
6094                             "op port flush in progress",
6095                             p_buffer_hdr,
6096                             m_buffer_array_op[index].buffer_swvdec.p_buffer);
6097 
6098         async_post_event(OMX_SWVDEC_EVENT_FBD,
6099                          (unsigned long) p_buffer_hdr,
6100                          (unsigned long) index);
6101     }
6102     else
6103     {
6104         SWVDEC_STATUS retval_swvdec;
6105 
6106         SWVDEC_BUFFER *p_buffer_swvdec =
6107             &(m_buffer_array_op[index].buffer_swvdec);
6108         p_buffer_swvdec->fd = m_buffer_array_op[index].buffer_payload.pmem_fd;
6109         retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec);
6110 
6111         if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6112         {
6113             retval = retval_swvdec2omx(retval_swvdec);
6114         }
6115     }
6116 
6117     return retval;
6118 }
6119 
6120 /**
6121  * @brief Process EBD event.
6122  *
6123  * @param[in] p_buffer_hdr: Pointer to buffer header.
6124  * @param[in] index:        Index of buffer in output buffer info array.
6125  *
6126  * @retval OMX_ERRORTYPE
6127  */
async_process_event_ebd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6128 OMX_ERRORTYPE omx_swvdec::async_process_event_ebd(
6129     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6130     unsigned int          index)
6131 {
6132     OMX_ERRORTYPE retval = OMX_ErrorNone;
6133 
6134     if (index < m_port_ip.def.nBufferCountActual)
6135     {
6136         if (m_arbitrary_bytes_mode && m_buffer_array_ip[index].split_count)
6137         {
6138             m_buffer_array_ip[index].split_count--;
6139         }
6140         else
6141         {
6142             m_port_ip.num_pending_buffers--;
6143 
6144             OMX_SWVDEC_LOG_CALLBACK(
6145                 "EmptyBufferDone(): %p, buffer %p",
6146                 p_buffer_hdr,
6147                 m_buffer_array_ip[index].buffer_swvdec.p_buffer);
6148 
6149             m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
6150         }
6151     }
6152     else
6153     {
6154         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
6155 
6156         retval = OMX_ErrorBadParameter;
6157     }
6158 
6159     return retval;
6160 }
6161 
6162 /**
6163  * @brief Process FBD event.
6164  *
6165  * @param[in] p_buffer_hdr: Pointer to buffer header.
6166  * @param[in] index:        Index of buffer in output buffer info array.
6167  *
6168  * @retval OMX_ERRORTYPE
6169  */
async_process_event_fbd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6170 OMX_ERRORTYPE omx_swvdec::async_process_event_fbd(
6171     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6172     unsigned int          index)
6173 {
6174     OMX_ERRORTYPE retval = OMX_ErrorNone;
6175 
6176     static long long timestamp_prev = 0;
6177 
6178     if (index < m_port_op.def.nBufferCountActual)
6179     {
6180         OMX_U8 *p_buffer;
6181 
6182         p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer;
6183 
6184         m_port_op.num_pending_buffers--;
6185 
6186         if (m_port_op.flush_inprogress)
6187         {
6188             p_buffer_hdr->nFilledLen = 0;
6189             p_buffer_hdr->nTimeStamp = 0;
6190             p_buffer_hdr->nFlags    &= ~OMX_BUFFERFLAG_DATACORRUPT;
6191         }
6192 
6193         if (p_buffer_hdr->nFilledLen)
6194         {
6195             if (m_sync_frame_decoding_mode)
6196             {
6197                 OMX_SWVDEC_LOG_LOW("sync frame decoding mode; "
6198                                    "setting timestamp to zero");
6199 
6200                 p_buffer_hdr->nTimeStamp = 0;
6201             }
6202             else
6203             {
6204                 if (m_queue_timestamp.empty())
6205                 {
6206                     OMX_SWVDEC_LOG_ERROR("timestamp queue empty; "
6207                                          "re-using previous timestamp %lld",
6208                                          timestamp_prev);
6209 
6210                     p_buffer_hdr->nTimeStamp = timestamp_prev;
6211                 }
6212                 else
6213                 {
6214                     p_buffer_hdr->nTimeStamp = m_queue_timestamp.top();
6215 
6216                     m_queue_timestamp.pop();
6217 
6218                     timestamp_prev = p_buffer_hdr->nTimeStamp;
6219                 }
6220             }
6221 
6222             ion_flush_op(index);
6223 
6224             if (m_meta_buffer_mode)
6225             {
6226                 pthread_mutex_lock(&m_meta_buffer_array_mutex);
6227             }
6228 
6229             m_diag.dump_op(p_buffer,
6230                            m_frame_dimensions.width,
6231                            m_frame_dimensions.height,
6232                            m_frame_attributes.stride,
6233                            m_frame_attributes.scanlines);
6234 
6235             if (m_meta_buffer_mode)
6236             {
6237                 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
6238             }
6239         }
6240         else
6241         {
6242             OMX_SWVDEC_LOG_LOW("filled length zero; "
6243                                "setting timestamp to zero");
6244 
6245             p_buffer_hdr->nTimeStamp = 0;
6246         }
6247 
6248         if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS)
6249         {
6250             async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0);
6251 
6252             OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue",
6253                                m_queue_timestamp.size());
6254 
6255             while (m_queue_timestamp.empty() == false)
6256             {
6257                 m_queue_timestamp.pop();
6258             }
6259         }
6260 
6261         if (m_meta_buffer_mode &&
6262             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0)
6263         {
6264             meta_buffer_ref_remove(index);
6265         }
6266 
6267         OMX_SWVDEC_LOG_CALLBACK(
6268             "FillBufferDone(): %p, buffer %p, "
6269             "flags 0x%08x, filled length %d, timestamp %lld",
6270             p_buffer_hdr,
6271             p_buffer,
6272             p_buffer_hdr->nFlags,
6273             p_buffer_hdr->nFilledLen,
6274             p_buffer_hdr->nTimeStamp);
6275 
6276         m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
6277     }
6278     else
6279     {
6280         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
6281 
6282         retval = OMX_ErrorBadParameter;
6283     }
6284 
6285     return retval;
6286 }
6287 
6288 /**
6289  * @brief Process EOS event.
6290  *
6291  * @retval OMX_ErrorNone
6292  */
async_process_event_eos()6293 OMX_ERRORTYPE omx_swvdec::async_process_event_eos()
6294 {
6295     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6296                             "OMX_EventBufferFlag, port index %d, EOS",
6297                             OMX_CORE_PORT_INDEX_OP);
6298 
6299     m_callback.EventHandler(&m_cmp,
6300                             m_app_data,
6301                             OMX_EventBufferFlag,
6302                             OMX_CORE_PORT_INDEX_OP,
6303                             OMX_BUFFERFLAG_EOS,
6304                             NULL);
6305 
6306     return OMX_ErrorNone;
6307 }
6308 
6309 /**
6310  * @brief Process input port flush event.
6311  *
6312  * @retval OMX_ERRORTYPE
6313  */
async_process_event_flush_port_ip()6314 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip()
6315 {
6316     OMX_ERRORTYPE retval = OMX_ErrorNone;
6317 
6318     OMX_SWVDEC_EVENT_INFO event_info;
6319 
6320     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
6321 
6322     unsigned int index;
6323 
6324     while (m_queue_port_ip.pop(&event_info))
6325     {
6326         switch (event_info.event_id)
6327         {
6328 
6329         case OMX_SWVDEC_EVENT_ETB:
6330         {
6331             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6332 
6333             index = event_info.event_param2;
6334 
6335             // compensate decrement in async_process_event_ebd()
6336             m_port_ip.num_pending_buffers++;
6337 
6338             retval = async_process_event_ebd(p_buffer_hdr, index);
6339             break;
6340         }
6341 
6342         case OMX_SWVDEC_EVENT_EBD:
6343         {
6344             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6345 
6346             index = event_info.event_param2;
6347 
6348             retval = async_process_event_ebd(p_buffer_hdr, index);
6349             break;
6350         }
6351 
6352         default:
6353         {
6354             assert(0);
6355             break;
6356         }
6357 
6358         }
6359     }
6360 
6361     assert(m_port_ip.num_pending_buffers == 0);
6362 
6363     if ((retval == OMX_ErrorNone) &&
6364         (m_status_flags & (1 << PENDING_PORT_FLUSH_IP)))
6365     {
6366         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP);
6367 
6368         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6369                          OMX_CommandFlush,
6370                          OMX_CORE_PORT_INDEX_IP);
6371     }
6372 
6373     m_port_ip.flush_inprogress = OMX_FALSE;
6374 
6375     return retval;
6376 }
6377 
6378 /**
6379  * @brief Process output port flush event.
6380  *
6381  * @retval OMX_ERRORTYPE
6382  */
async_process_event_flush_port_op()6383 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op()
6384 {
6385     OMX_ERRORTYPE retval = OMX_ErrorNone;
6386 
6387     OMX_SWVDEC_EVENT_INFO event_info;
6388 
6389     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
6390 
6391     unsigned int index;
6392 
6393     while (m_queue_port_op.pop(&event_info))
6394     {
6395         switch (event_info.event_id)
6396         {
6397 
6398         case OMX_SWVDEC_EVENT_FTB:
6399         {
6400             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6401 
6402             index = event_info.event_param2;
6403 
6404             // compensate decrement in async_process_event_fbd()
6405             m_port_op.num_pending_buffers++;
6406 
6407             retval = async_process_event_fbd(p_buffer_hdr, index);
6408             break;
6409         }
6410 
6411         case OMX_SWVDEC_EVENT_FBD:
6412         {
6413             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6414 
6415             index = event_info.event_param2;
6416 
6417             retval = async_process_event_fbd(p_buffer_hdr, index);
6418             break;
6419         }
6420 
6421         default:
6422         {
6423             assert(0);
6424             break;
6425         }
6426 
6427         }
6428     }
6429 
6430     assert(m_port_op.num_pending_buffers == 0);
6431 
6432     if ((retval == OMX_ErrorNone) &&
6433         (m_status_flags & (1 << PENDING_PORT_FLUSH_OP)))
6434     {
6435         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP);
6436 
6437         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6438                          OMX_CommandFlush,
6439                          OMX_CORE_PORT_INDEX_OP);
6440     }
6441 
6442     if ((retval == OMX_ErrorNone) &&
6443         (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE)))
6444     {
6445         m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE);
6446 
6447         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6448                          OMX_CommandStateSet,
6449                          OMX_StateIdle);
6450     }
6451 
6452     if (m_port_reconfig_inprogress == false)
6453     {
6454         OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue",
6455                            m_queue_timestamp.size());
6456 
6457         while (m_queue_timestamp.empty() == false)
6458         {
6459             m_queue_timestamp.pop();
6460         }
6461     }
6462 
6463     m_port_op.flush_inprogress = OMX_FALSE;
6464 
6465     return retval;
6466 }
6467 
6468 /**
6469  * @brief Process port reconfiguration event.
6470  *
6471  * @retval OMX_ERRORTYPE
6472  */
async_process_event_port_reconfig()6473 OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig()
6474 {
6475     OMX_ERRORTYPE retval = OMX_ErrorNone;
6476 
6477     if (m_port_reconfig_inprogress)
6478     {
6479         OMX_SWVDEC_LOG_ERROR("port reconfiguration already in progress");
6480 
6481         retval = OMX_ErrorIncorrectStateOperation;
6482     }
6483     else
6484     {
6485         m_port_reconfig_inprogress = true;
6486 
6487         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6488                                 "OMX_EventPortSettingsChanged, port index %d",
6489                                 OMX_CORE_PORT_INDEX_OP);
6490 
6491         m_callback.EventHandler(&m_cmp,
6492                                 m_app_data,
6493                                 OMX_EventPortSettingsChanged,
6494                                 OMX_CORE_PORT_INDEX_OP,
6495                                 OMX_IndexParamPortDefinition,
6496                                 NULL);
6497     }
6498 
6499     return retval;
6500 }
6501 
6502 /**
6503  * @brief Process dimensions updated event.
6504  *
6505  * @retval OMX_ERRORTYPE
6506  */
async_process_event_dimensions_updated()6507 OMX_ERRORTYPE omx_swvdec::async_process_event_dimensions_updated()
6508 {
6509     OMX_ERRORTYPE retval = OMX_ErrorNone;
6510 
6511     if (m_dimensions_update_inprogress)
6512     {
6513         OMX_SWVDEC_LOG_ERROR("dimensions update already in progress");
6514 
6515         retval = OMX_ErrorIncorrectStateOperation;
6516     }
6517     else
6518     {
6519         m_dimensions_update_inprogress = true;
6520 
6521         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6522                                 "OMX_EventPortSettingsChanged, port index %d, "
6523                                 "OMX_IndexConfigCommonOutputCrop",
6524                                 OMX_CORE_PORT_INDEX_OP);
6525 
6526         m_callback.EventHandler(&m_cmp,
6527                                 m_app_data,
6528                                 OMX_EventPortSettingsChanged,
6529                                 OMX_CORE_PORT_INDEX_OP,
6530                                 OMX_IndexConfigCommonOutputCrop,
6531                                 NULL);
6532     }
6533 
6534     return retval;
6535 }
6536 
6537 /**
6538  * @brief Map the memory and run the ioctl SYNC operations
6539  *.on ION fd with DMA_BUF_IOCTL_SYNC
6540  *.@param[in] fd: ION header.
6541  * @param[in] len:Lenth of the memory.
6542  * @retval mapped memory pointer
6543  */
ion_map(int fd,int len)6544 unsigned char *omx_swvdec::ion_map(int fd, int len)
6545 {
6546     unsigned char *bufaddr = (unsigned char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
6547                                 MAP_SHARED, fd, 0);
6548     if (bufaddr != MAP_FAILED) {
6549 #ifdef USE_ION
6550         struct dma_buf_sync buf_sync;
6551         buf_sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
6552         int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync);
6553         if (rc) {
6554             OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC");
6555         }
6556 #endif
6557     }
6558     return bufaddr;
6559 }
6560 
6561 /**
6562  * @brief Unmap the memory
6563  *.@param[in] fd: ION header.
6564  .*.@param[in].bufaddr : buffer address
6565  * @param[in] len:Lenth of the memory.
6566  * @retval OMX_ERRORTYPE
6567  */
ion_unmap(int fd,void * bufaddr,int len)6568 OMX_ERRORTYPE omx_swvdec::ion_unmap(int fd, void *bufaddr, int len)
6569 {
6570 #ifdef USE_ION
6571     struct dma_buf_sync buf_sync;
6572     buf_sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
6573     int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync);
6574     if (rc) {
6575         OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC");
6576     }
6577 #endif
6578     if (-1 == munmap(bufaddr, len)) {
6579         OMX_SWVDEC_LOG_ERROR("munmap failed.");
6580         return OMX_ErrorInsufficientResources;
6581     }
6582     return OMX_ErrorNone;
6583 }
6584 
6585