1 /*****************************************************************
2 |
3 | AP4 - hvcC Atoms
4 |
5 | Copyright 2002-2014 Axiomatic Systems, LLC
6 |
7 |
8 | This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 | Unless you have obtained Bento4 under a difference license,
11 | this version of Bento4 is Bento4|GPL.
12 | Bento4|GPL is free software; you can redistribute it and/or modify
13 | it under the terms of the GNU General Public License as published by
14 | the Free Software Foundation; either version 2, or (at your option)
15 | any later version.
16 |
17 | Bento4|GPL is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have received a copy of the GNU General Public License
23 | along with Bento4|GPL; see the file COPYING. If not, write to the
24 | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 | 02111-1307, USA.
26 |
27 ****************************************************************/
28
29 /*----------------------------------------------------------------------
30 | includes
31 +---------------------------------------------------------------------*/
32 #include "Ap4HvccAtom.h"
33 #include "Ap4AtomFactory.h"
34 #include "Ap4Utils.h"
35 #include "Ap4Types.h"
36
37 /*----------------------------------------------------------------------
38 | dynamic cast support
39 +---------------------------------------------------------------------*/
AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_HvccAtom) const40 AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_HvccAtom)
41
42 /*----------------------------------------------------------------------
43 | AP4_HvccAtom::GetProfileName
44 +---------------------------------------------------------------------*/
45 const char*
46 AP4_HvccAtom::GetProfileName(AP4_UI08 profile_space, AP4_UI08 profile)
47 {
48 if (profile_space != 0) {
49 return NULL;
50 }
51 switch (profile) {
52 case AP4_HEVC_PROFILE_MAIN: return "Main";
53 case AP4_HEVC_PROFILE_MAIN_10: return "Main 10";
54 case AP4_HEVC_PROFILE_MAIN_STILL_PICTURE: return "Main Still Picture";
55 case AP4_HEVC_PROFILE_REXT: return "Rext";
56 }
57
58 return NULL;
59 }
60
61 /*----------------------------------------------------------------------
62 | AP4_HvccAtom::GetChromaFormatName
63 +---------------------------------------------------------------------*/
64 const char*
GetChromaFormatName(AP4_UI08 chroma_format)65 AP4_HvccAtom::GetChromaFormatName(AP4_UI08 chroma_format)
66 {
67 switch (chroma_format) {
68 case AP4_HEVC_CHROMA_FORMAT_MONOCHROME: return "Monochrome";
69 case AP4_HEVC_CHROMA_FORMAT_420: return "4:2:0";
70 case AP4_HEVC_CHROMA_FORMAT_422: return "4:2:2";
71 case AP4_HEVC_CHROMA_FORMAT_444: return "4:4:4";
72 }
73
74 return NULL;
75 }
76
77 /*----------------------------------------------------------------------
78 | AP4_AvccAtom::Create
79 +---------------------------------------------------------------------*/
80 AP4_HvccAtom*
Create(AP4_Size size,AP4_ByteStream & stream)81 AP4_HvccAtom::Create(AP4_Size size, AP4_ByteStream& stream)
82 {
83 // read the raw bytes in a buffer
84 unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
85 AP4_DataBuffer payload_data(payload_size);
86 AP4_Result result = stream.Read(payload_data.UseData(), payload_size);
87 if (AP4_FAILED(result)) return NULL;
88
89 return new AP4_HvccAtom(size, payload_data.GetData());
90 }
91
92 /*----------------------------------------------------------------------
93 | AP4_HvccAtom::AP4_HvccAtom
94 +---------------------------------------------------------------------*/
AP4_HvccAtom()95 AP4_HvccAtom::AP4_HvccAtom() :
96 AP4_Atom(AP4_ATOM_TYPE_HVCC, AP4_ATOM_HEADER_SIZE),
97 m_ConfigurationVersion(1),
98 m_GeneralProfileSpace(0),
99 m_GeneralTierFlag(0),
100 m_GeneralProfile(0),
101 m_GeneralProfileCompatibilityFlags(0),
102 m_GeneralConstraintIndicatorFlags(0),
103 m_GeneralLevel(0),
104 m_Reserved1(0),
105 m_MinSpatialSegmentation(0),
106 m_Reserved2(0),
107 m_ParallelismType(0),
108 m_Reserved3(0),
109 m_ChromaFormat(0),
110 m_Reserved4(0),
111 m_LumaBitDepth(0),
112 m_Reserved5(0),
113 m_ChromaBitDepth(0),
114 m_AverageFrameRate(0),
115 m_ConstantFrameRate(0),
116 m_NumTemporalLayers(0),
117 m_TemporalIdNested(0),
118 m_NaluLengthSize(0)
119 {
120 UpdateRawBytes();
121 m_Size32 += m_RawBytes.GetDataSize();
122 }
123
124 /*----------------------------------------------------------------------
125 | AP4_HvccAtom::AP4_HvccAtom
126 +---------------------------------------------------------------------*/
AP4_HvccAtom(const AP4_HvccAtom & other)127 AP4_HvccAtom::AP4_HvccAtom(const AP4_HvccAtom& other) :
128 AP4_Atom(AP4_ATOM_TYPE_HVCC, other.m_Size32),
129 m_ConfigurationVersion(other.m_ConfigurationVersion),
130 m_GeneralProfileSpace(other.m_GeneralProfileSpace),
131 m_GeneralTierFlag(other.m_GeneralTierFlag),
132 m_GeneralProfile(other.m_GeneralProfile),
133 m_GeneralProfileCompatibilityFlags(other.m_GeneralProfileCompatibilityFlags),
134 m_GeneralConstraintIndicatorFlags(other.m_GeneralConstraintIndicatorFlags),
135 m_GeneralLevel(other.m_GeneralLevel),
136 m_Reserved1(other.m_Reserved1),
137 m_MinSpatialSegmentation(other.m_MinSpatialSegmentation),
138 m_Reserved2(other.m_Reserved2),
139 m_ParallelismType(other.m_ParallelismType),
140 m_Reserved3(other.m_Reserved3),
141 m_ChromaFormat(other.m_ChromaFormat),
142 m_Reserved4(other.m_Reserved4),
143 m_LumaBitDepth(other.m_LumaBitDepth),
144 m_Reserved5(other.m_Reserved5),
145 m_ChromaBitDepth(other.m_ChromaBitDepth),
146 m_AverageFrameRate(other.m_AverageFrameRate),
147 m_ConstantFrameRate(other.m_ConstantFrameRate),
148 m_NumTemporalLayers(other.m_NumTemporalLayers),
149 m_TemporalIdNested(other.m_TemporalIdNested),
150 m_NaluLengthSize(other.m_NaluLengthSize),
151 m_RawBytes(other.m_RawBytes)
152 {
153 // deep copy of the parameters
154 unsigned int i = 0;
155 for (i=0; i<other.m_Sequences.ItemCount(); i++) {
156 m_Sequences.Append(other.m_Sequences[i]);
157 }
158 }
159
160 /*----------------------------------------------------------------------
161 | AP4_HvccAtom::AP4_HvccAtom
162 +---------------------------------------------------------------------*/
AP4_HvccAtom(AP4_UI32 size,const AP4_UI08 * payload)163 AP4_HvccAtom::AP4_HvccAtom(AP4_UI32 size, const AP4_UI08* payload) :
164 AP4_Atom(AP4_ATOM_TYPE_HVCC, size)
165 {
166 // make a copy of our configuration bytes
167 unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
168 m_RawBytes.SetData(payload, payload_size);
169
170 // parse the payload
171 m_ConfigurationVersion = payload[0];
172 m_GeneralProfileSpace = (payload[1]>>6) & 0x03;
173 m_GeneralTierFlag = (payload[1]>>5) & 0x01;
174 m_GeneralProfile = (payload[1] ) & 0x1F;
175 m_GeneralProfileCompatibilityFlags = AP4_BytesToUInt32BE(&payload[2]);
176 m_GeneralConstraintIndicatorFlags = (((AP4_UI64)AP4_BytesToUInt32BE(&payload[6]))<<16) | AP4_BytesToUInt16BE(&payload[10]);
177 m_GeneralLevel = payload[12];
178 m_Reserved1 = (payload[13]>>4) & 0x0F;
179 m_MinSpatialSegmentation = AP4_BytesToUInt16BE(&payload[13]) & 0x0FFF;
180 m_Reserved2 = (payload[15]>>2) & 0x3F;
181 m_ParallelismType = payload[15] & 0x03;
182 m_Reserved3 = (payload[16]>>2) & 0x3F;
183 m_ChromaFormat = payload[16] & 0x03;
184 m_Reserved4 = (payload[17]>>3) & 0x1F;
185 m_LumaBitDepth = 8+(payload[17] & 0x07);
186 m_Reserved5 = (payload[18]>>3) & 0x1F;
187 m_ChromaBitDepth = 8+(payload[18] & 0x07);
188 m_AverageFrameRate = AP4_BytesToUInt16BE(&payload[19]);
189 m_ConstantFrameRate = (payload[21]>>6) & 0x03;
190 m_NumTemporalLayers = (payload[21]>>3) & 0x07;
191 m_TemporalIdNested = (payload[21]>>2) & 0x01;
192 m_NaluLengthSize = 1+(payload[21] & 0x03);
193
194 AP4_UI08 num_seq = payload[22];
195 m_Sequences.SetItemCount(num_seq);
196 unsigned int cursor = 23;
197 for (unsigned int i=0; i<num_seq; i++) {
198
199 Sequence& seq = m_Sequences[i];
200 if (cursor+1 > payload_size) break;
201 seq.m_ArrayCompleteness = (payload[cursor] >> 7) & 0x01;
202 seq.m_Reserved = (payload[cursor] >> 6) & 0x01;
203 seq.m_NaluType = payload[cursor] & 0x3F;
204 cursor += 1;
205
206 if (cursor+2 > payload_size) break;
207 AP4_UI16 nalu_count = AP4_BytesToUInt16BE(&payload[cursor]);
208 seq.m_Nalus.SetItemCount(nalu_count);
209 cursor += 2;
210
211 for (unsigned int j=0; j<nalu_count; j++) {
212 if (cursor+2 > payload_size) break;
213 unsigned int nalu_length = AP4_BytesToUInt16BE(&payload[cursor]);
214 cursor += 2;
215 if (cursor + nalu_length > payload_size) break;
216 seq.m_Nalus[j].SetData(&payload[cursor], nalu_length);
217 cursor += nalu_length;
218 }
219 }
220 }
221
222 /*----------------------------------------------------------------------
223 | AP4_HvccAtom::UpdateRawBytes
224 +---------------------------------------------------------------------*/
225 void
UpdateRawBytes()226 AP4_HvccAtom::UpdateRawBytes()
227 {
228 // FIXME: not implemented yet
229 }
230
231 /*----------------------------------------------------------------------
232 | AP4_HvccAtom::WriteFields
233 +---------------------------------------------------------------------*/
234 AP4_Result
WriteFields(AP4_ByteStream & stream)235 AP4_HvccAtom::WriteFields(AP4_ByteStream& stream)
236 {
237 return stream.Write(m_RawBytes.GetData(), m_RawBytes.GetDataSize());
238 }
239
240 /*----------------------------------------------------------------------
241 | AP4_HvccAtom::InspectFields
242 +---------------------------------------------------------------------*/
243 AP4_Result
InspectFields(AP4_AtomInspector & inspector)244 AP4_HvccAtom::InspectFields(AP4_AtomInspector& inspector)
245 {
246 inspector.AddField("Configuration Version", m_ConfigurationVersion);
247 inspector.AddField("Profile Space", m_GeneralProfileSpace);
248 const char* profile_name = GetProfileName(m_GeneralProfileSpace, m_GeneralProfile);
249 if (profile_name) {
250 inspector.AddField("Profile", profile_name);
251 } else {
252 inspector.AddField("Profile", m_GeneralProfile);
253 }
254 inspector.AddField("Tier", m_GeneralTierFlag);
255 inspector.AddField("Profile Compatibility", m_GeneralProfileCompatibilityFlags, AP4_AtomInspector::HINT_HEX);
256 inspector.AddField("Constraint", m_GeneralConstraintIndicatorFlags, AP4_AtomInspector::HINT_HEX);
257 inspector.AddField("Level", m_GeneralLevel);
258 inspector.AddField("Min Spatial Segmentation", m_MinSpatialSegmentation);
259 inspector.AddField("Parallelism Type", m_ParallelismType);
260 inspector.AddField("Chroma Format", m_ChromaFormat);
261 inspector.AddField("Chroma Depth", m_ChromaBitDepth);
262 inspector.AddField("Luma Depth", m_LumaBitDepth);
263 inspector.AddField("Average Frame Rate", m_AverageFrameRate);
264 inspector.AddField("Constant Frame Rate", m_ConstantFrameRate);
265 inspector.AddField("Number Of Temporal Layers", m_NumTemporalLayers);
266 inspector.AddField("Temporal Id Nested", m_TemporalIdNested);
267 inspector.AddField("NALU Length Size", m_NaluLengthSize);
268 return AP4_SUCCESS;
269 }
270