-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathNALUnit.h
219 lines (180 loc) · 4.12 KB
/
NALUnit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//
// NALUnit.h
//
// Basic parsing of H.264 NAL Units
//
// Geraint Davies, March 2004
//
// Copyright (c) GDCL 2004-2008 http://www.gdcl.co.uk/license.htm
#pragma once
typedef unsigned char BYTE;
typedef unsigned long ULONG;
#ifndef NULL
#define NULL 0
#endif
class NALUnit
{
public:
NALUnit();
NALUnit(const BYTE* pStart, int len)
{
m_pStart = m_pStartCodeStart = pStart;
m_cBytes = len;
ResetBitstream();
}
virtual ~NALUnit() {}
// assignment copies a pointer into a fixed buffer managed elsewhere. We do not copy the data
NALUnit(const NALUnit& r)
{
m_pStart = r.m_pStart;
m_cBytes = r.m_cBytes;
ResetBitstream();
}
const NALUnit& operator=(const NALUnit& r)
{
m_pStart = r.m_pStart;
m_cBytes = r.m_cBytes;
ResetBitstream();
return *this;
}
enum eNALType {
NAL_Slice = 1,
NAL_PartitionA = 2,
NAL_PartitionB = 3,
NAL_PartitionC = 4,
NAL_IDR_Slice = 5,
NAL_SEI = 6,
NAL_Sequence_Params = 7,
NAL_Picture_Params = 8,
NAL_AUD = 9,
};
// identify a NAL unit within a buffer.
// If LengthSize is non-zero, it is the number of bytes
// of length field we expect. Otherwise, we expect start-code
// delimiters.
bool Parse(const BYTE* pBuffer, int cSpace, int LengthSize, bool bEnd);
eNALType Type() {
if (m_pStart == NULL) {
return eNALType(0);
}
return eNALType(m_pStart[0] & 0x1F);
}
int Length() {
return m_cBytes;
}
const BYTE* Start() {
return m_pStart;
}
// bitwise access to data
void ResetBitstream();
void Skip(int nBits);
unsigned long GetWord(int nBits);
unsigned long GetUE();
long GetSE();
BYTE GetBYTE();
unsigned long GetBit();
const BYTE* StartCodeStart() {
return m_pStartCodeStart;
}
private:
bool GetStartCode(const BYTE*& pBegin, const BYTE*& pStart, int& cRemain);
private:
const BYTE* m_pStartCodeStart;
const BYTE* m_pStart;
int m_cBytes;
// bitstream access
int m_idx;
int m_nBits;
BYTE m_byte;
int m_cZeros;
};
// simple parser for the Sequence parameter set things that we need
class SeqParamSet
{
public:
SeqParamSet();
bool Parse(NALUnit* pnalu);
int FrameBits() {
return m_FrameBits;
}
long EncodedWidth() {
return m_cx;
}
long EncodedHeight() {
return m_cy;
}
#if 0
long CroppedWidth() {
if (IsRectEmpty(&m_rcFrame)) {
return EncodedWidth();
}
return m_rcFrame.right - m_rcFrame.left;
}
long CroppedHeight() {
if (IsRectEmpty(&m_rcFrame)) {
return EncodedHeight();
}
return m_rcFrame.bottom - m_rcFrame.top;
}
RECT* CropRect() {
return &m_rcFrame;
}
#endif
bool Interlaced() {
return !m_bFrameOnly;
}
unsigned int Profile() { return m_Profile; }
unsigned int Level() { return m_Level; }
BYTE Compat() { return m_Compatibility; }
NALUnit* NALU() {return &m_nalu; }
private:
NALUnit m_nalu;
int m_FrameBits;
long m_cx;
long m_cy;
// RECT m_rcFrame;
bool m_bFrameOnly;
int m_Profile;
int m_Level;
BYTE m_Compatibility;
};
// extract frame num from slice headers
class SliceHeader {
public:
SliceHeader(int nBitsFrame)
: m_framenum(0),
m_nBitsFrame(nBitsFrame)
{
}
bool Parse(NALUnit* pnalu);
int FrameNum() {
return m_framenum;
}
private:
int m_framenum;
int m_nBitsFrame;
};
// SEI message structure
class SEIMessage
{
public:
SEIMessage(NALUnit* pnalu);
int Type() { return m_type; }
int Length() { return m_length; }
const BYTE* Payload() { return m_pnalu->Start() + m_idxPayload; }
private:
NALUnit* m_pnalu;
int m_type;
int m_length;
int m_idxPayload;
};
// avcC structure from MP4
class avcCHeader {
public:
avcCHeader(const BYTE* header, int cBytes);
NALUnit* sps() { return &m_sps; }
NALUnit* pps() { return &m_pps; }
private:
NALUnit m_sps;
NALUnit m_pps;
};