// this function run the boilerplate to setup the openmax components; int setupOpenMaxJpegDecoder(OPENMAX_JPEG_DECODER ** pDecoder) { *pDecoder = malloc(sizeof(OPENMAX_JPEG_DECODER)); if (pDecoder[0] == NULL) { perror("malloc decoder"); return OMXJPEG_ERROR_MEMORY; } memset(*pDecoder, 0, sizeof(OPENMAX_JPEG_DECODER)); if ((pDecoder[0]->client = ilclient_init()) == NULL) { perror("ilclient_init"); return OMXJPEG_ERROR_ILCLIENT_INIT; } if (OMX_Init() != OMX_ErrorNone) { ilclient_destroy(pDecoder[0]->client); perror("OMX_Init"); return OMXJPEG_ERROR_OMX_INIT; } // prepare the image decoder int ret = prepareImageDecoder(pDecoder[0]); if (ret != OMXJPEG_OK) return ret; ret = prepareResizer(pDecoder[0]); if (ret != OMXJPEG_OK) return ret; ret = startupImageDecoder(pDecoder[0]); if (ret != OMXJPEG_OK) return ret; return OMXJPEG_OK; }
ILCLIENT_T * encode_init(COMPONENT_T **video_encode) { ILCLIENT_T *client = ilclient_init(); if (client == NULL) { return NULL; } if (OMX_Init() != OMX_ErrorNone) { ilclient_destroy(client); return NULL; } // create video_encode int omx_return = ilclient_create_component(client, video_encode, "video_encode", (ILCLIENT_CREATE_FLAGS_T)(ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_ENABLE_OUTPUT_BUFFERS)); if (omx_return != 0) { fprintf(stderr, "ilclient_create_component() for video_encode failed with %x!\n", omx_return); ilclient_destroy(client); return NULL; } return client; }
// 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; }
int main(int argc, char *argv[]) { AVFormatContext *ic; char *iname; char *oname; char *size; int err; int vidindex; int i, j; OMX_ERRORTYPE oerr; OMX_HANDLETYPE m2 = NULL, m4 = NULL, resize = NULL; OMX_VIDEO_PARAM_PORTFORMATTYPE *pfmt; OMX_PORT_PARAM_TYPE *porttype; OMX_PARAM_PORTDEFINITIONTYPE *portdef; OMX_BUFFERHEADERTYPE *decbufs; OMX_VIDEO_PORTDEFINITIONTYPE *viddef; OMX_VIDEO_PARAM_PROFILELEVELTYPE *level; int decportidx = 200; int resizeportidx = 60; int encportidx = 130; int fd; time_t start, end; int offset; AVPacket *p, *rp; int ish264; int filtertest; int opt; ILCLIENT_T *client; if (argc < 3) usage(argv[0]); ctx.bitrate = 2*1024*1024; ctx.verbose = 0; ctx.width = 0; ctx.height = 0; while ((opt = getopt(argc, argv, ":b:vs:")) != -1) { switch (opt) { case 'b': //bitrate ctx.bitrate = atoi(optarg); printf("bitrate = %d\n", ctx.bitrate); break; case 'v': //verbose` ctx.verbose = 1; break; case 's': //WxH ctx.width = atoi(optarg); if ((atoi(optarg) % 16) != 0) { printf("W = %d is not a multiple of 16\n", ctx.width); usage(argv[0]); } if (ctx.width <16 || ctx.width > 1080) { printf("W = %d should be between 16 and 1080\n", ctx.width); usage(argv[0]); } printf("W = %d\n", ctx.width); if ((size = strchr(optarg, 'x')) == NULL) { printf("wrong size parameter (no 'x') exiting\n"); usage(argv[0]); } ctx.height = atoi(size+1); if ((atoi(size+1) % 16) != 0) { printf("H = %d is not a multiple of 16\n", ctx.height); usage(argv[0]); } if (ctx.height <16 || ctx.height > 1080) { printf("H = %d should be between 16 and 1080\n", ctx.height); usage(argv[0]); } printf("H = %d\n", ctx.height); break; case '?': usage(argv[0]); } } if ((client = ilclient_init()) == NULL) return -2; iname = argv[optind++]; oname = argv[optind++]; MAKEME(porttype, OMX_PORT_PARAM_TYPE); MAKEME(portdef, OMX_PARAM_PORTDEFINITIONTYPE); MAKEME(pfmt, OMX_VIDEO_PARAM_PORTFORMATTYPE); av_register_all(); ic = NULL; ish264 = 0; pthread_mutex_init(&ctx.lock, NULL); #if 0 fmt = av_oformat_next(fmt); while (fmt) { printf("Found '%s'\t\t'%s'\n", fmt->name, fmt->long_name); fmt = av_oformat_next(fmt); } #endif /* Input init: */ if ((err = avformat_open_input(&ic, iname, NULL, NULL) != 0)) { fprintf(stderr, "Failed to open '%s': %s\n", iname, strerror(err)); exit(1); } ctx.ic = ic; if (avformat_find_stream_info(ic, NULL) < 0) { fprintf(stderr, "Failed to find streams in '%s'\n", iname); exit(1); } av_dump_format(ic, 0, iname, 0); vidindex = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (vidindex < 0) { fprintf(stderr, "Failed to find a video stream in '%s'\n", iname); exit(1); } printf("Found a video at index %d\n", vidindex); printf("Frame size: %dx%d\n", ic->streams[vidindex]->codec->width, ic->streams[vidindex]->codec->height); ish264 = (ic->streams[vidindex]->codec->codec_id == CODEC_ID_H264); /* Output init: */ ctx.fd = fd = open(oname, O_CREAT | O_LARGEFILE | O_WRONLY | O_TRUNC, 0666); printf("File descriptor %d\n", fd); #if 0 avformat_alloc_output_context(&oc, NULL, /*NULL,*/ oname); if (!oc) { printf("Couldn't determine output from '%s'; using MPEG.\n", oname); avformat_alloc_output_context(&oc, NULL, /*"matroska",*/ oname); } #endif // if (!oc) // exit(1); // fmt = oc->oformat; for (i = 0; i < ic->nb_streams; i++) { printf("Found stream %d, context %p\n", ic->streams[i]->index, ic->streams[i]->codec); } bcm_host_init(); OERR(OMX_Init(), ctx.verbose); OERR(OMX_GetHandle(&m2, DECNAME, &ctx, &decevents), ctx.verbose); OERR(OMX_GetHandle(&m4, ENCNAME, &ctx, &encevents), ctx.verbose); OERR(OMX_GetHandle(&resize, RESIZENAME, &ctx, &resizeevents), ctx.verbose); ctx.m2 = m2; ctx.m4 = m4; ctx.resize = resize; if (ctx.verbose) printf("Obtained handles. %p decode, %p resize, %p encode\n", m2, resize, m4); OERR(OMX_GetParameter(m2, OMX_IndexParamVideoInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on decoder\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.decportidx = decportidx = porttype->nStartPortNumber; OERR(OMX_GetParameter(resize, OMX_IndexParamImageInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on resizer\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.resizeportidx = resizeportidx = porttype->nStartPortNumber; OERR(OMX_GetParameter(m4, OMX_IndexParamVideoInit, porttype), ctx.verbose); if (ctx.verbose) printf("Found %d ports, starting at %d (%x) on encoder\n", porttype->nPorts, porttype->nStartPortNumber, porttype->nStartPortNumber); ctx.encportidx = encportidx = porttype->nStartPortNumber; free(porttype); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx+1, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx+1, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx+1, NULL), ctx.verbose); portdef->nPortIndex = decportidx; OERR(OMX_GetParameter(m2, OMX_IndexParamPortDefinition, portdef), ctx.verbose); viddef = &portdef->format.video; viddef->nFrameWidth = ic->streams[vidindex]->codec->width; viddef->nFrameHeight = ic->streams[vidindex]->codec->height; printf("Mapping codec %d to %d\n", ic->streams[vidindex]->codec->codec_id, mapcodec(ic->streams[vidindex]->codec->codec_id)); viddef->eCompressionFormat = mapcodec(ic->streams[vidindex]->codec->codec_id); viddef->bFlagErrorConcealment = 0; // viddef->xFramerate = 25<<16; OERR(OMX_SetParameter(m2, OMX_IndexParamPortDefinition, portdef), ctx.verbose); free(portdef); #if 0 /* It appears these have limited effect: */ dataunit->nPortIndex = decportidx; dataunit->eUnitType = OMX_DataUnitCodedPicture; dataunit->eEncapsulationType = OMX_DataEncapsulationGenericPayload; OERR(OMX_SetParameter(m2, OMX_IndexParamBrcmDataUnit, dataunit), ctx.verbose); if (ish264) { naltype->nPortIndex = decportidx; naltype->eNaluFormat = OMX_NaluFormatStartCodes; OERR(OMX_SetParameter(m2, OMX_IndexParamNalStreamFormatSelect, naltype), ctx.verbose); } #endif MAKEME(level, OMX_VIDEO_PARAM_PROFILELEVELTYPE); level->nPortIndex = encportidx+1; /* Dump what the encoder is capable of: */ if (ctx.verbose) print_codecs(); if (ctx.verbose) { for (oerr = OMX_ErrorNone, i = 0; oerr == OMX_ErrorNone; i++) { pfmt->nIndex = i; oerr = OMX_GetParameter(m4, OMX_IndexParamVideoPortFormat, pfmt); if (oerr == OMX_ErrorNoMore) break; printf("Codecs supported:\n" "\tIndex:\t\t%d\n" "\tCodec:\t\t%d (%x)\n" "\tColour:\t\t%d\n" "\tFramerate:\t%x (%f)\n", pfmt->nIndex, pfmt->eCompressionFormat, pfmt->eCompressionFormat, pfmt->eColorFormat, pfmt->xFramerate, ((float)pfmt->xFramerate/(float)65536)); } for (oerr = OMX_ErrorNone, i = 0; oerr == OMX_ErrorNone; i++) { level->nProfileIndex = i; oerr = OMX_GetParameter(m4, OMX_IndexParamVideoProfileLevelQuerySupported, level); if (oerr == OMX_ErrorNoMore) break; printf("Levels supported:\n" "\tIndex:\t\t%d\n" "\tProfile:\t%d\n" "\tLevel:\t\t%d\n", level->nProfileIndex, level->eProfile, level->eLevel); } } free(pfmt); free(level); /* Dump current port states: */ if (ctx.verbose) { dumpport(m2, decportidx); dumpport(m2, decportidx+1); dumpport(resize, resizeportidx); dumpport(resize, resizeportidx+1); dumpport(m4, encportidx); dumpport(m4, encportidx+1); } OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); decbufs = allocbufs(m2, decportidx, 1); /* Start the initial loop. Process until we have a state change on port 131 */ ctx.decstate = DECINIT; ctx.encstate = ENCPREINIT; OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateExecuting, NULL), ctx.verbose); rp = calloc(sizeof(AVPacket), 1); filtertest = ish264; for (offset = i = j = 0; ctx.decstate != DECFAILED; i++, j++) { int rc; int k; int size, nsize; OMX_BUFFERHEADERTYPE *spare; if (offset == 0 && ctx.decstate != DECFLUSH) { rc = av_read_frame(ic, rp); if (rc != 0) { if (ic->pb->eof_reached) ctx.decstate = DECFLUSH; break; } if (rp->stream_index != vidindex) { i--; av_free_packet(rp); continue; } size = rp->size; ctx.fps++; ctx.framecount++; if (ish264 && filtertest) { filtertest = 0; ctx.bsfc = dofiltertest(rp); } if (ctx.bsfc) { p = filter(&ctx, rp); } else { p = rp; } } switch (ctx.decstate) { case DECTUNNELSETUP: start = time(NULL); //printf("NOW to CONFIGURE !!!!!!!!!!!!!!\n\n"); configure(&ctx); ctx.decstate = DECRUNNING; break; case DECFLUSH: size = 0; /* Add the flush code here */ printf("IN FLUSH NOW\n\n"); break; case DECINIT: if (i < 120) /* Bail; decoder doesn't like it */ break; ctx.decstate = DECFAILED; /* Drop through */ case DECFAILED: fprintf(stderr, "Failed to set the parameters after " "%d video frames. Giving up.\n", i); dumpport(m2, decportidx); dumpport(m2, decportidx+1); dumpport(resize, resizeportidx); dumpport(resize, resizeportidx+1); dumpport(m4, encportidx); dumpport(m4, encportidx+1); exit(1); break; default: break; /* Shuts the compiler up */ } for (spare = NULL; !spare; usleep(10)) { pthread_mutex_lock(&ctx.lock); spare = ctx.bufhead; ctx.bufhead = NULL; ctx.flags &= ~FLAGS_DECEMPTIEDBUF; pthread_mutex_unlock(&ctx.lock); while (spare) { write(fd, &spare->pBuffer[spare->nOffset], spare->nFilledLen); spare->nFilledLen = 0; spare->nOffset = 0; OERRq(OMX_FillThisBuffer(m4, spare)); spare = spare->pAppPrivate; } spare = decbufs; for (k = 0; spare && spare->nFilledLen != 0; k++) spare = spare->pAppPrivate; } if (size > spare->nAllocLen) { nsize = spare->nAllocLen; } else { nsize = size; } if (ctx.decstate != DECFLUSH) { memcpy(spare->pBuffer, &(p->data[offset]), nsize); spare->nFlags = i == 0 ? OMX_BUFFERFLAG_STARTTIME : 0; spare->nFlags |= size == nsize ? OMX_BUFFERFLAG_ENDOFFRAME : 0; } else { spare->nFlags = OMX_BUFFERFLAG_STARTTIME | OMX_BUFFERFLAG_EOS; } spare->nFilledLen = nsize; spare->nOffset = 0; OERRq(OMX_EmptyThisBuffer(m2, spare)); size -= nsize; if (size) { offset += nsize; } else { offset = 0; av_free_packet(p); } } close(fd); end = time(NULL); printf("Processed %d frames in %d seconds; %df/s\n", ctx.framecount, end-start, (ctx.framecount/(end-start))); // flush the encoder // OERR(OMX_SendCommand(m4, OMX_CommandFlush, encportidx, NULL), ctx.verbose); // OERR(OMX_SendCommand(m4, OMX_CommandFlush, encportidx+ctx.verbose, NULL), ctx.verbose); // tear down the tunnels OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateIdle, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandStateSet, OMX_StateLoaded, NULL), ctx.verbose); // free buffers vcos_free(decbufs); vcos_free(ctx.encbufs); // Apparantly the teardwon function is not implemented. Use setup function instead //OERR(OMX_TeardownTunnel(m2, decportidx+ctx.verbose, resize, resizeportidx), ctx.verbose); //OERR(OMX_TeardownTunnel(resize, resizeportidx+ctx.verbose, m4, encportidx), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m2, OMX_CommandPortDisable, decportidx+ctx.verbose, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(resize, OMX_CommandPortDisable, resizeportidx+ctx.verbose, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx, NULL), ctx.verbose); OERR(OMX_SendCommand(m4, OMX_CommandPortDisable, encportidx+ctx.verbose, NULL), ctx.verbose); // ilclient_disable_port_buffers(m2, decportidx, NULL, NULL, NULL); // ilclient_disable_port_buffers(m4, encportidx, NULL, NULL, NULL); OERR(OMX_SetupTunnel(m2, decportidx+ctx.verbose, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(resize, resizeportidx, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(resize, resizeportidx+ctx.verbose, NULL, 0), ctx.verbose); OERR(OMX_SetupTunnel(m4, encportidx, NULL, 0), ctx.verbose); OERR(OMX_FreeHandle(m2), ctx.verbose); OERR(OMX_FreeHandle(resize), ctx.verbose); OERR(OMX_FreeHandle(m4), ctx.verbose); // free(porttype); // free(portdef); // free(pfmt); // free(level); return 0; }
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; }
static void omx_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) { int rc, error; OMX_ERRORTYPE err; unsigned char omxMapping[6]; char* componentName = "audio_render"; channelCount = opusConfig->channelCount; /* The supplied mapping array has order: FL-FR-C-LFE-RL-RR * OMX expects the order: FL-FR-LFE-C-RL-RR * We need copy the mapping locally and swap the channels around. */ memcpy(omxMapping, opusConfig->mapping, sizeof(omxMapping)); if (opusConfig->channelCount > 2) { omxMapping[2] = opusConfig->mapping[3]; omxMapping[3] = opusConfig->mapping[2]; } decoder = opus_multistream_decoder_create(opusConfig->sampleRate, opusConfig->channelCount, opusConfig->streams, opusConfig->coupledStreams, omxMapping, &rc); handle = ilclient_init(); if (handle == NULL) { fprintf(stderr, "IL client init failed\n"); exit(1); } if (ilclient_create_component(handle, &component, componentName, ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) { fprintf(stderr, "Component create failed\n"); exit(1); } if (ilclient_change_component_state(component, OMX_StateIdle)!= 0) { fprintf(stderr, "Couldn't change state to Idle\n"); exit(1); } // must be before we enable buffers OMX_AUDIO_PARAM_PORTFORMATTYPE audioPortFormat; memset(&audioPortFormat, 0, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); audioPortFormat.nSize = sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE); audioPortFormat.nVersion.nVersion = OMX_VERSION; audioPortFormat.nPortIndex = 100; OMX_GetParameter(ilclient_get_handle(component), OMX_IndexParamAudioPortFormat, &audioPortFormat); audioPortFormat.eEncoding = OMX_AUDIO_CodingPCM; OMX_SetParameter(ilclient_get_handle(component), OMX_IndexParamAudioPortFormat, &audioPortFormat); OMX_AUDIO_PARAM_PCMMODETYPE sPCMMode; memset(&sPCMMode, 0, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); sPCMMode.nSize = sizeof(OMX_AUDIO_PARAM_PCMMODETYPE); sPCMMode.nVersion.nVersion = OMX_VERSION; sPCMMode.nPortIndex = 100; sPCMMode.nChannels = channelCount; sPCMMode.eNumData = OMX_NumericalDataSigned; sPCMMode.eEndian = OMX_EndianLittle; sPCMMode.nSamplingRate = opusConfig->sampleRate; sPCMMode.bInterleaved = OMX_TRUE; sPCMMode.nBitPerSample = 16; sPCMMode.ePCMMode = OMX_AUDIO_PCMModeLinear; switch(channelCount) { case 1: sPCMMode.eChannelMapping[0] = OMX_AUDIO_ChannelCF; break; case 8: sPCMMode.eChannelMapping[7] = OMX_AUDIO_ChannelRS; case 7: sPCMMode.eChannelMapping[6] = OMX_AUDIO_ChannelLS; case 6: sPCMMode.eChannelMapping[5] = OMX_AUDIO_ChannelRR; case 5: sPCMMode.eChannelMapping[4] = OMX_AUDIO_ChannelLR; case 4: sPCMMode.eChannelMapping[3] = OMX_AUDIO_ChannelLFE; case 3: sPCMMode.eChannelMapping[2] = OMX_AUDIO_ChannelCF; case 2: sPCMMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF; sPCMMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF; break; } err = OMX_SetParameter(ilclient_get_handle(component), OMX_IndexParamAudioPcm, &sPCMMode); if(err != OMX_ErrorNone){ fprintf(stderr, "PCM mode unsupported\n"); return; } OMX_CONFIG_BRCMAUDIODESTINATIONTYPE arDest; if (audio_device == NULL) audio_device = "hdmi"; if (audio_device && strlen(audio_device) < sizeof(arDest.sName)) { memset(&arDest, 0, sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE)); arDest.nSize = sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE); arDest.nVersion.nVersion = OMX_VERSION; strcpy((char *)arDest.sName, audio_device); err = OMX_SetParameter(ilclient_get_handle(component), OMX_IndexConfigBrcmAudioDestination, &arDest); if (err != OMX_ErrorNone) { fprintf(stderr, "Error on setting audio destination\nomx option must be set to hdmi or local\n"); exit(1); } } // input port ilclient_enable_port_buffers(component, 100, NULL, NULL, NULL); ilclient_enable_port(component, 100); err = ilclient_change_component_state(component, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change state to Executing\n"); exit(1); } }
int main(int argc, char **argv) { int i; char *decodeComponentName; char *renderComponentName; int err; ILCLIENT_T *handle; COMPONENT_T *decodeComponent; COMPONENT_T *renderComponent; COMPONENT_T *fxComponent; int do_deinterlace = 0; if (argc >= 2) { IMG = argv[1]; } if (argc >= 3) { if (strcmp(argv[2],"d")==0) do_deinterlace = 1; } FILE *fp = fopen(IMG, "r"); int toread = get_file_size(IMG); OMX_BUFFERHEADERTYPE *buff_header; decodeComponentName = "video_decode"; renderComponentName = "video_render"; bcm_host_init(); handle = ilclient_init(); if (handle == NULL) { fprintf(stderr, "IL client init failed\n"); exit(1); } if (OMX_Init() != OMX_ErrorNone) { ilclient_destroy(handle); fprintf(stderr, "OMX init failed\n"); exit(1); } ilclient_set_error_callback(handle, error_callback, NULL); ilclient_set_eos_callback(handle, eos_callback, NULL); setup_decodeComponent(handle, decodeComponentName, &decodeComponent); setup_renderComponent(handle, renderComponentName, &renderComponent); if (do_deinterlace) setup_fxComponent(handle, "image_fx", &fxComponent); // both components now in Idle state, no buffers, ports disabled // input port ilclient_enable_port_buffers(decodeComponent, 130, NULL, NULL, NULL); ilclient_enable_port(decodeComponent, 130); err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change state to Executing\n"); exit(1); } printState(ilclient_get_handle(decodeComponent)); // Read the first block so that the decodeComponent can get // the dimensions of the video and call port settings // changed on the output port to configure it while (toread > 0) { buff_header = ilclient_get_input_buffer(decodeComponent, 130, 1 /* block */); if (buff_header != NULL) { read_into_buffer_and_empty(fp, decodeComponent, buff_header, &toread); // If all the file has been read in, then // we have to re-read this first block. // Broadcom bug? if (toread <= 0) { printf("Rewinding\n"); // wind back to start and repeat fp = freopen(IMG, "r", fp); toread = get_file_size(IMG); } } if (toread > 0 && ilclient_remove_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) { printf("Removed port settings event\n"); break; } else { printf("No port setting seen yet\n"); } // wait for first input block to set params for output port if (toread == 0) { // wait for first input block to set params for output port err = ilclient_wait_for_event(decodeComponent, OMX_EventPortSettingsChanged, 131, 0, 0, 1, ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 2000); if (err < 0) { fprintf(stderr, "No port settings change\n"); //exit(1); } else { printf("Port settings changed\n"); break; } } } // set the decode component to idle and disable its ports err = ilclient_change_component_state(decodeComponent, OMX_StateIdle); if (err < 0) { fprintf(stderr, "Couldn't change state to Idle\n"); exit(1); } ilclient_disable_port(decodeComponent, 131); ilclient_disable_port_buffers(decodeComponent, 131, NULL, NULL, NULL); if (do_deinterlace) { // set up the tunnel between decode and fx ports err = OMX_SetupTunnel(ilclient_get_handle(decodeComponent), 131, ilclient_get_handle(fxComponent), 190); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel 1 %X\n", err); exit(1); } else { printf("Tunnel 1 set up ok\n"); } // set up the tunnel between fx and render ports err = OMX_SetupTunnel(ilclient_get_handle(fxComponent), 191, ilclient_get_handle(renderComponent), 90); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel 2 %X\n", err); exit(1); } else { printf("Tunnel 2 set up ok\n"); } } else { // set up the tunnel between decode and render ports err = OMX_SetupTunnel(ilclient_get_handle(decodeComponent), 131, ilclient_get_handle(renderComponent), 90); if (err != OMX_ErrorNone) { fprintf(stderr, "Error setting up tunnel %X\n", err); exit(1); } else { printf("Tunnel set up ok\n"); } } // Okay to go back to processing data // enable the decode output ports //UNNECESSARY?? PGB OMX_SendCommand(ilclient_get_handle(decodeComponent), //UNNECESSARY?? PGB OMX_CommandPortEnable, 131, NULL); ilclient_enable_port(decodeComponent, 131); if (do_deinterlace) { setup_shared_buffer_format(decodeComponent, 131, fxComponent, 191); // enable fx ports ilclient_enable_port(fxComponent, 190); ilclient_enable_port(fxComponent, 191); //UNNECESSARY?? PGB OMX_SendCommand(ilclient_get_handle(renderComponent), //UNNECESSARY?? PGB OMX_CommandPortEnable, 90, NULL); // setup_shared_buffer_format(fxComponent, renderComponent); } // enable the render output ports ilclient_enable_port(renderComponent, 90); // set all components to executing state err = ilclient_change_component_state(decodeComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change decode to Executing\n"); exit(1); } if (do_deinterlace) { err = ilclient_change_component_state(fxComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change fx to Executing\n"); exit(1); } } err = ilclient_change_component_state(renderComponent, OMX_StateExecuting); if (err < 0) { fprintf(stderr, "Couldn't change render to Executing\n"); exit(1); } print_port_info(ilclient_get_handle(decodeComponent), 131); if (do_deinterlace) { print_port_info(ilclient_get_handle(fxComponent), 190); print_port_info(ilclient_get_handle(fxComponent), 191); } print_port_info(ilclient_get_handle(renderComponent), 90); // now work through the file while (toread > 0) { OMX_ERRORTYPE r; // do we have a decode input buffer we can fill and empty? buff_header = ilclient_get_input_buffer(decodeComponent, 130, 1 /* block */); if (buff_header != NULL) { read_into_buffer_and_empty(fp, decodeComponent, buff_header, &toread); } usleep(100000); // print_port_info(ilclient_get_handle(renderComponent), 90); } ilclient_wait_for_event(renderComponent, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, ILCLIENT_BUFFER_FLAG_EOS, 10000); printf("EOS on render\n"); sleep(100); exit(0); }
static int brcm_omx_vc03_start(void) { struct snd_pcm_runtime *runtime; OMX_ERRORTYPE error=OMX_ErrorNone; DEBUG("\n %lx:brcm_omx_vc03_start %d\n",jiffies,alsa_pcm_event); //return if stopped by ALSA if ( ((alsa_pcm_event & PCM_EVENT_PLAY_START) == 0) && ((alsa_pcm_event & PCM_EVENT_RECD_START) == 0) ) return 0; //check if init? if (client==NULL) { client = ilclient_init(); if (client==NULL) { DEBUG("\n %lx:ilclient_init failed\n",jiffies); return -1; } // error = OMX_Init(); ERROR_RETURN("OMX_Init",error); } //init playback if ( (alsa_pcm_event & PCM_EVENT_PLAY_START) && (play_init==0)) { play_init=1; brcm_omx_vc03_play_init(); ilclient_set_empty_buffer_done_callback(client,empty_buffer_done_cb,NULL); } //init record if ( (alsa_pcm_event & PCM_EVENT_RECD_START) && (recd_init==0)) { recd_init=1; brcm_omx_vc03_recd_init(); ilclient_set_fill_buffer_done_callback(client,fill_buffer_done_cb,NULL); } if (alsa_pcm_event & PCM_EVENT_PLAY_START) { //do volume control if (g_brcm_alsa_chip->pcm_param_changed & PCM_EVENT_PLAY_VOLM) { OMX_AUDIO_CONFIG_VOLUMETYPE param; memset(¶m, 0, sizeof(OMX_AUDIO_CONFIG_VOLUMETYPE)); param.nSize = sizeof(OMX_AUDIO_CONFIG_VOLUMETYPE); param.nVersion.nVersion = OMX_VERSION; param.nPortIndex = 100; error = OMX_GetParameter(st_play.comp, OMX_IndexConfigAudioVolume, ¶m); ERROR_RETURN("OMX_GetParameter play volume param",error); param.bLinear = 1; param.sVolume.nValue = g_brcm_alsa_chip->pcm_playback_volume; error = OMX_SetParameter(st_play.comp, OMX_IndexConfigAudioVolume, ¶m); ERROR_RETURN("OMX_SetParameter play volume param",error); error = OMX_GetParameter(st_play.comp, OMX_IndexConfigAudioVolume, ¶m); ERROR_RETURN("OMX_GetParameter play volume param",error); DEBUG("\n play volume=%d %d %d %d\n",g_brcm_alsa_chip->pcm_playback_volume, (int)param.sVolume.nValue,(int)param.sVolume.nMin,(int)param.sVolume.nMax); //reset: i don't think we need a lock here g_brcm_alsa_chip->pcm_param_changed &= ~PCM_EVENT_PLAY_VOLM; } //do mute if (g_brcm_alsa_chip->pcm_param_changed & PCM_EVENT_PLAY_MUTE) { OMX_AUDIO_CONFIG_MUTETYPE param; memset(¶m, 0, sizeof(OMX_AUDIO_CONFIG_MUTETYPE)); param.nSize = sizeof(OMX_AUDIO_CONFIG_MUTETYPE); param.nVersion.nVersion = OMX_VERSION; param.nPortIndex = 100; param.bMute = g_brcm_alsa_chip->pcm_playback_mute; error = OMX_SetParameter(st_play.comp, OMX_IndexConfigAudioMute, ¶m); ERROR_RETURN("OMX_SetParameter play mute param",error); DEBUG("\n play mute = %d\n",g_brcm_alsa_chip->pcm_playback_mute); //reset: i don't think we need a lock here g_brcm_alsa_chip->pcm_param_changed &= ~PCM_EVENT_PLAY_MUTE; } runtime = g_brcm_alsa_chip->substream[0]->runtime; play_buffer = st_play.out_list; play_buffer->nOffset = 0; play_buffer->nFilledLen = g_brcm_alsa_chip->period_bytes[0]; play_buffer->pBuffer = &(runtime->dma_area[g_brcm_alsa_chip->pcm_ptr[0]]); error = OMX_EmptyThisBuffer(st_play.comp, play_buffer); ERROR_RETURN("OMX_EmptyThisBuffer",error); DEBUG("\n %lx:playback wait to be done\n",jiffies); } if (alsa_pcm_event & PCM_EVENT_RECD_START) { //do volume control //? runtime = g_brcm_alsa_chip->substream[1]->runtime; recd_buffer->nOffset = 0; recd_buffer->nFilledLen = g_brcm_alsa_chip->period_bytes[1]; recd_buffer->pBuffer = &(runtime->dma_area[g_brcm_alsa_chip->pcm_ptr[1]]); DEBUG("\n %lx:record do OMX_FillThisBuffer %x %x\n",jiffies,(int)recd_buffer,(int)recd_buffer); error = OMX_FillThisBuffer(st_recd.comp, recd_buffer); ERROR_RETURN("OMX_FillThisBuffer",error); DEBUG("\n %lx:record wait to be done OMX_FillThisBuffer %x\n",jiffies,(int)recd_buffer->pBuffer); //circular would be nicer recd_buffer = (OMX_BUFFERHEADERTYPE*)st_recd.out_list->pAppPrivate; if (recd_buffer==NULL) recd_buffer = st_recd.out_list; } return 0; }
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; }
/* ------------------------------------------------- / 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"); }
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
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); }