1 /*****************************************************************
2 |
3 |    AP4 - sidx 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 "Ap4SidxAtom.h"
33 #include "Ap4Utils.h"
34 
35 /*----------------------------------------------------------------------
36 |   dynamic cast support
37 +---------------------------------------------------------------------*/
AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_SidxAtom)38 AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_SidxAtom)
39 
40 
41 /*----------------------------------------------------------------------
42 |   AP4_SidxAtom::Create
43 +---------------------------------------------------------------------*/
44 AP4_SidxAtom*
45 AP4_SidxAtom::Create(AP4_Size size, AP4_ByteStream& stream)
46 {
47     AP4_UI08 version;
48     AP4_UI32 flags;
49     if (size < AP4_FULL_ATOM_HEADER_SIZE) return NULL;
50     if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
51     if (version > 1) return NULL;
52     return new AP4_SidxAtom(size, version, flags, stream);
53 }
54 
55 /*----------------------------------------------------------------------
56 |   AP4_SidxAtom::AP4_SidxAtom
57 +---------------------------------------------------------------------*/
AP4_SidxAtom(AP4_UI32 reference_id,AP4_UI32 timescale,AP4_UI64 earliest_presentation_time,AP4_UI64 first_offset)58 AP4_SidxAtom::AP4_SidxAtom(AP4_UI32 reference_id,
59                            AP4_UI32 timescale,
60                            AP4_UI64 earliest_presentation_time,
61                            AP4_UI64 first_offset) :
62     AP4_Atom(AP4_ATOM_TYPE_SIDX, AP4_FULL_ATOM_HEADER_SIZE+20, 0, 0),
63     m_ReferenceId(reference_id),
64     m_TimeScale(timescale),
65     m_EarliestPresentationTime(earliest_presentation_time),
66     m_FirstOffset(first_offset)
67 {
68     if ((earliest_presentation_time >> 32) || (first_offset >> 32)) {
69         m_Version = 1;
70         m_Size32 += 8;
71     }
72 }
73 
74 /*----------------------------------------------------------------------
75 |   AP4_SidxAtom::AP4_SidxAtom
76 +---------------------------------------------------------------------*/
AP4_SidxAtom(AP4_UI32 size,AP4_UI08 version,AP4_UI32 flags,AP4_ByteStream & stream)77 AP4_SidxAtom::AP4_SidxAtom(AP4_UI32        size,
78                            AP4_UI08        version,
79                            AP4_UI32        flags,
80                            AP4_ByteStream& stream) :
81     AP4_Atom(AP4_ATOM_TYPE_SIDX, size, version, flags)
82 {
83     stream.ReadUI32(m_ReferenceId);
84     stream.ReadUI32(m_TimeScale);
85     if (version == 0) {
86         AP4_UI32 earliest_presentation_time = 0;
87         AP4_UI32 first_offset = 0;
88         stream.ReadUI32(earliest_presentation_time);
89         stream.ReadUI32(first_offset);
90         m_EarliestPresentationTime = earliest_presentation_time;
91         m_FirstOffset              = first_offset;
92     } else {
93         stream.ReadUI64(m_EarliestPresentationTime);
94         stream.ReadUI64(m_FirstOffset);
95     }
96     AP4_UI16 reserved;
97     stream.ReadUI16(reserved);
98     AP4_UI16 reference_count = 0;
99     stream.ReadUI16(reference_count);
100     if (size < AP4_FULL_ATOM_HEADER_SIZE+4+4+(version==0?8:16)+2+2+reference_count*12) {
101         // not enough space to store all references, something's wrong
102         return;
103     }
104     m_References.SetItemCount(reference_count);
105     for (unsigned int i=0; i<reference_count; i++) {
106         AP4_UI32 value = 0;
107         stream.ReadUI32(value);
108         m_References[i].m_ReferenceType = (value&(1<<31))?1:0;
109         m_References[i].m_ReferencedSize = value & 0x7FFFFFFF;
110         stream.ReadUI32(m_References[i].m_SubsegmentDuration);
111         stream.ReadUI32(value);
112         m_References[i].m_StartsWithSap = ((value&(1<<31)) != 0);
113         m_References[i].m_SapType       = (AP4_UI08)((value >>28)&0x07);
114         m_References[i].m_SapDeltaTime  = value & 0x0FFFFFFF;
115     }
116 }
117 
118 /*----------------------------------------------------------------------
119 |   AP4_SidxAtom::WriteFields
120 +---------------------------------------------------------------------*/
121 AP4_Result
WriteFields(AP4_ByteStream & stream)122 AP4_SidxAtom::WriteFields(AP4_ByteStream& stream)
123 {
124     stream.WriteUI32(m_ReferenceId);
125     stream.WriteUI32(m_TimeScale);
126     if (m_Version == 0) {
127         stream.WriteUI32((AP4_UI32)m_EarliestPresentationTime);
128         stream.WriteUI32((AP4_UI32)m_FirstOffset);
129     } else {
130         stream.WriteUI64(m_EarliestPresentationTime);
131         stream.WriteUI64(m_FirstOffset);
132     }
133     stream.WriteUI16(0);
134     stream.WriteUI16((AP4_UI16)m_References.ItemCount());
135     for (unsigned int i=0; i<m_References.ItemCount(); i++) {
136         stream.WriteUI32((m_References[i].m_ReferenceType<<31) |
137                           m_References[i].m_ReferencedSize);
138         stream.WriteUI32(m_References[i].m_SubsegmentDuration);
139         stream.WriteUI32(((m_References[i].m_StartsWithSap?1:0)<<31) |
140                           (m_References[i].m_SapType << 28) |
141                            m_References[i].m_SapDeltaTime);
142     }
143 
144     return AP4_SUCCESS;
145 }
146 
147 /*----------------------------------------------------------------------
148 |   AP4_SidxAtom::InspectFields
149 +---------------------------------------------------------------------*/
150 AP4_Result
InspectFields(AP4_AtomInspector & inspector)151 AP4_SidxAtom::InspectFields(AP4_AtomInspector& inspector)
152 {
153     inspector.AddField("reference_ID", m_ReferenceId);
154     inspector.AddField("timescale", m_TimeScale);
155     inspector.AddField("earliest_presentation_time", m_EarliestPresentationTime);
156     inspector.AddField("first_offset", m_FirstOffset);
157 
158     if (inspector.GetVerbosity() >= 1) {
159         AP4_UI32 reference_count = m_References.ItemCount();
160         inspector.StartArray("entries", reference_count);
161         for (unsigned int i=0; i<reference_count; i++) {
162             inspector.StartObject(NULL, 6, true);
163             inspector.AddField("reference_type",      m_References[i].m_ReferenceType);
164             inspector.AddField("referenced_size",     m_References[i].m_ReferencedSize);
165             inspector.AddField("subsegment_duration", m_References[i].m_SubsegmentDuration);
166             inspector.AddField("starts_with_SAP",     m_References[i].m_StartsWithSap);
167             inspector.AddField("SAP_type",            m_References[i].m_SapType);
168             inspector.AddField("SAP_delta_time",      m_References[i].m_SapDeltaTime);
169             inspector.EndObject();
170         }
171         inspector.EndArray();
172     }
173 
174     return AP4_SUCCESS;
175 }
176 
177 /*----------------------------------------------------------------------
178 |   AP4_SidxAtom::SetReferenceCount
179 +---------------------------------------------------------------------*/
180 void
SetReferenceCount(unsigned int count)181 AP4_SidxAtom::SetReferenceCount(unsigned int count) {
182     m_Size32 -= m_References.ItemCount()*12;
183     m_References.SetItemCount(count);
184     m_Size32 += m_References.ItemCount()*12;
185 }
186