/** @brief the entry point for sending buffers to the port
 * 
 * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on
 * the nature of the port, that can be an input or output port.
 */
OMX_ERRORTYPE base_clock_port_SendBufferFunction(
  omx_base_PortType *openmaxStandPort,
  OMX_BUFFERHEADERTYPE* pBuffer) {

  OMX_ERRORTYPE err;
  OMX_U32 portIndex;
  OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer;
  omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
#if NO_GST_OMX_PATCH
  unsigned int i;
#endif
  portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex;
  DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex);

  if (portIndex != openmaxStandPort->sPortParam.nPortIndex) {
    DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex);
    return OMX_ErrorBadPortIndex;
  }

  if(omx_base_component_Private->state == OMX_StateInvalid) {
    DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__);
    return OMX_ErrorInvalidState;
  }

  if(omx_base_component_Private->state != OMX_StateExecuting &&
    omx_base_component_Private->state != OMX_StatePause &&
    omx_base_component_Private->state != OMX_StateIdle) {
    DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state);
    return OMX_ErrorIncorrectStateOperation;
  }
  if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) ||
      (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && 
      (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) {
    DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name);
    return OMX_ErrorIncorrectStateOperation;
  }

  /* Temporarily disable this check for gst-openmax */
#if NO_GST_OMX_PATCH
  {
  OMX_BOOL foundBuffer = OMX_FALSE;
  if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) {
    for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
    if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) {
      foundBuffer = OMX_TRUE;
      break;
    }
    }
  }
  if (!foundBuffer) {
    return OMX_ErrorBadParameter;
  }
  }
#endif

  if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) {
    DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__);
    return err;
  }
  /*If port is not tunneled then simply return the buffer except paused state*/
  if (!PORT_IS_TUNNELED(openmaxStandPort) && (omx_base_component_Private->state != OMX_StatePause)) {
    openmaxStandPort->ReturnBufferFunction(openmaxStandPort,pBuffer);
    return OMX_ErrorNone;
  }
  
  /* And notify the buffer management thread we have a fresh new buffer to manage */
  if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){
    queue(openmaxStandPort->pBufferQueue, pBuffer);
    tsem_up(openmaxStandPort->pBufferSem);
    DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex);
    tsem_up(omx_base_component_Private->bMgmtSem);
  }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){
    DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", 
        __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex);
    queue(openmaxStandPort->pBufferQueue, pBuffer);
    tsem_up(openmaxStandPort->pBufferSem);
  }
  else { // If port being flushed and not tunneled then return error
    DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__);
    return OMX_ErrorIncorrectStateOperation;
  }
  return OMX_ErrorNone;
}
/** @brief the entry point for sending buffers to the alsa sink port
 *
 * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on
 * the nature of the port, that can be an input or output port.
 */
OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) {

  OMX_ERRORTYPE                   err;
  OMX_U32                         portIndex;
  OMX_COMPONENTTYPE*              omxComponent = openmaxStandPort->standCompContainer;
  omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate;
  OMX_BOOL                        SendFrame;
  omx_base_clock_PortType*        pClockPort;
  int                             errQue;
#if NO_GST_OMX_PATCH
  unsigned int i;
#endif

  portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex;
  DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, portIndex);

  if (portIndex != openmaxStandPort->sPortParam.nPortIndex) {
    DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n",
           __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex);
    return OMX_ErrorBadPortIndex;
  }

  if(omx_base_component_Private->state == OMX_StateInvalid) {
    DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__);
    return OMX_ErrorInvalidState;
  }

  if(omx_base_component_Private->state != OMX_StateExecuting &&
    omx_base_component_Private->state != OMX_StatePause &&
    omx_base_component_Private->state != OMX_StateIdle) {
    DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state);
    return OMX_ErrorIncorrectStateOperation;
  }
  if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) ||
      (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle &&
      (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) {
    DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name);
    return OMX_ErrorIncorrectStateOperation;
  }

  /* Temporarily disable this check for gst-openmax */
