Projects
Eulaceura:Factory
raspberrypi-userland
_service:obs_scm:0002-Revert-Revert-mmal-Suppor...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0002-Revert-Revert-mmal-Support-64-bit-clients.patch of Package raspberrypi-userland
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2