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