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 45namespace Imf { 46 47 48TimeCode::TimeCode () 49{ 50 _time = 0; 51 _user = 0; 52} 53 54 55TimeCode::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 96TimeCode::TimeCode 97 (unsigned int timeAndFlags, 98 unsigned int userData, 99 Packing packing) 100{ 101 setTimeAndFlags (timeAndFlags, packing); 102 setUserData (userData); 103} 104 105 106TimeCode::TimeCode (const TimeCode &other) 107{ 108 _time = other._time; 109 _user = other._user; 110} 111 112 113TimeCode & 114TimeCode::operator = (const TimeCode &other) 115{ 116 _time = other._time; 117 _user = other._user; 118 return *this; 119} 120 121 122namespace { 123 124unsigned int 125bitField (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 133void 134setBitField (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 142int 143bcdToBinary (unsigned int bcd) 144{ 145 return int ((bcd & 0x0f) + 10 * ((bcd >> 4) & 0x0f)); 146} 147 148 149unsigned int 150binaryToBcd (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 161int 162TimeCode::hours () const 163{ 164 return bcdToBinary (bitField (_time, 24, 29)); 165} 166 167 168void 169TimeCode::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 179int 180TimeCode::minutes () const 181{ 182 return bcdToBinary (bitField (_time, 16, 22)); 183} 184 185 186void 187TimeCode::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 197int 198TimeCode::seconds () const 199{ 200 return bcdToBinary (bitField (_time, 8, 14)); 201} 202 203 204void 205TimeCode::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 215int 216TimeCode::frame () const 217{ 218 return bcdToBinary (bitField (_time, 0, 5)); 219} 220 221 222void 223TimeCode::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 233bool 234TimeCode::dropFrame () const 235{ 236 return bool (bitField (_time, 6, 6)); 237} 238 239 240void 241TimeCode::setDropFrame (bool value) 242{ 243 setBitField (_time, 6, 6, (unsigned int) !!value); 244} 245 246 247bool 248TimeCode::colorFrame () const 249{ 250 return bool (bitField (_time, 7, 7)); 251} 252 253 254void 255TimeCode::setColorFrame (bool value) 256{ 257 setBitField (_time, 7, 7, (unsigned int) !!value); 258} 259 260 261bool 262TimeCode::fieldPhase () const 263{ 264 return bool (bitField (_time, 15, 15)); 265} 266 267 268void 269TimeCode::setFieldPhase (bool value) 270{ 271 setBitField (_time, 15, 15, (unsigned int) !!value); 272} 273 274 275bool 276TimeCode::bgf0 () const 277{ 278 return bool (bitField (_time, 23, 23)); 279} 280 281 282void 283TimeCode::setBgf0 (bool value) 284{ 285 setBitField (_time, 23, 23, (unsigned int) !!value); 286} 287 288 289bool 290TimeCode::bgf1 () const 291{ 292 return bool (bitField (_time, 30, 30)); 293} 294 295 296void 297TimeCode::setBgf1 (bool value) 298{ 299 setBitField (_time, 30, 30, (unsigned int) !!value); 300} 301 302 303bool 304TimeCode::bgf2 () const 305{ 306 return bool (bitField (_time, 31, 31)); 307} 308 309 310void 311TimeCode::setBgf2 (bool value) 312{ 313 setBitField (_time, 31, 31, (unsigned int) !!value); 314} 315 316 317int 318TimeCode::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 330void 331TimeCode::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 343unsigned int 344TimeCode::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 370void 371TimeCode::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 401unsigned int 402TimeCode::userData () const 403{ 404 return _user; 405} 406 407 408void 409TimeCode::setUserData (unsigned int value) 410{ 411 _user = value; 412} 413 414 415} // namespace Imf 416