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 #include "ImfNamespace.h"
45 
46 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
47 
48 
TimeCode()49 TimeCode::TimeCode ()
50 {
51     _time = 0;
52     _user = 0;
53 }
54 
55 
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)56 TimeCode::TimeCode
57     (int hours,
58      int minutes,
59      int seconds,
60      int frame,
61      bool dropFrame,
62      bool colorFrame,
63      bool fieldPhase,
64      bool bgf0,
65      bool bgf1,
66      bool bgf2,
67      int binaryGroup1,
68      int binaryGroup2,
69      int binaryGroup3,
70      int binaryGroup4,
71      int binaryGroup5,
72      int binaryGroup6,
73      int binaryGroup7,
74      int binaryGroup8)
75 {
76     setHours (hours);
77     setMinutes (minutes);
78     setSeconds (seconds);
79     setFrame (frame);
80     setDropFrame (dropFrame);
81     setColorFrame (colorFrame);
82     setFieldPhase (fieldPhase);
83     setBgf0 (bgf0);
84     setBgf1 (bgf1);
85     setBgf2 (bgf2);
86     setBinaryGroup (1, binaryGroup1);
87     setBinaryGroup (2, binaryGroup2);
88     setBinaryGroup (3, binaryGroup3);
89     setBinaryGroup (4, binaryGroup4);
90     setBinaryGroup (5, binaryGroup5);
91     setBinaryGroup (6, binaryGroup6);
92     setBinaryGroup (7, binaryGroup7);
93     setBinaryGroup (8, binaryGroup8);
94 }
95 
96 
TimeCode(unsigned int timeAndFlags,unsigned int userData,Packing packing)97 TimeCode::TimeCode
98     (unsigned int timeAndFlags,
99      unsigned int userData,
100      Packing packing)
101 {
102     setTimeAndFlags (timeAndFlags, packing);
103     setUserData (userData);
104 }
105 
106 
TimeCode(const TimeCode & other)107 TimeCode::TimeCode (const TimeCode &other)
108 {
109     _time = other._time;
110     _user = other._user;
111 }
112 
113 
114 TimeCode &
operator =(const TimeCode & other)115 TimeCode::operator = (const TimeCode &other)
116 {
117     _time = other._time;
118     _user = other._user;
119     return *this;
120 }
121 
122 
123 bool
operator ==(const TimeCode & c) const124 TimeCode::operator == (const TimeCode & c) const
125 {
126     return (_time == c._time && _user == c._user);
127 }
128 
129 
130 bool
operator !=(const TimeCode & c) const131 TimeCode::operator != (const TimeCode & c) const
132 {
133     return (_time != c._time || _user != c._user);
134 }
135 
136 
137 
138 namespace {
139 
140 unsigned int
bitField(unsigned int value,int minBit,int maxBit)141 bitField (unsigned int value, int minBit, int maxBit)
142 {
143     int shift = minBit;
144     unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
145     return (value & mask) >> shift;
146 }
147 
148 
149 void
setBitField(unsigned int & value,int minBit,int maxBit,unsigned int field)150 setBitField (unsigned int &value, int minBit, int maxBit, unsigned int field)
151 {
152     int shift = minBit;
153     unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
154     value = ((value & ~mask) | ((field << shift) & mask));
155 }
156 
157 
158 int
bcdToBinary(unsigned int bcd)159 bcdToBinary (unsigned int bcd)
160 {
161     return int ((bcd & 0x0f) + 10 * ((bcd >> 4) & 0x0f));
162 }
163 
164 
165 unsigned int
binaryToBcd(int binary)166 binaryToBcd (int binary)
167 {
168     int units = binary % 10;
169     int tens = (binary / 10) % 10;
170     return (unsigned int) (units | (tens << 4));
171 }
172 
173 
174 } // namespace
175 
176 
177 int
hours() const178 TimeCode::hours () const
179 {
180     return bcdToBinary (bitField (_time, 24, 29));
181 }
182 
183 
184 void
setHours(int value)185 TimeCode::setHours (int value)
186 {
187     if (value < 0 || value > 23)
188 	throw IEX_NAMESPACE::ArgExc ("Cannot set hours field in time code. "
189 			   "New value is out of range.");
190 
191     setBitField (_time, 24, 29, binaryToBcd (value));
192 }
193 
194 
195 int
minutes() const196 TimeCode::minutes () const
197 {
198     return bcdToBinary (bitField (_time, 16, 22));
199 }
200 
201 
202 void
setMinutes(int value)203 TimeCode::setMinutes (int value)
204 {
205     if (value < 0 || value > 59)
206 	throw IEX_NAMESPACE::ArgExc ("Cannot set minutes field in time code. "
207 			   "New value is out of range.");
208 
209     setBitField (_time, 16, 22, binaryToBcd (value));
210 }
211 
212 
213 int
seconds() const214 TimeCode::seconds () const
215 {
216     return bcdToBinary (bitField (_time, 8, 14));
217 }
218 
219 
220 void
setSeconds(int value)221 TimeCode::setSeconds (int value)
222 {
223     if (value < 0 || value > 59)
224 	throw IEX_NAMESPACE::ArgExc ("Cannot set seconds field in time code. "
225 			   "New value is out of range.");
226 
227     setBitField (_time, 8, 14, binaryToBcd (value));
228 }
229 
230 
231 int
frame() const232 TimeCode::frame () const
233 {
234     return bcdToBinary (bitField (_time, 0, 5));
235 }
236 
237 
238 void
setFrame(int value)239 TimeCode::setFrame (int value)
240 {
241     if (value < 0 || value > 59)
242 	throw IEX_NAMESPACE::ArgExc ("Cannot set frame field in time code. "
243 			   "New value is out of range.");
244 
245     setBitField (_time, 0, 5, binaryToBcd (value));
246 }
247 
248 
249 bool
dropFrame() const250 TimeCode::dropFrame () const
251 {
252     return !!bitField (_time, 6, 6);
253 }
254 
255 
256 void
setDropFrame(bool value)257 TimeCode::setDropFrame (bool value)
258 {
259     setBitField (_time, 6, 6, (unsigned int) !!value);
260 }
261 
262 
263 bool
colorFrame() const264 TimeCode::colorFrame () const
265 {
266     return !!bitField (_time, 7, 7);
267 }
268 
269 
270 void
setColorFrame(bool value)271 TimeCode::setColorFrame (bool value)
272 {
273     setBitField (_time, 7, 7, (unsigned int) !!value);
274 }
275 
276 
277 bool
fieldPhase() const278 TimeCode::fieldPhase () const
279 {
280     return !!bitField (_time, 15, 15);
281 }
282 
283 
284 void
setFieldPhase(bool value)285 TimeCode::setFieldPhase (bool value)
286 {
287     setBitField (_time, 15, 15, (unsigned int) !!value);
288 }
289 
290 
291 bool
bgf0() const292 TimeCode::bgf0 () const
293 {
294     return !!bitField (_time, 23, 23);
295 }
296 
297 
298 void
setBgf0(bool value)299 TimeCode::setBgf0 (bool value)
300 {
301     setBitField (_time, 23, 23, (unsigned int) !!value);
302 }
303 
304 
305 bool
bgf1() const306 TimeCode::bgf1 () const
307 {
308     return!!bitField (_time, 30, 30);
309 }
310 
311 
312 void
setBgf1(bool value)313 TimeCode::setBgf1 (bool value)
314 {
315     setBitField (_time, 30, 30, (unsigned int) !!value);
316 }
317 
318 
319 bool
bgf2() const320 TimeCode::bgf2 () const
321 {
322     return !!bitField (_time, 31, 31);
323 }
324 
325 
326 void
setBgf2(bool value)327 TimeCode::setBgf2 (bool value)
328 {
329     setBitField (_time, 31, 31, (unsigned int) !!value);
330 }
331 
332 
333 int
binaryGroup(int group) const334 TimeCode::binaryGroup (int group) const
335 {
336     if (group < 1 || group > 8)
337 	throw IEX_NAMESPACE::ArgExc ("Cannot extract binary group from time code "
338 		           "user data.  Group number is out of range.");
339 
340     int minBit = 4 * (group - 1);
341     int maxBit = minBit + 3;
342     return int (bitField (_user, minBit, maxBit));
343 }
344 
345 
346 void
setBinaryGroup(int group,int value)347 TimeCode::setBinaryGroup (int group, int value)
348 {
349     if (group < 1 || group > 8)
350 	throw IEX_NAMESPACE::ArgExc ("Cannot extract binary group from time code "
351 		           "user data.  Group number is out of range.");
352 
353     int minBit = 4 * (group - 1);
354     int maxBit = minBit + 3;
355     setBitField (_user, minBit, maxBit, (unsigned int) value);
356 }
357 
358 
359 unsigned int
timeAndFlags(Packing packing) const360 TimeCode::timeAndFlags (Packing packing) const
361 {
362     if (packing == TV50_PACKING)
363     {
364 	unsigned int t = _time;
365 
366 	t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
367 
368 	t |= ((unsigned int) bgf0() << 15);
369 	t |= ((unsigned int) bgf2() << 23);
370 	t |= ((unsigned int) bgf1() << 30);
371 	t |= ((unsigned int) fieldPhase() << 31);
372 
373 	return t;
374     }
375     if (packing == FILM24_PACKING)
376     {
377 	return _time & ~((1 << 6) | (1 << 7));
378     }
379     else // packing == TV60_PACKING
380     {
381 	return _time;
382     }
383 }
384 
385 
386 void
setTimeAndFlags(unsigned int value,Packing packing)387 TimeCode::setTimeAndFlags (unsigned int value, Packing packing)
388 {
389     if (packing == TV50_PACKING)
390     {
391 	_time = value &
392 		 ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
393 
394 	if (value & (1 << 15))
395 	    setBgf0 (true);
396 
397 	if (value & (1 << 23))
398 	    setBgf2 (true);
399 
400 	if (value & (1 << 30))
401 	    setBgf1 (true);
402 
403 	if (value & (1 << 31))
404 	    setFieldPhase (true);
405     }
406     else if (packing == FILM24_PACKING)
407     {
408 	_time = value & ~((1 << 6) | (1 << 7));
409     }
410     else // packing == TV60_PACKING
411     {
412 	_time = value;
413     }
414 }
415 
416 
417 unsigned int
userData() const418 TimeCode::userData () const
419 {
420     return _user;
421 }
422 
423 
424 void
setUserData(unsigned int value)425 TimeCode::setUserData (unsigned int value)
426 {
427     _user = value;
428 }
429 
430 
431 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
432