00001
00030 #include <omxcore.h>
00031 #include <omx_base_audio_port.h>
00032 #include <omx_base_clock_port.h>
00033 #include <omx_alsasink_component.h>
00034 #include <config.h>
00035
00037 #define MAX_COMPONENT_ALSASINK 1
00038
00040 static OMX_U32 noAlsasinkInstance=0;
00041
00042 #ifdef AV_SYNC_LOG //TODO : give seg fault if enabled
00043 static FILE *fd = NULL;
00044 #endif
00045
00048 OMX_ERRORTYPE omx_alsasink_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) {
00049 int err;
00050 int omxErr;
00051 omx_base_audio_PortType *pPort;
00052 omx_alsasink_component_PrivateType* omx_alsasink_component_Private;
00053
00054 if (!openmaxStandComp->pComponentPrivate) {
00055 openmaxStandComp->pComponentPrivate = calloc(1, sizeof(omx_alsasink_component_PrivateType));
00056 if(openmaxStandComp->pComponentPrivate==NULL) {
00057 return OMX_ErrorInsufficientResources;
00058 }
00059 }
00060
00061 omx_alsasink_component_Private = openmaxStandComp->pComponentPrivate;
00062 omx_alsasink_component_Private->ports = NULL;
00063
00064 omxErr = omx_base_sink_Constructor(openmaxStandComp,cComponentName);
00065 if (omxErr != OMX_ErrorNone) {
00066 return OMX_ErrorInsufficientResources;
00067 }
00068
00069 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nStartPortNumber = 0;
00070 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts = 1;
00071
00072 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nStartPortNumber = 1;
00073 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts = 1;
00074
00076 if ((omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts +
00077 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)
00078 && !omx_alsasink_component_Private->ports) {
00079 omx_alsasink_component_Private->ports = calloc((omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts +
00080 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts), sizeof(omx_base_PortType *));
00081 if (!omx_alsasink_component_Private->ports) {
00082 return OMX_ErrorInsufficientResources;
00083 }
00084 omx_alsasink_component_Private->ports[0] = calloc(1, sizeof(omx_base_audio_PortType));
00085 if (!omx_alsasink_component_Private->ports[0]) {
00086 return OMX_ErrorInsufficientResources;
00087 }
00088 base_audio_port_Constructor(openmaxStandComp, &omx_alsasink_component_Private->ports[0], 0, OMX_TRUE);
00089
00090 omx_alsasink_component_Private->ports[1] = calloc(1, sizeof(omx_base_clock_PortType));
00091 if (!omx_alsasink_component_Private->ports[1]) {
00092 return OMX_ErrorInsufficientResources;
00093 }
00094 base_clock_port_Constructor(openmaxStandComp, &omx_alsasink_component_Private->ports[1], 1, OMX_TRUE);
00095 }
00096
00097 pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX];
00098
00099
00101 pPort->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
00102
00103 pPort->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE;
00104
00105
00106 omx_alsasink_component_Private->BufferMgmtCallback = omx_alsasink_component_BufferMgmtCallback;
00107 omx_alsasink_component_Private->destructor = omx_alsasink_component_Destructor;
00108 pPort->Port_SendBufferFunction = omx_alsasink_component_port_SendBufferFunction;
00109
00110 setHeader(&pPort->sAudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
00111 pPort->sAudioParam.nPortIndex = 0;
00112 pPort->sAudioParam.nIndex = 0;
00113 pPort->sAudioParam.eEncoding = OMX_AUDIO_CodingPCM;
00114
00115
00116 setHeader(&omx_alsasink_component_Private->sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00117 omx_alsasink_component_Private->sPCMModeParam.nPortIndex = 0;
00118 omx_alsasink_component_Private->sPCMModeParam.nChannels = 2;
00119 omx_alsasink_component_Private->sPCMModeParam.eNumData = OMX_NumericalDataSigned;
00120 omx_alsasink_component_Private->sPCMModeParam.eEndian = OMX_EndianLittle;
00121 omx_alsasink_component_Private->sPCMModeParam.bInterleaved = OMX_TRUE;
00122 omx_alsasink_component_Private->sPCMModeParam.nBitPerSample = 16;
00123 omx_alsasink_component_Private->sPCMModeParam.nSamplingRate = 44100;
00124 omx_alsasink_component_Private->sPCMModeParam.ePCMMode = OMX_AUDIO_PCMModeLinear;
00125 omx_alsasink_component_Private->sPCMModeParam.eChannelMapping[0] = OMX_AUDIO_ChannelNone;
00126
00127
00128 #ifdef AV_SYNC_LOG
00129 fd = fopen("audio_timestamps.out","w");
00130 if(!fd) {
00131 DEBUG(DEB_LEV_ERR, "Couldn't open audio timestamp log err=%d\n",errno);
00132 }
00133 #endif
00134
00135 noAlsasinkInstance++;
00136 if(noAlsasinkInstance > MAX_COMPONENT_ALSASINK) {
00137 return OMX_ErrorInsufficientResources;
00138 }
00139
00140
00141 if ((err = snd_pcm_open (&omx_alsasink_component_Private->playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
00142 DEBUG(DEB_LEV_ERR, "cannot open audio device %s (%s)\n", "default", snd_strerror (err));
00143 return OMX_ErrorHardware;
00144 }
00145 else
00146 DEBUG(DEB_LEV_SIMPLE_SEQ, "Got playback handle at %p %p in %i\n", omx_alsasink_component_Private->playback_handle, &omx_alsasink_component_Private->playback_handle, getpid());
00147
00148 if (snd_pcm_hw_params_malloc(&omx_alsasink_component_Private->hw_params) < 0) {
00149 DEBUG(DEB_LEV_ERR, "%s: failed allocating input pPort hw parameters\n", __func__);
00150 return OMX_ErrorHardware;
00151 }
00152 else
00153 DEBUG(DEB_LEV_SIMPLE_SEQ, "Got hw parameters at %p\n", omx_alsasink_component_Private->hw_params);
00154
00155 if ((err = snd_pcm_hw_params_any (omx_alsasink_component_Private->playback_handle, omx_alsasink_component_Private->hw_params)) < 0) {
00156 DEBUG(DEB_LEV_ERR, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));
00157 return OMX_ErrorHardware;
00158 }
00159
00160 openmaxStandComp->SetParameter = omx_alsasink_component_SetParameter;
00161 openmaxStandComp->GetParameter = omx_alsasink_component_GetParameter;
00162
00163
00164 omx_alsasink_component_Private->AudioPCMConfigured = 0;
00165 omx_alsasink_component_Private->eState = OMX_TIME_ClockStateStopped;
00166 omx_alsasink_component_Private->xScale = 1<<16;
00167
00168 if (!omx_alsasink_component_Private->AudioPCMConfigured) {
00169 DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring the PCM interface in the Init function\n");
00170 omxErr = omx_alsasink_component_SetParameter(openmaxStandComp, OMX_IndexParamAudioPcm, &omx_alsasink_component_Private->sPCMModeParam);
00171 if(omxErr != OMX_ErrorNone){
00172 DEBUG(DEB_LEV_ERR, "In %s Error %08x\n",__func__,omxErr);
00173 }
00174 }
00175
00176 return OMX_ErrorNone;
00177 }
00178
00181 OMX_ERRORTYPE omx_alsasink_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
00182 omx_alsasink_component_PrivateType* omx_alsasink_component_Private = openmaxStandComp->pComponentPrivate;
00183 OMX_U32 i;
00184
00185 if(omx_alsasink_component_Private->hw_params) {
00186 snd_pcm_hw_params_free (omx_alsasink_component_Private->hw_params);
00187 }
00188 if(omx_alsasink_component_Private->playback_handle) {
00189 snd_pcm_close(omx_alsasink_component_Private->playback_handle);
00190 }
00191
00192
00193 if (omx_alsasink_component_Private->ports) {
00194 for (i=0; i < (omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts +
00195 omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts); i++) {
00196 if(omx_alsasink_component_Private->ports[i])
00197 omx_alsasink_component_Private->ports[i]->PortDestructor(omx_alsasink_component_Private->ports[i]);
00198 }
00199 free(omx_alsasink_component_Private->ports);
00200 omx_alsasink_component_Private->ports=NULL;
00201 }
00202
00203 #ifdef AV_SYNC_LOG
00204 fclose(fd);
00205 #endif
00206
00207 noAlsasinkInstance--;
00208
00209 return omx_base_sink_Destructor(openmaxStandComp);
00210
00211 }
00212
00218 OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) {
00219
00220 OMX_ERRORTYPE err;
00221 OMX_U32 portIndex;
00222 OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
00223 omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00224 OMX_BOOL SendFrame;
00225 omx_base_clock_PortType* pClockPort;
00226 #if NO_GST_OMX_PATCH
00227 unsigned int i;
00228 #endif
00229
00230 portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex;
00231 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex);
00232
00233 if (portIndex != openmaxStandPort->sPortParam.nPortIndex) {
00234 DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n",
00235 __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex);
00236 return OMX_ErrorBadPortIndex;
00237 }
00238
00239 if(omx_base_component_Private->state == OMX_StateInvalid) {
00240 DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__);
00241 return OMX_ErrorInvalidState;
00242 }
00243
00244 if(omx_base_component_Private->state != OMX_StateExecuting &&
00245 omx_base_component_Private->state != OMX_StatePause &&
00246 omx_base_component_Private->state != OMX_StateIdle) {
00247 DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state);
00248 return OMX_ErrorIncorrectStateOperation;
00249 }
00250 if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) ||
00251 (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle &&
00252 (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) {
00253 DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name);
00254 return OMX_ErrorIncorrectStateOperation;
00255 }
00256
00257
00258 #if NO_GST_OMX_PATCh
00259 {
00260 OMX_BOOL foundBuffer = OMX_FALSE;
00261 if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) {
00262 for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00263 if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) {
00264 foundBuffer = OMX_TRUE;
00265 break;
00266 }
00267 }
00268 }
00269 if (!foundBuffer) {
00270 return OMX_ErrorBadParameter;
00271 }
00272 }
00273 #endif
00274
00275 if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) {
00276 DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__);
00277 return err;
00278 }
00279
00280 pClockPort = (omx_base_clock_PortType*)omx_base_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX];
00281 if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort)){
00282 if(pBuffer->nInputPortIndex == OMX_BASE_SINK_INPUTPORT_INDEX && pBuffer->nFlags == OMX_BUFFERFLAG_STARTTIME)
00283 SendFrame = OMX_TRUE;
00284 else{
00285 SendFrame = omx_alsasink_component_ClockPortHandleFunction((omx_alsasink_component_PrivateType*)omx_base_component_Private, pBuffer);
00286
00287 if(!SendFrame) pBuffer->nFilledLen=0;
00288 }
00289 }
00290
00291
00292 if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){
00293 queue(openmaxStandPort->pBufferQueue, pBuffer);
00294 tsem_up(openmaxStandPort->pBufferSem);
00295 DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex);
00296 tsem_up(omx_base_component_Private->bMgmtSem);
00297 }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){
00298 DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n",
00299 __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex);
00300 queue(openmaxStandPort->pBufferQueue, pBuffer);
00301 tsem_up(openmaxStandPort->pBufferSem);
00302 }
00303 else {
00304 DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__);
00305 return OMX_ErrorIncorrectStateOperation;
00306 }
00307 return OMX_ErrorNone;
00308 }
00309
00310 OMX_BOOL omx_alsasink_component_ClockPortHandleFunction(omx_alsasink_component_PrivateType* omx_alsasink_component_Private, OMX_BUFFERHEADERTYPE* inputbuffer){
00311 omx_base_clock_PortType* pClockPort;
00312 OMX_BUFFERHEADERTYPE* clockBuffer;
00313 OMX_TIME_MEDIATIMETYPE* pMediaTime;
00314 OMX_HANDLETYPE hclkComponent;
00315 OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp;
00316 OMX_ERRORTYPE err;
00317 OMX_BOOL SendFrame=OMX_TRUE;
00318
00319 int static count=0;
00320
00321 pClockPort = (omx_base_clock_PortType*)omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX];
00322 hclkComponent = pClockPort->hTunneledComponent;
00323 setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE));
00324
00325
00326 if(pClockPort->pBufferSem->semval>0){
00327 tsem_down(pClockPort->pBufferSem);
00328 clockBuffer = dequeue(pClockPort->pBufferQueue);
00329 pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00330 if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) {
00331 if( (pMediaTime->xScale>>16)==1){
00332
00333 hclkComponent = pClockPort->hTunneledComponent;
00334 setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE));
00335 sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00336 sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp;
00337 err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference, &sClientTimeStamp);
00338 if(err!=OMX_ErrorNone) {
00339 DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00340 }
00341 }
00342 omx_alsasink_component_Private->xScale = pMediaTime->xScale;
00343 }
00344 pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer);
00345 }
00346
00347 count++;
00348 if(count==15){
00349 count=0;
00350
00351 if(!PORT_IS_BEING_FLUSHED(pClockPort)){
00352 pClockPort->sMediaTimeRequest.nOffset = 100;
00353 pClockPort->sMediaTimeRequest.nPortIndex = pClockPort->nTunneledPort;
00354 pClockPort->sMediaTimeRequest.pClientPrivate = NULL;
00355 pClockPort->sMediaTimeRequest.nMediaTimestamp = inputbuffer->nTimeStamp;
00356 err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeMediaTimeRequest, &pClockPort->sMediaTimeRequest);
00357 if(err!=OMX_ErrorNone) {
00358 DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00359 }
00360 if(!PORT_IS_BEING_FLUSHED(pClockPort)) {
00361 tsem_down(pClockPort->pBufferSem);
00362 clockBuffer = dequeue(pClockPort->pBufferQueue);
00363 pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00364 if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) {
00365 omx_alsasink_component_Private->xScale = pMediaTime->xScale;
00366 }
00367 if(pMediaTime->eUpdateType==OMX_TIME_UpdateRequestFulfillment){
00368 if((pMediaTime->nOffset)>0) {
00369 #ifdef AV_SYNC_LOG
00370 fprintf(fd,"%lld %lld\n",inputbuffer->nTimeStamp,pMediaTime->nWallTimeAtMediaTime);
00371 #endif
00372 SendFrame = OMX_TRUE;
00373 }
00374 else {
00375 SendFrame = OMX_FALSE;
00376 }
00377 }
00378 pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer);
00379 }
00380 }
00381 }
00382
00383 return(SendFrame);
00384 }
00385
00389 void omx_alsasink_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer) {
00390 OMX_U32 frameSize;
00391 OMX_S32 written;
00392 OMX_S32 totalBuffer;
00393 OMX_S32 offsetBuffer;
00394 OMX_BOOL allDataSent;
00395 omx_alsasink_component_PrivateType* omx_alsasink_component_Private = openmaxStandComp->pComponentPrivate;
00396 omx_base_audio_PortType *pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX];
00397 OMX_HANDLETYPE hclkComponent;
00398 OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp;
00399 OMX_ERRORTYPE err;
00400 omx_base_clock_PortType* pClockPort;
00401 OMX_BUFFERHEADERTYPE* clockBuffer;
00402 OMX_TIME_MEDIATIMETYPE* pMediaTime;
00403
00404 pClockPort = (omx_base_clock_PortType*)omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX];
00405 if(PORT_IS_TUNNELED(pClockPort)){
00406
00407 if(inputbuffer->nInputPortIndex == OMX_BASE_SINK_INPUTPORT_INDEX && inputbuffer->nFlags == OMX_BUFFERFLAG_STARTTIME) {
00408 DEBUG(DEB_LEV_ERR,"In %s first time stamp = %llx \n", __func__,inputbuffer->nTimeStamp);
00409 inputbuffer->nFlags = 0;
00410 hclkComponent = pClockPort->hTunneledComponent;
00411 setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE));
00412 sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort;
00413 sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp;
00414 err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp);
00415 if(err!=OMX_ErrorNone) {
00416 DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__);
00417 }
00418
00419 if(!PORT_IS_BEING_FLUSHED(pPort) && !PORT_IS_BEING_FLUSHED(pClockPort)) {
00420 tsem_down(pClockPort->pBufferSem);
00421
00422
00423 clockBuffer = dequeue(pClockPort->pBufferQueue);
00424 pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer;
00425 omx_alsasink_component_Private->eState = pMediaTime->eState;
00426 omx_alsasink_component_Private->xScale = pMediaTime->xScale;
00427 pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer);
00428 }
00429 }
00430
00431
00432 if(!(omx_alsasink_component_Private->eState==OMX_TIME_ClockStateRunning && (omx_alsasink_component_Private->xScale>>16)==1)){
00433 inputbuffer->nFilledLen=0;
00434 return;
00435 }
00436 }
00437
00438
00439 frameSize = (omx_alsasink_component_Private->sPCMModeParam.nChannels * omx_alsasink_component_Private->sPCMModeParam.nBitPerSample) >> 3;
00440 DEBUG(DEB_LEV_FULL_SEQ, "Framesize is %u chl=%d bufSize=%d\n",
00441 (int)frameSize, (int)omx_alsasink_component_Private->sPCMModeParam.nChannels, (int)inputbuffer->nFilledLen);
00442
00443 if(inputbuffer->nFilledLen < frameSize){
00444 DEBUG(DEB_LEV_ERR, "Ouch!! In %s input buffer filled len(%d) less than frame size(%d)\n",__func__, (int)inputbuffer->nFilledLen, (int)frameSize);
00445 return;
00446 }
00447
00448 allDataSent = OMX_FALSE;
00449
00450 totalBuffer = inputbuffer->nFilledLen/frameSize;
00451 offsetBuffer = 0;
00452 while (!allDataSent) {
00453
00454 written = snd_pcm_writei(omx_alsasink_component_Private->playback_handle, inputbuffer->pBuffer + (offsetBuffer * frameSize), totalBuffer);
00455 if (written < 0) {
00456 if(written == -EPIPE){
00457 DEBUG(DEB_LEV_ERR, "ALSA Underrun..\n");
00458 snd_pcm_prepare(omx_alsasink_component_Private->playback_handle);
00459 written = 0;
00460 } else {
00461 DEBUG(DEB_LEV_ERR, "Cannot send any data to the audio device %s (%s)\n", "default", snd_strerror (written));
00462 DEBUG(DEB_LEV_ERR, "IB FilledLen=%d,totalBuffer=%d,frame size=%d,offset=%d\n",
00463 (int)inputbuffer->nFilledLen, (int)totalBuffer, (int)frameSize, (int)offsetBuffer);
00464 break;
00465 return;
00466 }
00467 }
00468
00469 if(written != totalBuffer){
00470 totalBuffer = totalBuffer - written;
00471 offsetBuffer = written;
00472 } else {
00473 DEBUG(DEB_LEV_FULL_SEQ, "Buffer successfully sent to ALSA. Length was %i\n", (int)inputbuffer->nFilledLen);
00474 allDataSent = OMX_TRUE;
00475 }
00476 }
00477 inputbuffer->nFilledLen=0;
00478 }
00479
00480 OMX_ERRORTYPE omx_alsasink_component_SetParameter(
00481 OMX_IN OMX_HANDLETYPE hComponent,
00482 OMX_IN OMX_INDEXTYPE nParamIndex,
00483 OMX_IN OMX_PTR ComponentParameterStructure)
00484 {
00485 int err;
00486 int omxErr = OMX_ErrorNone;
00487 OMX_AUDIO_PARAM_PORTFORMATTYPE *pAudioPortFormat;
00488 OMX_OTHER_PARAM_PORTFORMATTYPE *pOtherPortFormat;
00489 OMX_AUDIO_PARAM_MP3TYPE * pAudioMp3;
00490 OMX_U32 portIndex;
00491
00492
00493 OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
00494 omx_alsasink_component_PrivateType* omx_alsasink_component_Private = openmaxStandComp->pComponentPrivate;
00495 omx_base_audio_PortType* pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX];
00496 omx_base_clock_PortType *pClockPort;
00497 snd_pcm_t* playback_handle = omx_alsasink_component_Private->playback_handle;
00498 snd_pcm_hw_params_t* hw_params = omx_alsasink_component_Private->hw_params;
00499
00500 if (ComponentParameterStructure == NULL) {
00501 return OMX_ErrorBadParameter;
00502 }
00503
00504 DEBUG(DEB_LEV_SIMPLE_SEQ, " Setting parameter %i\n", nParamIndex);
00505
00511 err = snd_pcm_hw_params_any (playback_handle, hw_params);
00512
00513 switch(nParamIndex) {
00514 case OMX_IndexParamAudioPortFormat:
00515 pAudioPortFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00516 portIndex = pAudioPortFormat->nPortIndex;
00517
00518 omxErr = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pAudioPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
00519 if(omxErr!=OMX_ErrorNone) {
00520 DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr);
00521 break;
00522 }
00523 if (portIndex < 1) {
00524 memcpy(&pPort->sAudioParam,pAudioPortFormat,sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
00525 } else {
00526 return OMX_ErrorBadPortIndex;
00527 }
00528 break;
00529 case OMX_IndexParamOtherPortFormat:
00530 pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00531 portIndex = pOtherPortFormat->nPortIndex;
00532 err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pOtherPortFormat, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE));
00533 if(err!=OMX_ErrorNone) {
00534 DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err);
00535 break;
00536 }
00537 if(portIndex != 1) {
00538 return OMX_ErrorBadPortIndex;
00539 }
00540 pClockPort = (omx_base_clock_PortType *) omx_alsasink_component_Private->ports[portIndex];
00541
00542 pClockPort->sOtherParam.eFormat = pOtherPortFormat->eFormat;
00543 break;
00544 case OMX_IndexParamAudioPcm:
00545 {
00546 unsigned int rate;
00547 OMX_AUDIO_PARAM_PCMMODETYPE* sPCMModeParam = (OMX_AUDIO_PARAM_PCMMODETYPE*)ComponentParameterStructure;
00548
00549 portIndex = sPCMModeParam->nPortIndex;
00550
00551 omxErr = omx_base_component_ParameterSanityCheck(hComponent, portIndex, sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00552 if(omxErr!=OMX_ErrorNone) {
00553 DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr);
00554 break;
00555 }
00556
00557 omx_alsasink_component_Private->AudioPCMConfigured = 1;
00558 if(sPCMModeParam->nPortIndex != omx_alsasink_component_Private->sPCMModeParam.nPortIndex){
00559 DEBUG(DEB_LEV_ERR, "Error setting input pPort index\n");
00560 omxErr = OMX_ErrorBadParameter;
00561 break;
00562 }
00563
00564 if(snd_pcm_hw_params_set_channels(playback_handle, hw_params, sPCMModeParam->nChannels)){
00565 DEBUG(DEB_LEV_ERR, "Error setting number of channels\n");
00566 return OMX_ErrorBadParameter;
00567 }
00568
00569 if(sPCMModeParam->bInterleaved == OMX_TRUE){
00570 if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
00571 DEBUG(DEB_LEV_ERR, "cannot set access type intrleaved (%s)\n", snd_strerror (err));
00572 return OMX_ErrorHardware;
00573 }
00574 }
00575 else{
00576 if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) {
00577 DEBUG(DEB_LEV_ERR, "cannot set access type non interleaved (%s)\n", snd_strerror (err));
00578 return OMX_ErrorHardware;
00579 }
00580 }
00581 rate = sPCMModeParam->nSamplingRate;
00582 if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0)) < 0) {
00583 DEBUG(DEB_LEV_ERR, "cannot set sample rate (%s)\n", snd_strerror (err));
00584 return OMX_ErrorHardware;
00585 }
00586 else{
00587 sPCMModeParam->nSamplingRate = rate;
00588 DEBUG(DEB_LEV_PARAMS, "Set correctly sampling rate to %lu\n", sPCMModeParam->nSamplingRate);
00589 }
00590
00591 if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeLinear){
00592 snd_pcm_format_t snd_pcm_format = SND_PCM_FORMAT_UNKNOWN;
00593 DEBUG(DEB_LEV_PARAMS, "Bit per sample %i, signed=%i, little endian=%i\n",
00594 (int)sPCMModeParam->nBitPerSample,
00595 (int)sPCMModeParam->eNumData == OMX_NumericalDataSigned,
00596 (int)sPCMModeParam->eEndian == OMX_EndianLittle);
00597
00598 switch(sPCMModeParam->nBitPerSample){
00599 case 8:
00600 if(sPCMModeParam->eNumData == OMX_NumericalDataSigned) {
00601 snd_pcm_format = SND_PCM_FORMAT_S8;
00602 } else {
00603 snd_pcm_format = SND_PCM_FORMAT_U8;
00604 }
00605 break;
00606 case 16:
00607 if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){
00608 if(sPCMModeParam->eEndian == OMX_EndianLittle) {
00609 snd_pcm_format = SND_PCM_FORMAT_S16_LE;
00610 } else {
00611 snd_pcm_format = SND_PCM_FORMAT_S16_BE;
00612 }
00613 }
00614 if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){
00615 if(sPCMModeParam->eEndian == OMX_EndianLittle){
00616 snd_pcm_format = SND_PCM_FORMAT_U16_LE;
00617 } else {
00618 snd_pcm_format = SND_PCM_FORMAT_U16_BE;
00619 }
00620 }
00621 break;
00622 case 24:
00623 if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){
00624 if(sPCMModeParam->eEndian == OMX_EndianLittle) {
00625 snd_pcm_format = SND_PCM_FORMAT_S24_LE;
00626 } else {
00627 snd_pcm_format = SND_PCM_FORMAT_S24_BE;
00628 }
00629 }
00630 if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){
00631 if(sPCMModeParam->eEndian == OMX_EndianLittle) {
00632 snd_pcm_format = SND_PCM_FORMAT_U24_LE;
00633 } else {
00634 snd_pcm_format = SND_PCM_FORMAT_U24_BE;
00635 }
00636 }
00637 break;
00638
00639 case 32:
00640 if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){
00641 if(sPCMModeParam->eEndian == OMX_EndianLittle) {
00642 snd_pcm_format = SND_PCM_FORMAT_S32_LE;
00643 } else {
00644 snd_pcm_format = SND_PCM_FORMAT_S32_BE;
00645 }
00646 }
00647 if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){
00648 if(sPCMModeParam->eEndian == OMX_EndianLittle) {
00649 snd_pcm_format = SND_PCM_FORMAT_U32_LE;
00650 } else {
00651 snd_pcm_format = SND_PCM_FORMAT_U32_BE;
00652 }
00653 }
00654 break;
00655 default:
00656 omxErr = OMX_ErrorBadParameter;
00657 break;
00658 }
00659
00660 if(snd_pcm_format != SND_PCM_FORMAT_UNKNOWN){
00661 if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, snd_pcm_format)) < 0) {
00662 DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err));
00663 return OMX_ErrorHardware;
00664 }
00665 memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00666 } else{
00667 DEBUG(DEB_LEV_SIMPLE_SEQ, "ALSA OMX_IndexParamAudioPcm configured\n");
00668 memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00669 }
00670 }
00671 else if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeALaw){
00672 DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring ALAW format\n\n");
00673 if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_A_LAW)) < 0) {
00674 DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err));
00675 return OMX_ErrorHardware;
00676 }
00677 memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00678 }
00679 else if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeMULaw){
00680 DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring ALAW format\n\n");
00681 if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_MU_LAW)) < 0) {
00682 DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err));
00683 return OMX_ErrorHardware;
00684 }
00685 memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00686 }
00688 DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring the PCM interface\n");
00689 if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
00690 DEBUG(DEB_LEV_ERR, "cannot set parameters (%s)\n", snd_strerror (err));
00691 return OMX_ErrorHardware;
00692 }
00693
00694 if ((err = snd_pcm_prepare (playback_handle)) < 0) {
00695 DEBUG(DEB_LEV_ERR, "cannot prepare audio interface for use (%s)\n", snd_strerror (err));
00696 return OMX_ErrorHardware;
00697 }
00698 }
00699 break;
00700 case OMX_IndexParamAudioMp3:
00701 pAudioMp3 = (OMX_AUDIO_PARAM_MP3TYPE*)ComponentParameterStructure;
00702
00703 omxErr = omx_base_component_ParameterSanityCheck(hComponent, pAudioMp3->nPortIndex, pAudioMp3, sizeof(OMX_AUDIO_PARAM_MP3TYPE));
00704 if(omxErr != OMX_ErrorNone) {
00705 DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr);
00706 break;
00707 }
00708 break;
00709 default:
00710 return omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00711 }
00712 return omxErr;
00713 }
00714
00715 OMX_ERRORTYPE omx_alsasink_component_GetParameter(
00716 OMX_IN OMX_HANDLETYPE hComponent,
00717 OMX_IN OMX_INDEXTYPE nParamIndex,
00718 OMX_INOUT OMX_PTR ComponentParameterStructure)
00719 {
00720 OMX_AUDIO_PARAM_PORTFORMATTYPE *pAudioPortFormat;
00721 OMX_OTHER_PARAM_PORTFORMATTYPE *pOtherPortFormat;
00722 OMX_ERRORTYPE err = OMX_ErrorNone;
00723 OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
00724 omx_alsasink_component_PrivateType* omx_alsasink_component_Private = openmaxStandComp->pComponentPrivate;
00725 omx_base_audio_PortType *pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX];
00726 omx_base_clock_PortType *pClockPort = (omx_base_clock_PortType *) omx_alsasink_component_Private->ports[1];
00727 if (ComponentParameterStructure == NULL) {
00728 return OMX_ErrorBadParameter;
00729 }
00730 DEBUG(DEB_LEV_SIMPLE_SEQ, " Getting parameter %i\n", nParamIndex);
00731
00732 switch(nParamIndex) {
00733 case OMX_IndexParamAudioInit:
00734 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) {
00735 break;
00736 }
00737 memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio], sizeof(OMX_PORT_PARAM_TYPE));
00738 break;
00739 case OMX_IndexParamOtherInit:
00740 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) {
00741 break;
00742 }
00743 memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther], sizeof(OMX_PORT_PARAM_TYPE));
00744 break;
00745 case OMX_IndexParamAudioPortFormat:
00746 pAudioPortFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00747 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) {
00748 break;
00749 }
00750 if (pAudioPortFormat->nPortIndex < 1) {
00751 memcpy(pAudioPortFormat, &pPort->sAudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE));
00752 } else {
00753 return OMX_ErrorBadPortIndex;
00754 }
00755 break;
00756 case OMX_IndexParamAudioPcm:
00757 if(((OMX_AUDIO_PARAM_PCMMODETYPE*)ComponentParameterStructure)->nPortIndex !=
00758 omx_alsasink_component_Private->sPCMModeParam.nPortIndex) {
00759 return OMX_ErrorBadParameter;
00760 }
00761 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE))) != OMX_ErrorNone) {
00762 break;
00763 }
00764 memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
00765 break;
00766 case OMX_IndexParamOtherPortFormat:
00767
00768 pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00769
00770 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) {
00771 break;
00772 }
00773 if (pOtherPortFormat->nPortIndex == 1) {
00774 memcpy(pOtherPortFormat, &pClockPort->sOtherParam, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE));
00775 } else {
00776 return OMX_ErrorBadPortIndex;
00777 }
00778 break;
00779 default:
00780 return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00781 }
00782 return err;
00783 }