forked from Qortal/Brooklyn
1578 lines
54 KiB
C
1578 lines
54 KiB
C
/*
|
|
Copyright (c) 2012, Broadcom Europe Ltd
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of the copyright holder nor the
|
|
names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
|
|
#include "mmalomx.h"
|
|
#include "mmalomx_commands.h"
|
|
#include "mmalomx_roles.h"
|
|
#include "mmalomx_registry.h"
|
|
#include "mmalomx_buffer.h"
|
|
#include "mmalomx_parameters.h"
|
|
#include "mmalomx_logging.h"
|
|
|
|
#include <util/mmal_util.h>
|
|
#include <util/mmal_util_params.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#define MAX_CMD_BUFFERS 5
|
|
|
|
#define PARAM_GET_PORT(port, component, index) \
|
|
if (index >= component->ports_num) return OMX_ErrorBadPortIndex; \
|
|
port = &component->ports[index]
|
|
|
|
static void *mmalomx_cmd_thread_func(void *arg);
|
|
#define MMALOMX_ZERO_COPY_THRESHOLD 256
|
|
|
|
/*****************************************************************************/
|
|
OMX_ERRORTYPE mmalomx_callback_event_handler(
|
|
MMALOMX_COMPONENT_T *component,
|
|
OMX_EVENTTYPE eEvent,
|
|
OMX_U32 nData1,
|
|
OMX_U32 nData2,
|
|
OMX_PTR pEventData)
|
|
{
|
|
LOG_DEBUG("component %p, eEvent %i, nData1 %u, nData2 %u, pEventData %p",
|
|
component, (int)eEvent, (unsigned int)nData1, (unsigned int)nData2, pEventData);
|
|
return component->callbacks.EventHandler((OMX_HANDLETYPE)&component->omx,
|
|
component->callbacks_data, eEvent, nData1, nData2, pEventData);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentGetComponentVersion(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_STRING pComponentName,
|
|
OMX_VERSIONTYPE* pComponentVersion,
|
|
OMX_VERSIONTYPE* pSpecVersion,
|
|
OMX_UUIDTYPE* pComponentUUID)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
const char *short_name, *prefix;
|
|
|
|
LOG_TRACE("hComponent %p, componentName %p, componentVersion %p, "
|
|
"pSpecVersion %p, componentUUID %p",
|
|
hComponent, pComponentName, pComponentVersion, pSpecVersion,
|
|
pComponentUUID);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
if (!pComponentName || !pComponentVersion || !pSpecVersion || !pComponentUUID )
|
|
return OMX_ErrorBadParameter;
|
|
|
|
short_name = mmalomx_registry_component_name(component->registry_id, &prefix);
|
|
|
|
snprintf(pComponentName, OMX_MAX_STRINGNAME_SIZE, "%s%s", short_name, prefix);
|
|
pComponentVersion->nVersion = 0;
|
|
pSpecVersion->nVersion = OMX_VERSION;
|
|
snprintf((char *)(*pComponentUUID), sizeof(OMX_UUIDTYPE), "%s", pComponentName);
|
|
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentSendCommand(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_COMMANDTYPE Cmd,
|
|
OMX_U32 nParam1,
|
|
OMX_PTR pCmdData)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
OMX_ERRORTYPE status = OMX_ErrorNone;
|
|
|
|
LOG_TRACE("hComponent %p, Cmd %i (%s), nParam1 %i (%s), pCmdData %p",
|
|
hComponent, Cmd, mmalomx_cmd_to_string(Cmd), (int)nParam1,
|
|
Cmd == OMX_CommandStateSet ? mmalomx_state_to_string((OMX_STATETYPE)nParam1) : "",
|
|
pCmdData);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
/* Sanity check port index */
|
|
if (Cmd == OMX_CommandFlush || Cmd == OMX_CommandMarkBuffer ||
|
|
Cmd == OMX_CommandPortEnable || Cmd == OMX_CommandPortDisable)
|
|
{
|
|
if (nParam1 != OMX_ALL && nParam1 >= component->ports_num)
|
|
return OMX_ErrorBadPortIndex;
|
|
}
|
|
|
|
if (Cmd == OMX_CommandStateSet ||
|
|
Cmd == OMX_CommandFlush ||
|
|
Cmd == OMX_CommandPortEnable ||
|
|
Cmd == OMX_CommandPortDisable)
|
|
{
|
|
status = mmalomx_command_queue(component, Cmd, nParam1);
|
|
}
|
|
else if (Cmd == OMX_CommandMarkBuffer)
|
|
{
|
|
status = mmalomx_command_port_mark(hComponent, nParam1, pCmdData);
|
|
}
|
|
else
|
|
{
|
|
status = OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static MMAL_STATUS_T mmalomx_get_port_settings(MMALOMX_PORT_T *port, OMX_PARAM_PORTDEFINITIONTYPE *def)
|
|
{
|
|
MMAL_STATUS_T status = MMAL_SUCCESS;
|
|
MMAL_PORT_T *mmal = port->mmal;
|
|
|
|
def->eDomain = mmalil_es_type_to_omx_domain(mmal->format->type);
|
|
def->eDir = OMX_DirInput;
|
|
if (mmal->type == MMAL_PORT_TYPE_OUTPUT)
|
|
def->eDir = OMX_DirOutput;
|
|
|
|
if (def->eDomain == OMX_PortDomainVideo)
|
|
{
|
|
def->format.video.eColorFormat = OMX_COLOR_FormatUnused;
|
|
def->format.video.eCompressionFormat = mmalil_encoding_to_omx_video_coding(mmal->format->encoding);
|
|
if (def->format.video.eCompressionFormat == OMX_VIDEO_CodingUnused)
|
|
def->format.video.eColorFormat = mmalil_encoding_to_omx_color_format(mmal->format->encoding);
|
|
|
|
def->format.video.nBitrate = mmal->format->bitrate;
|
|
def->format.video.nFrameWidth = mmal->format->es->video.width;
|
|
if (mmal->format->es->video.crop.width)
|
|
def->format.video.nFrameWidth = mmal->format->es->video.crop.width;
|
|
def->format.video.nStride = mmal->format->es->video.width;
|
|
if (port->no_cropping)
|
|
def->format.video.nFrameWidth = def->format.video.nStride;
|
|
def->format.video.nStride =
|
|
mmal_encoding_width_to_stride(mmal->format->encoding, def->format.video.nStride);
|
|
def->format.video.nFrameHeight = mmal->format->es->video.height;
|
|
if (mmal->format->es->video.crop.height)
|
|
def->format.video.nFrameHeight = mmal->format->es->video.crop.height;
|
|
def->format.video.nSliceHeight = mmal->format->es->video.height;
|
|
if (port->no_cropping)
|
|
def->format.video.nFrameHeight = def->format.video.nSliceHeight;
|
|
if (mmal->format->es->video.frame_rate.den)
|
|
def->format.video.xFramerate = (((int64_t)mmal->format->es->video.frame_rate.num) << 16) /
|
|
mmal->format->es->video.frame_rate.den;
|
|
else
|
|
def->format.video.xFramerate = 0;
|
|
}
|
|
else if (def->eDomain == OMX_PortDomainImage)
|
|
{
|
|
def->format.image.eColorFormat = OMX_COLOR_FormatUnused;
|
|
def->format.image.eCompressionFormat = mmalil_encoding_to_omx_image_coding(mmal->format->encoding);
|
|
if (def->format.image.eCompressionFormat == OMX_IMAGE_CodingUnused)
|
|
def->format.image.eColorFormat = mmalil_encoding_to_omx_color_format(mmal->format->encoding);
|
|
if (mmal->format->encoding == MMAL_ENCODING_UNKNOWN)
|
|
def->format.image.eCompressionFormat = OMX_IMAGE_CodingAutoDetect;
|
|
def->format.image.nFrameWidth = mmal->format->es->video.width;
|
|
if (mmal->format->es->video.crop.width)
|
|
def->format.image.nFrameWidth = mmal->format->es->video.crop.width;
|
|
def->format.image.nStride = mmal->format->es->video.width;
|
|
if (port->no_cropping)
|
|
def->format.image.nFrameWidth = def->format.image.nStride;
|
|
def->format.image.nStride =
|
|
mmal_encoding_width_to_stride(mmal->format->encoding, def->format.image.nStride);
|
|
def->format.image.nFrameHeight = mmal->format->es->video.height;
|
|
if (mmal->format->es->video.crop.height)
|
|
def->format.image.nFrameHeight = mmal->format->es->video.crop.height;
|
|
def->format.image.nSliceHeight = mmal->format->es->video.height;
|
|
if (port->no_cropping)
|
|
def->format.image.nFrameHeight = def->format.image.nSliceHeight;
|
|
}
|
|
else if(def->eDomain == OMX_PortDomainAudio)
|
|
{
|
|
def->format.audio.eEncoding = mmalil_encoding_to_omx_audio_coding(mmal->format->encoding);
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR("%s: unsupported domain (%u)", mmal->name, def->eDomain);
|
|
status = MMAL_EINVAL;
|
|
goto finish;
|
|
}
|
|
|
|
def->nBufferAlignment = mmal->buffer_alignment_min;
|
|
def->nBufferCountActual = mmal->buffer_num;
|
|
def->nBufferCountMin = mmal->buffer_num_min;
|
|
def->nBufferSize = mmal->buffer_size;
|
|
if (def->nBufferSize < mmal->buffer_size_min)
|
|
def->nBufferSize = mmal->buffer_size_min;
|
|
def->bEnabled = port->enabled;
|
|
def->bPopulated = port->populated;
|
|
|
|
finish:
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentGetParameter(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_INDEXTYPE nParamIndex,
|
|
OMX_PTR pParam)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMALOMX_PORT_T *port = NULL;
|
|
|
|
LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
|
|
hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pParam)
|
|
return OMX_ErrorBadParameter;
|
|
if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
switch(nParamIndex)
|
|
{
|
|
case OMX_IndexParamAudioInit:
|
|
case OMX_IndexParamVideoInit:
|
|
case OMX_IndexParamImageInit:
|
|
case OMX_IndexParamOtherInit:
|
|
{
|
|
OMX_PORT_PARAM_TYPE *param = (OMX_PORT_PARAM_TYPE *)pParam;
|
|
param->nStartPortNumber = 0;
|
|
param->nPorts = component->ports_domain_num[OMX_PortDomainAudio];
|
|
if (nParamIndex == OMX_IndexParamAudioInit)
|
|
return OMX_ErrorNone;
|
|
param->nStartPortNumber += param->nPorts;
|
|
param->nPorts = component->ports_domain_num[OMX_PortDomainVideo];
|
|
if (nParamIndex == OMX_IndexParamVideoInit)
|
|
return OMX_ErrorNone;
|
|
param->nStartPortNumber += param->nPorts;
|
|
param->nPorts = component->ports_domain_num[OMX_PortDomainImage];
|
|
if (nParamIndex == OMX_IndexParamImageInit)
|
|
return OMX_ErrorNone;
|
|
param->nStartPortNumber += param->nPorts;
|
|
param->nPorts = component->ports_domain_num[OMX_PortDomainOther];
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamPortDefinition:
|
|
{
|
|
OMX_PARAM_PORTDEFINITIONTYPE *param = (OMX_PARAM_PORTDEFINITIONTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
return mmalil_error_to_omx(mmalomx_get_port_settings(port, param));
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamCompBufferSupplier:
|
|
{
|
|
OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
param->eBufferSupplier = OMX_BufferSupplyUnspecified;
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamPriorityMgmt:
|
|
{
|
|
OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam;
|
|
param->nGroupPriority = component->group_priority;
|
|
param->nGroupID = component->group_id;
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamVideoPortFormat:
|
|
case OMX_IndexParamAudioPortFormat:
|
|
{
|
|
OMX_VIDEO_PARAM_PORTFORMATTYPE *param = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
|
|
/* Populate our internal list of encodings the first time around */
|
|
if (!port->encodings_num)
|
|
{
|
|
port->encodings_header.id = MMAL_PARAMETER_SUPPORTED_ENCODINGS;
|
|
port->encodings_header.size = sizeof(port->encodings_header) + sizeof(port->encodings);
|
|
if (mmal_port_parameter_get(port->mmal, &port->encodings_header) == MMAL_SUCCESS)
|
|
{
|
|
port->encodings_num = (port->encodings_header.size - sizeof(port->encodings_header)) /
|
|
sizeof(port->encodings[0]);
|
|
}
|
|
if (!port->encodings_num)
|
|
{
|
|
port->encodings_num = 1;
|
|
port->encodings[0] = port->mmal->format->encoding;
|
|
}
|
|
}
|
|
|
|
if (param->nIndex >= port->encodings_num)
|
|
return OMX_ErrorNoMore;
|
|
|
|
if (nParamIndex == OMX_IndexParamVideoPortFormat)
|
|
{
|
|
param->eColorFormat = OMX_COLOR_FormatUnused;
|
|
param->eCompressionFormat =
|
|
mmalil_encoding_to_omx_video_coding(port->encodings[param->nIndex]);
|
|
if (param->eCompressionFormat == OMX_VIDEO_CodingUnused)
|
|
param->eColorFormat =
|
|
mmalil_encoding_to_omx_color_format(port->encodings[param->nIndex]);
|
|
param->xFramerate = 0;
|
|
}
|
|
else
|
|
{
|
|
OMX_AUDIO_PARAM_PORTFORMATTYPE *aparam =
|
|
(OMX_AUDIO_PARAM_PORTFORMATTYPE *)pParam;
|
|
aparam->eEncoding =
|
|
mmalil_encoding_to_omx_audio_coding(port->encodings[param->nIndex]);
|
|
}
|
|
return OMX_ErrorNone;
|
|
}
|
|
break;
|
|
case OMX_IndexParamImagePortFormat:
|
|
case OMX_IndexParamOtherPortFormat:
|
|
break;
|
|
case OMX_IndexParamStandardComponentRole:
|
|
{
|
|
OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam;
|
|
const char *role = mmalomx_role_to_name(component->role);
|
|
if (!role)
|
|
role = component->name;
|
|
snprintf((char *)param->cRole, sizeof(param->cRole), "%s", role);
|
|
}
|
|
return OMX_ErrorNone;
|
|
default:
|
|
return mmalomx_parameter_get(component, nParamIndex, pParam);
|
|
}
|
|
|
|
return OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static MMAL_STATUS_T mmalomx_set_port_settings(MMALOMX_PORT_T *mmalomx_port,
|
|
OMX_PARAM_PORTDEFINITIONTYPE *def)
|
|
{
|
|
MMAL_PORT_T *port = mmalomx_port->mmal;
|
|
uint32_t buffer_size_min = port->buffer_size_min;
|
|
MMAL_STATUS_T status;
|
|
|
|
port->format->type = mmalil_omx_domain_to_es_type(def->eDomain);
|
|
port->format->encoding_variant = 0;
|
|
|
|
if(def->eDomain == OMX_PortDomainVideo)
|
|
{
|
|
if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused)
|
|
port->format->encoding = mmalil_omx_video_coding_to_encoding(def->format.video.eCompressionFormat);
|
|
else
|
|
port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.video.eColorFormat);
|
|
|
|
port->format->bitrate = def->format.video.nBitrate;
|
|
port->format->es->video.width = def->format.video.nFrameWidth;
|
|
if (!mmalomx_port->no_cropping)
|
|
port->format->es->video.crop.width = port->format->es->video.width;
|
|
if (mmal_encoding_stride_to_width(port->format->encoding, def->format.video.nStride))
|
|
port->format->es->video.width =
|
|
mmal_encoding_stride_to_width(port->format->encoding, def->format.video.nStride);
|
|
port->format->es->video.height = def->format.video.nFrameHeight;
|
|
if (!mmalomx_port->no_cropping)
|
|
port->format->es->video.crop.height = port->format->es->video.height;
|
|
if (def->format.video.nSliceHeight > def->format.video.nFrameHeight)
|
|
port->format->es->video.height = def->format.video.nSliceHeight;
|
|
port->format->es->video.frame_rate.num = def->format.video.xFramerate;
|
|
port->format->es->video.frame_rate.den = (1<<16);
|
|
}
|
|
else if(def->eDomain == OMX_PortDomainImage)
|
|
{
|
|
if (def->format.image.eCompressionFormat != OMX_IMAGE_CodingUnused)
|
|
port->format->encoding = mmalil_omx_image_coding_to_encoding(def->format.image.eCompressionFormat);
|
|
else
|
|
port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.image.eColorFormat);
|
|
|
|
port->format->es->video.width = def->format.image.nFrameWidth;
|
|
if (!mmalomx_port->no_cropping)
|
|
port->format->es->video.crop.width = port->format->es->video.width;
|
|
if (mmal_encoding_stride_to_width(port->format->encoding, def->format.image.nStride))
|
|
port->format->es->video.width =
|
|
mmal_encoding_stride_to_width(port->format->encoding, def->format.image.nStride);
|
|
port->format->es->video.height = def->format.image.nFrameHeight;
|
|
if (!mmalomx_port->no_cropping)
|
|
port->format->es->video.crop.height = port->format->es->video.height;
|
|
if (def->format.image.nSliceHeight > def->format.image.nFrameHeight)
|
|
port->format->es->video.height = def->format.image.nSliceHeight;
|
|
}
|
|
else if(def->eDomain == OMX_PortDomainAudio)
|
|
{
|
|
port->format->encoding = mmalil_omx_audio_coding_to_encoding(def->format.audio.eEncoding);
|
|
}
|
|
else
|
|
{
|
|
port->format->encoding = MMAL_ENCODING_UNKNOWN;
|
|
}
|
|
|
|
port->buffer_num = def->nBufferCountActual;
|
|
port->buffer_size = def->nBufferSize;
|
|
if (port->buffer_size < port->buffer_size_min)
|
|
port->buffer_size = port->buffer_size_min;
|
|
|
|
status = mmal_port_format_commit(port);
|
|
if (status != MMAL_SUCCESS)
|
|
return status;
|
|
|
|
/* Acknowledge any ongoing port format changed event */
|
|
mmalomx_port->format_changed = MMAL_FALSE;
|
|
|
|
/* The minimum buffer size only changes when the format significantly changes
|
|
* and in that case we want to advertise the new requirement to the client. */
|
|
if (port->buffer_size_min != buffer_size_min)
|
|
port->buffer_size = port->buffer_size_min;
|
|
|
|
return MMAL_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentSetParameter(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_INDEXTYPE nParamIndex,
|
|
OMX_PTR pParam)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMALOMX_PORT_T *port = NULL;
|
|
|
|
LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
|
|
hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pParam)
|
|
return OMX_ErrorBadParameter;
|
|
if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
switch(nParamIndex)
|
|
{
|
|
case OMX_IndexParamPortDefinition:
|
|
{
|
|
OMX_PARAM_PORTDEFINITIONTYPE *param = (OMX_PARAM_PORTDEFINITIONTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
return mmalil_error_to_omx(mmalomx_set_port_settings(port, param));
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamCompBufferSupplier:
|
|
{
|
|
OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
//param->eBufferSupplier = OMX_BufferSupplyUnspecified;
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamPriorityMgmt:
|
|
{
|
|
OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam;
|
|
|
|
if (component->state != OMX_StateLoaded)
|
|
return OMX_ErrorIncorrectStateOperation;
|
|
|
|
component->group_priority = param->nGroupPriority;
|
|
component->group_id = param->nGroupID;
|
|
}
|
|
return OMX_ErrorNone;
|
|
break;
|
|
case OMX_IndexParamAudioPortFormat:
|
|
{
|
|
OMX_AUDIO_PARAM_PORTFORMATTYPE *param = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
port->mmal->format->encoding = mmalil_omx_audio_coding_to_encoding(param->eEncoding);
|
|
port->mmal->format->encoding_variant = 0;
|
|
if (mmal_port_format_commit(port->mmal) != MMAL_SUCCESS)
|
|
LOG_ERROR("OMX_IndexParamAudioPortFormat commit failed");
|
|
return OMX_ErrorNone;
|
|
}
|
|
break;
|
|
case OMX_IndexParamVideoPortFormat:
|
|
{
|
|
OMX_VIDEO_PARAM_PORTFORMATTYPE *param = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pParam;
|
|
PARAM_GET_PORT(port, component, param->nPortIndex);
|
|
if (param->eCompressionFormat != OMX_VIDEO_CodingUnused)
|
|
port->mmal->format->encoding = mmalil_omx_video_coding_to_encoding(param->eCompressionFormat);
|
|
else
|
|
port->mmal->format->encoding = mmalil_omx_color_format_to_encoding(param->eColorFormat);
|
|
port->mmal->format->encoding_variant = 0;
|
|
|
|
if (mmal_port_format_commit(port->mmal) != MMAL_SUCCESS)
|
|
LOG_ERROR("OMX_IndexParamAudioPortFormat commit failed");
|
|
return OMX_ErrorNone;
|
|
}
|
|
break;
|
|
case OMX_IndexParamImagePortFormat:
|
|
case OMX_IndexParamOtherPortFormat:
|
|
break;
|
|
case OMX_IndexParamStandardComponentRole:
|
|
{
|
|
OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam;
|
|
return mmalomx_role_set(component, (const char *)param->cRole);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
OMX_ERRORTYPE status = mmalomx_parameter_set(component, nParamIndex, pParam);
|
|
|
|
/* Keep track of the zero-copy state */
|
|
if (status == OMX_ErrorNone && nParamIndex == OMX_IndexParamBrcmZeroCopy)
|
|
{
|
|
PARAM_GET_PORT(port, component, ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->nPortIndex);
|
|
port->zero_copy = ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->bEnabled;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentGetConfig(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_INDEXTYPE nParamIndex,
|
|
OMX_PTR pParam)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
|
|
LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
|
|
hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pParam)
|
|
return OMX_ErrorBadParameter;
|
|
if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
return mmalomx_parameter_get(component, nParamIndex, pParam);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentSetConfig(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_INDEXTYPE nParamIndex,
|
|
OMX_PTR pParam)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
|
|
LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
|
|
hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pParam)
|
|
return OMX_ErrorBadParameter;
|
|
if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
return mmalomx_parameter_set(component, nParamIndex, pParam);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentGetExtensionIndex(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_STRING cParameterName,
|
|
OMX_INDEXTYPE* pIndexType)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
|
|
LOG_TRACE("hComponent %p, cParameterName %s, pIndexType %p",
|
|
hComponent, cParameterName, pIndexType);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
return mmalomx_parameter_extension_index_get(cParameterName, pIndexType);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentGetState(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_STATETYPE* pState)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMAL_PARAM_UNUSED(component);
|
|
|
|
LOG_TRACE("hComponent %p, pState, %p", hComponent, pState);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pState)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
*pState = component->state;
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentTunnelRequest(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_U32 nPort,
|
|
OMX_HANDLETYPE hTunneledComp,
|
|
OMX_U32 nTunneledPort,
|
|
OMX_TUNNELSETUPTYPE* pTunnelSetup)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMAL_PARAM_UNUSED(component);
|
|
|
|
LOG_TRACE("hComponent %p, nPort %i, hTunneledComp %p, nTunneledPort %i, "
|
|
"pTunnelSetup %p", hComponent, (int)nPort, hTunneledComp,
|
|
(int)nTunneledPort, pTunnelSetup);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
if (nPort >= component->ports_num)
|
|
return OMX_ErrorBadPortIndex;
|
|
if (component->state != OMX_StateLoaded && component->ports[nPort].enabled)
|
|
return OMX_ErrorIncorrectStateOperation;
|
|
if (hTunneledComp && !pTunnelSetup)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
if (!hTunneledComp)
|
|
return OMX_ErrorNone;
|
|
return OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentUseBuffer(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_BUFFERHEADERTYPE** ppBuffer,
|
|
OMX_U32 nPortIndex,
|
|
OMX_PTR pAppPrivate,
|
|
OMX_U32 nSizeBytes,
|
|
OMX_U8* pBuffer)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
OMX_ERRORTYPE status = OMX_ErrorNone;
|
|
MMAL_BOOL_T populated = MMAL_FALSE;
|
|
OMX_BUFFERHEADERTYPE *buffer;
|
|
MMALOMX_PORT_T *port;
|
|
|
|
LOG_TRACE("hComponent %p, ppBufferHdr %p, nPortIndex %i, pAppPrivate %p,"
|
|
" nSizeBytes %i, pBuffer %p", hComponent, ppBuffer,
|
|
(int)nPortIndex, pAppPrivate, (int)nSizeBytes, pBuffer);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!ppBuffer)
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
if (nPortIndex >= component->ports_num)
|
|
return OMX_ErrorBadPortIndex;
|
|
|
|
/* Make sure any previous command has been processed.
|
|
* This is not ideal since done inline but in practice the actual
|
|
* notification to the client will not be done as part of this call. */
|
|
mmalomx_commands_actions_check(component);
|
|
|
|
port = &component->ports[nPortIndex];
|
|
MMALOMX_LOCK_PORT(component, port);
|
|
|
|
if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED))
|
|
status = OMX_ErrorIncorrectStateOperation;
|
|
if (port->populated)
|
|
status = OMX_ErrorIncorrectStateOperation;
|
|
if (status != OMX_ErrorNone)
|
|
goto error;
|
|
|
|
/* Check for mismatched calls to UseBuffer/AllocateBuffer */
|
|
if (port->buffers && port->buffers_allocated)
|
|
{
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
|
|
/* Sanity check buffer size */
|
|
if (nSizeBytes < port->mmal->buffer_size_min)
|
|
{
|
|
LOG_ERROR("buffer size too small (%i/%i)", (int)nSizeBytes,
|
|
(int)port->mmal->buffer_size_min);
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
if (!port->buffers)
|
|
port->mmal->buffer_size = nSizeBytes;
|
|
if (nSizeBytes > port->mmal->buffer_size)
|
|
{
|
|
LOG_ERROR("buffer size too big (%i/%i)", (int)nSizeBytes,
|
|
(int)port->mmal->buffer_size);
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
|
|
buffer = calloc( 1, sizeof(*buffer) );
|
|
if (!buffer)
|
|
{
|
|
status = OMX_ErrorInsufficientResources;
|
|
goto error;
|
|
}
|
|
|
|
buffer->nSize = sizeof(*buffer);
|
|
buffer->nVersion.nVersion = OMX_VERSION;
|
|
buffer->nAllocLen = nSizeBytes;
|
|
buffer->pBuffer = pBuffer;
|
|
buffer->pAppPrivate = pAppPrivate;
|
|
if (port->direction == OMX_DirInput)
|
|
{
|
|
buffer->nInputPortIndex = nPortIndex;
|
|
buffer->pOutputPortPrivate = pAppPrivate;
|
|
}
|
|
else
|
|
{
|
|
buffer->nOutputPortIndex = nPortIndex;
|
|
buffer->pInputPortPrivate = pAppPrivate;
|
|
}
|
|
|
|
*ppBuffer = buffer;
|
|
port->buffers++;
|
|
port->buffers_allocated = MMAL_FALSE;
|
|
port->populated = populated = port->buffers == port->mmal->buffer_num;
|
|
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
|
|
LOG_DEBUG("allocated %i/%i buffers", port->buffers, port->mmal->buffer_num);
|
|
|
|
if (populated)
|
|
mmalomx_commands_actions_signal(component);
|
|
|
|
return OMX_ErrorNone;
|
|
|
|
error:
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentAllocateBuffer(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_BUFFERHEADERTYPE** ppBuffer,
|
|
OMX_U32 nPortIndex,
|
|
OMX_PTR pAppPrivate,
|
|
OMX_U32 nSizeBytes)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
OMX_ERRORTYPE status = OMX_ErrorNone;
|
|
MMAL_BOOL_T populated = MMAL_FALSE;
|
|
OMX_BUFFERHEADERTYPE *buffer = 0;
|
|
MMALOMX_PORT_T *port;
|
|
|
|
LOG_TRACE("hComponent %p, ppBuffer %p, nPortIndex %i, pAppPrivate %p, "
|
|
"nSizeBytes %i", hComponent, ppBuffer, (int)nPortIndex,
|
|
pAppPrivate, (int)nSizeBytes);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!ppBuffer)
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
if (nPortIndex >= component->ports_num)
|
|
return OMX_ErrorBadPortIndex;
|
|
|
|
/* Make sure any previous command has been processed.
|
|
* This is not ideal since done inline but in practice the actual
|
|
* notification to the client will not be done as part of this call. */
|
|
mmalomx_commands_actions_check(component);
|
|
|
|
port = &component->ports[nPortIndex];
|
|
MMALOMX_LOCK_PORT(component, port);
|
|
|
|
if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED))
|
|
status = OMX_ErrorIncorrectStateOperation;
|
|
if (port->populated)
|
|
status = OMX_ErrorIncorrectStateOperation;
|
|
if (status != OMX_ErrorNone)
|
|
goto error;
|
|
|
|
/* Check for mismatched calls to UseBuffer/AllocateBuffer */
|
|
if (!status && port->buffers && !port->buffers_allocated)
|
|
{
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
|
|
/* Sanity check buffer size */
|
|
if (nSizeBytes < port->mmal->buffer_size_min)
|
|
{
|
|
LOG_ERROR("buffer size too small (%i/%i)", (int)nSizeBytes,
|
|
(int)port->mmal->buffer_size_min);
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
if (!port->buffers)
|
|
port->mmal->buffer_size = nSizeBytes;
|
|
if (nSizeBytes > port->mmal->buffer_size)
|
|
{
|
|
LOG_ERROR("buffer size too big (%i/%i)", (int)nSizeBytes,
|
|
(int)port->mmal->buffer_size);
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
|
|
/* Set the zero-copy mode */
|
|
if (!port->buffers_allocated && nSizeBytes > MMALOMX_ZERO_COPY_THRESHOLD &&
|
|
!port->zero_copy)
|
|
{
|
|
MMAL_STATUS_T status = mmal_port_parameter_set_boolean(port->mmal,
|
|
MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
|
|
if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
|
|
LOG_ERROR("failed to enable zero copy on %s", port->mmal->name);
|
|
}
|
|
|
|
buffer = calloc( 1, sizeof(*buffer) );
|
|
if (!buffer)
|
|
{
|
|
status = OMX_ErrorInsufficientResources;
|
|
goto error;
|
|
}
|
|
|
|
buffer->pBuffer = mmal_port_payload_alloc(port->mmal, nSizeBytes);
|
|
if (!buffer->pBuffer)
|
|
{
|
|
status = OMX_ErrorInsufficientResources;
|
|
goto error;
|
|
}
|
|
|
|
buffer->nSize = sizeof(*buffer);
|
|
buffer->nVersion.nVersion = OMX_VERSION;
|
|
buffer->nAllocLen = nSizeBytes;
|
|
buffer->pAppPrivate = pAppPrivate;
|
|
if (port->direction == OMX_DirInput)
|
|
{
|
|
buffer->nInputPortIndex = nPortIndex;
|
|
buffer->pOutputPortPrivate = pAppPrivate;
|
|
}
|
|
else
|
|
{
|
|
buffer->nOutputPortIndex = nPortIndex;
|
|
buffer->pInputPortPrivate = pAppPrivate;
|
|
}
|
|
/* Keep an unmodified copy of the pointer for when we come to free it */
|
|
buffer->pPlatformPrivate = (OMX_PTR)buffer->pBuffer;
|
|
|
|
*ppBuffer = buffer;
|
|
port->buffers++;
|
|
port->buffers_allocated = MMAL_TRUE;
|
|
port->populated = populated = port->buffers == port->mmal->buffer_num;
|
|
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
|
|
LOG_DEBUG("allocated %i/%i buffers", port->buffers, port->mmal->buffer_num);
|
|
|
|
if (populated)
|
|
mmalomx_commands_actions_signal(component);
|
|
|
|
return OMX_ErrorNone;
|
|
|
|
error:
|
|
if (!port->buffers_allocated && !port->zero_copy)
|
|
mmal_port_parameter_set_boolean(port->mmal, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE);
|
|
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
LOG_ERROR("failed to allocate %i/%i buffers", port->buffers, port->mmal->buffer_num);
|
|
if (buffer)
|
|
free(buffer);
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentFreeBuffer(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_U32 nPortIndex,
|
|
OMX_BUFFERHEADERTYPE* pBuffer)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
OMX_ERRORTYPE status = OMX_ErrorNone;
|
|
MMAL_BOOL_T unpopulated, allocated;
|
|
MMALOMX_PORT_T *port;
|
|
unsigned int buffers;
|
|
|
|
LOG_TRACE("hComponent %p, nPortIndex %i, pBuffer %p",
|
|
hComponent, (int)nPortIndex, pBuffer);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pBuffer)
|
|
return OMX_ErrorBadParameter;
|
|
if (nPortIndex >= component->ports_num)
|
|
return OMX_ErrorBadPortIndex;
|
|
|
|
/* Make sure any previous command has been processed.
|
|
* This is not ideal since done inline but in practice the actual
|
|
* notification to the client will not be done as part of this call. */
|
|
mmalomx_commands_actions_check(component);
|
|
|
|
port = &component->ports[nPortIndex];
|
|
MMALOMX_LOCK_PORT(component, port);
|
|
|
|
if (!port->buffers)
|
|
{
|
|
status = OMX_ErrorBadParameter;
|
|
goto error;
|
|
}
|
|
|
|
buffers = --port->buffers;
|
|
port->populated = MMAL_FALSE;
|
|
unpopulated = !(port->actions & MMALOMX_ACTION_CHECK_DEALLOCATED);
|
|
allocated = port->buffers_allocated;
|
|
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
|
|
if (allocated) /* Free the unmodified pointer */
|
|
mmal_port_payload_free(port->mmal, pBuffer->pPlatformPrivate);
|
|
free(pBuffer);
|
|
|
|
if (allocated && !port->zero_copy) /* Reset the zero-copy status */
|
|
mmal_port_parameter_set_boolean(port->mmal, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE);
|
|
|
|
LOG_DEBUG("freed %i/%i buffers", port->mmal->buffer_num - port->buffers, port->mmal->buffer_num);
|
|
|
|
if (unpopulated)
|
|
mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorPortUnpopulated, 0, NULL);
|
|
|
|
if (!buffers)
|
|
mmalomx_commands_actions_signal(component);
|
|
|
|
return OMX_ErrorNone;
|
|
|
|
error:
|
|
MMALOMX_UNLOCK_PORT(component, port);
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentEmptyThisBuffer(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_BUFFERHEADERTYPE* pBuffer)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
|
|
if (ENABLE_MMAL_EXTRA_LOGGING)
|
|
LOG_TRACE("hComponent %p, port %i, pBuffer %p", hComponent,
|
|
pBuffer ? (int)pBuffer->nInputPortIndex : -1, pBuffer);
|
|
|
|
return mmalomx_buffer_send(component, pBuffer, OMX_DirInput);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentFillThisBuffer(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_BUFFERHEADERTYPE* pBuffer)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
|
|
if (ENABLE_MMAL_EXTRA_LOGGING)
|
|
LOG_TRACE("hComponent %p, port %i, pBuffer %p", hComponent,
|
|
pBuffer ? (int)pBuffer->nOutputPortIndex : -1, pBuffer);
|
|
|
|
return mmalomx_buffer_send(component, pBuffer, OMX_DirOutput);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentSetCallbacks(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_CALLBACKTYPE* pCallbacks,
|
|
OMX_PTR pAppData)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMAL_PARAM_UNUSED(component);
|
|
|
|
LOG_TRACE("hComponent %p, pCallbacks %p, pAppData %p",
|
|
hComponent, pCallbacks, pAppData);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (!pCallbacks)
|
|
return OMX_ErrorBadParameter;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
if (component->state != OMX_StateLoaded)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
component->callbacks = *pCallbacks;
|
|
component->callbacks_data = pAppData;
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentDeInit(
|
|
OMX_HANDLETYPE hComponent)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMAL_PARAM_UNUSED(component);
|
|
|
|
LOG_TRACE("hComponent %p", hComponent);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentUseEGLImage(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_BUFFERHEADERTYPE** ppBufferHdr,
|
|
OMX_U32 nPortIndex,
|
|
OMX_PTR pAppPrivate,
|
|
void* eglImage)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMAL_PARAM_UNUSED(component);
|
|
|
|
LOG_TRACE("hComponent %p, ppBufferHdr %p, nPortIndex %i, pAppPrivate %p,"
|
|
" eglImage %p", hComponent, ppBufferHdr, (int)nPortIndex,
|
|
pAppPrivate, eglImage);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
return OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static OMX_ERRORTYPE mmalomx_ComponentRoleEnum(
|
|
OMX_HANDLETYPE hComponent,
|
|
OMX_U8 *cRole,
|
|
OMX_U32 nIndex)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
MMALOMX_ROLE_T role;
|
|
|
|
LOG_TRACE("hComponent %p, cRole %p, nIndex %i",
|
|
hComponent, cRole, (int)nIndex);
|
|
|
|
/* Sanity checks */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
if (component->state == OMX_StateInvalid)
|
|
return OMX_ErrorInvalidState;
|
|
|
|
role = mmalomx_registry_component_roles(component->registry_id, nIndex);
|
|
if (!role)
|
|
return OMX_ErrorNoMore;
|
|
if (!mmalomx_role_to_name(role))
|
|
return OMX_ErrorNoMore;
|
|
|
|
strcpy((char *)cRole, mmalomx_role_to_name(role));
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Init)(void)
|
|
{
|
|
mmalomx_logging_init();
|
|
LOG_TRACE("Init");
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Deinit)(void)
|
|
{
|
|
LOG_TRACE("Deinit");
|
|
mmalomx_logging_deinit();
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_ComponentNameEnum)(
|
|
OMX_STRING cComponentName,
|
|
OMX_U32 nNameLength,
|
|
OMX_U32 nIndex)
|
|
{
|
|
const char *prefix, *name;
|
|
name = mmalomx_registry_component_name(nIndex, &prefix);
|
|
|
|
LOG_TRACE("cComponentName %p, nNameLength %i, nIndex %i",
|
|
cComponentName, (int)nNameLength, (int)nIndex);
|
|
|
|
/* Sanity checking */
|
|
if (!cComponentName)
|
|
return OMX_ErrorBadParameter;
|
|
if (!name)
|
|
return OMX_ErrorNoMore;
|
|
if (nNameLength <= strlen(name) + strlen(prefix))
|
|
return OMX_ErrorBadParameter;
|
|
|
|
sprintf(cComponentName, "%s%s", prefix, name);
|
|
LOG_TRACE("cComponentName: %s", cComponentName);
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static void mmalomx_buffer_cb_control(
|
|
MMAL_PORT_T *port,
|
|
MMAL_BUFFER_HEADER_T *buffer)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)port->userdata;
|
|
|
|
LOG_DEBUG("received event %4.4s on port %s", (char *)&buffer->cmd, port->name);
|
|
|
|
if (buffer->cmd == MMAL_EVENT_ERROR)
|
|
{
|
|
mmalomx_callback_event_handler(component, OMX_EventError,
|
|
mmalil_error_to_omx(*(MMAL_STATUS_T *)buffer->data), 0, NULL);
|
|
}
|
|
else if (buffer->cmd == MMAL_EVENT_EOS &&
|
|
buffer->length == sizeof(MMAL_EVENT_END_OF_STREAM_T))
|
|
{
|
|
MMAL_EVENT_END_OF_STREAM_T *eos = (MMAL_EVENT_END_OF_STREAM_T *)buffer->data;
|
|
if (eos->port_index < port->component->input_num)
|
|
{
|
|
MMALOMX_PORT_T *omx_port = (MMALOMX_PORT_T *)
|
|
port->component->input[eos->port_index]->userdata;
|
|
LOG_DEBUG("send EOS on %i", omx_port->index);
|
|
mmalomx_callback_event_handler(component, OMX_EventBufferFlag,
|
|
omx_port->index, OMX_BUFFERFLAG_EOS, NULL);
|
|
}
|
|
}
|
|
|
|
mmal_buffer_header_release(buffer);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_GetHandle)(
|
|
OMX_HANDLETYPE* pHandle,
|
|
OMX_STRING cComponentName,
|
|
OMX_PTR pAppData,
|
|
OMX_CALLBACKTYPE* pCallBacks)
|
|
{
|
|
OMX_ERRORTYPE status = OMX_ErrorInsufficientResources;
|
|
MMALOMX_COMPONENT_T *component = 0;
|
|
MMAL_COMPONENT_T *mmal_component = 0;
|
|
MMAL_STATUS_T mmal_status;
|
|
unsigned int i, ports_num;
|
|
OMX_PORTDOMAINTYPE domain;
|
|
const char *mmal_name;
|
|
int registry_id;
|
|
|
|
LOG_TRACE("pHandle %p, cComponentName %s, pAppData %p, pCallBacks %p",
|
|
pHandle, cComponentName, pAppData, pCallBacks);
|
|
|
|
/* Sanity check params */
|
|
if (!pHandle || !cComponentName || !pCallBacks)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
/* Find component */
|
|
registry_id = mmalomx_registry_find_component(cComponentName);
|
|
if (registry_id < 0)
|
|
return OMX_ErrorComponentNotFound;
|
|
|
|
/* create and setup component */
|
|
mmal_name = mmalomx_registry_component_mmal(registry_id);
|
|
mmal_status = mmal_component_create(mmal_name, &mmal_component);
|
|
if (mmal_status != MMAL_SUCCESS)
|
|
{
|
|
LOG_ERROR("could not create mmal component %s", mmal_name);
|
|
return mmalil_error_to_omx(mmal_status);
|
|
}
|
|
mmal_status = mmal_port_enable(mmal_component->control, mmalomx_buffer_cb_control);
|
|
if (mmal_status != MMAL_SUCCESS)
|
|
{
|
|
LOG_ERROR("could not enable %s", mmal_component->control->name);
|
|
mmal_component_destroy(mmal_component);
|
|
return mmalil_error_to_omx(mmal_status);
|
|
}
|
|
|
|
ports_num = mmal_component->port_num - 1;
|
|
|
|
component = calloc(1, sizeof(*component) + ports_num * sizeof(*component->ports));
|
|
if (!component)
|
|
{
|
|
mmal_component_destroy(mmal_component);
|
|
return OMX_ErrorInsufficientResources;
|
|
}
|
|
|
|
if (vcos_mutex_create(&component->lock, "mmalomx lock") != VCOS_SUCCESS)
|
|
{
|
|
mmal_component_destroy(mmal_component);
|
|
free(component);
|
|
return OMX_ErrorInsufficientResources;
|
|
}
|
|
if (vcos_mutex_create(&component->lock_port, "mmalomx port lock") != VCOS_SUCCESS)
|
|
{
|
|
vcos_mutex_delete(&component->lock);
|
|
mmal_component_destroy(mmal_component);
|
|
free(component);
|
|
return OMX_ErrorInsufficientResources;
|
|
}
|
|
|
|
component->omx.nSize = sizeof(component->omx);
|
|
component->omx.nVersion.nVersion = OMX_VERSION;
|
|
component->mmal = mmal_component;
|
|
component->state = OMX_StateLoaded;
|
|
component->callbacks = *pCallBacks;
|
|
component->callbacks_data = pAppData;
|
|
component->ports = (MMALOMX_PORT_T *)&component[1];
|
|
component->registry_id = registry_id;
|
|
component->name = mmalomx_registry_component_name(registry_id, 0);
|
|
component->role = mmalomx_registry_component_roles(registry_id, 0);
|
|
|
|
// FIXME: make this configurable
|
|
component->cmd_thread_used = MMAL_TRUE;
|
|
|
|
/* Sort the ports into separate OMX domains */
|
|
for (domain = OMX_PortDomainAudio; domain < OMX_PortDomainOther; domain++)
|
|
{
|
|
for (i = 1; i < mmal_component->port_num; i++)
|
|
{
|
|
if (domain == mmalil_es_type_to_omx_domain(mmal_component->port[i]->format->type))
|
|
{
|
|
component->ports[component->ports_num].mmal = mmal_component->port[i];
|
|
component->ports_domain_num[domain]++;
|
|
component->ports_num++;
|
|
}
|
|
}
|
|
}
|
|
LOG_DEBUG("ports: %i audio, %i video",
|
|
component->ports_domain_num[OMX_PortDomainAudio],
|
|
component->ports_domain_num[OMX_PortDomainVideo]);
|
|
|
|
/* Setup our ports */
|
|
for (i = 0; i < component->ports_num; i++)
|
|
{
|
|
component->ports[i].component = component;
|
|
if (component->ports[i].mmal->type == MMAL_PORT_TYPE_OUTPUT)
|
|
component->ports[i].direction = OMX_DirOutput;
|
|
component->ports[i].index = i;
|
|
component->ports[i].enabled = MMAL_TRUE;
|
|
component->ports[i].pool =
|
|
mmal_port_pool_create(component->ports[i].mmal, 0, 0);
|
|
if (!component->ports[i].pool)
|
|
goto error;
|
|
component->ports[i].mmal->userdata = (struct MMAL_PORT_USERDATA_T *)&component->ports[i];
|
|
}
|
|
mmal_component->control->userdata = (struct MMAL_PORT_USERDATA_T *)component;
|
|
|
|
/* Create our OMX commands queue */
|
|
component->cmd_queue = mmal_queue_create();
|
|
if (!component->cmd_queue)
|
|
goto error;
|
|
component->cmd_pool = mmal_pool_create(MAX_CMD_BUFFERS, 0);
|
|
if (!component->cmd_pool)
|
|
goto error;
|
|
|
|
if (component->cmd_thread_used &&
|
|
vcos_semaphore_create(&component->cmd_sema,
|
|
"mmalomx sema", 0) != VCOS_SUCCESS)
|
|
{
|
|
component->cmd_thread_used = MMAL_FALSE;
|
|
goto error;
|
|
}
|
|
|
|
if (component->cmd_thread_used &&
|
|
vcos_thread_create(&component->cmd_thread, component->name, NULL,
|
|
mmalomx_cmd_thread_func, component) != VCOS_SUCCESS)
|
|
{
|
|
vcos_semaphore_delete(&component->cmd_sema);
|
|
component->cmd_thread_used = MMAL_FALSE;
|
|
goto error;
|
|
}
|
|
|
|
/* Set the function pointer for the component's interface */
|
|
component->omx.GetComponentVersion = mmalomx_ComponentGetComponentVersion;
|
|
component->omx.SendCommand = mmalomx_ComponentSendCommand;
|
|
component->omx.GetParameter = mmalomx_ComponentGetParameter;
|
|
component->omx.SetParameter = mmalomx_ComponentSetParameter;
|
|
component->omx.GetConfig = mmalomx_ComponentGetConfig;
|
|
component->omx.SetConfig = mmalomx_ComponentSetConfig;
|
|
component->omx.GetExtensionIndex = mmalomx_ComponentGetExtensionIndex;
|
|
component->omx.GetState = mmalomx_ComponentGetState;
|
|
component->omx.ComponentTunnelRequest = mmalomx_ComponentTunnelRequest;
|
|
component->omx.UseBuffer = mmalomx_ComponentUseBuffer;
|
|
component->omx.AllocateBuffer = mmalomx_ComponentAllocateBuffer;
|
|
component->omx.FreeBuffer = mmalomx_ComponentFreeBuffer;
|
|
component->omx.EmptyThisBuffer = mmalomx_ComponentEmptyThisBuffer;
|
|
component->omx.FillThisBuffer = mmalomx_ComponentFillThisBuffer;
|
|
component->omx.SetCallbacks = mmalomx_ComponentSetCallbacks;
|
|
component->omx.ComponentDeInit = mmalomx_ComponentDeInit;
|
|
component->omx.UseEGLImage = mmalomx_ComponentUseEGLImage;
|
|
component->omx.ComponentRoleEnum = mmalomx_ComponentRoleEnum;
|
|
*pHandle = (OMX_HANDLETYPE)&component->omx;
|
|
|
|
return OMX_ErrorNone;
|
|
|
|
error:
|
|
MMALOMX_IMPORT(OMX_FreeHandle)((OMX_HANDLETYPE)&component->omx);
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_FreeHandle)(
|
|
OMX_HANDLETYPE hComponent)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
|
OMX_ERRORTYPE status;
|
|
unsigned int i;
|
|
|
|
LOG_TRACE("hComponent %p", hComponent);
|
|
|
|
/* Sanity check */
|
|
if (!hComponent)
|
|
return OMX_ErrorInvalidComponent;
|
|
|
|
if (component->omx.ComponentDeInit)
|
|
{
|
|
status = component->omx.ComponentDeInit(hComponent);
|
|
if (status != OMX_ErrorNone)
|
|
{
|
|
LOG_ERROR("ComponentDeInit failed");
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (component->cmd_thread_used)
|
|
{
|
|
component->cmd_thread_used = MMAL_FALSE;
|
|
vcos_semaphore_post(&component->cmd_sema);
|
|
vcos_thread_join(&component->cmd_thread, NULL);
|
|
}
|
|
|
|
mmal_component_destroy(component->mmal);
|
|
for (i = 0; i < component->ports_num; i++)
|
|
if (component->ports[i].pool)
|
|
mmal_pool_destroy(component->ports[i].pool);
|
|
|
|
if (component->cmd_pool)
|
|
mmal_pool_destroy(component->cmd_pool);
|
|
if (component->cmd_queue)
|
|
mmal_queue_destroy(component->cmd_queue);
|
|
if (component->cmd_thread_used)
|
|
vcos_semaphore_delete(&component->cmd_sema);
|
|
vcos_mutex_delete(&component->lock_port);
|
|
vcos_mutex_delete(&component->lock);
|
|
free(component);
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetRolesOfComponent)(
|
|
OMX_STRING compName,
|
|
OMX_U32 *pNumRoles,
|
|
OMX_U8 **roles)
|
|
{
|
|
OMX_U32 i, num_roles;
|
|
MMALOMX_ROLE_T role;
|
|
int registry_id;
|
|
|
|
LOG_TRACE("compName %s, pNumRoles %p, roles %p", compName, pNumRoles, roles);
|
|
|
|
/* Sanity checks */
|
|
if (!compName || !pNumRoles)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
if (!roles || *pNumRoles > MMALOMX_MAX_ROLES)
|
|
num_roles = MMALOMX_MAX_ROLES;
|
|
else
|
|
num_roles = *pNumRoles;
|
|
*pNumRoles = 0;
|
|
|
|
/* Find component */
|
|
registry_id = mmalomx_registry_find_component(compName);
|
|
if (registry_id < 0)
|
|
return OMX_ErrorComponentNotFound;
|
|
|
|
/* Enumerate Roles */
|
|
for (i = 0; i < num_roles; i++)
|
|
{
|
|
role = mmalomx_registry_component_roles(registry_id, i);
|
|
if (!role || !mmalomx_role_to_name(role))
|
|
break;
|
|
|
|
if(roles)
|
|
{
|
|
strncpy((char *)roles[i], mmalomx_role_to_name(role), OMX_MAX_STRINGNAME_SIZE);
|
|
LOG_DEBUG("found role: %s", roles[i]);
|
|
}
|
|
}
|
|
LOG_DEBUG("found %i roles", (int)i);
|
|
*pNumRoles = i;
|
|
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetComponentsOfRole)(
|
|
OMX_STRING role,
|
|
OMX_U32 *pNumComps,
|
|
OMX_U8 **compNames)
|
|
{
|
|
OMX_ERRORTYPE status;
|
|
OMX_HANDLETYPE handle;
|
|
OMX_COMPONENTTYPE *comp;
|
|
OMX_U8 name[OMX_MAX_STRINGNAME_SIZE], compRole[OMX_MAX_STRINGNAME_SIZE];
|
|
OMX_U32 nNameLength = OMX_MAX_STRINGNAME_SIZE, nIndex = 0;
|
|
OMX_U32 nRoles, nIndexRoles, nComps = 0;
|
|
OMX_CALLBACKTYPE callbacks = {0,0,0};
|
|
|
|
LOG_TRACE("role %s, pNumComps %p, compNames %p", role, pNumComps, compNames);
|
|
|
|
/* Sanity checks */
|
|
if (!role || !pNumComps)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
/* Enumerates components */
|
|
while ((status = OMX_ComponentNameEnum((OMX_STRING)name, nNameLength,
|
|
nIndex++)) == OMX_ErrorNone)
|
|
{
|
|
/* Find component */
|
|
status = MMALOMX_IMPORT(OMX_GetHandle)(&handle, (OMX_STRING)name, 0, &callbacks);
|
|
if(status != OMX_ErrorNone) continue;
|
|
comp = (OMX_COMPONENTTYPE *)handle;
|
|
|
|
/* Enumerate Roles */
|
|
status = MMALOMX_IMPORT(OMX_GetRolesOfComponent)((OMX_STRING)name, &nRoles, 0);
|
|
if(status != OMX_ErrorNone) continue;
|
|
|
|
for (nIndexRoles = 0; nIndexRoles < nRoles; nIndexRoles++)
|
|
{
|
|
status = comp->ComponentRoleEnum(handle, compRole, nIndexRoles);
|
|
if(status != OMX_ErrorNone) break;
|
|
|
|
if(!strncmp((char *)role, (char *)compRole, OMX_MAX_STRINGNAME_SIZE))
|
|
{
|
|
/* Found one */
|
|
nComps++;
|
|
|
|
if(!compNames) break;
|
|
|
|
/* Check if enough space was provided for all the component names */
|
|
if(nComps > *pNumComps) return OMX_ErrorBadParameter;
|
|
|
|
strncpy((char *)compNames[nComps-1], (char *)name, OMX_MAX_STRINGNAME_SIZE);
|
|
|
|
LOG_DEBUG("found component: %s", name);
|
|
}
|
|
}
|
|
|
|
MMALOMX_IMPORT(OMX_FreeHandle)(handle);
|
|
}
|
|
LOG_DEBUG("found %i components", (int)nComps);
|
|
*pNumComps = nComps;
|
|
|
|
return OMX_ErrorNone;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_SetupTunnel)(
|
|
OMX_HANDLETYPE hOutput,
|
|
OMX_U32 nPortOutput,
|
|
OMX_HANDLETYPE hInput,
|
|
OMX_U32 nPortInput)
|
|
{
|
|
OMX_TUNNELSETUPTYPE tunnel_setup = {0, OMX_BufferSupplyUnspecified};
|
|
OMX_ERRORTYPE status = OMX_ErrorNone;
|
|
|
|
LOG_TRACE("hOutput %p, nPortOutput %d, hInput %p, nPortInput %d",
|
|
hOutput, (int)nPortOutput, hInput, (int)nPortInput);
|
|
|
|
/* Sanity checks */
|
|
if (!hOutput && !hInput)
|
|
return OMX_ErrorBadParameter;
|
|
|
|
if (hOutput)
|
|
{
|
|
status = ((OMX_COMPONENTTYPE *)hOutput)->ComponentTunnelRequest(
|
|
hOutput, nPortOutput, hInput, nPortInput, &tunnel_setup);
|
|
if (status != OMX_ErrorNone)
|
|
LOG_DEBUG("OMX_SetupTunnel failed on output port (%i)", status);
|
|
}
|
|
|
|
if (status == OMX_ErrorNone && hInput)
|
|
{
|
|
status = ((OMX_COMPONENTTYPE *)hInput)->ComponentTunnelRequest(
|
|
hInput, nPortInput, hOutput, nPortOutput, &tunnel_setup);
|
|
if (status != OMX_ErrorNone)
|
|
{
|
|
LOG_DEBUG("OMX_SetupTunnel failed on input port (%i)", status);
|
|
/* Cancel request on output port */
|
|
if (hOutput)
|
|
((OMX_COMPONENTTYPE *)hOutput)->ComponentTunnelRequest(
|
|
hOutput, nPortOutput, NULL, 0, NULL);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetContentPipe)(
|
|
OMX_HANDLETYPE *hPipe,
|
|
OMX_STRING szURI)
|
|
{
|
|
MMAL_PARAM_UNUSED(hPipe);
|
|
MMAL_PARAM_UNUSED(szURI);
|
|
|
|
LOG_TRACE("hPipe %p, szURI %s", hPipe, szURI);
|
|
|
|
return OMX_ErrorNotImplemented;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Processing thread
|
|
*****************************************************************************/
|
|
static void *mmalomx_cmd_thread_func(void *arg)
|
|
{
|
|
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)arg;
|
|
VCOS_STATUS_T status;
|
|
|
|
while (component->cmd_thread_used)
|
|
{
|
|
status = vcos_semaphore_wait(&component->cmd_sema);
|
|
if (status == VCOS_EAGAIN)
|
|
continue;
|
|
mmalomx_commands_actions_check(component);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|