VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvavcreader.h
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 /// \file gvavcreader.h
19 ///
20 
21 #ifndef GV_AVC_READER__H
22 #define GV_AVC_READER__H
23 
24 #include "gdef.h"
25 #include "gravc.h"
26 #include "grcolourspace.h"
27 #include "grimagedata.h"
28 #include "grimagetype.h"
29 
30 namespace Gv
31 {
32  class AvcReaderStream ;
33  class AvcReaderStreamImp ;
34  class AvcReader ;
35 }
36 
37 /// \class Gv::AvcReaderStream
38 /// Holds state for an AVC (aka H.264) decoder. Each image is decoded
39 /// separately by Gr::AvcReader, but state for a sequence of images is
40 /// managed by this class.
41 ///
43 {
44 public:
45  AvcReaderStream() ;
46  ///< Default constructor. Since no configuration is supplied
47  ///< the decoding will only work once the the required SPS
48  ///< and PPS NALUs have been supplied.
49 
50  explicit AvcReaderStream( const Gr::Avc::Configuration & avcc ) ;
51  ///< Constructor taking a configuration object.
52 
54  ///< Destructor.
55 
56  int dx() const ;
57  ///< Returns the image width as indicated by the first SPS structure,
58  ///< or zero if default constructed.
59 
60  int dy() const ;
61  ///< Returns the image height as indicated by the first SPS structure,
62  ///< or zero if default constructed.
63 
64 private:
65  AvcReaderStream( const AvcReaderStream & ) ;
66  void operator=( const AvcReaderStream & ) ;
67 
68 private:
69  friend class AvcReader ;
70  AvcReaderStreamImp * m_imp ;
71 } ;
72 
73 /// \class Gv::AvcReader
74 /// A decoder for an AVC (aka H.264) video packet.
75 ///
76 /// The class name alludes to the Gr::JpegReader and Gr::PngReader classes,
77 /// which have a similar interface.
78 ///
80 {
81 public:
82  AvcReader( AvcReaderStream & stream , const char * p , size_t n ) ;
83  ///< Constructor taking a complete NALU data buffer, including
84  ///< a leading four-byte 00-00-00-01 start code.
85 
86  AvcReader( AvcReaderStream & stream , const unsigned char * p , size_t n ) ;
87  ///< Constructor overload for unsigned char.
88 
89  static bool available() ;
90  ///< Returns true if the decoder library is built in.
91 
92  bool valid() const ;
93  ///< Returns true if a picture was decoded successfully.
94 
95  int dx() const ;
96  ///< Returns the image width.
97 
98  int dy() const ;
99  ///< Returns the image height.
100 
101  bool keyframe() const ;
102  ///< Returns true if a key frame.
103 
104  unsigned char r( int x , int y ) const ;
105  ///< Returns a pixel red value.
106 
107  unsigned char g( int x , int y ) const ;
108  ///< Returns a pixel green value.
109 
110  unsigned char b( int x , int y ) const ;
111  ///< Returns a pixel blue value.
112 
113  unsigned char luma( int x , int y ) const ;
114  ///< Returns a pixel luma value.
115 
116  unsigned int rgb( int x , int y ) const ;
117  ///< Returns the three rgb values packed into one integer.
118 
119  Gr::ImageType fill( std::vector<char> & , int scale = 1 , bool monochrome = false ) ;
120  ///< Fills the supplied buffer with RGB or greyscale image data
121  ///< and returns the raw image type.
122 
123  bool simple() const ;
124  ///< Returns true if the data format is simple enough for the
125  ///< optimised iterator, Gv::AvcReader::SimpleIterator.
126 
127 private:
128  friend struct Iterator ;
129  friend struct SimpleIterator ;
130  AvcReader( const AvcReader & ) ;
131  void operator=( const AvcReader & ) ;
132  void init( const unsigned char * p , size_t n ) ;
133  unsigned char value( int c , int x , int y ) const ;
134  unsigned char value( int c , size_t offset ) const ;
135  unsigned int fullvalue( int c , int x , int y ) const ;
136  unsigned int fullvalue( int c , size_t offset ) const ;
137  size_t offset( int c , int x , int y ) const ;
138 
139 public:
140  struct Component /// Describes one plane of a Gv::AvcReader image, and points to its data.
141  {
142  const unsigned char * data ;
143  size_t offset ; // fixed offset in data
144  size_t linesize ; // offset for each new line
145  size_t step ; // offset for next horizontal pixel
146  unsigned short depth ; // number of bits, eg. 8
147  unsigned int mask ; // mask for 'depth' bits
148  unsigned short shift ; // right-shift to get the value
149  bool eightbit ; // bytes rather than words
150  unsigned short x_shift ; // chroma bit-shift for x (also Data.m_x_shift)
151  unsigned short y_shift ; // chroma bit-shift for y (also Data.m_y_shift)
152  //
153  unsigned int fullvalue( const unsigned char * p , bool be ) const ;
154  unsigned char value( const unsigned char * p , bool be ) const ;
155  unsigned char simplevalue( const unsigned char * p ) const ;
156  size_t rowoffset( int y ) const ;
157  size_t xoffset( int x ) const ;
158  size_t simplexoffset( int x ) const ;
159  bool simple() const ;
160  } ;
161  struct Data /// Describes a Gv::AvcReader image, and points to its data via up to four Components.
162  {
163  int m_dx ;
164  int m_dy ;
165  bool m_rgb ;
166  bool m_big_endian ;
167  unsigned short m_x_shift ; // chroma bit-shift for x
168  unsigned short m_y_shift ; // chroma bit-shift for y
169  Component m_component[4] ;
170  } ;
171  struct Iterator /// A row iterator for Gv::AvcReader providing r/g/b or y/u/v across a row.
172  {
173  Iterator( const AvcReader & , int y , int scale ) ;
174  unsigned char value0() const ;
175  unsigned char value1() const ;
176  unsigned char value2() const ;
177  unsigned char r() const ;
178  unsigned char g() const ;
179  unsigned char b() const ;
180  unsigned char luma() const ;
181  void operator++() ;
182  //
183  int m_x ;
184  int m_y ;
185  int m_scale ;
186  const Component & m_c0 ;
187  const Component & m_c1 ;
188  const Component & m_c2 ;
189  const unsigned char * m_rp0 ;
190  const unsigned char * m_rp1 ;
191  const unsigned char * m_rp2 ;
192  bool m_data_rgb ;
193  size_t m_data_big_endian ;
194  } ;
195  struct SimpleIterator /// An optimised row iterator for Gv::AvcReader when simple().
196  {
197  SimpleIterator( const AvcReader & , int y , int scale ) ;
198  unsigned char value0() const ;
199  unsigned char value1() const ;
200  unsigned char value2() const ;
201  unsigned char r() const ;
202  unsigned char g() const ;
203  unsigned char b() const ;
204  unsigned char luma() const ;
205  void operator++() ;
206  //
207  int m_x ;
208  int m_y ;
209  int m_scale ;
210  const Component & m_c0 ;
211  const Component & m_c1 ;
212  const Component & m_c2 ;
213  const unsigned char * m_rp0 ;
214  const unsigned char * m_rp1 ;
215  const unsigned char * m_rp2 ;
216  bool m_data_rgb ;
217  } ;
218 
219 private:
220  AvcReaderStream & m_stream ;
221  Data m_data ;
222 } ;
223 
224 inline
225 Gv::AvcReader::AvcReader( AvcReaderStream & stream , const char * p , size_t n ) :
226  m_stream(stream)
227 {
228  init( reinterpret_cast<const unsigned char*>(p) , n ) ;
229 }
230 
231 inline
232 Gv::AvcReader::AvcReader( AvcReaderStream & stream , const unsigned char * p , size_t n ) :
233  m_stream(stream)
234 {
235  init( p , n ) ;
236 }
237 
238 inline
240 {
241  return
242  m_data.m_component[0].data != nullptr &&
243  m_data.m_component[1].data != nullptr &&
244  m_data.m_component[2].data != nullptr ;
245 }
246 
247 inline
249 {
250  return
251  m_data.m_component[0].simple() &&
252  m_data.m_component[1].simple() &&
253  m_data.m_component[2].simple() ;
254 }
255 
256 inline
257 int Gv::AvcReader::dx() const
258 {
259  return m_data.m_dx ;
260 }
261 
262 inline
263 int Gv::AvcReader::dy() const
264 {
265  return m_data.m_dy ;
266 }
267 
268 inline
269 unsigned char Gv::AvcReader::luma( int x , int y ) const
270 {
271  return m_data.m_rgb ? Gr::ColourSpace::y_int( value(0,x,y) , value(1,x,y) , value(2,x,y) ) : value(0,x,y) ;
272 }
273 
274 inline
275 unsigned int Gv::AvcReader::fullvalue( int c , size_t offset ) const
276 {
277  // cf. Gv::CaptureBuffer::value()
278  const Component & comp = m_data.m_component[c] ;
279  return comp.fullvalue( comp.data+offset , m_data.m_big_endian ) ;
280 }
281 
282 inline
283 unsigned int Gv::AvcReader::Component::fullvalue( const unsigned char * p , bool big_endian ) const
284 {
285  unsigned int v = *p ;
286  if( !eightbit )
287  {
288  unsigned int v2 = p[1] ;
289  v = big_endian ? ((v<<8)|v2) : ((v2<<8)|v) ;
290  }
291  return ( v >> shift ) & mask ;
292 }
293 
294 inline
295 unsigned char Gv::AvcReader::Component::value( const unsigned char * p , bool big_endian ) const
296 {
297  unsigned int v = fullvalue( p , big_endian ) ;
298  if( depth <= 8U )
299  v <<= (8U-depth) ;
300  else
301  v >>= (depth-8U) ;
302  return v ;
303 }
304 
305 inline
306 bool Gv::AvcReader::Component::simple() const
307 {
308  return eightbit && shift == 0 && depth == 8 && step == 1 && ( x_shift == 0 || x_shift == 1 ) ;
309 }
310 
311 inline
312 unsigned char Gv::AvcReader::Component::simplevalue( const unsigned char * p ) const
313 {
314  //G_ASSERT( eightbit && shift==0 && mask=0xff && depth==8 ) ;
315  return *p ;
316 }
317 
318 inline
319 size_t Gv::AvcReader::Component::rowoffset( int y ) const
320 {
321  size_t yy = static_cast<size_t>(y) ;
322  yy >>= y_shift ;
323  return yy*linesize + offset ;
324 }
325 
326 inline
327 size_t Gv::AvcReader::Component::xoffset( int x ) const
328 {
329  size_t xx = static_cast<size_t>(x) ;
330  xx >>= x_shift ;
331  if( step <= 8 )
332  {
333  switch( step )
334  {
335  case 8: xx += xx ;
336  case 7: xx += xx ;
337  case 6: xx += xx ;
338  case 5: xx += xx ;
339  case 4: xx += xx ;
340  case 3: xx += xx ;
341  case 2: xx += xx ;
342  }
343  return xx ;
344  }
345  else
346  {
347  return xx*step ;
348  }
349 }
350 
351 inline
352 size_t Gv::AvcReader::Component::simplexoffset( int x ) const
353 {
354  //G_ASSERT( step == 1 ) ;
355  //G_ASSERT( x_shift == 0 || x_shift == 1 ) ;
356  return x_shift == 0 ? static_cast<size_t>(x) : static_cast<size_t>(x/2) ;
357 }
358 
359 inline
360 size_t Gv::AvcReader::offset( int c , int x , int y ) const
361 {
362  const Component & comp = m_data.m_component[c] ;
363  return comp.rowoffset(y) + comp.xoffset(x) ;
364 }
365 
366 inline
367 unsigned int Gv::AvcReader::fullvalue( int c , int x , int y ) const
368 {
369  return fullvalue( c , offset(c,x,y) ) ;
370 }
371 
372 inline
373 unsigned char Gv::AvcReader::value( int c , size_t offset ) const
374 {
375  const Component & comp = m_data.m_component[c] ;
376  return comp.value( comp.data+offset , m_data.m_big_endian ) ;
377 }
378 
379 inline
380 unsigned char Gv::AvcReader::value( int c , int x , int y ) const
381 {
382  const Component & comp = m_data.m_component[c] ;
383  unsigned int v = fullvalue( c , x , y ) ;
384  if( comp.depth <= 8U )
385  v <<= (8U-comp.depth) ;
386  else
387  v >>= (comp.depth-8U) ;
388  return v ;
389 }
390 
391 inline
392 unsigned char Gv::AvcReader::r( int x , int y ) const
393 {
394  return m_data.m_rgb ? value(0,x,y) : Gr::ColourSpace::r_int( value(0,x,y) , value(1,x,y) , value(2,x,y) ) ;
395 }
396 
397 inline
398 unsigned char Gv::AvcReader::g( int x , int y ) const
399 {
400  return m_data.m_rgb ? value(1,x,y) : Gr::ColourSpace::g_int( value(0,x,y) , value(1,x,y) , value(2,x,y) ) ;
401 }
402 
403 inline
404 unsigned char Gv::AvcReader::b( int x , int y ) const
405 {
406  return m_data.m_rgb ? value(2,x,y) : Gr::ColourSpace::b_int( value(0,x,y) , value(1,x,y) , value(2,x,y) ) ;
407 }
408 
409 inline
410 unsigned int Gv::AvcReader::rgb( int x , int y ) const
411 {
412  return
413  ( static_cast<unsigned int>(r(x,y)) << 16 ) |
414  ( static_cast<unsigned int>(g(x,y)) << 8 ) |
415  ( static_cast<unsigned int>(b(x,y)) ) ;
416 }
417 
418 inline
419 Gv::AvcReader::Iterator::Iterator( const AvcReader & reader , int y , int scale ) :
420  m_x(0) ,
421  m_y(y) ,
422  m_scale(scale) ,
423  m_c0(reader.m_data.m_component[0]) ,
424  m_c1(reader.m_data.m_component[1]) ,
425  m_c2(reader.m_data.m_component[2]) ,
426  m_rp0(m_c0.data+m_c0.rowoffset(y)) ,
427  m_rp1(m_c1.data+m_c1.rowoffset(y)) ,
428  m_rp2(m_c2.data+m_c2.rowoffset(y)) ,
429  m_data_rgb(reader.m_data.m_rgb) ,
430  m_data_big_endian(reader.m_data.m_big_endian)
431 {
432 }
433 
434 inline
435 Gv::AvcReader::SimpleIterator::SimpleIterator( const AvcReader & reader , int y , int scale ) :
436  m_x(0) ,
437  m_y(y) ,
438  m_scale(scale) ,
439  m_c0(reader.m_data.m_component[0]) ,
440  m_c1(reader.m_data.m_component[1]) ,
441  m_c2(reader.m_data.m_component[2]) ,
442  m_rp0(m_c0.data+m_c0.rowoffset(y)) ,
443  m_rp1(m_c1.data+m_c1.rowoffset(y)) ,
444  m_rp2(m_c2.data+m_c2.rowoffset(y)) ,
445  m_data_rgb(reader.m_data.m_rgb)
446 {
447 }
448 
449 inline
450 unsigned char Gv::AvcReader::Iterator::value0() const
451 {
452  return m_c0.value( m_rp0+m_c0.xoffset(m_x) , m_data_big_endian ) ;
453 }
454 
455 inline
456 unsigned char Gv::AvcReader::SimpleIterator::value0() const
457 {
458  return m_c0.simplevalue( m_rp0+m_c0.simplexoffset(m_x) ) ;
459 }
460 
461 inline
462 unsigned char Gv::AvcReader::Iterator::value1() const
463 {
464  return m_c1.value( m_rp1+m_c1.xoffset(m_x) , m_data_big_endian ) ;
465 }
466 
467 inline
468 unsigned char Gv::AvcReader::SimpleIterator::value1() const
469 {
470  return m_c1.simplevalue( m_rp1+m_c1.simplexoffset(m_x) ) ;
471 }
472 
473 inline
474 unsigned char Gv::AvcReader::Iterator::value2() const
475 {
476  return m_c2.value( m_rp2+m_c2.xoffset(m_x) , m_data_big_endian ) ;
477 }
478 
479 inline
480 unsigned char Gv::AvcReader::SimpleIterator::value2() const
481 {
482  return m_c2.simplevalue( m_rp2+m_c2.simplexoffset(m_x) ) ;
483 }
484 
485 inline
486 unsigned char Gv::AvcReader::Iterator::r() const
487 {
488  return m_data_rgb ? value0() : Gr::ColourSpace::r_int( value0() , value1() , value2() ) ;
489 }
490 
491 inline
492 unsigned char Gv::AvcReader::SimpleIterator::r() const
493 {
494  return m_data_rgb ? value0() : Gr::ColourSpace::r_int( value0() , value1() , value2() ) ;
495 }
496 
497 inline
498 unsigned char Gv::AvcReader::Iterator::g() const
499 {
500  return m_data_rgb ? value1() : Gr::ColourSpace::g_int( value0() , value1() , value2() ) ;
501 }
502 
503 inline
504 unsigned char Gv::AvcReader::SimpleIterator::g() const
505 {
506  return m_data_rgb ? value1() : Gr::ColourSpace::g_int( value0() , value1() , value2() ) ;
507 }
508 
509 inline
510 unsigned char Gv::AvcReader::Iterator::b() const
511 {
512  return m_data_rgb ? value2() : Gr::ColourSpace::b_int( value0() , value1() , value2() ) ;
513 }
514 
515 inline
516 unsigned char Gv::AvcReader::SimpleIterator::b() const
517 {
518  return m_data_rgb ? value2() : Gr::ColourSpace::b_int( value0() , value1() , value2() ) ;
519 }
520 
521 inline
522 unsigned char Gv::AvcReader::Iterator::luma() const
523 {
524  return m_data_rgb ? Gr::ColourSpace::y_int( value0() , value1() , value2() ) : value0() ;
525 }
526 
527 inline
528 unsigned char Gv::AvcReader::SimpleIterator::luma() const
529 {
530  return m_data_rgb ? Gr::ColourSpace::y_int( value0() , value1() , value2() ) : value0() ;
531 }
532 
533 inline
534 void Gv::AvcReader::Iterator::operator++()
535 {
536  m_x += m_scale ;
537 }
538 
539 inline
540 void Gv::AvcReader::SimpleIterator::operator++()
541 {
542  m_x += m_scale ;
543 }
544 
545 #endif
static bool available()
Returns true if the decoder library is built in.
bool simple() const
Returns true if the data format is simple enough for the optimised iterator, Gv::AvcReader::SimpleIte...
Definition: gvavcreader.h:248
A decoder for an AVC (aka H.264) video packet.
Definition: gvavcreader.h:79
int dx() const
Returns the image width.
Definition: gvavcreader.h:257
unsigned char b_int(unsigned char y, unsigned char u, unsigned char) g__noexcept
A fast conversion from yuv to b.
unsigned char luma(int x, int y) const
Returns a pixel luma value.
Definition: gvavcreader.h:269
bool valid() const
Returns true if a picture was decoded successfully.
Definition: gvavcreader.h:239
Contains AVC configuration parameters, initialised from an "avcC" file segment or from an SDP "fmtp" ...
Definition: gravc.h:93
An encapsulation of image type, including width, height and number of channels, with support for a st...
Definition: grimagetype.h:43
unsigned char g(int x, int y) const
Returns a pixel green value.
Definition: gvavcreader.h:398
Describes one plane of a Gv::AvcReader image, and points to its data.
Definition: gvavcreader.h:140
int dx() const
Returns the image width as indicated by the first SPS structure, or zero if default constructed...
int dy() const
Returns the image height.
Definition: gvavcreader.h:263
~AvcReaderStream()
Destructor.
int dy() const
Returns the image height as indicated by the first SPS structure, or zero if default constructed...
unsigned char g_int(unsigned char y, unsigned char u, unsigned char v) g__noexcept
A fast conversion from yuv to g.
unsigned char b(int x, int y) const
Returns a pixel blue value.
Definition: gvavcreader.h:404
AvcReaderStream()
Default constructor.
bool keyframe() const
Returns true if a key frame.
unsigned char r(int x, int y) const
Returns a pixel red value.
Definition: gvavcreader.h:392
unsigned char r_int(unsigned char y, unsigned char, unsigned char v) g__noexcept
A fast conversion from yuv to r.
A private pimple class for Gv::AvcReaderStream, holding AVCode, AVCodecContext and AVFrame libav obje...
AvcReader(AvcReaderStream &stream, const char *p, size_t n)
Constructor taking a complete NALU data buffer, including a leading four-byte 00-00-00-01 start code...
Definition: gvavcreader.h:225
unsigned char y_int(unsigned char r, unsigned char g, unsigned char b)
A fast conversion from rgb to y.
Holds state for an AVC (aka H.264) decoder.
Definition: gvavcreader.h:42
A row iterator for Gv::AvcReader providing r/g/b or y/u/v across a row.
Definition: gvavcreader.h:171
unsigned int rgb(int x, int y) const
Returns the three rgb values packed into one integer.
Definition: gvavcreader.h:410
Gr::ImageType fill(std::vector< char > &, int scale=1, bool monochrome=false)
Fills the supplied buffer with RGB or greyscale image data and returns the raw image type...
Describes a Gv::AvcReader image, and points to its data via up to four Components.
Definition: gvavcreader.h:161
An optimised row iterator for Gv::AvcReader when simple().
Definition: gvavcreader.h:195