diff --git a/00-vmcs.conf b/00-vmcs.conf new file mode 100644 index 0000000..b0a1aeb --- /dev/null +++ b/00-vmcs.conf @@ -0,0 +1 @@ +/opt/vc/lib diff --git a/0001-Revert-Revert-Add-MMAL-and-MMAL_APPS-to-64bit-builds.patch b/0001-Revert-Revert-Add-MMAL-and-MMAL_APPS-to-64bit-builds.patch new file mode 100644 index 0000000..4d87fcf --- /dev/null +++ b/0001-Revert-Revert-Add-MMAL-and-MMAL_APPS-to-64bit-builds.patch @@ -0,0 +1,84 @@ +From 3297328f8d8902c80a154d96517870d2dbae7b4a Mon Sep 17 00:00:00 2001 +From: yafen +Date: Wed, 11 Aug 2021 04:58:33 +0800 +Subject: [PATCH 1/2] Revert "Revert "Add MMAL and MMAL_APPS to 64bit builds"" + +This reverts commit f97b1af1b3e653f9da2c1a3643479bfd469e3b74. +--- + CMakeLists.txt | 18 ++++++++---------- + host_applications/linux/CMakeLists.txt | 4 ++-- + interface/mmal/CMakeLists.txt | 6 ++++-- + 3 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fe67fc8..d8ba238 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -8,13 +8,9 @@ SET(PROJECT_VER_PATCH 0) + SET(PROJECT_VER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}.${PROJECT_VER_PATCH}") + SET(PROJECT_APIVER "${PROJECT_VER}") + +-if(ARM64) +- set(BUILD_MMAL FALSE) +- set(BUILD_MMAL_APPS FALSE) +-else() +- set(BUILD_MMAL TRUE) +- set(BUILD_MMAL_APPS TRUE) +-endif() ++set(BUILD_MMAL TRUE) ++set(BUILD_MMAL_APPS TRUE) ++ + set(vmcs_root ${PROJECT_SOURCE_DIR}) + get_filename_component(VIDEOCORE_ROOT . ABSOLUTE) + +@@ -78,9 +74,11 @@ if(BUILD_MMAL) + endif() + + # VidTex supports Android and Linux +-if(BUILD_MMAL_APPS) +-add_subdirectory(host_applications/android/apps/vidtex) +-endif(BUILD_MMAL_APPS) ++if(NOT ARM64) ++ if(BUILD_MMAL_APPS) ++ add_subdirectory(host_applications/android/apps/vidtex) ++ endif(BUILD_MMAL_APPS) ++endif() + + if(NOT ARM64) + add_subdirectory(middleware/openmaxil) +diff --git a/host_applications/linux/CMakeLists.txt b/host_applications/linux/CMakeLists.txt +index 928b637..4bb1e98 100644 +--- a/host_applications/linux/CMakeLists.txt ++++ b/host_applications/linux/CMakeLists.txt +@@ -4,9 +4,9 @@ add_subdirectory(libs/bcm_host) + add_subdirectory(apps/gencmd) + add_subdirectory(apps/tvservice) + add_subdirectory(apps/vcmailbox) ++add_subdirectory(apps/raspicam) ++add_subdirectory(libs/sm) + if(NOT ARM64) +- add_subdirectory(apps/raspicam) +- add_subdirectory(libs/sm) + add_subdirectory(apps/smem) + endif() + add_subdirectory(libs/debug_sym) +diff --git a/interface/mmal/CMakeLists.txt b/interface/mmal/CMakeLists.txt +index 46f149d..8208f7c 100644 +--- a/interface/mmal/CMakeLists.txt ++++ b/interface/mmal/CMakeLists.txt +@@ -11,8 +11,10 @@ add_subdirectory(core) + add_subdirectory(util) + add_subdirectory(vc) + add_subdirectory(components) +-add_subdirectory(openmaxil) +-add_subdirectory(client) ++if(NOT ARM64) ++ add_subdirectory(openmaxil) ++ add_subdirectory(client) ++endif() + + target_link_libraries(mmal mmal_core mmal_util mmal_vc_client vcos mmal_components) + +-- +2.27.0 + diff --git a/0002-Revert-Revert-mmal-Support-64-bit-clients.patch b/0002-Revert-Revert-mmal-Support-64-bit-clients.patch new file mode 100644 index 0000000..b0fa17e --- /dev/null +++ b/0002-Revert-Revert-mmal-Support-64-bit-clients.patch @@ -0,0 +1,1017 @@ +From 30475fef6590cf05f3f84122238fc2cc9bb1d676 Mon Sep 17 00:00:00 2001 +From: yafen +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_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; iwaiters[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 + diff --git a/10-local-rpi.rules b/10-local-rpi.rules new file mode 100644 index 0000000..001571d --- /dev/null +++ b/10-local-rpi.rules @@ -0,0 +1,3 @@ +SUBSYSTEM=="vchiq", GROUP="video", MODE="0660" +SUBSYSTEM=="vc-sm", GROUP="video", MODE="0660" +SUBSYSTEM=="bcm2708_vcio", GROUP="video", MODE="0660" diff --git a/raspberrypi-userland.spec b/raspberrypi-userland.spec new file mode 100644 index 0000000..81132a2 --- /dev/null +++ b/raspberrypi-userland.spec @@ -0,0 +1,168 @@ +%global _ld_path /etc/ld.so.conf.d +%global _rules_path /lib/udev/rules.d +%global _opt_bin_path /opt/vc/bin +%global _opt_man_path /opt/vc/man +%global commitid 97bc8180ad682b004ea224d1db7b8e108eda4397 +%global debug_package %{nil} + +Name: raspberrypi-userland +Version: 20210902 +Release: 1 +Summary: Libraries for interfacing to Raspberry Pi GPU +License: BSD-3-Clause +URL: https://github.com/raspberrypi/userland +Source0: https://github.com/raspberrypi/userland/archive/%{commitid}/userland-%{commitid}.tar.gz +Source10: 00-vmcs.conf +Source11: 10-local-rpi.rules + +Patch0000: 0001-Revert-Revert-Add-MMAL-and-MMAL_APPS-to-64bit-builds.patch +Patch0001: 0002-Revert-Revert-mmal-Support-64-bit-clients.patch + +BuildRequires: make >= 3.78 +BuildRequires: gcc >= 3.4.2 +BuildRequires: cmake ncurses-devel bison gzip +AutoReq: no +AutoProv: yes + +Requires: libraspberrypi0 = %{version}-%{release} +Requires: libraspberrypi-bin = %{version}-%{release} +Requires: libraspberrypi-devel = %{version}-%{release} +Requires: libraspberrypi-help = %{version}-%{release} + +Provides: raspberrypi-userland = %{version}-%{release} + +ExclusiveArch: aarch64 +ExclusiveOS: Linux + +%description +This package contains libraries for interfacing to Raspberry Pi GPU. + +%package -n libraspberrypi0 +Summary: EGL/GLES/OpenVG/etc. libraries for the Raspberry Pi's VideoCore IV +Requires: raspberrypi-firmware +Provides: libraspberrypi0 = %{version}-%{release} +%description -n libraspberrypi0 +This package provides implementations of EGL, OpenGL ES, OpenVG, OpenWF +Composition, and others for the Raspberry Pi's VideoCore IV multimedia +processor. + +%package -n libraspberrypi-bin +Summary: Miscellaneous Raspberry Pi utilities +Requires: libraspberrypi0 dtc +Provides: libraspberrypi-bin = %{version}-%{release} +%description -n libraspberrypi-bin +This package provides various utilities for interacting with the Raspberry Pi's +VideoCore IV. + +%package -n libraspberrypi-devel +Summary: EGL/GLES/OpenVG/etc. libraries for the Raspberry Pi's VideoCore IV (headers) +Requires: libraspberrypi0 +Provides: libraspberrypi-devel = %{version}-%{release} +%description -n libraspberrypi-devel +This package provides headers and other development files for implementations +of EGL, OpenGL ES, OpenVG, OpenWF Composition, and others for the Raspberry Pi's +VideoCore IV multimedia processor. + +%package -n libraspberrypi-help +Summary: EGL/GLES/OpenVG/etc. libraries for the Raspberry Pi's VideoCore IV (headers) +Requires: libraspberrypi0 +Provides: libraspberrypi-help = %{version}-%{release} +%description -n libraspberrypi-help +This package provides headers, example code, and other development files for +implementations of EGL, OpenGL ES, OpenVG, OpenWF Composition, and others for +the Raspberry Pi's VideoCore IV multimedia processor. + +%prep +%setup -q -n %{name}-%{version} -c +mv userland-%{commitid} %{name}-%{version} + +cd %{name}-%{version} +cp %{SOURCE10} . +cp %{SOURCE11} . +%patch0000 -p1 +%patch0001 -p1 + +%build +cd %{name}-%{version} +mkdir -p build/raspberry/release +cd build/raspberry/release +cmake -DCMAKE_BUILD_TYPE=Release -DARM64=ON ../../.. +make + +%install +cd %{name}-%{version} +mkdir -p %{buildroot}%{_ld_path} +mkdir -p %{buildroot}%{_rules_path} +install -p -m 644 %{SOURCE10} %{buildroot}%{_ld_path}/ +install -p -m 644 %{SOURCE11} %{buildroot}%{_rules_path}/ +cd ./build/raspberry/release +make install DESTDIR=%{buildroot} +mkdir -p %{buildroot}%{_bindir} +cd %{buildroot}%{_bindir} +ln -s ../..%{_opt_bin_path}/raspistill ./ +ln -s ../..%{_opt_bin_path}/raspivid ./ +ln -s ../..%{_opt_bin_path}/raspividyuv ./ +ln -s ../..%{_opt_bin_path}/raspiyuv ./ +ln -s ../..%{_opt_bin_path}/tvservice ./ +ln -s ../..%{_opt_bin_path}/vcgencmd ./ +ln -s ../..%{_opt_bin_path}/vchiq_test ./ +ln -s ../..%{_opt_bin_path}/dtoverlay ./ +ln -s ../..%{_opt_bin_path}/dtoverlay-pre ./ +ln -s ../..%{_opt_bin_path}/dtoverlay-post ./ +ln -s ../..%{_opt_bin_path}/dtoverlay ./dtparam +ln -s ../..%{_opt_bin_path}/dtmerge ./ +mkdir -p %{buildroot}%{_mandir}/man1 +mkdir -p %{buildroot}%{_mandir}/man7 +cd %{buildroot}%{_opt_man_path}/man1 +gzip $(ls *.1) +cd %{buildroot}%{_mandir}/man1 +ln -s $(ls ../../../..%{_opt_man_path}/man1/*.1.gz) ./ +cd %{buildroot}%{_opt_man_path}/man7 +gzip $(ls *.7) +cd %{buildroot}%{_mandir}/man7 +ln -s $(ls ../../../..%{_opt_man_path}/man7/*.7.gz) ./ + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%defattr (-, root, root) +%license %{name}-%{version}/LICENCE + +%files -n libraspberrypi0 +%defattr (-, root, root) +%dir /opt/vc +%dir /opt/vc/lib +%{_ld_path}/* +%{_rules_path}/* +/opt/vc/lib/lib*.so +/opt/vc/lib/plugins +%license %{name}-%{version}/LICENCE + +%files -n libraspberrypi-bin +%defattr (-, root, root) +%dir /opt/vc +%{_opt_bin_path} +%{_bindir}/* +%{_opt_man_path} +%{_mandir}/* +%license %{name}-%{version}/LICENCE + +%files -n libraspberrypi-devel +%defattr (-, root, root) +%dir /opt/vc +%dir /opt/vc/lib +/opt/vc/include +/opt/vc/lib/lib*.a +/opt/vc/lib/pkgconfig +%license %{name}-%{version}/LICENCE + +%files -n libraspberrypi-help +%defattr (-, root, root) +%dir /opt/vc +/opt/vc/src +%license %{name}-%{version}/LICENCE + +%changelog +* Thu Sep 2 2021 Yafen Fang - 20210902-1 +- init package \ No newline at end of file diff --git a/userland-97bc8180ad682b004ea224d1db7b8e108eda4397.tar.gz b/userland-97bc8180ad682b004ea224d1db7b8e108eda4397.tar.gz new file mode 100644 index 0000000..b78406a Binary files /dev/null and b/userland-97bc8180ad682b004ea224d1db7b8e108eda4397.tar.gz differ