Home | History | Annotate | Download | only in omx
      1 /**************************************************************************
      2  *
      3  * Copyright 2013 Advanced Micro Devices, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 /*
     29  * Authors:
     30  *      Christian Knig <christian.koenig (at) amd.com>
     31  *
     32  */
     33 
     34 
     35 #include <assert.h>
     36 
     37 #include <OMX_Video.h>
     38 
     39 /* bellagio defines a DEBUG macro that we don't want */
     40 #ifndef DEBUG
     41 #include <bellagio/omxcore.h>
     42 #undef DEBUG
     43 #else
     44 #include <bellagio/omxcore.h>
     45 #endif
     46 
     47 #include "pipe/p_screen.h"
     48 #include "pipe/p_video_codec.h"
     49 #include "util/u_memory.h"
     50 #include "util/u_surface.h"
     51 #include "vl/vl_video_buffer.h"
     52 #include "vl/vl_vlc.h"
     53 
     54 #include "entrypoint.h"
     55 #include "vid_dec.h"
     56 
     57 static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name);
     58 static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp);
     59 static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param);
     60 static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param);
     61 static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg);
     62 static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf);
     63 static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf);
     64 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output);
     65 
     66 OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp)
     67 {
     68    comp->componentVersion.s.nVersionMajor = 0;
     69    comp->componentVersion.s.nVersionMinor = 0;
     70    comp->componentVersion.s.nRevision = 0;
     71    comp->componentVersion.s.nStep = 1;
     72    comp->name_specific_length = 3;
     73 
     74    comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
     75    if (comp->name == NULL)
     76       goto error;
     77 
     78    comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *));
     79    if (comp->name_specific == NULL)
     80       goto error;
     81 
     82    comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *));
     83    if (comp->role_specific == NULL)
     84       goto error;
     85 
     86    comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
     87    if (comp->name_specific[0] == NULL)
     88       goto error_specific;
     89 
     90    comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
     91    if (comp->name_specific[1] == NULL)
     92       goto error_specific;
     93 
     94    comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
     95    if (comp->name_specific[2] == NULL)
     96       goto error_specific;
     97 
     98    comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
     99    if (comp->role_specific[0] == NULL)
    100       goto error_specific;
    101 
    102    comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
    103    if (comp->role_specific[1] == NULL)
    104       goto error_specific;
    105 
    106    comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);
    107    if (comp->role_specific[2] == NULL)
    108       goto error_specific;
    109 
    110    strcpy(comp->name, OMX_VID_DEC_BASE_NAME);
    111    strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME);
    112    strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME);
    113    strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME);
    114 
    115    strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE);
    116    strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE);
    117    strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE);
    118 
    119    comp->constructor = vid_dec_Constructor;
    120 
    121    return OMX_ErrorNone;
    122 
    123 error_specific:
    124    FREE(comp->role_specific[2]);
    125    FREE(comp->role_specific[1]);
    126    FREE(comp->role_specific[0]);
    127    FREE(comp->name_specific[2]);
    128    FREE(comp->name_specific[1]);
    129    FREE(comp->name_specific[0]);
    130 
    131 error:
    132    FREE(comp->role_specific);
    133    FREE(comp->name_specific);
    134 
    135    FREE(comp->name);
    136 
    137    return OMX_ErrorInsufficientResources;
    138 }
    139 
    140 static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name)
    141 {
    142    vid_dec_PrivateType *priv;
    143    omx_base_video_PortType *port;
    144    struct pipe_screen *screen;
    145    OMX_ERRORTYPE r;
    146    int i;
    147 
    148    assert(!comp->pComponentPrivate);
    149 
    150    priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType));
    151    if (!priv)
    152       return OMX_ErrorInsufficientResources;
    153 
    154    r = omx_base_filter_Constructor(comp, name);
    155    if (r)
    156       return r;
    157 
    158    priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN;
    159 
    160    if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME))
    161       priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN;
    162 
    163    if (!strcmp(name, OMX_VID_DEC_AVC_NAME))
    164       priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;
    165 
    166    if (!strcmp(name, OMX_VID_DEC_HEVC_NAME))
    167       priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;
    168 
    169    priv->BufferMgmtCallback = vid_dec_FrameDecoded;
    170    priv->messageHandler = vid_dec_MessageHandler;
    171    priv->destructor = vid_dec_Destructor;
    172 
    173    comp->SetParameter = vid_dec_SetParameter;
    174    comp->GetParameter = vid_dec_GetParameter;
    175 
    176    priv->screen = omx_get_screen();
    177    if (!priv->screen)
    178       return OMX_ErrorInsufficientResources;
    179 
    180    screen = priv->screen->pscreen;
    181    priv->pipe = screen->context_create(screen, priv->screen, 0);
    182    if (!priv->pipe)
    183       return OMX_ErrorInsufficientResources;
    184 
    185    if (!vl_compositor_init(&priv->compositor, priv->pipe)) {
    186       priv->pipe->destroy(priv->pipe);
    187       priv->pipe = NULL;
    188       return OMX_ErrorInsufficientResources;
    189    }
    190 
    191    if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) {
    192       vl_compositor_cleanup(&priv->compositor);
    193       priv->pipe->destroy(priv->pipe);
    194       priv->pipe = NULL;
    195       return OMX_ErrorInsufficientResources;
    196    }
    197 
    198    priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0;
    199    priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2;
    200    priv->ports = CALLOC(2, sizeof(omx_base_PortType *));
    201    if (!priv->ports)
    202       return OMX_ErrorInsufficientResources;
    203 
    204    for (i = 0; i < 2; ++i) {
    205       priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType));
    206       if (!priv->ports[i])
    207          return OMX_ErrorInsufficientResources;
    208 
    209       base_video_port_Constructor(comp, &priv->ports[i], i, i == 0);
    210    }
    211 
    212    port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
    213    strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2");
    214    port->sPortParam.nBufferCountMin = 8;
    215    port->sPortParam.nBufferCountActual = 8;
    216    port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE;
    217    port->sPortParam.format.video.nFrameWidth = 176;
    218    port->sPortParam.format.video.nFrameHeight = 144;
    219    port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
    220    port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
    221    port->Port_SendBufferFunction = vid_dec_DecodeBuffer;
    222    port->Port_FreeBuffer = vid_dec_FreeDecBuffer;
    223 
    224    port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
    225    port->sPortParam.nBufferCountActual = 8;
    226    port->sPortParam.nBufferCountMin = 4;
    227    port->sPortParam.format.video.nFrameWidth = 176;
    228    port->sPortParam.format.video.nFrameHeight = 144;
    229    port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    230    port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    231 
    232    return OMX_ErrorNone;
    233 }
    234 
    235 static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp)
    236 {
    237    vid_dec_PrivateType* priv = comp->pComponentPrivate;
    238    int i;
    239 
    240    if (priv->ports) {
    241       for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) {
    242          if(priv->ports[i])
    243             priv->ports[i]->PortDestructor(priv->ports[i]);
    244       }
    245       FREE(priv->ports);
    246       priv->ports=NULL;
    247    }
    248 
    249    if (priv->pipe) {
    250       vl_compositor_cleanup_state(&priv->cstate);
    251       vl_compositor_cleanup(&priv->compositor);
    252       priv->pipe->destroy(priv->pipe);
    253    }
    254 
    255    if (priv->screen)
    256       omx_put_screen();
    257 
    258    return omx_workaround_Destructor(comp);
    259 }
    260 
    261 static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param)
    262 {
    263    OMX_COMPONENTTYPE *comp = handle;
    264    vid_dec_PrivateType *priv = comp->pComponentPrivate;
    265    OMX_ERRORTYPE r;
    266 
    267    if (!param)
    268       return OMX_ErrorBadParameter;
    269 
    270    switch(idx) {
    271    case OMX_IndexParamPortDefinition: {
    272       OMX_PARAM_PORTDEFINITIONTYPE *def = param;
    273 
    274       r = omx_base_component_SetParameter(handle, idx, param);
    275       if (r)
    276          return r;
    277 
    278       if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) {
    279          omx_base_video_PortType *port;
    280          unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight;
    281 
    282          port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
    283          port->sPortParam.nBufferSize = framesize * 512 / (16*16);
    284 
    285          port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
    286          port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth;
    287          port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight;
    288          port->sPortParam.format.video.nStride = def->format.video.nFrameWidth;
    289          port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight;
    290          port->sPortParam.nBufferSize = framesize*3/2;
    291 
    292          priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged,
    293                                        OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL);
    294       }
    295       break;
    296    }
    297    case OMX_IndexParamStandardComponentRole: {
    298       OMX_PARAM_COMPONENTROLETYPE *role = param;
    299 
    300       r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE));
    301       if (r)
    302          return r;
    303 
    304       if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) {
    305          priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN;
    306       } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) {
    307          priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;
    308       } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) {
    309          priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;
    310       } else {
    311          return OMX_ErrorBadParameter;
    312       }
    313 
    314       break;
    315    }
    316    case OMX_IndexParamVideoPortFormat: {
    317       OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param;
    318       omx_base_video_PortType *port;
    319 
    320       r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
    321       if (r)
    322          return r;
    323 
    324       if (format->nPortIndex > 1)
    325          return OMX_ErrorBadPortIndex;
    326 
    327       port = (omx_base_video_PortType *)priv->ports[format->nPortIndex];
    328       memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
    329       break;
    330    }
    331    default:
    332       return omx_base_component_SetParameter(handle, idx, param);
    333    }
    334    return OMX_ErrorNone;
    335 }
    336 
    337 static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param)
    338 {
    339    OMX_COMPONENTTYPE *comp = handle;
    340    vid_dec_PrivateType *priv = comp->pComponentPrivate;
    341    OMX_ERRORTYPE r;
    342 
    343    if (!param)
    344       return OMX_ErrorBadParameter;
    345 
    346    switch(idx) {
    347    case OMX_IndexParamStandardComponentRole: {
    348       OMX_PARAM_COMPONENTROLETYPE *role = param;
    349 
    350       r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE));
    351       if (r)
    352          return r;
    353 
    354       if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN)
    355          strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE);
    356       else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH)
    357          strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE);
    358       else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN)
    359          strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE);
    360 
    361       break;
    362    }
    363 
    364    case OMX_IndexParamVideoInit:
    365       r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE));
    366       if (r)
    367          return r;
    368 
    369       memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE));
    370       break;
    371 
    372    case OMX_IndexParamVideoPortFormat: {
    373       OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param;
    374       omx_base_video_PortType *port;
    375 
    376       r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
    377       if (r)
    378          return r;
    379 
    380       if (format->nPortIndex > 1)
    381          return OMX_ErrorBadPortIndex;
    382 
    383       port = (omx_base_video_PortType *)priv->ports[format->nPortIndex];
    384       memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
    385       break;
    386    }
    387 
    388    default:
    389       return omx_base_component_GetParameter(handle, idx, param);
    390 
    391    }
    392    return OMX_ErrorNone;
    393 }
    394 
    395 static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg)
    396 {
    397    vid_dec_PrivateType* priv = comp->pComponentPrivate;
    398 
    399    if (msg->messageType == OMX_CommandStateSet) {
    400       if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) {
    401          if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN)
    402             vid_dec_mpeg12_Init(priv);
    403          else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH)
    404             vid_dec_h264_Init(priv);
    405          else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN)
    406             vid_dec_h265_Init(priv);
    407 
    408       } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) {
    409          if (priv->shadow) {
    410             priv->shadow->destroy(priv->shadow);
    411             priv->shadow = NULL;
    412          }
    413          if (priv->codec) {
    414             priv->codec->destroy(priv->codec);
    415             priv->codec = NULL;
    416          }
    417       }
    418    }
    419 
    420    return omx_base_component_MessageHandler(comp, msg);
    421 }
    422 
    423 void vid_dec_NeedTarget(vid_dec_PrivateType *priv)
    424 {
    425    struct pipe_video_buffer templat = {};
    426    struct vl_screen *omx_screen;
    427    struct pipe_screen *pscreen;
    428 
    429    omx_screen = priv->screen;
    430    assert(omx_screen);
    431 
    432    pscreen = omx_screen->pscreen;
    433    assert(pscreen);
    434 
    435    if (!priv->target) {
    436       memset(&templat, 0, sizeof(templat));
    437 
    438       templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
    439       templat.width = priv->codec->width;
    440       templat.height = priv->codec->height;
    441       templat.buffer_format = pscreen->get_video_param(
    442             pscreen,
    443             PIPE_VIDEO_PROFILE_UNKNOWN,
    444             PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
    445             PIPE_VIDEO_CAP_PREFERED_FORMAT
    446       );
    447       templat.interlaced = pscreen->get_video_param(
    448           pscreen,
    449           PIPE_VIDEO_PROFILE_UNKNOWN,
    450           PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
    451           PIPE_VIDEO_CAP_PREFERS_INTERLACED
    452       );
    453       priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat);
    454    }
    455 }
    456 
    457 static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf)
    458 {
    459    struct pipe_video_buffer *vbuf = buf->pInputPortPrivate;
    460    if (!vbuf)
    461       return;
    462 
    463    vbuf->destroy(vbuf);
    464    buf->pInputPortPrivate = NULL;
    465 }
    466 
    467 static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)
    468 {
    469    OMX_COMPONENTTYPE* comp = port->standCompContainer;
    470    vid_dec_PrivateType *priv = comp->pComponentPrivate;
    471    unsigned i = priv->num_in_buffers++;
    472    OMX_ERRORTYPE r;
    473 
    474    priv->in_buffers[i] = buf;
    475    priv->sizes[i] = buf->nFilledLen;
    476    priv->inputs[i] = buf->pBuffer;
    477    priv->timestamps[i] = buf->nTimeStamp;
    478 
    479    while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) {
    480       bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS);
    481       unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32);
    482       struct vl_vlc vlc;
    483 
    484       vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes);
    485 
    486       if (priv->slice)
    487          priv->bytes_left = vl_vlc_bits_left(&vlc) / 8;
    488 
    489       while (vl_vlc_bits_left(&vlc) > min_bits_left) {
    490          priv->Decode(priv, &vlc, min_bits_left);
    491          vl_vlc_fillbits(&vlc);
    492       }
    493 
    494       if (priv->slice) {
    495          unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8;
    496 
    497          priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
    498                                        1, &priv->slice, &bytes);
    499 
    500          if (priv->num_in_buffers)
    501             priv->slice = priv->inputs[1];
    502          else
    503             priv->slice = NULL;
    504       }
    505 
    506       if (eos && priv->frame_started)
    507          priv->EndFrame(priv);
    508 
    509       if (priv->frame_finished) {
    510          priv->frame_finished = false;
    511          priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen;
    512          r = base_port_SendBufferFunction(port, priv->in_buffers[0]);
    513       } else if (eos) {
    514          vid_dec_FreeInputPortPrivate(priv->in_buffers[0]);
    515          priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen;
    516          r = base_port_SendBufferFunction(port, priv->in_buffers[0]);
    517       } else {
    518          priv->in_buffers[0]->nFilledLen = 0;
    519          r = port->ReturnBufferFunction(port, priv->in_buffers[0]);
    520       }
    521 
    522       if (--priv->num_in_buffers) {
    523          unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]);
    524 
    525          priv->in_buffers[0] = priv->in_buffers[1];
    526          priv->sizes[0] = priv->sizes[1] - delta;
    527          priv->inputs[0] = priv->inputs[1] + delta;
    528          priv->timestamps[0] = priv->timestamps[1];
    529       }
    530 
    531       if (r)
    532          return r;
    533    }
    534 
    535    return OMX_ErrorNone;
    536 }
    537 
    538 static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf)
    539 {
    540    vid_dec_FreeInputPortPrivate(buf);
    541    return base_port_FreeBuffer(port, idx, buf);
    542 }
    543 
    544 static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf,
    545                                OMX_BUFFERHEADERTYPE* output)
    546 {
    547    omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
    548    OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
    549 
    550    struct pipe_sampler_view **views;
    551    unsigned i, j;
    552    unsigned width, height;
    553 
    554    views = buf->get_sampler_view_planes(buf);
    555 
    556    for (i = 0; i < 2 /* NV12 */; i++) {
    557       if (!views[i]) continue;
    558       width = def->nFrameWidth;
    559       height = def->nFrameHeight;
    560       vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced);
    561       for (j = 0; j < views[i]->texture->array_size; ++j) {
    562          struct pipe_box box = {0, 0, j, width, height, 1};
    563          struct pipe_transfer *transfer;
    564          uint8_t *map, *dst;
    565          map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0,
    566                   PIPE_TRANSFER_READ, &box, &transfer);
    567          if (!map)
    568             return;
    569 
    570          dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride +
    571                i * def->nFrameWidth * def->nFrameHeight;
    572          util_copy_rect(dst,
    573             views[i]->texture->format,
    574             def->nStride * views[i]->texture->array_size, 0, 0,
    575             box.width, box.height, map, transfer->stride, 0, 0);
    576 
    577          pipe_transfer_unmap(priv->pipe, transfer);
    578       }
    579    }
    580 }
    581 
    582 static void vid_dec_deint(vid_dec_PrivateType *priv, struct pipe_video_buffer *src_buf,
    583                           struct pipe_video_buffer *dst_buf)
    584 {
    585    struct vl_compositor *compositor = &priv->compositor;
    586    struct vl_compositor_state *s = &priv->cstate;
    587    struct pipe_surface **dst_surface;
    588    struct u_rect dst_rect;
    589 
    590    dst_surface = dst_buf->get_surfaces(dst_buf);
    591    vl_compositor_clear_layers(s);
    592 
    593    dst_rect.x0 = 0;
    594    dst_rect.x1 = src_buf->width;
    595    dst_rect.y0 = 0;
    596    dst_rect.y1 = src_buf->height;
    597 
    598    vl_compositor_set_yuv_layer(s, compositor, 0, src_buf, NULL, NULL, true);
    599    vl_compositor_set_layer_dst_area(s, 0, &dst_rect);
    600    vl_compositor_render(s, compositor, dst_surface[0], NULL, false);
    601 
    602    dst_rect.x1 /= 2;
    603    dst_rect.y1 /= 2;
    604 
    605    vl_compositor_set_yuv_layer(s, compositor, 0, src_buf, NULL, NULL, false);
    606    vl_compositor_set_layer_dst_area(s, 0, &dst_rect);
    607    vl_compositor_render(s, compositor, dst_surface[1], NULL, false);
    608 }
    609 
    610 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input,
    611                                  OMX_BUFFERHEADERTYPE* output)
    612 {
    613    vid_dec_PrivateType *priv = comp->pComponentPrivate;
    614    bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS);
    615    OMX_TICKS timestamp;
    616 
    617    if (!input->pInputPortPrivate) {
    618       input->pInputPortPrivate = priv->Flush(priv, &timestamp);
    619       if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID)
    620          input->nTimeStamp = timestamp;
    621    }
    622 
    623    if (input->pInputPortPrivate) {
    624       if (output->pInputPortPrivate && !priv->disable_tunnel) {
    625          struct pipe_video_buffer *tmp, *vbuf, *new_vbuf;
    626 
    627          tmp = output->pOutputPortPrivate;
    628          vbuf = input->pInputPortPrivate;
    629          if (vbuf->interlaced) {
    630             /* re-allocate the progressive buffer */
    631             omx_base_video_PortType *port;
    632             struct pipe_video_buffer templat = {};
    633 
    634             port = (omx_base_video_PortType *)
    635                     priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
    636             memset(&templat, 0, sizeof(templat));
    637             templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
    638             templat.width = port->sPortParam.format.video.nFrameWidth;
    639             templat.height = port->sPortParam.format.video.nFrameHeight;
    640             templat.buffer_format = PIPE_FORMAT_NV12;
    641             templat.interlaced = false;
    642             new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat);
    643 
    644             /* convert the interlaced to the progressive */
    645             vid_dec_deint(priv, input->pInputPortPrivate, new_vbuf);
    646             priv->pipe->flush(priv->pipe, NULL, 0);
    647 
    648             /* set the progrssive buffer for next round */
    649             vbuf->destroy(vbuf);
    650             input->pInputPortPrivate = new_vbuf;
    651          }
    652          output->pOutputPortPrivate = input->pInputPortPrivate;
    653          input->pInputPortPrivate = tmp;
    654       } else {
    655          vid_dec_FillOutput(priv, input->pInputPortPrivate, output);
    656       }
    657       output->nFilledLen = output->nAllocLen;
    658       output->nTimeStamp = input->nTimeStamp;
    659    }
    660 
    661    if (eos && input->pInputPortPrivate)
    662       vid_dec_FreeInputPortPrivate(input);
    663    else
    664       input->nFilledLen = 0;
    665 }
    666