#if NO_GST_OMX_PATCH
  {
  OMX_BOOL foundBuffer = OMX_FALSE;
  if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) {
    for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){
    if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) {
      foundBuffer = OMX_TRUE;
      break;
    }
    }
  }
  if (!foundBuffer) {
    return OMX_ErrorBadParameter;
  }
  }
#endif

  if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) {
    DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__);
    return err;
  }

  pClockPort  = (omx_base_clock_PortType*)omx_base_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX];
  if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort) &&
      (omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle) &&
      ((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)){
    SendFrame = omx_alsasink_component_ClockPortHandleFunction((omx_alsasink_component_PrivateType*)omx_base_component_Private, pBuffer);
    /* drop the frame */
    if(!SendFrame) pBuffer->nFilledLen=0;
  }

  /* And notify the buffer management thread we have a fresh new buffer to manage */
  if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){
      errQue = queue(openmaxStandPort->pBufferQueue, pBuffer);
      if (errQue) {
    	  /* /TODO the queue is full. This can be handled in a fine way with
    	   * some retrials, or other checking. For the moment this is a critical error
    	   * and simply causes the failure of this call
    	   */
    	  return OMX_ErrorInsufficientResources;
      }
      tsem_up(openmaxStandPort->pBufferSem);
      DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex);
      tsem_up(omx_base_component_Private->bMgmtSem);
  }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){
      DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n",
        __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex);
      errQue = queue(openmaxStandPort->pBufferQueue, pBuffer);
      if (errQue) {
    	  /* /TODO the queue is full. This can be handled in a fine way with
    	   * some retrials, or other checking. For the moment this is a critical error
    	   * and simply causes the failure of this call
    	   */
    	  return OMX_ErrorInsufficientResources;
      }
      tsem_up(openmaxStandPort->pBufferSem);
  }
  else { // If port being flushed and not tunneled then return error
    DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__);
    return OMX_ErrorIncorrectStateOperation;
  }
  return OMX_ErrorNone;
}
/** @brief the entry point for sending buffers to the port
 *
 * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on
 * the nature of the port, that can be an input or output port.
 */
OMX_ERRORTYPE videoenc_port_SendBufferFunction(
	omx_base_PortType *openmaxStandPort,
	OMX_BUFFERHEADERTYPE *pBuffer)
{
	int errQue;
	OMX_U32 portIndex;
	OMX_ERRORTYPE err = OMX_ErrorNone;
	OMX_COMPONENTTYPE *omxComponent = openmaxStandPort->standCompContainer;
	omx_videoenc_PortType *omx_videoenc_Port = (omx_videoenc_PortType *)openmaxStandPort;
	omx_base_component_PrivateType *omx_base_component_Private = (omx_base_component_PrivateType *)omxComponent->pComponentPrivate;
	OMX_VCE_Buffers_List *pBuffersMng_List= &(omx_videoenc_Port->BuffersMng_List);
	DEBUG(DEB_LEV_FUNCTION_NAME, "In %s for port %p\n", __func__, omx_videoenc_Port);
#if NO_GST_OMX_PATCH
	unsigned int i;
#endif
	portIndex = (omx_videoenc_Port->sPortParam.eDir == OMX_DirInput) ? pBuffer->nInputPortIndex : pBuffer->nOutputPortIndex;
	DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %d\n", __func__, portIndex);

	if (portIndex != omx_videoenc_Port->sPortParam.nPortIndex)
	{
		DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex,
			(int)omx_videoenc_Port->sPortParam.nPortIndex);
		return OMX_ErrorBadPortIndex;
	}

	if(omx_base_component_Private->state == OMX_StateInvalid)
	{
		DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__);
		return OMX_ErrorInvalidState;
	}

	if(omx_base_component_Private->state != OMX_StateExecuting &&
		omx_base_component_Private->state != OMX_StatePause &&
		omx_base_component_Private->state != OMX_StateIdle)
	{
		DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state);
		return OMX_ErrorIncorrectStateOperation;
	}

	if (!PORT_IS_ENABLED(omx_videoenc_Port) || (PORT_IS_BEING_DISABLED(omx_videoenc_Port) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port)) ||
		((omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle ||
		omx_base_component_Private->transientState == OMX_TransStatePauseToIdle) &&
		(PORT_IS_TUNNELED(omx_videoenc_Port) && !PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port))))
	{
		DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex, omx_base_component_Private->name);
		return OMX_ErrorIncorrectStateOperation;
	}

	/* Temporarily disable this check for gst-openmax */
