int decoding_thread_setSpeed(float speed){ printf("try to lock thread\n"); if(ILC_GET_HANDLE(omx_clock) == NULL) return -1; pthread_mutex_lock(&m_lock); OMX_ERRORTYPE omx_err = OMX_ErrorNone; OMX_TIME_CONFIG_SCALETYPE scaleType; OMX_INIT_STRUCTURE(scaleType); scaleType.xScale = floor((speed * pow(2,16))); printf("set speed to : %.2f, %d\n", speed, scaleType.xScale); omx_err = OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeScale, &scaleType); if(omx_err != OMX_ErrorNone) { printf("Speed error setting OMX_IndexConfigTimeClockState : %d\n", omx_err); pthread_mutex_unlock(&m_lock); return -1; } printf("unlock thread\n"); pthread_mutex_unlock(&m_lock); return 0; }
static int prepareResizer(OMX_RESIZER *resizer){ int ret = ilclient_create_component(resizer->client, &resizer->component, "resize", ILCLIENT_DISABLE_ALL_PORTS| ILCLIENT_ENABLE_INPUT_BUFFERS| ILCLIENT_ENABLE_OUTPUT_BUFFERS); if (ret != 0) { return OMX_IMAGE_ERROR_CREATING_COMP; } resizer->handle = ILC_GET_HANDLE(resizer->component); OMX_PORT_PARAM_TYPE port; port.nSize = sizeof(OMX_PORT_PARAM_TYPE); port.nVersion.nVersion = OMX_VERSION; OMX_GetParameter(resizer->handle,OMX_IndexParamImageInit, &port); if (port.nPorts != 2) { return OMX_IMAGE_ERROR_PORTS; } resizer->inPort = port.nStartPortNumber; resizer->outPort = port.nStartPortNumber + 1; resizer->pOutputBufferHeader = NULL; return OMX_IMAGE_OK; }
int32_t ilctts_delete(TTSRENDER_STATE_T *st) { int32_t ret; OMX_ERRORTYPE omx_err; ret = ilclient_change_component_state(st->audio_render, OMX_StateIdle); if (ret < 0) { ERROR("ilctts_change_component_state returned error in ilctts_delete: %d", ret); return -1; } omx_err = OMX_SendCommand(ILC_GET_HANDLE(st->audio_render), OMX_CommandStateSet, OMX_StateLoaded, NULL); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SendCommand returned error in ilctts_delete: %d", omx_err); return -1; } ilclient_disable_port_buffers(st->audio_render, 100, st->user_buffer_list, NULL, NULL); ilclient_change_component_state(st->audio_render, OMX_StateLoaded); ilclient_cleanup_components(st->list); ilclient_destroy(st->client); //sem_destroy(&st->buffer_list_sema); destroy_semaphores(st); destroy_mutexes(st); free(st); return 0; } // end ilctts_delete
void* audio_exec(void* udata) { float buffer_time_us = (float)(1e6 * NUM_SAMPLES) / SAMPLE_FREQ; while(1) { /* get a buffer */ OMX_BUFFERHEADERTYPE *hdr; while((hdr = ilclient_get_input_buffer(audio_render, 100, 0)) == NULL) { usleep(buffer_time_us / 4); // wait 1/4 of the time to drain a buffer } // fill the buffer audio_fill_buffer((int16_t*)hdr->pBuffer, NUM_SAMPLES * 2); hdr->nOffset = 0; hdr->nFilledLen = scaled_buffer_size(NUM_SAMPLES); // submit the buffer OMX_ERRORTYPE error; error = OMX_EmptyThisBuffer(ILC_GET_HANDLE(audio_render), hdr); assert(error == OMX_ErrorNone); // drive down the latency to a buffer's length or less uint32_t latency; while(audio_get_latency() > NUM_SAMPLES) { usleep(buffer_time_us / 2); } } }
static void input_buffer_callback(void *data, COMPONENT_T *comp) { TTSRENDER_STATE_T *st = (TTSRENDER_STATE_T*)data; ILC_GET_HANDLE(comp); // just to suppress warnings about unused parameter pthread_mutex_lock(&st->free_buffer_mutex); pthread_cond_signal(&st->free_buffer_cv); pthread_mutex_unlock(&st->free_buffer_mutex); } // end input_buffer_callback
int32_t ilctts_flush(TTSRENDER_STATE_T *st) { OMX_ERRORTYPE omx_err; omx_err = OMX_SendCommand(ILC_GET_HANDLE(st->audio_render), OMX_CommandFlush, -1, NULL); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SendCommand returned error in ilctts_flush: %d", omx_err); return -1; } return 0; } // end ilctts_flush
int32_t ilctts_get_state(TTSRENDER_STATE_T *st, OMX_STATETYPE *state) { OMX_ERRORTYPE omx_err = OMX_GetState(ILC_GET_HANDLE(st->audio_render), state); if (omx_err != OMX_ErrorNone) { ERROR("OMX_GetState returned error in ilctts_get_state: %d", omx_err); return -1; } return 0; } // end ilctts_get_state
int prepareResizer(OPENMAX_JPEG_DECODER * decoder) { decoder->imageResizer = malloc(sizeof(COMPONENT_DETAILS)); if (decoder->imageResizer == NULL) { perror("malloc image resizer"); return OMXJPEG_ERROR_MEMORY; } int ret = ilclient_create_component(decoder->client, &decoder-> imageResizer-> component, "resize", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_ENABLE_OUTPUT_BUFFERS); if (ret != 0) { perror("image resizer"); return OMXJPEG_ERROR_CREATING_COMP; } // grab the handle for later use decoder->imageResizer->handle = ILC_GET_HANDLE(decoder->imageResizer->component); // get and store the ports OMX_PORT_PARAM_TYPE port; port.nSize = sizeof(OMX_PORT_PARAM_TYPE); port.nVersion.nVersion = OMX_VERSION; OMX_GetParameter(ILC_GET_HANDLE(decoder->imageResizer->component), OMX_IndexParamImageInit, &port); if (port.nPorts != 2) { return OMXJPEG_ERROR_WRONG_NO_PORTS; } decoder->imageResizer->inPort = port.nStartPortNumber; decoder->imageResizer->outPort = port.nStartPortNumber + 1; decoder->pOutputBufferHeader = NULL; return OMXJPEG_OK; }
uint32_t ilctts_get_latency(TTSRENDER_STATE_T *st) { OMX_PARAM_U32TYPE param; OMX_ERRORTYPE omx_err; OMX_INIT_STRUCTURE(param); param.nPortIndex = 100; omx_err = OMX_GetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigAudioRenderingLatency, ¶m); if (omx_err != OMX_ErrorNone) { ERROR("OMX_GetConfig returned error in ilctts_get_latency: %d", omx_err); return -1; } return param.nU32; } // end ilctts_get_latency
uint32_t audio_get_latency() { OMX_PARAM_U32TYPE param; OMX_ERRORTYPE error; memset(¶m, 0, sizeof(OMX_PARAM_U32TYPE)); param.nSize = sizeof(OMX_PARAM_U32TYPE); param.nVersion.nVersion = OMX_VERSION; param.nPortIndex = 100; error = OMX_GetConfig(ILC_GET_HANDLE(audio_render), OMX_IndexConfigAudioRenderingLatency, ¶m); assert(error == OMX_ErrorNone); return param.nU32; }
bool encode_config_input(COMPONENT_T* handle, int32_t width, int32_t height, int32_t framerate, OMX_COLOR_FORMATTYPE colorFormat) { OMX_ERRORTYPE omx_return; // get current settings of video_encode component from port 200 OMX_PARAM_PORTDEFINITIONTYPE def; memset(&def, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); def.nVersion.nVersion = OMX_VERSION; def.nPortIndex = 200; if (OMX_GetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamPortDefinition, &def) != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_GetParameter() for video_encode port 200 failed!\n", __FUNCTION__, __LINE__); return NULL; } print_def(def); def.format.video.nFrameWidth = width; def.format.video.nFrameHeight = height; def.format.video.xFramerate = framerate << 16; def.format.video.nSliceHeight = def.format.video.nFrameHeight; def.format.video.nStride = (def.format.video.nFrameWidth + def.nBufferAlignment - 1) & (~(def.nBufferAlignment - 1)); def.format.video.eColorFormat = colorFormat; print_def(def); omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamPortDefinition, &def); if (omx_return != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_SetParameter() for video_encode port 200 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); return false; } return true; }
int32_t ilctts_set_volume(TTSRENDER_STATE_T *st, unsigned int vol) { OMX_ERRORTYPE omx_err; OMX_AUDIO_CONFIG_VOLUMETYPE volume; OMX_INIT_STRUCTURE(volume); vol = min(100, vol); volume.nPortIndex = 100; volume.sVolume.nValue = vol; omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigAudioVolume, &volume); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetParameter returned error in ilctts_set_volume: %d", omx_err); return -1; } return 0; } // end ilctts_set_volume
/* ------------------------------------------------- / sx_audio_sink_playback_speed_reset() / TODO why?? /---------------------------------------------------*/ void sx_audio_sink_playback_speed_rset(void){ OMX_TIME_CONFIG_SCALETYPE scale; OMX_ERRORTYPE error; memset(&scale, 0, sizeof(OMX_TIME_CONFIG_SCALETYPE)); scale.nSize = sizeof(OMX_TIME_CONFIG_SCALETYPE); scale.nVersion.nVersion = OMX_VERSION; scale.xScale = 65536; ///< normal speed 0x00010000 error = OMX_SetConfig(ILC_GET_HANDLE(st->clock), OMX_IndexConfigTimeScale, &scale); assert(error == OMX_ErrorNone); }
int32_t ilctts_send_audio(TTSRENDER_STATE_T *st, uint8_t *buffer, uint32_t length) { OMX_BUFFERHEADERTYPE *hdr = NULL, *prev = NULL; int32_t ret = -1; if(length % st->bytes_per_sample) { ERROR("length invalid in ilctts_send_audio: %d", length); return -1; } if (length > st->buffer_size) { ERROR("length exceeds component buffer size in ilctts_send_audio: %d, buffer size: %d", length, st->buffer_size); return -1; } sem_wait(&st->buffer_list_sema); // search through user list for the right buffer header hdr = st->user_buffer_list; while(hdr != NULL && hdr->pBuffer != buffer && hdr->nAllocLen < length) { prev = hdr; hdr = hdr->pAppPrivate; } if(hdr) { // we found it, remove from list ret = 0; if(prev) prev->pAppPrivate = hdr->pAppPrivate; else st->user_buffer_list = hdr->pAppPrivate; } sem_post(&st->buffer_list_sema); if(hdr) { OMX_ERRORTYPE omx_err; hdr->pAppPrivate = NULL; hdr->nOffset = 0; hdr->nFilledLen = length; INFO(LOGLEVEL_5, "Calling empty_this_buffer"); omx_err = OMX_EmptyThisBuffer(ILC_GET_HANDLE(st->audio_render), hdr); if (omx_err != OMX_ErrorNone) { ERROR("OMX_EmptyThisBuffer returned error in ilctts_send_audio: %d", omx_err); return -1; } } return ret; } // end ilctts_send_audio
/* ------------------------------------------------- / audioplay_play_buffer() / TODO why?> /---------------------------------------------------*/ INT32 audioplay_play_buffer( AUDIOPLAY_STATE_T *st, UINT8 *buffer, UINT32 length ){ OMX_BUFFERHEADERTYPE *hdr = NULL, *prev = NULL; INT32 ret = -1; if(length % st->bytes_per_sample) return ret; sem_wait(&st->sema); /* search through user list for the right buffer header */ hdr = st->user_buffer_list; while(hdr != NULL && hdr->pBuffer != buffer && hdr->nAllocLen < length){ prev = hdr; hdr = hdr->pAppPrivate; } /* we found it , remove from list */ if(hdr){ ret = 0; if(prev){ prev->pAppPrivate = hdr->pAppPrivate; }else{ st->user_buffer_list = hdr->pAppPrivate; } } sem_post(&st->sema); if(hdr){ OMX_ERRORTYPE error; hdr->pAppPrivate = NULL; hdr->nOffset = 0; hdr->nFilledLen = length; error = OMX_EmptyThisBuffer(ILC_GET_HANDLE(st->audio_render), hdr); assert(error == OMX_ErrorNone); } return ret; }
/* ------------------------------------------------- / sx_video_sink_buf_set() / /---------------------------------------------------*/ void sx_video_sink_buf_set( sDECODER_HW_BUFFER *decoder_hw_buf ){ OMX_BUFFERHEADERTYPE *buf; int rc; buf = (OMX_BUFFERHEADERTYPE *) decoder_hw_buf; if(!port_setting_changed && (ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0)){ printf("(decoder_hw): port setting changed!\n"); port_setting_changed = 1; /* Setup tunnel for ... */ rc = ilclient_setup_tunnel(tunnel, 0 ,0); assert(rc = 0); /* Kick start scheduler */ ilclient_change_component_state(video_scheduler, OMX_StateExecuting); rc = ilclient_setup_tunnel(tunnel+1, 0, 1000); ///< TODO 1000? assert(rc == 0); /* Kick start render */ ilclient_change_component_state(video_render, OMX_StateExecuting); } /* Set buffer property */ buf->nOffset = 0; buf->nFlags = first_packet ? OMX_BUFFERFLAG_STARTTIME : OMX_BUFFERFLAG_TIME_UNKNOWN; first_packet = 0; /* Flush into the decoder */ rc = OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf); assert(rc == 0); }
static void omx_renderer_cleanup() { if (decoder != NULL) opus_multistream_decoder_destroy(decoder); if (handle != NULL) { if((buf = ilclient_get_input_buffer(component, 100, 1)) == NULL){ fprintf(stderr, "Can't get audio buffer\n"); exit(EXIT_FAILURE); } buf->nFilledLen = 0; buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(component), buf) != OMX_ErrorNone){ fprintf(stderr, "Can't empty audio buffer\n"); return; } ilclient_disable_port_buffers(component, 100, NULL, NULL, NULL); ilclient_change_component_state(component, OMX_StateIdle); ilclient_change_component_state(component, OMX_StateLoaded); } }
int32_t ilctts_set_dest(TTSRENDER_STATE_T *st, const char *name) { OMX_ERRORTYPE omx_err; OMX_CONFIG_BRCMAUDIODESTINATIONTYPE dest; char device[8]; if ( (strcmp(name, "local") != 0) && (strcmp(name, "hdmi") != 0) ) strcpy(device, "local"); else strcpy(device, name); OMX_INIT_STRUCTURE(dest); strcpy((char *)dest.sName, device); omx_err = OMX_SetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigBrcmAudioDestination, &dest); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetConfig returned error in ilctts_set_dest: %d", omx_err); return -1; } SHOW(LOGLEVEL_3, "Audio device set to: %s", device); return 0; } // end ilctts_set_dest
/* ------------------------------------------------- / audioplay_set_dest() / Set audio render destination /---------------------------------------------------*/ static INT32 audioplay_set_dest( AUDIOPLAY_STATE_T *st, const char *name ){ INT32 success = -1; /* TODO OMX_CONFIG_BRCMAUDIODESTINATIONTYPE *ar_dest , strcpy((char *)&(ar_dest->sName), name) */ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE ar_dest; if(name && strlen(name) < sizeof(ar_dest.sName)){ OMX_ERRORTYPE error; 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(st->audio_render), OMX_IndexConfigBrcmAudioDestination, &ar_dest); assert(error == OMX_ErrorNone); success = 0; } return success; }
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 int data_len = 0; 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; } // 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) break; 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); } fclose(in); ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel+1); ilclient_disable_tunnel(tunnel+2); ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); 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); }
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 image_decode_test(char *filename) { OMX_BUFFERHEADERTYPE *pIbuf; int bytes_read; int status = 0, ret; int port_settings_changed = 0; OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat; COMPONENT_T *image_decode = NULL; COMPONENT_T *video_render = NULL; COMPONENT_T *list[3]; TUNNEL_T tunnel[2]; ILCLIENT_T *client; FILE *fin; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((fin = fopen(filename, "rb")) == NULL ) { perror(filename); return -1; } if((client = ilclient_init()) == NULL) { return -3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(fin); return -4; } #if 0 //this was an attempt to use the image_read component COMPONENT_T *image_read; // create image_read if(ilclient_create_component(client, &image_read, "image_read", ILCLIENT_DISABLE_ALL_PORTS ) != 0) status = -14; //set URI OMX_PARAM_CONTENTURITYPE *pUri; sz = sizeof(pUri)+strlen(filename); pUri = (OMX_PARAM_CONTENTURITYPE*)calloc(1, sz); pUri->nSize = sz; pUri->nVersion.nVersion = OMX_VERSION; strcpy(pUri->contentURI, filename); if(image_read != NULL && OMX_SetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamContentURI, pUri) != 0) status = -17; //enable port ilclient_enable_port(image_read, 310); //get OMX_IndexParamPortDefinition { OMX_PARAM_PORTDEFINITIONTYPE portDef; portDef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portDef.nVersion.nVersion = OMX_VERSION; portDef.nPortIndex = 310; ret = OMX_GetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamPortDefinition, &portDef); } //get OMX_IndexParamImagePortFormat i=0; while(ret == 0) { OMX_IMAGE_PARAM_PORTFORMATTYPE portFormat; portFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); portFormat.nVersion.nVersion = OMX_VERSION; portFormat.nPortIndex = 310; portFormat.nIndex = i; ret = OMX_GetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamImagePortFormat, &portFormat); i++; } { OMX_IMAGE_PARAM_PORTFORMATTYPE portFormat; portFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); portFormat.nVersion.nVersion = OMX_VERSION; portFormat.nPortIndex = 310; portFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; ret = OMX_SetParameter(ILC_GET_HANDLE(image_read), OMX_IndexParamImagePortFormat, &portFormat); } if((ret = ilclient_change_component_state(image_read, OMX_StateIdle) < 0)) //this fails printf("Cannot change image_read component state to OMX_StateIdle\n"); #endif //image_read attempt // create image_decode ret = ilclient_create_component(client, &image_decode, "image_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS ); if (ret != 0) status = -15; list[0] = image_decode; // create video_render ret = ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS); if (ret != 0) status = -14; list[1] = video_render; list[2] = NULL; ret = ilclient_change_component_state(image_decode, OMX_StateIdle); set_tunnel(tunnel, image_decode, 321, video_render, 90); #if 0 //not necessary { //get OMX_IndexParamPortDefinition OMX_PARAM_PORTDEFINITIONTYPE portDef; portDef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portDef.nVersion.nVersion = OMX_VERSION; portDef.nPortIndex = 320; ret = OMX_GetParameter(ILC_GET_HANDLE(image_decode), OMX_IndexParamPortDefinition, &portDef); } #endif { // OMX_IndexParamImagePortFormat imagePortFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); imagePortFormat.nVersion.nVersion = OMX_VERSION; imagePortFormat.nPortIndex = 320; imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; // imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingPNG; //does not seem to work // imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingAutoDetect; //does not seem to work. ret = OMX_SetParameter(ILC_GET_HANDLE(image_decode), OMX_IndexParamImagePortFormat, &imagePortFormat); } ret = ilclient_enable_port_buffers(image_decode, 320, NULL, NULL, NULL); ret = ilclient_change_component_state(image_decode, OMX_StateExecuting); while( (pIbuf = ilclient_get_input_buffer(image_decode, 320, 1)) != NULL ) { bytes_read = fread(pIbuf->pBuffer, 1, pIbuf->nAllocLen, fin); if( port_settings_changed == 0 && (( bytes_read > 0 && ilclient_remove_event(image_decode, OMX_EventPortSettingsChanged, 321, 0, 0, 1) == 0) || ( bytes_read == 0 && ilclient_wait_for_event(image_decode, OMX_EventPortSettingsChanged, 321, 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_render, OMX_StateExecuting); } if(!bytes_read) break; pIbuf->nFilledLen = bytes_read; pIbuf->nOffset = 0; pIbuf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(image_decode), pIbuf) != OMX_ErrorNone) { status = -6; break; } } pIbuf->nFilledLen = 0; pIbuf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(image_decode), pIbuf) != 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); printf("Press ENTER to continue...\n"); fflush(stdout); getchar(); // need to flush the renderer to allow video_decode to disable its input port // ilclient_flush_tunnels(tunnel, 0); ilclient_disable_port_buffers(image_decode, 320, NULL, NULL, NULL); fclose(fin); ilclient_disable_tunnel(tunnel); ilclient_teardown_tunnels(tunnel); ret = ilclient_change_component_state(image_decode, OMX_StateIdle); ret = ilclient_change_component_state(image_decode, OMX_StateLoaded); ilclient_cleanup_components(list); OMX_Deinit(); ilclient_destroy(client); return status; }
// Modified function prototype to work with pthreads void *video_decode_test(void* arg) { pthread_mutex_init(&m_lock, NULL); printf("OMX version : %d.%d.%d-%d\n",OMX_VERSION_MAJOR, OMX_VERSION_MINOR, OMX_VERSION_REVISION, OMX_VERSION_STEP); printf("file to read : %s\n", filename); eglImage = arg; if (eglImage == 0) { printf("eglImage is null.\n"); exit(1); } int status = 0; unsigned int data_len = 0; int packet_size = 80<<10; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return (void *)-2; if((client = ilclient_init()) == NULL) { fclose(in); return (void *)-3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return (void *)-4; } // callback ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0); // 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) if(status == 0 && ilclient_create_component(client, &video_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0) status = -14; list[1] = video_render; // create clock if(status == 0 && ilclient_create_component(client, &omx_clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) status = -14; list[2] = omx_clock; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; if(omx_clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) status = -13; // set the clock refenrece to "none" memset(&cref,0,sizeof(cref)); cref.nSize = sizeof(cref); cref.nVersion.nVersion = OMX_VERSION; cref.eClock = OMX_TIME_RefClockNone; if(omx_clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeActiveRefClock, &cref) != OMX_ErrorNone){ status = -13; printf("error setting refclock\n"); } // 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+1, video_scheduler, 11, video_render, 220); set_tunnel(tunnel+2, omx_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(omx_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 && stop_flag==0 ) { // feed data and wait until we get port settings changed unsigned char *dest = buf->pBuffer; // loop if at end if (feof(in)) rewind(in); data_len += fread(dest, 1, packet_size-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; } // Set egl_render to idle ilclient_change_component_state(video_render, OMX_StateIdle); // Enable the output port and tell egl_render to use the texture as a buffer //ilclient_enable_port(video_render, 221); THIS BLOCKS SO CANT BE USED if (OMX_SendCommand(ILC_GET_HANDLE(video_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone) { printf("OMX_CommandPortEnable failed.\n"); exit(1); } if (OMX_UseEGLImage(ILC_GET_HANDLE(video_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone) { printf("OMX_UseEGLImage failed.\n"); exit(1); } // Set egl_render to executing ilclient_change_component_state(video_render, OMX_StateExecuting); // Request egl_render to write data to the texture buffer if(OMX_FillThisBuffer(ILC_GET_HANDLE(video_render), eglBuffer) != OMX_ErrorNone) { printf("OMX_FillThisBuffer failed.\n"); //~ exit(1); } } if(!data_len) break; 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; } } printf("loop ends, now flush the buffer\n"); OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,130,NULL); OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,131,NULL); ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 130, 0, ILCLIENT_PORT_FLUSH, -1); ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 131, 0, ILCLIENT_PORT_FLUSH, -1); data_len=0; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateStopped; cstate.nWaitMask = 1; OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate); memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; OMX_SetParameter(ILC_GET_HANDLE(omx_clock), OMX_IndexConfigTimeClockState, &cstate); //~ scheduler should be stopped... 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 //~ printf("wait for EOS from render\n"); //~ ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, //~ ILCLIENT_BUFFER_FLAG_EOS, 10000); while ((ilclient_remove_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0) <0 ) && !stop_flag){ } printf("flush the render\n"); // 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); } printf("close file\n"); 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); printf("thread will return...\n"); pthread_mutex_destroy(&m_lock); return (void *)status; }
/* ------------------------------------------------- / audioplay_create() / Create audio decoder & render & other hardware component /---------------------------------------------------*/ static INT32 audioplay_create( AUDIOPLAY_STATE_T **handle, UINT32 sample_rate, UINT32 num_channels, UINT32 bit_depth, UINT32 num_buffers, ///< 100 UINT32 buffer_size ///< 480*(16/8)*2 = 1920 ){ OMX_AUDIO_PARAM_PCMMODETYPE pcm; UINT32 bytes_per_sample = (bit_depth * num_channels) >> 3; INT32 ret = -1; int rv; *handle = NULL; /* TODO basic sanity check on arguments */ if(sample_rate >= 8000 && sample_rate <= 96000 && (num_channels == 1 || num_channels == 2 || num_channels == 4 || num_channels == 8) && (bit_depth == 16 || bit_depth == 32) && (num_buffers > 0) && (buffer_size >= bytes_per_sample)){ /* TODO buffer length must be 16 bytes aligned for VCHI */ int size = (buffer_size + 15) & ~15; /* TODO buffer length must be 16 bytes aligned for VCHI */ st = calloc(1, sizeof(AUDIOPLAY_STATE_T)); assert(st != NULL); OMX_ERRORTYPE error; OMX_PARAM_PORTDEFINITIONTYPE param; INT32 s; ret = 0; /* TODO combine with st = calloc()?*/ *handle = st; /* create and start up audio codec hardware component */ /* TODO semaphore */ s = sem_init(&st->sema, 0 ,1); assert(s == 0); st->bytes_per_sample = bytes_per_sample; st->num_buffers = num_buffers; st->client = ilclient_init(); assert(st->client != NULL); /*TODO input_buffer_callback*/ ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st); error = OMX_Init(); assert(error == OMX_ErrorNone); /* Create audio render */ ilclient_create_component(st->client, &(st->audio_render), "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS); assert(st->audio_render != NULL); st->list[0] = st->audio_render; /* Create clock component */ ilclient_create_component(st->client, &(st->clock), "clock", ILCLIENT_DISABLE_ALL_PORTS); assert(st->clock != NULL); st->list[1] = st->clock; /* Configure clock */ OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; //TODO error = OMX_SetParameter(ILC_GET_HANDLE(st->clock), OMX_IndexConfigTimeClockState, &cstate); assert(error == 0); /* Setup tunnel to connect clock and audio render */ set_tunnel(&st->tunnel, st->clock, 80, st->audio_render, 101); rv = ilclient_setup_tunnel(&st->tunnel, 0, 0); assert(rv == 0); /* kick off clock */ ilclient_change_component_state(st->clock, OMX_StateExecuting); /* Set audio render port definition */ /* 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(st->audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); param.nBufferSize = size; param.nBufferCountActual = num_buffers; error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); assert(error == OMX_ErrorNone); /* Set audio render PCM definition */ 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 = num_channels; pcm.eNumData = OMX_NumericalDataSigned; //TODO pcm.eEndian = OMX_EndianLittle; pcm.nSamplingRate = sample_rate; pcm.bInterleaved = OMX_TRUE; pcm.nBitPerSample = bit_depth; pcm.ePCMMode = OMX_AUDIO_PCMModeLinear; switch(num_channels){ case 1: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF; break; } case 8: { /*TODO*/ pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE; pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR; pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR; pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS; pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS; break; } case 4: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelLR; pcm.eChannelMapping[3] = OMX_AUDIO_ChannelRR; break; } case 2: { pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; break; } } error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm); assert(error == OMX_ErrorNone); /* Set audio reference clock */ OMX_CONFIG_BOOLEANTYPE ref_clock; memset(&ref_clock, 0, sizeof(OMX_CONFIG_BOOLEANTYPE)); param.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); param.nVersion.nVersion = OMX_VERSION; param.bEnabled = OMX_FALSE; error = OMX_SetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigBrcmClockReferenceSource, &ref_clock); assert(error == OMX_ErrorNone); /* Enable audio render */ ilclient_change_component_state(st->audio_render, OMX_StateIdle); if(ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL) < 0){ /* Error situation */ ilclient_change_component_state(st->audio_render, OMX_StateLoaded); ilclient_cleanup_components(st->list); error = OMX_Deinit(); assert(error == OMX_ErrorNone); ilclient_destroy(st->client); sem_destroy(&st->sema); free(st); *handle = NULL; return -1; } ilclient_change_component_state(st->audio_render, OMX_StateExecuting); } return ret; }
int prepareRender(OPENMAX_JPEG_DECODER * decoder) { decoder->imageRender = malloc(sizeof(COMPONENT_DETAILS)); if (decoder->imageRender == NULL) { perror("malloc image render"); return OMXJPEG_ERROR_MEMORY; } int ret = ilclient_create_component(decoder->client, &decoder-> imageRender-> component, "video_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS ); if (ret != 0) { perror("image render"); return OMXJPEG_ERROR_CREATING_COMP; } // grab the handle for later use decoder->imageRender->handle = ILC_GET_HANDLE(decoder->imageRender->component); // get and store the ports OMX_PORT_PARAM_TYPE port; port.nSize = sizeof(OMX_PORT_PARAM_TYPE); port.nVersion.nVersion = OMX_VERSION; OMX_GetParameter(ILC_GET_HANDLE(decoder->imageRender->component), OMX_IndexParamVideoInit, &port); if (port.nPorts != 1) { return OMXJPEG_ERROR_WRONG_NO_PORTS; } decoder->imageRender->inPort = port.nStartPortNumber; /* decoder->imageRender->outPort = port.nStartPortNumber + 1; */ // the default is 3 buffers, but we want to use only one // query output buffer requirements for render OMX_PARAM_PORTDEFINITIONTYPE portdef; portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = decoder->imageRender->inPort; OMX_GetParameter(decoder->imageRender->handle, OMX_IndexParamPortDefinition, &portdef); decoder->renderInputBufferHeaderCount = portdef.nBufferCountActual; /* later settings params doesn't like this! portdef.nBufferCountActual = 1; ret = OMX_SetParameter(decoder->imageRender->handle, OMX_IndexParamPortDefinition, &portdef); if (ret != OMX_ErrorNone) { fprintf(stderr, "Eror setting render buffers to one %s\n", err2str(ret)); return OMXJPEG_ERROR_MEMORY; } */ decoder->pOutputBufferHeader = NULL; return OMXJPEG_OK; }
/* ------------------------------------------------- / sx_video_sink_init() / /---------------------------------------------------*/ void sx_video_sink_init(void){ OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; int rc; /* Init compoent & tunnel */ memset(comp_list, 0, sizeof(comp_list)); memset(tunnel, 0, sizeof(tunnel)); /* Init Broadcom host */ bcm_host_init(); /* Init il client */ client = ilclient_init(); assert(client != NULL); /* Init OpenMax */ rc = OMX_Init(); assert(rc == OMX_ErrorNone); /* Create Decoder Component,beacuse enable input buffers,so in the end need to OMX_EmptyThisBuffer */ rc = ilclient_create_component( client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS); assert(rc == 0); comp_list[0] = video_decode; /* Create video render */ rc = ilclient_create_component( client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[1] = video_render; /* Create clock */ rc = ilclient_create_component( client, &video_clock, "clock", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[2] = video_clock; /* Configure clock */ memset(&cstate, 0, sizeof(cstate)); cstate.nSize = sizeof(cstate); cstate.nVersion.nVersion = OMX_VERSION; cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; cstate.nWaitMask = 1; rc = OMX_SetParameter(ILC_GET_HANDLE(video_clock), OMX_IndexConfigTimeClockState, &cstate); assert(rc == 0); /* Create video scheduler */ rc = ilclient_create_component( client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS); assert(rc == 0); comp_list[3] = video_scheduler; /* Set tunnels */ /* Connect decode to scheduler */ set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); /* Connect scheduler to render */ set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); /* Connect clock to scheduler */ set_tunnel(tunnel+2, video_clock, 80, video_scheduler, 12); /* Setup clock tunnel first */ rc = ilclient_setup_tunnel(tunnel+2, 0, 0); assert(rc == 0); /* Kick start the clock */ ilclient_change_component_state(video_clock, OMX_StateExecuting); #define AUTO_FULLSCREEN #if 1 OMX_CONFIG_DISPLAYREGIONTYPE drt; memset(&drt, 0, sizeof(drt)); drt.nVersion.nVersion = OMX_VERSION; drt.nSize = sizeof(drt); drt.nPortIndex = 90; /* if not defined AUTO_FULLSCREEN it means that set other display region type */ #if 0 #if !defined(AUTO_FULLSCREEN) /*TODO*/ drt.src_rect.x_offset = 0; drt.src_rect.y_offset = 0; drt.src_rect.width = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_WIDTH); drt.src_rect.height = sx_mgmt_env_get(MGMT_ENV_VAR_SESSION_HEIGHT); drt.dest_rect.x_offset = -56; drt.dest_rect.y_offset = 0; drt.dest_rect.width = 1792; drt.dest_rect.height = 1050; #endif #endif #if !defined(AUTO_FULLSCREEN) drt.fullscreen = OMX_FALSE; #else /* define AUTO_FULLSCREEN */ drt.fullscreen = OMX_TRUE; #endif drt.noaspect = OMX_TRUE; drt.mode = OMX_DISPLAY_MODE_FILL; #if !defined(AUTO_FULLSCREEN) /*TODO*/ drt.set = (OMX_DISPLAYSETTYPE) ( OMX_DISPLAY_SET_SRC_RECT | OMX_DISPLAY_SET_DEST_RECT | OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT); #else drt.set = (OMX_DISPLAYSETTYPE) (OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT); #endif rc = OMX_SetConfig(ILC_GET_HANDLE(video_render), OMX_IndexConfigDisplayRegion, &drt); assert(rc==0); #endif /* Kick start video decoder */ ilclient_change_component_state(video_decode, OMX_StateIdle); /*TODO Configure decoder */ 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; rc = OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format); assert(rc == 0); /* Enable video decode */ rc = ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL); assert(rc ==0); /* Kick start video decode */ ilclient_change_component_state(video_decode, OMX_StateExecuting); printf("decoder_hw: initialized"); }
// Modified function prototype to work with pthreads void *video_decode_test(void* arg) { const char* filename = "/opt/vc/src/hello_pi/hello_video/test.h264"; eglImage = arg; if (eglImage == 0) { printf("eglImage is null.\n"); exit(1); } OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; COMPONENT_T *video_decode = NULL, *video_scheduler = 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 packet_size = 80<<10; memset(list, 0, sizeof(list)); memset(tunnel, 0, sizeof(tunnel)); if((in = fopen(filename, "rb")) == NULL) return (void *)-2; if((client = ilclient_init()) == NULL) { fclose(in); return (void *)-3; } if(OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); fclose(in); return (void *)-4; } // callback ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0); // 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) if(status == 0 && ilclient_create_component(client, &video_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 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+1, video_scheduler, 11, video_render, 220); 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; // loop if at end if (feof(in)) rewind(in); data_len += fread(dest, 1, packet_size-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; } // Set egl_render to idle ilclient_change_component_state(video_render, OMX_StateIdle); // Enable the output port and tell egl_render to use the texture as a buffer //ilclient_enable_port(video_render, 221); THIS BLOCKS SO CANT BE USED if (OMX_SendCommand(ILC_GET_HANDLE(video_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone) { printf("OMX_CommandPortEnable failed.\n"); exit(1); } if (OMX_UseEGLImage(ILC_GET_HANDLE(video_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone) { printf("OMX_UseEGLImage failed.\n"); exit(1); } // Set egl_render to executing ilclient_change_component_state(video_render, OMX_StateExecuting); // Request egl_render to write data to the texture buffer if(OMX_FillThisBuffer(ILC_GET_HANDLE(video_render), eglBuffer) != OMX_ErrorNone) { printf("OMX_FillThisBuffer failed.\n"); exit(1); } } if(!data_len) break; 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 (void *)status; }
bool encode_config_output(COMPONENT_T* handle, OMX_VIDEO_CODINGTYPE codec, uint32_t bitrate) { OMX_ERRORTYPE omx_return; // set format OMX_VIDEO_PARAM_PORTFORMATTYPE format; memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); format.nVersion.nVersion = OMX_VERSION; format.nPortIndex = 201; format.eCompressionFormat = codec; fprintf(stderr, "OMX_SetParameter(OMX_IndexParamVideoPortFormat) for video_encode:201...\n"); omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoPortFormat, &format); if (omx_return != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_SetParameter() for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); return false; } // ask to repeat SPS/PPS OMX_CONFIG_PORTBOOLEANTYPE config; config.nSize = sizeof(config); config.nVersion.nVersion = OMX_VERSION; config.nPortIndex = 201; config.bEnabled = OMX_TRUE; fprintf(stderr, "OMX_SetParameter(OMX_IndexParamBrcmVideoAVCInlineHeaderEnable) for video_encode:201...\n"); omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config); if (omx_return != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_SetParameter() for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); return false; } // set current bitrate OMX_VIDEO_PARAM_BITRATETYPE bitrateType; memset(&bitrateType, 0, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); bitrateType.nSize = sizeof(OMX_VIDEO_PARAM_BITRATETYPE); bitrateType.nVersion.nVersion = OMX_VERSION; bitrateType.eControlRate = OMX_Video_ControlRateVariable; bitrateType.nTargetBitrate = bitrate; bitrateType.nPortIndex = 201; omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoBitrate, &bitrateType); if (omx_return != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_SetParameter() for bitrate for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); return false; } // get current bitrate memset(&bitrateType, 0, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); bitrateType.nSize = sizeof(OMX_VIDEO_PARAM_BITRATETYPE); bitrateType.nVersion.nVersion = OMX_VERSION; bitrateType.nPortIndex = 201; if (OMX_GetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoBitrate, &bitrateType) != OMX_ErrorNone) { fprintf(stderr, "%s:%d: OMX_GetParameter() for video_encode for bitrate port 201 failed!\n", __FUNCTION__, __LINE__); return false; } fprintf(stderr, "Current Bitrate=%u\n",bitrateType.nTargetBitrate); return true; }