1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34
35
36 //-----------------------------------------------------------------------------
37 //
38 // class TimeCode
39 //
40 //-----------------------------------------------------------------------------
41
42 #include <ImfTimeCode.h>
43 #include "Iex.h"
44
45 namespace Imf {
46
47
TimeCode()48 TimeCode::TimeCode ()
49 {
50 _time = 0;
51 _user = 0;
52 }
53
54
TimeCode(int hours,int minutes,int seconds,int frame,bool dropFrame,bool colorFrame,bool fieldPhase,bool bgf0,bool bgf1,bool bgf2,int binaryGroup1,int binaryGroup2,int binaryGroup3,int binaryGroup4,int binaryGroup5,int binaryGroup6,int binaryGroup7,int binaryGroup8)55 TimeCode::TimeCode
56 (int hours,
57 int minutes,
58 int seconds,
59 int frame,
60 bool dropFrame,
61 bool colorFrame,
62 bool fieldPhase,
63 bool bgf0,
64 bool bgf1,
65 bool bgf2,
66 int binaryGroup1,
67 int binaryGroup2,
68 int binaryGroup3,
69 int binaryGroup4,
70 int binaryGroup5,
71 int binaryGroup6,
72 int binaryGroup7,
73 int binaryGroup8)
74 {
75 setHours (hours);
76 setMinutes (minutes);
77 setSeconds (seconds);
78 setFrame (frame);
79 setDropFrame (dropFrame);
80 setColorFrame (colorFrame);
81 setFieldPhase (fieldPhase);
82 setBgf0 (bgf0);
83 setBgf1 (bgf1);
84 setBgf2 (bgf2);
85 setBinaryGroup (1, binaryGroup1);
86 setBinaryGroup (2, binaryGroup2);
87 setBinaryGroup (3, binaryGroup3);
88 setBinaryGroup (4, binaryGroup4);
89 setBinaryGroup (5, binaryGroup5);
90 setBinaryGroup (6, binaryGroup6);
91 setBinaryGroup (7, binaryGroup7);
92 setBinaryGroup (8, binaryGroup8);
93 }
94
95
TimeCode(unsigned int timeAndFlags,unsigned int userData,Packing packing)96 TimeCode::TimeCode
97 (unsigned int timeAndFlags,
98 unsigned int userData,
99 Packing packing)
100 {
101 setTimeAndFlags (timeAndFlags, packing);
102 setUserData (userData);
103 }
104
105
TimeCode(const TimeCode & other)106 TimeCode::TimeCode (const TimeCode &other)
107 {
108 _time = other._time;
109 _user = other._user;
110 }
111
112
113 TimeCode &
operator =(const TimeCode & other)114 TimeCode::operator = (const TimeCode &other)
115 {
116 _time = other._time;
117 _user = other._user;
118 return *this;
119 }
120
121
122 namespace {
123
124 unsigned int
bitField(unsigned int value,int minBit,int maxBit)125 bitField (unsigned int value, int minBit, int maxBit)
126 {
127 int shift = minBit;
128 unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
129 return (value & mask) >> shift;
130 }
131
132
133 void
setBitField(unsigned int & value,int minBit,int maxBit,unsigned int field)134 setBitField (unsigned int &value, int minBit, int maxBit, unsigned int field)
135 {
136 int shift = minBit;
137 unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
138 value = ((value & ~mask) | ((field << shift) & mask));
139 }
140
141
142 int
bcdToBinary(unsigned int bcd)143 bcdToBinary (unsigned int bcd)
144 {
145 return int ((bcd & 0x0f) + 10 * ((bcd >> 4) & 0x0f));
146 }
147
148
149 unsigned int
binaryToBcd(int binary)150 binaryToBcd (int binary)
151 {
152 int units = binary % 10;
153 int tens = (binary / 10) % 10;
154 return (unsigned int) (units | (tens << 4));
155 }
156
157
158 } // namespace
159
160
161 int
hours() const162 TimeCode::hours () const
163 {
164 return bcdToBinary (bitField (_time, 24, 29));
165 }
166
167
168 void
setHours(int value)169 TimeCode::setHours (int value)
170 {
171 if (value < 0 || value > 23)
172 throw Iex::ArgExc ("Cannot set hours field in time code. "
173 "New value is out of range.");
174
175 setBitField (_time, 24, 29, binaryToBcd (value));
176 }
177
178
179 int
minutes() const180 TimeCode::minutes () const
181 {
182 return bcdToBinary (bitField (_time, 16, 22));
183 }
184
185
186 void
setMinutes(int value)187 TimeCode::setMinutes (int value)
188 {
189 if (value < 0 || value > 59)
190 throw Iex::ArgExc ("Cannot set minutes field in time code. "
191 "New value is out of range.");
192
193 setBitField (_time, 16, 22, binaryToBcd (value));
194 }
195
196
197 int
seconds() const198 TimeCode::seconds () const
199 {
200 return bcdToBinary (bitField (_time, 8, 14));
201 }
202
203
204 void
setSeconds(int value)205 TimeCode::setSeconds (int value)
206 {
207 if (value < 0 || value > 59)
208 throw Iex::ArgExc ("Cannot set seconds field in time code. "
209 "New value is out of range.");
210
211 setBitField (_time, 8, 14, binaryToBcd (value));
212 }
213
214
215 int
frame() const216 TimeCode::frame () const
217 {
218 return bcdToBinary (bitField (_time, 0, 5));
219 }
220
221
222 void
setFrame(int value)223 TimeCode::setFrame (int value)
224 {
225 if (value < 0 || value > 59)
226 throw Iex::ArgExc ("Cannot set frame field in time code. "
227 "New value is out of range.");
228
229 setBitField (_time, 0, 5, binaryToBcd (value));
230 }
231
232
233 bool
dropFrame() const234 TimeCode::dropFrame () const
235 {
236 return bool (bitField (_time, 6, 6));
237 }
238
239
240 void
setDropFrame(bool value)241 TimeCode::setDropFrame (bool value)
242 {
243 setBitField (_time, 6, 6, (unsigned int) !!value);
244 }
245
246
247 bool
colorFrame() const248 TimeCode::colorFrame () const
249 {
250 return bool (bitField (_time, 7, 7));
251 }
252
253
254 void
setColorFrame(bool value)255 TimeCode::setColorFrame (bool value)
256 {
257 setBitField (_time, 7, 7, (unsigned int) !!value);
258 }
259
260
261 bool
fieldPhase() const262 TimeCode::fieldPhase () const
263 {
264 return bool (bitField (_time, 15, 15));
265 }
266
267
268 void
setFieldPhase(bool value)269 TimeCode::setFieldPhase (bool value)
270 {
271 setBitField (_time, 15, 15, (unsigned int) !!value);
272 }
273
274
275 bool
bgf0() const276 TimeCode::bgf0 () const
277 {
278 return bool (bitField (_time, 23, 23));
279 }
280
281
282 void
setBgf0(bool value)283 TimeCode::setBgf0 (bool value)
284 {
285 setBitField (_time, 23, 23, (unsigned int) !!value);
286 }
287
288
289 bool
bgf1() const290 TimeCode::bgf1 () const
291 {
292 return bool (bitField (_time, 30, 30));
293 }
294
295
296 void
setBgf1(bool value)297 TimeCode::setBgf1 (bool value)
298 {
299 setBitField (_time, 30, 30, (unsigned int) !!value);
300 }
301
302
303 bool
bgf2() const304 TimeCode::bgf2 () const
305 {
306 return bool (bitField (_time, 31, 31));
307 }
308
309
310 void
setBgf2(bool value)311 TimeCode::setBgf2 (bool value)
312 {
313 setBitField (_time, 31, 31, (unsigned int) !!value);
314 }
315
316
317 int
binaryGroup(int group) const318 TimeCode::binaryGroup (int group) const
319 {
320 if (group < 1 || group > 8)
321 throw Iex::ArgExc ("Cannot extract binary group from time code "
322 "user data. Group number is out of range.");
323
324 int minBit = 4 * (group - 1);
325 int maxBit = minBit + 3;
326 return int (bitField (_user, minBit, maxBit));
327 }
328
329
330 void
setBinaryGroup(int group,int value)331 TimeCode::setBinaryGroup (int group, int value)
332 {
333 if (group < 1 || group > 8)
334 throw Iex::ArgExc ("Cannot extract binary group from time code "
335 "user data. Group number is out of range.");
336
337 int minBit = 4 * (group - 1);
338 int maxBit = minBit + 3;
339 setBitField (_user, minBit, maxBit, (unsigned int) value);
340 }
341
342
343 unsigned int
timeAndFlags(Packing packing) const344 TimeCode::timeAndFlags (Packing packing) const
345 {
346 if (packing == TV50_PACKING)
347 {
348 unsigned int t = _time;
349
350 t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
351
352 t |= ((unsigned int) bgf0() << 15);
353 t |= ((unsigned int) bgf2() << 23);
354 t |= ((unsigned int) bgf1() << 30);
355 t |= ((unsigned int) fieldPhase() << 31);
356
357 return t;
358 }
359 if (packing == FILM24_PACKING)
360 {
361 return _time & ~((1 << 6) | (1 << 7));
362 }
363 else // packing == TV60_PACKING
364 {
365 return _time;
366 }
367 }
368
369
370 void
setTimeAndFlags(unsigned int value,Packing packing)371 TimeCode::setTimeAndFlags (unsigned int value, Packing packing)
372 {
373 if (packing == TV50_PACKING)
374 {
375 _time = value &
376 ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
377
378 if (value & (1 << 15))
379 setBgf0 (true);
380
381 if (value & (1 << 23))
382 setBgf2 (true);
383
384 if (value & (1 << 30))
385 setBgf1 (true);
386
387 if (value & (1 << 31))
388 setFieldPhase (true);
389 }
390 else if (packing == FILM24_PACKING)
391 {
392 _time = value & ~((1 << 6) | (1 << 7));
393 }
394 else // packing == TV60_PACKING
395 {
396 _time = value;
397 }
398 }
399
400
401 unsigned int
userData() const402 TimeCode::userData () const
403 {
404 return _user;
405 }
406
407
408 void
setUserData(unsigned int value)409 TimeCode::setUserData (unsigned int value)
410 {
411 _user = value;
412 }
413
414
415 } // namespace Imf
416