VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gvrtpavcpacket.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 // gvrtpavcpacket.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gvrtpavcpacket.h"
23 #include "gravc.h"
24 #include "gassert.h"
25 #include <string>
26 #include <sstream>
27 #include <iomanip>
28 #include <stdexcept>
29 
31 {
32  return 2U ; // one NALU header byte and one of payload or FU header
33 }
34 
35 Gv::RtpAvcPacket::RtpAvcPacket( const unsigned char * begin , const unsigned char * end ) :
36  m_p(begin) ,
37  m_n(end-begin)
38 {
39  G_ASSERT( m_n >= smallest() ) ;
40 }
41 
42 Gv::RtpAvcPacket::RtpAvcPacket( const std::string & data ) :
43  m_p(reinterpret_cast<const unsigned char*>(data.data())) ,
44  m_n(data.size())
45 {
46  G_ASSERT( m_n >= smallest() ) ;
47 }
48 
49 const char * Gv::RtpAvcPacket::reason() const
50 {
51  if( (*m_p&0x80) != 0U ) return "top bit of nalu header byte is set" ;
52  if( type() == 0 ) return "nalu header byte is zero" ;
53  if( type_is_fu() && fu_start() && fu_end() ) return "conflicting fragmentation flags" ;
54  if( m_n <= payloadOffset() ) return "packet too small" ;
55  return nullptr ;
56 }
57 
59 {
60  return reason() == nullptr ;
61 }
62 
63 std::string Gv::RtpAvcPacket::str( bool more ) const
64 {
65  std::ostringstream ss ;
66  ss << "type=" << type() ;
67  if( type_is_fu() )
68  ss << " fu-start=" << fu_start() << " fu-end=" << fu_end() << " fu-type=" << fu_type() ;
69  if( more )
70  ss
71  << std::hex << std::setfill('0') << std::setw(2)
72  << " p0=0x" << static_cast<unsigned int>(m_p[0]) << " "
73  << " p1=0x" << static_cast<unsigned int>(m_p[1]) << " "
74  << " p2=0x" << static_cast<unsigned int>(m_p[2]) << " "
75  << " pf=0x" << static_cast<unsigned int>(static_cast<unsigned char>(payloadFirst()))
76  << std::dec ;
77  return ss.str() ;
78 }
79 
80 unsigned int Gv::RtpAvcPacket::type() const
81 {
82  return *m_p & 0x1f ;
83 }
84 
85 unsigned int Gv::RtpAvcPacket::nri() const
86 {
87  unsigned int n = static_cast<unsigned char>(*m_p) ;
88  return ( n >> 5 ) & 3U ;
89 }
90 
91 unsigned int Gv::RtpAvcPacket::payloadOffset() const
92 {
93  // for simple packets the first byte is the nalu-header so there
94  // is effectively no RTP-AVC header and the offset is zero --
95  // for fu packets there is an fu-indicator byte and an fu-header
96  // byte, and the nalu-type is in the lower bits of the fu-header
97  // (see payloadFirst()) so the offset is one -- however, the RTP-AVC
98  // payload for non-leading fragments must not have a nalu-header
99  // byte because they are not at the head of the nalu, so the offset
100  // is two
101 
102  // TODO more packet types
103 
104  if( type() == FU_A )
105  return fu_start() ? 1U : 2U ;
106  else if( type() == FU_B )
107  return fu_start() ? 3U : 4U ;
108  else if( type_is_single() )
109  return 0U ;
110  else
111  throw std::runtime_error( "unsupported RTP-AVC packet type" ) ;
112 }
113 
115 {
116  G_ASSERT( m_n >= payloadOffset() ) ;
117  return m_n - payloadOffset() ;
118 }
119 
120 const char * Gv::RtpAvcPacket::payloadBegin() const
121 {
122  const char * p = reinterpret_cast<const char*>( m_p ) ;
123  return p + payloadOffset() ;
124 }
125 
127 {
128  if( type_is_fu() && fu_start() )
129  return ( (m_p[0]&0xe0) | (m_p[1]&0x1f) ) ; // merge bits from fu-indicator and fu-header
130  else
131  return m_p[payloadOffset()] ;
132 }
133 
134 const char * Gv::RtpAvcPacket::payloadEnd() const
135 {
136  return payloadBegin() + payloadSize() ;
137 }
138 
140 {
141  return type() >= SINGLE_NALU_1 && type() <= SINGLE_NALU_23 ;
142 }
143 
145 {
146  return type() == FU_A || type() == FU_B ;
147 }
148 
150 {
151  G_ASSERT( m_n >= 2U ) ;
152  return !!( m_p[1] & 0x80 ) ;
153 }
154 
156 {
157  G_ASSERT( m_n >= 2U ) ;
158  return !!( m_p[1] & 0x40 ) ;
159 }
160 
161 unsigned int Gv::RtpAvcPacket::fu_type() const
162 {
163  G_ASSERT( m_n >= 2U ) ;
164  return m_p[1] & 0x1f ; // ie. inner nalu type
165 }
166 
168 {
169  return type() == 7 ; // SINGLE_NALU_7 = SPS
170 }
171 
173 {
174  return type() == 8 ; // SINGLE_NALU_8 = PPS
175 }
176 
177 /// \file gvrtpavcpacket.cpp
const char * payloadBegin() const
Returns the RTP-AVC payload pointer, but the first byte may be wrong so use payloadFirst() to overwri...
static size_t smallest()
The smallest parsable packet.
bool type_is_single() const
Returns true if type() is SINGLE_NALU_x.
unsigned int type() const
Returns the RTP-AVC packet type, matching the Type enum.
bool valid() const
Returns true if a valid packet.
bool fu_start() const
Returns true for the first FU packet in the fragmented NALU.
const char * payloadEnd() const
Returns the RTP-AVC payload end pointer.
RtpAvcPacket(const unsigned char *begin, const unsigned char *end)
Constructor taking in an RTP payload with Payload Type of H264/90000.
bool type_is_picture_parameter_set() const
Returns true if type() is SINGLE_NALU_8.
unsigned int nri() const
Returns the NALU nal_ref_idc value, in the range 0..3.
unsigned int fu_type() const
Returns the type of the fragmented NALU.
char payloadFirst() const
Returns the first RTP-AVC payload byte.
std::string str(bool more=false) const
Returns a summary of the packet header for debugging purposes.
const char * reason() const
Returns the in-valid() reason, or nullptr.
bool type_is_fu() const
Returns true if type() is FU_A or FU_B.
bool fu_end() const
Returns true for the last FU packet in the fragmented NALU.
size_t payloadSize() const
Returns the RTP-AVC payload size.
bool type_is_sequence_parameter_set() const
Returns true if type() is SINGLE_NALU_7.