omx_alsasink_component.c

Go to the documentation of this file.
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  /* for checking AV sync */ //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   // set the pPort params, now that the ports exist  
00101   pPort->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
00102   /*Input pPort buffer size is equal to the size of the output buffer of the previous component*/
00103   pPort->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE;
00104 
00105  /* Initializing the function pointers */
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   /* OMX_AUDIO_PARAM_PCMMODETYPE */
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 /* testing the A/V sync */
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   /* Allocate the playback handle and the hardware parameter structure */
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   /* Write in the default parameters */
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   /* frees port/s */
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   /* Temporarily disable this check for gst-openmax */
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       /* drop the frame */
00287       if(!SendFrame) pBuffer->nFilledLen=0;
00288     }
00289   }
00290 
00291   /* And notify the buffer management thread we have a fresh new buffer to manage */
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 { // If port being flushed and not tunneled then return error
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; //frame counter
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     /* check for any scale change information from the clock component */
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(/*(omx_alsasink_component_Private->xScale>>16)==2 &&*/ (pMediaTime->xScale>>16)==1){ /* check with Q16 format only */
00332              /* rebase the clock time base when turning to normal play mode*/
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){ //send request for every 15th frame 
00349      count=0;
00350     /* requesting for the timestamp for the data delivery */
00351     if(!PORT_IS_BEING_FLUSHED(pClockPort)){
00352      pClockPort->sMediaTimeRequest.nOffset         = 100; /*set the requested offset */
00353      pClockPort->sMediaTimeRequest.nPortIndex      = pClockPort->nTunneledPort;
00354      pClockPort->sMediaTimeRequest.pClientPrivate  = NULL; /* fill the appropriate value */
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); /* wait for the request fullfillment */
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; /* as offset is >0 send the data to the device */
00373          }
00374          else {
00375          SendFrame = OMX_FALSE; /* as offset is <0 do not send the data to the device */
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     /* if  first time stamp is received then notify the clock component */  
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); /* wait for state change notification from clock src*/
00421 
00422         /* update the clock state and clock scale info into the alsa sink private data */
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     /* do not send the data to alsa and return back, if the clock is not running or the scale is anything but 1*/
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   /* Feed it to ALSA */
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 //  DEBUG(DEB_LEV_ERR, "Writing to the device ..\n");
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   /* Check which structure we are being fed and make control its header */
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     /*Check Structure Header and verify component state*/
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       /*Check Structure Header and verify component state*/
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     /*Check Structure Header and verify component state*/
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: /*Call the base component function*/
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   /* Check which structure we are being fed and fill its header */
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: /*Call the base component function*/
00780   return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00781   }
00782   return err;
00783 }

Generated for OpenMAX Bellagio rel. 0.9.0 by  doxygen 1.5.1
SourceForge.net Logo