• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             /* Content for which low delay is 0 for ex: XVID clips
3550                minimum two buffers are required to generate thumbnail */
3551             p_buffer_req->mincount = 2;
3552         }
3553 
3554         m_port_op.def.nBufferSize        = p_buffer_req->size;
3555         m_port_op.def.nBufferCountMin    = p_buffer_req->mincount;
3556         m_port_op.def.nBufferCountActual = MAX(p_buffer_req->mincount,
3557                                                m_port_op.def.nBufferCountActual);
3558         m_port_op.def.nBufferAlignment   = p_buffer_req->alignment;
3559 
3560         OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned",
3561                             m_port_op.def.nBufferSize,
3562                             m_port_op.def.nBufferCountActual,
3563                             m_port_op.def.nBufferAlignment);
3564     }
3565     else
3566     {
3567         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index);
3568 
3569         retval = OMX_ErrorBadPortIndex;
3570     }
3571 
3572 get_buffer_requirements_swvdec_exit:
3573     return retval;
3574 }
3575 
3576 /**
3577  * @brief Allocate input buffer, and input buffer info array if ncessary.
3578  *
3579  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3580  *                               structure.
3581  * @param[in]     p_app_data:    Pointer to IL client app data.
3582  * @param[in]     size:          Size of buffer to be allocated in bytes.
3583  *
3584  * @retval OMX_ERRORTYPE
3585  */
buffer_allocate_ip(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3586 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip(
3587     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3588     OMX_PTR                p_app_data,
3589     OMX_U32                size)
3590 {
3591     OMX_ERRORTYPE retval = OMX_ErrorNone;
3592     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
3593 
3594     unsigned int ii;
3595 
3596     if (size != m_port_ip.def.nBufferSize)
3597     {
3598         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3599                              "configured size (%d bytes)",
3600                              size,
3601                              m_port_ip.def.nBufferSize);
3602 
3603         return OMX_ErrorBadParameter;
3604     }
3605 
3606     if (m_buffer_array_ip == NULL)
3607     {
3608         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3609                             m_port_ip.def.nBufferCountActual,
3610                             (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3611 
3612         if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone)
3613         {
3614             return retval;
3615         }
3616     }
3617 
3618     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3619     {
3620         if (m_buffer_array_ip[ii].buffer_populated == false)
3621         {
3622             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3623             break;
3624         }
3625     }
3626 
3627     if (ii < m_port_ip.def.nBufferCountActual)
3628     {
3629         int pmem_fd = -1;
3630 
3631         unsigned char *bufferaddr;
3632 
3633         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated",
3634                             ii,
3635                             size);
3636 
3637         m_buffer_array_ip[ii].ion_info.dev_fd=
3638             ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info,size,
3639                                   m_port_ip.def.nBufferAlignment);
3640 
3641         if (m_buffer_array_ip[ii].ion_info.dev_fd< 0)
3642         {
3643             return OMX_ErrorInsufficientResources;
3644         }
3645 
3646         pmem_fd = m_buffer_array_ip[ii].ion_info.data_fd;
3647 
3648         bufferaddr = ion_map(pmem_fd,size);
3649 
3650         if (bufferaddr == MAP_FAILED)
3651         {
3652             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d error %s",
3653                                  pmem_fd,
3654                                  size, strerror(errno));
3655 
3656             close(pmem_fd);
3657             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3658 
3659             return OMX_ErrorInsufficientResources;
3660         }
3661 
3662         *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3663 
3664         m_buffer_array_ip[ii].buffer_payload.bufferaddr  = bufferaddr;
3665         m_buffer_array_ip[ii].buffer_payload.pmem_fd     = pmem_fd;
3666         m_buffer_array_ip[ii].buffer_payload.buffer_len  = size;
3667         m_buffer_array_ip[ii].buffer_payload.mmaped_size = size;
3668         m_buffer_array_ip[ii].buffer_payload.offset      = 0;
3669 
3670         m_buffer_array_ip[ii].buffer_swvdec.p_buffer      = bufferaddr;
3671         m_buffer_array_ip[ii].buffer_swvdec.size          = size;
3672         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3673             (void *) ((unsigned long) ii);
3674         m_buffer_array_ip[ii].buffer_swvdec.fd = pmem_fd;
3675 
3676         m_buffer_array_ip[ii].buffer_populated = true;
3677 
3678         if(m_swvdec_codec == SWVDEC_CODEC_VC1)
3679         {
3680             OMX_SWVDEC_LOG_LOW("map ip buffer");
3681 
3682             if((retval_swvdec = swvdec_register_buffer(m_swvdec_handle,
3683                                                        &m_buffer_array_ip[ii].buffer_swvdec))
3684                != SWVDEC_STATUS_SUCCESS)
3685             {
3686                 OMX_SWVDEC_LOG_ERROR("swvdec_map failed for ip buffer %d: %p",ii,bufferaddr);
3687 
3688                 close(pmem_fd);
3689                 ion_memory_free(&m_buffer_array_ip[ii].ion_info);
3690 
3691                 return retval_swvdec2omx(retval_swvdec);
3692             }
3693         }
3694 
3695         OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, fd = %d %d bytes",
3696                             ii,
3697                             bufferaddr,
3698                             pmem_fd,
3699                             size);
3700 
3701         (*pp_buffer_hdr)->pBuffer           = (OMX_U8 *) bufferaddr;
3702         (*pp_buffer_hdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
3703         (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
3704         (*pp_buffer_hdr)->nAllocLen         = size;
3705         (*pp_buffer_hdr)->pAppPrivate       = p_app_data;
3706         (*pp_buffer_hdr)->nInputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3707         (*pp_buffer_hdr)->pInputPortPrivate =
3708             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3709 
3710         m_port_ip.populated   = port_ip_populated();
3711         m_port_ip.unpopulated = OMX_FALSE;
3712     }
3713     else
3714     {
3715         OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated",
3716                              m_port_ip.def.nBufferCountActual);
3717 
3718         return OMX_ErrorInsufficientResources;
3719     }
3720 
3721     return retval;
3722 }
3723 
3724 /**
3725  * @brief Allocate output buffer, and output buffer info array if necessary.
3726  *
3727  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
3728  *                               structure.
3729  * @param[in]     p_app_data:    Pointer to IL client app data.
3730  * @param[in]     size:          Size of buffer to be allocated in bytes.
3731  *
3732  * @retval OMX_ERRORTYPE
3733  */
buffer_allocate_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size)3734 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op(
3735     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
3736     OMX_PTR                p_app_data,
3737     OMX_U32                size)
3738 {
3739     OMX_ERRORTYPE retval = OMX_ErrorNone;
3740     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
3741     unsigned int ii;
3742 
3743     if (size != m_port_op.def.nBufferSize)
3744     {
3745         OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
3746                              "configured size (%d bytes)",
3747                              size,
3748                              m_port_op.def.nBufferSize);
3749 
3750         return OMX_ErrorBadParameter;
3751     }
3752 
3753     if (m_buffer_array_op == NULL)
3754     {
3755         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3756                             m_port_op.def.nBufferCountActual,
3757                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3758 
3759         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
3760         {
3761             return retval;
3762         }
3763     }
3764 
3765     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3766     {
3767         if (m_buffer_array_op[ii].buffer_populated == false)
3768         {
3769             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
3770             break;
3771         }
3772     }
3773 
3774     if (ii < m_port_op.def.nBufferCountActual)
3775     {
3776         int pmem_fd = -1;
3777 
3778         unsigned char *bufferaddr;
3779 
3780         OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated",
3781                             ii,
3782                             size);
3783 
3784         m_buffer_array_op[ii].ion_info.dev_fd=
3785             ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info,size,
3786                                  m_port_op.def.nBufferAlignment);
3787 
3788         if (m_buffer_array_op[ii].ion_info.dev_fd < 0)
3789         {
3790             return OMX_ErrorInsufficientResources;
3791         }
3792 
3793         pmem_fd = m_buffer_array_op[ii].ion_info.data_fd;
3794 
3795         bufferaddr = ion_map(pmem_fd,size);
3796 
3797         if (bufferaddr == MAP_FAILED)
3798         {
3799             OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
3800                                  pmem_fd,
3801                                  size);
3802 
3803             close(pmem_fd);
3804             ion_memory_free(&m_buffer_array_op[ii].ion_info);
3805 
3806             return OMX_ErrorInsufficientResources;
3807         }
3808 
3809         *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3810 
3811         m_buffer_array_op[ii].buffer_payload.bufferaddr  = bufferaddr;
3812         m_buffer_array_op[ii].buffer_payload.pmem_fd     = pmem_fd;
3813         m_buffer_array_op[ii].buffer_payload.buffer_len  = size;
3814         m_buffer_array_op[ii].buffer_payload.mmaped_size = size;
3815         m_buffer_array_op[ii].buffer_payload.offset      = 0;
3816 
3817         m_buffer_array_op[ii].buffer_swvdec.p_buffer      = bufferaddr;
3818         m_buffer_array_op[ii].buffer_swvdec.size          = size;
3819         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3820             (void *) ((unsigned long) ii);
3821 
3822         m_buffer_array_op[ii].buffer_populated = true;
3823 
3824         m_buffer_array_op[ii].buffer_swvdec.fd            = pmem_fd ;
3825 
3826         if(m_swvdec_codec == SWVDEC_CODEC_VC1)
3827         {
3828             OMX_SWVDEC_LOG_LOW("map op buffer");
3829 
3830             if((retval_swvdec = swvdec_map(m_swvdec_handle,&m_buffer_array_op[ii].buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
3831             {
3832                 OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,bufferaddr);
3833 
3834                 close(pmem_fd);
3835                 ion_memory_free(&m_buffer_array_op[ii].ion_info);
3836 
3837                 return retval_swvdec2omx(retval_swvdec);
3838             }
3839         }
3840         OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, fd = %d %d bytes",
3841                             ii,
3842                             bufferaddr,
3843                             pmem_fd,
3844                             size);
3845 
3846         (*pp_buffer_hdr)->pBuffer            = (OMX_U8 *) bufferaddr;
3847         (*pp_buffer_hdr)->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3848         (*pp_buffer_hdr)->nVersion.nVersion  = OMX_SPEC_VERSION;
3849         (*pp_buffer_hdr)->nAllocLen          = size;
3850         (*pp_buffer_hdr)->pAppPrivate        = p_app_data;
3851         (*pp_buffer_hdr)->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3852         (*pp_buffer_hdr)->pOutputPortPrivate =
3853             (void *) &(m_buffer_array_op[ii].buffer_payload);
3854 
3855         m_port_op.populated   = port_op_populated();
3856         m_port_op.unpopulated = OMX_FALSE;
3857     }
3858     else
3859     {
3860         OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated",
3861                              m_port_op.def.nBufferCountActual);
3862 
3863         retval = OMX_ErrorInsufficientResources;
3864     }
3865 
3866     return retval;
3867 }
3868 
3869 /**
3870  * @brief Allocate input buffer info array.
3871  */
buffer_allocate_ip_info_array()3872 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array()
3873 {
3874     OMX_ERRORTYPE retval = OMX_ErrorNone;
3875 
3876     unsigned int ii;
3877 
3878     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3879 
3880     if (m_buffer_array_ip != NULL)
3881     {
3882         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3883 
3884         retval = OMX_ErrorInsufficientResources;
3885         goto buffer_allocate_ip_info_array_exit;
3886     }
3887 
3888     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3889                         m_port_ip.def.nBufferCountActual,
3890                         (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
3891 
3892     m_buffer_array_ip =
3893         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3894                                           m_port_ip.def.nBufferCountActual);
3895 
3896     if (m_buffer_array_ip == NULL)
3897     {
3898         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3899                              "%d element%s, %zu bytes requested",
3900                              m_port_ip.def.nBufferCountActual,
3901                              (m_port_ip.def.nBufferCountActual > 1) ? "s" : "",
3902                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3903                              m_port_ip.def.nBufferCountActual);
3904 
3905         retval = OMX_ErrorInsufficientResources;
3906         goto buffer_allocate_ip_info_array_exit;
3907     }
3908 
3909     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
3910     {
3911         p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
3912 
3913         // reset file descriptors
3914 
3915         m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
3916         m_buffer_array_ip[ii].ion_info.dev_fd= -1;
3917 
3918         m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
3919             (void *) ((unsigned long) ii);
3920 
3921         p_buffer_hdr->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
3922         p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
3923         p_buffer_hdr->nInputPortIndex   = OMX_CORE_PORT_INDEX_IP;
3924         p_buffer_hdr->pInputPortPrivate =
3925             (void *) &(m_buffer_array_ip[ii].buffer_payload);
3926     }
3927 
3928 buffer_allocate_ip_info_array_exit:
3929     return retval;
3930 }
3931 
3932 /**
3933  * @brief Allocate output buffer info array.
3934  */
buffer_allocate_op_info_array()3935 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array()
3936 {
3937     OMX_ERRORTYPE retval = OMX_ErrorNone;
3938 
3939     unsigned int ii;
3940 
3941     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
3942 
3943     if (m_buffer_array_op != NULL)
3944     {
3945         OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
3946 
3947         retval = OMX_ErrorInsufficientResources;
3948         goto buffer_allocate_op_info_array_exit;
3949     }
3950 
3951     OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
3952                         m_port_op.def.nBufferCountActual,
3953                         (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
3954 
3955     m_buffer_array_op =
3956         (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
3957                                           m_port_op.def.nBufferCountActual);
3958 
3959     if (m_buffer_array_op == NULL)
3960     {
3961         OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
3962                              "%d element%s, %zu bytes requested",
3963                              m_port_op.def.nBufferCountActual,
3964                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
3965                              sizeof(OMX_SWVDEC_BUFFER_INFO) *
3966                              m_port_op.def.nBufferCountActual);
3967 
3968         retval = OMX_ErrorInsufficientResources;
3969         goto buffer_allocate_op_info_array_exit;
3970     }
3971 
3972     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
3973     {
3974         p_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
3975 
3976         // reset file descriptors
3977 
3978         m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
3979         m_buffer_array_op[ii].ion_info.dev_fd = -1;
3980 
3981         m_buffer_array_op[ii].buffer_swvdec.p_client_data =
3982             (void *) ((unsigned long) ii);
3983 
3984         p_buffer_hdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
3985         p_buffer_hdr->nVersion.nVersion  = OMX_SPEC_VERSION;
3986         p_buffer_hdr->nOutputPortIndex   = OMX_CORE_PORT_INDEX_OP;
3987         p_buffer_hdr->pOutputPortPrivate =
3988             (void *) &(m_buffer_array_op[ii].buffer_payload);
3989     }
3990 
3991 buffer_allocate_op_info_array_exit:
3992     return retval;
3993 }
3994 
3995 /**
3996  * @brief Use buffer allocated by IL client; allocate output buffer info array
3997  *        if necessary.
3998  *
3999  * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
4000  *                               structure.
4001  * @param[in]     p_app_data:    Pointer to IL client app data.
4002  * @param[in]     size:          Size of buffer to be allocated in bytes.
4003  * @param[in]     p_buffer:      Pointer to buffer to be used.
4004  *
4005  * @retval OMX_ERRORTYPE
4006  */
buffer_use_op(OMX_BUFFERHEADERTYPE ** pp_buffer_hdr,OMX_PTR p_app_data,OMX_U32 size,OMX_U8 * p_buffer)4007 OMX_ERRORTYPE omx_swvdec::buffer_use_op(
4008     OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
4009     OMX_PTR                p_app_data,
4010     OMX_U32                size,
4011     OMX_U8                *p_buffer)
4012 {
4013     OMX_ERRORTYPE retval = OMX_ErrorNone;
4014     SWVDEC_STATUS retval_swvdec;
4015     unsigned int ii;
4016 
4017     (void) size;
4018 
4019     if (m_buffer_array_op == NULL)
4020     {
4021         OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
4022                             m_port_op.def.nBufferCountActual,
4023                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
4024 
4025         if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
4026         {
4027             goto buffer_use_op_exit;
4028         }
4029     }
4030 
4031     if (m_meta_buffer_mode && (m_meta_buffer_array == NULL))
4032     {
4033         OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s",
4034                             m_port_op.def.nBufferCountActual,
4035                             (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
4036 
4037         if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone)
4038         {
4039             goto buffer_use_op_exit;
4040         }
4041     }
4042 
4043     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4044     {
4045         if (m_buffer_array_op[ii].buffer_populated == false)
4046         {
4047             OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
4048             break;
4049         }
4050     }
4051 
4052     if (ii < m_port_op.def.nBufferCountActual)
4053     {
4054         struct vdec_bufferpayload *p_buffer_payload;
4055 
4056         SWVDEC_BUFFER *p_buffer_swvdec;
4057 
4058         *pp_buffer_hdr   = &m_buffer_array_op[ii].buffer_header;
4059         p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
4060         p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4061 
4062         if (m_meta_buffer_mode)
4063         {
4064             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
4065             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
4066 
4067             m_buffer_array_op[ii].buffer_populated = true;
4068 
4069             (*pp_buffer_hdr)->pBuffer     = p_buffer;
4070             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
4071             (*pp_buffer_hdr)->nAllocLen   =
4072                 sizeof(struct VideoDecoderOutputMetaData);
4073 
4074             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)",
4075                                 ii,
4076                                 *pp_buffer_hdr);
4077 
4078             m_port_op.populated   = port_op_populated();
4079             m_port_op.unpopulated = OMX_FALSE;
4080         }
4081         else if (m_android_native_buffers)
4082         {
4083             private_handle_t *p_handle;
4084 
4085             OMX_U8 *p_buffer_mapped;
4086 
4087             p_handle = (private_handle_t *) p_buffer;
4088 
4089             if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize)
4090             {
4091                 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
4092                                      "configured size (%d bytes)",
4093                                      p_handle->size,
4094                                      m_port_op.def.nBufferSize);
4095 
4096                 retval = OMX_ErrorBadParameter;
4097                 goto buffer_use_op_exit;
4098             }
4099 
4100             m_port_op.def.nBufferSize = p_handle->size;
4101 
4102             p_buffer_mapped = ion_map(p_handle->fd,p_handle->size);
4103 
4104             if (p_buffer_mapped == MAP_FAILED)
4105             {
4106                 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
4107                                      p_handle->fd,
4108                                      p_handle->size);
4109 
4110                 retval = OMX_ErrorInsufficientResources;
4111                 goto buffer_use_op_exit;
4112             }
4113 
4114             p_buffer_payload->bufferaddr  = p_buffer_mapped;
4115             p_buffer_payload->pmem_fd     = p_handle->fd;
4116             p_buffer_payload->buffer_len  = p_handle->size;
4117             p_buffer_payload->mmaped_size = p_handle->size;
4118             p_buffer_payload->offset      = 0;
4119 
4120             p_buffer_swvdec->p_buffer      = p_buffer_mapped;
4121             p_buffer_swvdec->size          = m_port_op.def.nBufferSize;
4122             p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
4123             p_buffer_swvdec->fd            = p_buffer_payload->pmem_fd ;
4124 
4125             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4126             {
4127                 OMX_SWVDEC_LOG_LOW("map op buffer");
4128 
4129                 if((retval_swvdec = swvdec_map(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4130                 {
4131                     OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,p_buffer_mapped);
4132                     retval = retval_swvdec2omx(retval_swvdec);;
4133                     goto buffer_use_op_exit;
4134                 }
4135             }
4136             m_buffer_array_op[ii].buffer_populated = true;
4137 
4138             (*pp_buffer_hdr)->pBuffer     = (m_android_native_buffers ?
4139                                              ((OMX_U8 *) p_handle) :
4140                                              p_buffer_mapped);
4141             (*pp_buffer_hdr)->pAppPrivate = p_app_data;
4142             (*pp_buffer_hdr)->nAllocLen   = m_port_op.def.nBufferSize;
4143 
4144             m_buffer_array_op[ii].ion_info.data_fd = p_handle->fd;
4145 
4146             OMX_SWVDEC_LOG_HIGH("op buffer %d: %p",
4147                                 ii,
4148                                 *pp_buffer_hdr);
4149 
4150             m_port_op.populated   = port_op_populated();
4151             m_port_op.unpopulated = OMX_FALSE;
4152         }
4153         else
4154         {
4155             OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor "
4156                                  "'android native buffers' enabled");
4157 
4158             retval = OMX_ErrorBadParameter;
4159         }
4160     }
4161     else
4162     {
4163         OMX_SWVDEC_LOG_ERROR("all %d op buffers populated",
4164                              m_port_op.def.nBufferCountActual);
4165 
4166         retval = OMX_ErrorInsufficientResources;
4167     }
4168 
4169 buffer_use_op_exit:
4170     return retval;
4171 }
4172 
4173 /**
4174  * @brief De-allocate input buffer.
4175  *
4176  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
4177  *
4178  * @retval OMX_ERRORTYPE
4179  */
buffer_deallocate_ip(OMX_BUFFERHEADERTYPE * p_buffer_hdr)4180 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip(
4181     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4182 {
4183     OMX_ERRORTYPE retval = OMX_ErrorNone;
4184     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
4185 
4186     unsigned int ii;
4187 
4188     if (p_buffer_hdr == NULL)
4189     {
4190         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
4191 
4192         retval = OMX_ErrorBadParameter;
4193         goto buffer_deallocate_ip_exit;
4194     }
4195     else if (m_buffer_array_ip == NULL)
4196     {
4197         OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated");
4198 
4199         retval = OMX_ErrorBadParameter;
4200         goto buffer_deallocate_ip_exit;
4201     }
4202 
4203     for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4204     {
4205         if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
4206         {
4207             OMX_SWVDEC_LOG_LOW("%p has index %d",
4208                                p_buffer_hdr->pBuffer,
4209                                ii);
4210             break;
4211         }
4212     }
4213 
4214     if (ii < m_port_ip.def.nBufferCountActual)
4215     {
4216         if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0)
4217         {
4218 
4219            if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4220             {
4221                 SWVDEC_BUFFER *p_buffer_swvdec;
4222                 p_buffer_swvdec  = &m_buffer_array_ip[ii].buffer_swvdec;
4223                 OMX_SWVDEC_LOG_LOW("unmap ip buffer");
4224 
4225                 if((retval_swvdec = swvdec_unregister_buffer(m_swvdec_handle,p_buffer_swvdec))
4226                    != SWVDEC_STATUS_SUCCESS)
4227                 {
4228                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for ip buffer %d: %p",
4229                                          ii,p_buffer_swvdec->p_buffer);
4230                     retval = retval_swvdec2omx(retval_swvdec);;
4231                 }
4232             }
4233 
4234             m_buffer_array_ip[ii].buffer_populated = false;
4235 
4236             m_port_ip.populated = OMX_FALSE;
4237 
4238             ion_unmap(m_buffer_array_ip[ii].buffer_payload.pmem_fd,
4239                       m_buffer_array_ip[ii].buffer_payload.bufferaddr,
4240                       m_buffer_array_ip[ii].buffer_payload.mmaped_size);
4241 
4242             close(m_buffer_array_ip[ii].buffer_payload.pmem_fd);
4243             m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
4244 
4245             ion_memory_free(&m_buffer_array_ip[ii].ion_info);
4246 
4247             for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4248             {
4249                 if (m_buffer_array_ip[ii].buffer_populated)
4250                 {
4251                     break;
4252                 }
4253             }
4254 
4255             if (ii == m_port_ip.def.nBufferCountActual)
4256             {
4257                 buffer_deallocate_ip_info_array();
4258 
4259                 m_port_ip.unpopulated = OMX_TRUE;
4260             }
4261         }
4262         else
4263         {
4264             OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d",
4265                                  p_buffer_hdr->pBuffer,
4266                                  m_buffer_array_ip[ii].buffer_payload.pmem_fd);
4267         }
4268     }
4269     else
4270     {
4271         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
4272 
4273         retval = OMX_ErrorBadParameter;
4274     }
4275 
4276 buffer_deallocate_ip_exit:
4277     return retval;
4278 }
4279 
4280 /**
4281  * @brief De-allocate output buffer.
4282  *
4283  * @param[in] p_buffer_hdr: Pointer to buffer header structure.
4284  *
4285  * @retval OMX_ERRORTYPE
4286  */
buffer_deallocate_op(OMX_BUFFERHEADERTYPE * p_buffer_hdr)4287 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op(
4288     OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4289 {
4290     OMX_ERRORTYPE retval = OMX_ErrorNone;
4291     SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS;
4292     unsigned int ii;
4293 
4294     if (p_buffer_hdr == NULL)
4295     {
4296         OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
4297 
4298         retval = OMX_ErrorBadParameter;
4299         goto buffer_deallocate_op_exit;
4300     }
4301     else if (m_buffer_array_op == NULL)
4302     {
4303         OMX_SWVDEC_LOG_ERROR("op buffer array not allocated");
4304 
4305         retval = OMX_ErrorBadParameter;
4306         goto buffer_deallocate_op_exit;
4307     }
4308 
4309     for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4310     {
4311         if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
4312         {
4313             OMX_SWVDEC_LOG_LOW("%p has index %d",
4314                                p_buffer_hdr->pBuffer,
4315                                ii);
4316             break;
4317         }
4318     }
4319 
4320     if (ii < m_port_op.def.nBufferCountActual)
4321     {
4322         if (m_meta_buffer_mode)
4323         {
4324             // do nothing; munmap() & FD reset done in FBD or RR
4325         }
4326         else if (m_android_native_buffers)
4327         {
4328 
4329             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4330             {
4331                 SWVDEC_BUFFER *p_buffer_swvdec;
4332                 p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4333                 OMX_SWVDEC_LOG_LOW("unmap op buffer");
4334 
4335                 if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4336                 {
4337                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer);
4338                     retval = retval_swvdec2omx(retval_swvdec);;
4339                 }
4340             }
4341             ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd ,
4342                       m_buffer_array_op[ii].buffer_payload.bufferaddr,
4343                       m_buffer_array_op[ii].buffer_payload.mmaped_size);
4344 
4345             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
4346         }
4347         else
4348         {
4349             if(m_swvdec_codec == SWVDEC_CODEC_VC1)
4350             {
4351                 SWVDEC_BUFFER *p_buffer_swvdec;
4352                 p_buffer_swvdec  = &m_buffer_array_op[ii].buffer_swvdec;
4353                 OMX_SWVDEC_LOG_LOW("unmap op buffer");
4354 
4355                 if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS)
4356                 {
4357                     OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer);
4358                     retval = retval_swvdec2omx(retval_swvdec);;
4359                 }
4360             }
4361             ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd,
4362                       m_buffer_array_op[ii].buffer_payload.bufferaddr,
4363                       m_buffer_array_op[ii].buffer_payload.mmaped_size);
4364 
4365             close(m_buffer_array_op[ii].buffer_payload.pmem_fd);
4366 
4367             m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
4368 
4369             ion_memory_free(&m_buffer_array_op[ii].ion_info);
4370         }
4371 
4372         m_buffer_array_op[ii].buffer_populated = false;
4373 
4374         m_port_op.populated = OMX_FALSE;
4375 
4376         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4377         {
4378             if (m_buffer_array_op[ii].buffer_populated)
4379             {
4380                 break;
4381             }
4382         }
4383 
4384         if (ii == m_port_op.def.nBufferCountActual)
4385         {
4386             buffer_deallocate_op_info_array();
4387 
4388             m_port_op.unpopulated = OMX_TRUE;
4389 
4390             if (m_meta_buffer_mode)
4391             {
4392                 meta_buffer_array_deallocate();
4393             }
4394         }
4395     }
4396     else
4397     {
4398         OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
4399 
4400         retval = OMX_ErrorBadParameter;
4401     }
4402 
4403 buffer_deallocate_op_exit:
4404     return retval;
4405 }
4406 
4407 /**
4408  * @brief De-allocate input buffer info array.
4409  */
buffer_deallocate_ip_info_array()4410 void omx_swvdec::buffer_deallocate_ip_info_array()
4411 {
4412     assert(m_buffer_array_ip != NULL);
4413 
4414     free(m_buffer_array_ip);
4415 
4416     m_buffer_array_ip = NULL;
4417 }
4418 
4419 /**
4420  * @brief De-allocate output buffer info array.
4421  */
buffer_deallocate_op_info_array()4422 void omx_swvdec::buffer_deallocate_op_info_array()
4423 {
4424     assert(m_buffer_array_op != NULL);
4425 
4426     free(m_buffer_array_op);
4427 
4428     m_buffer_array_op = NULL;
4429 }
4430 
4431 /**
4432  * @brief Allocate meta buffer info array.
4433  *
4434  * @retval OMX_ERRORTYPE
4435  */
meta_buffer_array_allocate()4436 OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate()
4437 {
4438     OMX_ERRORTYPE retval = OMX_ErrorNone;
4439 
4440     m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *)
4441                            calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO),
4442                                   m_port_op.def.nBufferCountActual));
4443 
4444     if (m_meta_buffer_array == NULL)
4445     {
4446         OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; "
4447                              "%d element%s, %zu bytes requested",
4448                              m_port_op.def.nBufferCountActual,
4449                              (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
4450                              sizeof(OMX_SWVDEC_META_BUFFER_INFO) *
4451                              m_port_op.def.nBufferCountActual);
4452 
4453         retval = OMX_ErrorInsufficientResources;
4454     }
4455     else
4456     {
4457         unsigned int ii;
4458 
4459         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4460         {
4461             m_meta_buffer_array[ii].fd = -1;
4462         }
4463     }
4464 
4465     return retval;
4466 }
4467 
4468 /**
4469  * @brief De-allocate meta buffer info array.
4470  */
meta_buffer_array_deallocate()4471 void omx_swvdec::meta_buffer_array_deallocate()
4472 {
4473     assert(m_meta_buffer_array != NULL);
4474 
4475     free(m_meta_buffer_array);
4476 
4477     m_meta_buffer_array = NULL;
4478 }
4479 
4480 /**
4481  * @brief Add meta buffer reference.
4482  *
4483  * @param[in] index: Buffer index.
4484  * @param[in] fd:    File descriptor.
4485  */
meta_buffer_ref_add(unsigned int index,int fd)4486 void omx_swvdec::meta_buffer_ref_add(unsigned int index, int fd)
4487 {
4488     if (m_meta_buffer_array[index].ref_count == 0)
4489     {
4490         m_meta_buffer_array[index].fd = fd;
4491     }
4492 
4493     m_meta_buffer_array[index].ref_count++;
4494 }
4495 
4496 /**
4497  * @brief Remove meta buffer reference.
4498  *
4499  * @param[in] index: Buffer index.
4500  */
meta_buffer_ref_remove(unsigned int index)4501 void omx_swvdec::meta_buffer_ref_remove(unsigned int index)
4502 {
4503     pthread_mutex_lock(&m_meta_buffer_array_mutex);
4504 
4505     m_meta_buffer_array[index].ref_count--;
4506 
4507     if (m_meta_buffer_array[index].ref_count == 0)
4508     {
4509         ion_unmap(m_meta_buffer_array[index].fd,
4510                   m_buffer_array_op[index].buffer_payload.bufferaddr,
4511                   m_buffer_array_op[index].buffer_payload.mmaped_size);
4512 
4513         m_meta_buffer_array[index].fd = -1;
4514         m_buffer_array_op[index].buffer_payload.bufferaddr  = NULL;
4515         m_buffer_array_op[index].buffer_payload.offset      = 0;
4516         m_buffer_array_op[index].buffer_payload.mmaped_size = 0;
4517 
4518         m_buffer_array_op[index].buffer_swvdec.p_buffer = NULL;
4519         m_buffer_array_op[index].buffer_swvdec.size     = 0;
4520     }
4521 
4522     pthread_mutex_unlock(&m_meta_buffer_array_mutex);
4523 }
4524 
4525 /**
4526  * @brief Split MPEG-4 bitstream buffer into multiple frames (if they exist).
4527  *
4528  * @param[in,out] offset_array: Array of offsets to frame headers.
4529  * @param[in]     p_buffer_hdr: Pointer to buffer header.
4530  *
4531  * @retval Number of frames in buffer.
4532  */
split_buffer_mpeg4(unsigned int * offset_array,OMX_BUFFERHEADERTYPE * p_buffer_hdr)4533 unsigned int split_buffer_mpeg4(unsigned int         *offset_array,
4534                                 OMX_BUFFERHEADERTYPE *p_buffer_hdr)
4535 {
4536     unsigned char *p_buffer = p_buffer_hdr->pBuffer;
4537 
4538     unsigned int byte_count = 0;
4539 
4540     unsigned int num_frame_headers = 0;
4541 
4542     unsigned int next_4bytes;
4543 
4544     while ((byte_count < p_buffer_hdr->nFilledLen) &&
4545            (num_frame_headers < OMX_SWVDEC_MAX_FRAMES_PER_ETB))
4546     {
4547         next_4bytes = *((unsigned int *) p_buffer);
4548 
4549         next_4bytes = __builtin_bswap32(next_4bytes);
4550 
4551         if (next_4bytes == 0x000001B6)
4552         {
4553             OMX_SWVDEC_LOG_HIGH("%p, buffer %p: "
4554                                 "frame header at %d bytes offset",
4555                                 p_buffer_hdr,
4556                                 p_buffer_hdr->pBuffer,
4557                                 byte_count);
4558 
4559             offset_array[num_frame_headers] = byte_count;
4560 
4561             num_frame_headers++;
4562 
4563             p_buffer   += 4;
4564             byte_count += 4;
4565         }
4566         else
4567         {
4568             p_buffer++;
4569             byte_count++;
4570         }
4571     }
4572 
4573     return num_frame_headers;
4574 }
4575 
4576 /**
4577  * @brief Check if ip port is populated, i.e., if all ip buffers are populated.
4578  *
4579  * @retval  true
4580  * @retval false
4581  */
port_ip_populated()4582 OMX_BOOL omx_swvdec::port_ip_populated()
4583 {
4584     OMX_BOOL retval = OMX_FALSE;
4585 
4586     if (m_buffer_array_ip != NULL)
4587     {
4588         unsigned int ii;
4589 
4590         for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
4591         {
4592             if (m_buffer_array_ip[ii].buffer_populated == false)
4593             {
4594                 break;
4595             }
4596         }
4597 
4598         if (ii == m_port_ip.def.nBufferCountActual)
4599         {
4600             retval = OMX_TRUE;
4601         }
4602     }
4603 
4604     return retval;
4605 }
4606 
4607 /**
4608  * @brief Check if op port is populated, i.e., if all op buffers are populated.
4609  *
4610  * @retval  true
4611  * @retval false
4612  */
port_op_populated()4613 OMX_BOOL omx_swvdec::port_op_populated()
4614 {
4615     OMX_BOOL retval = OMX_FALSE;
4616 
4617     if (m_buffer_array_op != NULL)
4618     {
4619         unsigned int ii;
4620 
4621         for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
4622         {
4623             if (m_buffer_array_op[ii].buffer_populated == false)
4624             {
4625                 break;
4626             }
4627         }
4628 
4629         if (ii == m_port_op.def.nBufferCountActual)
4630         {
4631             retval = OMX_TRUE;
4632         }
4633     }
4634 
4635     return retval;
4636 }
4637 
4638 /**
4639  * @brief Flush input, output, or both input & output ports.
4640  *
4641  * @param[in] port_index: Index of port to flush.
4642  *
4643  * @retval OMX_ERRORTYPE
4644  */
flush(unsigned int port_index)4645 OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index)
4646 {
4647     OMX_ERRORTYPE retval = OMX_ErrorNone;
4648 
4649     if (((port_index == OMX_CORE_PORT_INDEX_IP) &&
4650          m_port_ip.flush_inprogress) ||
4651         ((port_index == OMX_CORE_PORT_INDEX_OP) &&
4652          m_port_op.flush_inprogress) ||
4653         ((port_index == OMX_ALL) &&
4654          m_port_ip.flush_inprogress &&
4655          m_port_op.flush_inprogress))
4656     {
4657         OMX_SWVDEC_LOG_HIGH("flush port index %d already in progress",
4658                             port_index);
4659     }
4660     else
4661     {
4662         SWVDEC_FLUSH_TYPE swvdec_flush_type;
4663 
4664         SWVDEC_STATUS retval_swvdec;
4665 
4666         if (port_index == OMX_CORE_PORT_INDEX_IP)
4667         {
4668             m_port_ip.flush_inprogress = OMX_TRUE;
4669 
4670             //for VTS test case IP flush , trigger flush all
4671             // for IP flush, similar behavior is for hwcodecs
4672             m_port_ip.flush_inprogress = OMX_TRUE;
4673             m_port_op.flush_inprogress = OMX_TRUE;
4674 
4675             swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4676 
4677             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4678                                               swvdec_flush_type)) !=
4679                 SWVDEC_STATUS_SUCCESS)
4680             {
4681                 retval = retval_swvdec2omx(retval_swvdec);
4682             }
4683         }
4684         else if (port_index == OMX_CORE_PORT_INDEX_OP)
4685         {
4686             m_port_op.flush_inprogress = OMX_TRUE;
4687 
4688             swvdec_flush_type = (m_port_ip.flush_inprogress ?
4689                                  SWVDEC_FLUSH_TYPE_ALL :
4690                                  SWVDEC_FLUSH_TYPE_OP);
4691 
4692             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4693                                               swvdec_flush_type)) !=
4694                 SWVDEC_STATUS_SUCCESS)
4695             {
4696                 retval = retval_swvdec2omx(retval_swvdec);
4697             }
4698         }
4699         else if (port_index == OMX_ALL)
4700         {
4701             m_port_ip.flush_inprogress = OMX_TRUE;
4702             m_port_op.flush_inprogress = OMX_TRUE;
4703 
4704             swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
4705 
4706             if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
4707                                               swvdec_flush_type)) !=
4708                 SWVDEC_STATUS_SUCCESS)
4709             {
4710                 retval = retval_swvdec2omx(retval_swvdec);
4711             }
4712         }
4713         else
4714         {
4715             assert(0);
4716         }
4717     }
4718 
4719     return retval;
4720 }
4721 
4722 /**
4723  * @brief Allocate & map ION memory.
4724  */
ion_memory_alloc_map(vdec_ion * p_ion_info,OMX_U32 size,OMX_U32 alignment)4725 int omx_swvdec::ion_memory_alloc_map(vdec_ion *p_ion_info, OMX_U32 size, OMX_U32 alignment)
4726 {
4727     int rc = -EINVAL;
4728 
4729     if((!p_ion_info) || (size == 0))
4730     {
4731         OMX_SWVDEC_LOG_ERROR("invalid arguments");
4732         goto ion_memory_alloc_map_exit;
4733     }
4734 
4735     p_ion_info->dev_fd = -EINVAL;
4736 
4737     if ((p_ion_info->dev_fd = ion_open()) < 0)
4738     {
4739         OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", p_ion_info->dev_fd);
4740         goto ion_memory_alloc_map_exit;
4741     }
4742 
4743     p_ion_info->alloc_data.len = size;
4744     p_ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
4745     p_ion_info->alloc_data.flags        = 0;//check if ION_FLAG_CACHED need to be set;
4746     alignment = ALIGN(alignment,4096);
4747 
4748     OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %zu",
4749                        p_ion_info->alloc_data.heap_id_mask,
4750                        p_ion_info->alloc_data.len);
4751 
4752     rc = ion_alloc_fd(p_ion_info->dev_fd, p_ion_info->alloc_data.len, alignment,
4753                       p_ion_info->alloc_data.heap_id_mask, p_ion_info->alloc_data.flags,
4754                       &p_ion_info->data_fd);
4755 
4756     if (rc || p_ion_info->data_fd == 0)
4757     {
4758         OMX_SWVDEC_LOG_ERROR("ion_alloc_fd() for allocation failed");
4759         ion_close(p_ion_info->dev_fd);
4760         p_ion_info->data_fd = -1;
4761         p_ion_info->dev_fd = -1;
4762         goto ion_memory_alloc_map_exit;
4763     }
4764 
4765 
4766     OMX_SWVDEC_LOG_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
4767                         p_ion_info->dev_fd, p_ion_info->data_fd, (unsigned int)p_ion_info->alloc_data.len,
4768                      (unsigned int)p_ion_info->alloc_data.flags,
4769                      (unsigned int)p_ion_info->alloc_data.heap_id_mask);
4770 
4771 ion_memory_alloc_map_exit:
4772     return (p_ion_info == nullptr) ? -EINVAL : p_ion_info->dev_fd;
4773 }
4774 
4775 /**
4776  * @brief Free ION memory.
4777  */
ion_memory_free(struct vdec_ion * p_ion_buf_info)4778 void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info)
4779 {
4780     if (p_ion_buf_info == NULL)
4781     {
4782         OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL");
4783         goto ion_memory_free_exit;
4784     }
4785 
4786     OMX_SWVDEC_LOG_HIGH("Free ion memory: map fd %d ion_dev fd %d len %d flags %#x mask %#x",
4787         p_ion_buf_info->data_fd, p_ion_buf_info->dev_fd,
4788         (unsigned int)p_ion_buf_info->alloc_data.len,
4789         (unsigned int)p_ion_buf_info->alloc_data.flags,
4790         (unsigned int)p_ion_buf_info->alloc_data.heap_id_mask);
4791 
4792     if (p_ion_buf_info->data_fd >= 0) {
4793         close(p_ion_buf_info->data_fd);
4794         p_ion_buf_info->data_fd = -1;
4795     }
4796 
4797     if (p_ion_buf_info->dev_fd >= 0) {
4798         ion_close(p_ion_buf_info->dev_fd);
4799         p_ion_buf_info->dev_fd = -1;
4800     }
4801 
4802 ion_memory_free_exit:
4803     return;
4804 }
4805 
4806 /**
4807  * @brief Flush cached ION output buffer.
4808  *
4809  * @param[in] index: Index of buffer in output buffer info array.
4810  */
ion_flush_op(unsigned int index)4811 void omx_swvdec::ion_flush_op(unsigned int index)
4812 {
4813     if (index < m_port_op.def.nBufferCountActual)
4814     {
4815 #ifdef USE_ION
4816         struct dma_buf_sync dma_buf_sync_data[2];
4817         dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE;
4818         dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE;
4819 
4820         for (unsigned int i=0; i<2; i++)
4821         {
4822             int ret = ioctl(m_buffer_array_op[index].buffer_swvdec.fd,
4823                       DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]);
4824             if (ret < 0)
4825             {
4826                 OMX_SWVDEC_LOG_ERROR("Cache %s failed for fd %d : %s\n",
4827                                   (i==0) ? "START" : "END",
4828                                   m_buffer_array_op[index].buffer_swvdec.fd,
4829                                   strerror(errno));
4830                 goto ion_flush_op_exit;
4831             }
4832        }
4833 #endif
4834     }
4835     else
4836     {
4837         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
4838     }
4839 
4840 ion_flush_op_exit:
4841     return;
4842 }
4843 
4844 
4845 /**
4846  * ----------------------------
4847  * component callback functions
4848  * ----------------------------
4849  */
4850 
4851 /**
4852  * @brief Empty buffer done callback.
4853  *
4854  * @param[in] p_buffer_ip: Pointer to input buffer structure.
4855  */
swvdec_empty_buffer_done(SWVDEC_BUFFER * p_buffer_ip)4856 void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip)
4857 {
4858     unsigned long index = (unsigned long) p_buffer_ip->p_client_data;
4859 
4860     m_buffer_array_ip[index].buffer_header.nFilledLen =
4861         p_buffer_ip->filled_length;
4862 
4863     async_post_event(OMX_SWVDEC_EVENT_EBD,
4864                      (unsigned long) &m_buffer_array_ip[index].buffer_header,
4865                      index);
4866 }
4867 
4868 /**
4869  * @brief Fill buffer done callback.
4870  *
4871  * @param[in] p_buffer_op: Pointer to output buffer structure.
4872  */
swvdec_fill_buffer_done(SWVDEC_BUFFER * p_buffer_op)4873 void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op)
4874 {
4875     unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4876 
4877     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
4878 
4879     if (index < ((unsigned long) m_port_op.def.nBufferCountActual))
4880     {
4881         p_buffer_hdr = &m_buffer_array_op[index].buffer_header;
4882 
4883         p_buffer_hdr->nFlags     = p_buffer_op->flags;
4884         p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp;
4885         p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode &&
4886                                      p_buffer_op->filled_length) ?
4887                                     p_buffer_hdr->nAllocLen :
4888                                     p_buffer_op->filled_length);
4889     }
4890 
4891     async_post_event(OMX_SWVDEC_EVENT_FBD,
4892                      (unsigned long) &m_buffer_array_op[index].buffer_header,
4893                      index);
4894 }
4895 
4896 /**
4897  * @brief Event handler callback.
4898  *
4899  * @param[in] event:  Event.
4900  * @param[in] p_data: Pointer to event-specific data.
4901  */
swvdec_event_handler(SWVDEC_EVENT event,void * p_data)4902 void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data)
4903 {
4904     switch (event)
4905     {
4906 
4907     case SWVDEC_EVENT_FLUSH_ALL_DONE:
4908     {
4909         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0);
4910         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4911 
4912         break;
4913     }
4914 
4915     case SWVDEC_EVENT_FLUSH_OP_DONE:
4916     {
4917         async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
4918 
4919         break;
4920     }
4921 
4922     case SWVDEC_EVENT_RELEASE_REFERENCE:
4923     {
4924         SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data;
4925 
4926         unsigned long index = (unsigned long) p_buffer_op->p_client_data;
4927 
4928         OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer);
4929 
4930         assert(index < ((unsigned long) m_port_op.def.nBufferCountActual));
4931 
4932         if (m_meta_buffer_mode)
4933         {
4934             meta_buffer_ref_remove(index);
4935         }
4936 
4937         break;
4938     }
4939 
4940     case SWVDEC_EVENT_RECONFIG_REQUIRED:
4941     {
4942         async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0);
4943 
4944         break;
4945     }
4946 
4947     case SWVDEC_EVENT_DIMENSIONS_UPDATED:
4948     {
4949         async_post_event(OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED, 0, 0);
4950 
4951         break;
4952     }
4953 
4954     case SWVDEC_EVENT_FATAL_ERROR:
4955     default:
4956     {
4957         async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0);
4958 
4959         break;
4960     }
4961 
4962     }
4963 }
4964 
4965 /**
4966  * @brief Translate SwVdec status return value to OMX error type return value.
4967  *
4968  * @param[in] retval_swvdec: SwVdec status return value.
4969  *
4970  * @retval OMX_ERRORTYPE
4971  */
retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)4972 OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)
4973 {
4974     OMX_ERRORTYPE retval_omx;
4975 
4976     switch (retval_swvdec) {
4977         case SWVDEC_STATUS_SUCCESS:
4978             retval_omx = OMX_ErrorNone;
4979             break;
4980 
4981         case SWVDEC_STATUS_FAILURE:
4982             retval_omx = OMX_ErrorUndefined;
4983             break;
4984 
4985         case SWVDEC_STATUS_NULL_POINTER:
4986         case SWVDEC_STATUS_INVALID_PARAMETERS:
4987             retval_omx = OMX_ErrorBadParameter;
4988             break;
4989 
4990         case SWVDEC_STATUS_INVALID_STATE:
4991             retval_omx = OMX_ErrorInvalidState;
4992             break;
4993 
4994         case SWVDEC_STATUS_INSUFFICIENT_RESOURCES:
4995             retval_omx = OMX_ErrorInsufficientResources;
4996             break;
4997 
4998         case SWVDEC_STATUS_UNSUPPORTED:
4999             retval_omx = OMX_ErrorUnsupportedSetting;
5000             break;
5001 
5002         case SWVDEC_STATUS_NOT_IMPLEMENTED:
5003             retval_omx = OMX_ErrorNotImplemented;
5004             break;
5005 
5006         default:
5007             retval_omx = OMX_ErrorUndefined;
5008             break;
5009     }
5010 
5011     return retval_omx;
5012 }
5013 
5014 /**
5015  * @brief Create asynchronous thread.
5016  *
5017  * @retval OMX_ERRORTYPE
5018  */
async_thread_create()5019 OMX_ERRORTYPE omx_swvdec::async_thread_create()
5020 {
5021     OMX_ERRORTYPE retval = OMX_ErrorNone;
5022 
5023     pthread_attr_t thread_attributes;
5024 
5025     if (sem_init(&m_async_thread.sem_thread_created, 0, 0))
5026     {
5027         OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore");
5028 
5029         retval = OMX_ErrorInsufficientResources;
5030     }
5031     else if (sem_init(&m_async_thread.sem_event, 0, 0))
5032     {
5033         OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore");
5034 
5035         retval = OMX_ErrorInsufficientResources;
5036     }
5037     else if (pthread_attr_init(&thread_attributes))
5038     {
5039         OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object");
5040 
5041         retval = OMX_ErrorInsufficientResources;
5042     }
5043     else if (pthread_attr_setdetachstate(&thread_attributes,
5044                                          PTHREAD_CREATE_JOINABLE))
5045     {
5046         OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute");
5047 
5048         retval = OMX_ErrorInsufficientResources;
5049 
5050         pthread_attr_destroy(&thread_attributes);
5051     }
5052     else
5053     {
5054         m_async_thread.created = false;
5055         m_async_thread.exit    = false;
5056 
5057         if (pthread_create(&m_async_thread.handle,
5058                            &thread_attributes,
5059                            (void *(*)(void *)) async_thread,
5060                            this))
5061         {
5062             OMX_SWVDEC_LOG_ERROR("failed to create async thread");
5063 
5064             retval = OMX_ErrorInsufficientResources;
5065 
5066             pthread_attr_destroy(&thread_attributes);
5067         }
5068         else
5069         {
5070             if (pthread_setname_np(m_async_thread.handle, "swvdec_async"))
5071             {
5072                 // don't return error
5073                 OMX_SWVDEC_LOG_ERROR("failed to set async thread name");
5074             }
5075 
5076             sem_wait(&m_async_thread.sem_thread_created);
5077 
5078             m_async_thread.created = true;
5079         }
5080     }
5081 
5082     return retval;
5083 }
5084 
5085 /**
5086  * @brief Destroy asynchronous thread.
5087  */
async_thread_destroy()5088 void omx_swvdec::async_thread_destroy()
5089 {
5090     if (m_async_thread.created)
5091     {
5092         m_async_thread.exit = true;
5093 
5094         sem_post(&m_async_thread.sem_event);
5095 
5096         pthread_join(m_async_thread.handle, NULL);
5097 
5098         m_async_thread.created = false;
5099     }
5100 
5101     m_async_thread.exit = false;
5102 
5103     sem_destroy(&m_async_thread.sem_event);
5104     sem_destroy(&m_async_thread.sem_thread_created);
5105 }
5106 
5107 /**
5108  * @brief Post event to appropriate queue.
5109  *
5110  * @param[in] event_id:     Event ID.
5111  * @param[in] event_param1: Event parameter 1.
5112  * @param[in] event_param2: Event parameter 2.
5113  */
async_post_event(unsigned long event_id,unsigned long event_param1,unsigned long event_param2)5114 void omx_swvdec::async_post_event(unsigned long event_id,
5115                                   unsigned long event_param1,
5116                                   unsigned long event_param2)
5117 {
5118     OMX_SWVDEC_EVENT_INFO event_info;
5119 
5120     event_info.event_id     = event_id;
5121     event_info.event_param1 = event_param1;
5122     event_info.event_param2 = event_param2;
5123 
5124     switch (event_id)
5125     {
5126 
5127     case OMX_SWVDEC_EVENT_ETB:
5128     case OMX_SWVDEC_EVENT_EBD:
5129     {
5130         m_queue_port_ip.push(&event_info);
5131         break;
5132     }
5133 
5134     case OMX_SWVDEC_EVENT_FTB:
5135     case OMX_SWVDEC_EVENT_FBD:
5136     {
5137         m_queue_port_op.push(&event_info);
5138         break;
5139     }
5140 
5141     default:
5142     {
5143         m_queue_command.push(&event_info);
5144         break;
5145     }
5146 
5147     }
5148 
5149     sem_post(&m_async_thread.sem_event);
5150 }
5151 
5152 /**
5153  * @brief Asynchronous thread.
5154  *
5155  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
5156  */
async_thread(void * p_cmp)5157 void omx_swvdec::async_thread(void *p_cmp)
5158 {
5159     if (p_cmp == NULL)
5160     {
5161         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
5162     }
5163     else
5164     {
5165         omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp;
5166 
5167         ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread;
5168 
5169         OMX_SWVDEC_LOG_HIGH("created");
5170 
5171         sem_post(&p_async_thread->sem_thread_created);
5172 
5173         while (p_async_thread->exit == false)
5174         {
5175             sem_wait(&p_async_thread->sem_event);
5176 
5177             if (p_async_thread->exit == true)
5178             {
5179                 break;
5180             }
5181 
5182             p_omx_swvdec->async_process_event(p_cmp);
5183         }
5184     }
5185 
5186     OMX_SWVDEC_LOG_HIGH("exiting");
5187 }
5188 
5189 /**
5190  * @brief Process event.
5191  *
5192  * @param[in] p_cmp: Pointer to OMX SwVdec component class.
5193  */
async_process_event(void * p_cmp)5194 void omx_swvdec::async_process_event(void *p_cmp)
5195 {
5196     omx_swvdec *p_omx_swvdec;
5197 
5198     OMX_SWVDEC_EVENT_INFO event_info;
5199 
5200     OMX_ERRORTYPE retval = OMX_ErrorNone;
5201 
5202     if (p_cmp == NULL)
5203     {
5204         OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
5205 
5206         goto async_process_event_exit;
5207     }
5208 
5209     p_omx_swvdec = (omx_swvdec *) p_cmp;
5210 
5211     // NOTE: queues popped in order of priority; do not change!
5212 
5213     if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) &&
5214         (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) &&
5215         (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false))
5216     {
5217         OMX_SWVDEC_LOG_LOW("no event popped");
5218 
5219         goto async_process_event_exit;
5220     }
5221 
5222     switch (event_info.event_id)
5223     {
5224 
5225     case OMX_SWVDEC_EVENT_CMD:
5226     {
5227         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
5228         OMX_U32         param = (OMX_U32)         event_info.event_param2;
5229 
5230         retval = p_omx_swvdec->async_process_event_cmd(cmd, param);
5231         break;
5232     }
5233 
5234     case OMX_SWVDEC_EVENT_CMD_ACK:
5235     {
5236         OMX_COMMANDTYPE cmd   = (OMX_COMMANDTYPE) event_info.event_param1;
5237         OMX_U32         param = (OMX_U32)         event_info.event_param2;
5238 
5239         retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param);
5240         break;
5241     }
5242 
5243     case OMX_SWVDEC_EVENT_ERROR:
5244     {
5245         OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1;
5246 
5247         retval = p_omx_swvdec->async_process_event_error(error_code);
5248         break;
5249     }
5250 
5251     case OMX_SWVDEC_EVENT_ETB:
5252     {
5253         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5254             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5255 
5256         unsigned int index = event_info.event_param2;
5257 
5258         retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index);
5259         break;
5260     }
5261 
5262     case OMX_SWVDEC_EVENT_FTB:
5263     {
5264         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5265             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5266 
5267         unsigned int index = event_info.event_param2;
5268 
5269         retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index);
5270         break;
5271     }
5272 
5273     case OMX_SWVDEC_EVENT_EBD:
5274     {
5275         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5276             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5277 
5278         unsigned int index = event_info.event_param2;
5279 
5280         retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index);
5281         break;
5282     }
5283 
5284     case OMX_SWVDEC_EVENT_FBD:
5285     {
5286         OMX_BUFFERHEADERTYPE *p_buffer_hdr =
5287             (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
5288 
5289         unsigned int index = event_info.event_param2;
5290 
5291         retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index);
5292         break;
5293     }
5294 
5295     case OMX_SWVDEC_EVENT_EOS:
5296     {
5297         retval = p_omx_swvdec->async_process_event_eos();
5298         break;
5299     }
5300 
5301     case OMX_SWVDEC_EVENT_FLUSH_PORT_IP:
5302     {
5303         retval = p_omx_swvdec->async_process_event_flush_port_ip();
5304         break;
5305     }
5306 
5307     case OMX_SWVDEC_EVENT_FLUSH_PORT_OP:
5308     {
5309         retval = p_omx_swvdec->async_process_event_flush_port_op();
5310         break;
5311     }
5312 
5313     case OMX_SWVDEC_EVENT_PORT_RECONFIG:
5314     {
5315         retval = p_omx_swvdec->async_process_event_port_reconfig();
5316         break;
5317     }
5318 
5319     case OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED:
5320     {
5321         retval = p_omx_swvdec->async_process_event_dimensions_updated();
5322         break;
5323     }
5324 
5325     default:
5326     {
5327         assert(0);
5328 
5329         retval = OMX_ErrorUndefined;
5330         break;
5331     }
5332 
5333     }
5334 
5335     if (retval != OMX_ErrorNone)
5336     {
5337         p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
5338     }
5339 
5340 async_process_event_exit:
5341     return;
5342 }
5343 
5344 /**
5345  * @brief Process command event.
5346  *
5347  * @param[in] cmd:   Command.
5348  * @param[in] param: Command parameter.
5349  *
5350  * @retval OMX_ERRORTYPE
5351  */
async_process_event_cmd(OMX_COMMANDTYPE cmd,OMX_U32 param)5352 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd,
5353                                                   OMX_U32         param)
5354 {
5355     OMX_ERRORTYPE retval = OMX_ErrorNone;
5356 
5357     bool cmd_ack = false;
5358 
5359     switch (cmd)
5360     {
5361 
5362     case OMX_CommandStateSet:
5363     {
5364         retval = async_process_event_cmd_state_set(&cmd_ack,
5365                                                    (OMX_STATETYPE) param);
5366         break;
5367     }
5368 
5369     case OMX_CommandFlush:
5370     {
5371         retval = async_process_event_cmd_flush((unsigned int) param);
5372         break;
5373     }
5374 
5375     case OMX_CommandPortDisable:
5376     {
5377         retval = async_process_event_cmd_port_disable(&cmd_ack,
5378                                                       (unsigned int) param);
5379         break;
5380     }
5381 
5382     case OMX_CommandPortEnable:
5383     {
5384         retval = async_process_event_cmd_port_enable(&cmd_ack,
5385                                                      (unsigned int) param);
5386         break;
5387     }
5388 
5389     default:
5390     {
5391         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
5392 
5393         retval = OMX_ErrorBadParameter;
5394         break;
5395     }
5396 
5397     } // switch (cmd)
5398 
5399     if (retval != OMX_ErrorNone)
5400     {
5401         async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
5402     }
5403     else if (cmd_ack)
5404     {
5405         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param);
5406     }
5407 
5408     sem_post(&m_sem_cmd);
5409 
5410     return retval;
5411 }
5412 
5413 /**
5414  * @brief Process command acknowledgement event.
5415  *
5416  * @param[in] cmd:   Command.
5417  * @param[in] param: Command parameter.
5418  *
5419  * @retval OMX_ERRORTYPE
5420  */
async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,OMX_U32 param)5421 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,
5422                                                       OMX_U32         param)
5423 {
5424     OMX_ERRORTYPE retval = OMX_ErrorNone;
5425 
5426     switch (cmd)
5427     {
5428 
5429     case OMX_CommandStateSet:
5430     {
5431         OMX_SWVDEC_LOG_HIGH("%s -> %s",
5432                             OMX_STATETYPE_STRING(m_state),
5433                             OMX_STATETYPE_STRING((OMX_STATETYPE) param));
5434 
5435         m_state = (OMX_STATETYPE) param;
5436 
5437         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
5438                                 "OMX_CommandStateSet, %s",
5439                                 OMX_STATETYPE_STRING(m_state));
5440 
5441         m_callback.EventHandler(&m_cmp,
5442                                 m_app_data,
5443                                 OMX_EventCmdComplete,
5444                                 OMX_CommandStateSet,
5445                                 (OMX_U32) m_state,
5446                                 NULL);
5447         break;
5448     }
5449 
5450     case OMX_CommandFlush:
5451     case OMX_CommandPortEnable:
5452     case OMX_CommandPortDisable:
5453     {
5454         if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress)
5455         {
5456             m_port_reconfig_inprogress = false;
5457         }
5458 
5459         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
5460                                 "%s, port index %d",
5461                                 OMX_COMMANDTYPE_STRING(cmd),
5462                                 param);
5463 
5464         m_callback.EventHandler(&m_cmp,
5465                                 m_app_data,
5466                                 OMX_EventCmdComplete,
5467                                 cmd,
5468                                 param,
5469                                 NULL);
5470         break;
5471     }
5472 
5473     default:
5474     {
5475         OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
5476 
5477         retval = OMX_ErrorBadParameter;
5478         break;
5479     }
5480 
5481     } // switch (cmd)
5482 
5483     return retval;
5484 }
5485 
5486 /**
5487  * @brief Process error event.
5488  *
5489  * @param[in] error_code: Error code.
5490  *
5491  * @retval OMX_ErrorNone
5492  */
async_process_event_error(OMX_ERRORTYPE error_code)5493 OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code)
5494 {
5495     if (error_code == OMX_ErrorInvalidState)
5496     {
5497         OMX_SWVDEC_LOG_HIGH("%s -> OMX_StateInvalid",
5498                             OMX_STATETYPE_STRING(m_state));
5499 
5500         m_state = OMX_StateInvalid;
5501     }
5502 
5503     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x",
5504                             error_code);
5505 
5506     m_callback.EventHandler(&m_cmp,
5507                             m_app_data,
5508                             OMX_EventError,
5509                             (OMX_U32) error_code,
5510                             0,
5511                             NULL);
5512 
5513     return OMX_ErrorNone;
5514 }
5515 
5516 /**
5517  * @brief Process OMX_CommandStateSet.
5518  *
5519  * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
5520  * @param[in]     state_new: New state to which transition is requested.
5521  *
5522  * @retval OMX_ERRORTYPE
5523  */
async_process_event_cmd_state_set(bool * p_cmd_ack,OMX_STATETYPE state_new)5524 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set(
5525     bool         *p_cmd_ack,
5526     OMX_STATETYPE state_new)
5527 {
5528     OMX_ERRORTYPE retval = OMX_ErrorNone;
5529 
5530     SWVDEC_STATUS retval_swvdec;
5531 
5532     OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested",
5533                         OMX_STATETYPE_STRING(m_state),
5534                         OMX_STATETYPE_STRING(state_new));
5535 
5536     /**
5537      * Only the following state transitions are allowed via CommandStateSet:
5538      *
5539      * LOADED -> IDLE -> EXECUTING
5540      * LOADED <- IDLE <- EXECUTING
5541      */
5542 
5543     if (m_state == OMX_StateInvalid)
5544     {
5545         OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state));
5546 
5547         retval = OMX_ErrorInvalidState;
5548     }
5549     else if (state_new == OMX_StateInvalid)
5550     {
5551         OMX_SWVDEC_LOG_ERROR("requested transition to state %s",
5552                              OMX_STATETYPE_STRING(state_new));
5553 
5554         retval = OMX_ErrorInvalidState;
5555     }
5556     else if ((m_state   == OMX_StateLoaded) &&
5557              (state_new == OMX_StateIdle))
5558     {
5559         if ((m_port_ip.populated == OMX_TRUE) &&
5560             (m_port_op.populated == OMX_TRUE))
5561         {
5562             if ((retval_swvdec = swvdec_start(m_swvdec_handle)) ==
5563                 SWVDEC_STATUS_SUCCESS)
5564             {
5565                 *p_cmd_ack = true;
5566             }
5567             else
5568             {
5569                 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
5570 
5571                 retval = retval_swvdec2omx(retval_swvdec);
5572             }
5573         }
5574         else
5575         {
5576             m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE);
5577 
5578             OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending");
5579         }
5580     }
5581     else if ((m_state   == OMX_StateIdle) &&
5582              (state_new == OMX_StateExecuting))
5583     {
5584         *p_cmd_ack = true;
5585     }
5586     else if ((m_state   == OMX_StateExecuting) &&
5587              (state_new == OMX_StateIdle))
5588     {
5589         m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE);
5590 
5591         OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending");
5592 
5593         retval = flush(OMX_ALL);
5594     }
5595     else if ((m_state   == OMX_StateIdle) &&
5596              (state_new == OMX_StateLoaded))
5597     {
5598         if ((m_port_ip.unpopulated == OMX_TRUE) &&
5599             (m_port_op.unpopulated == OMX_TRUE))
5600         {
5601             if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
5602                 SWVDEC_STATUS_SUCCESS)
5603             {
5604                 *p_cmd_ack = true;
5605             }
5606             else
5607             {
5608                 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
5609 
5610                 retval = retval_swvdec2omx(retval_swvdec);
5611             }
5612         }
5613         else
5614         {
5615             m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED);
5616 
5617             OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending");
5618         }
5619     }
5620     else
5621     {
5622         OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal",
5623                              OMX_STATETYPE_STRING(m_state),
5624                              OMX_STATETYPE_STRING(state_new));
5625 
5626         retval = ((state_new == m_state) ?
5627                   OMX_ErrorSameState :
5628                   OMX_ErrorIncorrectStateTransition);
5629     }
5630 
5631     return retval;
5632 }
5633 
5634 /**
5635  * @brief Process OMX_CommandFlush.
5636  *
5637  * @param[in] port_index: Index of port to flush.
5638  *
5639  * @retval OMX_ERRORTYPE
5640  */
async_process_event_cmd_flush(unsigned int port_index)5641 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index)
5642 {
5643     OMX_ERRORTYPE retval = OMX_ErrorNone;
5644 
5645     OMX_SWVDEC_LOG_HIGH("flush port index %d requested", port_index);
5646 
5647     if (port_index == OMX_CORE_PORT_INDEX_IP)
5648     {
5649         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5650 
5651         OMX_SWVDEC_LOG_LOW("ip port flush pending");
5652     }
5653     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5654     {
5655         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5656 
5657         OMX_SWVDEC_LOG_LOW("op port flush pending");
5658     }
5659     else if (port_index == OMX_ALL)
5660     {
5661         m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
5662         m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
5663 
5664         OMX_SWVDEC_LOG_LOW("ip & op ports flush pending");
5665     }
5666 
5667     retval = flush(port_index);
5668 
5669     return retval;
5670 }
5671 
5672 /**
5673  * @brief Process OMX_CommandPortDisable.
5674  *
5675  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5676  * @param[in]     port_index: Index of port to disable.
5677  *
5678  * @retval OMX_ERRORTYPE
5679  */
async_process_event_cmd_port_disable(bool * p_cmd_ack,unsigned int port_index)5680 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable(
5681     bool         *p_cmd_ack,
5682     unsigned int  port_index)
5683 {
5684     OMX_ERRORTYPE retval = OMX_ErrorNone;
5685 
5686     OMX_SWVDEC_LOG_HIGH("disable port index %d requested", port_index);
5687 
5688     if (port_index == OMX_CORE_PORT_INDEX_IP)
5689     {
5690         if (m_port_ip.enabled == OMX_FALSE)
5691         {
5692             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5693 
5694             retval = OMX_ErrorBadPortIndex;
5695         }
5696         else
5697         {
5698             m_port_ip.enabled = OMX_FALSE;
5699 
5700             if (m_port_ip.unpopulated)
5701             {
5702                 *p_cmd_ack = true;
5703             }
5704             else
5705             {
5706                 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5707 
5708                 OMX_SWVDEC_LOG_LOW("ip port disable pending");
5709 
5710                 if (m_port_ip.num_pending_buffers)
5711                 {
5712                     retval = flush(port_index);
5713                 }
5714             }
5715         }
5716     }
5717     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5718     {
5719         if (m_port_op.enabled == OMX_FALSE)
5720         {
5721             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5722 
5723             retval = OMX_ErrorBadPortIndex;
5724         }
5725         else
5726         {
5727             m_port_op.enabled = OMX_FALSE;
5728 
5729             if (m_port_op.unpopulated)
5730             {
5731                 *p_cmd_ack = true;
5732             }
5733             else
5734             {
5735                 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5736 
5737                 OMX_SWVDEC_LOG_LOW("op port disable pending");
5738 
5739                 if (m_port_op.num_pending_buffers)
5740                 {
5741                     retval = flush(port_index);
5742                 }
5743             }
5744         }
5745     }
5746     else if (port_index == OMX_ALL)
5747     {
5748         if (m_port_ip.enabled == OMX_FALSE)
5749         {
5750             OMX_SWVDEC_LOG_ERROR("ip port already disabled");
5751 
5752             retval = OMX_ErrorBadPortIndex;
5753         }
5754         else if (m_port_op.enabled == OMX_FALSE)
5755         {
5756             OMX_SWVDEC_LOG_ERROR("op port already disabled");
5757 
5758             retval = OMX_ErrorBadPortIndex;
5759         }
5760         else
5761         {
5762             if (m_port_ip.unpopulated && m_port_op.unpopulated)
5763             {
5764                 *p_cmd_ack = true;
5765             }
5766             else
5767             {
5768                 m_port_ip.enabled = OMX_FALSE;
5769                 m_port_op.enabled = OMX_FALSE;
5770 
5771                 if (m_port_ip.unpopulated == OMX_FALSE)
5772                 {
5773                     m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
5774 
5775                     OMX_SWVDEC_LOG_LOW("ip port disable pending");
5776 
5777                     if (m_port_ip.num_pending_buffers)
5778                     {
5779                         retval = flush(port_index);
5780                     }
5781                 }
5782 
5783                 if ((retval == OMX_ErrorNone) &&
5784                     (m_port_op.unpopulated == OMX_FALSE))
5785                 {
5786                     m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
5787 
5788                     OMX_SWVDEC_LOG_LOW("op port disable pending");
5789 
5790                     if (m_port_op.num_pending_buffers)
5791                     {
5792                         retval = flush(port_index);
5793                     }
5794                 }
5795             }
5796         }
5797     }
5798     else
5799     {
5800         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
5801                              port_index);
5802 
5803         retval = OMX_ErrorBadPortIndex;
5804     }
5805 
5806     return retval;
5807 }
5808 
5809 /**
5810  * @brief Process OMX_CommandPortEnable.
5811  *
5812  * @param[in,out] p_cmd_ack:  Pointer to 'command acknowledge' boolean variable.
5813  * @param[in]     port_index: Index of port to enable.
5814  *
5815  * @retval OMX_ERRORTYPE
5816  */
async_process_event_cmd_port_enable(bool * p_cmd_ack,unsigned int port_index)5817 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable(
5818     bool        *p_cmd_ack,
5819     unsigned int port_index)
5820 {
5821     OMX_ERRORTYPE retval = OMX_ErrorNone;
5822 
5823     OMX_SWVDEC_LOG_HIGH("enable port index %d requested", port_index);
5824 
5825     if (port_index == OMX_CORE_PORT_INDEX_IP)
5826     {
5827         if (m_port_ip.enabled)
5828         {
5829             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5830 
5831             retval = OMX_ErrorBadPortIndex;
5832         }
5833         else
5834         {
5835             m_port_ip.enabled = OMX_TRUE;
5836 
5837             if (m_port_ip.populated)
5838             {
5839                 *p_cmd_ack = true;
5840             }
5841             else
5842             {
5843                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5844 
5845                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5846             }
5847         }
5848     }
5849     else if (port_index == OMX_CORE_PORT_INDEX_OP)
5850     {
5851         if (m_port_op.enabled)
5852         {
5853             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5854 
5855             retval = OMX_ErrorBadPortIndex;
5856         }
5857         else
5858         {
5859             m_port_op.enabled = OMX_TRUE;
5860 
5861             if (m_port_op.populated)
5862             {
5863                 *p_cmd_ack = true;
5864             }
5865             else
5866             {
5867                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5868 
5869                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5870             }
5871         }
5872     }
5873     else if (port_index == OMX_ALL)
5874     {
5875         if (m_port_ip.enabled)
5876         {
5877             OMX_SWVDEC_LOG_ERROR("ip port already enabled");
5878 
5879             retval = OMX_ErrorBadPortIndex;
5880         }
5881         else if (m_port_op.enabled)
5882         {
5883             OMX_SWVDEC_LOG_ERROR("op port already enabled");
5884 
5885             retval = OMX_ErrorBadPortIndex;
5886         }
5887         else
5888         {
5889             m_port_ip.enabled = OMX_TRUE;
5890             m_port_op.enabled = OMX_TRUE;
5891 
5892             if (m_port_ip.populated && m_port_op.populated)
5893             {
5894                 *p_cmd_ack = true;
5895             }
5896             else if (m_port_ip.populated == false)
5897             {
5898                 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
5899 
5900                 OMX_SWVDEC_LOG_LOW("ip port enable pending");
5901             }
5902             else if (m_port_op.populated == false)
5903             {
5904                 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
5905 
5906                 OMX_SWVDEC_LOG_LOW("op port enable pending");
5907             }
5908         }
5909     }
5910     else
5911     {
5912         OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
5913                              port_index);
5914 
5915         retval = OMX_ErrorBadPortIndex;
5916     }
5917 
5918     return retval;
5919 }
5920 
5921 /**
5922  * @brief Process ETB event.
5923  *
5924  * @param[in] p_buffer_hdr: Pointer to buffer header.
5925  * @param[in] index:        Index of buffer in input buffer info array.
5926  *
5927  * @retval OMX_ERRORTYPE
5928  */
async_process_event_etb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)5929 OMX_ERRORTYPE omx_swvdec::async_process_event_etb(
5930     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
5931     unsigned int          index)
5932 {
5933     OMX_ERRORTYPE retval = OMX_ErrorNone;
5934 
5935     m_port_ip.num_pending_buffers++;
5936 
5937     if ((p_buffer_hdr->nFilledLen == 0) &&
5938         ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0))
5939     {
5940         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p,"
5941                             "zero length & no EOS flag",
5942                             p_buffer_hdr,
5943                             p_buffer_hdr->pBuffer);
5944 
5945         async_post_event(OMX_SWVDEC_EVENT_EBD,
5946                          (unsigned long) p_buffer_hdr,
5947                          (unsigned long) index);
5948     }
5949     else if (m_port_ip.flush_inprogress)
5950     {
5951         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
5952                             "ip port flush in progress",
5953                             p_buffer_hdr,
5954                             p_buffer_hdr->pBuffer);
5955 
5956         async_post_event(OMX_SWVDEC_EVENT_EBD,
5957                          (unsigned long) p_buffer_hdr,
5958                          (unsigned long) index);
5959     }
5960     else
5961     {
5962         SWVDEC_STATUS retval_swvdec;
5963 
5964         SWVDEC_BUFFER *p_buffer_swvdec =
5965             &(m_buffer_array_ip[index].buffer_swvdec);
5966 
5967         if (p_buffer_hdr->nFilledLen &&
5968             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5969         {
5970             m_queue_timestamp.push(p_buffer_hdr->nTimeStamp);
5971         }
5972 
5973         assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer);
5974         //sending the fd info
5975         p_buffer_swvdec->fd = m_buffer_array_ip[index].buffer_payload.pmem_fd;
5976         if (m_arbitrary_bytes_mode &&
5977             p_buffer_hdr->nFilledLen &&
5978             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
5979         {
5980             unsigned int offset_array[OMX_SWVDEC_MAX_FRAMES_PER_ETB] = {0};
5981 
5982             unsigned int num_frame_headers = 1;
5983 
5984             if ((m_omx_video_codingtype ==
5985                  ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)) ||
5986                 (m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4))
5987             {
5988                 num_frame_headers = split_buffer_mpeg4(offset_array,
5989                                                        p_buffer_hdr);
5990             }
5991             else
5992             {
5993                 assert(0);
5994             }
5995 
5996             if(num_frame_headers > 1)
5997             {
5998                 m_buffer_array_ip[index].split_count = num_frame_headers - 1;
5999 
6000                 for (unsigned int ii = 0; ii < num_frame_headers; ii++)
6001                 {
6002                     p_buffer_swvdec->flags     = p_buffer_hdr->nFlags;
6003                     p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp;
6004 
6005                     if (ii == 0)
6006                     {
6007                         p_buffer_swvdec->offset        = 0;
6008                         p_buffer_swvdec->filled_length = (offset_array[ii + 1] ?
6009                                                           offset_array[ii + 1] :
6010                                                           p_buffer_hdr->nFilledLen);
6011                     }
6012                     else
6013                     {
6014                         p_buffer_swvdec->offset        = offset_array[ii];
6015                         p_buffer_swvdec->filled_length =
6016                             p_buffer_hdr->nFilledLen - offset_array[ii];
6017                     }
6018 
6019                     m_diag.dump_ip(p_buffer_swvdec->p_buffer +
6020                                    p_buffer_swvdec->offset,
6021                                    p_buffer_swvdec->filled_length);
6022 
6023                     retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6024                                                            p_buffer_swvdec);
6025 
6026                     if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6027                     {
6028                         retval = retval_swvdec2omx(retval_swvdec);
6029                         break;
6030                     }
6031                 }
6032             }
6033             else
6034             {
6035                 OMX_SWVDEC_LOG_HIGH("No frame detected for Buffer %p, with TS %lld",
6036                                     p_buffer_hdr->pBuffer, p_buffer_hdr->nTimeStamp );
6037 
6038                 p_buffer_swvdec->flags         = p_buffer_hdr->nFlags;
6039                 p_buffer_swvdec->offset        = 0;
6040                 p_buffer_swvdec->timestamp     = p_buffer_hdr->nTimeStamp;
6041                 p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
6042 
6043                 m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset,
6044                                p_buffer_swvdec->filled_length);
6045 
6046                 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6047                                                        p_buffer_swvdec);
6048 
6049                 if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6050                 {
6051                     retval = retval_swvdec2omx(retval_swvdec);
6052                 }
6053             }
6054         }
6055         else
6056         {
6057             p_buffer_swvdec->flags         = p_buffer_hdr->nFlags;
6058             p_buffer_swvdec->offset        = 0;
6059             p_buffer_swvdec->timestamp     = p_buffer_hdr->nTimeStamp;
6060             p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
6061 
6062             m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset,
6063                            p_buffer_swvdec->filled_length);
6064 
6065             retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
6066                                                    p_buffer_swvdec);
6067 
6068             if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6069             {
6070                 retval = retval_swvdec2omx(retval_swvdec);
6071             }
6072         }
6073     }
6074     return retval;
6075 }
6076 
6077 /**
6078  * @brief Process FTB event.
6079  *
6080  * @param[in] p_buffer_hdr: Pointer to buffer header.
6081  * @param[in] index:        Index of buffer in output buffer info array.
6082  *
6083  * @retval OMX_ERRORTYPE
6084  */
async_process_event_ftb(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6085 OMX_ERRORTYPE omx_swvdec::async_process_event_ftb(
6086     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6087     unsigned int          index)
6088 {
6089     OMX_ERRORTYPE retval = OMX_ErrorNone;
6090 
6091     m_port_op.num_pending_buffers++;
6092 
6093     if (m_port_op.flush_inprogress)
6094     {
6095         OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
6096                             "op port flush in progress",
6097                             p_buffer_hdr,
6098                             m_buffer_array_op[index].buffer_swvdec.p_buffer);
6099 
6100         async_post_event(OMX_SWVDEC_EVENT_FBD,
6101                          (unsigned long) p_buffer_hdr,
6102                          (unsigned long) index);
6103     }
6104     else
6105     {
6106         SWVDEC_STATUS retval_swvdec;
6107 
6108         SWVDEC_BUFFER *p_buffer_swvdec =
6109             &(m_buffer_array_op[index].buffer_swvdec);
6110         p_buffer_swvdec->fd = m_buffer_array_op[index].buffer_payload.pmem_fd;
6111         retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec);
6112 
6113         if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
6114         {
6115             retval = retval_swvdec2omx(retval_swvdec);
6116         }
6117     }
6118 
6119     return retval;
6120 }
6121 
6122 /**
6123  * @brief Process EBD event.
6124  *
6125  * @param[in] p_buffer_hdr: Pointer to buffer header.
6126  * @param[in] index:        Index of buffer in output buffer info array.
6127  *
6128  * @retval OMX_ERRORTYPE
6129  */
async_process_event_ebd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6130 OMX_ERRORTYPE omx_swvdec::async_process_event_ebd(
6131     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6132     unsigned int          index)
6133 {
6134     OMX_ERRORTYPE retval = OMX_ErrorNone;
6135 
6136     if (index < m_port_ip.def.nBufferCountActual)
6137     {
6138         if (m_arbitrary_bytes_mode && m_buffer_array_ip[index].split_count)
6139         {
6140             m_buffer_array_ip[index].split_count--;
6141         }
6142         else
6143         {
6144             m_port_ip.num_pending_buffers--;
6145 
6146             OMX_SWVDEC_LOG_CALLBACK(
6147                 "EmptyBufferDone(): %p, buffer %p",
6148                 p_buffer_hdr,
6149                 m_buffer_array_ip[index].buffer_swvdec.p_buffer);
6150 
6151             m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
6152         }
6153     }
6154     else
6155     {
6156         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
6157 
6158         retval = OMX_ErrorBadParameter;
6159     }
6160 
6161     return retval;
6162 }
6163 
6164 /**
6165  * @brief Process FBD event.
6166  *
6167  * @param[in] p_buffer_hdr: Pointer to buffer header.
6168  * @param[in] index:        Index of buffer in output buffer info array.
6169  *
6170  * @retval OMX_ERRORTYPE
6171  */
async_process_event_fbd(OMX_BUFFERHEADERTYPE * p_buffer_hdr,unsigned int index)6172 OMX_ERRORTYPE omx_swvdec::async_process_event_fbd(
6173     OMX_BUFFERHEADERTYPE *p_buffer_hdr,
6174     unsigned int          index)
6175 {
6176     OMX_ERRORTYPE retval = OMX_ErrorNone;
6177 
6178     static long long timestamp_prev = 0;
6179 
6180     if (index < m_port_op.def.nBufferCountActual)
6181     {
6182         OMX_U8 *p_buffer;
6183 
6184         p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer;
6185 
6186         m_port_op.num_pending_buffers--;
6187 
6188         if (m_port_op.flush_inprogress)
6189         {
6190             p_buffer_hdr->nFilledLen = 0;
6191             p_buffer_hdr->nTimeStamp = 0;
6192             p_buffer_hdr->nFlags    &= ~OMX_BUFFERFLAG_DATACORRUPT;
6193         }
6194 
6195         if (p_buffer_hdr->nFilledLen)
6196         {
6197             if (m_sync_frame_decoding_mode)
6198             {
6199                 OMX_SWVDEC_LOG_LOW("sync frame decoding mode; "
6200                                    "setting timestamp to zero");
6201 
6202                 p_buffer_hdr->nTimeStamp = 0;
6203             }
6204             else
6205             {
6206                 if (m_queue_timestamp.empty())
6207                 {
6208                     OMX_SWVDEC_LOG_ERROR("timestamp queue empty; "
6209                                          "re-using previous timestamp %lld",
6210                                          timestamp_prev);
6211 
6212                     p_buffer_hdr->nTimeStamp = timestamp_prev;
6213                 }
6214                 else
6215                 {
6216                     p_buffer_hdr->nTimeStamp = m_queue_timestamp.top();
6217 
6218                     m_queue_timestamp.pop();
6219 
6220                     timestamp_prev = p_buffer_hdr->nTimeStamp;
6221                 }
6222             }
6223 
6224             ion_flush_op(index);
6225 
6226             if (m_meta_buffer_mode)
6227             {
6228                 pthread_mutex_lock(&m_meta_buffer_array_mutex);
6229             }
6230 
6231             m_diag.dump_op(p_buffer,
6232                            m_frame_dimensions.width,
6233                            m_frame_dimensions.height,
6234                            m_frame_attributes.stride,
6235                            m_frame_attributes.scanlines);
6236 
6237             if (m_meta_buffer_mode)
6238             {
6239                 pthread_mutex_unlock(&m_meta_buffer_array_mutex);
6240             }
6241         }
6242         else
6243         {
6244             OMX_SWVDEC_LOG_LOW("filled length zero; "
6245                                "setting timestamp to zero");
6246 
6247             p_buffer_hdr->nTimeStamp = 0;
6248         }
6249 
6250         if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS)
6251         {
6252             async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0);
6253 
6254             OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue",
6255                                m_queue_timestamp.size());
6256 
6257             while (m_queue_timestamp.empty() == false)
6258             {
6259                 m_queue_timestamp.pop();
6260             }
6261         }
6262 
6263         if (m_meta_buffer_mode &&
6264             ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0)
6265         {
6266             meta_buffer_ref_remove(index);
6267         }
6268 
6269         OMX_SWVDEC_LOG_CALLBACK(
6270             "FillBufferDone(): %p, buffer %p, "
6271             "flags 0x%08x, filled length %d, timestamp %lld",
6272             p_buffer_hdr,
6273             p_buffer,
6274             p_buffer_hdr->nFlags,
6275             p_buffer_hdr->nFilledLen,
6276             p_buffer_hdr->nTimeStamp);
6277 
6278         m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
6279     }
6280     else
6281     {
6282         OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
6283 
6284         retval = OMX_ErrorBadParameter;
6285     }
6286 
6287     return retval;
6288 }
6289 
6290 /**
6291  * @brief Process EOS event.
6292  *
6293  * @retval OMX_ErrorNone
6294  */
async_process_event_eos()6295 OMX_ERRORTYPE omx_swvdec::async_process_event_eos()
6296 {
6297     OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6298                             "OMX_EventBufferFlag, port index %d, EOS",
6299                             OMX_CORE_PORT_INDEX_OP);
6300 
6301     m_callback.EventHandler(&m_cmp,
6302                             m_app_data,
6303                             OMX_EventBufferFlag,
6304                             OMX_CORE_PORT_INDEX_OP,
6305                             OMX_BUFFERFLAG_EOS,
6306                             NULL);
6307 
6308     return OMX_ErrorNone;
6309 }
6310 
6311 /**
6312  * @brief Process input port flush event.
6313  *
6314  * @retval OMX_ERRORTYPE
6315  */
async_process_event_flush_port_ip()6316 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip()
6317 {
6318     OMX_ERRORTYPE retval = OMX_ErrorNone;
6319 
6320     OMX_SWVDEC_EVENT_INFO event_info;
6321 
6322     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
6323 
6324     unsigned int index;
6325 
6326     while (m_queue_port_ip.pop(&event_info))
6327     {
6328         switch (event_info.event_id)
6329         {
6330 
6331         case OMX_SWVDEC_EVENT_ETB:
6332         {
6333             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6334 
6335             index = event_info.event_param2;
6336 
6337             // compensate decrement in async_process_event_ebd()
6338             m_port_ip.num_pending_buffers++;
6339 
6340             retval = async_process_event_ebd(p_buffer_hdr, index);
6341             break;
6342         }
6343 
6344         case OMX_SWVDEC_EVENT_EBD:
6345         {
6346             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6347 
6348             index = event_info.event_param2;
6349 
6350             retval = async_process_event_ebd(p_buffer_hdr, index);
6351             break;
6352         }
6353 
6354         default:
6355         {
6356             assert(0);
6357             break;
6358         }
6359 
6360         }
6361     }
6362 
6363     assert(m_port_ip.num_pending_buffers == 0);
6364 
6365     if ((retval == OMX_ErrorNone) &&
6366         (m_status_flags & (1 << PENDING_PORT_FLUSH_IP)))
6367     {
6368         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP);
6369 
6370         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6371                          OMX_CommandFlush,
6372                          OMX_CORE_PORT_INDEX_IP);
6373     }
6374 
6375     m_port_ip.flush_inprogress = OMX_FALSE;
6376 
6377     return retval;
6378 }
6379 
6380 /**
6381  * @brief Process output port flush event.
6382  *
6383  * @retval OMX_ERRORTYPE
6384  */
async_process_event_flush_port_op()6385 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op()
6386 {
6387     OMX_ERRORTYPE retval = OMX_ErrorNone;
6388 
6389     OMX_SWVDEC_EVENT_INFO event_info;
6390 
6391     OMX_BUFFERHEADERTYPE *p_buffer_hdr;
6392 
6393     unsigned int index;
6394 
6395     while (m_queue_port_op.pop(&event_info))
6396     {
6397         switch (event_info.event_id)
6398         {
6399 
6400         case OMX_SWVDEC_EVENT_FTB:
6401         {
6402             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6403 
6404             index = event_info.event_param2;
6405 
6406             // compensate decrement in async_process_event_fbd()
6407             m_port_op.num_pending_buffers++;
6408 
6409             retval = async_process_event_fbd(p_buffer_hdr, index);
6410             break;
6411         }
6412 
6413         case OMX_SWVDEC_EVENT_FBD:
6414         {
6415             p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
6416 
6417             index = event_info.event_param2;
6418 
6419             retval = async_process_event_fbd(p_buffer_hdr, index);
6420             break;
6421         }
6422 
6423         default:
6424         {
6425             assert(0);
6426             break;
6427         }
6428 
6429         }
6430     }
6431 
6432     assert(m_port_op.num_pending_buffers == 0);
6433 
6434     if ((retval == OMX_ErrorNone) &&
6435         (m_status_flags & (1 << PENDING_PORT_FLUSH_OP)))
6436     {
6437         m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP);
6438 
6439         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6440                          OMX_CommandFlush,
6441                          OMX_CORE_PORT_INDEX_OP);
6442     }
6443 
6444     if ((retval == OMX_ErrorNone) &&
6445         (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE)))
6446     {
6447         m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE);
6448 
6449         async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
6450                          OMX_CommandStateSet,
6451                          OMX_StateIdle);
6452     }
6453 
6454     if (m_port_reconfig_inprogress == false)
6455     {
6456         OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue",
6457                            m_queue_timestamp.size());
6458 
6459         while (m_queue_timestamp.empty() == false)
6460         {
6461             m_queue_timestamp.pop();
6462         }
6463     }
6464 
6465     m_port_op.flush_inprogress = OMX_FALSE;
6466 
6467     return retval;
6468 }
6469 
6470 /**
6471  * @brief Process port reconfiguration event.
6472  *
6473  * @retval OMX_ERRORTYPE
6474  */
async_process_event_port_reconfig()6475 OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig()
6476 {
6477     OMX_ERRORTYPE retval = OMX_ErrorNone;
6478 
6479     if (m_port_reconfig_inprogress)
6480     {
6481         OMX_SWVDEC_LOG_ERROR("port reconfiguration already in progress");
6482 
6483         retval = OMX_ErrorIncorrectStateOperation;
6484     }
6485     else
6486     {
6487         m_port_reconfig_inprogress = true;
6488 
6489         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6490                                 "OMX_EventPortSettingsChanged, port index %d",
6491                                 OMX_CORE_PORT_INDEX_OP);
6492 
6493         m_callback.EventHandler(&m_cmp,
6494                                 m_app_data,
6495                                 OMX_EventPortSettingsChanged,
6496                                 OMX_CORE_PORT_INDEX_OP,
6497                                 OMX_IndexParamPortDefinition,
6498                                 NULL);
6499     }
6500 
6501     return retval;
6502 }
6503 
6504 /**
6505  * @brief Process dimensions updated event.
6506  *
6507  * @retval OMX_ERRORTYPE
6508  */
async_process_event_dimensions_updated()6509 OMX_ERRORTYPE omx_swvdec::async_process_event_dimensions_updated()
6510 {
6511     OMX_ERRORTYPE retval = OMX_ErrorNone;
6512 
6513     if (m_dimensions_update_inprogress)
6514     {
6515         OMX_SWVDEC_LOG_ERROR("dimensions update already in progress");
6516 
6517         retval = OMX_ErrorIncorrectStateOperation;
6518     }
6519     else
6520     {
6521         m_dimensions_update_inprogress = true;
6522 
6523         OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
6524                                 "OMX_EventPortSettingsChanged, port index %d, "
6525                                 "OMX_IndexConfigCommonOutputCrop",
6526                                 OMX_CORE_PORT_INDEX_OP);
6527 
6528         m_callback.EventHandler(&m_cmp,
6529                                 m_app_data,
6530                                 OMX_EventPortSettingsChanged,
6531                                 OMX_CORE_PORT_INDEX_OP,
6532                                 OMX_IndexConfigCommonOutputCrop,
6533                                 NULL);
6534     }
6535 
6536     return retval;
6537 }
6538 
6539 /**
6540  * @brief Map the memory and run the ioctl SYNC operations
6541  *.on ION fd with DMA_BUF_IOCTL_SYNC
6542  *.@param[in] fd: ION header.
6543  * @param[in] len:Lenth of the memory.
6544  * @retval mapped memory pointer
6545  */
ion_map(int fd,int len)6546 unsigned char *omx_swvdec::ion_map(int fd, int len)
6547 {
6548     unsigned char *bufaddr = (unsigned char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
6549                                 MAP_SHARED, fd, 0);
6550     if (bufaddr != MAP_FAILED) {
6551 #ifdef USE_ION
6552         struct dma_buf_sync buf_sync;
6553         buf_sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
6554         int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync);
6555         if (rc) {
6556             OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC");
6557         }
6558 #endif
6559     }
6560     return bufaddr;
6561 }
6562 
6563 /**
6564  * @brief Unmap the memory
6565  *.@param[in] fd: ION header.
6566  .*.@param[in].bufaddr : buffer address
6567  * @param[in] len:Lenth of the memory.
6568  * @retval OMX_ERRORTYPE
6569  */
ion_unmap(int fd,void * bufaddr,int len)6570 OMX_ERRORTYPE omx_swvdec::ion_unmap(int fd, void *bufaddr, int len)
6571 {
6572 #ifdef USE_ION
6573     struct dma_buf_sync buf_sync;
6574     buf_sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
6575     int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync);
6576     if (rc) {
6577         OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC");
6578     }
6579 #endif
6580     if (-1 == munmap(bufaddr, len)) {
6581         OMX_SWVDEC_LOG_ERROR("munmap failed.");
6582         return OMX_ErrorInsufficientResources;
6583     }
6584     return OMX_ErrorNone;
6585 }
6586 
6587