Path: blob/21.2-virgl/src/gallium/frontends/omx/bellagio/vid_dec.c
4565 views
/**************************************************************************1*2* Copyright 2013 Advanced Micro Devices, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/*28* Authors:29* Christian König <[email protected]>30*31*/323334#include <assert.h>3536#include <OMX_Video.h>3738/* bellagio defines a DEBUG macro that we don't want */39#ifndef DEBUG40#include <bellagio/omxcore.h>41#undef DEBUG42#else43#include <bellagio/omxcore.h>44#endif4546#include "pipe/p_screen.h"47#include "pipe/p_video_codec.h"48#include "util/u_memory.h"49#include "util/u_surface.h"50#include "vl/vl_video_buffer.h"51#include "vl/vl_vlc.h"5253#include "entrypoint.h"54#include "vid_dec.h"55#include "vid_omx_common.h"56#include "vid_dec_h264_common.h"5758static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name);59static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp);60static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param);61static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param);62static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg);63static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf);64static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf);65static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output);6667OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp)68{69comp->componentVersion.s.nVersionMajor = 0;70comp->componentVersion.s.nVersionMinor = 0;71comp->componentVersion.s.nRevision = 0;72comp->componentVersion.s.nStep = 1;73comp->name_specific_length = 4;7475comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);76if (comp->name == NULL)77goto error;7879comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *));80if (comp->name_specific == NULL)81goto error;8283comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *));84if (comp->role_specific == NULL)85goto error;8687comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);88if (comp->name_specific[0] == NULL)89goto error_specific;9091comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);92if (comp->name_specific[1] == NULL)93goto error_specific;9495comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);96if (comp->name_specific[2] == NULL)97goto error_specific;9899comp->name_specific[3] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);100if (comp->name_specific[3] == NULL)101goto error_specific;102103comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);104if (comp->role_specific[0] == NULL)105goto error_specific;106107comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);108if (comp->role_specific[1] == NULL)109goto error_specific;110111comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);112if (comp->role_specific[2] == NULL)113goto error_specific;114115comp->role_specific[3] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE);116if (comp->role_specific[3] == NULL)117goto error_specific;118119strcpy(comp->name, OMX_VID_DEC_BASE_NAME);120strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME);121strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME);122strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME);123strcpy(comp->name_specific[3], OMX_VID_DEC_AV1_NAME);124125strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE);126strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE);127strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE);128strcpy(comp->role_specific[3], OMX_VID_DEC_AV1_ROLE);129130comp->constructor = vid_dec_Constructor;131132return OMX_ErrorNone;133134error_specific:135FREE(comp->role_specific[3]);136FREE(comp->role_specific[2]);137FREE(comp->role_specific[1]);138FREE(comp->role_specific[0]);139FREE(comp->name_specific[3]);140FREE(comp->name_specific[2]);141FREE(comp->name_specific[1]);142FREE(comp->name_specific[0]);143144error:145FREE(comp->role_specific);146FREE(comp->name_specific);147148FREE(comp->name);149150return OMX_ErrorInsufficientResources;151}152153static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name)154{155vid_dec_PrivateType *priv;156omx_base_video_PortType *port;157struct pipe_screen *screen;158OMX_ERRORTYPE r;159int i;160161assert(!comp->pComponentPrivate);162163priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType));164if (!priv)165return OMX_ErrorInsufficientResources;166167r = omx_base_filter_Constructor(comp, name);168if (r)169return r;170171priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN;172173if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME))174priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN;175176if (!strcmp(name, OMX_VID_DEC_AVC_NAME))177priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;178179if (!strcmp(name, OMX_VID_DEC_HEVC_NAME))180priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;181182if (!strcmp(name, OMX_VID_DEC_AV1_NAME))183priv->profile = PIPE_VIDEO_PROFILE_AV1_MAIN;184185if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN)186priv->BufferMgmtCallback = vid_dec_av1_FrameDecoded;187else188priv->BufferMgmtCallback = vid_dec_FrameDecoded;189priv->messageHandler = vid_dec_MessageHandler;190priv->destructor = vid_dec_Destructor;191192comp->SetParameter = vid_dec_SetParameter;193comp->GetParameter = vid_dec_GetParameter;194195priv->screen = omx_get_screen();196if (!priv->screen)197return OMX_ErrorInsufficientResources;198199screen = priv->screen->pscreen;200priv->pipe = pipe_create_multimedia_context(screen);201if (!priv->pipe)202return OMX_ErrorInsufficientResources;203204if (!vl_compositor_init(&priv->compositor, priv->pipe)) {205priv->pipe->destroy(priv->pipe);206priv->pipe = NULL;207return OMX_ErrorInsufficientResources;208}209210if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) {211vl_compositor_cleanup(&priv->compositor);212priv->pipe->destroy(priv->pipe);213priv->pipe = NULL;214return OMX_ErrorInsufficientResources;215}216217priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0;218priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2;219priv->ports = CALLOC(2, sizeof(omx_base_PortType *));220if (!priv->ports)221return OMX_ErrorInsufficientResources;222223for (i = 0; i < 2; ++i) {224priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType));225if (!priv->ports[i])226return OMX_ErrorInsufficientResources;227228base_video_port_Constructor(comp, &priv->ports[i], i, i == 0);229}230231port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];232strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2");233port->sPortParam.nBufferCountMin = 8;234port->sPortParam.nBufferCountActual = 8;235port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE;236port->sPortParam.format.video.nFrameWidth = 176;237port->sPortParam.format.video.nFrameHeight = 144;238port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;239port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2;240port->Port_SendBufferFunction = vid_dec_DecodeBuffer;241if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN) {242port->Port_AllocateBuffer = vid_dec_av1_AllocateInBuffer;243port->Port_UseBuffer = vid_dec_av1_UseInBuffer;244}245246port->Port_FreeBuffer = vid_dec_FreeDecBuffer;247port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];248port->sPortParam.nBufferCountActual = 8;249port->sPortParam.nBufferCountMin = 4;250port->sPortParam.format.video.nFrameWidth = 176;251port->sPortParam.format.video.nFrameHeight = 144;252port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;253port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;254255return OMX_ErrorNone;256}257258static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp)259{260vid_dec_PrivateType* priv = comp->pComponentPrivate;261int i;262263if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN)264vid_dec_av1_ReleaseTasks(priv);265266if (priv->ports) {267for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) {268if(priv->ports[i])269priv->ports[i]->PortDestructor(priv->ports[i]);270}271FREE(priv->ports);272priv->ports=NULL;273}274275if (priv->pipe) {276vl_compositor_cleanup_state(&priv->cstate);277vl_compositor_cleanup(&priv->compositor);278priv->pipe->destroy(priv->pipe);279}280281if (priv->screen)282omx_put_screen();283284return omx_workaround_Destructor(comp);285}286287static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param)288{289OMX_COMPONENTTYPE *comp = handle;290vid_dec_PrivateType *priv = comp->pComponentPrivate;291OMX_ERRORTYPE r;292293if (!param)294return OMX_ErrorBadParameter;295296switch(idx) {297case OMX_IndexParamPortDefinition: {298OMX_PARAM_PORTDEFINITIONTYPE *def = param;299300r = omx_base_component_SetParameter(handle, idx, param);301if (r)302return r;303304if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) {305omx_base_video_PortType *port;306unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight;307308port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];309port->sPortParam.nBufferSize = framesize * 512 / (16*16);310311port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];312port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth;313port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight;314port->sPortParam.format.video.nStride = def->format.video.nFrameWidth;315port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight;316port->sPortParam.nBufferSize = framesize*3/2;317318priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged,319OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL);320}321break;322}323case OMX_IndexParamStandardComponentRole: {324OMX_PARAM_COMPONENTROLETYPE *role = param;325326r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE));327if (r)328return r;329330if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) {331priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN;332} else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) {333priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH;334} else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) {335priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;336} else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AV1_ROLE)) {337priv->profile = PIPE_VIDEO_PROFILE_AV1_MAIN;338} else {339return OMX_ErrorBadParameter;340}341342break;343}344case OMX_IndexParamVideoPortFormat: {345OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param;346omx_base_video_PortType *port;347348r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));349if (r)350return r;351352if (format->nPortIndex > 1)353return OMX_ErrorBadPortIndex;354355port = (omx_base_video_PortType *)priv->ports[format->nPortIndex];356memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));357break;358}359default:360return omx_base_component_SetParameter(handle, idx, param);361}362return OMX_ErrorNone;363}364365static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param)366{367OMX_COMPONENTTYPE *comp = handle;368vid_dec_PrivateType *priv = comp->pComponentPrivate;369OMX_ERRORTYPE r;370371if (!param)372return OMX_ErrorBadParameter;373374switch(idx) {375case OMX_IndexParamStandardComponentRole: {376OMX_PARAM_COMPONENTROLETYPE *role = param;377378r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE));379if (r)380return r;381382if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN)383strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE);384else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH)385strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE);386else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN)387strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE);388else if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN)389strcpy((char *)role->cRole, OMX_VID_DEC_AV1_ROLE);390391break;392}393394case OMX_IndexParamVideoInit:395r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE));396if (r)397return r;398399memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE));400break;401402case OMX_IndexParamVideoPortFormat: {403OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param;404omx_base_video_PortType *port;405406r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));407if (r)408return r;409410if (format->nPortIndex > 1)411return OMX_ErrorBadPortIndex;412413port = (omx_base_video_PortType *)priv->ports[format->nPortIndex];414memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));415break;416}417418default:419return omx_base_component_GetParameter(handle, idx, param);420421}422return OMX_ErrorNone;423}424425static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg)426{427vid_dec_PrivateType* priv = comp->pComponentPrivate;428429if (msg->messageType == OMX_CommandStateSet) {430if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) {431if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN)432vid_dec_mpeg12_Init(priv);433else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH)434vid_dec_h264_Init(priv);435else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN)436vid_dec_h265_Init(priv);437else if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN) {438vid_dec_av1_Init(priv);439}440441} else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) {442if (priv->shadow) {443priv->shadow->destroy(priv->shadow);444priv->shadow = NULL;445}446if (priv->codec) {447priv->codec->destroy(priv->codec);448priv->codec = NULL;449}450}451}452453return omx_base_component_MessageHandler(comp, msg);454}455456static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf)457{458OMX_COMPONENTTYPE* comp = port->standCompContainer;459vid_dec_PrivateType *priv = comp->pComponentPrivate;460unsigned i = priv->num_in_buffers++;461OMX_ERRORTYPE r;462463priv->in_buffers[i] = buf;464priv->sizes[i] = buf->nFilledLen;465priv->inputs[i] = buf->pBuffer;466priv->timestamps[i] = buf->nTimeStamp;467468while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) {469bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS);470unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32);471struct vl_vlc vlc;472473vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes);474475if (priv->slice)476priv->bytes_left = vl_vlc_bits_left(&vlc) / 8;477478while (vl_vlc_bits_left(&vlc) > min_bits_left) {479priv->Decode(priv, &vlc, min_bits_left);480vl_vlc_fillbits(&vlc);481}482483if (priv->slice) {484unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8;485486priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,4871, &priv->slice, &bytes);488489if (priv->num_in_buffers)490priv->slice = priv->inputs[1];491else492priv->slice = NULL;493}494495if (eos && priv->frame_started)496priv->EndFrame(priv);497498if (priv->frame_finished) {499priv->frame_finished = false;500priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen;501r = base_port_SendBufferFunction(port, priv->in_buffers[0]);502} else if (eos) {503if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN)504vid_dec_av1_FreeInputPortPrivate(priv, priv->in_buffers[0]);505else506vid_dec_FreeInputPortPrivate(priv->in_buffers[0]);507priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen;508r = base_port_SendBufferFunction(port, priv->in_buffers[0]);509} else {510priv->in_buffers[0]->nFilledLen = 0;511r = port->ReturnBufferFunction(port, priv->in_buffers[0]);512}513514if (--priv->num_in_buffers) {515unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]);516517priv->in_buffers[0] = priv->in_buffers[1];518priv->sizes[0] = priv->sizes[1] - delta;519priv->inputs[0] = priv->inputs[1] + delta;520priv->timestamps[0] = priv->timestamps[1];521}522523if (r)524return r;525}526527return OMX_ErrorNone;528}529530static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf)531{532OMX_COMPONENTTYPE* comp = port->standCompContainer;533vid_dec_PrivateType *priv = comp->pComponentPrivate;534535if (priv->profile == PIPE_VIDEO_PROFILE_AV1_MAIN)536vid_dec_av1_FreeInputPortPrivate(priv, buf);537else538vid_dec_FreeInputPortPrivate(buf);539540return base_port_FreeBuffer(port, idx, buf);541}542543static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input,544OMX_BUFFERHEADERTYPE* output)545{546vid_dec_PrivateType *priv = comp->pComponentPrivate;547548vid_dec_FrameDecoded_common(priv, input, output);549}550551552