#if NO_GST_OMX_PATCH
	{
		OMX_BOOL foundBuffer = OMX_FALSE;
		if(pBuffer!=NULL && pBuffer->pBuffer!=NULL)
		{
			for(i=0; i < omx_videoenc_Port->sPortParam.nBufferCountActual; i++)
			{
				if (pBuffer->pBuffer == omx_videoenc_Port->pInternalBufferStorage[i]->pBuffer)
				{
					foundBuffer = OMX_TRUE;
					break;
				}
			}
		}
		if (!foundBuffer)
		{
			return OMX_ErrorBadParameter;
		}
	}
#endif

	if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone)
	{
		DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__);
		return err;
	}

	/* And notify the buffer management thread we have a fresh new buffer to manage */
	if(!PORT_IS_BEING_FLUSHED(omx_videoenc_Port) && \
		!(PORT_IS_BEING_DISABLED(omx_videoenc_Port) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(omx_videoenc_Port)))
	{
		//here
		if(omx_videoenc_Port->bIsStoreMediaData == OMX_TRUE)
		{
			if((*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeCameraSource_act) && \
				(*(OMX_U32 *)pBuffer->pBuffer != kMetadataBufferTypeGrallocSource_act))
			{
				DEBUG(DEB_LEV_ERR, "Warning!in StoreMediaData mode,but the buffer (%x) is not kMetadataBufferTypeCameraSource_act!\n",
					(int)*(OMX_U32 *)pBuffer->pBuffer);
			}
		}

		if(omx_videoenc_Port->ringbuffer == OMX_TRUE && omx_videoenc_Port->sPortParam.nPortIndex == OMX_BASE_FILTER_OUTPUTPORT_INDEX)
		{
			err = Free_UseRingBuffer_BuffersMng(&omx_videoenc_Port->BuffersMng_List,omx_videoenc_Port->bufferpool,pBuffer,
				omx_videoenc_Port->sPortParam.nBufferSize);
			if( err != OMX_ErrorNone)
			{
				DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__);
				return err;
			}
		}
		else
		{
			err = SendBuffer_BuffersMng(pBuffersMng_List,pBuffer,omx_videoenc_Port->bIsStoreMediaData,omx_videoenc_Port->sPortParam.eDir);
			if( err != OMX_ErrorNone)
			{
				DEBUG(DEB_LEV_ERR, "err!In %s: SendBuffer_BuffersMng\n", __func__);
				return err;
			}
		}

		errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer);
		if (errQue)
		{
			/* /TODO the queue is full. This can be handled in a fine way with
			* some retrials, or other checking. For the moment this is a critical error
			* and simply causes the failure of this call
			*/
			return OMX_ErrorInsufficientResources;
		}

		tsem_up(omx_videoenc_Port->pBufferSem);
		DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n", __func__, (int)portIndex);
		tsem_up(omx_base_component_Private->bMgmtSem);
	}
	else if(PORT_IS_BUFFER_SUPPLIER(omx_videoenc_Port))
	{
		DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n",
			__func__, omx_base_component_Private->name, (int)omx_videoenc_Port->sPortParam.nPortIndex);

		errQue = queue(omx_videoenc_Port->pBufferQueue, pBuffer);
		if (errQue)
		{
			/* /TODO the queue is full. This can be handled in a fine way with
			* some retrials, or other checking. For the moment this is a critical error
			* and simply causes the failure of this call
			*/
			return OMX_ErrorInsufficientResources;
		}
		tsem_up(omx_videoenc_Port->pBufferSem);
	}
	else
	{
		// If port being flushed and not tunneled then return error
		DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__);
		return OMX_ErrorIncorrectStateOperation;
	}

	DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s for port %p\n", __func__, omx_videoenc_Port);
	return OMX_ErrorNone;
}