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