OMX_ERRORTYPE FileSink::Start()
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;

    // make sure we've been configured
    if (m_nFrames >= 0)
    {
      VENC_TEST_MSG_MEDIUM("starting thread...");
      result = m_pThread->Start(SinkThreadEntry,  // thread fn
          this,             // thread data
          0);               // thread priority
      if (result == OMX_ErrorNone)
      {
        m_bStarted = OMX_TRUE;
      }
      else
      {
        VENC_TEST_MSG_ERROR("failed to start thread");
      }
    }
    else
    {
      VENC_TEST_MSG_ERROR("source has not been configured");
      result = OMX_ErrorUndefined;
    }
    return result;
  }
  OMX_ERRORTYPE ITestCase::Finish()
  {
    OMX_ERRORTYPE result = OMX_ErrorUndefined;

    if (m_pThread)
    {
      OMX_ERRORTYPE threadResult;

      VENC_TEST_MSG_MEDIUM("waiting for thread to finish...");

      // wait for thread to exit
      result = m_pThread->Join(&threadResult);

      if (result == OMX_ErrorNone)
      {
        result = threadResult;
      }

      if (threadResult != OMX_ErrorNone)
      {
        VENC_TEST_MSG_ERROR("test case thread execution error");
      }
    }

    // let's not over-ride the original error with a different result
    if (m_eTestResult == OMX_ErrorNone)
    {
      m_eTestResult = result;
    }

    return m_eTestResult;
  }
  OMX_ERRORTYPE FileSink::Configure(OMX_S32 nFrames,
      OMX_STRING pFileName,
      OMX_S32 nTestNum,
      FrameReleaseFnType pFrameReleaseFn)
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;
    if (nFrames >= 0 &&
        pFrameReleaseFn != NULL)
    {
      m_nFrames = nFrames;
      m_pFrameReleaseFn = pFrameReleaseFn;

      if (pFileName != NULL &&
          Parser::StringICompare((OMX_STRING)"", pFileName) != 0)
      {
        (void) Parser::AppendTestNum(pFileName, nTestNum);

        m_pFile = new File();
        if (m_pFile != NULL)
        {
          VENC_TEST_MSG_MEDIUM("Opening output file...");
          result = m_pFile->Open(pFileName, OMX_FALSE);
          if (result != OMX_ErrorNone)
          {
            VENC_TEST_MSG_ERROR("Failed to open file");
          }
        }
        else
        {
          VENC_TEST_MSG_ERROR("Failed to allocate file");
          result = OMX_ErrorInsufficientResources;
        }
      }
      else
      {
        VENC_TEST_MSG_MEDIUM("No output file");
      }
    }
    else
    {
      VENC_TEST_MSG_ERROR("Bad param(s)");
      result = OMX_ErrorBadParameter;
    }
    return result;
  }
   ITestCase::ITestCase()
      : m_pThread(new Thread()),
        m_eTestResult(OMX_ErrorNone),
        m_nTestNum(0),
	m_bIsVTPath(OMX_FALSE) 
   {
      if (venc_semaphore_create(&m_pSemaphore, 0, 1) != 0)
      {
         VENC_TEST_MSG_MEDIUM("error creating semaphore, sync will not work", 0, 0, 0);
      }
   }
  OMX_ERRORTYPE FileSource::SetFreeBuffer(OMX_BUFFERHEADERTYPE* pBufferHdr)
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;

    if (pBufferHdr != NULL && pBufferHdr->pBuffer != NULL)
    {
      // if we have not started then the client is registering buffers
      if (m_bStarted == OMX_FALSE)
      {
        // need to fill the buffer with YUV data upon registration
        if (m_nFramesRegistered < m_nBuffers &&
            m_bLiveMode == OMX_TRUE)
        {

          VENC_TEST_MSG_MEDIUM("register buffer");

          if (m_pFile)
          {
            OMX_S32 nFrameBytes = m_nFrameWidth * m_nFrameHeight * 3 / 2;
            OMX_S32 nBytesRead;
            result = m_pFile->Read((OMX_U8*)pBufferHdr->pBuffer,
                nFrameBytes,
                &nBytesRead);
            if (result != OMX_ErrorNone ||
                nBytesRead != nFrameBytes)
            {
              VENC_TEST_MSG_HIGH("yuv file is too small"
                  "result(%d) nFrameBytes(%ld) nBytesRead(%ld)",
                  result, nFrameBytes, nBytesRead);
              result = m_pFile->SeekStart(0);
              result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
                  nFrameBytes,
                  &nBytesRead);
            }
          }
        }

        ++m_nFramesRegistered;
      }
      result = m_pBufferQueue->Push(&pBufferHdr,
          sizeof(OMX_BUFFERHEADERTYPE**));
    }
    else
    {
      VENC_TEST_MSG_ERROR("bad params");
      result = OMX_ErrorBadParameter;
    }
    return result;
  }
   OMX_ERRORTYPE ITestCase::Start(OMX_STRING pConfigFileName,
                                  OMX_S32 nTestNum)
   {
      OMX_ERRORTYPE result = OMX_ErrorNone;

      Config config;
      config.GetEncoderConfig(&m_sConfig);
      config.GetDynamicConfig(&m_sDynamicConfig);

      m_nTestNum = nTestNum;

      result = config.Parse(pConfigFileName, &m_sConfig, &m_sDynamicConfig);
      if (result == OMX_ErrorNone)
      {
         result = ValidateAssumptions(&m_sConfig, &m_sDynamicConfig);

         if (result == OMX_ErrorNone)
         {
     	    if (m_sConfig.eControlRate == OMX_Video_ControlRateConstantSkipFrames || 
		        m_sConfig.eResyncMarkerType != RESYNC_MARKER_NONE) 
	        {
                  m_bIsVTPath = OMX_TRUE;
		}
 
            VENC_TEST_MSG_MEDIUM("Starting test thread...", 0, 0, 0);
            if (m_pThread)
            {
               result = m_pThread->Start(ThreadEntry,    // thread entry
                                         this,           // thread args
                                         0);             // priority
            }
            else
            {
               VENC_TEST_MSG_ERROR("Start test thread failed...", 0, 0, 0);
               result = OMX_ErrorUndefined;
            }
         }
         else
         {
            VENC_TEST_MSG_ERROR("Invalid config. Assumptions not validated", 0, 0, 0);
         }
      }
      else
      {
         VENC_TEST_MSG_ERROR("Error parsing config file", 0, 0, 0);
      }

      return result;
   }
  OMX_ERRORTYPE ITestCase::Start(OMX_STRING pConfigFileName,
      OMX_S32 nTestNum)
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;

    Config config;
    config.GetEncoderConfig(&m_sConfig);
    config.GetDynamicConfig(&m_sDynamicConfig);

    m_nTestNum = nTestNum;

    result = config.Parse(pConfigFileName, &m_sConfig, &m_sDynamicConfig);
    if (result == OMX_ErrorNone)
    {
      result = ValidateAssumptions(&m_sConfig, &m_sDynamicConfig);

      if (result == OMX_ErrorNone)
      {
        VENC_TEST_MSG_MEDIUM("Starting test thread...");
        if (m_pThread)
        {
          result = m_pThread->Start(ThreadEntry,    // thread entry
              this,           // thread args
              0);             // priority
        }
        else
        {
          VENC_TEST_MSG_ERROR("Start test thread failed...");
          result = OMX_ErrorUndefined;
        }
      }
      else
      {
        VENC_TEST_MSG_ERROR("Invalid config. Assumptions not validated");
      }
    }
    else
    {
      VENC_TEST_MSG_ERROR("Error parsing config file");
    }

    return result;
  }
  OMX_ERRORTYPE FileSource::Start()
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;

    // make sure we've been configured
    if (m_nFrames >= 0 &&
        m_nFramerate >= 0 &&
        m_nBuffers > 0)
    {
      if (m_nFramesRegistered == m_nBuffers)
      {

        VENC_TEST_MSG_MEDIUM("starting thread...");

        result = m_pThread->Start(SourceThreadEntry,  // thread fn
            this,               // thread data
            0);                 // thread priority

        if (result == OMX_ErrorNone)
        {
          m_bStarted = OMX_TRUE;
        }
        else
        {
          VENC_TEST_MSG_ERROR("failed to start thread");
        }
      }
      else
      {
        VENC_TEST_MSG_ERROR("need to register all buffers with the source");
        result = OMX_ErrorUndefined;
      }

    }
    else
    {
      VENC_TEST_MSG_ERROR("source has not been configured");
      result = OMX_ErrorUndefined;
    }
    return result;
  }
  OMX_ERRORTYPE FileSource::Finish()
  {
    OMX_ERRORTYPE result = OMX_ErrorNone;

    if (m_bStarted == OMX_TRUE)
    {
      if (m_pThread != NULL)
      {
        OMX_ERRORTYPE threadResult;

        VENC_TEST_MSG_MEDIUM("waiting for thread to finish...");

        // wait for thread to exit
        result = m_pThread->Join(&threadResult);

        if (result == OMX_ErrorNone)
        {
          result = threadResult;
        }

        if (threadResult != OMX_ErrorNone)
        {
          VENC_TEST_MSG_ERROR("source thread execution error");
        }
      }

      m_bStarted = OMX_FALSE;
    }
    else
    {
      VENC_TEST_MSG_ERROR("already stopped");
      result = OMX_ErrorIncorrectStateTransition;
    }

    return result;
  }
  OMX_ERRORTYPE FileSource::SourceThread()
  {
    OMX_BOOL bKeepGoing = OMX_TRUE;
    OMX_ERRORTYPE result = OMX_ErrorNone;
    OMX_TICKS nTimeStamp = 0;

    VENC_TEST_MSG_MEDIUM("thread has started");

    for (OMX_S32 i = 0; i < m_nFrames && bKeepGoing == OMX_TRUE; i++)
    {

      OMX_BUFFERHEADERTYPE* pBufferHdr = NULL;
      const OMX_S32 nFrameBytes = m_nFrameWidth * m_nFrameHeight * 3 / 2;

      // Since frame rate can change at any time, let's make sure that we use
      // the same frame rate for the duration of this loop iteration
      OMX_S32 nFramerate = m_nFramerate;

      // If in live mode we deliver frames in a real-time fashion
      if (m_bLiveMode == OMX_TRUE)
      {
        Sleeper::Sleep(1000 / nFramerate);

        if (m_pBufferQueue->GetSize() <= 0)
        {
          VENC_TEST_MSG_MEDIUM("No buffers. Block until buffer available...");
        }

        VENC_TEST_MSG_MEDIUM("Wait for free buffer...");

        result = m_pBufferQueue->Pop(&pBufferHdr,
            sizeof(pBufferHdr),
            0); // wait forever
      }

      // if not in live mode, we deliver frames as they become available
      else
      {
        result = m_pBufferQueue->Pop(&pBufferHdr,
            sizeof(pBufferHdr),
            0); // wait forever
        if (m_pFile != NULL)
        {
          OMX_S32 nBytesRead;
          result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
              nFrameBytes,
              &nBytesRead);
          if (result != OMX_ErrorNone ||
              nBytesRead != nFrameBytes)
          {
            VENC_TEST_MSG_HIGH("yuv file is too small"
                "result:%d,nFrameBytse(%ld),nBytesRead(%ld)",
                result, nFrameBytes, nBytesRead);

            VENC_TEST_MSG_HIGH("buffer virt %p \n", pBufferHdr->pBuffer);
            result = m_pFile->SeekStart(0);
            result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
                nFrameBytes,
                &nBytesRead);
          }
        }
      }

      if (result == OMX_ErrorNone)
      {
        if (pBufferHdr != NULL)
        {
          VENC_TEST_MSG_MEDIUM("delivering frame %ld...",i);

          if (m_bLiveMode == OMX_TRUE)
          {
            nTimeStamp = (OMX_TICKS) Time::GetTimeMicrosec();
          }
          else
          {
            nTimeStamp = nTimeStamp + (OMX_TICKS) (1000000 / nFramerate);
          }

          pBufferHdr->nFilledLen = nFrameBytes;
          pBufferHdr->nTimeStamp = nTimeStamp;

          // set the EOS flag if this is the last frame
          pBufferHdr->nFlags = 0;
          if (i == m_nFrames - 1)
          {
            pBufferHdr->nFlags = OMX_BUFFERFLAG_EOS;
          }

          pBufferHdr->nOffset = ((m_nFrameWidth * m_nDVSYOffset) + m_nDVSXOffset) * 3 / 2;
          m_pFrameDeliverFn(pBufferHdr);
        }
        else
        {
          VENC_TEST_MSG_ERROR("Buffer is null");
        }
      }
      else
      {
        VENC_TEST_MSG_ERROR("Error getting buffer");
        bKeepGoing = OMX_FALSE;
      }
    }
    VENC_TEST_MSG_HIGH("Source thread is exiting...");
    return result;
  }
  OMX_ERRORTYPE FileSink::SinkThread()
  {
    OMX_BOOL bKeepGoing = OMX_TRUE;
    OMX_ERRORTYPE result = OMX_ErrorNone;

    VENC_TEST_MSG_MEDIUM("thread has started");

    for (OMX_S32 i = 0; i < m_nFrames && bKeepGoing == OMX_TRUE; i++)
    {

      OMX_BUFFERHEADERTYPE* pBufferHdr = NULL;

      result = m_pBufferQueue->Pop(&pBufferHdr,
          sizeof(pBufferHdr),
          0); // wait forever

      if (result == OMX_ErrorNone)
      {
        if (pBufferHdr != NULL)
        {
          OMX_U32 nBytes;

          if (m_pFile != NULL)
          {
            if (pBufferHdr->nFilledLen > 0)
            {
              VENC_TEST_MSG_HIGH("writing frame %ld with %lu bytes...", i, pBufferHdr->nFilledLen);
              result = m_pFile->Write((OMX_U8 *)pBufferHdr->pBuffer,
                  pBufferHdr->nFilledLen,
                  &nBytes);

              if (result != OMX_ErrorNone)
              {
                VENC_TEST_MSG_ERROR("error writing to file...");
              }
              else if (nBytes != pBufferHdr->nFilledLen)
              {
                VENC_TEST_MSG_ERROR("mismatched number of bytes in file write");
                result = OMX_ErrorUndefined;
              }
            }
            else
            {
              VENC_TEST_MSG_HIGH("skipping frame %ld...",i);
            }

          }
          else
          {
            VENC_TEST_MSG_MEDIUM("received frame %ld...",i);
          }

          if (pBufferHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
          {
            // this is just the syntax header, not a frame so increase loop count
            VENC_TEST_MSG_HIGH("got codecconfig");
            ++m_nFrames;
          }

          if (pBufferHdr->nFlags & OMX_BUFFERFLAG_EOS)
          {
            // this is the last frame. note that we may get fewer frames
            // than expected if RC is enabled with frame skips
            VENC_TEST_MSG_HIGH("got eos");
            bKeepGoing = OMX_FALSE;
          }

          m_pFrameReleaseFn(pBufferHdr);
        }
        else
        {
          VENC_TEST_MSG_ERROR("Buffer is null");
        }
      }
      else
      {
        VENC_TEST_MSG_ERROR("Error getting buffer");
        bKeepGoing = OMX_FALSE;
      }
    }
    VENC_TEST_MSG_HIGH("Sink thread is exiting...");
    return result;
  }