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; }