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