40 m_reason =
"invalid payload offset" ;
44 m_reason =
"dynamic type field" ;
48 m_reason =
"unexpected type field" ;
52 m_reason =
"unexpected quantisation field: support for in-band tables not implemented" ;
56 G_WARNING_ONCE(
"ignoring rtp jpeg interlacing" ) ;
61 return m_reason.empty() ;
71 if( type_has_restart_markers() )
72 return make_word( &m_p[8U] ) ;
79 if( type_has_restart_markers() )
80 return make_word( &m_p[10U] ) & 0x3fff ;
87 std::ostringstream ss ;
88 ss <<
"ts=" << ts() <<
" fo=" << fo() <<
" t=" << type() <<
" q=" << q() <<
" dx=" << dx() <<
" dy=" << dy() <<
" ri=" << ri() <<
" rc=" << rc() ;
94 const unsigned int p0 =
static_cast<unsigned char>(m_p[0]) ;
100 const unsigned int p1 =
static_cast<unsigned char>(m_p[1]) ;
101 const unsigned int p2 =
static_cast<unsigned char>(m_p[2]) ;
102 const unsigned int p3 =
static_cast<unsigned char>(m_p[3]) ;
103 return make_dword( 0U , p1 , p2 , p3 ) ;
108 const unsigned int p4 =
static_cast<unsigned char>(m_p[4]) ;
114 return type() >= 128U ;
119 return type() >= 64U && type() <= 127U ;
124 return type_has_restart_markers() ? (type()-64U) : type() ;
129 const unsigned int p5 =
static_cast<unsigned char>(m_p[5]) ;
135 return !!( q() & 0x80 ) ;
140 const unsigned int p6 =
static_cast<unsigned char>(m_p[6]) ;
146 const unsigned int p7 =
static_cast<unsigned char>(m_p[7]) ;
150 unsigned int Gv::RtpJpegPacket::make_word(
const char * p )
152 unsigned int p0 =
static_cast<unsigned char>(p[0]) ;
153 unsigned int p1 =
static_cast<unsigned char>(p[1]) ;
154 return (p0<<8) | p1 ;
157 unsigned long Gv::RtpJpegPacket::make_dword(
unsigned long c3 ,
unsigned long c2 ,
unsigned long c1 ,
unsigned long c0 )
159 return ( c3 << 24 ) | ( c2 << 16 ) | ( c1 << 8 ) | ( c0 << 0 ) ;
165 p.offset = payloadOffset() ;
166 p.size = payloadSize() ;
167 p.begin = payloadBegin() ;
168 p.end = payloadEnd() ;
174 size_t header_size = 8U ;
175 if( type_has_restart_markers() )
180 if( q_is_special() && fo() == 0UL )
184 unsigned int qtl = make_word( &m_p[header_size+2U] ) ;
185 header_size += ( 4U + qtl ) ;
192 G_ASSERT( payloadOffset() <= m_n ) ;
193 return m_n - payloadOffset() ;
198 return m_p + payloadOffset() ;
210 static const int table_rfc[128] =
213 16, 11, 10, 16, 24, 40, 51, 61,
214 12, 12, 14, 19, 26, 58, 60, 55,
215 14, 13, 16, 24, 40, 57, 69, 56,
216 14, 17, 22, 29, 51, 87, 80, 62,
217 18, 22, 37, 56, 68, 109, 103, 77,
218 24, 35, 55, 64, 81, 104, 113, 92,
219 49, 64, 78, 87, 103, 121, 120, 101,
220 72, 92, 95, 98, 112, 100, 103, 99,
222 17, 18, 24, 47, 99, 99, 99, 99,
223 18, 21, 26, 66, 99, 99, 99, 99,
224 24, 26, 56, 99, 99, 99, 99, 99,
225 47, 66, 99, 99, 99, 99, 99, 99,
226 99, 99, 99, 99, 99, 99, 99, 99,
227 99, 99, 99, 99, 99, 99, 99, 99,
228 99, 99, 99, 99, 99, 99, 99, 99,
229 99, 99, 99, 99, 99, 99, 99, 99
234 static const int table_erratum[128] =
237 16, 11, 12, 14, 12, 10, 16, 14,
238 13, 14, 18, 17, 16, 19, 24, 40,
239 26, 24, 22, 22, 24, 49, 35, 37,
240 29, 40, 58, 51, 61, 60, 57, 51,
241 56, 55, 64, 72, 92, 78, 64, 68,
242 87, 69, 55, 56, 80, 109, 81, 87,
243 95, 98, 103, 104, 103, 62, 77, 113,
244 121, 112, 100, 120, 92, 101, 103, 99 ,
246 17, 18, 18, 24, 21, 24, 47, 26,
247 26, 47, 99, 66, 56, 66, 99, 99,
248 99, 99, 99, 99, 99, 99, 99, 99,
249 99, 99, 99, 99, 99, 99, 99, 99,
250 99, 99, 99, 99, 99, 99, 99, 99,
251 99, 99, 99, 99, 99, 99, 99, 99,
252 99, 99, 99, 99, 99, 99, 99, 99,
253 99, 99, 99, 99, 99, 99, 99, 99
256 static const int table_x[128] =
259 13, 9, 10, 11, 10, 8, 13, 11,
260 10, 11, 14, 14, 13, 15, 19, 32,
261 21, 19, 18, 18, 19, 39, 28, 30,
262 23, 32, 46, 41, 49, 48, 46, 41,
263 45, 44, 51, 58, 74, 62, 51, 54,
264 70, 55, 44, 45, 64, 87, 65, 70,
265 76, 78, 82, 83, 82, 50, 62, 90,
266 97, 90, 80, 96, 74, 81, 82, 79,
268 14, 14, 14, 19, 17, 19, 38, 21,
269 21, 38, 79, 53, 45, 53, 79, 79,
270 79, 79, 79, 79, 79, 79, 79, 79,
271 79, 79, 79, 79, 79, 79, 79, 79,
272 79, 79, 79, 79, 79, 79, 79, 79,
273 79, 79, 79, 79, 79, 79, 79, 79,
274 79, 79, 79, 79, 79, 79, 79, 79,
275 79, 79, 79, 79, 79, 79, 79, 79,
278 template <
typename T>
280 T limit( T min , T value , T max )
282 return value < min ? min : ( value > max ? max : value ) ;
285 template <
typename Titerator>
286 static void make_table(
int q_in , Titerator out ,
const int * p ,
const int * end =
nullptr )
288 if( end ==
nullptr ) end = p + 128 ;
289 int factor = limit( 1 , q_in , 99 ) ;
290 int q = q_in < 50 ? (q_in/factor) : (200-factor*2) ;
291 for( ; p != end ; ++p )
293 int qq = ((*p) * q + 50) / 100 ;
294 *out++ = limit( 1 , qq , 255 ) ;
298 template <
typename Titerator>
299 static void make_table( Titerator out ,
const int * p ,
const int * end =
nullptr )
301 if( end ==
nullptr ) end = p + 128 ;
302 for( ; p != end ; ++p )
304 *out++ = limit( 1 , *p , 255 ) ;
312 Table(
int q ,
int fudge )
316 m_key = key( q , fudge ) ;
317 make_table( q , std::back_inserter(m_data) , table_erratum ) ;
319 else if( fudge == 1 )
321 m_key = key( q , fudge ) ;
322 make_table( q , std::back_inserter(m_data) , table_rfc ) ;
326 G_ASSERT( fudge == 2 ) ;
327 m_key = key( 0 , fudge ) ;
328 make_table( std::back_inserter(m_data) , table_x ) ;
331 const unsigned char * p()
const
335 static int key(
int q ,
int fudge )
337 if( fudge == 2 ) q = 0 ;
338 return q + fudge*1000 ;
345 private: std::vector<unsigned char> m_data ;
349 explicit Match(
int k ) : m_k(k) {}
350 bool operator()(
const Table & t )
const
352 return m_k == t.key() ;
358 static const unsigned char * table(
int q ,
int fudge )
360 static std::vector<Table> tables ;
361 std::vector<Table>::iterator p = std::find_if( tables.begin() , tables.end() , Match(Table::key(q,fudge)) ) ;
362 if( p == tables.end() )
364 tables.push_back( Table(q,fudge) ) ;
365 return tables.back().p() ;
373 static const unsigned char * luma_table(
int q ,
int fudge )
375 return table( q , fudge ) ;
378 static const unsigned char * chroma_table(
int q ,
int fudge )
380 return table(q,fudge) + 64 ;
385 static const unsigned char lum_dc_codelens[] = {
386 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
389 static const unsigned char lum_dc_symbols[] = {
390 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
393 static const unsigned char lum_ac_codelens[] = {
394 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d,
397 static const unsigned char lum_ac_symbols[] = {
398 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
399 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
400 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
401 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
402 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
403 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
404 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
405 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
406 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
407 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
408 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
409 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
410 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
411 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
412 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
413 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
414 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
415 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
416 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
417 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
421 static const unsigned char chm_dc_codelens[] = {
422 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
425 static const unsigned char chm_dc_symbols[] = {
426 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
429 static const unsigned char chm_ac_codelens[] = {
430 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77,
433 static const unsigned char chm_ac_symbols[] = {
434 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
435 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
436 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
437 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
438 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
439 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
440 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
441 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
442 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
443 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
444 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
445 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
446 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
447 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
448 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
449 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
450 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
451 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
452 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
453 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
457 template <
typename T>
458 static T make_quant_header( T p ,
const unsigned char * qt ,
int table_no )
465 p = std::copy( qt , qt+64 , p ) ;
469 template <
typename T>
470 static T make_huffman_header( T p ,
const unsigned char * codelens ,
int ncodelens ,
471 const unsigned char * symbols ,
int nsymbols ,
int table_no ,
int table_class )
473 G_ASSERT( ( 3 + ncodelens + nsymbols ) <= 255 ) ;
478 *p++ = 3 + ncodelens + nsymbols ;
479 *p++ = ( table_class << 4 ) | table_no ;
480 p = std::copy( codelens , codelens+ncodelens , p ) ;
481 p = std::copy( symbols , symbols+nsymbols , p ) ;
485 template <
typename T>
486 static T make_dri_header( T p ,
unsigned int dri )
500 template <
typename T>
501 static T make_app0( T p )
524 unsigned char comp(
unsigned char n )
531 template <
typename T>
532 static T make_headers( T p ,
unsigned int type ,
unsigned int w_pixels ,
unsigned int h_pixels ,
const unsigned char * lqt ,
533 const unsigned char * cqt ,
unsigned int dri )
540 p = make_quant_header( p , lqt , 0 ) ;
541 p = make_quant_header( p , cqt , 1 ) ;
542 p = make_dri_header( p , dri ) ;
549 *p++ = h_pixels >> 8 ;
551 *p++ = w_pixels >> 8 ;
555 *p++ = type == 0U ? 0x21 : 0x22 ;
564 p = make_huffman_header( p , lum_dc_codelens,
sizeof(lum_dc_codelens), lum_dc_symbols,
sizeof(lum_dc_symbols), 0, 0 ) ;
565 p = make_huffman_header( p , lum_ac_codelens,
sizeof(lum_ac_codelens), lum_ac_symbols,
sizeof(lum_ac_symbols), 0, 1 ) ;
566 p = make_huffman_header( p , chm_dc_codelens,
sizeof(chm_dc_codelens), chm_dc_symbols,
sizeof(chm_dc_symbols), 1, 0 ) ;
567 p = make_huffman_header( p , chm_ac_codelens,
sizeof(chm_ac_codelens), chm_ac_symbols,
sizeof(chm_ac_symbols), 1, 1 ) ;
591 return make_headers( out , packet.
type_base() , packet.
dx() , packet.
dy() ,
592 luma_table(packet.
q(),fudge) , chroma_table(packet.
q(),fudge) , packet.
ri() ) ;
std::string reason() const
Returns the reason if in-valid().
unsigned int dx() const
Returns the image width in pixels, not MCUs, ie. including the x8.
An RTP payload parser for the jpeg payload type.
unsigned long fo() const
Returns the fragment offset.
unsigned int type_base() const
Returns type() with the special bit reset.
bool type_has_restart_markers() const
Returns true if type() indicates the presence of a restart marker header.
unsigned int payloadOffset() const
Returns payload().offset.
unsigned int ts() const
Returns the "type-specific" value.
bool q_is_special() const
Returns true if q() indicates in-band quantisation tables.
std::string str() const
Returns a summary of the packet header for debugging purposes.
static iterator_t generateHeader(iterator_t out, const RtpJpegPacket &, int fudge=0)
Generates the start of a JFIF buffer; the rest of the JFIF buffer is a simple copy of all the payload...
A descriptor for the payload within an RTP JPEG packet.
unsigned int ri() const
Returns the restart interval (JFIF DRI).
bool type_is_dynamic() const
Returns true if type() indicates that the type is defined out-of-band by the session setup process...
RtpJpegPacket(const char *begin, const char *end)
Constructor taking in an RTP payload with Payload Type of JPEG/90000.
static size_t smallest()
The smallest parsable packet.
const char * payloadBegin() const
Returns payload().begin.
bool valid() const
Returns true if a valid packet.
const char * payloadEnd() const
Returns payload().end.
unsigned int q() const
Returns the Q value.
Payload payload() const
Returns the JPEG entropy-coded image scan data, using pointers into the buffer that was passed in to ...
unsigned int rc() const
Returns the restart count.
size_t payloadSize() const
Returns payload().size.
unsigned int dy() const
Returns the image height in pixels, not MCUs, ie. including the x8.
unsigned int type() const
Returns the type.