Änderungen Gruppe 30_10_2022 V2

This commit is contained in:
2022-10-30 20:01:47 +01:00
parent 269f807b31
commit 2517e52e59
239 changed files with 54983 additions and 9 deletions
@@ -0,0 +1,28 @@
add_library (mmal_util ${LIBRARY_TYPE}
mmal_il.c
mmal_util.c
mmal_connection.c
mmal_graph.c
mmal_list.c
mmal_param_convert.c
mmal_util_params.c
mmal_component_wrapper.c
mmal_util_rational.c
)
target_link_libraries (mmal_util vcos)
install(TARGETS mmal_util DESTINATION lib)
install(FILES
mmal_component_wrapper.h
mmal_connection.h
mmal_default_components.h
mmal_graph.h
mmal_il.h
mmal_list.h
mmal_param_convert.h
mmal_util.h
mmal_util_params.h
mmal_util_rational.h
DESTINATION include/interface/mmal/util
)
@@ -0,0 +1,368 @@
/*
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 "mmal.h"
#include "util/mmal_util.h"
#include "util/mmal_component_wrapper.h"
#include "mmal_logging.h"
#include <stdio.h>
typedef struct
{
MMAL_WRAPPER_T wrapper; /**< Must be the first member! */
VCOS_SEMAPHORE_T sema;
} MMAL_WRAPPER_PRIVATE_T;
/** Callback from a control port. Error events will be received there. */
static void mmal_wrapper_control_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
LOG_TRACE("%s(%p),%p,%4.4s", port->name, port, buffer, (char *)&buffer->cmd);
if (buffer->cmd == MMAL_EVENT_ERROR)
{
private->wrapper.status = *(MMAL_STATUS_T *)buffer->data;
mmal_buffer_header_release(buffer);
vcos_semaphore_post(&private->sema);
if (private->wrapper.callback)
private->wrapper.callback(&private->wrapper);
return;
}
mmal_buffer_header_release(buffer);
}
/** Callback from an input port. Buffer is released. */
static void mmal_wrapper_bh_in_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_PARAM_UNUSED(port);
LOG_TRACE("(%s)%p,%p,%p,%i", port->name, port, buffer, buffer->data, (int)buffer->length);
/* We're done with the buffer, just recycle it */
mmal_buffer_header_release(buffer);
}
/** Callback from an output port. Buffer is queued for the next component. */
static void mmal_wrapper_bh_out_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
LOG_TRACE("(%s)%p,%p,%p,%i", port->name, port, buffer, buffer->data, (int)buffer->length);
/* Queue the buffer produced by the output port */
mmal_queue_put(private->wrapper.output_queue[port->index], buffer);
vcos_semaphore_post(&private->sema);
if (private->wrapper.callback)
private->wrapper.callback(&private->wrapper);
}
/** Callback from the pool. Buffer is available. */
static MMAL_BOOL_T mmal_wrapper_bh_release_cb(MMAL_POOL_T *pool, MMAL_BUFFER_HEADER_T *buffer,
void *userdata)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)userdata;
mmal_queue_put(pool->queue, buffer);
vcos_semaphore_post(&private->sema);
if (private->wrapper.callback)
private->wrapper.callback(&private->wrapper);
return 0;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_wrapper_destroy(MMAL_WRAPPER_T *wrapper)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)wrapper;
unsigned int i;
LOG_TRACE("%p, %s", wrapper, wrapper->component->name);
/* Cleanup resources */
mmal_component_destroy(wrapper->component);
for (i = 0; i < wrapper->input_num; i++)
{
if (wrapper->input_pool[i])
mmal_pool_destroy(wrapper->input_pool[i]);
}
for (i = 0; i < wrapper->output_num; i++)
{
if (wrapper->output_pool[i])
mmal_pool_destroy(wrapper->output_pool[i]);
if (wrapper->output_queue[i])
mmal_queue_destroy(wrapper->output_queue[i]);
}
vcos_semaphore_delete(&private->sema);
vcos_free(private);
return MMAL_SUCCESS;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_wrapper_create(MMAL_WRAPPER_T **ctx, const char *name)
{
MMAL_STATUS_T status;
MMAL_COMPONENT_T *component;
MMAL_WRAPPER_PRIVATE_T *private;
MMAL_WRAPPER_T *wrapper;
int64_t start_time;
unsigned int i, extra_size;
LOG_TRACE("wrapper %p, name %s", ctx, name);
/* Sanity checking */
if (!ctx || !name)
return MMAL_EINVAL;
start_time = vcos_getmicrosecs();
status = mmal_component_create(name, &component);
if (status != MMAL_SUCCESS)
return status;
extra_size = (component->input_num + component->output_num) * 2;
private = vcos_calloc(1, sizeof(*private) + extra_size, "mmal wrapper");
if (!private)
{
mmal_component_destroy(component);
return MMAL_ENOMEM;
}
if (vcos_semaphore_create(&private->sema, "mmal wrapper", 0) != VCOS_SUCCESS)
{
mmal_component_destroy(component);
vcos_free(private);
return MMAL_ENOMEM;
}
wrapper = &private->wrapper;
wrapper->component = component;
wrapper->control = component->control;
wrapper->input_num = component->input_num;
wrapper->input = component->input;
wrapper->output_num = component->output_num;
wrapper->output = component->output;
wrapper->input_pool = (MMAL_POOL_T **)&private[1];
wrapper->output_pool = (MMAL_POOL_T **)&wrapper->input_pool[component->input_num];
wrapper->output_queue = (MMAL_QUEUE_T **)&wrapper->output_pool[component->output_num];
/* Create our pools and queues */
for (i = 0; i < wrapper->input_num; i++)
{
wrapper->input_pool[i] = mmal_port_pool_create(wrapper->input[i], 0, 0);
if (!wrapper->input_pool[i])
goto error;
mmal_pool_callback_set(wrapper->input_pool[i], mmal_wrapper_bh_release_cb, (void *)wrapper);
wrapper->input[i]->userdata = (void *)wrapper;
}
for (i = 0; i < wrapper->output_num; i++)
{
wrapper->output_pool[i] = mmal_port_pool_create(wrapper->output[i], 0, 0);
wrapper->output_queue[i] = mmal_queue_create();
if (!wrapper->output_pool[i] || !wrapper->output_queue[i])
goto error;
mmal_pool_callback_set(wrapper->output_pool[i], mmal_wrapper_bh_release_cb, (void *)wrapper);
wrapper->output[i]->userdata = (void *)wrapper;
}
/* Setup control port */
wrapper->control->userdata = (void *)wrapper;
status = mmal_port_enable(wrapper->control, mmal_wrapper_control_cb);
if (status != MMAL_SUCCESS)
goto error;
wrapper->time_setup = vcos_getmicrosecs() - start_time;
*ctx = wrapper;
return MMAL_SUCCESS;
error:
mmal_wrapper_destroy(wrapper);
return status == MMAL_SUCCESS ? MMAL_ENOMEM : status;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_wrapper_port_enable(MMAL_PORT_T *port, uint32_t flags)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
MMAL_WRAPPER_T *wrapper = &private->wrapper;
int64_t start_time = vcos_getmicrosecs();
uint32_t buffer_size;
MMAL_STATUS_T status;
MMAL_POOL_T *pool;
LOG_TRACE("%p, %s", wrapper, port->name);
if (port->type != MMAL_PORT_TYPE_INPUT && port->type != MMAL_PORT_TYPE_OUTPUT)
return MMAL_EINVAL;
if (port->is_enabled)
return MMAL_SUCCESS;
pool = port->type == MMAL_PORT_TYPE_INPUT ?
wrapper->input_pool[port->index] : wrapper->output_pool[port->index];
buffer_size = (flags & MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE) ? port->buffer_size : 0;
/* FIXME: we don't support switching between shared and non-shared memory.
* We would need to save the flag and force a pool resize when switching. */
if (flags & MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY)
{
MMAL_PARAMETER_BOOLEAN_T param_zc =
{{MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T)}, 1};
status = mmal_port_parameter_set(port, &param_zc.hdr);
if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
{
LOG_ERROR("failed to set zero copy on %s", port->name);
return status;
}
}
/* Resize the pool */
status = mmal_pool_resize(pool, port->buffer_num, buffer_size);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("could not resize pool (%i/%i)", (int)port->buffer_num, (int)buffer_size);
return status;
}
/* Enable port. The callback specified here is the function which
* will be called when a buffer header comes back to the port. */
status = mmal_port_enable(port, port->type == MMAL_PORT_TYPE_INPUT ?
mmal_wrapper_bh_in_cb : mmal_wrapper_bh_out_cb);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("could not enable port");
return status;
}
wrapper->time_enable += vcos_getmicrosecs() - start_time;
return MMAL_SUCCESS;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_wrapper_port_disable(MMAL_PORT_T *port)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
MMAL_WRAPPER_T *wrapper = &private->wrapper;
int64_t start_time = vcos_getmicrosecs();
MMAL_STATUS_T status;
LOG_TRACE("%p, %s", wrapper, port->name);
if (port->type != MMAL_PORT_TYPE_INPUT && port->type != MMAL_PORT_TYPE_OUTPUT)
return MMAL_EINVAL;
if (!port->is_enabled)
return MMAL_SUCCESS;
/* Disable port */
status = mmal_port_disable(port);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("could not disable port");
return status;
}
/* Flush the queue */
if (port->type == MMAL_PORT_TYPE_OUTPUT)
{
MMAL_POOL_T *pool = wrapper->output_pool[port->index];
MMAL_QUEUE_T *queue = wrapper->output_queue[port->index];
MMAL_BUFFER_HEADER_T *buffer;
while ((buffer = mmal_queue_get(queue)) != NULL)
mmal_buffer_header_release(buffer);
if ( !vcos_verify(mmal_queue_length(pool->queue) == pool->headers_num) )
{
LOG_ERROR("coul dnot release all buffers");
}
}
wrapper->time_disable = vcos_getmicrosecs() - start_time;
return status;
}
/** Wait for an empty buffer to be available on a port */
MMAL_STATUS_T mmal_wrapper_buffer_get_empty(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T **buffer,
uint32_t flags)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
MMAL_WRAPPER_T *wrapper = &private->wrapper;
MMAL_POOL_T *pool;
LOG_TRACE("%p, %s", wrapper, port->name);
if (!buffer || (port->type != MMAL_PORT_TYPE_INPUT && port->type != MMAL_PORT_TYPE_OUTPUT))
return MMAL_EINVAL;
pool = port->type == MMAL_PORT_TYPE_INPUT ?
wrapper->input_pool[port->index] : wrapper->output_pool[port->index];
while (wrapper->status == MMAL_SUCCESS &&
(*buffer = mmal_queue_get(pool->queue)) == NULL)
{
if (!(flags & MMAL_WRAPPER_FLAG_WAIT))
break;
vcos_semaphore_wait(&private->sema);
}
return wrapper->status == MMAL_SUCCESS && !*buffer ? MMAL_EAGAIN : wrapper->status;
}
/** Wait for a full buffer to be available on a port */
MMAL_STATUS_T mmal_wrapper_buffer_get_full(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T **buffer,
uint32_t flags)
{
MMAL_WRAPPER_PRIVATE_T *private = (MMAL_WRAPPER_PRIVATE_T *)port->userdata;
MMAL_WRAPPER_T *wrapper = &private->wrapper;
MMAL_QUEUE_T *queue;
LOG_TRACE("%p, %s", wrapper, port->name);
if (!buffer || port->type != MMAL_PORT_TYPE_OUTPUT)
return MMAL_EINVAL;
queue = wrapper->output_queue[port->index];
while (wrapper->status == MMAL_SUCCESS &&
(*buffer = mmal_queue_get(queue)) == NULL)
{
if (!(flags & MMAL_WRAPPER_FLAG_WAIT))
break;
vcos_semaphore_wait(&private->sema);
}
return wrapper->status == MMAL_SUCCESS && !*buffer ? MMAL_EAGAIN : wrapper->status;
}
@@ -0,0 +1,157 @@
/*
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.
*/
#ifndef MMAL_WRAPPER_H
#define MMAL_WRAPPER_H
/** \defgroup MmalComponentWrapper utility
* \ingroup MmalUtilities
* The component wrapper utility functions can be used in place of common sequences
* of calls to the MMAL API in order to control a standalone component. It hides some
* of the complexity in using standalone components behind a fully synchronous
* interface.
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** Forward type definition for a wrapper */
typedef struct MMAL_WRAPPER_T MMAL_WRAPPER_T;
/** Definition of the callback used by a wrapper to signal back to the client
* that a buffer header is available either in the pool or in the output queue.
*
* @param wrapper Pointer to the wrapper
*/
typedef void (*MMAL_WRAPPER_CALLBACK_T)(MMAL_WRAPPER_T *wrapper);
/** Structure describing a wrapper around a component */
struct MMAL_WRAPPER_T {
void *user_data; /**< Field reserved for use by the client. */
MMAL_WRAPPER_CALLBACK_T callback; /**< Callback set by the client. */
MMAL_COMPONENT_T *component;
MMAL_STATUS_T status;
MMAL_PORT_T *control; /**< Control port (Read Only). */
uint32_t input_num; /**< Number of input ports (Read Only). */
MMAL_PORT_T **input; /**< Array of input ports (Read Only). */
MMAL_POOL_T **input_pool; /**< Array of input pools (Read Only). */
uint32_t output_num; /**< Number of output ports (Read Only). */
MMAL_PORT_T **output; /**< Array of output ports (Read Only). */
MMAL_POOL_T **output_pool; /**< Array of output pools (Read Only). */
MMAL_QUEUE_T **output_queue; /**< Array of output queues (Read Only). */
/* Used for debug / statistics */
int64_t time_setup; /**< Time in microseconds taken to setup the connection. */
int64_t time_enable; /**< Time in microseconds taken to enable the connection. */
int64_t time_disable; /**< Time in microseconds taken to disable the connection. */
};
/** Create a wrapper around a component.
* The wrapper shall include a pool of buffer headers for each port. The pools will be suitable
* for the current format of its associated port.
*
* @param wrapper The address of a wrapper pointer that will be set to point to the created
* wrapper.
* @param name The name of the component to create.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_create(MMAL_WRAPPER_T **wrapper, const char *name);
/** \name MMAL wrapper flags
* \anchor wrapperflags
*/
/* @{ */
/** The operation should be blocking */
#define MMAL_WRAPPER_FLAG_WAIT 1
/** The pool for the port should allocate memory for the payloads */
#define MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE 2
/** The port will use shared memory payloads */
#define MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY 4
/* @} */
/** Enable a port on a component wrapper.
*
* @param port port to enable
* @param flags used to specify payload allocation flags for the pool
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_port_enable(MMAL_PORT_T *port, uint32_t flags);
/** Disable a port on a component wrapper.
*
* @param port port to disable
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_port_disable(MMAL_PORT_T *port);
/** Wait for an empty buffer to be available on a port.
*
* @param port port to get an empty buffer from
* @param buffer points to the retreived buffer on return
* @param flags specify MMAL_WRAPPER_FLAG_WAIT for a blocking operation
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_buffer_get_empty(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T **buffer, uint32_t flags);
/** Wait for a full buffer to be available on a port.
*
* @param port port to get a full buffer from
* @param buffer points to the retreived buffer on return
* @param flags specify MMAL_WRAPPER_FLAG_WAIT for a blocking operation
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_buffer_get_full(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T **buffer, uint32_t flags);
/** Cancel any ongoing blocking operation on a component wrapper.
*
* @param wrapper The wrapper on which to cancel operations.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_cancel(MMAL_WRAPPER_T *wrapper);
/** Destroy a wrapper.
* Destroys a component wrapper and any resources it owns.
*
* @param wrapper The wrapper to be destroyed.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_wrapper_destroy(MMAL_WRAPPER_T *wrapper);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* MMAL_WRAPPER_H */
@@ -0,0 +1,513 @@
/*
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 "mmal.h"
#include "util/mmal_util.h"
#include "util/mmal_connection.h"
#include "mmal_logging.h"
#include <stdio.h>
#define CONNECTION_NAME_FORMAT "%s:%.2222s:%i/%s:%.2222s:%i"
typedef struct
{
MMAL_CONNECTION_T connection; /**< Must be the first member! */
MMAL_PORT_T *pool_port; /**< Port used to create the pool */
/** Reference counting */
int refcount;
} MMAL_CONNECTION_PRIVATE_T;
/** Callback from an input port. Buffer is released. */
static void mmal_connection_bh_in_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_PARAM_UNUSED(port);
LOG_TRACE("(%s)%p,%p,%p,%i", port->name, port, buffer, buffer->data, (int)buffer->length);
/* FIXME: Clock ports are bi-directional and a buffer coming from an
* "input" clock port can potentially have valid payload data, in
* which case it should be queued and not released, however this
* callback doesn't have access to the pool queue. */
if (port->type == MMAL_PORT_TYPE_CLOCK && buffer->length)
{
LOG_ERROR("clock ports not supported");
}
/* We're done with the buffer, just recycle it */
mmal_buffer_header_release(buffer);
}
/** Callback from an output port. Buffer is queued for the next component. */
static void mmal_connection_bh_out_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_CONNECTION_T *connection = (MMAL_CONNECTION_T *)port->userdata;
MMAL_PARAM_UNUSED(port);
LOG_TRACE("(%s)%p,%p,%p,%i", port->name, port, buffer, buffer->data, (int)buffer->length);
/* Queue the buffer produced by the output port */
mmal_queue_put(connection->queue, buffer);
if (connection->callback)
connection->callback(connection);
}
/** Callback from the pool. Buffer is available. */
static MMAL_BOOL_T mmal_connection_bh_release_cb(MMAL_POOL_T *pool, MMAL_BUFFER_HEADER_T *buffer,
void *userdata)
{
MMAL_CONNECTION_T *connection = (MMAL_CONNECTION_T *)userdata;
MMAL_PARAM_UNUSED(pool);
/* Queue the buffer produced by the output port */
mmal_queue_put(pool->queue, buffer);
if (connection->callback)
connection->callback(connection);
return 0;
}
/*****************************************************************************/
static MMAL_STATUS_T mmal_connection_destroy_internal(MMAL_CONNECTION_T *connection)
{
MMAL_STATUS_T status;
if (connection->is_enabled)
{
status = mmal_connection_disable(connection);
if (status != MMAL_SUCCESS)
return status;
}
/* Special case for tunnelling */
if (connection->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
{
status = mmal_port_disconnect(connection->out);
if (status != MMAL_SUCCESS)
LOG_ERROR("connection %s could not be cleared", connection->name);
}
/* Cleanup resources */
if (connection->pool)
mmal_pool_destroy(connection->pool);
if (connection->queue)
mmal_queue_destroy(connection->queue);
vcos_free(connection);
return MMAL_SUCCESS;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_destroy(MMAL_CONNECTION_T *connection)
{
MMAL_CONNECTION_PRIVATE_T *private = (MMAL_CONNECTION_PRIVATE_T *)connection;
LOG_TRACE("%p, %s", connection, connection->name);
if (--private->refcount)
{
LOG_DEBUG("delaying destruction of %s (refount %i)", connection->name,
private->refcount);
return MMAL_SUCCESS;
}
return mmal_connection_destroy_internal(connection);
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_create(MMAL_CONNECTION_T **cx,
MMAL_PORT_T *out, MMAL_PORT_T *in, uint32_t flags)
{
MMAL_STATUS_T status = MMAL_ENOMEM;
unsigned int name_size = strlen(out->component->name) + strlen(in->component->name) + sizeof(CONNECTION_NAME_FORMAT);
unsigned int size = sizeof(MMAL_CONNECTION_PRIVATE_T) + name_size;
MMAL_CONNECTION_PRIVATE_T *private;
MMAL_CONNECTION_T *connection;
char *name;
/* Sanity checking */
if (!cx)
return MMAL_EINVAL;
private = vcos_malloc(size, "mmal connection");
if (!private)
return MMAL_ENOMEM;
memset(private, 0, size);
connection = &private->connection;
private->refcount = 1;
name = (char *)&private[1];
vcos_snprintf(name, name_size - 1, CONNECTION_NAME_FORMAT,
out->component->name,
mmal_port_type_to_string(out->type), (int)out->index,
in->component->name,
mmal_port_type_to_string(in->type), (int)in->index);
LOG_TRACE("out %p, in %p, flags %x, %s", out, in, flags, name);
connection->out = out;
connection->in = in;
connection->flags = flags;
connection->name = name;
connection->time_setup = vcos_getmicrosecs();
/* Set the format of the input port to match the output one */
status = mmal_format_full_copy(in->format, out->format);
if (status == MMAL_SUCCESS)
status = mmal_port_format_commit(in);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("format not set on input port");
goto error;
}
/* In pass-through mode we need to propagate the buffer requirements of the
* connected input port */
if (out->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
{
MMAL_PARAMETER_BUFFER_REQUIREMENTS_T param =
{{MMAL_PARAMETER_BUFFER_REQUIREMENTS, sizeof(MMAL_PARAMETER_BUFFER_REQUIREMENTS_T)},
in->buffer_num_min, in->buffer_size_min, in->buffer_alignment_min,
in->buffer_num_recommended, in->buffer_size_recommended};
status = mmal_port_parameter_set(out, &param.hdr);
if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
{
LOG_ERROR("failed to propagate buffer requirements");
goto error;
}
status = MMAL_SUCCESS;
}
/* Special case for tunnelling */
if (connection->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
{
status = mmal_port_connect(out, in);
if (status != MMAL_SUCCESS)
LOG_ERROR("connection could not be made");
goto done;
}
/* Create empty pool of buffer headers for now (will be resized later on) */
private->pool_port = (in->capabilities & MMAL_PORT_CAPABILITY_ALLOCATION) ? in : out;
if (flags & MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT)
private->pool_port = in;
if (flags & MMAL_CONNECTION_FLAG_ALLOCATION_ON_OUTPUT)
private->pool_port = out;
connection->pool = mmal_port_pool_create(private->pool_port, 0, 0);
if (!connection->pool)
goto error;
mmal_pool_callback_set(connection->pool, mmal_connection_bh_release_cb, (void *)connection);
/* Create a queue to store the buffers from the output port */
connection->queue = mmal_queue_create();
if (!connection->queue)
goto error;
done:
out->userdata = (void *)connection;
in->userdata = (void *)connection;
connection->time_setup = vcos_getmicrosecs() - connection->time_setup;
*cx = connection;
return status;
error:
/* coverity[var_deref_model] mmal_connection_destroy_internal will check connection->pool correctly */
mmal_connection_destroy_internal(connection);
return status == MMAL_SUCCESS ? MMAL_ENOMEM : status;
}
/*****************************************************************************/
void mmal_connection_acquire(MMAL_CONNECTION_T *connection)
{
MMAL_CONNECTION_PRIVATE_T *private = (MMAL_CONNECTION_PRIVATE_T *)connection;
LOG_TRACE("connection %s(%p), refcount %i", connection->name, connection,
private->refcount);
private->refcount++;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_release(MMAL_CONNECTION_T *connection)
{
MMAL_CONNECTION_PRIVATE_T *private = (MMAL_CONNECTION_PRIVATE_T *)connection;
LOG_TRACE("connection %s(%p), refcount %i", connection->name, connection,
private->refcount);
if (--private->refcount)
return MMAL_SUCCESS;
LOG_TRACE("destroying connection %s(%p)", connection->name, connection);
return mmal_connection_destroy_internal(connection);
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_enable(MMAL_CONNECTION_T *connection)
{
MMAL_PORT_T *in = connection->in, *out = connection->out;
uint32_t buffer_num, buffer_size;
MMAL_STATUS_T status;
LOG_TRACE("%p, %s", connection, connection->name);
if (connection->is_enabled)
return MMAL_SUCCESS;
connection->time_enable = vcos_getmicrosecs();
/* Override the buffer values with the recommended ones (the port probably knows best) */
if (!(connection->flags & MMAL_CONNECTION_FLAG_KEEP_BUFFER_REQUIREMENTS))
{
if (out->buffer_num_recommended)
out->buffer_num = out->buffer_num_recommended;
if (out->buffer_size_recommended)
out->buffer_size = out->buffer_size_recommended;
if (in->buffer_num_recommended)
in->buffer_num = in->buffer_num_recommended;
if (in->buffer_size_recommended)
in->buffer_size = in->buffer_size_recommended;
}
/* Special case for tunnelling */
if (connection->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
{
/* Enable port. No callback because the port is connected. Other end of the connection
* will be enabled automatically. */
status = mmal_port_enable(out, NULL);
if (status)
LOG_ERROR("output port couldn't be enabled");
goto done;
}
/* Set the buffering properties on both ports */
buffer_num = MMAL_MAX(out->buffer_num, in->buffer_num);
buffer_size = MMAL_MAX(out->buffer_size, in->buffer_size);
out->buffer_num = in->buffer_num = buffer_num;
out->buffer_size = in->buffer_size = buffer_size;
/* In pass-through mode there isn't any need to allocate memory */
if (out->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
buffer_size = 0;
/* Resize the output pool */
status = mmal_pool_resize(connection->pool, buffer_num, buffer_size);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("couldn't resize pool");
goto done;
}
/* Enable output port. The callback specified here is the function which
* will be called when an empty buffer header comes back to the port. */
status = mmal_port_enable(out, mmal_connection_bh_out_cb);
if(status)
{
LOG_ERROR("output port couldn't be enabled");
goto done;
}
/* Enable input port. The callback specified here is the function which
* will be called when an empty buffer header comes back to the port. */
status = mmal_port_enable(in, mmal_connection_bh_in_cb);
if(status)
{
LOG_ERROR("input port couldn't be enabled");
mmal_port_disable(out);
goto done;
}
/* Clock ports need buffers to send clock updates, so
* populate both connected clock ports */
if ((out->type == MMAL_PORT_TYPE_CLOCK) && (in->type == MMAL_PORT_TYPE_CLOCK))
{
MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(connection->pool->queue);
while (buffer)
{
mmal_port_send_buffer(out, buffer);
buffer = mmal_queue_get(connection->pool->queue);
if (buffer)
{
mmal_port_send_buffer(in, buffer);
buffer = mmal_queue_get(connection->pool->queue);
}
}
}
done:
connection->time_enable = vcos_getmicrosecs() - connection->time_enable;
connection->is_enabled = status == MMAL_SUCCESS;
return status;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_disable(MMAL_CONNECTION_T *connection)
{
MMAL_STATUS_T status;
MMAL_BUFFER_HEADER_T *buffer;
LOG_TRACE("%p, %s", connection, connection->name);
if (!connection->is_enabled)
return MMAL_SUCCESS;
connection->time_disable = vcos_getmicrosecs();
/* Special case for tunnelling */
if (connection->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
{
/* Disable port. Other end of the connection will be disabled automatically. */
status = mmal_port_disable(connection->out);
if (status)
LOG_ERROR("output port couldn't be disabled");
goto done;
}
/* Disable input port. */
status = mmal_port_disable(connection->in);
if(status)
{
LOG_ERROR("input port couldn't be disabled");
goto done;
}
/* Disable output port */
status = mmal_port_disable(connection->out);
if(status)
{
LOG_ERROR("output port couldn't be disabled");
goto done;
}
/* Flush the queue */
buffer = mmal_queue_get(connection->queue);
while (buffer)
{
mmal_buffer_header_release(buffer);
buffer = mmal_queue_get(connection->queue);
}
vcos_assert(mmal_queue_length(connection->pool->queue) == connection->pool->headers_num);
done:
connection->time_disable = vcos_getmicrosecs() - connection->time_disable;
connection->is_enabled = !(status == MMAL_SUCCESS);
return status;
}
/*****************************************************************************/
static MMAL_STATUS_T mmal_connection_reconfigure(MMAL_CONNECTION_T *connection, MMAL_ES_FORMAT_T *format)
{
MMAL_STATUS_T status;
LOG_TRACE("%p, %s", connection, connection->name);
status = mmal_connection_disable(connection);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("connection couldn't be disabled");
return status;
}
/* Set the new format for the output port */
status = mmal_format_full_copy(connection->out->format, format);
if (status == MMAL_SUCCESS)
status = mmal_port_format_commit(connection->out);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("commit failed on port %s(%p) (%i)",
connection->out->name, connection->out, status);
return status;
}
/* Set the new format for the input port */
status = mmal_format_full_copy(connection->in->format, connection->out->format);
if (status == MMAL_SUCCESS)
status = mmal_port_format_commit(connection->in);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("commit failed on port %s(%p) (%i)",
connection->in->name, connection->in, status);
return status;
}
/* Enable ports */
status = mmal_connection_enable(connection);
if (status)
{
LOG_ERROR("connection couldn't be enabled");
return status;
}
return MMAL_SUCCESS;
}
/*****************************************************************************/
MMAL_STATUS_T mmal_connection_event_format_changed(MMAL_CONNECTION_T *connection,
MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_EVENT_FORMAT_CHANGED_T *event;
MMAL_STATUS_T status;
LOG_TRACE("%p, %s", connection, connection->name);
if (buffer->cmd != MMAL_EVENT_FORMAT_CHANGED)
return MMAL_EINVAL;
event = mmal_event_format_changed_get(buffer);
if (!event)
return MMAL_EINVAL;
/* If we don't need to recreate our buffers then we can just forward the event
* to the next component (so it gets configured properly) */
if ((connection->in->capabilities & MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE) &&
event->buffer_size_min <= connection->out->buffer_size &&
event->buffer_num_min <= connection->out->buffer_num)
{
status = mmal_format_full_copy(connection->out->format, event->format);
if (status == MMAL_SUCCESS)
status = mmal_port_format_commit(connection->out);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("format commit failed on port %s(%p) (%i)",
connection->out->name, connection->out, status);
return status;
}
mmal_buffer_header_acquire(buffer);
status = mmal_port_send_buffer(connection->in, buffer);
if (status != MMAL_SUCCESS)
{
LOG_ERROR("buffer send failed on port %s(%p) (%i)",
connection->in->name, connection->in, status);
mmal_buffer_header_release(buffer);
return status;
}
return MMAL_SUCCESS;
}
/* Otherwise we have to reconfigure our pipeline */
return mmal_connection_reconfigure(connection, event->format);
}
@@ -0,0 +1,230 @@
/*
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.
*/
#ifndef MMAL_CONNECTION_H
#define MMAL_CONNECTION_H
/** \defgroup MmalConnectionUtility Port connection utility
* \ingroup MmalUtilities
* The port connection utility functions can be used in place of common sequences
* of calls to the MMAL API in order to process buffers being passed between two
* ports.
*
* \section ProcessingConnectionBufferHeaders Processing connection buffer headers
* Either in response to the client callback function being called, or simply on a
* timer, the client will need to process the buffer headers of the connection
* (unless tunneling is used).
*
* Buffer headers that are in the pool queue will need to be sent to the output port,
* while buffer headers in the connection queue are sent to the input port. The
* buffer headers in the connection queue may contain pixel data (the cmd field is
* zero) or an event (the cmd field is non-zero). In general, pixel data buffer
* headers need to be passed on, while event buffer headers are released. In the
* case of the format changed event, mmal_connection_event_format_changed() can be
* called before the event is released.
*
* Other, specialized use cases may also be implemented, such as getting and
* immediately releasing buffer headers from the connection queue in order to
* prevent their propagation. This could be used to drop out video, for example.
*
* \section TunnellingConnections Tunnelling connections
* If the \ref MMAL_CONNECTION_FLAG_TUNNELLING flag is set when the connection is
* created, MMAL tunneling will be used. This automates the passing of the buffer
* headers between the output port and input port, and back again. It will also do
* this as efficiently as possible, avoiding trips between the ARM and the VideoCore
* if both components are implemented on the VideoCore. The consequence of this is
* that there is no client callback made as buffer headers get transferred.
*
* The client can still monitor the control port of a component (usually a sink
* component, such as video_render) for the end of stream, in order to know when to
* dismantle the connection.
*
* \section ConnectionClientCallback Client callback
* When not using tunnelling, the client callback function is called each time a
* buffer arrives from a port (either input or output).
*
* \note The callback is made on a different thread from the one used by the
* client to set up the connection, so care must be taken with thread safety.
* One option is to raise a signal to the main client thread that queue processing
* needs to be done, another is for the callback to perform the queue processing
* itself.
*
* The client can also store an opaque pointer in the connection object, which is
* never used by the MMAL code and is only meaningful to the client.
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** \name Connection flags
* \anchor connectionflags
* The following flags describe the properties of the connection. */
/* @{ */
/** The connection is tunnelled. Buffer headers do not transit via the client but
* directly from the output port to the input port. */
#define MMAL_CONNECTION_FLAG_TUNNELLING 0x1
/** Force the pool of buffer headers used by the connection to be allocated on the input port. */
#define MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT 0x2
/** Force the pool of buffer headers used by the connection to be allocated on the output port. */
#define MMAL_CONNECTION_FLAG_ALLOCATION_ON_OUTPUT 0x4
/** Specify that the connection should not modify the buffer requirements. */
#define MMAL_CONNECTION_FLAG_KEEP_BUFFER_REQUIREMENTS 0x8
/** The connection is flagged as direct. This doesn't change the behaviour of
* the connection itself but is used by the the graph utility to specify that
* the buffer should be sent to the input port from with the port callback. */
#define MMAL_CONNECTION_FLAG_DIRECT 0x10
/* @} */
/** Forward type definition for a connection */
typedef struct MMAL_CONNECTION_T MMAL_CONNECTION_T;
/** Definition of the callback used by a connection to signal back to the client
* that a buffer header is available either in the pool or in the output queue.
*
* @param connection Pointer to the connection
*/
typedef void (*MMAL_CONNECTION_CALLBACK_T)(MMAL_CONNECTION_T *connection);
/** Structure describing a connection between 2 ports (1 output and 1 input port) */
struct MMAL_CONNECTION_T {
void *user_data; /**< Field reserved for use by the client. */
MMAL_CONNECTION_CALLBACK_T callback; /**< Callback set by the client. */
uint32_t is_enabled; /**< Specifies whether the connection is enabled or not (Read Only). */
uint32_t flags; /**< Flags passed during the create call (Read Only). A bitwise
* combination of \ref connectionflags "Connection flags" values.
*/
MMAL_PORT_T *in; /**< Input port used for the connection (Read Only). */
MMAL_PORT_T *out; /**< Output port used for the connection (Read Only). */
MMAL_POOL_T *pool; /**< Pool of buffer headers used by the output port (Read Only). */
MMAL_QUEUE_T *queue; /**< Queue for the buffer headers produced by the output port (Read Only). */
const char *name; /**< Connection name (Read Only). Used for debugging purposes. */
/* Used for debug / statistics */
int64_t time_setup; /**< Time in microseconds taken to setup the connection. */
int64_t time_enable; /**< Time in microseconds taken to enable the connection. */
int64_t time_disable; /**< Time in microseconds taken to disable the connection. */
};
/** Create a connection between two ports.
* The connection shall include a pool of buffer headers suitable for the current format of
* the output port. The format of the input port shall have been set to the same as that of
* the input port.
* Note that connections are reference counted and creating a connection automatically
* acquires a reference to it (released when \ref mmal_connection_destroy is called).
*
* @param connection The address of a connection pointer that will be set to point to the created
* connection.
* @param out The output port to use for the connection.
* @param in The input port to use for the connection.
* @param flags The flags specifying which type of connection should be created.
* A bitwise combination of \ref connectionflags "Connection flags" values.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_connection_create(MMAL_CONNECTION_T **connection,
MMAL_PORT_T *out, MMAL_PORT_T *in, uint32_t flags);
/** Acquire a reference on a connection.
* Acquiring a reference on a connection will prevent a connection from being destroyed until
* the acquired reference is released (by a call to \ref mmal_connection_destroy).
* References are internally counted so all acquired references need a matching call to
* release them.
*
* @param connection connection to acquire
*/
void mmal_connection_acquire(MMAL_CONNECTION_T *connection);
/** Release a reference on a connection
* Release an acquired reference on a connection. Triggers the destruction of the connection when
* the last reference is being released.
* \note This is in fact an alias of \ref mmal_connection_destroy which is added to make client
* code clearer.
*
* @param connection connection to release
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_connection_release(MMAL_CONNECTION_T *connection);
/** Destroy a connection.
* Release an acquired reference on a connection. Only actually destroys the connection when
* the last reference is being released.
* The actual destruction of the connection will start by disabling it, if necessary.
* Any pool, queue, and so on owned by the connection shall then be destroyed.
*
* @param connection The connection to be destroyed.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_connection_destroy(MMAL_CONNECTION_T *connection);
/** Enable a connection.
* The format of the two ports must have been committed before calling this function,
* although note that on creation, the connection automatically copies and commits the
* output port's format to the input port.
*
* The MMAL_CONNECTION_T::callback field must have been set if the \ref MMAL_CONNECTION_FLAG_TUNNELLING
* flag was not specified on creation. The client may also set the MMAL_CONNECTION_T::user_data
* in order to get a pointer passed, via the connection, to the callback.
*
* @param connection The connection to be enabled.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_connection_enable(MMAL_CONNECTION_T *connection);
/** Disable a connection.
*
* @param connection The connection to be disabled.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_connection_disable(MMAL_CONNECTION_T *connection);
/** Apply a format changed event to the connection.
* This function can be used when the client is processing buffer headers and receives
* a format changed event (\ref MMAL_EVENT_FORMAT_CHANGED). The connection is
* reconfigured, changing the format of the ports, the number of buffer headers and
* the size of the payload buffers as necessary.
*
* @param connection The connection to which the event shall be applied.
* @param buffer The buffer containing a format changed event.
* @return MMAL_SUCCESS on success.
*/
MMAL_STATUS_T mmal_connection_event_format_changed(MMAL_CONNECTION_T *connection,
MMAL_BUFFER_HEADER_T *buffer);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* MMAL_CONNECTION_H */
@@ -0,0 +1,90 @@
/*
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.
*/
#ifndef MMAL_DEFAULT_COMPONENTS_H
#define MMAL_DEFAULT_COMPONENTS_H
/** \defgroup MmalDefaultComponents List of default components
* This provides a list of default components on a per platform basis.
* @{
*/
#define MMAL_COMPONENT_DEFAULT_CONTAINER_READER "container_reader"
#define MMAL_COMPONENT_DEFAULT_CONTAINER_WRITER "container_writer"
#if defined(ENABLE_MMAL_STANDALONE)
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "avcodec.video_decode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "avcodec.video_encode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "sdl.video_render"
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "avcodec.video_decode"
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "avcodec.video_encode"
# define MMAL_COMPONENT_DEFAULT_CAMERA "artificial_camera"
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "avcodec.video_convert"
# define MMAL_COMPONENT_DEFAULT_SPLITTER "splitter"
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "scheduler"
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "video_inject"
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "avcodec.audio_decode"
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "sdl.audio_render"
# define MMAL_COMPONENT_DEFAULT_MIRACAST "miracast"
# define MMAL_COMPONENT_DEFAULT_CLOCK "clock"
#elif defined(__VIDEOCORE__)
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "ril.video_decode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "ril.video_encode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "ril.video_render"
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "ril.image_decode"
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "ril.image_encode"
# define MMAL_COMPONENT_DEFAULT_CAMERA "ril.camera"
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "video_convert"
# define MMAL_COMPONENT_DEFAULT_SPLITTER "splitter"
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "scheduler"
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "video_inject"
# define MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER "ril.video_splitter"
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "none"
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "ril.audio_render"
# define MMAL_COMPONENT_DEFAULT_MIRACAST "miracast"
# define MMAL_COMPONENT_DEFAULT_CLOCK "clock"
#else
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "vc.ril.video_decode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "vc.ril.video_encode"
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "vc.ril.video_render"
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "vc.ril.image_decode"
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "vc.ril.image_encode"
# define MMAL_COMPONENT_DEFAULT_CAMERA "vc.ril.camera"
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "vc.video_convert"
# define MMAL_COMPONENT_DEFAULT_SPLITTER "vc.splitter"
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "vc.scheduler"
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "vc.video_inject"
# define MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER "vc.ril.video_splitter"
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "none"
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "vc.ril.audio_render"
# define MMAL_COMPONENT_DEFAULT_MIRACAST "vc.miracast"
# define MMAL_COMPONENT_DEFAULT_CLOCK "vc.clock"
#endif
/** @} */
#endif /* MMAL_DEFAULT_COMPONENTS_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,243 @@
/*
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.
*/
#ifndef MMAL_GRAPH_H
#define MMAL_GRAPH_H
#include "util/mmal_connection.h"
/** \defgroup MmalGraphUtility Graph Utility
* \ingroup MmalUtilities
* The graph utility functions allows one to easily create graphs of MMAL components.
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** List of topology types */
typedef enum
{
MMAL_GRAPH_TOPOLOGY_ALL = 0, /**< All input ports and output ports are linked */
MMAL_GRAPH_TOPOLOGY_STRAIGHT, /**< Input ports and output ports of the same index are linked */
MMAL_GRAPH_TOPOLOGY_CUSTOM, /**< Custom defined topology */
MMAL_GRAPH_TOPOLOGY_MAX
} MMAL_GRAPH_TOPOLOGY_T;
/** Structure describing a graph */
typedef struct MMAL_GRAPH_T
{
/** Pointer to private data of the client */
struct MMAL_GRAPH_USERDATA_T *userdata;
/** Optional callback that the client can set to get notified when the graph is going to be destroyed */
void (*pf_destroy)(struct MMAL_GRAPH_T *);
/** Optional callback that the client can set to intercept parameter requests on ports exposed by the graph */
MMAL_STATUS_T (*pf_parameter_set)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param);
/** Optional callback that the client can set to intercept parameter requests on ports exposed by the graph */
MMAL_STATUS_T (*pf_parameter_get)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param);
/** Optional callback that the client can set to intercept format commit calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_format_commit)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port);
/** Optional callback that the client can set to intercept send buffer calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_send_buffer)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
/** Optional callback that the client can set to intercept buffer callbacks on ports exposed by the graph */
MMAL_STATUS_T (*pf_return_buffer)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
/** Optional callback that the client can set to intercept payload alloc calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_payload_alloc)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, uint32_t payload_size, uint8_t **);
/** Optional callback that the client can set to intercept payload free calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_payload_free)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, uint8_t *payload);
/** Optional callback that the client can set to intercept flush calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_flush)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port);
/** Optional callback that the client can set to control callbacks from the internal components of the graph */
/** Optional callback that the client can set to intercept enable calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_enable)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port);
/** Optional callback that the client can set to intercept disable calls on ports exposed by the graph */
MMAL_STATUS_T (*pf_disable)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port);
/** Optional callback that the client can set to control callbacks from the internal components of the graph */
MMAL_STATUS_T (*pf_control_callback)(struct MMAL_GRAPH_T *, MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
/** Optional callback that the client can set to intercept component_enable/disable calls made to the graph */
MMAL_STATUS_T (*pf_graph_enable)(struct MMAL_GRAPH_T *, MMAL_BOOL_T enable);
/** Optional callback that the client can set to intercept buffers going through internal connections.
* This will only be triggered if the connection is not tunnelled */
MMAL_STATUS_T (*pf_connection_buffer)(struct MMAL_GRAPH_T *, MMAL_CONNECTION_T *connection, MMAL_BUFFER_HEADER_T *buffer);
} MMAL_GRAPH_T;
/** Create an instance of a graph.
* The newly created graph will need to be populated by the client.
*
* @param graph returned graph
* @param userdata_size size to be allocated for the userdata field
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_create(MMAL_GRAPH_T **graph, unsigned int userdata_size);
/** Add a component to a graph.
* Allows the client to add a component to the graph.
*
* @param graph instance of the graph
* @param component component to add to a graph
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_add_component(MMAL_GRAPH_T *graph, MMAL_COMPONENT_T *component);
/** Describe the topology of the ports of a component.
* Allows the client to describe the topology of a component. This information
* is used by the graph to choose which action to perform when
* enabling / disabling / committing / flushing a port exposed by the graph.
* Note that by default the topology of a component is set to MMAL_GRAPH_TOPOLOGY_ALL.
*
* @param graph instance of the graph
* @param component component to describe
* @param topology type of topology used by this component
* @param input output index (or -1 if sink) linked to each input port
* @param input_num number of indexes in the input list
* @param output input index (or -1 if source) linked to each output port
* @param output_num number of indexes in the output list
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_component_topology(MMAL_GRAPH_T *graph, MMAL_COMPONENT_T *component,
MMAL_GRAPH_TOPOLOGY_T topology, int8_t *input, unsigned int input_num,
int8_t *output, unsigned int output_num);
/** Add a port to a graph.
* Allows the client to add an input or output port to a graph. The given port
* will effectively become an end point for the graph.
*
* @param graph instance of the graph
* @param port port to add to the graph
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_add_port(MMAL_GRAPH_T *graph, MMAL_PORT_T *port);
/** Add a connection to a graph.
* Allows the client to add an internal connection to a graph.
*
* @param graph instance of the graph
* @param connection connection to add to the graph
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_add_connection(MMAL_GRAPH_T *graph, MMAL_CONNECTION_T *connection);
/** Create a new component and add it to a graph.
* Allows the client to create and add a component to the graph.
*
* @param graph instance of the graph
* @param name name of the component to create
* @param component if not NULL, will contain a pointer to the created component
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_new_component(MMAL_GRAPH_T *graph, const char *name,
MMAL_COMPONENT_T **component);
/** Create and add a connection to a graph.
* Allows the client to create and add an internal connection to a graph.
*
* @param graph instance of the graph
* @param out the output port to use for the connection
* @param in the input port to use for the connection
* @param flags the flags specifying which type of connection should be created
* @param connection if not NULL, will contain a pointer to the created connection
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_new_connection(MMAL_GRAPH_T *graph, MMAL_PORT_T *out, MMAL_PORT_T *in,
uint32_t flags, MMAL_CONNECTION_T **connection);
/** Definition of the callback used by a graph to send events to the client.
*
* @param graph the graph sending the event
* @param port the port which generated the event
* @param buffer the buffer header containing the event data
* @param cb_data data passed back to the client when the callback is invoked
*/
typedef void (*MMAL_GRAPH_EVENT_CB)(MMAL_GRAPH_T *graph, MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer,
void *cb_data);
/** Enable the graph and start processing.
*
* @param graph the graph to enable
* @param cb the callback to invoke when an event occurs on any of the internal control ports
* @param cb_data data passed back to the client when the callback is invoked
*
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_enable(MMAL_GRAPH_T *graph, MMAL_GRAPH_EVENT_CB cb, void *cb_data);
MMAL_STATUS_T mmal_graph_disable(MMAL_GRAPH_T *graph);
/** Find a port in the graph.
*
* @param graph graph instance
* @param name name of the component of interest
* @param type type of port (in/out)
* @param index which port index within the component
*
* @return port, or NULL if not found
*/
MMAL_PORT_T *mmal_graph_find_port(MMAL_GRAPH_T *graph,
const char *name,
MMAL_PORT_TYPE_T type,
unsigned index);
/** Create an instance of a component from a graph.
* The newly created component will expose input and output ports to the client.
* Not that all the exposed ports will be in a disabled state by default.
*
* @param graph graph to create the component from
* @param name name of the component to create
* @param component returned component
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_build(MMAL_GRAPH_T *ctx,
const char *name, MMAL_COMPONENT_T **component);
/** Component constructor for a graph.
* FIXME: private function
*
* @param name name of the component to create
* @param component component
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_component_constructor(const char *name, MMAL_COMPONENT_T *component);
/** Destroy a previously created graph
* @param graph graph to destroy
* @return MMAL_SUCCESS on success
*/
MMAL_STATUS_T mmal_graph_destroy(MMAL_GRAPH_T *ctx);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* MMAL_GRAPH_H */
@@ -0,0 +1,915 @@
/*
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 "mmal.h"
#include "util/mmal_il.h"
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
/*****************************************************************************/
static struct {
MMAL_STATUS_T mmal;
OMX_ERRORTYPE omx;
} mmal_omx_error[] =
{
{MMAL_SUCCESS, OMX_ErrorNone},
{MMAL_ENOMEM, OMX_ErrorInsufficientResources},
{MMAL_ENOSPC, OMX_ErrorInsufficientResources},
{MMAL_EINVAL, OMX_ErrorBadParameter},
{MMAL_ENOSYS, OMX_ErrorNotImplemented},
{(MMAL_STATUS_T)-1, OMX_ErrorUndefined},
};
OMX_ERRORTYPE mmalil_error_to_omx(MMAL_STATUS_T status)
{
unsigned int i;
for(i = 0; mmal_omx_error[i].mmal != (MMAL_STATUS_T)-1; i++)
if(mmal_omx_error[i].mmal == status) break;
return mmal_omx_error[i].omx;
}
MMAL_STATUS_T mmalil_error_to_mmal(OMX_ERRORTYPE error)
{
unsigned int i;
for(i = 0; mmal_omx_error[i].mmal != (MMAL_STATUS_T)-1; i++)
if(mmal_omx_error[i].omx == error) break;
return mmal_omx_error[i].mmal;
}
/*****************************************************************************/
OMX_U32 mmalil_buffer_flags_to_omx(uint32_t flags)
{
OMX_U32 omx_flags = 0;
if(flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
omx_flags |= OMX_BUFFERFLAG_SYNCFRAME;
if(flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
omx_flags |= OMX_BUFFERFLAG_ENDOFFRAME;
if(flags & MMAL_BUFFER_HEADER_FLAG_EOS)
omx_flags |= OMX_BUFFERFLAG_EOS;
if(flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
omx_flags |= OMX_BUFFERFLAG_CODECCONFIG;
if(flags & MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY)
omx_flags |= OMX_BUFFERFLAG_DISCONTINUITY;
if (flags & MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO)
omx_flags |= OMX_BUFFERFLAG_CODECSIDEINFO;
if (flags & MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT)
omx_flags |= OMX_BUFFERFLAG_CAPTURE_PREVIEW;
if (flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED)
omx_flags |= OMX_BUFFERFLAG_DATACORRUPT;
if (flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)
omx_flags |= OMX_BUFFERFLAG_DECODEONLY;
if (flags & MMAL_BUFFER_HEADER_FLAG_USER0)
omx_flags |= 1<<28;
if (flags & MMAL_BUFFER_HEADER_FLAG_USER1)
omx_flags |= 1<<29;
if (flags & MMAL_BUFFER_HEADER_FLAG_USER2)
omx_flags |= 1<<30;
if (flags & MMAL_BUFFER_HEADER_FLAG_USER3)
omx_flags |= 1<<31;
return omx_flags;
}
uint32_t mmalil_buffer_flags_to_mmal(OMX_U32 flags)
{
uint32_t mmal_flags = 0;
if (flags & OMX_BUFFERFLAG_SYNCFRAME)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
if (flags & OMX_BUFFERFLAG_ENDOFFRAME)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
if (flags & OMX_BUFFERFLAG_EOS)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
if (flags & OMX_BUFFERFLAG_CODECCONFIG)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG;
if (flags & OMX_BUFFERFLAG_DISCONTINUITY)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY;
if (flags & OMX_BUFFERFLAG_CODECSIDEINFO)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO;
if (flags & OMX_BUFFERFLAG_CAPTURE_PREVIEW)
mmal_flags |= MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT;
if (flags & OMX_BUFFERFLAG_DATACORRUPT)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_CORRUPTED;
if (flags & OMX_BUFFERFLAG_DECODEONLY)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_DECODEONLY;
if (flags & 1<<28)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_USER0;
if (flags & 1<<29)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_USER1;
if (flags & 1<<30)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_USER2;
if (flags & 1<<31)
mmal_flags |= MMAL_BUFFER_HEADER_FLAG_USER3;
return mmal_flags;
}
/*****************************************************************************/
void mmalil_buffer_header_to_omx(OMX_BUFFERHEADERTYPE *omx, MMAL_BUFFER_HEADER_T *mmal)
{
omx->pBuffer = mmal->data;
omx->nAllocLen = mmal->alloc_size;
omx->nFilledLen = mmal->length;
omx->nOffset = mmal->offset;
omx->nFlags = mmalil_buffer_flags_to_omx(mmal->flags);
omx->nTimeStamp = omx_ticks_from_s64(mmal->pts);
if (mmal->pts == MMAL_TIME_UNKNOWN)
{
omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
omx->nTimeStamp = omx_ticks_from_s64(0);
}
}
void mmalil_buffer_header_to_mmal(MMAL_BUFFER_HEADER_T *mmal, OMX_BUFFERHEADERTYPE *omx)
{
mmal->cmd = 0;
mmal->data = omx->pBuffer;
mmal->alloc_size = omx->nAllocLen;
mmal->length = omx->nFilledLen;
mmal->offset = omx->nOffset;
mmal->pts = omx_ticks_to_s64(omx->nTimeStamp);
if (omx->nFlags & OMX_BUFFERFLAG_TIME_UNKNOWN)
mmal->pts = MMAL_TIME_UNKNOWN;
mmal->dts = MMAL_TIME_UNKNOWN;
mmal->flags = mmalil_buffer_flags_to_mmal(omx->nFlags);
}
/*****************************************************************************/
static struct {
MMAL_ES_TYPE_T type;
OMX_PORTDOMAINTYPE domain;
} mmal_omx_es_type_table[] =
{
{MMAL_ES_TYPE_VIDEO, OMX_PortDomainVideo},
{MMAL_ES_TYPE_VIDEO, OMX_PortDomainImage},
{MMAL_ES_TYPE_AUDIO, OMX_PortDomainAudio},
{MMAL_ES_TYPE_UNKNOWN, OMX_PortDomainMax}
};
OMX_PORTDOMAINTYPE mmalil_es_type_to_omx_domain(MMAL_ES_TYPE_T type)
{
unsigned int i;
for(i = 0; mmal_omx_es_type_table[i].type != MMAL_ES_TYPE_UNKNOWN; i++)
if(mmal_omx_es_type_table[i].type == type) break;
return mmal_omx_es_type_table[i].domain;
}
MMAL_ES_TYPE_T mmalil_omx_domain_to_es_type(OMX_PORTDOMAINTYPE domain)
{
unsigned int i;
for(i = 0; mmal_omx_es_type_table[i].type != MMAL_ES_TYPE_UNKNOWN; i++)
if(mmal_omx_es_type_table[i].domain == domain) break;
return mmal_omx_es_type_table[i].type;
}
/*****************************************************************************/
static struct {
uint32_t encoding;
OMX_AUDIO_CODINGTYPE coding;
} mmal_omx_audio_coding_table[] =
{
{MMAL_ENCODING_MP4A, OMX_AUDIO_CodingAAC},
{MMAL_ENCODING_MPGA, OMX_AUDIO_CodingMP3},
{MMAL_ENCODING_WMA2, OMX_AUDIO_CodingWMA},
{MMAL_ENCODING_WMA1, OMX_AUDIO_CodingWMA},
{MMAL_ENCODING_AMRNB, OMX_AUDIO_CodingAMR},
{MMAL_ENCODING_AMRWB, OMX_AUDIO_CodingAMR},
{MMAL_ENCODING_AMRWBP, OMX_AUDIO_CodingAMR},
{MMAL_ENCODING_VORBIS, OMX_AUDIO_CodingVORBIS},
{MMAL_ENCODING_ALAW, OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_MULAW, OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_PCM_SIGNED_LE, OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_PCM_UNSIGNED_LE,OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_PCM_SIGNED_BE, OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_PCM_UNSIGNED_BE,OMX_AUDIO_CodingPCM},
{MMAL_ENCODING_AC3, OMX_AUDIO_CodingDDP},
{MMAL_ENCODING_EAC3, OMX_AUDIO_CodingDDP},
{MMAL_ENCODING_DTS, OMX_AUDIO_CodingDTS},
{MMAL_ENCODING_UNKNOWN, OMX_AUDIO_CodingUnused}
};
uint32_t mmalil_omx_audio_coding_to_encoding(OMX_AUDIO_CODINGTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_audio_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_audio_coding_table[i].coding == coding) break;
return mmal_omx_audio_coding_table[i].encoding;
}
OMX_AUDIO_CODINGTYPE mmalil_encoding_to_omx_audio_coding(uint32_t encoding)
{
unsigned int i;
for(i = 0; mmal_omx_audio_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_audio_coding_table[i].encoding == encoding) break;
return mmal_omx_audio_coding_table[i].coding;
}
static struct {
OMX_AUDIO_CODINGTYPE coding;
OMX_INDEXTYPE index;
unsigned int size;
} mmal_omx_audio_format_table[] =
{
{OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)},
{OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm, sizeof(OMX_AUDIO_PARAM_ADPCMTYPE)},
{OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr, sizeof(OMX_AUDIO_PARAM_AMRTYPE)},
{OMX_AUDIO_CodingGSMFR, OMX_IndexParamAudioGsm_FR, sizeof(OMX_AUDIO_PARAM_GSMFRTYPE)},
{OMX_AUDIO_CodingGSMEFR, OMX_IndexParamAudioGsm_EFR, sizeof(OMX_AUDIO_PARAM_GSMEFRTYPE)},
{OMX_AUDIO_CodingGSMHR, OMX_IndexParamAudioGsm_HR, sizeof(OMX_AUDIO_PARAM_GSMHRTYPE)},
{OMX_AUDIO_CodingPDCFR, OMX_IndexParamAudioPdc_FR, sizeof(OMX_AUDIO_PARAM_PDCFRTYPE)},
{OMX_AUDIO_CodingPDCEFR, OMX_IndexParamAudioPdc_EFR, sizeof(OMX_AUDIO_PARAM_PDCEFRTYPE)},
{OMX_AUDIO_CodingPDCHR, OMX_IndexParamAudioPdc_HR, sizeof(OMX_AUDIO_PARAM_PDCHRTYPE)},
{OMX_AUDIO_CodingTDMAFR, OMX_IndexParamAudioTdma_FR, sizeof(OMX_AUDIO_PARAM_TDMAFRTYPE)},
{OMX_AUDIO_CodingTDMAEFR, OMX_IndexParamAudioTdma_EFR, sizeof(OMX_AUDIO_PARAM_TDMAEFRTYPE)},
{OMX_AUDIO_CodingQCELP8, OMX_IndexParamAudioQcelp8, sizeof(OMX_AUDIO_PARAM_QCELP8TYPE)},
{OMX_AUDIO_CodingQCELP13, OMX_IndexParamAudioQcelp13, sizeof(OMX_AUDIO_PARAM_QCELP13TYPE)},
{OMX_AUDIO_CodingEVRC, OMX_IndexParamAudioEvrc, sizeof(OMX_AUDIO_PARAM_EVRCTYPE)},
{OMX_AUDIO_CodingSMV, OMX_IndexParamAudioSmv, sizeof(OMX_AUDIO_PARAM_SMVTYPE)},
{OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723, sizeof(OMX_AUDIO_PARAM_G723TYPE)},
{OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726, sizeof(OMX_AUDIO_PARAM_G726TYPE)},
{OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729, sizeof(OMX_AUDIO_PARAM_G729TYPE)},
{OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)},
{OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3, sizeof(OMX_AUDIO_PARAM_MP3TYPE)},
{OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc, sizeof(OMX_AUDIO_PARAM_SBCTYPE)},
{OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis, sizeof(OMX_AUDIO_PARAM_VORBISTYPE)},
{OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma, sizeof(OMX_AUDIO_PARAM_WMATYPE)},
{OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa, sizeof(OMX_AUDIO_PARAM_RATYPE)},
{OMX_AUDIO_CodingMIDI, OMX_IndexParamAudioMidi, sizeof(OMX_AUDIO_PARAM_MIDITYPE)},
{OMX_AUDIO_CodingDDP, OMX_IndexParamAudioDdp, sizeof(OMX_AUDIO_PARAM_DDPTYPE)},
{OMX_AUDIO_CodingDTS, OMX_IndexParamAudioDts, sizeof(OMX_AUDIO_PARAM_DTSTYPE)},
{OMX_AUDIO_CodingUnused, 0, 0}
};
OMX_AUDIO_CODINGTYPE mmalil_omx_audio_param_index_to_coding(OMX_INDEXTYPE index)
{
unsigned int i;
for(i = 0; mmal_omx_audio_format_table[i].coding != OMX_AUDIO_CodingUnused; i++)
if(mmal_omx_audio_format_table[i].index == index) break;
return mmal_omx_audio_format_table[i].coding;
}
OMX_INDEXTYPE mmalil_omx_audio_param_index(OMX_AUDIO_CODINGTYPE coding, OMX_U32 *size)
{
unsigned int i;
for(i = 0; mmal_omx_audio_format_table[i].coding != OMX_AUDIO_CodingUnused; i++)
if(mmal_omx_audio_format_table[i].coding == coding) break;
if(size) *size = mmal_omx_audio_format_table[i].size;
return mmal_omx_audio_format_table[i].index;
}
MMAL_STATUS_T mmalil_omx_default_channel_mapping(OMX_AUDIO_CHANNELTYPE *channel_mapping, unsigned int nchannels)
{
static const OMX_AUDIO_CHANNELTYPE default_mapping[][8] = {
{OMX_AUDIO_ChannelNone},
{OMX_AUDIO_ChannelCF},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF,
OMX_AUDIO_ChannelCS},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF,
OMX_AUDIO_ChannelLR, OMX_AUDIO_ChannelRR},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF,
OMX_AUDIO_ChannelLFE, OMX_AUDIO_ChannelLR, OMX_AUDIO_ChannelRR},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF,
OMX_AUDIO_ChannelLFE, OMX_AUDIO_ChannelLR, OMX_AUDIO_ChannelRR,
OMX_AUDIO_ChannelCS},
{OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF, OMX_AUDIO_ChannelCF,
OMX_AUDIO_ChannelLFE, OMX_AUDIO_ChannelLR, OMX_AUDIO_ChannelRR,
OMX_AUDIO_ChannelLS, OMX_AUDIO_ChannelRS}
};
if (!nchannels || nchannels + 1 >= MMAL_COUNTOF(default_mapping))
return MMAL_EINVAL;
memcpy(channel_mapping, default_mapping[nchannels],
sizeof(default_mapping[0][0]) * nchannels);
return MMAL_SUCCESS;
}
MMAL_FOURCC_T mmalil_omx_audio_param_to_format(MMAL_ES_FORMAT_T *format,
OMX_AUDIO_CODINGTYPE coding, OMX_FORMAT_PARAM_TYPE *param)
{
MMAL_AUDIO_FORMAT_T *audio = &format->es->audio;
format->encoding = mmalil_omx_audio_coding_to_encoding(coding);
format->encoding_variant = 0;
switch(coding)
{
case OMX_AUDIO_CodingPCM:
audio->channels = param->pcm.nChannels;
audio->sample_rate = param->pcm.nSamplingRate;
audio->bits_per_sample = param->pcm.nBitPerSample;
if(param->pcm.ePCMMode == OMX_AUDIO_PCMModeLinear && param->pcm.bInterleaved)
{
if(param->pcm.eEndian == OMX_EndianBig &&
param->pcm.eNumData == OMX_NumericalDataSigned)
format->encoding = MMAL_ENCODING_PCM_SIGNED_BE;
else if(param->pcm.eEndian == OMX_EndianLittle &&
param->pcm.eNumData == OMX_NumericalDataSigned)
format->encoding = MMAL_ENCODING_PCM_SIGNED_LE;
if(param->pcm.eEndian == OMX_EndianBig &&
param->pcm.eNumData == OMX_NumericalDataUnsigned)
format->encoding = MMAL_ENCODING_PCM_UNSIGNED_BE;
if(param->pcm.eEndian == OMX_EndianLittle &&
param->pcm.eNumData == OMX_NumericalDataUnsigned)
format->encoding = MMAL_ENCODING_PCM_UNSIGNED_LE;
}
else if(param->pcm.ePCMMode == OMX_AUDIO_PCMModeALaw)
format->encoding = MMAL_ENCODING_ALAW;
else if(param->pcm.ePCMMode == OMX_AUDIO_PCMModeMULaw)
format->encoding = MMAL_ENCODING_MULAW;
break;
case OMX_AUDIO_CodingAAC:
audio->channels = param->aac.nChannels;
audio->sample_rate = param->aac.nSampleRate;
format->bitrate = param->aac.nBitRate;
switch(param->aac.eAACStreamFormat)
{
case OMX_AUDIO_AACStreamFormatMP2ADTS:
case OMX_AUDIO_AACStreamFormatMP4ADTS:
format->encoding = MMAL_ENCODING_MP4A;
format->encoding_variant = MMAL_ENCODING_VARIANT_MP4A_ADTS;
break;
case OMX_AUDIO_AACStreamFormatMP4FF:
case OMX_AUDIO_AACStreamFormatRAW:
format->encoding = MMAL_ENCODING_MP4A;
format->encoding_variant = MMAL_ENCODING_VARIANT_MP4A_DEFAULT;
break;
default: break;
}
break;
case OMX_AUDIO_CodingMP3:
format->encoding = MMAL_ENCODING_MPGA;
audio->channels = param->mp3.nChannels;
audio->sample_rate = param->mp3.nSampleRate;
format->bitrate = param->mp3.nBitRate;
break;
case OMX_AUDIO_CodingWMA:
audio->channels = param->wma.nChannels;
audio->sample_rate = param->wma.nSamplingRate;
audio->block_align = param->wma.nBlockAlign;
format->bitrate = param->wma.nBitRate;
switch(param->wma.eFormat)
{
case OMX_AUDIO_WMAFormat7:
format->encoding = MMAL_ENCODING_WMA1;
break;
case OMX_AUDIO_WMAFormat8:
case OMX_AUDIO_WMAFormat9:
format->encoding = MMAL_ENCODING_WMA2;
break;
default: break;
}
break;
case OMX_AUDIO_CodingVORBIS:
audio->channels = param->vorbis.nChannels;
audio->sample_rate = param->vorbis.nSampleRate;
format->bitrate = param->vorbis.nBitRate;
break;
case OMX_AUDIO_CodingAMR:
audio->channels = param->amr.nChannels;
audio->sample_rate = 8000;
format->bitrate = param->amr.nBitRate;
if(param->amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0 &&
param->amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7)
format->encoding = MMAL_ENCODING_AMRNB;
if(param->amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0 &&
param->amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8)
format->encoding = MMAL_ENCODING_AMRWB;
break;
case OMX_AUDIO_CodingDDP:
audio->channels = param->ddp.nChannels;
audio->sample_rate = param->ddp.nSampleRate;
if(param->ddp.eBitStreamId > OMX_AUDIO_DDPBitStreamIdAC3)
format->encoding = MMAL_ENCODING_EAC3;
break;
case OMX_AUDIO_CodingDTS:
audio->channels = param->dts.nChannels;
audio->sample_rate = param->dts.nSampleRate;
audio->block_align = param->dts.nDtsFrameSizeBytes;
break;
case OMX_AUDIO_CodingADPCM:
case OMX_AUDIO_CodingGSMFR:
case OMX_AUDIO_CodingGSMEFR:
case OMX_AUDIO_CodingGSMHR:
case OMX_AUDIO_CodingPDCFR:
case OMX_AUDIO_CodingPDCEFR:
case OMX_AUDIO_CodingPDCHR:
case OMX_AUDIO_CodingTDMAFR:
case OMX_AUDIO_CodingTDMAEFR:
case OMX_AUDIO_CodingQCELP8:
case OMX_AUDIO_CodingQCELP13:
case OMX_AUDIO_CodingEVRC:
case OMX_AUDIO_CodingSMV:
case OMX_AUDIO_CodingG711:
case OMX_AUDIO_CodingG723:
case OMX_AUDIO_CodingG726:
case OMX_AUDIO_CodingG729:
case OMX_AUDIO_CodingSBC:
case OMX_AUDIO_CodingRA:
case OMX_AUDIO_CodingMIDI:
default:
vcos_assert(0);
break;
}
return format->encoding;
}
OMX_AUDIO_CODINGTYPE mmalil_format_to_omx_audio_param(OMX_FORMAT_PARAM_TYPE *param,
OMX_INDEXTYPE *param_index, MMAL_ES_FORMAT_T *format)
{
MMAL_AUDIO_FORMAT_T *audio = &format->es->audio;
OMX_AUDIO_CODINGTYPE coding = mmalil_encoding_to_omx_audio_coding(format->encoding);
OMX_U32 size = 0;
OMX_INDEXTYPE index = mmalil_omx_audio_param_index(coding, &size);
if(param_index) *param_index = index;
memset(param, 0, size);
param->common.nSize = size;
switch(coding)
{
case OMX_AUDIO_CodingPCM:
param->pcm.nChannels = audio->channels;
param->pcm.nSamplingRate = audio->sample_rate;
param->pcm.nBitPerSample = audio->bits_per_sample;
mmalil_omx_default_channel_mapping(param->pcm.eChannelMapping, audio->channels);
if(format->encoding == MMAL_ENCODING_PCM_SIGNED_BE ||
format->encoding == MMAL_ENCODING_PCM_SIGNED_LE ||
format->encoding == MMAL_ENCODING_PCM_UNSIGNED_BE ||
format->encoding == MMAL_ENCODING_PCM_UNSIGNED_LE)
{
param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
param->pcm.bInterleaved = OMX_TRUE;
param->pcm.eEndian = OMX_EndianLittle;
param->pcm.eNumData = OMX_NumericalDataSigned;
if(format->encoding == MMAL_ENCODING_PCM_SIGNED_BE ||
format->encoding == MMAL_ENCODING_PCM_UNSIGNED_BE)
param->pcm.eEndian = OMX_EndianBig;
if(format->encoding == MMAL_ENCODING_PCM_UNSIGNED_LE ||
format->encoding == MMAL_ENCODING_PCM_UNSIGNED_BE)
param->pcm.eNumData = OMX_NumericalDataUnsigned;
}
else if(format->encoding == MMAL_ENCODING_ALAW)
param->pcm.ePCMMode = OMX_AUDIO_PCMModeALaw;
else if(format->encoding == MMAL_ENCODING_MULAW)
param->pcm.ePCMMode = OMX_AUDIO_PCMModeMULaw;
break;
case OMX_AUDIO_CodingAAC:
param->aac.nChannels = audio->channels;
param->aac.nSampleRate = audio->sample_rate;
param->aac.nBitRate = format->bitrate;
switch(format->encoding_variant)
{
case MMAL_ENCODING_VARIANT_MP4A_ADTS:
param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
break;
case MMAL_ENCODING_VARIANT_MP4A_DEFAULT:
param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
break;
default: break;
}
break;
case OMX_AUDIO_CodingMP3:
param->mp3.nChannels = audio->channels;
param->mp3.nSampleRate = audio->sample_rate;
param->mp3.nBitRate = format->bitrate;
break;
case OMX_AUDIO_CodingWMA:
param->wma.nChannels = audio->channels;
param->wma.nSamplingRate = audio->sample_rate;
param->wma.nBlockAlign = audio->block_align;
param->wma.nBitRate = format->bitrate;
switch(format->encoding)
{
case MMAL_ENCODING_WMA1:
param->wma.eFormat = OMX_AUDIO_WMAFormat7;
break;
case MMAL_ENCODING_WMA2:
param->wma.eFormat = OMX_AUDIO_WMAFormat8;
break;
default: break;
}
break;
case OMX_AUDIO_CodingVORBIS:
param->vorbis.nChannels = audio->channels;
param->vorbis.nSampleRate = audio->sample_rate;
param->vorbis.nBitRate = format->bitrate;
break;
case OMX_AUDIO_CodingAMR:
param->amr.nChannels = audio->channels;
param->amr.nBitRate = format->bitrate;
if(format->encoding == MMAL_ENCODING_AMRNB)
param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
if(format->encoding == MMAL_ENCODING_AMRWB)
param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
break;
case OMX_AUDIO_CodingDDP:
param->ddp.nChannels = audio->channels;
param->ddp.nSampleRate = audio->sample_rate;
param->ddp.eBitStreamId = OMX_AUDIO_DDPBitStreamIdAC3;
if(format->encoding == MMAL_ENCODING_EAC3)
param->ddp.eBitStreamId = OMX_AUDIO_DDPBitStreamIdEAC3;
param->ddp.eBitStreamMode = 0;
param->ddp.eDolbySurroundMode = 0;
mmalil_omx_default_channel_mapping(param->ddp.eChannelMapping, audio->channels);
break;
case OMX_AUDIO_CodingDTS:
param->dts.nChannels = audio->channels;
param->dts.nSampleRate = audio->sample_rate;
param->dts.nDtsFrameSizeBytes = audio->block_align;
param->dts.nDtsType = 1;
param->dts.nFormat = 0;
mmalil_omx_default_channel_mapping(param->dts.eChannelMapping, audio->channels);
break;
case OMX_AUDIO_CodingADPCM:
case OMX_AUDIO_CodingGSMFR:
case OMX_AUDIO_CodingGSMEFR:
case OMX_AUDIO_CodingGSMHR:
case OMX_AUDIO_CodingPDCFR:
case OMX_AUDIO_CodingPDCEFR:
case OMX_AUDIO_CodingPDCHR:
case OMX_AUDIO_CodingTDMAFR:
case OMX_AUDIO_CodingTDMAEFR:
case OMX_AUDIO_CodingQCELP8:
case OMX_AUDIO_CodingQCELP13:
case OMX_AUDIO_CodingEVRC:
case OMX_AUDIO_CodingSMV:
case OMX_AUDIO_CodingG711:
case OMX_AUDIO_CodingG723:
case OMX_AUDIO_CodingG726:
case OMX_AUDIO_CodingG729:
case OMX_AUDIO_CodingSBC:
case OMX_AUDIO_CodingRA:
case OMX_AUDIO_CodingMIDI:
default:
vcos_assert(0);
break;
}
return coding;
}
/*****************************************************************************/
static struct {
uint32_t encoding;
OMX_VIDEO_CODINGTYPE coding;
} mmal_omx_video_coding_table[] =
{
{MMAL_ENCODING_H264, OMX_VIDEO_CodingAVC},
{MMAL_ENCODING_MP4V, OMX_VIDEO_CodingMPEG4},
{MMAL_ENCODING_MP2V, OMX_VIDEO_CodingMPEG2},
{MMAL_ENCODING_MP1V, OMX_VIDEO_CodingMPEG2},
{MMAL_ENCODING_H263, OMX_VIDEO_CodingH263},
{MMAL_ENCODING_WMV3, OMX_VIDEO_CodingWMV},
{MMAL_ENCODING_WMV2, OMX_VIDEO_CodingWMV},
{MMAL_ENCODING_WMV1, OMX_VIDEO_CodingWMV},
{MMAL_ENCODING_WVC1, OMX_VIDEO_CodingWMV},
{MMAL_ENCODING_VP6, OMX_VIDEO_CodingVP6},
{MMAL_ENCODING_VP7, OMX_VIDEO_CodingVP7},
{MMAL_ENCODING_VP8, OMX_VIDEO_CodingVP8},
{MMAL_ENCODING_SPARK, OMX_VIDEO_CodingSorenson},
{MMAL_ENCODING_THEORA, OMX_VIDEO_CodingTheora},
{MMAL_ENCODING_MJPEG, OMX_VIDEO_CodingMJPEG},
{MMAL_ENCODING_UNKNOWN, OMX_VIDEO_CodingUnused}
};
uint32_t mmalil_omx_video_coding_to_encoding(OMX_VIDEO_CODINGTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_video_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_video_coding_table[i].coding == coding) break;
return mmal_omx_video_coding_table[i].encoding;
}
OMX_VIDEO_CODINGTYPE mmalil_encoding_to_omx_video_coding(uint32_t encoding)
{
unsigned int i;
for(i = 0; mmal_omx_video_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_video_coding_table[i].encoding == encoding) break;
return mmal_omx_video_coding_table[i].coding;
}
/*****************************************************************************/
static struct {
uint32_t encoding;
OMX_IMAGE_CODINGTYPE coding;
} mmal_omx_image_coding_table[] =
{
{MMAL_ENCODING_JPEG, OMX_IMAGE_CodingJPEG},
{MMAL_ENCODING_GIF, OMX_IMAGE_CodingGIF},
{MMAL_ENCODING_PNG, OMX_IMAGE_CodingPNG},
{MMAL_ENCODING_BMP, OMX_IMAGE_CodingBMP},
{MMAL_ENCODING_TGA, OMX_IMAGE_CodingTGA},
{MMAL_ENCODING_PPM, OMX_IMAGE_CodingPPM},
{MMAL_ENCODING_UNKNOWN, OMX_IMAGE_CodingUnused}
};
uint32_t mmalil_omx_image_coding_to_encoding(OMX_IMAGE_CODINGTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_image_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_image_coding_table[i].coding == coding) break;
return mmal_omx_image_coding_table[i].encoding;
}
OMX_IMAGE_CODINGTYPE mmalil_encoding_to_omx_image_coding(uint32_t encoding)
{
unsigned int i;
for(i = 0; mmal_omx_image_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_image_coding_table[i].encoding == encoding) break;
return mmal_omx_image_coding_table[i].coding;
}
uint32_t mmalil_omx_coding_to_encoding(uint32_t encoding, OMX_PORTDOMAINTYPE domain)
{
if(domain == OMX_PortDomainVideo)
return mmalil_omx_video_coding_to_encoding((OMX_VIDEO_CODINGTYPE)encoding);
else if(domain == OMX_PortDomainAudio)
return mmalil_omx_audio_coding_to_encoding((OMX_AUDIO_CODINGTYPE)encoding);
else if(domain == OMX_PortDomainImage)
return mmalil_omx_image_coding_to_encoding((OMX_IMAGE_CODINGTYPE)encoding);
else
return MMAL_ENCODING_UNKNOWN;
}
/*****************************************************************************/
static struct {
uint32_t encoding;
OMX_COLOR_FORMATTYPE coding;
} mmal_omx_colorformat_coding_table[] =
{
{MMAL_ENCODING_I420, OMX_COLOR_FormatYUV420PackedPlanar},
{MMAL_ENCODING_I422, OMX_COLOR_FormatYUV422PackedPlanar},
{MMAL_ENCODING_I420_SLICE, OMX_COLOR_FormatYUV420PackedPlanar},
{MMAL_ENCODING_I422_SLICE, OMX_COLOR_FormatYUV422PackedPlanar},
{MMAL_ENCODING_I420, OMX_COLOR_FormatYUV420Planar},
{MMAL_ENCODING_YV12, OMX_COLOR_FormatYVU420PackedPlanar},
{MMAL_ENCODING_NV12, OMX_COLOR_FormatYUV420PackedSemiPlanar},
{MMAL_ENCODING_NV12, OMX_COLOR_FormatYUV420SemiPlanar},
{MMAL_ENCODING_NV21, OMX_COLOR_FormatYVU420PackedSemiPlanar},
{MMAL_ENCODING_YUVUV128, OMX_COLOR_FormatYUVUV128},
{MMAL_ENCODING_YUYV, OMX_COLOR_FormatYCbYCr},
{MMAL_ENCODING_YVYU, OMX_COLOR_FormatYCrYCb},
{MMAL_ENCODING_UYVY, OMX_COLOR_FormatCbYCrY},
{MMAL_ENCODING_VYUY, OMX_COLOR_FormatCrYCbY},
{MMAL_ENCODING_RGB16, OMX_COLOR_Format16bitRGB565},
{MMAL_ENCODING_BGR24, OMX_COLOR_Format24bitRGB888},
{MMAL_ENCODING_BGRA, OMX_COLOR_Format32bitARGB8888},
{MMAL_ENCODING_BGR16, OMX_COLOR_Format16bitBGR565},
{MMAL_ENCODING_RGB24, OMX_COLOR_Format24bitBGR888},
{MMAL_ENCODING_ARGB, OMX_COLOR_Format32bitBGRA8888},
{MMAL_ENCODING_RGBA, OMX_COLOR_Format32bitABGR8888},
{MMAL_ENCODING_EGL_IMAGE, OMX_COLOR_FormatBRCMEGL},
{MMAL_ENCODING_OPAQUE, OMX_COLOR_FormatBRCMOpaque},
{MMAL_ENCODING_UNKNOWN, OMX_COLOR_FormatUnused}
};
uint32_t mmalil_omx_color_format_to_encoding(OMX_COLOR_FORMATTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_colorformat_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_colorformat_coding_table[i].coding == coding) break;
return mmal_omx_colorformat_coding_table[i].encoding;
}
OMX_COLOR_FORMATTYPE mmalil_encoding_to_omx_color_format(uint32_t encoding)
{
unsigned int i;
for(i = 0; mmal_omx_colorformat_coding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(mmal_omx_colorformat_coding_table[i].encoding == encoding) break;
return mmal_omx_colorformat_coding_table[i].coding;
}
/*****************************************************************************/
static struct {
uint32_t mmal;
OMX_COLORSPACETYPE omx;
} mmal_omx_colorspace_coding_table[] =
{
{MMAL_COLOR_SPACE_ITUR_BT601, OMX_COLORSPACE_ITU_R_BT601},
{MMAL_COLOR_SPACE_ITUR_BT709, OMX_COLORSPACE_ITU_R_BT709},
{MMAL_COLOR_SPACE_JPEG_JFIF, OMX_COLORSPACE_JPEG_JFIF},
{MMAL_COLOR_SPACE_FCC, OMX_COLORSPACE_FCC},
{MMAL_COLOR_SPACE_SMPTE240M, OMX_COLORSPACE_SMPTE240M},
{MMAL_COLOR_SPACE_BT470_2_M, OMX_COLORSPACE_BT470_2_M},
{MMAL_COLOR_SPACE_BT470_2_BG, OMX_COLORSPACE_BT470_2_BG},
{MMAL_COLOR_SPACE_JFIF_Y16_255, OMX_COLORSPACE_JFIF_Y16_255},
{MMAL_COLOR_SPACE_UNKNOWN, OMX_COLORSPACE_UNKNOWN}
};
uint32_t mmalil_omx_color_space_to_mmal(OMX_COLORSPACETYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_colorspace_coding_table[i].mmal != MMAL_COLOR_SPACE_UNKNOWN; i++)
if(mmal_omx_colorspace_coding_table[i].omx == coding) break;
return mmal_omx_colorspace_coding_table[i].mmal;
}
OMX_COLORSPACETYPE mmalil_color_space_to_omx(uint32_t coding)
{
unsigned int i;
for(i = 0; mmal_omx_colorspace_coding_table[i].mmal != MMAL_COLOR_SPACE_UNKNOWN; i++)
if(mmal_omx_colorspace_coding_table[i].mmal == coding) break;
return mmal_omx_colorspace_coding_table[i].omx;
}
/*****************************************************************************/
static struct {
uint32_t mmal;
OMX_U32 omx;
OMX_VIDEO_CODINGTYPE omx_coding;
} mmal_omx_video_profile_table[] =
{
{ MMAL_VIDEO_PROFILE_H263_BASELINE, OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_H320CODING, OMX_VIDEO_H263ProfileH320Coding, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE, OMX_VIDEO_H263ProfileBackwardCompatible, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_ISWV2, OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_ISWV3, OMX_VIDEO_H263ProfileISWV3, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION, OMX_VIDEO_H263ProfileHighCompression, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_INTERNET, OMX_VIDEO_H263ProfileInternet, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_INTERLACE, OMX_VIDEO_H263ProfileInterlace, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_H263_HIGHLATENCY, OMX_VIDEO_H263ProfileHighLatency, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_PROFILE_MP4V_SIMPLE, OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE, OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_CORE, OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_MAIN, OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_NBIT, OMX_VIDEO_MPEG4ProfileNbit, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE, OMX_VIDEO_MPEG4ProfileScalableTexture, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE, OMX_VIDEO_MPEG4ProfileSimpleFace, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA, OMX_VIDEO_MPEG4ProfileSimpleFBA, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED, OMX_VIDEO_MPEG4ProfileBasicAnimated, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_HYBRID, OMX_VIDEO_MPEG4ProfileHybrid, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME, OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE, OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING, OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE, OMX_VIDEO_MPEG4ProfileAdvancedCore, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE, OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE, OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_PROFILE_H264_BASELINE, OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_MAIN, OMX_VIDEO_AVCProfileMain, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_EXTENDED, OMX_VIDEO_AVCProfileExtended, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_HIGH, OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_HIGH10, OMX_VIDEO_AVCProfileHigh10, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_HIGH422, OMX_VIDEO_AVCProfileHigh422, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_HIGH444, OMX_VIDEO_AVCProfileHigh444, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, OMX_VIDEO_AVCProfileConstrainedBaseline, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_PROFILE_DUMMY, OMX_VIDEO_AVCProfileMax, OMX_VIDEO_CodingAVC},
};
uint32_t mmalil_omx_video_profile_to_mmal(OMX_U32 profile, OMX_VIDEO_CODINGTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_video_profile_table[i].mmal != MMAL_VIDEO_PROFILE_DUMMY; i++)
if(mmal_omx_video_profile_table[i].omx == profile
&& mmal_omx_video_profile_table[i].omx_coding == coding) break;
return mmal_omx_video_profile_table[i].mmal;
}
OMX_U32 mmalil_video_profile_to_omx(uint32_t profile)
{
unsigned int i;
for(i = 0; mmal_omx_video_profile_table[i].mmal != MMAL_VIDEO_PROFILE_DUMMY; i++)
if(mmal_omx_video_profile_table[i].mmal == profile) break;
return mmal_omx_video_profile_table[i].omx;
}
/*****************************************************************************/
static struct {
uint32_t mmal;
OMX_U32 omx;
OMX_VIDEO_CODINGTYPE omx_coding;
} mmal_omx_video_level_table[] =
{
{ MMAL_VIDEO_LEVEL_H263_10, OMX_VIDEO_H263Level10, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_20, OMX_VIDEO_H263Level20, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_30, OMX_VIDEO_H263Level30, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_40, OMX_VIDEO_H263Level40, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_45, OMX_VIDEO_H263Level45, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_50, OMX_VIDEO_H263Level50, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_60, OMX_VIDEO_H263Level60, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_H263_70, OMX_VIDEO_H263Level70, OMX_VIDEO_CodingH263},
{ MMAL_VIDEO_LEVEL_MP4V_0, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_0b, OMX_VIDEO_MPEG4Level0b, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_1, OMX_VIDEO_MPEG4Level1, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_2, OMX_VIDEO_MPEG4Level2, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_3, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_4, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_4a, OMX_VIDEO_MPEG4Level4a, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_5, OMX_VIDEO_MPEG4Level5, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_MP4V_6, OMX_VIDEO_MPEG4Level6, OMX_VIDEO_CodingMPEG4},
{ MMAL_VIDEO_LEVEL_H264_1, OMX_VIDEO_AVCLevel1, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_1b, OMX_VIDEO_AVCLevel1b, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_11, OMX_VIDEO_AVCLevel11, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_12, OMX_VIDEO_AVCLevel12, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_13, OMX_VIDEO_AVCLevel13, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_2, OMX_VIDEO_AVCLevel2, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_21, OMX_VIDEO_AVCLevel21, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_22, OMX_VIDEO_AVCLevel22, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_3, OMX_VIDEO_AVCLevel3, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_31, OMX_VIDEO_AVCLevel31, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_32, OMX_VIDEO_AVCLevel32, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_4, OMX_VIDEO_AVCLevel4, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_41, OMX_VIDEO_AVCLevel41, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_42, OMX_VIDEO_AVCLevel42, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_5, OMX_VIDEO_AVCLevel5, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_H264_51, OMX_VIDEO_AVCLevel51, OMX_VIDEO_CodingAVC},
{ MMAL_VIDEO_LEVEL_DUMMY, OMX_VIDEO_AVCLevelMax, OMX_VIDEO_CodingMax},
};
uint32_t mmalil_omx_video_level_to_mmal(OMX_U32 level, OMX_VIDEO_CODINGTYPE coding)
{
unsigned int i;
for(i = 0; mmal_omx_video_level_table[i].mmal != MMAL_VIDEO_LEVEL_DUMMY; i++)
if(mmal_omx_video_level_table[i].omx == level
&& mmal_omx_video_level_table[i].omx_coding == coding) break;
return mmal_omx_video_level_table[i].mmal;
}
OMX_U32 mmalil_video_level_to_omx(uint32_t level)
{
unsigned int i;
for(i = 0; mmal_omx_video_level_table[i].mmal != MMAL_VIDEO_LEVEL_DUMMY; i++)
if(mmal_omx_video_level_table[i].mmal == level) break;
return mmal_omx_video_level_table[i].omx;
}
/*****************************************************************************/
static struct {
MMAL_VIDEO_RATECONTROL_T mmal;
OMX_VIDEO_CONTROLRATETYPE omx;
} mmal_omx_video_ratecontrol_table[] =
{
{ MMAL_VIDEO_RATECONTROL_DEFAULT, OMX_Video_ControlRateDisable},
{ MMAL_VIDEO_RATECONTROL_VARIABLE, OMX_Video_ControlRateVariable},
{ MMAL_VIDEO_RATECONTROL_CONSTANT, OMX_Video_ControlRateConstant},
{ MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES, OMX_Video_ControlRateVariableSkipFrames},
{ MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES, OMX_Video_ControlRateConstantSkipFrames},
{ MMAL_VIDEO_RATECONTROL_DUMMY, OMX_Video_ControlRateMax},
};
MMAL_VIDEO_RATECONTROL_T mmalil_omx_video_ratecontrol_to_mmal(OMX_VIDEO_CONTROLRATETYPE omx)
{
unsigned int i;
for(i = 0; mmal_omx_video_ratecontrol_table[i].mmal != MMAL_VIDEO_RATECONTROL_DUMMY; i++)
if(mmal_omx_video_ratecontrol_table[i].omx == omx) break;
return mmal_omx_video_ratecontrol_table[i].mmal;
}
OMX_VIDEO_CONTROLRATETYPE mmalil_video_ratecontrol_to_omx(MMAL_VIDEO_RATECONTROL_T mmal)
{
unsigned int i;
for(i = 0; mmal_omx_video_ratecontrol_table[i].mmal != MMAL_VIDEO_RATECONTROL_DUMMY; i++)
if(mmal_omx_video_ratecontrol_table[i].mmal == mmal) break;
return mmal_omx_video_ratecontrol_table[i].omx;
}
/*****************************************************************************/
static struct {
MMAL_VIDEO_INTRA_REFRESH_T mmal;
OMX_VIDEO_INTRAREFRESHTYPE omx;
} mmal_omx_video_intrarefresh_table[] =
{
{ MMAL_VIDEO_INTRA_REFRESH_CYCLIC, OMX_VIDEO_IntraRefreshCyclic},
{ MMAL_VIDEO_INTRA_REFRESH_ADAPTIVE, OMX_VIDEO_IntraRefreshAdaptive},
{ MMAL_VIDEO_INTRA_REFRESH_BOTH, OMX_VIDEO_IntraRefreshBoth},
{ MMAL_VIDEO_INTRA_REFRESH_KHRONOSEXTENSIONS, OMX_VIDEO_IntraRefreshKhronosExtensions},
{ MMAL_VIDEO_INTRA_REFRESH_VENDORSTARTUNUSED, OMX_VIDEO_IntraRefreshVendorStartUnused},
{ MMAL_VIDEO_INTRA_REFRESH_DUMMY, OMX_VIDEO_IntraRefreshMax},
};
MMAL_VIDEO_INTRA_REFRESH_T mmalil_omx_video_intrarefresh_to_mmal(OMX_VIDEO_INTRAREFRESHTYPE omx)
{
unsigned int i;
for(i = 0; mmal_omx_video_intrarefresh_table[i].mmal != MMAL_VIDEO_INTRA_REFRESH_DUMMY; i++)
if(mmal_omx_video_intrarefresh_table[i].omx == omx) break;
return mmal_omx_video_intrarefresh_table[i].mmal;
}
@@ -0,0 +1,212 @@
/*
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.
*/
#ifndef MMAL_IL_H
#define MMAL_IL_H
/** \defgroup MmalILUtility MMAL to OMX IL conversion utilities
* \ingroup MmalUtilities
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "interface/vmcs_host/khronos/IL/OMX_Core.h"
#include "interface/vmcs_host/khronos/IL/OMX_Component.h"
#include "interface/vmcs_host/khronos/IL/OMX_Video.h"
#include "interface/vmcs_host/khronos/IL/OMX_Audio.h"
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
/** Convert MMAL status codes into OMX error codes.
*
* @param status MMAL status code.
* @return OMX error code.
*/
OMX_ERRORTYPE mmalil_error_to_omx(MMAL_STATUS_T status);
/** Convert OMX error codes into MMAL status codes.
*
* @param error OMX error code.
* @return MMAL status code.
*/
MMAL_STATUS_T mmalil_error_to_mmal(OMX_ERRORTYPE error);
/** Convert MMAL buffer header flags into OMX buffer header flags.
*
* @param flags OMX buffer header flags.
* @return MMAL buffer header flags.
*/
uint32_t mmalil_buffer_flags_to_mmal(OMX_U32 flags);
/** Convert OMX buffer header flags into MMAL buffer header flags.
*
* @param flags MMAL buffer header flags.
* @return OMX buffer header flags.
*/
OMX_U32 mmalil_buffer_flags_to_omx(uint32_t flags);
/** Convert a MMAL buffer header into an OMX buffer header.
* Note that only the fields which have a direct mapping between OMX and MMAL are converted.
*
* @param omx Pointer to the destination OMX buffer header.
* @param mmal Pointer to the source MMAL buffer header.
*/
void mmalil_buffer_header_to_omx(OMX_BUFFERHEADERTYPE *omx, MMAL_BUFFER_HEADER_T *mmal);
/** Convert an OMX buffer header into a MMAL buffer header.
*
* @param mmal Pointer to the destination MMAL buffer header.
* @param omx Pointer to the source OMX buffer header.
*/
void mmalil_buffer_header_to_mmal(MMAL_BUFFER_HEADER_T *mmal, OMX_BUFFERHEADERTYPE *omx);
OMX_PORTDOMAINTYPE mmalil_es_type_to_omx_domain(MMAL_ES_TYPE_T type);
MMAL_ES_TYPE_T mmalil_omx_domain_to_es_type(OMX_PORTDOMAINTYPE domain);
uint32_t mmalil_omx_audio_coding_to_encoding(OMX_AUDIO_CODINGTYPE coding);
OMX_AUDIO_CODINGTYPE mmalil_encoding_to_omx_audio_coding(uint32_t encoding);
uint32_t mmalil_omx_video_coding_to_encoding(OMX_VIDEO_CODINGTYPE coding);
OMX_VIDEO_CODINGTYPE mmalil_encoding_to_omx_video_coding(uint32_t encoding);
uint32_t mmalil_omx_image_coding_to_encoding(OMX_IMAGE_CODINGTYPE coding);
OMX_IMAGE_CODINGTYPE mmalil_encoding_to_omx_image_coding(uint32_t encoding);
uint32_t mmalil_omx_coding_to_encoding(uint32_t encoding, OMX_PORTDOMAINTYPE domain);
uint32_t mmalil_omx_color_format_to_encoding(OMX_COLOR_FORMATTYPE coding);
OMX_COLOR_FORMATTYPE mmalil_encoding_to_omx_color_format(uint32_t encoding);
uint32_t mmalil_omx_color_space_to_mmal(OMX_COLORSPACETYPE coding);
OMX_COLORSPACETYPE mmalil_color_space_to_omx(uint32_t coding);
uint32_t mmalil_omx_video_profile_to_mmal(OMX_U32 level, OMX_VIDEO_CODINGTYPE coding);
OMX_U32 mmalil_video_profile_to_omx(uint32_t profile);
uint32_t mmalil_omx_video_level_to_mmal(OMX_U32 level, OMX_VIDEO_CODINGTYPE coding);
OMX_U32 mmalil_video_level_to_omx(uint32_t level);
MMAL_VIDEO_RATECONTROL_T mmalil_omx_video_ratecontrol_to_mmal(OMX_VIDEO_CONTROLRATETYPE omx);
OMX_VIDEO_CONTROLRATETYPE mmalil_video_ratecontrol_to_omx(MMAL_VIDEO_RATECONTROL_T mmal);
MMAL_VIDEO_INTRA_REFRESH_T mmalil_omx_video_intrarefresh_to_mmal(OMX_VIDEO_INTRAREFRESHTYPE omx);
/** Union of all the OMX_VIDEO/AUDIO_PARAM types */
typedef union OMX_FORMAT_PARAM_TYPE {
OMX_PARAM_U32TYPE common;
/* Video */
OMX_VIDEO_PARAM_AVCTYPE avc;
OMX_VIDEO_PARAM_H263TYPE h263;
OMX_VIDEO_PARAM_MPEG2TYPE mpeg2;
OMX_VIDEO_PARAM_MPEG4TYPE mpeg4;
OMX_VIDEO_PARAM_WMVTYPE wmv;
OMX_VIDEO_PARAM_RVTYPE rv;
/* Audio */
OMX_AUDIO_PARAM_PCMMODETYPE pcm;
OMX_AUDIO_PARAM_MP3TYPE mp3;
OMX_AUDIO_PARAM_AACPROFILETYPE aac;
OMX_AUDIO_PARAM_VORBISTYPE vorbis;
OMX_AUDIO_PARAM_WMATYPE wma;
OMX_AUDIO_PARAM_RATYPE ra;
OMX_AUDIO_PARAM_SBCTYPE sbc;
OMX_AUDIO_PARAM_ADPCMTYPE adpcm;
OMX_AUDIO_PARAM_G723TYPE g723;
OMX_AUDIO_PARAM_G726TYPE g726;
OMX_AUDIO_PARAM_G729TYPE g729;
OMX_AUDIO_PARAM_AMRTYPE amr;
OMX_AUDIO_PARAM_GSMFRTYPE gsmfr;
OMX_AUDIO_PARAM_GSMHRTYPE gsmhr;
OMX_AUDIO_PARAM_GSMEFRTYPE gsmefr;
OMX_AUDIO_PARAM_TDMAFRTYPE tdmafr;
OMX_AUDIO_PARAM_TDMAEFRTYPE tdmaefr;
OMX_AUDIO_PARAM_PDCFRTYPE pdcfr;
OMX_AUDIO_PARAM_PDCEFRTYPE pdcefr;
OMX_AUDIO_PARAM_PDCHRTYPE pdchr;
OMX_AUDIO_PARAM_QCELP8TYPE qcelp8;
OMX_AUDIO_PARAM_QCELP13TYPE qcelp13;
OMX_AUDIO_PARAM_EVRCTYPE evrc;
OMX_AUDIO_PARAM_SMVTYPE smv;
OMX_AUDIO_PARAM_MIDITYPE midi;
#ifdef OMX_AUDIO_CodingDDP_Supported
OMX_AUDIO_PARAM_DDPTYPE ddp;
#endif
#ifdef OMX_AUDIO_CodingDTS_Supported
OMX_AUDIO_PARAM_DTSTYPE dts;
#endif
} OMX_FORMAT_PARAM_TYPE;
/** Get the OMX_IndexParamAudio index corresponding to a specified audio coding type.
*
* @param coding Audio coding type.
* @param size Pointer used to return the size of the parameter.
*
* @return OMX index or 0 if no match was found.
*/
OMX_INDEXTYPE mmalil_omx_audio_param_index(OMX_AUDIO_CODINGTYPE coding, OMX_U32 *size);
/** Get the audio coding corresponding to a specified OMX_IndexParamAudio index.
*
* @param index Audio coding type.
*
* @return Audio coding type.
*/
OMX_AUDIO_CODINGTYPE mmalil_omx_audio_param_index_to_coding(OMX_INDEXTYPE index);
/** Setup a default channel mapping based on the number of channels
* @param channel_mapping The output channel mapping
* @param nchannels Number of channels
*
* @return MMAL_SUCCESS if we managed to produce a channel mapping
*/
MMAL_STATUS_T mmalil_omx_default_channel_mapping(OMX_AUDIO_CHANNELTYPE *channel_mapping, unsigned int nchannels);
/** Convert an OMX_IndexParamAudio into a MMAL elementary stream format.
*
* @param format Format structure to update.
* @param coding Audio coding type.
* @param param Source OMX_IndexParamAudio structure.
*
* @return The MMAL encoding if a match was found or MMAL_ENCODING_UNKNOWN otherwise.
*/
MMAL_FOURCC_T mmalil_omx_audio_param_to_format(MMAL_ES_FORMAT_T *format,
OMX_AUDIO_CODINGTYPE coding, OMX_FORMAT_PARAM_TYPE *param);
/** Convert a MMAL elementary stream format into a OMX_IndexParamAudio structure.
*
* @param param OMX_IndexParamAudio structure to update.
* @param param_index returns the OMX_IndexParamAudio index corresponding to the format.
* @param format Source format structure.
*
* @return The OMX aduio coding type if a match was found or OMX_AUDIO_CodingUnused otherwise.
*/
OMX_AUDIO_CODINGTYPE mmalil_format_to_omx_audio_param(OMX_FORMAT_PARAM_TYPE *param,
OMX_INDEXTYPE *param_index, MMAL_ES_FORMAT_T *format);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* MMAL_IL_H */
@@ -0,0 +1,221 @@
/*
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/vcos/vcos.h"
#include "interface/mmal/util/mmal_list.h"
/* Private list context */
typedef struct MMAL_LIST_PRIVATE_T
{
MMAL_LIST_T list; /* must be first */
VCOS_MUTEX_T lock;
} MMAL_LIST_PRIVATE_T;
/* Lock the list. */
static inline void mmal_list_lock(MMAL_LIST_T *list)
{
vcos_mutex_lock(&((MMAL_LIST_PRIVATE_T*)list)->lock);
}
/* Unlock the list. */
static inline void mmal_list_unlock(MMAL_LIST_T *list)
{
vcos_mutex_unlock(&((MMAL_LIST_PRIVATE_T*)list)->lock);
}
/* Create a new linked list. */
MMAL_LIST_T* mmal_list_create(void)
{
MMAL_LIST_PRIVATE_T *private;
private = vcos_malloc(sizeof(MMAL_LIST_PRIVATE_T), "mmal-list");
if (private == NULL)
goto error;
if (vcos_mutex_create(&private->lock, "mmal-list lock") != VCOS_SUCCESS)
goto error;
/* lock to keep coverity happy */
vcos_mutex_lock(&private->lock);
private->list.first = NULL;
private->list.last = NULL;
private->list.length = 0;
vcos_mutex_unlock(&private->lock);
return &private->list;
error:
vcos_free(private);
return NULL;
}
/* Destroy a linked list. */
void mmal_list_destroy(MMAL_LIST_T *list)
{
MMAL_LIST_PRIVATE_T *private = (MMAL_LIST_PRIVATE_T*)list;
vcos_mutex_delete(&private->lock);
vcos_free(private);
}
/* Remove the last element in the list. */
MMAL_LIST_ELEMENT_T* mmal_list_pop_back(MMAL_LIST_T *list)
{
MMAL_LIST_ELEMENT_T *element;
mmal_list_lock(list);
element = list->last;
if (element != NULL)
{
list->length--;
list->last = element->prev;
if (list->last)
list->last->next = NULL;
else
list->first = NULL; /* list is now empty */
element->prev = NULL;
element->next = NULL;
}
mmal_list_unlock(list);
return element;
}
/* Remove the first element in the list. */
MMAL_LIST_ELEMENT_T* mmal_list_pop_front(MMAL_LIST_T *list)
{
MMAL_LIST_ELEMENT_T *element;
mmal_list_lock(list);
element = list->first;
if (element != NULL)
{
list->length--;
list->first = element->next;
if (list->first)
list->first->prev = NULL;
else
list->last = NULL; /* list is now empty */
element->prev = NULL;
element->next = NULL;
}
mmal_list_unlock(list);
return element;
}
/* Add an element to the front of the list. */
void mmal_list_push_front(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element)
{
mmal_list_lock(list);
list->length++;
element->prev = NULL;
element->next = list->first;
if (list->first)
list->first->prev = element;
else
list->last = element; /* list was empty */
list->first = element;
mmal_list_unlock(list);
}
/* Add an element to the back of the list. */
void mmal_list_push_back(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element)
{
mmal_list_lock(list);
list->length++;
element->next = NULL;
element->prev = list->last;
if (list->last)
list->last->next = element;
else
list->first = element; /* list was empty */
list->last = element;
mmal_list_unlock(list);
}
/* Insert an element into the list. */
void mmal_list_insert(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element, MMAL_LIST_COMPARE_T compare)
{
MMAL_LIST_ELEMENT_T *cur;
mmal_list_lock(list);
if (list->first == NULL)
{
/* List empty */
mmal_list_unlock(list);
mmal_list_push_front(list, element);
return;
}
cur = list->first;
while (cur)
{
if (compare(element, cur))
{
/* Slot found! */
list->length++;
if (cur == list->first)
list->first = element;
else
cur->prev->next = element;
element->prev = cur->prev;
element->next = cur;
cur->prev = element;
mmal_list_unlock(list);
return;
}
cur = cur->next;
}
/* If we get here, none of the existing elements are greater
* than the new on, so just add it to the back of the list */
mmal_list_unlock(list);
mmal_list_push_back(list, element);
}
@@ -0,0 +1,127 @@
/*
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.
*/
#ifndef MMAL_LIST_H
#define MMAL_LIST_H
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup MmalList Generic Linked List
* This provides a thread-safe implementation of a linked list which can be used
* with any data type. */
/* @{ */
/** Single element in the list */
typedef struct MMAL_LIST_ELEMENT_T
{
struct MMAL_LIST_ELEMENT_T *next;
struct MMAL_LIST_ELEMENT_T *prev;
} MMAL_LIST_ELEMENT_T;
/** Linked list type.
* Clients shouldn't modify this directly. Use the provided API functions to
* add new elements. The public members are only for debug purposes.
* */
typedef struct MMAL_LIST_T
{
unsigned int length; /**< Number of elements in the list (read-only) */
MMAL_LIST_ELEMENT_T *first; /**< First element in the list (read-only) */
MMAL_LIST_ELEMENT_T *last; /**< Last element in the list (read-only) */
} MMAL_LIST_T;
/** Create a new linked list.
*
* @return Pointer to new queue (NULL on failure).
*/
MMAL_LIST_T* mmal_list_create(void);
/** Destroy a linked list.
*
* @param list List to destroy
*/
void mmal_list_destroy(MMAL_LIST_T *list);
/** Remove the last element in the list.
*
* @param list List to remove from
*
* @return Pointer to the last element (or NULL if empty)
*/
MMAL_LIST_ELEMENT_T* mmal_list_pop_back(MMAL_LIST_T *list);
/** Remove the first element in the list.
*
* @param list List to remove from
*
* @return Pointer to the first element (or NULL if empty)
*/
MMAL_LIST_ELEMENT_T* mmal_list_pop_front(MMAL_LIST_T *list);
/** Add an element to the front of the list.
*
* @param list List to add to
* @param element The element to add
*/
void mmal_list_push_front(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element);
/** Add an element to the back of the list.
*
* @param list List to add to
* @param element The element to add
*/
void mmal_list_push_back(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element);
/** List comparison function.
* This is supplied by a client when inserting an element in
* the middle of the list. The list will always insert a smaller
* element in front of a larger element.
*
* @return TRUE: lhs < rhs
* FALSE: lhs >= rhs
*/
typedef int (*MMAL_LIST_COMPARE_T)(MMAL_LIST_ELEMENT_T *lhs, MMAL_LIST_ELEMENT_T *rhs);
/** Insert an element into the list.
* The location where the element is inserted is determined using
* the supplied comparison function. Smaller elements are inserted
* in front of larger elements.
*
* @param list List to add to
* @param element The element to insert
* @param compare Comparison function supplied by the client
*/
void mmal_list_insert(MMAL_LIST_T *list, MMAL_LIST_ELEMENT_T *element, MMAL_LIST_COMPARE_T compare);
/* @} */
#ifdef __cplusplus
}
#endif
#endif /* MMAL_LIST_H */
@@ -0,0 +1,177 @@
/*
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 "mmal_param_convert.h"
#include <stdlib.h>
#include <stdio.h>
typedef struct string_pair_t
{
const char *string;
int value;
} string_pair_t;
static MMAL_STATUS_T parse_enum(int *dest, string_pair_t *pairs, size_t n_pairs, const char *str)
{
size_t i;
for (i=0; i<n_pairs; i++)
{
if (vcos_strcasecmp(str, pairs[i].string) == 0)
{
*dest = pairs[i].value;
return MMAL_SUCCESS;
}
i++;
}
return MMAL_EINVAL;
}
MMAL_STATUS_T mmal_parse_video_size(uint32_t *w, uint32_t *h, const char *str)
{
static struct {
const char *name;
uint32_t width;
uint32_t height;
} sizes[] = {
{ "1080p", 1920, 1080 },
{ "720p", 1280, 720 },
{ "vga", 640, 480 },
{ "wvga", 800, 480 },
{ "cif", 352, 288 },
{ "qcif", 352/2, 288/2 },
};
size_t i;
for (i=0; i<vcos_countof(sizes); i++)
{
if (vcos_strcasecmp(str, sizes[i].name) == 0)
{
*w = sizes[i].width;
*h = sizes[i].height;
return MMAL_SUCCESS;
}
}
return MMAL_EINVAL;
}
MMAL_STATUS_T mmal_parse_rational(MMAL_RATIONAL_T *dest, const char *str)
{
MMAL_STATUS_T ret;
char *endptr;
long num, den = 1;
num = strtoul(str, &endptr, 0);
if (endptr[0] == '\0')
{
/* that's it */
ret = MMAL_SUCCESS;
}
else if (endptr[0] == '/')
{
den = strtoul(endptr+1, &endptr, 0);
if (endptr[0] == '\0')
ret = MMAL_SUCCESS;
else
ret = MMAL_EINVAL;
}
else
{
ret = MMAL_EINVAL;
}
dest->num = num;
dest->den = den;
return ret;
}
MMAL_STATUS_T mmal_parse_int(int *dest, const char *str)
{
char *endptr;
long i = strtol(str, &endptr, 0);
if (endptr[0] == '\0')
{
*dest = i;
return MMAL_SUCCESS;
}
else
{
return MMAL_EINVAL;
}
}
MMAL_STATUS_T mmal_parse_uint(unsigned int *dest, const char *str)
{
char *endptr;
unsigned long i = strtoul(str, &endptr, 0);
if (endptr[0] == '\0')
{
*dest = i;
return MMAL_SUCCESS;
}
else
{
return MMAL_EINVAL;
}
}
MMAL_STATUS_T mmal_parse_video_codec(uint32_t *dest, const char *str)
{
static string_pair_t video_codec_enums[] = {
{ "h264", MMAL_ENCODING_H264 },
{ "h263", MMAL_ENCODING_H263 },
{ "mpeg4", MMAL_ENCODING_MP4V },
{ "mpeg2", MMAL_ENCODING_MP2V },
{ "vp8", MMAL_ENCODING_VP8 },
{ "vp7", MMAL_ENCODING_VP7 },
{ "vp6", MMAL_ENCODING_VP6 },
};
int i = 0;
MMAL_STATUS_T ret;
ret = parse_enum(&i, video_codec_enums, vcos_countof(video_codec_enums), str);
*dest = i;
return ret;
}
MMAL_STATUS_T mmal_parse_geometry(MMAL_RECT_T *dest, const char *str)
{
MMAL_STATUS_T ret;
uint32_t w, h, x, y;
x = y = w = h = 0;
/* coverity[secure_coding] */
if (sscanf(str, "%d*%d+%d+%d", &w,&h,&x,&y) == 4 ||
sscanf(str, "%d*%d", &w,&h) == 2)
{
dest->x = x;
dest->y = y;
dest->width = w;
dest->height = h;
ret = MMAL_SUCCESS;
}
else
{
ret = MMAL_EINVAL;
}
return ret;
}
@@ -0,0 +1,92 @@
/*
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.
*/
/** \file
* Support for setting/getting parameters as string values.
*/
#ifndef MMAL_PARAM_CONVERT_H
#define MMAL_PARAM_CONVERT_H
#include "interface/mmal/mmal.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Parse a video size. e.g. "1080p" gives 1920x1080.
*
* @param w width result
* @param h height result
* @param str string to convert
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_video_size(uint32_t *w, uint32_t *h, const char *str);
/** Parse a rational number. e.g. "30000/1001", "30", etc.
* @param dest filled in with result
* @param str string to convert
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_rational(MMAL_RATIONAL_T *dest, const char *str);
/** Parse an integer, e.g. -10, 0x1A, etc.
* @param dest filled in with result
* @param str string to convert
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_int(int *dest, const char *str);
/** Parse an unsigned integer, e.g. 10, 0x1A, etc.
* @param dest filled in with result
* @param str string to convert
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_uint(unsigned int *dest, const char *str);
/** Parse a geometry for a rectangle
*
* e.g. 100*100+50+75
* or 200*150
* @param dest filled in with result
* @param str string to convert
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_geometry(MMAL_RECT_T *dest, const char *str);
/** Parse a video codec name (something that can be encoded/decoded)
* @param str string to convert
* @param dest filled in with result
* @return MMAL_SUCCESS or error code
*/
MMAL_STATUS_T mmal_parse_video_codec(uint32_t *dest, const char *str);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,355 @@
/*
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/mmal/mmal.h"
#include "mmal_encodings.h"
#include "mmal_util.h"
#include "mmal_logging.h"
#include <string.h>
#include <stdio.h>
#define STATUS_TO_STR(x) { MMAL_##x, #x }
static struct {
MMAL_STATUS_T status;
const char *str;
} status_to_string_map[] =
{
STATUS_TO_STR(SUCCESS),
STATUS_TO_STR(ENOMEM),
STATUS_TO_STR(ENOSPC),
STATUS_TO_STR(EINVAL),
STATUS_TO_STR(ENOSYS),
STATUS_TO_STR(ENOENT),
STATUS_TO_STR(ENXIO),
STATUS_TO_STR(EIO),
STATUS_TO_STR(ESPIPE),
STATUS_TO_STR(ECORRUPT),
STATUS_TO_STR(ENOTREADY),
STATUS_TO_STR(ECONFIG),
{0, 0}
};
const char *mmal_status_to_string(MMAL_STATUS_T status)
{
unsigned i;
for (i=0; status_to_string_map[i].str; i++)
if (status_to_string_map[i].status == status)
break;
return status_to_string_map[i].str ? status_to_string_map[i].str : "UNKNOWN";
}
static struct {
uint32_t encoding;
uint32_t pitch_num;
uint32_t pitch_den;
} pixel_pitch[] =
{
{MMAL_ENCODING_I420, 1, 1},
{MMAL_ENCODING_YV12, 1, 1},
{MMAL_ENCODING_I422, 1, 1},
{MMAL_ENCODING_NV21, 1, 1},
{MMAL_ENCODING_NV12, 1, 1},
{MMAL_ENCODING_ARGB, 4, 1},
{MMAL_ENCODING_RGBA, 4, 1},
{MMAL_ENCODING_RGB32, 4, 1},
{MMAL_ENCODING_ABGR, 4, 1},
{MMAL_ENCODING_BGRA, 4, 1},
{MMAL_ENCODING_BGR32, 4, 1},
{MMAL_ENCODING_RGB16, 2, 1},
{MMAL_ENCODING_RGB24, 3, 1},
{MMAL_ENCODING_BGR16, 2, 1},
{MMAL_ENCODING_BGR24, 3, 1},
{MMAL_ENCODING_YUYV, 2, 1},
{MMAL_ENCODING_YVYU, 2, 1},
{MMAL_ENCODING_UYVY, 2, 1},
{MMAL_ENCODING_VYUY, 2, 1},
/* {MMAL_ENCODING_YUVUV128, 1, 1}, That's a special case which must not be included */
{MMAL_ENCODING_UNKNOWN, 0, 0}
};
uint32_t mmal_encoding_stride_to_width(uint32_t encoding, uint32_t stride)
{
unsigned int i;
for(i = 0; pixel_pitch[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(pixel_pitch[i].encoding == encoding) break;
if(pixel_pitch[i].encoding == MMAL_ENCODING_UNKNOWN)
return 0;
return pixel_pitch[i].pitch_den * stride / pixel_pitch[i].pitch_num;
}
uint32_t mmal_encoding_width_to_stride(uint32_t encoding, uint32_t width)
{
unsigned int i;
for(i = 0; pixel_pitch[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
if(pixel_pitch[i].encoding == encoding) break;
if(pixel_pitch[i].encoding == MMAL_ENCODING_UNKNOWN)
return 0;
return pixel_pitch[i].pitch_num * width / pixel_pitch[i].pitch_den;
}
const char* mmal_port_type_to_string(MMAL_PORT_TYPE_T type)
{
const char *str;
switch (type)
{
case MMAL_PORT_TYPE_INPUT: str = "in"; break;
case MMAL_PORT_TYPE_OUTPUT: str = "out"; break;
case MMAL_PORT_TYPE_CLOCK: str = "clk"; break;
case MMAL_PORT_TYPE_CONTROL: str = "ctr"; break;
default: str = "invalid"; break;
}
return str;
}
MMAL_PARAMETER_HEADER_T *mmal_port_parameter_alloc_get(MMAL_PORT_T *port,
uint32_t id, uint32_t size, MMAL_STATUS_T *p_status)
{
MMAL_PARAMETER_HEADER_T *param = NULL;
MMAL_STATUS_T status = MMAL_ENOSYS;
if (size < sizeof(MMAL_PARAMETER_HEADER_T))
size = sizeof(MMAL_PARAMETER_HEADER_T);
if ((param = vcos_calloc(1, size, "mmal_port_param_get")) == NULL)
{
status = MMAL_ENOMEM;
goto error;
}
param->id = id;
param->size = size;
if ((status = mmal_port_parameter_get(port, param)) == MMAL_ENOSPC)
{
/* We need to reallocate to get enough space for all parameter data */
size = param->size;
vcos_free(param);
if ((param = vcos_calloc(1, size, "mmal_port_param_get")) == NULL)
{
status = MMAL_ENOMEM;
goto error;
}
/* Now retrieve it again */
param->id = id;
param->size = size;
status = mmal_port_parameter_get(port, param);
}
if (status != MMAL_SUCCESS)
goto error;
end:
if (p_status) *p_status = status;
return param;
error:
if (param) vcos_free(param);
param = NULL;
goto end;
}
void mmal_port_parameter_free(MMAL_PARAMETER_HEADER_T *param)
{
vcos_free(param);
}
/** Copy buffer header metadata from source to dest
*/
void mmal_buffer_header_copy_header(MMAL_BUFFER_HEADER_T *dest, const MMAL_BUFFER_HEADER_T *src)
{
dest->cmd = src->cmd;
dest->offset = src->offset;
dest->length = src->length;
dest->flags = src->flags;
dest->pts = src->pts;
dest->dts = src->dts;
*dest->type = *src->type;
}
/** Create a pool of MMAL_BUFFER_HEADER_T */
MMAL_POOL_T *mmal_port_pool_create(MMAL_PORT_T *port, unsigned int headers, uint32_t payload_size)
{
if (!port || !port->priv)
return NULL;
LOG_TRACE("%s(%i:%i) port %p, headers %u, size %i", port->component->name,
(int)port->type, (int)port->index, port, headers, (int)payload_size);
/* Create a pool and ask the port for some memory */
return mmal_pool_create_with_allocator(headers, payload_size, (void *)port,
(mmal_pool_allocator_alloc_t)mmal_port_payload_alloc,
(mmal_pool_allocator_free_t)mmal_port_payload_free);
}
/** Destroy a pool of MMAL_BUFFER_HEADER_T */
void mmal_port_pool_destroy(MMAL_PORT_T *port, MMAL_POOL_T *pool)
{
if (!port || !port->priv || !pool)
return;
LOG_TRACE("%s(%i:%i) port %p, pool %p", port->component->name,
(int)port->type, (int)port->index, port, pool);
if (!vcos_verify(!port->is_enabled))
{
LOG_ERROR("port %p, pool %p destroyed while port enabled", port, pool);
mmal_port_disable(port);
}
mmal_pool_destroy(pool);
}
/*****************************************************************************/
void mmal_log_dump_port(MMAL_PORT_T *port)
{
if (!port)
return;
LOG_DEBUG("%s(%p)", port->name, port);
mmal_log_dump_format(port->format);
LOG_DEBUG(" buffers num: %i(opt %i, min %i), size: %i(opt %i, min: %i), align: %i",
port->buffer_num, port->buffer_num_recommended, port->buffer_num_min,
port->buffer_size, port->buffer_size_recommended, port->buffer_size_min,
port->buffer_alignment_min);
}
/*****************************************************************************/
void mmal_log_dump_format(MMAL_ES_FORMAT_T *format)
{
const char *name_type;
if (!format)
return;
switch(format->type)
{
case MMAL_ES_TYPE_AUDIO: name_type = "audio"; break;
case MMAL_ES_TYPE_VIDEO: name_type = "video"; break;
case MMAL_ES_TYPE_SUBPICTURE: name_type = "subpicture"; break;
default: name_type = "unknown"; break;
}
LOG_DEBUG("type: %s, fourcc: %4.4s", name_type, (char *)&format->encoding);
LOG_DEBUG(" bitrate: %i, framed: %i", format->bitrate,
!!(format->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
LOG_DEBUG(" extra data: %i, %p", format->extradata_size, format->extradata);
switch(format->type)
{
case MMAL_ES_TYPE_AUDIO:
LOG_DEBUG(" samplerate: %i, channels: %i, bps: %i, block align: %i",
format->es->audio.sample_rate, format->es->audio.channels,
format->es->audio.bits_per_sample, format->es->audio.block_align);
break;
case MMAL_ES_TYPE_VIDEO:
LOG_DEBUG(" width: %i, height: %i, (%i,%i,%i,%i)",
format->es->video.width, format->es->video.height,
format->es->video.crop.x, format->es->video.crop.y,
format->es->video.crop.width, format->es->video.crop.height);
LOG_DEBUG(" pixel aspect ratio: %i/%i, frame rate: %i/%i",
format->es->video.par.num, format->es->video.par.den,
format->es->video.frame_rate.num, format->es->video.frame_rate.den);
break;
case MMAL_ES_TYPE_SUBPICTURE:
break;
default: break;
}
}
MMAL_PORT_T *mmal_util_get_port(MMAL_COMPONENT_T *comp, MMAL_PORT_TYPE_T type, unsigned index)
{
unsigned num;
MMAL_PORT_T **list;
switch (type)
{
case MMAL_PORT_TYPE_INPUT:
num = comp->input_num;
list = comp->input;
break;
case MMAL_PORT_TYPE_OUTPUT:
num = comp->output_num;
list = comp->output;
break;
case MMAL_PORT_TYPE_CLOCK:
num = comp->clock_num;
list = comp->clock;
break;
case MMAL_PORT_TYPE_CONTROL:
num = 1;
list = &comp->control;
break;
default:
vcos_assert(0);
return NULL;
}
if (index < num)
/* coverity[ptr_arith] num is 1 here */
return list[index];
else
return NULL;
}
char *mmal_4cc_to_string(char *buf, size_t len, uint32_t fourcc)
{
char *src = (char*)&fourcc;
vcos_assert(len >= 5);
if (len < 5)
{
buf[0] = '\0';
}
else if (fourcc)
{
memcpy(buf, src, 4);
buf[4] = '\0';
}
else
{
snprintf(buf, len, "<0>");
}
return buf;
}
@@ -0,0 +1,184 @@
/*
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.
*/
#ifndef MMAL_UTIL_H
#define MMAL_UTIL_H
#include "mmal.h"
/** \defgroup MmalUtilities Utility functions
* The utility functions provide helpers for common functionality that is not part
* of the core MMAL API.
* @{
*/
/** Offset in bytes of FIELD in TYPE. */
#define MMAL_OFFSET(TYPE, FIELD) ((size_t)((uint8_t *)&((TYPE*)0)->FIELD - (uint8_t *)0))
#ifdef __cplusplus
extern "C" {
#endif
/** Convert a status to a statically-allocated string.
*
* @param status The MMAL status code.
* @return A C string describing the status code.
*/
const char *mmal_status_to_string(MMAL_STATUS_T status);
/** Convert stride to pixel width for a given pixel encoding.
*
* @param encoding The pixel encoding (such as one of the \ref MmalEncodings "pre-defined encodings")
* @param stride The stride in bytes.
* @return The width in pixels.
*/
uint32_t mmal_encoding_stride_to_width(uint32_t encoding, uint32_t stride);
/** Convert pixel width to stride for a given pixel encoding
*
* @param encoding The pixel encoding (such as one of the \ref MmalEncodings "pre-defined encodings")
* @param width The width in pixels.
* @return The stride in bytes.
*/
uint32_t mmal_encoding_width_to_stride(uint32_t encoding, uint32_t width);
/** Convert a port type to a string.
*
* @param type The MMAL port type.
* @return A NULL-terminated string describing the port type.
*/
const char* mmal_port_type_to_string(MMAL_PORT_TYPE_T type);
/** Get a parameter from a port allocating the required amount of memory
* for the parameter (i.e. for variable length parameters like URI or arrays).
* The size field will be set on output to the actual size of the
* parameter allocated and retrieved.
*
* The pointer returned must be released by a call to \ref mmal_port_parameter_free().
*
* @param port port to send request to
* @param id parameter id
* @param size initial size hint for allocation (can be 0)
* @param status status of the parameter get operation (can be 0)
* @return pointer to the header of the parameter or NULL on failure.
*/
MMAL_PARAMETER_HEADER_T *mmal_port_parameter_alloc_get(MMAL_PORT_T *port,
uint32_t id, uint32_t size, MMAL_STATUS_T *status);
/** Free a parameter structure previously allocated via
* \ref mmal_port_parameter_alloc_get().
*
* @param param pointer to header of the parameter
*/
void mmal_port_parameter_free(MMAL_PARAMETER_HEADER_T *param);
/** Copy buffer header metadata from source to destination.
*
* @param dest The destination buffer header.
* @param src The source buffer header.
*/
void mmal_buffer_header_copy_header(MMAL_BUFFER_HEADER_T *dest, const MMAL_BUFFER_HEADER_T *src);
/** Create a pool of MMAL_BUFFER_HEADER_T associated with a specific port.
* This allows a client to allocate memory for the payload buffers based on the preferences
* of a port. This for instance will allow the port to allocate memory which can be shared
* between the host processor and videocore.
* After allocation, all allocated buffer headers will have been added to the queue.
*
* It is valid to create a pool with no buffer headers, or with zero size payload buffers.
* The mmal_pool_resize() function can be used to increase or decrease the number of buffer
* headers, or the size of the payload buffers, after creation of the pool.
*
* @param port Port responsible for creating the pool.
* @param headers Number of buffers which will be allocated with the pool.
* @param payload_size Size of the payload buffer which will be allocated in
* each of the buffer headers.
* @return Pointer to the newly created pool or NULL on failure.
*/
MMAL_POOL_T *mmal_port_pool_create(MMAL_PORT_T *port,
unsigned int headers, uint32_t payload_size);
/** Destroy a pool of MMAL_BUFFER_HEADER_T associated with a specific port.
* This will also deallocate all of the memory which was allocated when creating or
* resizing the pool.
*
* @param port Pointer to the port responsible for creating the pool.
* @param pool Pointer to the pool to be destroyed.
*/
void mmal_port_pool_destroy(MMAL_PORT_T *port, MMAL_POOL_T *pool);
/** Log the content of a \ref MMAL_PORT_T structure.
*
* @param port Pointer to the port to dump.
*/
void mmal_log_dump_port(MMAL_PORT_T *port);
/** Log the content of a \ref MMAL_ES_FORMAT_T structure.
*
* @param format Pointer to the format to dump.
*/
void mmal_log_dump_format(MMAL_ES_FORMAT_T *format);
/** Return the nth port.
*
* @param comp component to query
* @param index port index
* @param type port type
*
* @return port or NULL if not found
*/
MMAL_PORT_T *mmal_util_get_port(MMAL_COMPONENT_T *comp, MMAL_PORT_TYPE_T type, unsigned index);
/** Convert a 4cc into a string.
*
* @param buf Destination for result
* @param len Size of result buffer
* @param fourcc 4cc to be converted
* @return converted string (buf)
*
*/
char *mmal_4cc_to_string(char *buf, size_t len, uint32_t fourcc);
/** On FW prior to June 2016, camera and video_splitter
* had BGR24 and RGB24 support reversed.
* This is now fixed, and this function will return whether the
* FW has the fix or not.
*
* @param port MMAL port to check (on camera or video_splitter)
* @return 0 if old firmware, 1 if new.
*
*/
int mmal_util_rgb_order_fixed(MMAL_PORT_T *port);
#ifdef __cplusplus
}
#endif
/** @} */
#endif
@@ -0,0 +1,223 @@
/*
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 "mmal_util_params.h"
/** Helper function to set the value of a boolean parameter */
MMAL_STATUS_T mmal_port_parameter_set_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T value)
{
MMAL_PARAMETER_BOOLEAN_T param = {{id, sizeof(param)}, value};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a boolean parameter */
MMAL_STATUS_T mmal_port_parameter_get_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T *value)
{
MMAL_PARAMETER_BOOLEAN_T param = {{id, sizeof(param)}, 0};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.enable;
return status;
}
/** Helper function to set the value of a 64 bits unsigned integer parameter */
MMAL_STATUS_T mmal_port_parameter_set_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t value)
{
MMAL_PARAMETER_UINT64_T param = {{id, sizeof(param)}, value};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a 64 bits unsigned integer parameter */
MMAL_STATUS_T mmal_port_parameter_get_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t *value)
{
MMAL_PARAMETER_UINT64_T param = {{id, sizeof(param)}, 0LL};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.value;
return status;
}
/** Helper function to set the value of a 64 bits signed integer parameter */
MMAL_STATUS_T mmal_port_parameter_set_int64(MMAL_PORT_T *port, uint32_t id, int64_t value)
{
MMAL_PARAMETER_INT64_T param = {{id, sizeof(param)}, value};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a 64 bits signed integer parameter */
MMAL_STATUS_T mmal_port_parameter_get_int64(MMAL_PORT_T *port, uint32_t id, int64_t *value)
{
MMAL_PARAMETER_INT64_T param = {{id, sizeof(param)}, 0LL};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.value;
return status;
}
/** Helper function to set the value of a 32 bits unsigned integer parameter */
MMAL_STATUS_T mmal_port_parameter_set_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t value)
{
MMAL_PARAMETER_UINT32_T param = {{id, sizeof(param)}, value};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a 32 bits unsigned integer parameter */
MMAL_STATUS_T mmal_port_parameter_get_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t *value)
{
MMAL_PARAMETER_UINT32_T param = {{id, sizeof(param)}, 0};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.value;
return status;
}
/** Helper function to set the value of a 32 bits signed integer parameter */
MMAL_STATUS_T mmal_port_parameter_set_int32(MMAL_PORT_T *port, uint32_t id, int32_t value)
{
MMAL_PARAMETER_INT32_T param = {{id, sizeof(param)}, value};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a 32 bits signed integer parameter */
MMAL_STATUS_T mmal_port_parameter_get_int32(MMAL_PORT_T *port, uint32_t id, int32_t *value)
{
MMAL_PARAMETER_INT32_T param = {{id, sizeof(param)}, 0};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.value;
return status;
}
/** Helper function to set the value of a rational parameter */
MMAL_STATUS_T mmal_port_parameter_set_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T value)
{
MMAL_PARAMETER_RATIONAL_T param = {{id, sizeof(param)}, {value.num, value.den}};
return mmal_port_parameter_set(port, &param.hdr);
}
/** Helper function to get the value of a rational parameter */
MMAL_STATUS_T mmal_port_parameter_get_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T *value)
{
MMAL_PARAMETER_RATIONAL_T param = {{id, sizeof(param)}, {0,0}};
// coverity[overrun-buffer-val] Structure accessed correctly via size field
MMAL_STATUS_T status = mmal_port_parameter_get(port, &param.hdr);
if (status == MMAL_SUCCESS)
*value = param.value;
return status;
}
/** Helper function to set the value of a string parameter */
MMAL_STATUS_T mmal_port_parameter_set_string(MMAL_PORT_T *port, uint32_t id, const char *value)
{
MMAL_PARAMETER_STRING_T *param = 0;
MMAL_STATUS_T status;
size_t param_size = sizeof(param->hdr) + strlen(value) + 1;
param = calloc(1, param_size);
if (!param)
return MMAL_ENOMEM;
param->hdr.id = id;
param->hdr.size = param_size;
memcpy(param->str, value, strlen(value)+1);
status = mmal_port_parameter_set(port, &param->hdr);
free(param);
return status;
}
/** Helper function to set a MMAL_PARAMETER_URI_T parameter on a port */
MMAL_STATUS_T mmal_util_port_set_uri(MMAL_PORT_T *port, const char *uri)
{
return mmal_port_parameter_set_string(port, MMAL_PARAMETER_URI, uri);
}
/** Helper function to set the value of an array of bytes parameter */
MMAL_STATUS_T mmal_port_parameter_set_bytes(MMAL_PORT_T *port, uint32_t id,
const uint8_t *data, unsigned int size)
{
MMAL_PARAMETER_BYTES_T *param = 0;
MMAL_STATUS_T status;
size_t param_size = sizeof(param->hdr) + size;
param = calloc(1, param_size);
if (!param)
return MMAL_ENOMEM;
param->hdr.id = id;
param->hdr.size = param_size;
memcpy(param->data, data, size);
status = mmal_port_parameter_set(port, &param->hdr);
free(param);
return status;
}
/** Set the display region.
* @param port port to configure
* @param region region
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_util_set_display_region(MMAL_PORT_T *port,
MMAL_DISPLAYREGION_T *region)
{
region->hdr.id = MMAL_PARAMETER_DISPLAYREGION;
region->hdr.size = sizeof(*region);
return mmal_port_parameter_set(port, &region->hdr);
}
MMAL_STATUS_T mmal_util_camera_use_stc_timestamp(MMAL_PORT_T *port, MMAL_CAMERA_STC_MODE_T mode)
{
MMAL_PARAMETER_CAMERA_STC_MODE_T param =
{{MMAL_PARAMETER_USE_STC, sizeof(MMAL_PARAMETER_CAMERA_STC_MODE_T)},mode};
return mmal_port_parameter_set(port, &param.hdr);
}
MMAL_STATUS_T mmal_util_get_core_port_stats(MMAL_PORT_T *port,
MMAL_CORE_STATS_DIR dir,
MMAL_BOOL_T reset,
MMAL_CORE_STATISTICS_T *stats)
{
MMAL_PARAMETER_CORE_STATISTICS_T param;
MMAL_STATUS_T ret;
memset(&param, 0, sizeof(param));
param.hdr.id = MMAL_PARAMETER_CORE_STATISTICS;
param.hdr.size = sizeof(param);
param.dir = dir;
param.reset = reset;
// coverity[overrun-buffer-val] Structure accessed correctly via size field
ret = mmal_port_parameter_get(port, &param.hdr);
if (ret == MMAL_SUCCESS)
*stats = param.stats;
return ret;
}
@@ -0,0 +1,210 @@
/*
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.
*/
#ifndef MMAL_UTIL_PARAMS_H
#define MMAL_UTIL_PARAMS_H
#include "mmal.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* Utility functions to set some common parameters.
*/
/** Helper function to set the value of a boolean parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T value);
/** Helper function to get the value of a boolean parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T *value);
/** Helper function to set the value of a 64 bits unsigned integer parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t value);
/** Helper function to get the value of a 64 bits unsigned integer parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t *value);
/** Helper function to set the value of a 64 bits signed integer parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_int64(MMAL_PORT_T *port, uint32_t id, int64_t value);
/** Helper function to get the value of a 64 bits signed integer parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_int64(MMAL_PORT_T *port, uint32_t id, int64_t *value);
/** Helper function to set the value of a 32 bits unsigned integer parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t value);
/** Helper function to get the value of a 32 bits unsigned integer parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t *value);
/** Helper function to set the value of a 32 bits signed integer parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_int32(MMAL_PORT_T *port, uint32_t id, int32_t value);
/** Helper function to get the value of a 32 bits signed integer parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_int32(MMAL_PORT_T *port, uint32_t id, int32_t *value);
/** Helper function to set the value of a rational parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value value to set the parameter to
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T value);
/** Helper function to get the value of a rational parameter.
* @param port port on which to get the parameter
* @param id parameter id
* @param value pointer to where the value will be returned
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_get_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T *value);
/** Helper function to set the value of a string parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param value null-terminated string value
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_string(MMAL_PORT_T *port, uint32_t id, const char *value);
/** Helper function to set the value of an array of bytes parameter.
* @param port port on which to set the parameter
* @param id parameter id
* @param data pointer to the array of bytes
* @param size size of the array of bytes
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_port_parameter_set_bytes(MMAL_PORT_T *port, uint32_t id,
const uint8_t *data, unsigned int size);
/** Helper function to set a MMAL_PARAMETER_URI_T parameter on a port.
* @param port port on which to set the parameter
* @param uri URI string
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_util_port_set_uri(MMAL_PORT_T *port, const char *uri);
/** Set the display region.
* @param port port to configure
* @param region region
*
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_util_set_display_region(MMAL_PORT_T *port,
MMAL_DISPLAYREGION_T *region);
/** Tell the camera to use the STC for timestamps rather than the clock.
*
* @param port port to configure
* @param mode STC mode to use
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_util_camera_use_stc_timestamp(MMAL_PORT_T *port, MMAL_CAMERA_STC_MODE_T mode);
/** Get the MMAL core statistics for a given port.
*
* @param port port to query
* @param dir port direction
* @param reset reset the stats as well
* @param stats filled in with results
* @return MMAL_SUCCESS or error
*/
MMAL_STATUS_T mmal_util_get_core_port_stats(MMAL_PORT_T *port, MMAL_CORE_STATS_DIR dir, MMAL_BOOL_T reset,
MMAL_CORE_STATISTICS_T *stats);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,158 @@
/*
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 <limits.h>
#include "interface/mmal/util/mmal_util_rational.h"
#define Q16_ONE (1 << 16)
#define ABS(v) (((v) < 0) ? -(v) : (v))
/** Calculate the greatest common denominator between 2 integers.
* Avoids division. */
static int32_t gcd(int32_t a, int32_t b)
{
int shift;
if (a == 0 || b == 0)
return 1;
a = ABS(a);
b = ABS(b);
for (shift = 0; !((a | b) & 0x01); shift++)
a >>= 1, b >>= 1;
while (a > 0)
{
while (!(a & 0x01))
a >>= 1;
while (!(b & 0x01))
b >>= 1;
if (a >= b)
a = (a - b) >> 1;
else
b = (b - a) >> 1;
}
return b << shift;
}
/** Calculate a + b. */
MMAL_RATIONAL_T mmal_rational_add(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b)
{
MMAL_RATIONAL_T result;
int32_t g = gcd(a.den, b.den);
a.den /= g;
a.num = a.num * (b.den / g) + b.num * a.den;
g = gcd(a.num, g);
a.num /= g;
a.den *= b.den / g;
result.num = a.num;
result.den = a.den;
return result;
}
/** Calculate a - b. */
MMAL_RATIONAL_T mmal_rational_subtract(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b)
{
b.num = -b.num;
return mmal_rational_add(a, b);
}
/** Calculate a * b */
MMAL_RATIONAL_T mmal_rational_multiply(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b)
{
MMAL_RATIONAL_T result;
int32_t gcd1 = gcd(a.num, b.den);
int32_t gcd2 = gcd(b.num, a.den);
result.num = (a.num / gcd1) * (b.num / gcd2);
result.den = (a.den / gcd2) * (b.den / gcd1);
return result;
}
/** Calculate a / b */
MMAL_RATIONAL_T mmal_rational_divide(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b)
{
MMAL_RATIONAL_T result;
int32_t gcd1, gcd2;
if (b.num == 0)
{
vcos_assert(0);
return a;
}
if (a.num == 0)
return a;
gcd1 = gcd(a.num, b.num);
gcd2 = gcd(b.den, a.den);
result.num = (a.num / gcd1) * (b.den / gcd2);
result.den = (a.den / gcd2) * (b.num / gcd1);
return result;
}
/** Convert a rational number to a signed 32-bit Q16 number. */
int32_t mmal_rational_to_fixed_16_16(MMAL_RATIONAL_T rational)
{
int64_t result = (int64_t)rational.num << 16;
if (rational.den)
result /= rational.den;
if (result > INT_MAX)
result = INT_MAX;
else if (result < INT_MIN)
result = INT_MIN;
return (int32_t)result;
}
/** Convert a rational number to a signed 32-bit Q16 number. */
MMAL_RATIONAL_T mmal_rational_from_fixed_16_16(int32_t fixed)
{
MMAL_RATIONAL_T result = { fixed, Q16_ONE };
mmal_rational_simplify(&result);
return result;
}
/** Reduce a rational number to it's simplest form. */
void mmal_rational_simplify(MMAL_RATIONAL_T *rational)
{
int g = gcd(rational->num, rational->den);
rational->num /= g;
rational->den /= g;
}
/** Tests for equality */
MMAL_BOOL_T mmal_rational_equal(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b)
{
if (a.num != b.num && a.num * (int64_t)b.num == 0)
return MMAL_FALSE;
return a.num * (int64_t)b.den == b.num * (int64_t)a.den;
}
@@ -0,0 +1,127 @@
/*
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.
*/
#ifndef MMAL_UTIL_RATIONAL_H
#define MMAL_UTIL_RATIONAL_H
#include "interface/mmal/mmal_types.h"
/** \defgroup MmalRationalUtilities Rational Utility Functions
* \ingroup MmalUtilities
* The rational utility functions allow easy manipulation of rational numbers.
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** Add 2 rational numbers.
* It is assumed that both input rational numbers are in
* their simplest form.
*
* @param a First operand
* @param b Second operand
*
* @return a + b
*/
MMAL_RATIONAL_T mmal_rational_add(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b);
/** Subtract 2 rational numbers.
* It is assumed that both input rational numbers are in
* their simplest form.
*
* @param a First operand
* @param b Second operand
*
* @return a - b
*/
MMAL_RATIONAL_T mmal_rational_subtract(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b);
/** Multiply 2 rational numbers.
* It is assumed that both input rational numbers are in
* their simplest form.
*
* @param a First operand
* @param b Second operand
*
* @return a * b
*/
MMAL_RATIONAL_T mmal_rational_multiply(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b);
/** Divide 2 rational numbers.
* It is assumed that both input rational numbers are in
* their simplest form.
*
* @param a First operand
* @param b Second operand
*
* @return a / b
*/
MMAL_RATIONAL_T mmal_rational_divide(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b);
/** Convert a rational number to a 32-bit signed Q16 number.
* Saturation will occur for rational numbers with an absolute
* value greater than 32768.
*
* @param rational Rational number to convert
*
* @return 32-bit signed Q16 number
*/
int32_t mmal_rational_to_fixed_16_16(MMAL_RATIONAL_T rational);
/** Convert a signed 32-bit Q16 number to a rational number.
*
* @param fixed Signed 32-bit Q16 number to convert
*
* @return Rational number
*/
MMAL_RATIONAL_T mmal_rational_from_fixed_16_16(int32_t fixed);
/** Reduce a rational number to it's simplest form.
*
* @param rational Rational number to simplify
*/
void mmal_rational_simplify(MMAL_RATIONAL_T *rational);
/** Test 2 rational numbers for equality.
*
* @param a First operand
* @param b Second operand
*
* @return true if equal
*/
MMAL_BOOL_T mmal_rational_equal(MMAL_RATIONAL_T a, MMAL_RATIONAL_T b);
#ifdef __cplusplus
}
#endif
/** @} */
#endif