/*========================================================*/
OMX_ERRORTYPE SampleTest_TransitionWait(OMX_STATETYPE eToState,
    SampleCompTestCtxt * pContext)
{
	OMX_ERRORTYPE eError = OMX_ErrorNone;
	OMX_PARAM_PORTDEFINITIONTYPE tPortDef;
	OMX_U32 i, j;

	eError = OMX_SendCommand(pContext->hComp, OMX_CommandStateSet,
	    eToState, NULL);
	OMX_TEST_BAIL_IF_ERROR(eError);

	if ((eToState == OMX_StateIdle) &&
	    (pContext->eState == OMX_StateLoaded))
	{
		for (i = 0; i < NUM_DOMAINS; i++)
		{
			for (j = pContext->sPortParam[i].nStartPortNumber;
			    j < pContext->sPortParam[i].nStartPortNumber
			    + pContext->sPortParam[i].nPorts; j++)
			{

				OMX_TEST_INIT_STRUCT(tPortDef,
				    OMX_PARAM_PORTDEFINITIONTYPE);
				tPortDef.nPortIndex = j;
//printf("\nCalling GetParam before UseBuf on port %d\n",j);
				eError = OMX_GetParameter(pContext->hComp,
				    OMX_IndexParamPortDefinition,
				    (OMX_PTR) & tPortDef);
				OMX_TEST_BAIL_IF_ERROR(eError);

//                    if(tPortDef.bEnabled)//AD
				eError =
				    SampleTest_AllocateBuffers(pContext,
				    &tPortDef);

				OMX_TEST_BAIL_IF_ERROR(eError);
			}
		}
	} else if ((eToState == OMX_StateLoaded) &&
	    (pContext->eState == OMX_StateIdle))
	{

		eError = SampleTest_DeInitBuffers(pContext);
		OMX_TEST_BAIL_IF_ERROR(eError);

	}
	printf("\nWaiting for state set event\n");
	TIMM_OSAL_SemaphoreObtain(pContext->hStateSetEvent,
	    TIMM_OSAL_SUSPEND);
	printf("\nState set event recd.\n");

	if (pContext->eState != eToState)
		OMX_TEST_SET_ERROR_BAIL(OMX_ErrorUndefined,
		    " InComplete Transition \n");

      OMX_TEST_BAIL:
	return eError;
}
OMX_ERRORTYPE SampleTest_ReadOutBuffers(SampleCompTestCtxt * pContext)
{

	OMX_ERRORTYPE eError = OMX_ErrorNone;
	BufferList *pList;
	OMX_BUFFERHEADERTYPE *pBufHeader;

	pList = pContext->pOutBufferList;
	while (pList && pList->pBufHdr)
	{
		printf("\nAbout to do FTB\n");

		BUFFERLIST_CLEAR_ENTRY(pList, pBufHeader);

		eError = OMX_FillThisBuffer(pContext->hComp, pBufHeader);

		OMX_TEST_BAIL_IF_ERROR(eError);
		if (pBufHeader->nFlags == OMX_BUFFERFLAG_EOS)
		{
			pContext->nBufDoneCalls = OMX_TEST_BUFFERS_OF_TRAFFIC;
		}
	}

      OMX_TEST_BAIL:
	return eError;

}
/*========================================================*/
OMX_ERRORTYPE SampleTest_WriteInBuffers(SampleCompTestCtxt * pContext)
{

	OMX_ERRORTYPE eError = OMX_ErrorNone;
	BufferList *pList;
	OMX_BUFFERHEADERTYPE *pBufHeader;
#ifdef OMX_SAMPLE_TILER_TEST
	OMX_U8 *pTmpBuffer = NULL, *pOrigTmpBuffer = NULL;
#endif
	pList = pContext->pInBufferList;
	while (pList && pList->pBufHdr)
	{
		BUFFERLIST_CLEAR_ENTRY(pList, pBufHeader);
		printf("\nAbout to read from input file\n");
#if defined(OMX_SAMPLE_TILER_TEST)

		//OMX_SAMPLE_BUFFER_SIZE is the total amt of data to be sent in the buffer
		pTmpBuffer =
		    TIMM_OSAL_Malloc(OMX_SAMPLE_BUFFER_SIZE, 0, 0, 0);
		if (pTmpBuffer == NULL)
			OMX_TEST_SET_ERROR_BAIL
			    (OMX_ErrorInsufficientResources,
			    "malloc failed \n");
		pOrigTmpBuffer = pTmpBuffer;

		SampleTest_ReadInputFile(pContext, pTmpBuffer,
		    OMX_SAMPLE_BUFFER_SIZE, pContext->pInputfile);

		Test_Util_Memcpy_1Dto2D(pBufHeader->pBuffer, pTmpBuffer,
		    OMX_SAMPLE_BUFFER_SIZE, OMX_SAMPLE_IN_HEIGHT,
		    OMX_SAMPLE_IN_WIDTH, STRIDE_LINUX);
		pBufHeader->nFilledLen = OMX_SAMPLE_BUFFER_SIZE;

		printf("\nBefore ETB pBufHeader->nInputPortIndex = %d\n",
		    pBufHeader->nInputPortIndex);

		TIMM_OSAL_Free(pOrigTmpBuffer);

#else
		SampleTest_ReadInputFile(pContext, pBufHeader->pBuffer,
		    pBufHeader->nAllocLen, pContext->pInputfile);
		pBufHeader->nFilledLen = pBufHeader->nAllocLen;

#endif
		if (pContext->bEOS == OMX_TRUE)
		{
			pBufHeader->nFlags |= OMX_BUFFERFLAG_EOS;
		}

		eError = OMX_EmptyThisBuffer(pContext->hComp, pBufHeader);

		OMX_TEST_BAIL_IF_ERROR(eError);
	}

      OMX_TEST_BAIL:
	return eError;

}
/*========================================================*/
static int omx_fillthisbuffer(int index, int PortNum)
{
	struct port_param *sPortParam;
	sPortParam = &(pContext->sPortParam[PortNum]);
	eError = OMX_FillThisBuffer(pContext->hComp,
	    sPortParam->bufferheader[index]);

	OMX_TEST_BAIL_IF_ERROR(eError);
	return eError;

      OMX_TEST_BAIL:
	if (eError != OMX_ErrorNone)
		dprintf(0, "ERROR OMX_FillThisBuffer()\n");
	return eError;
}
/*========================================================*/
void main(void)
{
	OMX_ERRORTYPE eError = OMX_ErrorNone;
	OMX_HANDLETYPE hComp = NULL;
	OMX_CALLBACKTYPE oCallbacks;
	SampleCompTestCtxt *pContext;
	SampleCompTestCtxt oAppData;

	int ch1, ch2;
	int pass;
	int while_pass = 0, loc_diff = 0;


	pContext = &oAppData;
	printf(" Entering : %s \n", __FUNCTION__);
	memset(pContext, 0x0, sizeof(SampleCompTestCtxt));

	oCallbacks.EventHandler = SampleTest_EventHandler;
	oCallbacks.EmptyBufferDone = SampleTest_EmptyBufferDone;
	oCallbacks.FillBufferDone = SampleTest_FillBufferDone;
	printf("\nCalling sem create\n");
	/* Initialize Events to Track callbacks  */
	TIMM_OSAL_SemaphoreCreate(&pContext->hStateSetEvent, 0);
	TIMM_OSAL_SemaphoreCreate(&pContext->hPortDisableEvent, 0);
	//TIMM_OSAL_MutexObtain(pContext->hStateSetEvent, TIMM_OSAL_SUSPEND);
	printf("\nSem created\n");


	pContext->pInputfile = fopen(INPUT_FILE, "rb");
	if (NULL == pContext->pInputfile)
	{
		eError = OMX_ErrorInsufficientResources;
		//goto OMX_TEST_BAIL;
	}
	printf("\nInput file opened\n");
	pContext->pOutputFile = fopen(NON_TUN_OUTPUT_FILE, "wb");
	if (NULL == pContext->pOutputFile)
	{
		eError = OMX_ErrorInsufficientResources;
		//goto OMX_TEST_BAIL;
	}


	/* Initialize OpenMAX */
	printf("\nInitialize OpenMAX\n");
	eError = OMX_Init();
	OMX_TEST_BAIL_IF_ERROR(eError);
	/* Load a component  */
	printf("\nLoad a component\n");
	eError =
	    OMX_GetHandle(&hComp, (OMX_STRING) "OMX.TI.DUCATI1.MISC.SAMPLE",
	    pContext, &oCallbacks);
	OMX_TEST_BAIL_IF_ERROR(eError);
	pContext->hComp = hComp;
printf ("\neError = 0x%x\n", eError);
if(hComp)
	printf("\nhComp = 0x%x\n", hComp);
	/* Verify that the component is in Loaded state */
	printf("\nVerify that the component is in Loaded state\n");

	eError = OMX_GetState(pContext->hComp, &pContext->eState);
	OMX_TEST_BAIL_IF_ERROR(eError);
	if (OMX_StateLoaded != pContext->eState)
	{
		OMX_TEST_SET_ERROR_BAIL(OMX_ErrorUndefined,
		    "not in loaded state \n");
	}

	/* detect all Audio ports on the component */
	OMX_TEST_INIT_STRUCT(pContext->sPortParam[0], OMX_PORT_PARAM_TYPE);
	eError = OMX_GetParameter(hComp, OMX_IndexParamAudioInit,
	    (OMX_PTR) & pContext->sPortParam[0]);
	OMX_TEST_BAIL_IF_ERROR(eError);

	/* detect all video ports on the component */
	OMX_TEST_INIT_STRUCT(pContext->sPortParam[1], OMX_PORT_PARAM_TYPE);
	eError = OMX_GetParameter(hComp, OMX_IndexParamVideoInit,
	    (OMX_PTR) & pContext->sPortParam[1]);
	OMX_TEST_BAIL_IF_ERROR(eError);

	/* detect all image ports on the component */
	OMX_TEST_INIT_STRUCT(pContext->sPortParam[2], OMX_PORT_PARAM_TYPE);
	eError = OMX_GetParameter(hComp, OMX_IndexParamImageInit,
	    (OMX_PTR) & pContext->sPortParam[2]);
	OMX_TEST_BAIL_IF_ERROR(eError);

	/* detect all other ports on the component */
	OMX_TEST_INIT_STRUCT(pContext->sPortParam[3], OMX_PORT_PARAM_TYPE);
	eError = OMX_GetParameter(hComp, OMX_IndexParamOtherInit,
	    (OMX_PTR) & pContext->sPortParam[3]);
	OMX_TEST_BAIL_IF_ERROR(eError);

	pContext->nPorts = pContext->sPortParam[0].nPorts +
	    pContext->sPortParam[1].nPorts +
	    pContext->sPortParam[2].nPorts + pContext->sPortParam[3].nPorts;


	pContext->bClientAllocBuf = OMX_SAMPLE_USEBUF;
	if (pContext->bClientAllocBuf == OMX_TRUE)
	{
		printf(" Client does Allocation of buffers \n");
	} else
	{
		printf(" Component does Allocation of buffers \n");
	}

	/* Transition to Idle state */

	eError = SampleTest_TransitionWait(OMX_StateIdle, pContext);
	OMX_TEST_BAIL_IF_ERROR(eError);
	/* Transition to Executing state */
	eError = SampleTest_TransitionWait(OMX_StateExecuting, pContext);
	OMX_TEST_BAIL_IF_ERROR(eError);
	printf("\nAbout to start processing buffers\n");


	/*  process buffers   */

	while (pContext->nBufDoneCalls < OMX_TEST_BUFFERS_OF_TRAFFIC)
	{

		eError = SampleTest_WriteInBuffers(pContext);
		OMX_TEST_BAIL_IF_ERROR(eError);

		eError = SampleTest_ReadOutBuffers(pContext);
		OMX_TEST_BAIL_IF_ERROR(eError);
		while_pass++;
		//printf("\n WHILE PROCESS LOOP COUNT:  BufDoneCount = %d %d",
		//    while_pass, pContext->nBufDoneCalls);

		//printf("\n Waiting on Sample component to respond");

	}


	gTest = 0;

	/* Transition back to Idle state  */
	eError = SampleTest_TransitionWait(OMX_StateIdle, pContext);
	OMX_TEST_BAIL_IF_ERROR(eError);

	/* Trasnition back to Loaded state */
	eError = SampleTest_TransitionWait(OMX_StateLoaded, pContext);
	OMX_TEST_BAIL_IF_ERROR(eError);


      OMX_TEST_BAIL:

	fclose(pContext->pInputfile);
	fclose(pContext->pOutputFile);

	if (eError == OMX_ErrorNone)
	{
		eError = OMX_FreeHandle(pContext->hComp);
		eError = OMX_Deinit();
	} else
	{
		SampleTest_TransitionWait(OMX_StateInvalid, pContext);
		SampleTest_DeInitBuffers(pContext);

		OMX_FreeHandle(pContext->hComp);
		OMX_Deinit();
	}

	TIMM_OSAL_SemaphoreDelete(pContext->hStateSetEvent);
	TIMM_OSAL_SemaphoreDelete(pContext->hPortDisableEvent);

	/* emit the Test Result */
	if (OMX_ErrorNone != eError)
	{
		printf(" TestCase Failed and returned an error:: %s \n",
		    OMX_TEST_ErrorToString(eError));
	} else
	{
		printf
		    ("\nTest case has ended, now comparing input and output files\n");
		pContext->pInputfile = fopen(INPUT_FILE, "rb");
		if (NULL == pContext->pInputfile)
		{
			printf("\n Error in opening INPUT_FILE");
			eError = OMX_ErrorInsufficientResources;
		}

		pContext->pOutputFile = fopen(NON_TUN_OUTPUT_FILE, "rb");
		if (NULL == pContext->pOutputFile)
		{
			printf("\n Error in opening NON_TUN_OUTPUT_FILE");
			eError = OMX_ErrorInsufficientResources;
		}
		pass = 1;
		while (1)
		{
			if (eError != OMX_ErrorNone)
			{
				pass = 0;
				break;
			}
			ch1 = fgetc(pContext->pInputfile);
			ch2 = fgetc(pContext->pOutputFile);
			loc_diff++;
			if (ch1 == EOF || ch2 == EOF)
			{
				break;
			}
			if (ch1 != ch2)
			{
				pass = 0;
				printf("\n \n");
				printf
				    ("\n FILE SIZE = 320 KB - NUMBER OF ITERATIONS = 20 (10 for INPUT AND 10 FOR OUTPUT buffers\n");
				printf
				    ("\n ################### LOCATION OF DIFFERENCE: %d ################### \n",
				    loc_diff);
				break;
			}
		}
		fclose(pContext->pInputfile);
		fclose(pContext->pOutputFile);
		if (pass == 1)
			printf(" Test Case has Passed\n");
		else
		{
			printf("\nTest case has failed. (EOF not reached)\n");
			eError = OMX_ErrorUndefined;
		}
	}

	if (eError == OMX_ErrorNone)
	{
		printf(" Test Case has Passed :) \n");
	} else
	{
		printf("\nTest case has failed.(OMX Error)\n");
	}
}
/*========================================================*/
OMX_ERRORTYPE SampleTest_DeInitBuffers(SampleCompTestCtxt * pContext)
{
	OMX_ERRORTYPE eError = OMX_ErrorNone;
	OMX_U8 *pBuffer;
	BufferList *pBufferList;
	BufferList *pTemp;

	OMX_U32 nRetVal = 0;

	pTemp = pContext->pInBufferList;

	while (pTemp)
	{
		pBufferList = (BufferList *) pTemp;
		pBuffer = (OMX_U8 *) pTemp->pOrigBufHdr->pBuffer;

		printf("\nCalling Free Buffer on port no. %d\n",
		    pTemp->pOrigBufHdr->nInputPortIndex);

		eError =
		    OMX_FreeBuffer(pContext->hComp,
		    pTemp->pOrigBufHdr->nInputPortIndex, pTemp->pOrigBufHdr);
		OMX_TEST_BAIL_IF_ERROR(eError);

                if (pContext->bClientAllocBuf)
                {

#ifdef OMX_SAMPLE_TILER_TEST
                        nRetVal = MemMgr_Free(pBuffer);
                        if (nRetVal)
                        {
                                printf("\nError in MemMgr free\n");
                        }
#else
                        TIMM_OSAL_Free(pBuffer);
#endif
                }

		pTemp = pTemp->pNextBuf;
		if (pBufferList)
			TIMM_OSAL_Free(pBufferList);
	}

	pContext->pInBufferList = NULL;

	pTemp = pContext->pOutBufferList;
	while (pTemp)
	{
		pBufferList = (BufferList *) pTemp;
		pBuffer = (OMX_U8 *) pTemp->pOrigBufHdr->pBuffer;
		printf("\nCalling Free Buffer on port no. %d\n",
		    pTemp->pOrigBufHdr->nOutputPortIndex);

		eError =
		    OMX_FreeBuffer(pContext->hComp,
		    pTemp->pOrigBufHdr->nOutputPortIndex, pTemp->pOrigBufHdr);
		OMX_TEST_BAIL_IF_ERROR(eError);
                if (pContext->bClientAllocBuf)
                {
#ifdef OMX_SAMPLE_TILER_TEST
                        nRetVal = MemMgr_Free(pBuffer);
                        if (nRetVal)
                        {
                                printf("\nError in MemMgr free\n");
                        }
#else
                        TIMM_OSAL_Free(pBuffer);
#endif
                }

		pTemp = pTemp->pNextBuf;
		if (pBufferList)
			TIMM_OSAL_Free(pBufferList);

	}

	pContext->pOutBufferList = NULL;

      OMX_TEST_BAIL:
	return eError;
}
/*========================================================*/
OMX_ERRORTYPE SampleTest_AllocateBuffers(SampleCompTestCtxt * pContext,
    OMX_PARAM_PORTDEFINITIONTYPE * pPortDef)
{
	OMX_ERRORTYPE eError = OMX_ErrorNone;
	OMX_U8 *pBuffer = NULL;
	BufferList *pBufferList;
	BufferList *pTemp;
	OMX_BUFFERHEADERTYPE *pBufferHdr;
	OMX_U32 i = 100;
	OMX_COMPONENTTYPE *pComp;

#ifdef OMX_SAMPLE_TILER_TEST
	MemAllocBlock *pBlock = NULL;
	OMX_U32 nNumBlocks = 1;

/*For i/p port allocate 2D packed buffer, for o/p port allocate 1D buffer.
Ideally client should get this from GetParams but this is just a sample test so
values are hardcoded*/

	if (pPortDef->nPortIndex == OMX_SAMPLE_INPUT_PORT)
	{
		nNumBlocks = 2;
		pBlock =
		    TIMM_OSAL_Malloc(sizeof(MemAllocBlock) * nNumBlocks, 0, 0,
		    0);
		TIMM_OSAL_Memset(pBlock, 0, sizeof(MemAllocBlock) * nNumBlocks);
		pBlock[0].dim.area.width = OMX_SAMPLE_IN_2DYWIDTH;
		pBlock[0].dim.area.height = OMX_SAMPLE_IN_2DYHEIGHT;
		pBlock[0].pixelFormat = PIXEL_FMT_8BIT;
		pBlock[1].dim.area.width = OMX_SAMPLE_IN_2DUVWIDTH;
		pBlock[1].dim.area.height = OMX_SAMPLE_IN_2DUVHEIGHT;
		pBlock[1].pixelFormat = PIXEL_FMT_16BIT;
	} else
	{
		nNumBlocks = 1;
		pBlock =
		    TIMM_OSAL_Malloc(sizeof(MemAllocBlock) * nNumBlocks, 0, 0,
		    0);
		TIMM_OSAL_Memset(pBlock, 0, sizeof(MemAllocBlock) * nNumBlocks);
		pBlock[0].dim.len = OMX_SAMPLE_BUFFER_SIZE;
		pBlock[0].pixelFormat = PIXEL_FMT_PAGE;
	}
#endif

	for (i = 0; i < pPortDef->nBufferCountActual; i++)
	{
		pBufferList =
		    (BufferList *) TIMM_OSAL_Malloc(sizeof(BufferList),
		    TIMM_OSAL_TRUE, 0, TIMMOSAL_MEM_SEGMENT_INT);
		if (!pBufferList)
		{
			OMX_TEST_SET_ERROR_BAIL
			    (OMX_ErrorInsufficientResources,
			    "malloc failed \n");
		}

		if (pContext->bClientAllocBuf)
		{

#ifdef OMX_SAMPLE_TILER_TEST
/*For i/p port allocate 2D packed buffer, for o/p port allocate 1D buffer.
Ideally client should get this from GetParams but this is just a sample test so
values are hardcoded*/
			pBuffer = MemMgr_Alloc(pBlock, nNumBlocks);
			printf("\nMemMgr allocated buffer = 0x%x\n", pBuffer);
#else
			pBuffer =
			    (OMX_U8 *) TIMM_OSAL_MallocaBuffer(pPortDef->
			    nBufferSize, pPortDef->bBuffersContiguous,
			    pPortDef->nBufferAlignment);

#endif

			if (!pBufferList)
			{
				OMX_TEST_SET_ERROR_BAIL
				    (OMX_ErrorInsufficientResources,
				    "malloc failed \n");
			}

			printf("\nCalling UseBuf on port %d\n",
			    pPortDef->nPortIndex);
			eError =
			    OMX_UseBuffer(pContext->hComp, &pBufferHdr,
			    pPortDef->nPortIndex, 0, pPortDef->nBufferSize,
			    pBuffer);

			OMX_TEST_BAIL_IF_ERROR(eError);

		} else
		{

			pComp = (OMX_COMPONENTTYPE *) pContext->hComp;
			printf("\nCalling allocate buffer\n");
			eError =
			    OMX_AllocateBuffer(pContext->hComp, &pBufferHdr,
			    pPortDef->nPortIndex, 0, pPortDef->nBufferSize);

			OMX_TEST_BAIL_IF_ERROR(eError);
		}
		printf("\npBufferHdr->nOutputPortIndex = %d\n",
		    pBufferHdr->nOutputPortIndex);
		printf("\npBufferHdr->nInputPortIndex = %d\n",
		    pBufferHdr->nInputPortIndex);
		pBufferList->pNextBuf = NULL;
		pBufferList->pBufHdr = pBufferHdr;
		pBufferList->pOrigBufHdr = pBufferHdr;

		if (pPortDef->eDir == OMX_DirInput)
		{
			printf("\npBufferHdr->nOutputPortIndex = %d\n",
			    pBufferHdr->nOutputPortIndex);
			printf("\npBufferHdr->nInputPortIndex = %d\n",
			    pBufferHdr->nInputPortIndex);
			pBufferHdr->nOutputPortIndex = OMX_NOPORT;
			if (pContext->pInBufferList == NULL)
			{
				pContext->pInBufferList = pBufferList;
			} else
			{
				pTemp = pContext->pInBufferList;
				while (pTemp->pNextBuf)
					pTemp = pTemp->pNextBuf;
				pTemp->pNextBuf = pBufferList;
			}
		} else
		{
			pBufferHdr->nInputPortIndex = OMX_NOPORT;
			printf("\npBufferHdr->nOutputPortIndex = %d\n",
			    pBufferHdr->nOutputPortIndex);
			printf("\npBufferHdr->nInputPortIndex = %d\n",
			    pBufferHdr->nInputPortIndex);
			if (pContext->pOutBufferList == NULL)
			{
				pContext->pOutBufferList = pBufferList;
			} else
			{
				pTemp = pContext->pOutBufferList;
				while (pTemp->pNextBuf)
					pTemp = pTemp->pNextBuf;
				pTemp->pNextBuf = pBufferList;
			}
		}
	}

      OMX_TEST_BAIL:
#ifdef OMX_SAMPLE_TILER_TEST
	if (pBlock != NULL)
		TIMM_OSAL_Free(pBlock);
#endif
	if (eError != OMX_ErrorNone)
	{
		if (pBufferList)
		{
			TIMM_OSAL_Free(pBufferList);
		}
	}

	return eError;
}