OpenMAXBellagio 0.9.3
omxvolcontroltest.c
Go to the documentation of this file.
00001 
00027 #include "omxvolcontroltest.h"
00028 #include <extension_struct.h>
00029 
00030 /* Application private date: should go in the component field (segs...) */
00031 appPrivateType* appPriv;
00032 int fd = 0;
00033 unsigned int filesize;
00034 OMX_ERRORTYPE err;
00035 OMX_HANDLETYPE handle;
00036 
00037 OMX_CALLBACKTYPE callbacks = { .EventHandler = volcEventHandler,
00038                                .EmptyBufferDone = volcEmptyBufferDone,
00039                                .FillBufferDone = volcFillBufferDone,
00040 };
00041 
00042 static void setHeader(OMX_PTR header, OMX_U32 size) {
00043   OMX_VERSIONTYPE* ver = (OMX_VERSIONTYPE*)(header + sizeof(OMX_U32));
00044   *((OMX_U32*)header) = size;
00045 
00046   ver->s.nVersionMajor = VERSIONMAJOR;
00047   ver->s.nVersionMinor = VERSIONMINOR;
00048   ver->s.nRevision = VERSIONREVISION;
00049   ver->s.nStep = VERSIONSTEP;
00050 }
00051 
00052 void display_help() {
00053   printf("\n");
00054   printf("Usage: omxvolcontroltest [-o outfile] [-g gain] filename\n");
00055   printf("\n");
00056   printf("       -o outfile: If this option is specified, the output stream is written to outfile\n");
00057   printf("                   otherwise redirected to std output\n");
00058   printf("       -g: Gain of PCM data [0...100]\n");
00059   printf("       -h: Displays this help\n");
00060   printf("\n");
00061   exit(1);
00062 }
00063 
00064 int flagIsOutputExpected;
00065 int flagOutputReceived;
00066 int flagInputReceived;
00067 int flagIsGain;
00068 char *input_file, *output_file;
00069 static OMX_BOOL bEOS=OMX_FALSE;
00070 FILE *outfile;
00071 
00072 int main(int argc, char** argv) {
00073 
00074   OMX_PORT_PARAM_TYPE param;
00075   OMX_BUFFERHEADERTYPE *inBuffer1, *inBuffer2, *outBuffer1, *outBuffer2;
00076   int data_read1;
00077   int data_read2;
00078   OMX_PARAM_PORTDEFINITIONTYPE sPortDef;
00079   OMX_AUDIO_CONFIG_VOLUMETYPE sVolume;
00080   int gain=100;
00081   int argn_dec;
00082   OMX_PARAM_BELLAGIOTHREADS_ID threadsID;
00083   OMX_INDEXTYPE custom_index;
00084 
00085   /* Obtain file descriptor */
00086   if(argc < 2){
00087     display_help();
00088   } else {
00089     flagIsOutputExpected = 0;
00090     flagOutputReceived = 0;
00091     flagInputReceived = 0;
00092     flagIsGain = 0;
00093 
00094     argn_dec = 1;
00095     while (argn_dec<argc) {
00096       if (*(argv[argn_dec]) =='-') {
00097         if (flagIsOutputExpected) {
00098           display_help();
00099         }
00100         switch (*(argv[argn_dec]+1)) {
00101         case 'h':
00102           display_help();
00103           break;
00104         case 'o':
00105           flagIsOutputExpected = 1;
00106           break;
00107         case 'g':
00108           flagIsGain = 1;
00109           break;
00110         default:
00111           display_help();
00112         }
00113       } else {
00114         if (flagIsGain) {
00115           gain = (int)atoi(argv[argn_dec]);
00116           flagIsGain = 0;
00117           if(gain > 100) {
00118             DEBUG(DEFAULT_MESSAGES, "Gain should be between [0..100]\n");
00119             gain = 100;
00120           }
00121         } else if (flagIsOutputExpected) {
00122           output_file = malloc(strlen(argv[argn_dec]) + 1);
00123           strcpy(output_file,argv[argn_dec]);
00124           flagIsOutputExpected = 0;
00125           flagOutputReceived = 1;
00126         } else {
00127           input_file = malloc(strlen(argv[argn_dec]) + 1);
00128           strcpy(input_file,argv[argn_dec]);
00129           flagInputReceived = 1;
00130         }
00131       }
00132       argn_dec++;
00133     }
00134     if (!flagInputReceived) {
00135       display_help();
00136     }
00137     DEBUG(DEFAULT_MESSAGES, "Input file %s", input_file);
00138     DEBUG(DEFAULT_MESSAGES, " to ");
00139     if (flagOutputReceived) {
00140       DEBUG(DEFAULT_MESSAGES, " %s\n", output_file);
00141     }
00142   }
00143 
00144 
00145   fd = open(input_file, O_RDONLY);
00146   if(fd < 0){
00147     perror("Error opening input file\n");
00148     exit(1);
00149   }
00150 
00151   if (flagOutputReceived) {
00152     outfile = fopen(output_file,"wb");
00153     if(outfile == NULL) {
00154       DEBUG(DEB_LEV_ERR, "Error at opening the output file");
00155       exit(1);
00156     }
00157   }
00158 
00159   filesize = getFileSize(fd);
00160   /* Initialize application private data */
00161   appPriv = malloc(sizeof(appPrivateType));
00162   pthread_cond_init(&appPriv->condition, NULL);
00163   pthread_mutex_init(&appPriv->mutex, NULL);
00164   appPriv->eventSem = malloc(sizeof(tsem_t));
00165   tsem_init(appPriv->eventSem, 0);
00166   appPriv->eofSem = malloc(sizeof(tsem_t));
00167   tsem_init(appPriv->eofSem, 0);
00168 
00169   err = OMX_Init();
00170   if(err != OMX_ErrorNone) {
00171     DEBUG(DEB_LEV_ERR, "OMX_Init() failed\n");
00172     exit(1);
00173   }
00176   err = OMX_GetHandle(&handle, "OMX.st.volume.component", NULL /*appPriv */, &callbacks);
00177   if(err != OMX_ErrorNone) {
00178     DEBUG(DEB_LEV_ERR, "OMX_GetHandle failed\n");
00179     exit(1);
00180   }
00181 
00182   /* test the new feature of thread ID detection
00183    */
00184   err = OMX_GetExtensionIndex(handle, "OMX.st.index.param.BellagioThreadsID", &custom_index);
00185   if(err != OMX_ErrorNone) {
00186     DEBUG(DEB_LEV_ERR, "OMX_GetExtensionIndex failed\n");
00187     exit(1);
00188   }
00189 
00190   setHeader(&threadsID, sizeof(OMX_PARAM_BELLAGIOTHREADS_ID));
00191   err = OMX_GetParameter(handle, custom_index, &threadsID);
00192   if(err != OMX_ErrorNone) {
00193     DEBUG(DEB_LEV_ERR, "OMX_GetParameter of extended index failed\n");
00194   } else {
00195       DEBUG(DEFAULT_MESSAGES, "threadsID messages %i buffers %i\n", (int)threadsID.nThreadMessageID, (int)threadsID.nThreadBufferMngtID);
00196   }
00197 
00198   if((gain >= 0) && (gain <100)) {
00199     err = OMX_GetConfig(handle, OMX_IndexConfigAudioVolume, &sVolume);
00200     if(err!=OMX_ErrorNone) {
00201       DEBUG(DEB_LEV_ERR,"Error %08x In OMX_GetConfig 0 \n",err);
00202     }
00203     sVolume.sVolume.nValue = gain;
00204     DEBUG(DEFAULT_MESSAGES, "Setting Gain %d \n", gain);
00205     err = OMX_SetConfig(handle, OMX_IndexConfigAudioVolume, &sVolume);
00206     if(err!=OMX_ErrorNone) {
00207       DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig 0 \n",err);
00208     }
00209   }
00210 
00212   param.nPorts = 2;
00213   setHeader(&param, sizeof(OMX_PORT_PARAM_TYPE));
00214   err = OMX_GetParameter(handle, OMX_IndexParamAudioInit, &param);
00215   if(err != OMX_ErrorNone){
00216     DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n");
00217     exit(1);
00218   }
00219 
00220   setHeader(&sPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
00221   sPortDef.nPortIndex = 0;
00222   err = OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef);
00223 
00224   sPortDef.nBufferCountActual = 2;
00225   err = OMX_SetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef);
00226   if(err != OMX_ErrorNone){
00227     DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n");
00228     exit(1);
00229   }
00230   sPortDef.nPortIndex = 1;
00231   err = OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef);
00232 
00233   sPortDef.nBufferCountActual = 2;
00234   err = OMX_SetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef);
00235   if(err != OMX_ErrorNone){
00236     DEBUG(DEB_LEV_ERR, "Error in getting OMX_PORT_PARAM_TYPE parameter\n");
00237     exit(1);
00238   }
00239 
00240   err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
00241 
00242   inBuffer1 = inBuffer2 = outBuffer1 = outBuffer2 = NULL;
00243   err = OMX_AllocateBuffer(handle, &inBuffer1, 0, NULL, BUFFER_IN_SIZE);
00244   if (err != OMX_ErrorNone) {
00245     DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer in 1%i\n", err);
00246     exit(1);
00247   }
00248   err = OMX_AllocateBuffer(handle, &inBuffer2, 0, NULL, BUFFER_IN_SIZE);
00249   if (err != OMX_ErrorNone) {
00250     DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer in 2 %i\n", err);
00251     exit(1);
00252   }
00253   err = OMX_AllocateBuffer(handle, &outBuffer1, 1, NULL, BUFFER_IN_SIZE);
00254   if (err != OMX_ErrorNone) {
00255     DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer out 1 %i\n", err);
00256     exit(1);
00257   }
00258   err = OMX_AllocateBuffer(handle, &outBuffer2, 1, NULL, BUFFER_IN_SIZE);
00259   if (err != OMX_ErrorNone) {
00260     DEBUG(DEB_LEV_ERR, "Error on AllocateBuffer out 2 %i\n", err);
00261     exit(1);
00262   }
00263 
00264   tsem_down(appPriv->eventSem);
00265   /* in Idle the second thread has bee created, and the second thread ID
00266    * should be available
00267    */
00268   err = OMX_GetParameter(handle, custom_index, &threadsID);
00269   if(err != OMX_ErrorNone) {
00270     DEBUG(DEB_LEV_ERR, "OMX_GetParameter of extended index failed\n");
00271   } else {
00272       DEBUG(DEFAULT_MESSAGES, "threadsID messages %i buffers %i\n", (int)threadsID.nThreadMessageID, (int)threadsID.nThreadBufferMngtID);
00273   }
00274 
00275   err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateExecuting, NULL);
00276 
00277   /* Wait for commands to complete */
00278   tsem_down(appPriv->eventSem);
00279 
00280   DEBUG(DEB_LEV_PARAMS, "Had buffers at:\n0x%p\n0x%p\n0x%p\n0x%p\n",
00281                 inBuffer1->pBuffer, inBuffer2->pBuffer, outBuffer1->pBuffer, outBuffer2->pBuffer);
00282   DEBUG(DEB_LEV_PARAMS, "After switch to executing\n");
00283 
00284   data_read1 = read(fd, inBuffer1->pBuffer, BUFFER_IN_SIZE);
00285   inBuffer1->nFilledLen = data_read1;
00286   filesize -= data_read1;
00287 
00288   data_read2 = read(fd, inBuffer2->pBuffer, BUFFER_IN_SIZE);
00289   inBuffer2->nFilledLen = data_read2;
00290   filesize -= data_read2;
00291 
00292   DEBUG(DEB_LEV_PARAMS, "Empty first  buffer %p\n", inBuffer1);
00293   err = OMX_EmptyThisBuffer(handle, inBuffer1);
00294   DEBUG(DEB_LEV_PARAMS, "Empty second buffer %p\n", inBuffer2);
00295   err = OMX_EmptyThisBuffer(handle, inBuffer2);
00296 
00300   err = OMX_FillThisBuffer(handle, outBuffer1);
00301   err = OMX_FillThisBuffer(handle, outBuffer2);
00302 
00303   tsem_down(appPriv->eofSem);
00304 
00305   err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
00306   /* Wait for commands to complete */
00307   tsem_down(appPriv->eventSem);
00308 
00309   err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
00310   err = OMX_FreeBuffer(handle, 0, inBuffer1);
00311   err = OMX_FreeBuffer(handle, 0, inBuffer2);
00312   err = OMX_FreeBuffer(handle, 1, outBuffer1);
00313   err = OMX_FreeBuffer(handle, 1, outBuffer2);
00314 
00315   /* Wait for commands to complete */
00316   tsem_down(appPriv->eventSem);
00317 
00318   OMX_FreeHandle(handle);
00319 
00320   free(appPriv->eventSem);
00321   free(appPriv);
00322 
00323   if (flagOutputReceived) {
00324     if(fclose(outfile) != 0) {
00325       DEBUG(DEB_LEV_ERR,"Error in closing output file\n");
00326       exit(1);
00327     }
00328     free(output_file);
00329   }
00330 
00331   close(fd);
00332   free(input_file);
00333 
00334   return 0;
00335 }
00336 
00337 /* Callbacks implementation */
00338 OMX_ERRORTYPE volcEventHandler(
00339   OMX_HANDLETYPE hComponent,
00340   OMX_PTR pAppData,
00341   OMX_EVENTTYPE eEvent,
00342   OMX_U32 Data1,
00343   OMX_U32 Data2,
00344   OMX_PTR pEventData) {
00345 
00346   DEBUG(DEB_LEV_SIMPLE_SEQ, "Hi there, I am in the %s callback\n", __func__);
00347   if(eEvent == OMX_EventCmdComplete) {
00348     if (Data1 == OMX_CommandStateSet) {
00349       DEBUG(DEB_LEV_SIMPLE_SEQ, "Volume Component State changed in ");
00350       switch ((int)Data2) {
00351       case OMX_StateInvalid:
00352         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateInvalid\n");
00353         break;
00354       case OMX_StateLoaded:
00355         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateLoaded\n");
00356         break;
00357       case OMX_StateIdle:
00358         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateIdle\n");
00359         break;
00360       case OMX_StateExecuting:
00361         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateExecuting\n");
00362         break;
00363       case OMX_StatePause:
00364         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StatePause\n");
00365         break;
00366       case OMX_StateWaitForResources:
00367         DEBUG(DEB_LEV_SIMPLE_SEQ, "OMX_StateWaitForResources\n");
00368         break;
00369       }
00370       tsem_up(appPriv->eventSem);
00371     } else  if (Data1 == OMX_CommandPortEnable){
00372       tsem_up(appPriv->eventSem);
00373     } else if (Data1 == OMX_CommandPortDisable){
00374       tsem_up(appPriv->eventSem);
00375     }
00376   } else if(eEvent == OMX_EventBufferFlag) {
00377     if((int)Data2 == OMX_BUFFERFLAG_EOS) {
00378       tsem_up(appPriv->eofSem);
00379     }
00380   } else {
00381     DEBUG(DEB_LEV_SIMPLE_SEQ, "Param1 is %i\n", (int)Data1);
00382     DEBUG(DEB_LEV_SIMPLE_SEQ, "Param2 is %i\n", (int)Data2);
00383   }
00384 
00385   return OMX_ErrorNone;
00386 }
00387 
00388 OMX_ERRORTYPE volcEmptyBufferDone(
00389   OMX_HANDLETYPE hComponent,
00390   OMX_PTR pAppData,
00391   OMX_BUFFERHEADERTYPE* pBuffer) {
00392 
00393   int data_read;
00394   static int iBufferDropped=0;
00395 
00396   DEBUG(DEB_LEV_FULL_SEQ, "Hi there, I am in the %s callback.\n", __func__);
00397   data_read = read(fd, pBuffer->pBuffer, BUFFER_IN_SIZE);
00398   pBuffer->nFilledLen = data_read;
00399   pBuffer->nOffset = 0;
00400   filesize -= data_read;
00401   if (data_read <= 0) {
00402     DEBUG(DEB_LEV_SIMPLE_SEQ, "In the %s no more input data available\n", __func__);
00403     iBufferDropped++;
00404     if(iBufferDropped>=2) {
00405       tsem_up(appPriv->eofSem);
00406       return OMX_ErrorNone;
00407     }
00408     pBuffer->nFilledLen=0;
00409     pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
00410     bEOS=OMX_TRUE;
00411     err = OMX_EmptyThisBuffer(hComponent, pBuffer);
00412     return OMX_ErrorNone;
00413   }
00414   if(!bEOS) {
00415     DEBUG(DEB_LEV_FULL_SEQ, "Empty buffer %p\n", pBuffer);
00416     err = OMX_EmptyThisBuffer(hComponent, pBuffer);
00417   }else {
00418     DEBUG(DEB_LEV_FULL_SEQ, "In %s Dropping Empty This buffer to Audio Dec\n", __func__);
00419   }
00420 
00421   return OMX_ErrorNone;
00422 }
00423 
00424 OMX_ERRORTYPE volcFillBufferDone(
00425   OMX_HANDLETYPE hComponent,
00426   OMX_PTR pAppData,
00427   OMX_BUFFERHEADERTYPE* pBuffer) {
00428 
00429   OMX_ERRORTYPE err;
00430   int i;
00431 
00432   DEBUG(DEB_LEV_FULL_SEQ, "Hi there, I am in the %s callback. Got buflen %i for buffer at 0x%p\n",
00433                           __func__, (int)pBuffer->nFilledLen, pBuffer);
00434 
00435   /* Output data to standard output */
00436   if(pBuffer != NULL) {
00437     if (pBuffer->nFilledLen == 0) {
00438       DEBUG(DEB_LEV_ERR, "Ouch! In %s: no data in the output buffer!\n", __func__);
00439       return OMX_ErrorNone;
00440     }
00441     if (flagOutputReceived) {
00442       if(pBuffer->nFilledLen > 0) {
00443         fwrite(pBuffer->pBuffer, 1, pBuffer->nFilledLen, outfile);
00444       }
00445     } else {
00446       for(i=0;i<pBuffer->nFilledLen;i++) {
00447         putchar(*(char*)(pBuffer->pBuffer + i));
00448       }
00449     }
00450     pBuffer->nFilledLen = 0;
00451   } else {
00452     DEBUG(DEB_LEV_ERR, "Ouch! In %s: had NULL buffer to output...\n", __func__);
00453   }
00454   /* Reschedule the fill buffer request */
00455   if(!bEOS) {
00456     err = OMX_FillThisBuffer(hComponent, pBuffer);
00457   }
00458   return OMX_ErrorNone;
00459 }
00460 
00465 static int getFileSize(int fd) {
00466 
00467   struct stat input_file_stat;
00468   int err;
00469 
00470   /* Obtain input file length */
00471   err = fstat(fd, &input_file_stat);
00472   if(err){
00473     DEBUG(DEB_LEV_ERR, "fstat failed");
00474     exit(-1);
00475   }
00476   return input_file_stat.st_size;
00477 }