00001
00031 #include <assert.h>
00032 #include <omxcore.h>
00033 #include <omx_base_video_port.h>
00034 #include <omx_videosrc_component.h>
00035
00036 #define MAX_COMPONENT_VIDEOSRC 1
00037
00039 static OMX_U32 noViderSrcInstance=0;
00040
00041 #define DEFAULT_FILENAME_LENGTH 256
00042
00043 #define CLEAR(x) memset (&(x), 0, sizeof (x))
00044
00045 static unsigned int n_buffers = 0;
00046
00047 static int xioctl(int fd, int request, void *arg);
00048 static int init_device(omx_videosrc_component_PrivateType* omx_videosrc_component_Private);
00049 static int uninit_device(omx_videosrc_component_PrivateType* omx_videosrc_component_Private);
00050 static int start_capturing(omx_videosrc_component_PrivateType* omx_videosrc_component_Private);
00051 static int stop_capturing(omx_videosrc_component_PrivateType* omx_videosrc_component_Private);
00052 static int init_mmap(omx_videosrc_component_PrivateType* omx_videosrc_component_Private);
00053
00054 static int errno_return(const char *s)
00055 {
00056 DEBUG(DEB_LEV_ERR, "%s error %d, %s\n", s, errno, strerror(errno));
00057 return OMX_ErrorHardware;
00058 }
00059
00060
00063 OMX_ERRORTYPE omx_videosrc_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) {
00064
00065 OMX_ERRORTYPE err = OMX_ErrorNone;
00066 omx_base_video_PortType *pPort;
00067 omx_videosrc_component_PrivateType* omx_videosrc_component_Private;
00068 OMX_U32 i;
00069
00070 DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__);
00071
00072 if (!openmaxStandComp->pComponentPrivate) {
00073 openmaxStandComp->pComponentPrivate = calloc(1, sizeof(omx_videosrc_component_PrivateType));
00074 if(openmaxStandComp->pComponentPrivate == NULL) {
00075 return OMX_ErrorInsufficientResources;
00076 }
00077 }
00078
00079 omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00080 omx_videosrc_component_Private->ports = NULL;
00081 omx_videosrc_component_Private->deviceHandle = -1;
00082
00083 err = omx_base_source_Constructor(openmaxStandComp, cComponentName);
00084
00085 omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0;
00086 omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts = 1;
00087
00089 if (omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts && !omx_videosrc_component_Private->ports) {
00090 omx_videosrc_component_Private->ports = calloc(omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts, sizeof(omx_base_PortType *));
00091 if (!omx_videosrc_component_Private->ports) {
00092 return OMX_ErrorInsufficientResources;
00093 }
00094 for (i=0; i < omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts; i++) {
00095 omx_videosrc_component_Private->ports[i] = calloc(1, sizeof(omx_base_video_PortType));
00096 if (!omx_videosrc_component_Private->ports[i]) {
00097 return OMX_ErrorInsufficientResources;
00098 }
00099 }
00100 }
00101
00102 base_video_port_Constructor(openmaxStandComp, &omx_videosrc_component_Private->ports[0], 0, OMX_FALSE);
00103 omx_videosrc_component_Private->ports[0]->Port_AllocateBuffer = videosrc_port_AllocateBuffer;
00104 omx_videosrc_component_Private->ports[0]->Port_FreeBuffer = videosrc_port_FreeBuffer;
00105 omx_videosrc_component_Private->ports[0]->Port_AllocateTunnelBuffer = videosrc_port_AllocateTunnelBuffer;
00106 omx_videosrc_component_Private->ports[0]->Port_FreeTunnelBuffer = videosrc_port_FreeTunnelBuffer;
00107
00108 pPort = (omx_base_video_PortType *) omx_videosrc_component_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00109
00110 pPort->sPortParam.format.video.nFrameWidth = 320;
00111 pPort->sPortParam.format.video.nFrameHeight= 240;
00112 pPort->sPortParam.format.video.eColorFormat= OMX_COLOR_FormatYUV420Planar;
00113 pPort->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420Planar;
00114
00115 pPort->sPortParam.nBufferSize = pPort->sPortParam.format.video.nFrameWidth*
00116 pPort->sPortParam.format.video.nFrameHeight*3;
00117 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.nBufferSize;
00118
00119 omx_videosrc_component_Private->BufferMgmtCallback = omx_videosrc_component_BufferMgmtCallback;
00120 omx_videosrc_component_Private->destructor = omx_videosrc_component_Destructor;
00121 omx_videosrc_component_Private->messageHandler = omx_videosrc_component_MessageHandler;
00122
00123 noViderSrcInstance++;
00124 if(noViderSrcInstance > MAX_COMPONENT_VIDEOSRC) {
00125 return OMX_ErrorInsufficientResources;
00126 }
00127
00128 openmaxStandComp->SetParameter = omx_videosrc_component_SetParameter;
00129 openmaxStandComp->GetParameter = omx_videosrc_component_GetParameter;
00130
00131
00132 omx_videosrc_component_Private->videoReady = OMX_FALSE;
00133 if(!omx_videosrc_component_Private->videoSyncSem) {
00134 omx_videosrc_component_Private->videoSyncSem = calloc(1,sizeof(tsem_t));
00135 if(omx_videosrc_component_Private->videoSyncSem == NULL) return OMX_ErrorInsufficientResources;
00136 tsem_init(omx_videosrc_component_Private->videoSyncSem, 0);
00137 }
00138
00139 omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_FALSE;
00140
00141
00142 omx_videosrc_component_Private->deviceHandle = open(VIDEO_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
00143 if (omx_videosrc_component_Private->deviceHandle < 0) {
00144 DEBUG(DEB_LEV_ERR, "In %s Unable to open video capture device %s! errno=%d ENODEV : %d \n",
00145 __func__,VIDEO_DEV_NAME,errno,ENODEV);
00146 return OMX_ErrorHardware;
00147 }
00148
00149 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV420;
00150
00151 err = init_device(omx_videosrc_component_Private);
00152
00153 err = init_mmap(omx_videosrc_component_Private);
00154
00155 return err;
00156 }
00157
00160 OMX_ERRORTYPE omx_videosrc_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
00161 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00162 OMX_ERRORTYPE err = OMX_ErrorNone;
00163 OMX_U32 i;
00164
00165 if(omx_videosrc_component_Private->videoSyncSem) {
00166 tsem_deinit(omx_videosrc_component_Private->videoSyncSem);
00167 free(omx_videosrc_component_Private->videoSyncSem);
00168 omx_videosrc_component_Private->videoSyncSem=NULL;
00169 }
00170
00171 err = uninit_device(omx_videosrc_component_Private);
00172
00173 if(omx_videosrc_component_Private->deviceHandle != -1) {
00174 if(-1 == close(omx_videosrc_component_Private->deviceHandle)) {
00175 DEBUG(DEB_LEV_ERR, "In %s Closing video capture device failed \n",__func__);
00176 }
00177 omx_videosrc_component_Private->deviceHandle = -1;
00178 }
00179
00180
00181 if (omx_videosrc_component_Private->ports) {
00182 for (i=0; i < omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts; i++) {
00183 if(omx_videosrc_component_Private->ports[i])
00184 omx_videosrc_component_Private->ports[i]->PortDestructor(omx_videosrc_component_Private->ports[i]);
00185 }
00186 free(omx_videosrc_component_Private->ports);
00187 omx_videosrc_component_Private->ports=NULL;
00188 }
00189
00190 noViderSrcInstance--;
00191 DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__);
00192
00193 return omx_base_source_Destructor(openmaxStandComp);
00194 }
00195
00198 OMX_ERRORTYPE omx_videosrc_component_Init(OMX_COMPONENTTYPE *openmaxStandComp) {
00199
00200 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00201 omx_base_video_PortType *pPort = (omx_base_video_PortType *)omx_videosrc_component_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00202 OMX_ERRORTYPE err = OMX_ErrorNone;
00203
00204 DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__);
00205
00206
00207 switch(pPort->sPortParam.format.video.eColorFormat) {
00208 case OMX_COLOR_FormatYUV420Planar:
00209 case OMX_COLOR_FormatYUV420PackedPlanar:
00210 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV420;
00211 break;
00212 case OMX_COLOR_Format16bitRGB565:
00213 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB565 ;
00214 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00215 pPort->sPortParam.format.video.nFrameHeight*2;
00216 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00217 pPort->sPortParam.format.video.nFrameHeight*2;
00218 break;
00219 case OMX_COLOR_Format24bitRGB888:
00220 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB24 ;
00221 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00222 pPort->sPortParam.format.video.nFrameHeight*3;
00223 break;
00224 case OMX_COLOR_Format32bitARGB8888:
00225 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_RGB32 ;
00226 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00227 pPort->sPortParam.format.video.nFrameHeight*4;
00228 break;
00229 case OMX_COLOR_FormatYUV422Planar:
00230 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV422P ;
00231 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00232 pPort->sPortParam.format.video.nFrameHeight*2;
00233 break;
00234 case OMX_COLOR_FormatYUV411Planar:
00235 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV411P ;
00236 break;
00237 default:
00238 omx_videosrc_component_Private->pixel_format = V4L2_PIX_FMT_YUV420;
00239 break;
00240 }
00241
00243 omx_videosrc_component_Private->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00244 omx_videosrc_component_Private->fmt.fmt.pix.width = pPort->sPortParam.format.video.nFrameWidth;
00245 omx_videosrc_component_Private->fmt.fmt.pix.height = pPort->sPortParam.format.video.nFrameHeight;
00246 omx_videosrc_component_Private->fmt.fmt.pix.pixelformat = omx_videosrc_component_Private->pixel_format;
00247 omx_videosrc_component_Private->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
00248
00249 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_S_FMT, &omx_videosrc_component_Private->fmt))
00250 return errno_return("VIDIOC_S_FMT");
00251
00252
00253 pPort->sPortParam.format.video.nFrameWidth = omx_videosrc_component_Private->fmt.fmt.pix.width;
00254 pPort->sPortParam.format.video.nFrameHeight = omx_videosrc_component_Private->fmt.fmt.pix.height;
00255
00256
00257 omx_videosrc_component_Private->iFrameSize = pPort->sPortParam.format.video.nFrameWidth*
00258 pPort->sPortParam.format.video.nFrameHeight*3/2;
00259
00260 DEBUG(DEB_ALL_MESS,"Frame Width=%d, Height=%d, Frame Size=%d n_buffers=%d\n",
00261 (int)pPort->sPortParam.format.video.nFrameWidth,
00262 (int)pPort->sPortParam.format.video.nFrameHeight,
00263 (int)omx_videosrc_component_Private->iFrameSize,n_buffers);
00264
00266 omx_videosrc_component_Private->bIsEOSSent = OMX_FALSE;
00267
00268 err = start_capturing(omx_videosrc_component_Private);
00269
00270 omx_videosrc_component_Private->videoReady = OMX_TRUE;
00271
00272
00273 tsem_up(omx_videosrc_component_Private->videoSyncSem);
00274
00275
00276
00277 return err;
00278 }
00279
00282 OMX_ERRORTYPE omx_videosrc_component_Deinit(OMX_COMPONENTTYPE *openmaxStandComp) {
00283
00284 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00285
00286 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n",__func__);
00287
00288 stop_capturing(omx_videosrc_component_Private);
00289
00291 omx_videosrc_component_Private->videoReady = OMX_FALSE;
00292 tsem_reset(omx_videosrc_component_Private->videoSyncSem);
00293
00294 return OMX_ErrorNone;
00295 }
00296
00301 void omx_videosrc_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* pOutputBuffer) {
00302
00303 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00304 struct v4l2_buffer buf;
00305
00306 CLEAR(buf);
00307
00308 DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__);
00309
00310 if (omx_videosrc_component_Private->videoReady == OMX_FALSE) {
00311 if(omx_videosrc_component_Private->state == OMX_StateExecuting) {
00312
00313 tsem_down(omx_videosrc_component_Private->videoSyncSem);
00314 } else {
00315 return;
00316 }
00317 }
00318
00319 pOutputBuffer->nOffset = 0;
00320 pOutputBuffer->nFilledLen = 0;
00321
00322 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00323 buf.memory = V4L2_MEMORY_MMAP;
00324
00325 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_DQBUF, &buf)) {
00326 switch (errno) {
00327 case EAGAIN:
00328 return;
00329 case EIO:
00330
00331
00332
00333 default:
00334 DEBUG(DEB_LEV_ERR,"In %s error VIDIOC_DQBUF\n",__func__);
00335 return;
00336 }
00337 }
00338
00339 assert(buf.index < n_buffers);
00340
00341 if(omx_videosrc_component_Private->bOutBufferMemoryMapped == OMX_FALSE) {
00342 memcpy(pOutputBuffer->pBuffer,omx_videosrc_component_Private->buffers[buf.index].start,omx_videosrc_component_Private->iFrameSize);
00343 }
00344
00345 pOutputBuffer->nFilledLen = omx_videosrc_component_Private->iFrameSize;
00346
00347 DEBUG(DEB_LEV_FULL_SEQ,"Camera output buffer nFilledLen=%d buf.length=%d\n",(int)pOutputBuffer->nFilledLen,buf.length);
00348
00349 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_QBUF, &buf)) {
00350 DEBUG(DEB_LEV_ERR,"In %s error VIDIOC_DQBUF\n",__func__);
00351 }
00352
00354 return;
00355 }
00356
00357 OMX_ERRORTYPE omx_videosrc_component_SetParameter(
00358 OMX_IN OMX_HANDLETYPE hComponent,
00359 OMX_IN OMX_INDEXTYPE nParamIndex,
00360 OMX_IN OMX_PTR ComponentParameterStructure) {
00361
00362 OMX_ERRORTYPE err = OMX_ErrorNone;
00363 OMX_VIDEO_PARAM_PORTFORMATTYPE *pVideoPortFormat;
00364 OMX_U32 portIndex;
00365
00366
00367 OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
00368 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00369 omx_base_video_PortType* pPort = (omx_base_video_PortType *) omx_videosrc_component_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00370
00371 if(ComponentParameterStructure == NULL) {
00372 return OMX_ErrorBadParameter;
00373 }
00374
00375 DEBUG(DEB_LEV_SIMPLE_SEQ, " Setting parameter %i\n", nParamIndex);
00376
00377 switch(nParamIndex) {
00378 case OMX_IndexParamVideoPortFormat:
00379 pVideoPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00380 portIndex = pVideoPortFormat->nPortIndex;
00381
00382 err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pVideoPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
00383 if(err!=OMX_ErrorNone) {
00384 DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err);
00385 break;
00386 }
00387 if (portIndex < 1) {
00388 memcpy(&pPort->sVideoParam,pVideoPortFormat,sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
00389 } else {
00390 return OMX_ErrorBadPortIndex;
00391 }
00392 break;
00393 case OMX_IndexParamPortDefinition:
00394 err = omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00395 if(err == OMX_ErrorNone) {
00396 if(pPort->sPortParam.format.video.nFrameWidth > 640 || pPort->sPortParam.format.video.nFrameWidth <160 ||
00397 pPort->sPortParam.format.video.nFrameHeight > 480 || pPort->sPortParam.format.video.nFrameHeight < 120) {
00398 pPort->sPortParam.format.video.nFrameWidth = 160;
00399 pPort->sPortParam.format.video.nFrameHeight = 120;
00400 DEBUG(DEB_LEV_ERR, "In %s Frame Width Range[160..640] Frame Height Range[120..480]\n",__func__);
00401 return OMX_ErrorBadParameter;
00402 } else {
00403 pPort->sPortParam.nBufferSize = pPort->sPortParam.format.video.nFrameWidth*
00404 pPort->sPortParam.format.video.nFrameHeight*3/2;
00405 }
00406 }
00407 default:
00408 return omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00409 }
00410 return err;
00411 }
00412
00413 OMX_ERRORTYPE omx_videosrc_component_GetParameter(
00414 OMX_IN OMX_HANDLETYPE hComponent,
00415 OMX_IN OMX_INDEXTYPE nParamIndex,
00416 OMX_INOUT OMX_PTR ComponentParameterStructure) {
00417
00418 OMX_ERRORTYPE err = OMX_ErrorNone;
00419 OMX_VIDEO_PARAM_PORTFORMATTYPE *pVideoPortFormat;
00420 OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
00421 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = openmaxStandComp->pComponentPrivate;
00422 omx_base_video_PortType *pPort = (omx_base_video_PortType *) omx_videosrc_component_Private->ports[OMX_BASE_SOURCE_OUTPUTPORT_INDEX];
00423 if (ComponentParameterStructure == NULL) {
00424 return OMX_ErrorBadParameter;
00425 }
00426
00427 DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Getting parameter %08x\n",__func__, nParamIndex);
00428
00429
00430 switch(nParamIndex) {
00431 case OMX_IndexParamVideoInit:
00432 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) {
00433 break;
00434 }
00435 memcpy(ComponentParameterStructure, &omx_videosrc_component_Private->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE));
00436 break;
00437 case OMX_IndexParamVideoPortFormat:
00438 pVideoPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
00439 if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) {
00440 break;
00441 }
00442 if (pVideoPortFormat->nPortIndex < 1) {
00443 memcpy(pVideoPortFormat, &pPort->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
00444 } else {
00445 return OMX_ErrorBadPortIndex;
00446 }
00447 break;
00448 case OMX_IndexVendorFileReadInputFilename :
00449 strcpy((char *)ComponentParameterStructure, "still no filename");
00450 break;
00451 default:
00452 return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
00453 }
00454 return err;
00455 }
00456
00460 OMX_ERRORTYPE omx_videosrc_component_MessageHandler(OMX_COMPONENTTYPE* openmaxStandComp,internalRequestMessageType *message) {
00461 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)openmaxStandComp->pComponentPrivate;
00462 OMX_ERRORTYPE err = OMX_ErrorNone;
00463 OMX_STATETYPE oldState = omx_videosrc_component_Private->state;
00464
00465 DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s\n", __func__);
00466
00467
00468 err = omx_base_component_MessageHandler(openmaxStandComp,message);
00469
00470 if (message->messageType == OMX_CommandStateSet && err == OMX_ErrorNone){
00471 if ((message->messageParam == OMX_StateExecuting) && (oldState == OMX_StateIdle)) {
00472 err = omx_videosrc_component_Init(openmaxStandComp);
00473 if(err!=OMX_ErrorNone) {
00474 DEBUG(DEB_LEV_ERR, "In %s Video Source Init Failed Error=%x\n",__func__,err);
00475 }
00476 } else if ((message->messageParam == OMX_StateIdle) && (oldState == OMX_StateExecuting)) {
00477 err = omx_videosrc_component_Deinit(openmaxStandComp);
00478 if(err!=OMX_ErrorNone) {
00479 DEBUG(DEB_LEV_ERR, "In %s Video Source Deinit Failed Error=%x\n",__func__,err);
00480 }
00481 }
00482 }
00483 return err;
00484 }
00485
00486 OMX_ERRORTYPE videosrc_port_AllocateBuffer(
00487 omx_base_PortType *openmaxStandPort,
00488 OMX_BUFFERHEADERTYPE** pBuffer,
00489 OMX_U32 nPortIndex,
00490 OMX_PTR pAppPrivate,
00491 OMX_U32 nSizeBytes) {
00492
00493 int i;
00494 OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
00495 omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00496 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private;
00497 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00498
00499 if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) {
00500 return OMX_ErrorBadPortIndex;
00501 }
00502 if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00503 return OMX_ErrorBadPortIndex;
00504 }
00505
00506 if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) {
00507 if (!openmaxStandPort->bIsTransientToEnabled) {
00508 DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__);
00509 return OMX_ErrorIncorrectStateTransition;
00510 }
00511 }
00512
00513 if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) {
00514 DEBUG(DEB_LEV_ERR, "In %s: Requested Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, nSizeBytes, openmaxStandPort->sPortParam.nBufferSize);
00515 return OMX_ErrorIncorrectStateTransition;
00516 }
00517
00518 for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00519 if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) {
00520 openmaxStandPort->pInternalBufferStorage[i] = calloc(1,sizeof(OMX_BUFFERHEADERTYPE));
00521 if (!openmaxStandPort->pInternalBufferStorage[i]) {
00522 return OMX_ErrorInsufficientResources;
00523 }
00524 setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE));
00525
00526 if(i > n_buffers) {
00527 DEBUG(DEB_LEV_ERR, "In %s returning error i=%d, nframe=%d\n", __func__,i,n_buffers);
00528 return OMX_ErrorInsufficientResources;
00529 }
00530
00531 omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_TRUE;
00532 openmaxStandPort->pInternalBufferStorage[i]->pBuffer = omx_videosrc_component_Private->buffers[i].start;
00533 openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = (int)nSizeBytes;
00534 openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort;
00535 openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate;
00536 *pBuffer = openmaxStandPort->pInternalBufferStorage[i];
00537 openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED;
00538 openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED;
00539 if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) {
00540 openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex;
00541 } else {
00542 openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex;
00543 }
00544 openmaxStandPort->nNumAssignedBuffers++;
00545 DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers);
00546
00547 if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) {
00548 openmaxStandPort->sPortParam.bPopulated = OMX_TRUE;
00549 openmaxStandPort->bIsFullOfBuffers = OMX_TRUE;
00550 DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__,(int)nPortIndex);
00551 tsem_up(openmaxStandPort->pAllocSem);
00552 }
00553 return OMX_ErrorNone;
00554 }
00555 }
00556 DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers\n",__func__);
00557 return OMX_ErrorInsufficientResources;
00558 }
00559 OMX_ERRORTYPE videosrc_port_FreeBuffer(
00560 omx_base_PortType *openmaxStandPort,
00561 OMX_U32 nPortIndex,
00562 OMX_BUFFERHEADERTYPE* pBuffer) {
00563
00564 int i;
00565 OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
00566 omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00567 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private;
00568 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00569
00570 if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) {
00571 return OMX_ErrorBadPortIndex;
00572 }
00573 if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00574 return OMX_ErrorBadPortIndex;
00575 }
00576
00577 if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) {
00578 if (!openmaxStandPort->bIsTransientToDisabled) {
00579 DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__);
00580 (*(omx_base_component_Private->callbacks->EventHandler))
00581 (omxComponent,
00582 omx_base_component_Private->callbackData,
00583 OMX_EventError,
00584 OMX_ErrorPortUnpopulated,
00585 nPortIndex,
00586 NULL);
00587 }
00588 }
00589
00590 for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00591 if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) {
00592
00593 openmaxStandPort->bIsFullOfBuffers = OMX_FALSE;
00594 if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) {
00595 if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer){
00596 DEBUG(DEB_LEV_PARAMS, "In %s freeing %i pBuffer=%x\n",__func__, (int)i, (int)openmaxStandPort->pInternalBufferStorage[i]->pBuffer);
00597 openmaxStandPort->pInternalBufferStorage[i]->pBuffer=NULL;
00598 omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_FALSE;
00599 }
00600 } else if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ASSIGNED) {
00601 free(pBuffer);
00602 pBuffer=NULL;
00603 }
00604 if(openmaxStandPort->bBufferStateAllocated[i] & HEADER_ALLOCATED) {
00605 free(openmaxStandPort->pInternalBufferStorage[i]);
00606 openmaxStandPort->pInternalBufferStorage[i]=NULL;
00607 }
00608
00609 openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE;
00610
00611 openmaxStandPort->nNumAssignedBuffers--;
00612 DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers);
00613
00614 if (openmaxStandPort->nNumAssignedBuffers == 0) {
00615 openmaxStandPort->sPortParam.bPopulated = OMX_FALSE;
00616 openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE;
00617 tsem_up(openmaxStandPort->pAllocSem);
00618 }
00619 return OMX_ErrorNone;
00620 }
00621 }
00622 return OMX_ErrorInsufficientResources;
00623 }
00624
00625 OMX_ERRORTYPE videosrc_port_AllocateTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_U32 nSizeBytes)
00626 {
00627 int i;
00628 OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
00629 omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00630 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private;
00631 OMX_U8* pBuffer=NULL;
00632 OMX_ERRORTYPE eError=OMX_ErrorNone;
00633 OMX_U32 numRetry=0;
00634 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00635
00636 if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) {
00637 DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__);
00638 return OMX_ErrorBadPortIndex;
00639 }
00640 if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00641 DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled Flag=%x\n", __func__, (int)openmaxStandPort->nTunnelFlags);
00642 return OMX_ErrorBadPortIndex;
00643 }
00644
00645 if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) {
00646 if (!openmaxStandPort->bIsTransientToEnabled) {
00647 DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__);
00648 return OMX_ErrorIncorrectStateTransition;
00649 }
00650 }
00651
00652 for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00653 if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) {
00654
00655 if(i > n_buffers) {
00656 DEBUG(DEB_LEV_ERR, "In %s returning error i=%d, nframe=%d\n", __func__,i,n_buffers);
00657 return OMX_ErrorInsufficientResources;
00658 }
00659 omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_TRUE;
00660 pBuffer = omx_videosrc_component_Private->buffers[i].start;
00661
00662
00663 while(numRetry <TUNNEL_USE_BUFFER_RETRY) {
00664 eError=OMX_UseBuffer(openmaxStandPort->hTunneledComponent,&openmaxStandPort->pInternalBufferStorage[i],
00665 openmaxStandPort->nTunneledPort,NULL,nSizeBytes,pBuffer);
00666 if(eError!=OMX_ErrorNone) {
00667 DEBUG(DEB_LEV_FULL_SEQ,"Tunneled Component Couldn't Use buffer %i From Comp=%s Retry=%d\n",
00668 i,omx_base_component_Private->name,(int)numRetry);
00669
00670 if((eError == OMX_ErrorIncorrectStateTransition) && numRetry<TUNNEL_USE_BUFFER_RETRY) {
00671 DEBUG(DEB_LEV_FULL_SEQ,"Waiting for next try %i \n",(int)numRetry);
00672 usleep(TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME);
00673 numRetry++;
00674 continue;
00675 }
00676 return eError;
00677 }
00678 else {
00679 break;
00680 }
00681 }
00682 openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED;
00683 openmaxStandPort->nNumAssignedBuffers++;
00684 DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers);
00685
00686 if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) {
00687 openmaxStandPort->sPortParam.bPopulated = OMX_TRUE;
00688 openmaxStandPort->bIsFullOfBuffers = OMX_TRUE;
00689 DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__, (int)nPortIndex);
00690 }
00691 queue(openmaxStandPort->pBufferQueue, openmaxStandPort->pInternalBufferStorage[i]);
00692 }
00693 }
00694 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Allocated all buffers\n",__func__);
00695 return OMX_ErrorNone;
00696 }
00697
00698 OMX_ERRORTYPE videosrc_port_FreeTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex)
00699 {
00700 int i;
00701 OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
00702 omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
00703 omx_videosrc_component_PrivateType* omx_videosrc_component_Private = (omx_videosrc_component_PrivateType*)omx_base_component_Private;
00704 OMX_ERRORTYPE eError=OMX_ErrorNone;
00705 OMX_U32 numRetry=0;
00706 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__);
00707
00708 if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) {
00709 DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__);
00710 return OMX_ErrorBadPortIndex;
00711 }
00712 if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) {
00713 DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled\n", __func__);
00714 return OMX_ErrorBadPortIndex;
00715 }
00716
00717 if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) {
00718 if (!openmaxStandPort->bIsTransientToDisabled) {
00719 DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__);
00720 (*(omx_base_component_Private->callbacks->EventHandler))
00721 (omxComponent,
00722 omx_base_component_Private->callbackData,
00723 OMX_EventError,
00724 OMX_ErrorPortUnpopulated,
00725 nPortIndex,
00726 NULL);
00727 }
00728 }
00729
00730 for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
00731 if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) {
00732
00733 openmaxStandPort->bIsFullOfBuffers = OMX_FALSE;
00734 if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) {
00735 openmaxStandPort->pInternalBufferStorage[i]->pBuffer = NULL;
00736 omx_videosrc_component_Private->bOutBufferMemoryMapped = OMX_FALSE;
00737 }
00738
00739 while(numRetry <TUNNEL_USE_BUFFER_RETRY) {
00740 eError=OMX_FreeBuffer(openmaxStandPort->hTunneledComponent,openmaxStandPort->nTunneledPort,openmaxStandPort->pInternalBufferStorage[i]);
00741 if(eError!=OMX_ErrorNone) {
00742 DEBUG(DEB_LEV_ERR,"Tunneled Component Couldn't free buffer %i \n",i);
00743 if((eError == OMX_ErrorIncorrectStateTransition) && numRetry<TUNNEL_USE_BUFFER_RETRY) {
00744 DEBUG(DEB_LEV_ERR,"Waiting for next try %i \n",(int)numRetry);
00745 usleep(TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME);
00746 numRetry++;
00747 continue;
00748 }
00749 return eError;
00750 } else {
00751 break;
00752 }
00753 }
00754 openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE;
00755
00756 openmaxStandPort->nNumAssignedBuffers--;
00757 DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers);
00758
00759 if (openmaxStandPort->nNumAssignedBuffers == 0) {
00760 openmaxStandPort->sPortParam.bPopulated = OMX_FALSE;
00761 openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE;
00762
00763 }
00764 }
00765 }
00766 DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Qelem=%d BSem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem,openmaxStandPort->pBufferSem->semval);
00767 return OMX_ErrorNone;
00768 }
00769
00770 static int xioctl(int fd, int request, void *arg)
00771 {
00772 int r;
00773
00774 do
00775 r = ioctl(fd, request, arg);
00776 while (-1 == r && EINTR == errno);
00777
00778 return r;
00779 }
00780
00781 static int init_device(omx_videosrc_component_PrivateType* omx_videosrc_component_Private)
00782 {
00783
00784 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_QUERYCAP, &omx_videosrc_component_Private->cap)) {
00785 if (EINVAL == errno) {
00786 DEBUG(DEB_LEV_ERR, "%s is no V4L2 device\n", VIDEO_DEV_NAME);
00787 return OMX_ErrorHardware;
00788 } else {
00789 return errno_return("VIDIOC_QUERYCAP");
00790 }
00791 }
00792
00793 if (!(omx_videosrc_component_Private->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
00794 DEBUG(DEB_LEV_ERR, "%s is no video capture device\n", VIDEO_DEV_NAME);
00795 return OMX_ErrorHardware;
00796 }
00797
00798 if (!(omx_videosrc_component_Private->cap.capabilities & V4L2_CAP_STREAMING)) {
00799 DEBUG(DEB_LEV_ERR, "%s does not support streaming i/o\n", VIDEO_DEV_NAME);
00800 return OMX_ErrorHardware;
00801 }
00802
00803
00804 omx_videosrc_component_Private->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00805
00806 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_CROPCAP, &omx_videosrc_component_Private->cropcap)) {
00807
00808 }
00809
00810 omx_videosrc_component_Private->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00811 omx_videosrc_component_Private->crop.c = omx_videosrc_component_Private->cropcap.defrect;
00812
00813 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_S_CROP, &omx_videosrc_component_Private->crop)) {
00814 switch (errno) {
00815 case EINVAL:
00816
00817 break;
00818 default:
00819
00820 break;
00821 }
00822 }
00823
00824 CLEAR(omx_videosrc_component_Private->fmt);
00825
00826 return OMX_ErrorNone;
00827 }
00828
00829 static int start_capturing(omx_videosrc_component_PrivateType* omx_videosrc_component_Private)
00830 {
00831 unsigned int i;
00832 enum v4l2_buf_type type;
00833
00834 for (i = 0; i < n_buffers; ++i)
00835 {
00836 struct v4l2_buffer buf;
00837
00838 CLEAR(buf);
00839
00840 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00841 buf.memory = V4L2_MEMORY_MMAP;
00842 buf.index = i;
00843
00844 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_QBUF, &buf))
00845 return errno_return("VIDIOC_QBUF");
00846 }
00847
00848 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00849
00850 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_STREAMON, &type))
00851 return errno_return("VIDIOC_STREAMON");
00852
00853 return OMX_ErrorNone;
00854 }
00855
00856 static int stop_capturing(omx_videosrc_component_PrivateType* omx_videosrc_component_Private)
00857 {
00858 enum v4l2_buf_type type;
00859
00860 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00861
00862 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_STREAMOFF, &type))
00863 return errno_return("VIDIOC_STREAMOFF");
00864
00865 return OMX_ErrorNone;
00866 }
00867
00868 static int uninit_device(omx_videosrc_component_PrivateType* omx_videosrc_component_Private)
00869 {
00870 unsigned int i;
00871
00872 for (i = 0; i < n_buffers; ++i) {
00873 if (-1 == munmap(omx_videosrc_component_Private->buffers[i].start, omx_videosrc_component_Private->buffers[i].length))
00874 return errno_return("munmap");
00875 }
00876
00877 free(omx_videosrc_component_Private->buffers);
00878
00879 return OMX_ErrorNone;
00880 }
00881
00882 static int init_mmap(omx_videosrc_component_PrivateType* omx_videosrc_component_Private)
00883 {
00884 struct v4l2_requestbuffers req;
00885
00886 CLEAR(req);
00887
00888 req.count = 4;
00889 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00890 req.memory = V4L2_MEMORY_MMAP;
00891
00892 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_REQBUFS, &req)) {
00893 if (EINVAL == errno) {
00894 DEBUG(DEB_LEV_ERR, "%s does not support "
00895 "memory mapping\n", VIDEO_DEV_NAME);
00896 return OMX_ErrorHardware;
00897 } else {
00898 return errno_return("VIDIOC_REQBUFS");
00899 }
00900 }
00901
00902 if (req.count < 2) {
00903 DEBUG(DEB_LEV_ERR, "Insufficient buffer memory on %s\n", VIDEO_DEV_NAME);
00904 return OMX_ErrorHardware;
00905 }
00906
00907 omx_videosrc_component_Private->buffers = calloc(req.count, sizeof(*omx_videosrc_component_Private->buffers));
00908
00909 if (!omx_videosrc_component_Private->buffers) {
00910 DEBUG(DEB_LEV_ERR,"Out of memory\n");
00911 return OMX_ErrorHardware;
00912 }
00913
00914 for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
00915 struct v4l2_buffer buf;
00916
00917 CLEAR(buf);
00918
00919 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00920 buf.memory = V4L2_MEMORY_MMAP;
00921 buf.index = n_buffers;
00922
00923 if (-1 == xioctl(omx_videosrc_component_Private->deviceHandle, VIDIOC_QUERYBUF, &buf))
00924 return errno_return("VIDIOC_QUERYBUF");
00925
00926 omx_videosrc_component_Private->buffers[n_buffers].length = buf.length;
00927 omx_videosrc_component_Private->buffers[n_buffers].start = mmap(NULL ,
00928 buf.length,
00929 PROT_READ | PROT_WRITE ,
00930 MAP_SHARED ,
00931 omx_videosrc_component_Private->deviceHandle, buf.m.offset);
00932
00933 if (MAP_FAILED == omx_videosrc_component_Private->buffers[n_buffers].start)
00934 return errno_return("mmap");
00935 }
00936
00937 return OMX_ErrorNone;
00938 }