// project header
#include "MJPEGVideoSource.hh"

/*!*****************************************************************************
 * \brief Constructor
*************************************************************************************/
MJPEGVideoSource::MJPEGVideoSource(UsageEnvironment& env, FramedSource* source) : 
		JPEGVideoSource(env), 
		m_inputSource(source), 
		m_width(0), 
		m_height(0), 
		m_qTable0Init(false), 
		m_qTable1Init(false) 
{
}

/*!*****************************************************************************
 * \brief Destructor
*************************************************************************************/
MJPEGVideoSource::~MJPEGVideoSource()
{
	if (m_inputSource)
	{
		Medium::close(m_inputSource);
	}
}

/*!*****************************************************************************
 * \brief Ask for a frame from the source
*************************************************************************************/
void MJPEGVideoSource::doGetNextFrame() 
{
	if (m_inputSource)
	{
		m_inputSource->getNextFrame(fTo, fMaxSize, afterGettingFrameSub, this, FramedSource::handleClosure, this);			
	}
}

/*!*****************************************************************************
 * \brief source callback
*************************************************************************************/
void MJPEGVideoSource::afterGettingFrame(unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds) 
{
	int headerSize = 0;
	bool headerOk = false;

	for (unsigned int i = 0; i < frameSize ; ++i) 
	{
		// SOF 
		if ( (i+8) < frameSize  && fTo[i] == 0xFF && fTo[i+1] == 0xC0 ) 
		{
			 m_height = (fTo[i+5]<<5)|(fTo[i+6]>>3);
			 m_width = (fTo[i+7]<<5)|(fTo[i+8]>>3);
		}
		// DQT
		if ( (i+5+64) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xDB) 
		{
			if (fTo[i+4] ==0)
			{
				memcpy(m_qTable, fTo + i + 5, 64);
				m_qTable0Init = true;
			}
			else if (fTo[i+4] ==1)
			{
				memcpy(m_qTable + 64, fTo + i + 5, 64);
				m_qTable1Init = true;
			}
		}
		// End of header
		if ( (i+1) < frameSize && fTo[i] == 0x3F && fTo[i+1] == 0x00 ) 
		{
			 headerOk = true;
			 headerSize = i+2;
			 break;
		}
	}

	if (headerOk)
	{
		fFrameSize = frameSize - headerSize;
		memcpy( fTo, fTo + headerSize, fFrameSize );
	}
	
	fNumTruncatedBytes = numTruncatedBytes;
	fPresentationTime = presentationTime;
	fDurationInMicroseconds = durationInMicroseconds;
	afterGetting(this);
}		

/*!*****************************************************************************
 * \brief return quantification tables
*************************************************************************************/
u_int8_t const* MJPEGVideoSource::quantizationTables( u_int8_t& precision, u_int16_t& length )
{
	length = 0;
	precision = 0;
	if ( m_qTable0Init && m_qTable1Init )
	{
		precision = 8;
		length = sizeof(m_qTable);
	}
	return m_qTable;
}
		
