Example #1
0
IEventSPtr OMXComponent::WaitForGeneric(const list<IEventSPtr> &lstEvents, unsigned int uTimeoutMs)
{
	IEventSPtr pRes;
	uint32_t u32Sec;
	uint32_t u32NanoSec;

	m_pClock->GetCurrent(&u32Sec, &u32NanoSec);

	add_milliseconds(&u32Sec, &u32NanoSec, uTimeoutMs);

	bool bMatch = false;
	bool bFailure = false;

	// go until we either fail or succeed
	while ((!bFailure) && (!bMatch))
	{
		// go through all things we _can_ match with ...
		for (list<IEventSPtr>::const_iterator lsi = lstEvents.begin(); lsi != lstEvents.end(); lsi++)
		{
			// determine what type of event this is
			IEvent *pEvent = lsi->get();
			OMXEventData *pOMX = pEvent->ToEvent();
			EmptyBufferDoneData *pEmpty = pEvent->ToEmpty();
			FillBufferDoneData *pFill = pEvent->ToFill();

			Lock();

			if (pEmpty != NULL)
			{
				for (list<EmptyBufferDoneData>::iterator li = m_lstEmpty.begin(); li != m_lstEmpty.end(); li++)
				{
					if (li->pBuffer == pEmpty->pBuffer)
					{
						bMatch = true;
						m_lstEmpty.erase(li);
						pRes = *lsi;
						break;
					}
				}
			}

			// if we are waiting for an OMXEvent
			else if (pOMX != NULL)
			{
				for (list<OMXEventData>::iterator li = m_lstEvents.begin(); li != m_lstEvents.end(); li++)
				{
					// if we found the match
					if ((li->eEvent == pOMX->eEvent) && (pOMX->nData1 == li->nData1) && (pOMX->nData2 == li->nData2))
					{
						bMatch = true;
						m_lstEvents.erase(li);	// remove this item from the list because the caller knows about it now
						pRes = *lsi;
						break;	// must break here to about segfault since we just called erase()
					}
				}
			}
			else if (pFill != NULL)
			{
				for (list<FillBufferDoneData>::iterator li = m_lstFill.begin(); li != m_lstFill.end(); li++)
				{
					if (li->pBuffer == pFill->pBuffer)
					{
						bMatch = true;
						m_lstFill.erase(li);
						pRes = *lsi;
						break;
					}
				}
			}
			// else this should never happen
			else
			{
				assert(false);
			}

			Unlock();

			// if we found a match, we're done
			if (bMatch)
			{
				break;
			}
		}	// end for

		// if we didn't get a match we need to wait for success or a timeout
		if (!bMatch)
		{
			Lock();

			// If we got an error or timed out, then we're done
			// (this implicitly unlocks the mutex during the waiting period, then relocks it upon returning!)
			if (!m_pLocker->WaitForEvent(u32Sec, u32NanoSec))
			{
				bFailure = true;
			}

			Unlock();
		}

	} // end while we haven't succeeded or failed

	if (bFailure)
	{
		throw runtime_error("Waiting timed out");
	}

	return pRes;
}
Example #2
0
int JPEG::decode(const char* data_in, unsigned long int length_in, 
	char **out, unsigned int *width, unsigned int *height)
{
	try {
		// start of image
		width_out = width;
		height_out = height;

		bool bDone = false;
		bool bFillCalled = false;
		int iBufIdx = 0;

		const char* data = data_in;
		unsigned int length = length_in;

		// feed source buffer into component
		while (!bDone)
		{
			// get buffer to fill
			OMX_BUFFERHEADERTYPE *pBufHeader = vpBufHeaders[iBufIdx];
			iBufIdx++;

			// wraparound if necessary
			if (iBufIdx >= iBufferCount)
			{
				iBufIdx = 0;
			}

			size_t stBytesRead = (length > pBufHeader->nAllocLen) ? pBufHeader->nAllocLen : length;
			memcpy(pBufHeader->pBuffer, data, stBytesRead);
			data += stBytesRead;
			length -= stBytesRead;

			pBufHeader->nFilledLen = stBytesRead;
			pBufHeader->nOffset = 0;
			pBufHeader->nFlags = 0;

			// if we are at EOF
			if (length <= 0)
			{
				pBufHeader->nFlags = OMX_BUFFERFLAG_EOS;	// notify that the stream is done
				bDone = true;
			}

			m_pCompDecode->EmptyThisBuffer(pBufHeader);
			bool bGotEmpty = false;

			// we need to get an empty ack after calling EmptyThisBuffer,
			//   the only thing that can stand in our way is getting a port settings changed event.
			// For large JPEGs, more than one port settings changed event may occur (I haven't figured out why, I just handle it)
			// We also expect a port settings changed event if we have no output buffer and can't proceed without one.
			while ((!bGotEmpty) || (m_pBufOutput == NULL))
			{
				// we could get either a "empty done" or a "port settings changed" at this point
				IEventSPtr ev = m_pCompDecode->WaitForEventOrEmpty(OMX_EventPortSettingsChanged, m_iOutPortDecode, 0, pBufHeader, TIMEOUT_MS);

				IEvent *pEv = ev.get();
				OMXEventData *pEvOMX = pEv->ToEvent();
				EmptyBufferDoneData *pEvEmpty = pEv->ToEmpty();

				// if it's a port settings changed event
				if (pEvOMX != NULL)
				{
					// if we don't yet have an output buffer, then create one now
					if (m_pBufOutput == 0)
					{
						OnDecoderOutputChanged();	// setup output buffer
					}
					// else we already have an output buffer, so handle the event differently
					else
					{
						OnDecoderOutputChangedAgain();
					}
				}
				// else if this is an empty event
				else if (pEvEmpty != NULL)
				{
					bGotEmpty = true;
				}
				// else this is unexpected
				else
				{
					throw runtime_error("Unexpected IEvent");
				}
			}

			assert(m_pBufOutput != 0);
			assert(m_pHeaderOutput != 0);

			if (!bFillCalled)
			{
				m_pCompResize->FillThisBuffer(m_pHeaderOutput);
				bFillCalled = true;	// don't want to call FillThisBuffer twice
			}
		} // end while !bDone

		// both of these should be true at this point, if they're not it's a bug in my code
		assert(m_pBufOutput != 0);
		assert(bFillCalled);

		// wait for fill to finish so we can grab our final buffer
		m_pCompResize->WaitForFill(m_pHeaderOutput, TIMEOUT_MS);

		// wait for "end of stream" events from decoder and resizer
		m_pCompDecode->WaitForEvent(OMX_EventBufferFlag, m_iOutPortDecode, OMX_BUFFERFLAG_EOS, TIMEOUT_MS);
		m_pCompResize->WaitForEvent(OMX_EventBufferFlag, m_iOutPortResize, OMX_BUFFERFLAG_EOS, TIMEOUT_MS);

		// at this point, we should have no events queued up at all; if we do, we have probably missed one somewhere
		assert(m_pCompDecode->GetPendingEventCount() == 0);
		assert(m_pCompDecode->GetPendingEmptyCount() == 0);
		assert(m_pCompDecode->GetPendingFillCount() == 0);
		assert(m_pCompResize->GetPendingEventCount() == 0);
		assert(m_pCompResize->GetPendingEmptyCount() == 0);
		assert(m_pCompResize->GetPendingFillCount() == 0);
		*out = (char *)malloc(width[0]*height[0]*4);
		memcpy(*out, m_pHeaderOutput->pBuffer, width[0]*height[0]*4);
	}
	catch (std::exception &ex)
	{
		printf("Exception: %s\n", ex.what());
		m_pLogger->Log("Got exception:");
		m_pLogger->Log(ex.what());
		return 1;
	}
	return 0;
}