1018 lines
45 KiB
Diff
1018 lines
45 KiB
Diff
From 30475fef6590cf05f3f84122238fc2cc9bb1d676 Mon Sep 17 00:00:00 2001
|
|
From: yafen <yafen@iscas.ac.cn>
|
|
Date: Wed, 11 Aug 2021 04:58:40 +0800
|
|
Subject: [PATCH 2/2] Revert "Revert "mmal: Support 64 bit clients""
|
|
|
|
This reverts commit e31da99739927e87707b2e1bc978e75653706b9c.
|
|
---
|
|
interface/mmal/vc/mmal_vc_api.c | 72 ++++--
|
|
interface/mmal/vc/mmal_vc_client.c | 310 ++++++++++++++++++++----
|
|
interface/mmal/vc/mmal_vc_client_priv.h | 6 +
|
|
interface/mmal/vc/mmal_vc_msgs.h | 147 ++++++++++-
|
|
4 files changed, 461 insertions(+), 74 deletions(-)
|
|
|
|
diff --git a/interface/mmal/vc/mmal_vc_api.c b/interface/mmal/vc/mmal_vc_api.c
|
|
index a20cc28..f35e445 100644
|
|
--- a/interface/mmal/vc/mmal_vc_api.c
|
|
+++ b/interface/mmal/vc/mmal_vc_api.c
|
|
@@ -85,8 +85,10 @@ typedef struct MMAL_COMPONENT_MODULE_T
|
|
|
|
MMAL_BOOL_T event_ctx_initialised;
|
|
MMAL_VC_CLIENT_BUFFER_CONTEXT_T event_ctx; /**< Used as the ctx for event buffers */
|
|
+ uint32_t event_ctx_handle; /**< Used as the ctx for event buffers */
|
|
} MMAL_COMPONENT_MODULE_T;
|
|
|
|
+
|
|
/*****************************************************************************
|
|
* Local function prototypes
|
|
*****************************************************************************/
|
|
@@ -148,7 +150,8 @@ static MMAL_STATUS_T mmal_vc_port_requirements_set(MMAL_PORT_T *port)
|
|
msg.component_handle = module->component_handle;
|
|
msg.action = MMAL_WORKER_PORT_ACTION_SET_REQUIREMENTS;
|
|
msg.port_handle = module->port_handle;
|
|
- msg.param.enable.port = *port;
|
|
+ msg.param.enable.port.buffer_num = port->buffer_num;
|
|
+ msg.param.enable.port.buffer_size = port->buffer_size;
|
|
|
|
status = mmal_vc_sendwait_message(mmal_vc_get_client(), &msg.header, sizeof(msg),
|
|
MMAL_WORKER_PORT_ACTION, &reply, &replylen, MMAL_FALSE);
|
|
@@ -224,7 +227,7 @@ static MMAL_STATUS_T mmal_vc_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb
|
|
for (i = 0; i < pool->headers_num; i++)
|
|
{
|
|
drv = mmal_buffer_header_driver_data(pool->header[i]);
|
|
- drv->client_context = &port->component->priv->module->event_ctx;
|
|
+ drv->client_context = port->component->priv->module->event_ctx_handle;
|
|
drv->magic = MMAL_MAGIC;
|
|
}
|
|
|
|
@@ -255,7 +258,8 @@ static MMAL_STATUS_T mmal_vc_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb
|
|
msg.component_handle = module->component_handle;
|
|
msg.action = MMAL_WORKER_PORT_ACTION_ENABLE;
|
|
msg.port_handle = module->port_handle;
|
|
- msg.param.enable.port = *port;
|
|
+ msg.param.enable.port.buffer_num = port->buffer_num;
|
|
+ msg.param.enable.port.buffer_size = port->buffer_size;
|
|
|
|
status = mmal_vc_sendwait_message(mmal_vc_get_client(), &msg.header, sizeof(msg),
|
|
MMAL_WORKER_PORT_ACTION, &reply, &replylen, MMAL_FALSE);
|
|
@@ -368,7 +372,7 @@ static MMAL_STATUS_T mmal_vc_port_flush_sync(MMAL_PORT_T *port)
|
|
client_context.magic = MMAL_MAGIC;
|
|
client_context.port = port;
|
|
|
|
- msg->drvbuf.client_context = &client_context;
|
|
+ msg->drvbuf.client_context = mmal_vc_allocate_client_context(&client_context);
|
|
msg->drvbuf.component_handle = module->component_handle;
|
|
msg->drvbuf.port_handle = module->port_handle;
|
|
msg->drvbuf.magic = MMAL_MAGIC;
|
|
@@ -384,6 +388,7 @@ static MMAL_STATUS_T mmal_vc_port_flush_sync(MMAL_PORT_T *port)
|
|
if (status != MMAL_SUCCESS)
|
|
LOG_ERROR("failed to disable port - reason %d", status);
|
|
|
|
+ mmal_vc_release_client_context(&client_context);
|
|
return status;
|
|
}
|
|
|
|
@@ -502,7 +507,7 @@ static void mmal_vc_do_callback(MMAL_COMPONENT_T *component)
|
|
|
|
/* Events generated by this component are handled differently */
|
|
if (mmal_buffer_header_driver_data(buffer)->client_context ==
|
|
- &component->priv->module->event_ctx)
|
|
+ component->priv->module->event_ctx_handle)
|
|
{
|
|
mmal_port_event_send(port, buffer);
|
|
return;
|
|
@@ -528,14 +533,16 @@ static void mmal_vc_port_send_callback(mmal_worker_buffer_from_host *msg)
|
|
{
|
|
MMAL_BUFFER_HEADER_T *buffer;
|
|
MMAL_PORT_T *port;
|
|
- MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = msg->drvbuf.client_context;
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
|
|
|
|
vcos_assert(client_context);
|
|
vcos_assert(client_context->magic == MMAL_MAGIC);
|
|
|
|
buffer = client_context->buffer;
|
|
port = client_context->port;
|
|
- vcos_blockpool_free(msg->drvbuf.client_context);
|
|
+
|
|
+ vcos_blockpool_free(client_context);
|
|
+ mmal_vc_release_client_context(client_context);
|
|
|
|
vcos_assert(port->priv->module->magic == MMAL_MAGIC);
|
|
mmal_vc_msg_to_buffer_header(buffer, msg);
|
|
@@ -614,7 +621,7 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
|
|
client_context->callback_event = NULL;
|
|
client_context->port = port;
|
|
|
|
- msg->drvbuf.client_context = client_context;
|
|
+ msg->drvbuf.client_context = mmal_vc_allocate_client_context(client_context);
|
|
msg->drvbuf.component_handle = module->component_handle;
|
|
msg->drvbuf.port_handle = module->port_handle;
|
|
msg->drvbuf.magic = MMAL_MAGIC;
|
|
@@ -641,12 +648,14 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
|
|
if (!VCOS_BLOCKPOOL_IS_VALID_HANDLE_FORMAT(msg->drvbuf.component_handle, 256))
|
|
{
|
|
LOG_ERROR("bad component handle 0x%x", msg->drvbuf.component_handle);
|
|
+ mmal_vc_release_client_context(client_context);
|
|
return MMAL_EINVAL;
|
|
}
|
|
|
|
if (msg->drvbuf.port_handle > 255)
|
|
{
|
|
LOG_ERROR("bad port handle 0x%x", msg->drvbuf.port_handle);
|
|
+ mmal_vc_release_client_context(client_context);
|
|
return MMAL_EINVAL;
|
|
}
|
|
|
|
@@ -693,7 +702,8 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
|
|
if (status != MMAL_SUCCESS)
|
|
{
|
|
LOG_INFO("failed %d", status);
|
|
- vcos_blockpool_free(msg->drvbuf.client_context);
|
|
+ vcos_blockpool_free(client_context);
|
|
+ mmal_vc_release_client_context(client_context);
|
|
buffer->data = mmal_vc_shm_lock(buffer->data, port->priv->module->zero_copy_workaround);
|
|
}
|
|
|
|
@@ -795,6 +805,7 @@ static MMAL_STATUS_T mmal_vc_component_destroy(MMAL_COMPONENT_T *component)
|
|
mmal_ports_free(component->clock, component->clock_num);
|
|
|
|
mmal_queue_destroy(component->priv->module->callback_queue);
|
|
+ mmal_vc_release_client_context(&component->priv->module->event_ctx);
|
|
|
|
vcos_free(component->priv->module);
|
|
component->priv->module = NULL;
|
|
@@ -802,6 +813,7 @@ static MMAL_STATUS_T mmal_vc_component_destroy(MMAL_COMPONENT_T *component)
|
|
fail:
|
|
// no longer require videocore
|
|
mmal_vc_release();
|
|
+ mmal_vc_release_client_component(component);
|
|
mmal_vc_shm_exit();
|
|
mmal_vc_deinit();
|
|
return status;
|
|
@@ -928,6 +940,17 @@ MMAL_STATUS_T mmal_vc_get_core_stats(MMAL_CORE_STATISTICS_T *stats,
|
|
return status;
|
|
}
|
|
|
|
+static void mmal_vc_copy_es_format_to_vc(MMAL_ES_FORMAT_T *src, MMAL_VC_ES_FORMAT_T *dest)
|
|
+{
|
|
+ // IPC MMAL_VC_ES_FORMAT_T is not necessarily the same as MMAL_ES_FORMAT_T,
|
|
+ // so copy fields individually.
|
|
+ dest->type = src->type;
|
|
+ dest->encoding = src->encoding;
|
|
+ dest->encoding_variant = src->encoding_variant;
|
|
+ dest->bitrate = src->bitrate;
|
|
+ dest->flags = src->flags;
|
|
+ dest->extradata_size = src->extradata_size;
|
|
+}
|
|
|
|
/** Get port context data. */
|
|
static MMAL_STATUS_T mmal_vc_port_info_get(MMAL_PORT_T *port)
|
|
@@ -969,9 +992,9 @@ static MMAL_STATUS_T mmal_vc_port_info_get(MMAL_PORT_T *port)
|
|
port->buffer_alignment_min = reply.port.buffer_alignment_min;
|
|
port->is_enabled = reply.port.is_enabled;
|
|
port->capabilities = reply.port.capabilities;
|
|
- reply.format.extradata = port->format->extradata;
|
|
- reply.format.es = port->format->es;
|
|
- *port->format = reply.format;
|
|
+
|
|
+ mmal_vc_copy_es_format_from_vc(&reply.format, port->format);
|
|
+
|
|
*port->format->es = reply.es;
|
|
if(port->format->extradata_size)
|
|
{
|
|
@@ -1001,15 +1024,22 @@ static MMAL_STATUS_T mmal_vc_port_info_set(MMAL_PORT_T *port)
|
|
msg.component_handle = module->component_handle;
|
|
msg.port_type = port->type;
|
|
msg.index = port->index;
|
|
- msg.port = *port;
|
|
- msg.format = *port->format;
|
|
+
|
|
+ //Only copy the values that are used into the MMAL_PORT_T of the IPC.
|
|
+ msg.port.buffer_num = port->buffer_num;
|
|
+ msg.port.buffer_size = port->buffer_size;
|
|
+ msg.port.is_enabled = port->is_enabled;
|
|
+
|
|
+ mmal_vc_copy_es_format_to_vc(port->format, &msg.format);
|
|
+
|
|
msg.es = *port->format->es;
|
|
+
|
|
if(msg.format.extradata_size > MMAL_FORMAT_EXTRADATA_MAX_SIZE)
|
|
{
|
|
vcos_assert(0);
|
|
msg.format.extradata_size = MMAL_FORMAT_EXTRADATA_MAX_SIZE;
|
|
}
|
|
- memcpy(msg.extradata, msg.format.extradata, msg.format.extradata_size);
|
|
+ memcpy(msg.extradata, port->format->extradata, msg.format.extradata_size);
|
|
|
|
LOG_TRACE("set port info (%i:%i)", port->type, port->index);
|
|
|
|
@@ -1037,9 +1067,9 @@ static MMAL_STATUS_T mmal_vc_port_info_set(MMAL_PORT_T *port)
|
|
port->buffer_alignment_min = reply.port.buffer_alignment_min;
|
|
port->is_enabled = reply.port.is_enabled;
|
|
port->capabilities = reply.port.capabilities;
|
|
- reply.format.extradata = port->format->extradata;
|
|
- reply.format.es = port->format->es;
|
|
- *port->format = reply.format;
|
|
+
|
|
+ mmal_vc_copy_es_format_from_vc(&reply.format, port->format);
|
|
+
|
|
*port->format->es = reply.es;
|
|
if(port->format->extradata_size)
|
|
{
|
|
@@ -1328,7 +1358,6 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
|
|
return MMAL_EINVAL;
|
|
}
|
|
|
|
- msg.client_component = component;
|
|
/* coverity[secure_coding] Length tested above */
|
|
strcpy(msg.name, basename);
|
|
#ifdef __linux__
|
|
@@ -1351,6 +1380,8 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
|
|
return status;
|
|
}
|
|
|
|
+ msg.client_component = mmal_vc_allocate_client_component(component);
|
|
+
|
|
// claim VC for entire duration of component.
|
|
status = mmal_vc_use();
|
|
|
|
@@ -1371,6 +1402,7 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
|
|
LOG_ERROR("failed to create component '%s' (%i:%s)", name, status,
|
|
mmal_status_to_string(status));
|
|
mmal_vc_release();
|
|
+ mmal_vc_release_client_component(component);
|
|
mmal_vc_shm_exit();
|
|
mmal_vc_deinit();
|
|
return status;
|
|
@@ -1391,6 +1423,7 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
|
|
MMAL_WORKER_COMPONENT_DESTROY, &reply, &replylen, MMAL_FALSE);
|
|
vcos_assert(destroy_status == MMAL_SUCCESS);
|
|
mmal_vc_release();
|
|
+ mmal_vc_release_client_component(component);
|
|
mmal_vc_shm_exit();
|
|
mmal_vc_deinit();
|
|
return status;
|
|
@@ -1496,6 +1529,7 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
|
|
module->event_ctx_initialised = MMAL_FALSE;
|
|
module->event_ctx.magic = MMAL_MAGIC;
|
|
module->event_ctx.callback_event = mmal_vc_port_send_event_callback;
|
|
+ module->event_ctx_handle = mmal_vc_allocate_client_context(&module->event_ctx);
|
|
|
|
/* populate component structure */
|
|
component->priv->pf_enable = mmal_vc_component_enable;
|
|
diff --git a/interface/mmal/vc/mmal_vc_client.c b/interface/mmal/vc/mmal_vc_client.c
|
|
index 4935a27..f3241d2 100644
|
|
--- a/interface/mmal/vc/mmal_vc_client.c
|
|
+++ b/interface/mmal/vc/mmal_vc_client.c
|
|
@@ -53,6 +53,7 @@ static VCOS_LOG_CAT_T mmal_ipc_log_category;
|
|
*/
|
|
typedef struct MMAL_WAITER_T
|
|
{
|
|
+ int index;
|
|
VCOS_SEMAPHORE_T sem;
|
|
unsigned inuse;
|
|
void *dest; /**< Where to write reply */
|
|
@@ -82,6 +83,151 @@ struct MMAL_CLIENT_T
|
|
MMAL_BOOL_T inited;
|
|
};
|
|
|
|
+/*****************************************************************************
|
|
+ * Lookup table functions for client_component handles.
|
|
+ * Required as the IPC is strictly 32bit, therefore 64bit userland can not
|
|
+ * pass in the required pointers.
|
|
+ *****************************************************************************/
|
|
+#define MAX_COMPONENT_HANDLES 128
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ unsigned int inuse:1;
|
|
+ unsigned int index:31;
|
|
+ MMAL_COMPONENT_T *component;
|
|
+} MMAL_CLIENT_COMPONENT_T;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ MMAL_CLIENT_COMPONENT_T components[MAX_COMPONENT_HANDLES];
|
|
+ VCOS_MUTEX_T lock;
|
|
+} MMAL_CLIENT_COMPONENT_POOL_T;
|
|
+
|
|
+static MMAL_CLIENT_COMPONENT_POOL_T client_component_pool;
|
|
+
|
|
+uint32_t mmal_vc_allocate_client_component(MMAL_COMPONENT_T *component)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ vcos_mutex_lock(&client_component_pool.lock);
|
|
+ for (i=0; i<MAX_COMPONENT_HANDLES; i++)
|
|
+ {
|
|
+ if (client_component_pool.components[i].inuse == 0)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (vcos_verify(i != MAX_COMPONENT_HANDLES))
|
|
+ {
|
|
+ client_component_pool.components[i].index = i;
|
|
+ client_component_pool.components[i].component = component;
|
|
+ client_component_pool.components[i].inuse = 1;
|
|
+ }
|
|
+ vcos_mutex_unlock(&client_component_pool.lock);
|
|
+
|
|
+ return i;
|
|
+}
|
|
+
|
|
+static MMAL_COMPONENT_T *lookup_client_component(int index)
|
|
+{
|
|
+ if (vcos_verify(index < MAX_COMPONENT_HANDLES))
|
|
+ {
|
|
+ vcos_assert(client_component_pool.components[index].inuse);
|
|
+ return client_component_pool.components[index].component;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void mmal_vc_release_client_component(MMAL_COMPONENT_T *component)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ vcos_mutex_lock(&client_component_pool.lock);
|
|
+ for (i=0; i<MAX_COMPONENT_HANDLES; i++)
|
|
+ {
|
|
+ if (client_component_pool.components[i].component == component)
|
|
+ {
|
|
+ client_component_pool.components[i].component = NULL;
|
|
+ client_component_pool.components[i].inuse = 0;
|
|
+ }
|
|
+ }
|
|
+ vcos_mutex_unlock(&client_component_pool.lock);
|
|
+}
|
|
+
|
|
+#define MAX_CLIENT_CONTEXTS 512
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ unsigned int inuse:1;
|
|
+ unsigned int index:31;
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *ctx;
|
|
+} MMAL_CLIENT_CONTEXT_T;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ MMAL_CLIENT_CONTEXT_T contexts[MAX_CLIENT_CONTEXTS];
|
|
+ VCOS_MUTEX_T lock;
|
|
+} MMAL_CLIENT_CONTEXT_POOL_T;
|
|
+
|
|
+static MMAL_CLIENT_CONTEXT_POOL_T client_context_pool;
|
|
+#define CLIENT_CONTEXT_MAGIC 0xFEDC0000
|
|
+#define CLIENT_CONTEXT_MAGIC_MASK(a) (a & 0xFFFF)
|
|
+#define CLIENT_CONTEXT_MAGIC_CHECK(a) (a & 0xFFFF0000)
|
|
+
|
|
+uint32_t mmal_vc_allocate_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ vcos_mutex_lock(&client_context_pool.lock);
|
|
+ for (i=0; i<MAX_CLIENT_CONTEXTS; i++)
|
|
+ {
|
|
+ if (client_context_pool.contexts[i].inuse == 0)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (vcos_verify(i != MAX_CLIENT_CONTEXTS))
|
|
+ {
|
|
+ client_context_pool.contexts[i].index = i;
|
|
+ client_context_pool.contexts[i].ctx = context;
|
|
+ client_context_pool.contexts[i].inuse = 1;
|
|
+ }
|
|
+ vcos_mutex_unlock(&client_context_pool.lock);
|
|
+
|
|
+ return i | CLIENT_CONTEXT_MAGIC;
|
|
+}
|
|
+
|
|
+MMAL_VC_CLIENT_BUFFER_CONTEXT_T *mmal_vc_lookup_client_context(int index)
|
|
+{
|
|
+ if (vcos_verify((CLIENT_CONTEXT_MAGIC_CHECK(index) == CLIENT_CONTEXT_MAGIC) &&
|
|
+ (CLIENT_CONTEXT_MAGIC_MASK(index) < MAX_CLIENT_CONTEXTS)))
|
|
+ {
|
|
+ vcos_assert(client_context_pool.contexts[CLIENT_CONTEXT_MAGIC_MASK(index)].inuse);
|
|
+ return client_context_pool.contexts[CLIENT_CONTEXT_MAGIC_MASK(index)].ctx;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void mmal_vc_release_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ vcos_mutex_lock(&client_context_pool.lock);
|
|
+ for (i=0; i<MAX_CLIENT_CONTEXTS; i++)
|
|
+ {
|
|
+ if (client_context_pool.contexts[i].ctx == context)
|
|
+ {
|
|
+ client_context_pool.contexts[i].ctx = NULL;
|
|
+ client_context_pool.contexts[i].inuse = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (i >= MAX_CLIENT_CONTEXTS)
|
|
+ LOG_ERROR("Failed to release context %p - not found", context);
|
|
+
|
|
+ vcos_mutex_unlock(&client_context_pool.lock);
|
|
+}
|
|
+
|
|
/* One client per process/VC connection. Multiple threads may
|
|
* be using a single client.
|
|
*/
|
|
@@ -90,6 +236,8 @@ static MMAL_CLIENT_T client;
|
|
static void init_once(void)
|
|
{
|
|
vcos_mutex_create(&client.lock, VCOS_FUNCTION);
|
|
+ vcos_mutex_create(&client_component_pool.lock, VCOS_FUNCTION);
|
|
+ vcos_mutex_create(&client_context_pool.lock, VCOS_FUNCTION);
|
|
}
|
|
|
|
/** Create a pool of wait-structures.
|
|
@@ -107,6 +255,7 @@ static MMAL_STATUS_T create_waitpool(MMAL_WAITPOOL_T *waitpool)
|
|
for (i=0; i<MAX_WAITERS; i++)
|
|
{
|
|
waitpool->waiters[i].inuse = 0;
|
|
+ waitpool->waiters[i].index = i;
|
|
status = vcos_semaphore_create(&waitpool->waiters[i].sem,
|
|
"mmal waiter", 0);
|
|
if (status != VCOS_SUCCESS)
|
|
@@ -161,6 +310,19 @@ static MMAL_WAITER_T *get_waiter(MMAL_CLIENT_T *client)
|
|
return waiter;
|
|
}
|
|
|
|
+/** Look up a waiter reference based on the static client
|
|
+ */
|
|
+static MMAL_WAITER_T *lookup_waiter(uint32_t index)
|
|
+{
|
|
+ //NB this uses the static client variable, whilst most others use the client
|
|
+ //variable passed in. I don't believe there is a way to have multiple clients
|
|
+ //in one process, so this should be safe.
|
|
+ if (vcos_verify(index < MAX_WAITERS))
|
|
+ return &client.waitpool.waiters[index];
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
/** Return a waiter to the pool.
|
|
*/
|
|
static void release_waiter(MMAL_CLIENT_T *client, MMAL_WAITER_T *waiter)
|
|
@@ -198,13 +360,15 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
|
|
void *context)
|
|
{
|
|
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)vchiq_header->data;
|
|
- MMAL_COMPONENT_T *component = msg->client_component;
|
|
+ MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
|
|
MMAL_BUFFER_HEADER_T *buffer;
|
|
MMAL_STATUS_T status;
|
|
MMAL_PORT_T *port;
|
|
|
|
- LOG_DEBUG("event to host, cmd 0x%08x len %d to component %p port (%d,%d)",
|
|
- msg->cmd, msg->length, msg->client_component, msg->port_type, msg->port_num);
|
|
+ LOG_DEBUG("event to host, cmd 0x%08x len %d to component %u/%p port (%d,%d)",
|
|
+ msg->cmd, msg->length, msg->client_component, component, msg->port_type,
|
|
+ msg->port_num);
|
|
(void)context;
|
|
|
|
port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
|
|
@@ -229,11 +393,12 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
|
|
}
|
|
buffer->length = msg->length;
|
|
|
|
+ client_context = mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(buffer)->client_context);
|
|
/* Sanity check that the event buffers have the proper vc client context */
|
|
if (!vcos_verify(mmal_buffer_header_driver_data(buffer)->magic == MMAL_MAGIC &&
|
|
- mmal_buffer_header_driver_data(buffer)->client_context &&
|
|
- mmal_buffer_header_driver_data(buffer)->client_context->magic == MMAL_MAGIC &&
|
|
- mmal_buffer_header_driver_data(buffer)->client_context->callback_event))
|
|
+ client_context &&
|
|
+ client_context->magic == MMAL_MAGIC &&
|
|
+ client_context->callback_event))
|
|
{
|
|
LOG_ERROR("event buffers not configured properly by component");
|
|
goto error;
|
|
@@ -258,9 +423,53 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
|
|
else
|
|
{
|
|
if (msg->length)
|
|
- memcpy(buffer->data, msg->data, msg->length);
|
|
+ {
|
|
+ if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED && buffer->length >= msg->length)
|
|
+ {
|
|
+ //64bit userspace.
|
|
+ //No need to fix the pointers in the msg as mmal_event_format_changed_get
|
|
+ //will do that for us, but the start positions of each section does need
|
|
+ //to be adjusted.
|
|
+ mmal_worker_event_format_changed *fmt_changed_vc =
|
|
+ (mmal_worker_event_format_changed*)msg->data;
|
|
+ MMAL_EVENT_FORMAT_CHANGED_T *fmt_changed_host =
|
|
+ (MMAL_EVENT_FORMAT_CHANGED_T*)buffer->data;
|
|
+ MMAL_ES_FORMAT_T *fmt_host;
|
|
+ MMAL_VC_ES_FORMAT_T *fmt_vc;
|
|
+ MMAL_ES_SPECIFIC_FORMAT_T *es_host, *es_vc;
|
|
+ const uint32_t size_host = sizeof(MMAL_EVENT_FORMAT_CHANGED_T) +
|
|
+ sizeof(MMAL_ES_FORMAT_T) +
|
|
+ sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
|
|
+ const uint32_t size_vc = sizeof(mmal_worker_event_format_changed) +
|
|
+ sizeof(MMAL_VC_ES_FORMAT_T) +
|
|
+ sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
|
|
+
|
|
+ //Copy the base event (ignore the format pointer from the end)
|
|
+ memcpy(fmt_changed_host, fmt_changed_vc, sizeof(mmal_worker_event_format_changed));
|
|
+ fmt_changed_host->format = NULL;
|
|
+
|
|
+ //Copy the es format
|
|
+ fmt_vc = (MMAL_VC_ES_FORMAT_T *)&fmt_changed_vc[1];
|
|
+ fmt_host = (MMAL_ES_FORMAT_T *)&fmt_changed_host[1];
|
|
+ mmal_vc_copy_es_format_from_vc(fmt_vc, fmt_host);
|
|
+
|
|
+ //Copy the ES_SPECIFIC_FORMAT_T (structures are identical)
|
|
+ es_host = (MMAL_ES_SPECIFIC_FORMAT_T *)&fmt_host[1];
|
|
+ es_vc = (MMAL_ES_SPECIFIC_FORMAT_T *)&fmt_vc[1];
|
|
+ memcpy(es_host, es_vc, sizeof(MMAL_ES_SPECIFIC_FORMAT_T));
|
|
+
|
|
+ //Copy the extradata (if present)
|
|
+ fmt_host->extradata_size = msg->length - size_vc;
|
|
+ memcpy((uint8_t *)&es_host[1], (uint8_t*)&es_vc[1], fmt_host->extradata_size);
|
|
+ buffer->length = size_host + fmt_host->extradata_size;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ memcpy(buffer->data, msg->data, msg->length);
|
|
+ }
|
|
+ }
|
|
|
|
- mmal_buffer_header_driver_data(buffer)->client_context->callback_event(port, buffer);
|
|
+ client_context->callback_event(port, buffer);
|
|
LOG_DEBUG("done callback back to client");
|
|
vchiq_release_message(service, vchiq_header);
|
|
}
|
|
@@ -324,29 +533,36 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
|
|
if (msg->msgid == MMAL_WORKER_BUFFER_TO_HOST)
|
|
{
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
|
|
LOG_TRACE("buffer to host");
|
|
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)vchiq_header->data;
|
|
- LOG_TRACE("len %d context %p", msg->buffer_header.length, msg->drvbuf.client_context);
|
|
- vcos_assert(msg->drvbuf.client_context);
|
|
- vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
|
|
+
|
|
+ client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
|
|
+ LOG_TRACE("len %d context %p", msg->buffer_header.length, client_context);
|
|
+ vcos_assert(client_context);
|
|
+ vcos_assert(client_context->magic == MMAL_MAGIC);
|
|
|
|
/* If the buffer is referencing another, need to replicate it here
|
|
* in order to use the reference buffer's payload and ensure the
|
|
* reference is not released prematurely */
|
|
if (msg->has_reference)
|
|
- mmal_buffer_header_replicate(msg->drvbuf.client_context->buffer,
|
|
- msg->drvbuf_ref.client_context->buffer);
|
|
+ {
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *ref_context =
|
|
+ mmal_vc_lookup_client_context(msg->drvbuf_ref.client_context);
|
|
+ vcos_assert(ref_context);
|
|
+ mmal_buffer_header_replicate(client_context->buffer, ref_context->buffer);
|
|
+ }
|
|
|
|
/* Sanity check the size of the transfer so we don't overrun our buffer */
|
|
if (!vcos_verify(msg->buffer_header.offset + msg->buffer_header.length <=
|
|
- msg->drvbuf.client_context->buffer->alloc_size))
|
|
+ client_context->buffer->alloc_size))
|
|
{
|
|
LOG_TRACE("buffer too small (%i, %i)",
|
|
msg->buffer_header.offset + msg->buffer_header.length,
|
|
- msg->drvbuf.client_context->buffer->alloc_size);
|
|
+ client_context->buffer->alloc_size);
|
|
msg->buffer_header.length = 0;
|
|
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
+ client_context->callback(msg);
|
|
vchiq_release_message(service, vchiq_header);
|
|
break;
|
|
}
|
|
@@ -357,7 +573,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
{
|
|
/* a buffer full of data for us to process */
|
|
VCHIQ_STATUS_T vst = VCHIQ_SUCCESS;
|
|
- LOG_TRACE("queue bulk rx: %p, %d", msg->drvbuf.client_context->buffer->data +
|
|
+ LOG_TRACE("queue bulk rx: %p, %d", client_context->buffer->data +
|
|
msg->buffer_header.offset, msg->buffer_header.length);
|
|
int len = msg->buffer_header.length;
|
|
len = (len+3) & (~3);
|
|
@@ -370,7 +586,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
{
|
|
/* buffer transferred using vchiq bulk xfer */
|
|
vst = vchiq_queue_bulk_receive(service,
|
|
- msg->drvbuf.client_context->buffer->data + msg->buffer_header.offset,
|
|
+ client_context->buffer->data + msg->buffer_header.offset,
|
|
len, vchiq_header);
|
|
|
|
if (vst != VCHIQ_SUCCESS)
|
|
@@ -378,20 +594,20 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
LOG_TRACE("queue bulk rx len %d failed to start", msg->buffer_header.length);
|
|
msg->buffer_header.length = 0;
|
|
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
+ client_context->callback(msg);
|
|
vchiq_release_message(service, vchiq_header);
|
|
}
|
|
}
|
|
else if (msg->payload_in_message <= MMAL_VC_SHORT_DATA)
|
|
{
|
|
/* we have already received the buffer data in the message! */
|
|
- MMAL_BUFFER_HEADER_T *dst = msg->drvbuf.client_context->buffer;
|
|
+ MMAL_BUFFER_HEADER_T *dst = client_context->buffer;
|
|
LOG_TRACE("short data: dst = %p, dst->data = %p, len %d short len %d", dst, dst? dst->data : 0, msg->buffer_header.length, msg->payload_in_message);
|
|
memcpy(dst->data, msg->short_data, msg->payload_in_message);
|
|
dst->offset = 0;
|
|
dst->length = msg->payload_in_message;
|
|
vchiq_release_message(service, vchiq_header);
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
+ client_context->callback(msg);
|
|
}
|
|
else
|
|
{
|
|
@@ -409,9 +625,9 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
* be picked up in the callback to complete the sequence.
|
|
*/
|
|
LOG_TRACE("doing cb (%p) context %p",
|
|
- msg->drvbuf.client_context, msg->drvbuf.client_context ?
|
|
- msg->drvbuf.client_context->callback : 0);
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
+ client_context, client_context ?
|
|
+ client_context->callback : 0);
|
|
+ client_context->callback(msg);
|
|
LOG_TRACE("done callback back to client");
|
|
vchiq_release_message(service, vchiq_header);
|
|
}
|
|
@@ -422,7 +638,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
}
|
|
else
|
|
{
|
|
- MMAL_WAITER_T *waiter = msg->u.waiter;
|
|
+ MMAL_WAITER_T *waiter = lookup_waiter(msg->u.waiter);
|
|
LOG_TRACE("waking up waiter at %p", waiter);
|
|
vcos_assert(waiter->inuse);
|
|
int len = vcos_min(waiter->destlen, vchiq_header->size);
|
|
@@ -443,7 +659,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
#ifdef VCOS_LOGGING_ENABLED
|
|
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)context;
|
|
#endif
|
|
- LOG_TRACE("bulk tx done: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
+ LOG_TRACE("bulk tx done: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
}
|
|
break;
|
|
case VCHIQ_BULK_RECEIVE_DONE:
|
|
@@ -453,18 +669,21 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
if (msg_hdr->msgid == MMAL_WORKER_BUFFER_TO_HOST)
|
|
{
|
|
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)msg_hdr;
|
|
- vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
- LOG_TRACE("bulk rx done: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
|
|
+ vcos_assert(client_context && client_context->magic == MMAL_MAGIC);
|
|
+ client_context->callback(msg);
|
|
+ LOG_TRACE("bulk rx done: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
}
|
|
else
|
|
{
|
|
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)msg_hdr;
|
|
- MMAL_PORT_T *port = mmal_vc_port_by_number(msg->client_component, msg->port_type, msg->port_num);
|
|
+ MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
|
|
+ mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(msg->delayed_buffer)->client_context);
|
|
+ MMAL_PORT_T *port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
|
|
|
|
- vcos_assert(port);
|
|
- mmal_buffer_header_driver_data(msg->delayed_buffer)->
|
|
- client_context->callback_event(port, msg->delayed_buffer);
|
|
+ vcos_assert(client_context && port);
|
|
+ client_context->callback_event(port, msg->delayed_buffer);
|
|
LOG_DEBUG("event bulk rx done, length %d", msg->length);
|
|
}
|
|
vchiq_release_message(service, header);
|
|
@@ -477,21 +696,25 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
if (msg_hdr->msgid == MMAL_WORKER_BUFFER_TO_HOST)
|
|
{
|
|
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)msg_hdr;
|
|
- LOG_TRACE("bulk rx aborted: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
- vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
|
|
+ LOG_TRACE("bulk rx aborted: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
+ vcos_assert(client_context && client_context->magic == MMAL_MAGIC);
|
|
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
|
|
- msg->drvbuf.client_context->callback(msg);
|
|
+ client_context->callback(msg);
|
|
}
|
|
else
|
|
{
|
|
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)msg_hdr;
|
|
- MMAL_PORT_T *port = mmal_vc_port_by_number(msg->client_component, msg->port_type, msg->port_num);
|
|
+ MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
|
|
+ mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(msg->delayed_buffer)->client_context);
|
|
+ MMAL_PORT_T *port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
|
|
|
|
vcos_assert(port);
|
|
LOG_DEBUG("event bulk rx aborted");
|
|
msg->delayed_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
|
|
- mmal_buffer_header_driver_data(msg->delayed_buffer)->
|
|
- client_context->callback_event(port, msg->delayed_buffer);
|
|
+
|
|
+ client_context->callback_event(port, msg->delayed_buffer);
|
|
}
|
|
vchiq_release_message(service, header);
|
|
}
|
|
@@ -499,9 +722,12 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
|
|
case VCHIQ_BULK_TRANSMIT_ABORTED:
|
|
{
|
|
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)context;
|
|
- LOG_INFO("bulk tx aborted: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
- vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
|
|
+ MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
|
|
+ mmal_vc_lookup_client_context(msg->drvbuf.client_context);
|
|
+ LOG_INFO("bulk tx aborted: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
|
|
+ vcos_assert(client_context->magic == MMAL_MAGIC);
|
|
/* Nothing to do as the VC side will release the buffer and notify us of the error */
|
|
+ client_context = NULL; // Avoid warnings in release builds
|
|
}
|
|
break;
|
|
default:
|
|
@@ -548,7 +774,7 @@ MMAL_STATUS_T mmal_vc_sendwait_message(struct MMAL_CLIENT_T *client,
|
|
|
|
waiter = get_waiter(client);
|
|
msg_header->msgid = msgid;
|
|
- msg_header->u.waiter = waiter;
|
|
+ msg_header->u.waiter = waiter->index;
|
|
msg_header->magic = MMAL_MAGIC;
|
|
|
|
waiter->dest = dest;
|
|
diff --git a/interface/mmal/vc/mmal_vc_client_priv.h b/interface/mmal/vc/mmal_vc_client_priv.h
|
|
index 0fc3aaa..0b8f570 100644
|
|
--- a/interface/mmal/vc/mmal_vc_client_priv.h
|
|
+++ b/interface/mmal/vc/mmal_vc_client_priv.h
|
|
@@ -76,5 +76,11 @@ MMAL_STATUS_T mmal_vc_send_message(MMAL_CLIENT_T *client,
|
|
uint8_t *data, size_t data_size,
|
|
uint32_t msgid);
|
|
|
|
+uint32_t mmal_vc_allocate_client_component(MMAL_COMPONENT_T *component);
|
|
+void mmal_vc_release_client_component(MMAL_COMPONENT_T *component);
|
|
+
|
|
+uint32_t mmal_vc_allocate_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context);
|
|
+MMAL_VC_CLIENT_BUFFER_CONTEXT_T *mmal_vc_lookup_client_context(int index);
|
|
+void mmal_vc_release_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context);
|
|
#endif
|
|
|
|
diff --git a/interface/mmal/vc/mmal_vc_msgs.h b/interface/mmal/vc/mmal_vc_msgs.h
|
|
index 343922b..7e1a3e2 100644
|
|
--- a/interface/mmal/vc/mmal_vc_msgs.h
|
|
+++ b/interface/mmal/vc/mmal_vc_msgs.h
|
|
@@ -112,10 +112,10 @@ typedef struct
|
|
{
|
|
uint32_t magic;
|
|
uint32_t msgid;
|
|
- struct MMAL_CONTROL_SERVICE_T *control_service; /** Handle to the control service */
|
|
+ uint32_t control_service; /** Handle to the control service (unused) */
|
|
|
|
union {
|
|
- struct MMAL_WAITER_T *waiter; /** User-land wait structure, passed back */
|
|
+ uint32_t waiter; /** User-land wait structure, passed back */
|
|
} u;
|
|
|
|
MMAL_STATUS_T status; /** Result code, passed back */
|
|
@@ -152,7 +152,7 @@ typedef struct
|
|
typedef struct
|
|
{
|
|
mmal_worker_msg_header header;
|
|
- void *client_component; /** Client component */
|
|
+ uint32_t client_component; /** Client component */
|
|
char name[128];
|
|
uint32_t pid; /**< For debug */
|
|
} mmal_worker_component_create;
|
|
@@ -206,6 +206,71 @@ typedef struct
|
|
} mmal_worker_port_info_get;
|
|
vcos_static_assert(sizeof(mmal_worker_port_info_get) <= MMAL_WORKER_MAX_MSG_LEN);
|
|
|
|
+typedef struct
|
|
+{
|
|
+ MMAL_ES_TYPE_T type; /**< Type of the elementary stream */
|
|
+
|
|
+ MMAL_FOURCC_T encoding; /**< FourCC specifying the encoding of the elementary stream.
|
|
+ * See the \ref MmalEncodings "pre-defined encodings" for some
|
|
+ * examples.
|
|
+ */
|
|
+ MMAL_FOURCC_T encoding_variant;/**< FourCC specifying the specific encoding variant of
|
|
+ * the elementary stream. See the \ref MmalEncodingVariants
|
|
+ * "pre-defined encoding variants" for some examples.
|
|
+ */
|
|
+
|
|
+ uint32_t es; /**< Type specific information for the elementary stream */
|
|
+
|
|
+ uint32_t bitrate; /**< Bitrate in bits per second */
|
|
+ uint32_t flags; /**< Flags describing properties of the elementary stream.
|
|
+ * See \ref elementarystreamflags "Elementary stream flags".
|
|
+ */
|
|
+
|
|
+ uint32_t extradata_size; /**< Size of the codec specific data */
|
|
+ uint32_t extradata; /**< Codec specific data */
|
|
+
|
|
+} MMAL_VC_ES_FORMAT_T;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ uint32_t priv; /**< Private member used by the framework */
|
|
+ uint32_t name; /**< Port name. Used for debugging purposes (Read Only) */
|
|
+
|
|
+ MMAL_PORT_TYPE_T type; /**< Type of the port (Read Only) */
|
|
+ uint16_t index; /**< Index of the port in its type list (Read Only) */
|
|
+ uint16_t index_all; /**< Index of the port in the list of all ports (Read Only) */
|
|
+
|
|
+ uint32_t is_enabled; /**< Indicates whether the port is enabled or not (Read Only) */
|
|
+ uint32_t format; /**< Format of the elementary stream */
|
|
+
|
|
+ uint32_t buffer_num_min; /**< Minimum number of buffers the port requires (Read Only).
|
|
+ This is set by the component. */
|
|
+ uint32_t buffer_size_min; /**< Minimum size of buffers the port requires (Read Only).
|
|
+ This is set by the component. */
|
|
+ uint32_t buffer_alignment_min; /**< Minimum alignment requirement for the buffers (Read Only).
|
|
+ A value of zero means no special alignment requirements.
|
|
+ This is set by the component. */
|
|
+ uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal performance (Read Only).
|
|
+ A value of zero means no special recommendation.
|
|
+ This is set by the component. */
|
|
+ uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance (Read Only).
|
|
+ A value of zero means no special recommendation.
|
|
+ This is set by the component. */
|
|
+ uint32_t buffer_num; /**< Actual number of buffers the port will use.
|
|
+ This is set by the client. */
|
|
+ uint32_t buffer_size; /**< Actual maximum size of the buffers that will be sent
|
|
+ to the port. This is set by the client. */
|
|
+
|
|
+ uint32_t component; /**< Component this port belongs to (Read Only) */
|
|
+ uint32_t userdata; /**< Field reserved for use by the client */
|
|
+
|
|
+ uint32_t capabilities; /**< Flags describing the capabilities of a port (Read Only).
|
|
+ * Bitwise combination of \ref portcapabilities "Port capabilities"
|
|
+ * values.
|
|
+ */
|
|
+
|
|
+} MMAL_VC_PORT_T;
|
|
+
|
|
/** Component port info. Used to set port info.
|
|
*/
|
|
typedef struct
|
|
@@ -214,8 +279,8 @@ typedef struct
|
|
uint32_t component_handle; /**< Which component */
|
|
MMAL_PORT_TYPE_T port_type; /**< Type of port */
|
|
uint32_t index; /**< Which port of given type to get */
|
|
- MMAL_PORT_T port;
|
|
- MMAL_ES_FORMAT_T format;
|
|
+ MMAL_VC_PORT_T port;
|
|
+ MMAL_VC_ES_FORMAT_T format;
|
|
MMAL_ES_SPECIFIC_FORMAT_T es;
|
|
uint8_t extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
|
|
} mmal_worker_port_info_set;
|
|
@@ -231,8 +296,8 @@ typedef struct
|
|
uint32_t index; /**< Which port of given type to get */
|
|
int32_t found; /**< Did we find anything? */
|
|
uint32_t port_handle; /**< Handle to use for this port */
|
|
- MMAL_PORT_T port;
|
|
- MMAL_ES_FORMAT_T format;
|
|
+ MMAL_VC_PORT_T port;
|
|
+ MMAL_VC_ES_FORMAT_T format;
|
|
MMAL_ES_SPECIFIC_FORMAT_T es;
|
|
uint8_t extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
|
|
} mmal_worker_port_info;
|
|
@@ -285,7 +350,7 @@ typedef struct
|
|
/** Action parameter */
|
|
union {
|
|
struct {
|
|
- MMAL_PORT_T port;
|
|
+ MMAL_VC_PORT_T port;
|
|
} enable;
|
|
struct {
|
|
uint32_t component_handle;
|
|
@@ -357,9 +422,41 @@ struct MMAL_DRIVER_BUFFER_T
|
|
uint32_t port_handle; /**< Index into array of ports for this component */
|
|
|
|
/** Client side uses this to get back to its context structure. */
|
|
- struct MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
|
|
+ uint32_t client_context;
|
|
};
|
|
|
|
+typedef struct MMAL_VC_BUFFER_HEADER_T
|
|
+{
|
|
+ uint32_t next; /**< Used to link several buffer headers together */
|
|
+
|
|
+ uint32_t priv; /**< Data private to the framework */
|
|
+
|
|
+ uint32_t cmd; /**< Defines what the buffer header contains. This is a FourCC
|
|
+ with 0 as a special value meaning stream data */
|
|
+
|
|
+ uint32_t data; /**< Pointer to the start of the payload buffer (should not be
|
|
+ changed by component) */
|
|
+ uint32_t alloc_size; /**< Allocated size in bytes of payload buffer */
|
|
+ uint32_t length; /**< Number of bytes currently used in the payload buffer (starting
|
|
+ from offset) */
|
|
+ uint32_t offset; /**< Offset in bytes to the start of valid data in the payload buffer */
|
|
+
|
|
+ uint32_t flags; /**< Flags describing properties of a buffer header (see
|
|
+ \ref bufferheaderflags "Buffer header flags") */
|
|
+
|
|
+ int64_t pts; /**< Presentation timestamp in microseconds. \ref MMAL_TIME_UNKNOWN
|
|
+ is used when the pts is unknown. */
|
|
+ int64_t dts; /**< Decode timestamp in microseconds (dts = pts, except in the case
|
|
+ of video streams with B frames). \ref MMAL_TIME_UNKNOWN
|
|
+ is used when the dts is unknown. */
|
|
+
|
|
+ /** Type specific data that's associated with a payload buffer */
|
|
+ uint32_t type;
|
|
+
|
|
+ uint32_t user_data; /**< Field reserved for use by the client */
|
|
+
|
|
+} MMAL_VC_BUFFER_HEADER_T;
|
|
+
|
|
/** Receive a buffer from the host.
|
|
*
|
|
* @sa mmal_port_send_buffer()
|
|
@@ -382,7 +479,7 @@ typedef struct mmal_worker_buffer_from_host
|
|
struct MMAL_DRIVER_BUFFER_T drvbuf_ref;
|
|
|
|
/** the buffer header itself */
|
|
- MMAL_BUFFER_HEADER_T buffer_header;
|
|
+ MMAL_VC_BUFFER_HEADER_T buffer_header;
|
|
MMAL_BUFFER_HEADER_TYPE_SPECIFIC_T buffer_header_type_specific;
|
|
|
|
MMAL_BOOL_T is_zero_copy;
|
|
@@ -411,17 +508,29 @@ typedef struct mmal_worker_event_to_host
|
|
{
|
|
mmal_worker_msg_header header;
|
|
|
|
- struct MMAL_COMPONENT_T *client_component;
|
|
+ uint32_t client_component;
|
|
uint32_t port_type;
|
|
uint32_t port_num;
|
|
|
|
uint32_t cmd;
|
|
uint32_t length;
|
|
uint8_t data[MMAL_WORKER_EVENT_SPACE];
|
|
- MMAL_BUFFER_HEADER_T *delayed_buffer; /* Only used to remember buffer for bulk rx */
|
|
+ MMAL_BUFFER_HEADER_T *delayed_buffer; /* Only used to remember buffer for bulk rx */ // FIXME
|
|
} mmal_worker_event_to_host;
|
|
vcos_static_assert(sizeof(mmal_worker_event_to_host) <= MMAL_WORKER_MAX_MSG_LEN);
|
|
|
|
+typedef struct mmal_worker_event_format_changed
|
|
+{
|
|
+ uint32_t buffer_size_min; /**< Minimum size of buffers the port requires */
|
|
+ uint32_t buffer_num_min; /**< Minimum number of buffers the port requires */
|
|
+ uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance.
|
|
+ A value of zero means no special recommendation. */
|
|
+ uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal
|
|
+ performance. A value of zero means no special recommendation. */
|
|
+
|
|
+ uint32_t format; /**< New elementary stream format */
|
|
+} mmal_worker_event_format_changed;
|
|
+
|
|
typedef struct
|
|
{
|
|
mmal_worker_msg_header header;
|
|
@@ -515,7 +624,7 @@ static inline void mmal_vc_buffer_header_to_msg(mmal_worker_buffer_from_host *ms
|
|
msg->buffer_header.pts = header->pts;
|
|
msg->buffer_header.dts = header->dts;
|
|
msg->buffer_header.alloc_size = header->alloc_size;
|
|
- msg->buffer_header.data = header->data;
|
|
+ msg->buffer_header.data = (uintptr_t)header->data;
|
|
msg->buffer_header_type_specific = *header->type;
|
|
}
|
|
|
|
@@ -531,5 +640,17 @@ static inline void mmal_vc_msg_to_buffer_header(MMAL_BUFFER_HEADER_T *header,
|
|
*header->type = msg->buffer_header_type_specific;
|
|
}
|
|
|
|
+static inline void mmal_vc_copy_es_format_from_vc(MMAL_VC_ES_FORMAT_T *src, MMAL_ES_FORMAT_T *dest)
|
|
+{
|
|
+ // IPC MMAL_VC_ES_FORMAT_T is not necessarily the same as MMAL_ES_FORMAT_T,
|
|
+ // so copy fields individually.
|
|
+ dest->type = src->type;
|
|
+ dest->encoding = src->encoding;
|
|
+ dest->encoding_variant = src->encoding_variant;
|
|
+ dest->bitrate = src->bitrate;
|
|
+ dest->flags = src->flags;
|
|
+ dest->extradata_size = src->extradata_size;
|
|
+}
|
|
+
|
|
#endif
|
|
|
|
--
|
|
2.27.0
|
|
|