static void *guard_func(void *param) { GUARD_T *st = (GUARD_T *) param; uint32_t set; while(1) { int i; vcos_event_flags_get(&st->event, -1, VCOS_OR_CONSUME, 0, &set); vcos_semaphore_wait(&st->go); if(st->quit) break; for(i=0; i<2; i++) { if(vcos_event_flags_get(&st->event, 1, VCOS_OR, st->wait[i], &set) != VCOS_SUCCESS) { int j; st->timeout[i] = 1; for(j=0; j<st->post[i]; j++) vcos_semaphore_post(st->guard); } else st->timeout[i] = 0; } vcos_semaphore_post(&st->done); } vcos_thread_exit(NULL); return NULL; }
/** * buffer header callback function for video * * @param port Pointer to port from which callback originated * @param buffer mmal buffer header pointer */ static void video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { MMAL_BUFFER_HEADER_T *new_buffer; RASPIVID_STATE * state = (RASPIVID_STATE *)port->userdata; if (state) { if (state->finished) { vcos_semaphore_post(&state->capture_done_sem); return; } if (buffer->length) { mmal_buffer_header_mem_lock(buffer); // // *** PR : OPEN CV Stuff here ! // int w=state->width; // get image size int h=state->height; int pixelSize = state->monochrome ? 1 : 3; memcpy(state->dstImage->imageData,buffer->data,w*h*pixelSize); vcos_semaphore_post(&state->capture_done_sem); vcos_semaphore_wait(&state->capture_sem); mmal_buffer_header_mem_unlock(buffer); } else { vcos_log_error("buffer null"); } } else { vcos_log_error("Received a encoder buffer callback with no state"); } // release buffer back to the pool mmal_buffer_header_release(buffer); // and send one back to the port (if still open) if (port->is_enabled) { MMAL_STATUS_T status; new_buffer = mmal_queue_get(state->video_pool->queue); if (new_buffer) status = mmal_port_send_buffer(port, new_buffer); if (!new_buffer || status != MMAL_SUCCESS) vcos_log_error("Unable to return a buffer to the encoder port"); } }
void raspiCamCvReleaseCapture(RaspiCamCvCapture ** capture) { RASPIVID_STATE * state = (*capture)->pState; // Unblock the the callback. state->finished = 1; vcos_semaphore_post(&state->capture_sem); vcos_semaphore_wait(&state->capture_done_sem); vcos_semaphore_delete(&state->capture_sem); vcos_semaphore_delete(&state->capture_done_sem); if (state->camera_component) mmal_component_disable(state->camera_component); destroy_camera_component(state); cvReleaseImage(&state->pu); if (state->graymode==0) { cvReleaseImage(&state->pv); cvReleaseImage(&state->py); } if (state->graymode==0) { cvReleaseImage(&state->pu_big); cvReleaseImage(&state->pv_big); cvReleaseImage(&state->yuvImage); cvReleaseImage(&state->dstImage); } free(state); free(*capture); *capture = 0; }
/** Wrapper function around the real thread function. Posts the semaphore * when completed. */ static int vcos_thread_wrapper(void *arg) { void *ret; VCOS_THREAD_T *thread = arg; vcos_assert(thread->magic == VCOS_THREAD_MAGIC); thread->thread.thread = current; vcos_add_thread(thread); #ifdef VCOS_WANT_TLS_EMULATION vcos_tls_thread_register(&thread->_tls); #endif if (thread->legacy) { LEGACY_ENTRY_FN_T fn = (LEGACY_ENTRY_FN_T)thread->entry; fn(0,thread->arg); ret = 0; } else { ret = thread->entry(thread->arg); } thread->exit_data = ret; vcos_remove_thread(current); /* For join and cleanup */ vcos_semaphore_post(&thread->wait); return 0; }
/** Callback from video decode output port. */ static void svp_bh_output_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf) { SVP_T *svp = (SVP_T *)port->userdata; if (buf->length == 0) { LOG_TRACE("%s: zero-length buffer => EOS", port->name); svp_set_stop(svp, SVP_STOP_EOS); // This shouldn't be necessary, but it is ... mmal_buffer_header_release(buf); } else if (buf->data == NULL) { LOG_ERROR("%s: zero buffer handle", port->name); mmal_buffer_header_release(buf); } else { /* Reset watchdog timer */ vcos_timer_set(&svp->wd_timer, SVP_WATCHDOG_TIMEOUT_MS); /* Enqueue the decoded frame so we can return quickly to MMAL core */ mmal_queue_put(svp->queue, buf); } /* Notify worker */ vcos_semaphore_post(&svp->sema); }
/** Callback from a control port. */ static void svp_bh_control_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf) { SVP_T *svp = (SVP_T *)port->userdata; switch (buf->cmd) { case MMAL_EVENT_EOS: LOG_TRACE("%s: EOS", port->name); svp_set_stop(svp, SVP_STOP_EOS); break; case MMAL_EVENT_ERROR: LOG_ERROR("%s: MMAL error: %s", port->name, mmal_status_to_string(*(MMAL_STATUS_T *)buf->data)); svp_set_stop(svp, SVP_STOP_ERROR); break; default: LOG_TRACE("%s: buf %p, event %4.4s", port->name, buf, (char *)&buf->cmd); break; } mmal_buffer_header_release(buf); vcos_semaphore_post(&svp->sema); }
static void vcos_thread_wrapper(int argc, void *arg) #endif { int i; void *ret; VCOS_THREAD_T *thread = (VCOS_THREAD_T *)arg; vcos_assert(thread->magic == VCOS_THREAD_MAGIC); #ifdef VCOS_WANT_TLS_EMULATION vcos_tls_thread_register(&thread->_tls); #endif if (thread->legacy) { LEGACY_ENTRY_FN_T fn = (LEGACY_ENTRY_FN_T)thread->entry; fn(0,thread->arg); ret = 0; } else { ret = thread->entry(thread->arg); } // call termination functions for (i=0; i<VCOS_MAX_EXIT_HANDLERS; i++) { if (thread->at_exit[i].pfn) { thread->at_exit[i].pfn(thread->at_exit[i].cxt); } } thread->exit_data = ret; vcos_semaphore_post(&thread->wait); }
/** Callback to receive stop notification. Sets quit flag and posts semaphore. * @param ctx VIDTEX_T instance. Declared as void * in order to use as SVP callback. * @param stop_reason SVP stop reason. */ static void vidtex_stop_cb(void *ctx, uint32_t stop_reason) { VIDTEX_T *vt = ctx; vt->stop_reason = stop_reason; vidtex_set_quit(vt, true); vcos_semaphore_post(&vt->sem_decoded); }
/** * buffer header callback function for encoder * * Callback will dump buffer data to the specific file * * @param port Pointer to port from which callback originated * @param buffer mmal buffer header pointer */ static void encoder_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { int complete = 0; // We pass our file handle and other stuff in via the userdata field. PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata; if (pData) { int bytes_written = buffer->length; if (buffer->length && pData->file_handle) { mmal_buffer_header_mem_lock(buffer); bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle); mmal_buffer_header_mem_unlock(buffer); } // We need to check we wrote what we wanted - it's possible we have run out of storage. if (bytes_written != buffer->length) { vcos_log_error("Unable to write buffer to file - aborting"); complete = 1; } // Now flag if we have completed if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)) complete = 1; } else { vcos_log_error("Received a encoder buffer callback with no state"); } // release buffer back to the pool mmal_buffer_header_release(buffer); // and send one back to the port (if still open) if (port->is_enabled) { MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_BUFFER_HEADER_T *new_buffer; new_buffer = mmal_queue_get(pData->pstate->encoder_pool->queue); if (new_buffer) { status = mmal_port_send_buffer(port, new_buffer); } if (!new_buffer || status != MMAL_SUCCESS) vcos_log_error("Unable to return a buffer to the encoder port"); } if (complete) vcos_semaphore_post(&(pData->complete_semaphore)); }
/** Return a waiter to the pool. */ static void release_waiter(MMAL_CLIENT_T *client, MMAL_WAITER_T *waiter) { LOG_TRACE("at %p", waiter); vcos_assert(waiter); vcos_assert(waiter->inuse); waiter->inuse = 0; vcos_semaphore_post(&client->waitpool.sem); }
/** Watchdog timer callback - stops playback */ static void svp_watchdog_cb(void *ctx) { SVP_T *svp = ctx; LOG_ERROR("%s: no frames received for %d ms, aborting", svp->video_output->name, SVP_WATCHDOG_TIMEOUT_MS); svp_set_stop(svp, SVP_STOP_ERROR); vcos_semaphore_post(&svp->sema); }
IplImage * raspiCamCvQueryFrame(RaspiCamCvCapture * capture) { RASPIVID_STATE * state = capture->pState; vcos_semaphore_post(&state->capture_sem); vcos_semaphore_wait(&state->capture_done_sem); return state->dstImage; }
static void waiter_deinit(WAITER_T *waiter, int *passed) { waiter->quit = 1; vcos_semaphore_post(&waiter->go); vcos_thread_join(&waiter->thread,NULL); vcos_semaphore_delete(&waiter->go); vcos_semaphore_delete(&waiter->done); }
/** Callback from the input port. * Buffer has been consumed and is available to be used again. */ static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata; /* The decoder is done with the data, just recycle the buffer header into its pool */ mmal_buffer_header_release(buffer); /* Kick the processing thread */ vcos_semaphore_post(&ctx->semaphore); }
/** Callback from the output port. * Buffer has been produced by the port and is available for processing. */ static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata; /* Queue the decoded video frame */ mmal_queue_put(ctx->queue, buffer); /* Kick the processing thread */ vcos_semaphore_post(&ctx->semaphore); }
static void guard_deinit(GUARD_T *guard, int *passed) { guard->quit = 1; vcos_semaphore_post(&guard->go); vcos_thread_join(&guard->thread,0); vcos_semaphore_delete(&guard->go); vcos_semaphore_delete(&guard->done); vcos_event_flags_delete(&guard->event); }
static OMX_ERRORTYPE vcil_out_ComponentTunnelRequest(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPort, OMX_IN OMX_HANDLETYPE hTunneledComp, OMX_IN OMX_U32 nTunneledPort, OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent; VC_PRIVATE_COMPONENT_T *comp; IL_TUNNEL_REQUEST_EXECUTE_T exe; IL_TUNNEL_REQUEST_RESPONSE_T resp; VC_PRIVATE_COMPONENT_T *list; ILCS_COMMON_T *st; int rlen = sizeof(resp); if(!pComp) return OMX_ErrorBadParameter; st = pComp->pApplicationPrivate; comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate; exe.reference = comp->reference; exe.port = nPort; exe.tunnel_port = nTunneledPort; if (pTunnelSetup) exe.setup = *pTunnelSetup; // the other component may be on the host or on VC. Look through our list // so we can tell, and tell ILCS on VC the details. vcos_semaphore_wait(&st->component_lock); list = st->component_list; while (list != NULL && list->comp != (void *) hTunneledComp) list = list->next; vcos_semaphore_post(&st->component_lock); if (list == NULL) { exe.tunnel_ref = hTunneledComp; exe.tunnel_host = OMX_TRUE; } else { exe.tunnel_ref = list->reference; exe.tunnel_host = OMX_FALSE; } if(ilcs_execute_function(st->ilcs, IL_COMPONENT_TUNNEL_REQUEST, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp)) return OMX_ErrorHardware; if (pTunnelSetup) *pTunnelSetup = resp.setup; return resp.err; }
// Called by OMX when the encoder component has filled // the output buffer with H.264 encoded video data static OMX_ERRORTYPE fill_output_buffer_done_handler( OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer) { appctx *ctx = ((appctx*)pAppData); vcos_semaphore_wait(&ctx->handler_lock); // The main loop can now flush the buffer to output file ctx->encoder_output_buffer_available = 1; vcos_semaphore_post(&ctx->handler_lock); return OMX_ErrorNone; }
static OMX_ERRORTYPE vcil_out_ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) { OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent; VC_PRIVATE_COMPONENT_T *comp; IL_EXECUTE_HEADER_T exe; IL_RESPONSE_HEADER_T resp; ILCS_COMMON_T *st; int rlen = sizeof(resp); if(!pComp) return OMX_ErrorBadParameter; st = pComp->pApplicationPrivate; comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate; exe.reference = comp->reference; if(ilcs_execute_function(st->ilcs, IL_COMPONENT_DEINIT, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp) || resp.err == OMX_ErrorNone) { // remove from list, assuming that we successfully managed to deinit // this component, or that ilcs has returned an error. The assumption // here is that if the component has managed to correctly signal an // error, it still exists, but if the transport has failed then we might // as well try and cleanup VC_PRIVATE_COMPONENT_T *list, *prev; vcos_semaphore_wait(&st->component_lock); list = st->component_list; prev = NULL; while (list != NULL && list != comp) { prev = list; list = list->next; } // failing to find this component is not a good sign. if(vcos_verify(list)) { if (prev == NULL) st->component_list = list->next; else prev->next = list->next; } vcos_semaphore_post(&st->component_lock); vcos_free(comp); } return resp.err; }
/** Callback to receive decoded video frame */ static void vidtex_video_frame_cb(void *ctx, void *ob) { if (ob) { VIDTEX_T *vt = ctx; /* coverity[missing_lock] Coverity gets confused by the semaphore locking scheme */ vt->video_frame = ob; vcos_semaphore_post(&vt->sem_decoded); vcos_semaphore_wait(&vt->sem_drawn); vt->video_frame = NULL; } }
/** * buffer header callback function for camera output port * * Callback will dump buffer data to the specific file * * @param port Pointer to port from which callback originated * @param buffer mmal buffer header pointer */ static void camera_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { int complete = 0; // We pass our file handle and other stuff in via the userdata field. PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata; if (pData) { if (buffer->length) { mmal_buffer_header_mem_lock(buffer); int i; for( i = 0; i < buffer->length; i++ ) pData->data_dump[i] = buffer->data[i]; mmal_buffer_header_mem_unlock(buffer); } // Check end of frame or error if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)) complete = 1; } else { vcos_log_error("Received a camera still buffer callback with no state"); } // release buffer back to the pool mmal_buffer_header_release(buffer); // and send one back to the port (if still open) if (port->is_enabled) { MMAL_STATUS_T status; MMAL_BUFFER_HEADER_T *new_buffer = mmal_queue_get(pData->pstate->camera_pool->queue); // and back to the port from there. if (new_buffer) { status = mmal_port_send_buffer(port, new_buffer); } if (!new_buffer || status != MMAL_SUCCESS) vcos_log_error("Unable to return the buffer to the camera still port"); } if (complete) { vcos_semaphore_post(&(pData->complete_semaphore)); } }
/** Put a MMAL_BUFFER_HEADER_T back at the start of a QUEUE. */ void mmal_queue_put_back(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer) { if(!queue || !buffer) return; vcos_mutex_lock(&queue->lock); mmal_queue_sanity_check(queue, buffer); queue->length++; buffer->next = queue->first; queue->first = buffer; if(queue->last == &queue->first) queue->last = &buffer->next; vcos_semaphore_post(&queue->semaphore); vcos_mutex_unlock(&queue->lock); }
static void block_until_flushed(appctx *ctx) { int quit; while(!quit) { vcos_semaphore_wait(&ctx->handler_lock); if(ctx->flushed) { ctx->flushed = 0; quit = 1; } vcos_semaphore_post(&ctx->handler_lock); if(!quit) { usleep(10000); } } }
static void graph_connection_cb(MMAL_CONNECTION_T *connection) { MMAL_GRAPH_PRIVATE_T *graph = (MMAL_GRAPH_PRIVATE_T *)connection->user_data; MMAL_BUFFER_HEADER_T *buffer; if (connection->flags == MMAL_CONNECTION_FLAG_DIRECT && (buffer = mmal_queue_get(connection->queue)) != NULL) { graph_process_buffer(graph, connection, buffer); return; } vcos_semaphore_post(&graph->sema); }
// OMX calls this handler for all the events it emits static OMX_ERRORTYPE event_handler( OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData) { dump_event(hComponent, eEvent, nData1, nData2); appctx *ctx = (appctx *)pAppData; switch(eEvent) { case OMX_EventCmdComplete: vcos_semaphore_wait(&ctx->handler_lock); if(nData1 == OMX_CommandFlush) { ctx->flushed = 1; } vcos_semaphore_post(&ctx->handler_lock); break; case OMX_EventParamOrConfigChanged: vcos_semaphore_wait(&ctx->handler_lock); if(nData2 == OMX_IndexParamCameraDeviceNumber) { ctx->camera_ready = 1; } vcos_semaphore_post(&ctx->handler_lock); break; case OMX_EventError: omx_die(nData1, "error event received"); break; default: break; } return OMX_ErrorNone; }
IplImage * raspiCamCvQueryFrame_New_Final(RaspiCamCvCapture * capture) { RASPIVID_STATE * state = capture->pState; vcos_semaphore_post(&state->capture_sem); vcos_semaphore_wait(&state->capture_done_sem); cvResize(state->pu, state->pu_big, CV_INTER_NN); cvResize(state->pv, state->pv_big, CV_INTER_NN); //CV_INTER_LINEAR looks better but it's slower //cvResize(state->pu, state->pu_big, CV_INTER_AREA); //cvResize(state->pv, state->pv_big, CV_INTER_AREA); cvMerge(state->py, state->pu_big, state->pv_big, NULL, state->yuvImage); //cvMerge(state->py, state->pu, state->pv, NULL, state->yuvImage); //cvCvtColor(state->yuvImage,state->dstImage,CV_YCrCb2RGB); // convert in RGB color space (slow) return state->yuvImage; }
/** * <DFN>vc_hdcp2_service_send_command</DFN> sends a command which has no reply to Videocore * side HDCP2 service. * * @param client_handle is the vchi client handle * * @param sema is the locking semaphore to protect the buffer * * @param command is the command (VC_HDCP2_CMD_CODE_T in vc_hdcp2service_defs.h) * * @param buffer is the command buffer to be sent * * @param length is the size of buffer in bytes * * @return zero if successful, VCHI error code if failed */ int32_t vc_hdcp2_service_send_command(VCHI_SERVICE_HANDLE_T client_handle, VCOS_SEMAPHORE_T *sema, uint32_t command, void *buffer, uint32_t length) { VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)}, {buffer, length} }; VCOS_STATUS_T status; int32_t success = 0; vcos_assert(sema); status = vcos_semaphore_wait(sema); vcos_assert(status == VCOS_SUCCESS); success = vchi_msg_queuev( client_handle, vector, sizeof(vector)/sizeof(vector[0]), VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); status = vcos_semaphore_post(sema); vcos_assert(status == VCOS_SUCCESS); return success; }
/** * buffer header callback function for camera output port * * Callback will dump buffer data to the specific file * * @param port Pointer to port from which callback originated * @param buffer mmal buffer header pointer */ static void camera_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { MMAL_STATUS_T status; // We pass our file handle and other stuff in via the userdata field. PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata; if (pData) { if (buffer->length) { mmal_buffer_header_mem_lock(buffer); fwrite(buffer->data, 1, buffer->length, pData->file_handle); mmal_buffer_header_mem_unlock(buffer); } // What about error conditions? if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_EOS | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)) { vcos_semaphore_post(&(pData->complete_semaphore)); } } else { vcos_log_error("Received a camera still buffer callback with no state"); } // release buffer back to the pool mmal_buffer_header_release(buffer); // and send one back to the port (if still open) if (port->is_enabled) { MMAL_BUFFER_HEADER_T *new_buffer = mmal_queue_get(pData->pstate->camera_pool->queue); // and back to the port from there. status = mmal_port_send_buffer(port, new_buffer); if (status != MMAL_SUCCESS) vcos_log_error("Unable to return the buffer to the camera still port"); } }
static _VCOS_INLINE void vcos_msg_send_helper(VCOS_MSGQUEUE_T *src, VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg) { vcos_assert(msg); vcos_assert(dest); msg->code = code; msg->dst = dest; msg->src = src; msg->next = NULL; msg->src_thread = vcos_thread_current(); msgq_append(dest, msg); vcos_semaphore_post(&dest->sem); }
/** * Writes the next GL frame-buffer to a RAW .ppm formatted file * using the specified file-handle. * @param state Pointer to the GL preview state. * @param outpt_file Output file handle for the ppm image. * @return Zero on success. */ int raspitex_capture(RASPITEX_STATE *state, FILE *output_file) { int rc = 0; uint8_t *buffer = NULL; size_t size = 0; vcos_log_trace("%s: state %p file %p", VCOS_FUNCTION, state, output_file); if (state && output_file) { /* Only request one capture at a time */ vcos_semaphore_wait(&state->capture.start_sem); state->capture.request = 1; /* Wait for capture to start */ vcos_semaphore_wait(&state->capture.completed_sem); /* Take ownership of the captured buffer */ buffer = state->capture.buffer; size = state->capture.size; state->capture.request = 0; state->capture.buffer = 0; state->capture.size = 0; /* Allow another capture to be requested */ vcos_semaphore_post(&state->capture.start_sem); } if (size == 0 || ! buffer) { vcos_log_error("%s: capture failed", VCOS_FUNCTION); rc = -1; goto end; } raspitexutil_brga_to_rgba(buffer, size); rc = write_tga(output_file, state->width, state->height, buffer, size); fflush(output_file); end: free(buffer); return rc; }