You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
v4l2rtspserver/src/MJPEGVideoSource.cpp

119 lines
3.9 KiB
C++

/* ---------------------------------------------------------------------------
** This software is in the public domain, furnished "as is", without technical
** support, and with no warranty, express or implied, as to its usefulness for
** any purpose.
**
** MJPEGVideoSource.cpp
**
** V4L2 RTSP streamer
**
** MJPEG Source for RTSP server
**
** -------------------------------------------------------------------------*/
#include "MJPEGVideoSource.h"
void MJPEGVideoSource::afterGettingFrame(unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds)
{
int headerSize = 0;
unsigned int i = 0;
while ( (i<frameSize) && (headerSize==0) ) {
if ( ((i+11) < frameSize) && (fTo[i] == 0xFF) && (fTo[i+1] == 0xC0) ) {
// SOF
int length = (fTo[i+2]<<8)|(fTo[i+3]);
LOG(DEBUG) << "SOF length:" << length;
m_height = (fTo[i+5]<<5)|(fTo[i+6]>>3);
m_width = (fTo[i+7]<<5)|(fTo[i+8]>>3);
int hv_subsampling = fTo[i+11];
if (hv_subsampling == 0x21 ) {
m_type = 0; // JPEG 4:2:2
} else if (hv_subsampling == 0x22 ) {
m_type = 1; // JPEG 4:2:0
} else {
LOG(NOTICE) << "not managed sampling:0x" << std::hex << hv_subsampling;
m_type = 255;
}
int precision = fTo[i+4];
LOG(INFO) << "width:" << (int)(m_width<<3) << " height:" << (int)(m_height<<3) << " type:"<< (int)m_type << " precision:" << precision;
i+=length+2;
} else if (((i+5) < frameSize) && (fTo[i] == 0xFF) && (fTo[i+1] == 0xDB)) {
// DQT
int length = (fTo[i+2]<<8)|(fTo[i+3]);
LOG(DEBUG) << "DQT length:" << length;
int qtable_length = length-2;
unsigned int qtable_position = i+4;
while (qtable_length > 0) {
LOG(DEBUG) << "DQT qtable_length:" << qtable_length;
unsigned int precision = (fTo[qtable_position]&0xf0)<<4;
unsigned int quantIdx = fTo[qtable_position]&0x0f;
unsigned int quantSize = 64*(precision+1);
if (quantSize*quantIdx+quantSize <= sizeof(m_qTable)) {
if ( (qtable_position+quantSize) < frameSize) {
memcpy(m_qTable + quantSize*quantIdx, fTo + qtable_position + 1, quantSize);
LOG(DEBUG) << "Quantization table idx:" << quantIdx << " precision:" << precision << " size:" << quantSize << " total size:" << m_qTableSize;
if (quantSize*quantIdx+quantSize > m_qTableSize) {
m_qTableSize = quantSize*quantIdx+quantSize;
}
}
}
qtable_length -= quantSize+1;
qtable_position += quantSize+1;
}
i+=length+2;
} else if ( ((i+5) < frameSize) && (fTo[i] == 0xFF) && (fTo[i+1] == 0xDD) ) {
// DRI
int length = (fTo[i+2]<<8)|(fTo[i+3]);
m_restartInterval = (fTo[i+4]<<8)|(fTo[i+5]);
LOG(DEBUG) << "DRI restartInterval:" << m_restartInterval;
i+=length+2;
} else if ( ((i+3) < frameSize) && (fTo[i] == 0xFF) && (fTo[i+1] == 0xDA) ) {
// SOS
int length = (fTo[i+2]<<8)|(fTo[i+3]);
LOG(DEBUG) << "SOS length:" << length;
headerSize = i+length+2;
} else {
i++;
}
}
if (headerSize != 0) {
LOG(DEBUG) << "headerSize:" << headerSize;
fFrameSize = frameSize - headerSize;
memmove( fTo, fTo + headerSize, fFrameSize );
} else {
LOG(NOTICE) << "Bad header => dropping frame";
fFrameSize = 0;
}
fNumTruncatedBytes = numTruncatedBytes;
fPresentationTime = presentationTime;
fDurationInMicroseconds = durationInMicroseconds;
afterGetting(this);
}
u_int8_t const* MJPEGVideoSource::quantizationTables( u_int8_t& precision, u_int16_t& length )
{
length = 0;
precision = 0;
if (m_qTableSize > 0)
{
length = m_qTableSize;
precision = m_precision;
}
return m_qTable;
}