VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvrtpjpegpacket.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gvrtpjpegpacket.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gvrtpjpegpacket.h"
23 #include "gassert.h"
24 #include "ghexdump.h"
25 #include <algorithm>
26 #include <stdexcept>
27 
29 {
30  return 8U ;
31 }
32 
33 Gv::RtpJpegPacket::RtpJpegPacket( const char * begin , const char * end ) :
34  m_p(begin) ,
35  m_n(end-begin)
36 {
37  G_ASSERT( m_n >= smallest() ) ;
38 
39  if( payloadOffset() > m_n )
40  m_reason = "invalid payload offset" ;
41 
42  // we do not support types defined at session-setup
43  if( type_is_dynamic() )
44  m_reason = "dynamic type field" ;
45 
46  // in practice only two types are defined by RFC 2435 (although the older RFC 2035 defines more)
47  if( type_base() != 0U && type_base() != 1U )
48  m_reason = "unexpected type field" ;
49 
50  // TODO support in-band quantisation tables -- easy to do, but difficult to test
51  if( q_is_special() )
52  m_reason = "unexpected quantisation field: support for in-band tables not implemented" ;
53 
54  // (for types 0 and 1 the type-specific field is used for interlacing info)
55  if( ts() != 0 )
56  G_WARNING_ONCE( "ignoring rtp jpeg interlacing" ) ; // TODO deal with interlacing
57 }
58 
60 {
61  return m_reason.empty() ;
62 }
63 
64 std::string Gv::RtpJpegPacket::reason() const
65 {
66  return m_reason ;
67 }
68 
69 unsigned int Gv::RtpJpegPacket::ri() const
70 {
71  if( type_has_restart_markers() )
72  return make_word( &m_p[8U] ) ;
73  else
74  return 0U ;
75 }
76 
77 unsigned int Gv::RtpJpegPacket::rc() const
78 {
79  if( type_has_restart_markers() )
80  return make_word( &m_p[10U] ) & 0x3fff ;
81  else
82  return 0U ;
83 }
84 
85 std::string Gv::RtpJpegPacket::str() const
86 {
87  std::ostringstream ss ;
88  ss << "ts=" << ts() << " fo=" << fo() << " t=" << type() << " q=" << q() << " dx=" << dx() << " dy=" << dy() << " ri=" << ri() << " rc=" << rc() ;
89  return ss.str() ;
90 }
91 
92 unsigned int Gv::RtpJpegPacket::ts() const
93 {
94  const unsigned int p0 = static_cast<unsigned char>(m_p[0]) ;
95  return p0 ;
96 }
97 
98 unsigned long Gv::RtpJpegPacket::fo() const
99 {
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 ) ;
104 }
105 
106 unsigned int Gv::RtpJpegPacket::type() const
107 {
108  const unsigned int p4 = static_cast<unsigned char>(m_p[4]) ;
109  return p4 ;
110 }
111 
113 {
114  return type() >= 128U ; // ie. defined at session setup
115 }
116 
118 {
119  return type() >= 64U && type() <= 127U ; // ie. with restart marker header
120 }
121 
122 unsigned int Gv::RtpJpegPacket::type_base() const
123 {
124  return type_has_restart_markers() ? (type()-64U) : type() ;
125 }
126 
127 unsigned int Gv::RtpJpegPacket::q() const
128 {
129  const unsigned int p5 = static_cast<unsigned char>(m_p[5]) ;
130  return p5 ;
131 }
132 
134 {
135  return !!( q() & 0x80 ) ; // ie. with quantisation tables
136 }
137 
138 unsigned int Gv::RtpJpegPacket::dx() const
139 {
140  const unsigned int p6 = static_cast<unsigned char>(m_p[6]) ;
141  return p6 * 8U ;
142 }
143 
144 unsigned int Gv::RtpJpegPacket::dy() const
145 {
146  const unsigned int p7 = static_cast<unsigned char>(m_p[7]) ;
147  return p7 * 8U ;
148 }
149 
150 unsigned int Gv::RtpJpegPacket::make_word( const char * p )
151 {
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 ;
155 }
156 
157 unsigned long Gv::RtpJpegPacket::make_dword( unsigned long c3 , unsigned long c2 , unsigned long c1 , unsigned long c0 )
158 {
159  return ( c3 << 24 ) | ( c2 << 16 ) | ( c1 << 8 ) | ( c0 << 0 ) ;
160 }
161 
163 {
164  Payload p ;
165  p.offset = payloadOffset() ;
166  p.size = payloadSize() ;
167  p.begin = payloadBegin() ;
168  p.end = payloadEnd() ;
169  return p ;
170 }
171 
173 {
174  size_t header_size = 8U ;
175  if( type_has_restart_markers() )
176  {
177  // allow for a Restart Marker header -- see sections 3.1.3 and 3.1.7
178  header_size += 4U ;
179  }
180  if( q_is_special() && fo() == 0UL )
181  {
182  // allow for a Quantization Table header and table data -- see
183  // sections 3.1.4 and 3.1.8
184  unsigned int qtl = make_word( &m_p[header_size+2U] ) ;
185  header_size += ( 4U + qtl ) ;
186  }
187  return header_size ;
188 }
189 
191 {
192  G_ASSERT( payloadOffset() <= m_n ) ;
193  return m_n - payloadOffset() ;
194 }
195 
197 {
198  return m_p + payloadOffset() ;
199 }
200 
201 const char * Gv::RtpJpegPacket::payloadEnd() const
202 {
203  return m_p + m_n ;
204 }
205 
206 // ==
207 
208 // From RFC 2435 Appendix A...
209 
210 static const int table_rfc[128] =
211 {
212  // luma
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,
221  // chroma
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
230 } ;
231 
232 // see rejected erratum 4094
233 
234 static const int table_erratum[128] =
235 {
236  // luma
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 ,
245  // chroma
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
254 } ;
255 
256 static const int table_x[128] =
257 {
258  // luma
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,
267  // chroma
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,
276 } ;
277 
278 template <typename T>
279 inline
280 T limit( T min , T value , T max )
281 {
282  return value < min ? min : ( value > max ? max : value ) ;
283 }
284 
285 template <typename Titerator>
286 static void make_table( int q_in , Titerator out , const int * p , const int * end = nullptr )
287 {
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 )
292  {
293  int qq = ((*p) * q + 50) / 100 ;
294  *out++ = limit( 1 , qq , 255 ) ;
295  }
296 }
297 
298 template <typename Titerator>
299 static void make_table( Titerator out , const int * p , const int * end = nullptr )
300 {
301  if( end == nullptr ) end = p + 128 ;
302  for( ; p != end ; ++p )
303  {
304  *out++ = limit( 1 , *p , 255 ) ;
305  }
306 }
307 
308 namespace
309 {
310  struct Table
311  {
312  Table( int q , int fudge )
313  {
314  if( fudge == 0 ) // erratum table
315  {
316  m_key = key( q , fudge ) ;
317  make_table( q , std::back_inserter(m_data) , table_erratum ) ;
318  }
319  else if( fudge == 1 ) // rfc table
320  {
321  m_key = key( q , fudge ) ;
322  make_table( q , std::back_inserter(m_data) , table_rfc ) ;
323  }
324  else // ad-hoc pre-scaled table
325  {
326  G_ASSERT( fudge == 2 ) ;
327  m_key = key( 0 , fudge ) ; // ignore q
328  make_table( std::back_inserter(m_data) , table_x ) ;
329  }
330  }
331  const unsigned char * p() const
332  {
333  return &m_data[0] ;
334  }
335  static int key( int q , int fudge )
336  {
337  if( fudge == 2 ) q = 0 ;
338  return q + fudge*1000 ;
339  }
340  int key() const
341  {
342  return m_key ;
343  }
344  private: int m_key ;
345  private: std::vector<unsigned char> m_data ;
346  } ;
347  struct Match
348  {
349  explicit Match( int k ) : m_k(k) {}
350  bool operator()( const Table & t ) const
351  {
352  return m_k == t.key() ;
353  }
354  int m_k ;
355  } ;
356 }
357 
358 static const unsigned char * table( int q , int fudge )
359 {
360  static std::vector<Table> tables ; // cache, keyed by q and fudge factor
361  std::vector<Table>::iterator p = std::find_if( tables.begin() , tables.end() , Match(Table::key(q,fudge)) ) ;
362  if( p == tables.end() )
363  {
364  tables.push_back( Table(q,fudge) ) ;
365  return tables.back().p() ;
366  }
367  else
368  {
369  return (*p).p() ;
370  }
371 }
372 
373 static const unsigned char * luma_table( int q , int fudge )
374 {
375  return table( q , fudge ) ;
376 }
377 
378 static const unsigned char * chroma_table( int q , int fudge )
379 {
380  return table(q,fudge) + 64 ;
381 }
382 
383 // From RFC 2435 Appendix B...
384 
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,
387 };
388 
389 static const unsigned char lum_dc_symbols[] = {
390  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
391 };
392 
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,
395 };
396 
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,
418  0xf9, 0xfa,
419 };
420 
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,
423 };
424 
425 static const unsigned char chm_dc_symbols[] = {
426  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
427 };
428 
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,
431 };
432 
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,
454  0xf9, 0xfa,
455 };
456 
457 template <typename T>
458 static T make_quant_header( T p , const unsigned char * qt , int table_no )
459 {
460  *p++ = 0xff ;
461  *p++ = 0xdb ; // DQT
462  *p++ = 0 ; // length msb
463  *p++ = 67 ; // length lsb
464  *p++ = table_no ;
465  p = std::copy( qt , qt+64 , p ) ;
466  return p ;
467 }
468 
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 )
472 {
473  G_ASSERT( ( 3 + ncodelens + nsymbols ) <= 255 ) ;
474 
475  *p++ = 0xff ;
476  *p++ = 0xc4 ; // DHT
477  *p++ = 0 ; // length msb
478  *p++ = 3 + ncodelens + nsymbols ; // length lsb
479  *p++ = ( table_class << 4 ) | table_no ;
480  p = std::copy( codelens , codelens+ncodelens , p ) ;
481  p = std::copy( symbols , symbols+nsymbols , p ) ;
482  return p ;
483 }
484 
485 template <typename T>
486 static T make_dri_header( T p , unsigned int dri )
487 {
488  if( dri != 0U )
489  {
490  *p++ = 0xff ;
491  *p++ = 0xdd ; // DRI
492  *p++ = 0x0 ; // length msb
493  *p++ = 4 ; // length lsb
494  *p++ = dri >> 8 ; // dri msb
495  *p++ = dri & 0xff ; // dri lsb
496  }
497  return p ;
498 }
499 
500 template <typename T>
501 static T make_app0( T p )
502 {
503  *p++ = 0xff ;
504  *p++ = 0xe0 ; // APP0
505  *p++ = 0 ; // length msb
506  *p++ = 16 ; // length lsb
507  *p++ = 0x4a ; // 'J'
508  *p++ = 0x46 ; // 'F'
509  *p++ = 0x49 ; // 'I'
510  *p++ = 0x46 ; // 'F'
511  *p++ = 0 ;
512  *p++ = 0x01 ; // version major
513  *p++ = 0x02 ; // version minor
514  *p++ = 0 ; // pixel density units none
515  *p++ = 0 ; // pixel density x msb
516  *p++ = 1 ; // pixel density x lsb
517  *p++ = 0 ; // pixel density y msb
518  *p++ = 1 ; // pixel density y lsb
519  *p++ = 0 ; // thumbnail dx
520  *p++ = 0 ; // thumbnail dy
521  return p ;
522 }
523 
524 unsigned char comp( unsigned char n )
525 {
526  // component ids can be 0,1,2 or 1,2,3 or
527  // whatever -- use 1,2,3 for easy diffing
528  return n + 1U ;
529 }
530 
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 )
534 {
535  *p++ = 0xff ;
536  *p++ = 0xd8 ; // SOI
537 
538  p = make_app0( p ) ;
539 
540  p = make_quant_header( p , lqt , 0 ) ; // or use in-band tables if q_is_special()
541  p = make_quant_header( p , cqt , 1 ) ; // or use in-band tables if q_is_special()
542  p = make_dri_header( p , dri ) ;
543 
544  *p++ = 0xff ;
545  *p++ = 0xc0 ; // SOF
546  *p++ = 0 ; // length msb
547  *p++ = 17 ; // length lsb
548  *p++ = 8 ; // 8-bit precision
549  *p++ = h_pixels >> 8 ; // height msb
550  *p++ = h_pixels ; // height lsb
551  *p++ = w_pixels >> 8 ; // width msb
552  *p++ = w_pixels ; // width lsb
553  *p++ = 3 ; // number of components
554  *p++ = comp(0) ; // comp 0
555  *p++ = type == 0U ? 0x21 : 0x22 ; // hsamp=2,vsamp=1 : hsamp=2,vsamp=2
556  *p++ = 0 ; // quant table 0
557  *p++ = comp(1) ; // comp 1
558  *p++ = 0x11 ; // hsamp=1,vsamp=1
559  *p++ = 1 ; // quant table 1
560  *p++ = comp(2) ; // comp 2
561  *p++ = 0x11 ; // hsamp=1,vsamp=1
562  *p++ = 1 ; // quant table 1
563 
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 ) ;
568 
569  *p++ = 0xff ;
570  *p++ = 0xda ; // SOS
571  *p++ = 0 ; // length msb
572  *p++ = 12 ; // length lsb
573  *p++ = 3 ; // 3 components
574  *p++ = comp(0) ; // comp 0
575  *p++ = 0 ; // huffman table 0
576  *p++ = comp(1) ; // comp 1
577  *p++ = 0x11 ; // huffman table 1
578  *p++ = comp(2) ; // comp 2
579  *p++ = 0x11 ; // huffman table 1
580  *p++ = 0 ; // first DCT coeff
581  *p++ = 63 ; // last DCT coeff
582  *p++ = 0 ; // sucessive approximation
583 
584  return p ;
585 }
586 
587 // ==
588 
589 Gv::RtpJpegPacket::iterator_t Gv::RtpJpegPacket::generateHeader( iterator_t out , const RtpJpegPacket & packet , int fudge )
590 {
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() ) ;
593 }
594 
595 /// \file gvrtpjpegpacket.cpp
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.
Synopsis:
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.