static int video_decode_test() { OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL; COMPONENT_T *list[5]; TUNNEL_T tunnel[4]; ILCLIENT_T *client; FILE *in; int status = 0; unsigned int data_len = 0; int i = 0; int cpt = 0; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if (cpt == 0){ playlistLoader(); printf("Loading the main playlist ... %i elements \n", sizeOfPlaylist); cpt++; } printf("Now playing : %s \n", playlist[i]); if((in = fopen(playlist[i], "rb")) == NULL) return -2; i += 1; if((client = ilclient_init()) == NULL) { fclose(in); return -3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return -4; } // create video_decode if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) status = -14; list[0] = video_decode; // create video_render if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[1] = video_render; // create clock if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[2] = clock; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) status = -13; // create video_scheduler if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[3] = video_scheduler; set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); set_tunnel(tunnel+2, clock, 80, video_scheduler, 12); // setup clock tunnel first if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0) status = -15; else ilclient_change_component_state(clock, OMX_StateExecuting); if(status == 0) ilclient_change_component_state(video_decode, OMX_StateIdle); memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); format.nVersion.nVersion = OMX_VERSION; format.nPortIndex = 130; format.eCompressionFormat = OMX_VIDEO_CodingAVC; if(status == 0 && OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone && ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0) { OMX_BUFFERHEADERTYPE *buf; int port_settings_changed = 0; int first_packet = 1; ilclient_change_component_state(video_decode, OMX_StateExecuting); while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL) { // feed data and wait until we get port settings changed unsigned char *dest = buf->pBuffer; data_len += fread(dest, 1, buf->nAllocLen-data_len, in); if(port_settings_changed == 0 && ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) || (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0))) { port_settings_changed = 1; if(ilclient_setup_tunnel(tunnel, 0, 0) != 0) { status = -7; break; } ilclient_change_component_state(video_scheduler, OMX_StateExecuting); // now setup tunnel to video_render if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0) { status = -12; break; } ilclient_change_component_state(video_render, OMX_StateExecuting); } if(!data_len){ fclose(in); if (i == sizeOfPlaylist) { // loop i = 0; } while((in = fopen(playlist[i], "rb")) == NULL){ i+=1; } printf("Adding to the buffer: %s \n", playlist[i]); i += 1; if (i == sizeOfPlaylist) { // loop i = 0; } } buf->nFilledLen = data_len; data_len = 0; buf->nOffset = 0; if(first_packet) { buf->nFlags = OMX_BUFFERFLAG_STARTTIME; first_packet = 0; } else buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) { status = -6; break; } } buf->nFilledLen = 0; buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) status = -20; // wait for EOS from render ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000); // need to flush the renderer to allow video_decode to disable its input port ilclient_flush_tunnels(tunnel, 0); ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); } fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); ilclient_teardown_tunnels(tunnel); ilclient_state_transition(list, OMX_StateIdle); ilclient_state_transition(list, OMX_StateLoaded); ilclient_cleanup_components(list); OMX_Deinit(); ilclient_destroy(client); return status; }
void *initServerRcam(void *VoidPtrArgs) { struct cameraControl *currentArgs = VoidPtrArgs; pthread_mutex_lock(¤tArgs->mutexPtr); ILCLIENT_T *client = currentArgs->client; pthread_mutex_unlock(¤tArgs->mutexPtr); /////////////////////////////////////////// // Variables COMPONENT_T *client_video_render = NULL; OMX_ERRORTYPE OMXstatus; OMX_BUFFERHEADERTYPE *client_video_render_in; OMX_PARAM_PORTDEFINITIONTYPE render_params; memset(&render_params, 0, sizeof(render_params)); render_params.nVersion.nVersion = OMX_VERSION; render_params.nSize = sizeof(render_params); render_params.nPortIndex = 90; enum rcam_command rcam_command = NO_COMMAND; /////////////////////////////////////////// ////Initialise client video render pthread_mutex_lock(¤tArgs->mutexPtr); ilclient_create_component(client, &client_video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS); OMXstatus = ilclient_change_component_state(client_video_render, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move render component to Idle (1)\n"); exit(EXIT_FAILURE); } //set the port params to the same as remoteCam.c // !!! // needs the checks that the local camera does // to ensure sanity as only particular values excepted (OR DOES IT ALREADY DO THIS ? IT MIGHT BE) OMXstatus = OMX_GetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Getting video render port parameters (1)"); render_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; render_params.format.video.nFrameWidth = currentArgs->previewWidth; render_params.format.video.nFrameHeight = currentArgs->previewHeight; render_params.format.video.nStride = currentArgs->previewWidth; render_params.format.video.nSliceHeight = currentArgs->previewHeight; render_params.format.video.xFramerate = currentArgs->previewFramerate << 16; OMXstatus = OMX_SetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Setting video render port parameters (1)"); //check(print) the port params memset(&render_params, 0, sizeof(render_params)); render_params.nVersion.nVersion = OMX_VERSION; render_params.nSize = sizeof(render_params); render_params.nPortIndex = 90; OMXstatus = OMX_GetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Getting video render port parameters (1)"); print_OMX_PARAM_PORTDEFINITIONTYPE(render_params); //ask ilclient to allocate buffers for client_video_render //printf("enable client_video_render_input port\n"); ilclient_enable_port_buffers(client_video_render, 90, NULL, NULL, NULL); ilclient_enable_port(client_video_render, 90); //change preview render to executing OMXstatus = ilclient_change_component_state(client_video_render, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move video render component to Executing (1)\n"); exit(EXIT_FAILURE); } printf("client_video_render state is "); printState(ilclient_get_handle(client_video_render)); printf("***\n"); //set the position on the screen setRenderConfig(client_video_render, currentArgs->displayType); ///////////////////////////////////////////////////////////////// // SOCKET STUFF printf("start of socket stuff in rcam\n"); int socket_fd = 0, client_socket_fd = 0; socket_fd = getAndBindTCPServerSocket(PORT); printf("waiting for remotecam to connect\n"); client_socket_fd = listenAndAcceptTCPServerSocket(socket_fd, 10/*backlog*/); //////////////////////////////////////////////////////////// // INITIATE RCAM_REMOTE_SLAVE char char_buffer[12]; //handshake printf("waiting to recive handshake ... \n"); read(client_socket_fd, char_buffer, 11); printf("handshake result = %s", char_buffer); write(client_socket_fd, "got\0", sizeof(char)*4); //initalize preview write(client_socket_fd, ¤tArgs->previewWidth, sizeof(currentArgs->previewWidth)); write(client_socket_fd, ¤tArgs->previewHeight, sizeof(currentArgs->previewHeight)); write(client_socket_fd, ¤tArgs->previewFramerate, sizeof(currentArgs->previewFramerate)); //initalize capture write(client_socket_fd, ¤tArgs->photoWidth, sizeof(currentArgs->photoWidth)); write(client_socket_fd, ¤tArgs->photoHeight, sizeof(currentArgs->photoHeight)); pthread_mutex_unlock(¤tArgs->mutexPtr); //////////////////////////////////////////////////////////// //// Main Thread Loop void * preview_buffer; preview_buffer = malloc(render_params.nBufferSize + 1 ); printf("***preview nBufferSize = %d\n", render_params.nBufferSize); int photo_buffer_size; void * photo_buffer; //photo_buffer = malloc(); long int num_bytes = 0; enum rcam_command current_command = START_PREVIEW; printf("current_command = %d\n", current_command); printf("sending command ..."); write(client_socket_fd, ¤t_command, sizeof(current_command)); printf("sent command\n"); current_command = NO_COMMAND; // possibly abandon current command struct // and serialize the cameraControlStruct and sent that instead // see: http://stackoverflow.com/questions/1577161/passing-a-structure-through-sockets-in-c int count = 500; while(1) { pthread_mutex_lock(¤tArgs->mutexPtr); if (currentArgs->previewChanged == true) { printf("In previewChanged\n"); //needs to: //change the renderer params this side OMXstatus = ilclient_change_component_state(client_video_render, OMX_StateIdle); memset(&render_params, 0, sizeof(render_params)); render_params.nVersion.nVersion = OMX_VERSION; render_params.nSize = sizeof(render_params); render_params.nPortIndex = 90; OMXstatus = OMX_GetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Getting video render port parameters (in loop)"); render_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; render_params.format.video.nFrameWidth = currentArgs->previewWidth; render_params.format.video.nFrameHeight = currentArgs->previewHeight; render_params.format.video.nStride = currentArgs->previewWidth; render_params.format.video.nSliceHeight = currentArgs->previewHeight; render_params.format.video.xFramerate = currentArgs->previewFramerate << 16; OMXstatus = OMX_SetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Setting video render port parameters (in loop)"); OMXstatus = ilclient_change_component_state(client_video_render, OMX_StateExecuting); //resize the preview buffer memset(&render_params, 0, sizeof(render_params)); render_params.nVersion.nVersion = OMX_VERSION; render_params.nSize = sizeof(render_params); render_params.nPortIndex = 90; OMXstatus = OMX_GetConfig(ilclient_get_handle(client_video_render), OMX_IndexParamPortDefinition, &render_params); if (OMXstatus != OMX_ErrorNone) printf("Error Getting video render port parameters (in loop)"); free(preview_buffer); preview_buffer = malloc(render_params.nBufferSize + 1); //change the preview on the remote side current_command = SET_PREVIEW_RES; write(client_socket_fd, ¤t_command, sizeof(current_command)); //send needed paramaters to rcam_remote_slave for the preview change write(client_socket_fd, ¤tArgs->previewWidth, sizeof(currentArgs->previewWidth)); write(client_socket_fd, ¤tArgs->previewHeight, sizeof(currentArgs->previewHeight)); write(client_socket_fd, ¤tArgs->previewFramerate, sizeof(currentArgs->previewFramerate)); //!!! //possibly wait for confirmation currentArgs->previewChanged = false; sleep(1); } else if (currentArgs->photoChanged == true) { printf("in photoChanged !\n"); //needs to: //change the capture res on the remote side current_command = SET_CAPTURE_RES; write(client_socket_fd, ¤t_command, sizeof(current_command)); //send needed paramaters to rcam_remote_slave for the photo change write(client_socket_fd, ¤tArgs->previewWidth, sizeof(currentArgs->previewWidth)); write(client_socket_fd, ¤tArgs->previewHeight, sizeof(currentArgs->previewHeight)); //change the photo_buffer?? read(client_socket_fd, &photo_buffer_size, sizeof(photo_buffer_size)); free(photo_buffer); photo_buffer = malloc(photo_buffer_size + 1); //!!! //possibly wait for confirmation currentArgs->photoChanged = false; } else if (currentArgs->displayChanged == true) { printf("in displayChanged !\n"); setRenderConfig(client_video_render, currentArgs->displayType); currentArgs->displayChanged = false; } else if (currentArgs->takePhoto == true) { printf("in takePhoto !\n"); //needs to: //send command and then recive the capture current_command = TAKE_PHOTO; write(client_socket_fd, ¤t_command, sizeof(current_command)); currentArgs->takePhoto = false; printf("end of take photo\n"); } //loop terminationcurrent_command = TAKE_PHOTO; else if(currentArgs->rcamDeInit) { printf("in rcamDiInit !\n"); current_command = END_REMOTE_CAM; write(client_socket_fd, ¤t_command, sizeof(current_command)); printf("END_REMOTE_CAM sent\n"); break; //exits loop and ultimatly ends this pthread } else { printf("no commands in struct to parse !\n"); //send no command current_command = NO_COMMAND; write(client_socket_fd, ¤t_command, sizeof(current_command)); //printf("get a buffer to process\n"); //printf("waiting to recv buffer of size %d... ", render_params.nBufferSize); num_bytes = read(client_socket_fd, preview_buffer, render_params.nBufferSize); while (num_bytes < render_params.nBufferSize) { num_bytes += read(client_socket_fd, preview_buffer + num_bytes, render_params.nBufferSize - num_bytes); } //printf("buffer recived, recived %ld bytes\n", num_bytes); //change nAllocLen in bufferheader client_video_render_in = ilclient_get_input_buffer(client_video_render, 90, 1); memcpy(client_video_render_in->pBuffer, preview_buffer, render_params.nBufferSize); //printf("copied buffer form preview_buffer into client_video_render_in\n"); client_video_render_in->nFilledLen = render_params.nBufferSize; //empty buffer into render component OMX_EmptyThisBuffer(ilclient_get_handle(client_video_render), client_video_render_in); count++; //printf("Emptied buffer --- count = %d\n", count); } pthread_mutex_unlock(¤tArgs->mutexPtr); usleep(500); } //////////////////////////////////////////////////////////// //// end of thread, Cleanup //free buffer memory free(preview_buffer); printf("preview_buffer memory free\n"); //!free ilobjects and make sure all allocated memory is free! //!free sockets try to ensure no zombies printf("exiting rcam thread"); pthread_exit(NULL); }
void *initLocalCamera(void *VoidPtrArgs) { struct cameraControl *currentArgs = VoidPtrArgs; pthread_mutex_lock(¤tArgs->mutexPtr); ILCLIENT_T *client = currentArgs->client; pthread_mutex_unlock(¤tArgs->mutexPtr); ////////////////// //VARIABLES COMPONENT_T *camera = NULL, *video_render = NULL, *image_encode = NULL; COMPONENT_T *component_list[3] = {camera, video_render, image_encode}; COMPONENT_T *image_encode_list[1] = {image_encode}; //needed to destroy component? OMX_ERRORTYPE OMXstatus; TUNNEL_T tunnel_camera_to_render, tunnel_camera_to_encode; memset(&tunnel_camera_to_render, 0, sizeof(tunnel_camera_to_render)); memset(&tunnel_camera_to_encode, 0, sizeof(tunnel_camera_to_encode)); ////////////////// // STARTUP ////////////////// // Initalize Components ////////////////// ////initialise camera ilclient_create_component(client, &camera, "camera", ILCLIENT_DISABLE_ALL_PORTS); OMXstatus = ilclient_change_component_state(camera, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move camera component to Idle (1)"); exit(EXIT_FAILURE); } //change the capture resolution setCaptureRes(camera, currentArgs->photoWidth, currentArgs->photoHeight); //change the preview resolution setPreviewRes(camera, currentArgs->previewWidth, currentArgs->previewHeight, currentArgs->previewFramerate); ////////////////// ////Initialise video render ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS ); OMXstatus = ilclient_change_component_state(video_render, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move render component to Idle (1)\n"); exit(EXIT_FAILURE); } setRenderConfig(video_render, currentArgs->displayType); //////////////////// ////Initalise Image Encoder ilclient_create_component(client, &image_encode, "image_encode", ILCLIENT_DISABLE_ALL_PORTS /*| ILCLIENT_ENABLE_INPUT_BUFFERS*/ | ILCLIENT_ENABLE_OUTPUT_BUFFERS); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image encode component to Idle (1)\n"); exit(EXIT_FAILURE); } //image format Param set setParamImageFormat(image_encode, JPEG_HIGH_FORMAT); //////////////////// // enable components and tunnels //setup tunnel of camera preview to renderer set_tunnel(&tunnel_camera_to_render, camera, 70, video_render, 90); ilclient_setup_tunnel(&tunnel_camera_to_render, 0, 0); // change camera component to executing OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move camera component to Executing (1)\n"); exit(EXIT_FAILURE); } //change preview render to executing OMXstatus = ilclient_change_component_state(video_render, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move video render component to Executing (1)\n"); exit(EXIT_FAILURE); } //enable port and buffers for output port of image encode ilclient_enable_port_buffers(image_encode, 341, NULL, NULL, NULL); ilclient_enable_port(image_encode, 341); //setup tunnel from camera image port too image encode set_tunnel(&tunnel_camera_to_encode, camera, 72, image_encode, 340); ilclient_setup_tunnel(&tunnel_camera_to_encode, 0, 0); //change image_encode to executing OMXstatus = ilclient_change_component_state(image_encode, OMX_StateExecuting); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image_encode component to Executing (1) Error = %s\n", err2str(OMXstatus)); exit(EXIT_FAILURE); } ///////////////// // Main initLocalCamera() Loop while(1) { pthread_mutex_lock(¤tArgs->mutexPtr); if (currentArgs->previewChanged == true) { //working ilclient_disable_tunnel(&tunnel_camera_to_render); OMXstatus = ilclient_change_component_state(camera, OMX_StatePause); setPreviewRes(camera, currentArgs->previewWidth, currentArgs->previewHeight, currentArgs->previewFramerate); OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); ilclient_enable_tunnel(&tunnel_camera_to_render); currentArgs->previewChanged = false; } else if (currentArgs->photoChanged == true) { //NOT WORKING? CANT GET WORKING!! //TUNNEL_T *tunnel_ptr = &tunnel_camera_to_encode; ilclient_disable_tunnel(&tunnel_camera_to_encode); ilclient_flush_tunnels(&tunnel_camera_to_encode, 30); //ilclient_teardown_tunnels(&tunnel_camera_to_encode); //printf("teardown done"); setCaptureRes(camera, currentArgs->photoWidth, currentArgs->photoHeight); // DESTROY image encode and recreate (appears to be the only way) //destory OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateLoaded); //OMX_FreeHandle(ilclient_get_handle(image_encode)); ilclient_cleanup_components(image_encode_list); printf("managed to free the image_encode handle"); image_encode = NULL; //recreate ilclient_create_component(client, &image_encode, "image_encode", ILCLIENT_DISABLE_ALL_PORTS /*| ILCLIENT_ENABLE_INPUT_BUFFERS*/ | ILCLIENT_ENABLE_OUTPUT_BUFFERS); OMXstatus = ilclient_change_component_state(image_encode, OMX_StateIdle); if (OMXstatus != OMX_ErrorNone) { fprintf(stderr, "unable to move image encode component to Idle (1)\n"); exit(EXIT_FAILURE); } //image format Param set setParamImageFormat(image_encode, JPEG_HIGH_FORMAT); //OMXstatus = ilclient_change_component_state(camera, OMX_StateExecuting); ilclient_enable_tunnel(&tunnel_camera_to_encode); currentArgs->photoChanged = false; } else if (currentArgs->displayChanged == true) { //working setRenderConfig(video_render, currentArgs->displayType); currentArgs->displayChanged = false; } else if (currentArgs->takePhoto == true) { //working savePhoto(camera, image_encode, "/home/pi/Desktop/photo_", "_L.jpg"); currentArgs->takePhoto = false; } //loop termination else if (currentArgs->rcamDeInit == true) { //working printf("~~~~~ End local camera ~~~~~\n"); break; } pthread_mutex_unlock(¤tArgs->mutexPtr); usleep(500); } /////////////// //CLEANUP // Teardown tunnels ilclient_disable_tunnel(&tunnel_camera_to_render); ilclient_disable_tunnel(&tunnel_camera_to_encode); ilclient_teardown_tunnels(&tunnel_camera_to_render); ilclient_teardown_tunnels(&tunnel_camera_to_encode); // Disable components ilclient_cleanup_components(component_list); //Destroy ilclient // dont do for local as its done in main program //ilclient_destroy(currentArgs->client) //unlock mutex before teminating pthread_mutex_unlock(¤tArgs->mutexPtr); //call pthread_exit so caller can join pthread_exit(NULL); }
int32_t ilctts_create( TTSRENDER_STATE_T **component, uint32_t sample_rate, uint32_t num_channels, uint32_t bit_depth, uint32_t num_buffers, uint32_t buffer_size_ms, BUFFER_SIZE_TYPE_T buffer_size_type, uint32_t ringbuffer_length ) { ENTER(LOGLEVEL_1, "ilctts_create"); SHOW(LOGLEVEL_5, "Sample rate: %d", sample_rate); SHOW(LOGLEVEL_5, "Number of channels: %d", num_channels); SHOW(LOGLEVEL_5, "Bit depth: %d", bit_depth); SHOW(LOGLEVEL_5, "Number of buffers: %d", num_buffers); SHOW(LOGLEVEL_5, "Buffer size: %d", buffer_size_ms); SHOW(LOGLEVEL_5, "Ring buffer length: %d", ringbuffer_length); int32_t ret; uint32_t buffer_size; OMX_ERRORTYPE omx_err; TTSRENDER_STATE_T *st; *component = NULL; st = calloc(1, sizeof(TTSRENDER_STATE_T)); OMX_PARAM_PORTDEFINITIONTYPE param; OMX_AUDIO_PARAM_PCMMODETYPE pcm; int32_t s; *component = st; // create and start up everything // initialise buffer list semaphore s = sem_init(&st->buffer_list_sema, 0, 1); if (s < 0) { ERROR("sem_init returned error initializing buffer list semaphore in ilctts_create: %d", s); return -1; } // initial value of ringbuffer_empty_sema is 1 because at startup there is space s = sem_init(&st->ringbuffer_empty_sema, 0, 1); if (s < 0) { ERROR("sem_init returned error initializing ringbuffer_empty_sema in ilctts_create: %d", s); return -1; } // initial value of ringbuffer_data_sema is 0 because at startup there is no data s = sem_init(&st->ringbuffer_data_sema, 0, 0); if (s < 0) { ERROR("sem_init returned error initializing ringbuffer_data_sema in ilctts_create: %d", s); return -1; } // free_buffer mutex and cv pthread_mutex_init(&st->free_buffer_mutex, NULL); pthread_cond_init(&st->free_buffer_cv, NULL); // ringbuffer mutex pthread_mutex_init(&st->ringbuffer_mutex, NULL); //pthread_cond_init(&st->ringbuffer_cv, NULL); st->sample_rate = sample_rate; st->num_channels = num_channels; st->bit_depth = bit_depth; st->bytes_per_sample = (bit_depth * OUT_CHANNELS(num_channels)) >> 3; if (buffer_size_type == BS_MILLISECONDS) { // supplied buffer size was in milliseconds, calculate the byte size // note: calc_buffer_size_from_ms returns buffer size aligned for VCHI buffer_size = calc_buffer_size_from_ms(sample_rate, bit_depth, num_channels, buffer_size_ms, 1); } else { // supplied buffer size was in bytes // buffer size must be 16 byte aligned for VCHI buffer_size = (buffer_size_ms + 15) & ~15; } SHOW(LOGLEVEL_5, "Bytes per sample: %d", st->bytes_per_sample); SHOW(LOGLEVEL_5, "Calculated buffer size: %d", buffer_size); st->num_buffers = num_buffers; st->client = ilclient_init(); st->tts_stop = 0; st->tts_pause_state = TTS_PAUSE_OFF; st->ringbuffer = ringbuffer_init(ringbuffer_length); if (st->ringbuffer == NULL) { ERROR("ringbuffer_init failed in ilctts_create", ""); return -1; } // set up callbacks ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st); //ilclient_set_configchanged_callback(st->client, config_changed_callback, st); //ilclient_set_port_settings_callback(st->client, port_settings_changed_callback, st); ret = ilclient_create_component(st->client, &st->audio_render, "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS); if (ret == -1) { ERROR("ilclcient_create_component returned error in ilctts_create: %d", ret); return ret; } st->list[0] = st->audio_render; // set up the number/size of buffers OMX_INIT_STRUCTURE(param); param.nPortIndex = 100; omx_err = OMX_GetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); if (omx_err != OMX_ErrorNone) { ERROR("OMX_GetParameter returned error in ilctts_create: %d", omx_err); return -1; } // set the buffer size to the requested size, or the minimum size returned, whichever is greater st->buffer_size = max(buffer_size, param.nBufferSize); SHOW(LOGLEVEL_3, "Buffer size set to: %d", st->buffer_size); param.nBufferSize = st->buffer_size; param.nBufferCountActual = max(st->buffer_count, param.nBufferCountMin); omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err); return -1; } // set the pcm parameters OMX_INIT_STRUCTURE(pcm); pcm.nPortIndex = 100; pcm.nChannels = OUT_CHANNELS(num_channels); pcm.eNumData = OMX_NumericalDataSigned; pcm.eEndian = OMX_EndianLittle; pcm.nSamplingRate = sample_rate; pcm.bInterleaved = OMX_TRUE; pcm.nBitPerSample = bit_depth; pcm.ePCMMode = OMX_AUDIO_PCMModeLinear; switch(st->num_channels) { case 1: pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF; break; case 3: pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; break; case 8: pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS; case 7: pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS; case 6: pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR; case 5: pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR; case 4: pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; case 2: pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; break; } omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err); return -1; } // this function waits for the command to complete ret = ilclient_change_component_state(st->audio_render, OMX_StateIdle); if (ret < 0) { ERROR("ilctts_change_component_state returned error in ilctts_create: %d", ret); return -1; } ret = ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL); if (ret < 0) { ERROR("ilclient_enable_port_buffers returned error in ilctts_create: %d", ret); ilclient_change_component_state(st->audio_render, OMX_StateLoaded); ilclient_cleanup_components(st->list); omx_err = OMX_Deinit(); ilclient_destroy(st->client); destroy_semaphores(st); destroy_mutexes(st); ringbuffer_destroy(st->ringbuffer); // need to destroy and free other stuff here? free(st); *component = NULL; return -1; } INFO(LOGLEVEL_1, "Setting state to executing in ilctts_create"); return ilclient_change_component_state(st->audio_render, OMX_StateExecuting); } // end ilctts_create
static int video_decode_test(char *filename) { OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL; COMPONENT_T *list[5]; TUNNEL_T tunnel[4]; ILCLIENT_T *client; FILE *in; int status = 0; unsigned char *data = NULL; unsigned int data_len = 0; int find_start_codes = 0; int packet_size = 16<<10; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return -2; if((client = ilclient_init()) == NULL) { fclose(in); return -3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return -4; } if(find_start_codes && (data = malloc(packet_size+4)) == NULL) { status = -16; if(OMX_Deinit() != OMX_ErrorNone) status = -17; ilclient_destroy(client); fclose(in); return status; } // create video_decode if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) status = -14; list[0] = video_decode; // create video_render if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[1] = video_render; // create clock if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[2] = clock; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) status = -13; // create video_scheduler if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[3] = video_scheduler; set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); set_tunnel(tunnel+2, clock, 80, video_scheduler, 12); // setup clock tunnel first if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0) status = -15; else ilclient_change_component_state(clock, OMX_StateExecuting); if(status == 0) ilclient_change_component_state(video_decode, OMX_StateIdle); memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); format.nVersion.nVersion = OMX_VERSION; format.nPortIndex = 130; format.eCompressionFormat = OMX_VIDEO_CodingAVC; if(status == 0 && OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone && ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0) { OMX_BUFFERHEADERTYPE *buf; int port_settings_changed = 0; int first_packet = 1; ilclient_change_component_state(video_decode, OMX_StateExecuting); while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL) { // feed data and wait until we get port settings changed unsigned char *dest = find_start_codes ? data + data_len : buf->pBuffer; data_len += fread(dest, 1, packet_size+(find_start_codes*4)-data_len, in); if(port_settings_changed == 0 && ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) || (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0))) { port_settings_changed = 1; if(ilclient_setup_tunnel(tunnel, 0, 0) != 0) { status = -7; break; } ilclient_change_component_state(video_scheduler, OMX_StateExecuting); // now setup tunnel to video_render if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0) { status = -12; break; } ilclient_change_component_state(video_render, OMX_StateExecuting); } if(!data_len) break; if(find_start_codes) { int i, start = -1, len = 0; int max_len = data_len > packet_size ? packet_size : data_len; for(i=2; i<max_len; i++) { if(data[i-2] == 0 && data[i-1] == 0 && data[i] == 1) { len = 3; start = i-2; // check for 4 byte start code if(i > 2 && data[i-3] == 0) { len++; start--; } break; } } if(start == 0) { // start code is next, so just send that buf->nFilledLen = len; } else if(start == -1) { // no start codes seen, send the first block buf->nFilledLen = max_len; } else { // start code in the middle of the buffer, send up to the code buf->nFilledLen = start; } memcpy(buf->pBuffer, data, buf->nFilledLen); memmove(data, data + buf->nFilledLen, data_len - buf->nFilledLen); data_len -= buf->nFilledLen; } else { buf->nFilledLen = data_len; data_len = 0; } buf->nOffset = 0; if(first_packet) { buf->nFlags = OMX_BUFFERFLAG_STARTTIME; first_packet = 0; } else buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) { status = -6; break; } } buf->nFilledLen = 0; buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) status = -20; // wait for EOS from render ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000); // need to flush the renderer to allow video_decode to disable its input port ilclient_flush_tunnels(tunnel, 0); ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); } fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); ilclient_teardown_tunnels(tunnel); ilclient_state_transition(list, OMX_StateIdle); ilclient_state_transition(list, OMX_StateLoaded); ilclient_cleanup_components(list); OMX_Deinit(); ilclient_destroy(client); return status; }
void native_audio_init() { OMX_ERRORTYPE error; OMX_PARAM_PORTDEFINITIONTYPE param; OMX_AUDIO_PARAM_PCMMODETYPE pcm; int32_t s; // create and start up everything client = ilclient_init(); assert(client != NULL); error = OMX_Init(); assert(error == OMX_ErrorNone); ilclient_create_component(client, &audio_render, "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS); assert(audio_render != NULL); // set up the number/size of buffers memset(¶m, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); param.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); param.nVersion.nVersion = OMX_VERSION; param.nPortIndex = 100; error = OMX_GetParameter(ILC_GET_HANDLE(audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); int size = scaled_buffer_size(NUM_SAMPLES); size = (size + 15) & ~15; param.nBufferSize = size; param.nBufferCountActual = 2; error = OMX_SetParameter(ILC_GET_HANDLE(audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); // set the pcm parameters memset(&pcm, 0, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); pcm.nSize = sizeof(OMX_AUDIO_PARAM_PCMMODETYPE); pcm.nVersion.nVersion = OMX_VERSION; pcm.nPortIndex = 100; pcm.nChannels = 2; pcm.eNumData = OMX_NumericalDataSigned; pcm.eEndian = OMX_EndianLittle; pcm.nSamplingRate = SAMPLE_FREQ; pcm.bInterleaved = OMX_TRUE; pcm.nBitPerSample = 16; pcm.ePCMMode = OMX_AUDIO_PCMModeLinear; pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; error = OMX_SetParameter(ILC_GET_HANDLE(audio_render), OMX_IndexParamAudioPcm, &pcm); assert(error == OMX_ErrorNone); assert(ilclient_change_component_state(audio_render, OMX_StateIdle) == 0); if(ilclient_enable_port_buffers(audio_render, 100, NULL, NULL, NULL) < 0) { // error ilclient_change_component_state(audio_render, OMX_StateLoaded); COMPONENT_T* list[2]; list[0] = audio_render; list[1] = 0; ilclient_cleanup_components(list); error = OMX_Deinit(); assert(error == OMX_ErrorNone); ilclient_destroy(client); exit(-1); } assert(ilclient_change_component_state(audio_render, OMX_StateExecuting) == 0); // set the destination OMX_CONFIG_BRCMAUDIODESTINATIONTYPE ar_dest; const char* name = "hdmi"; memset(&ar_dest, 0, sizeof(ar_dest)); ar_dest.nSize = sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE); ar_dest.nVersion.nVersion = OMX_VERSION; strcpy((char *)ar_dest.sName, name); error = OMX_SetConfig(ILC_GET_HANDLE(audio_render), OMX_IndexConfigBrcmAudioDestination, &ar_dest); assert(error == OMX_ErrorNone); // get the buffer flow going pthread_create(&audio_thread, NULL, audio_exec, NULL); }