Coverage Report

Created: 2025-09-08 07:52

/src/openexr/src/lib/OpenEXR/ImfTimeCode.cpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// SPDX-License-Identifier: BSD-3-Clause
3
// Copyright (c) Contributors to the OpenEXR Project.
4
//
5
6
//-----------------------------------------------------------------------------
7
//
8
//  class TimeCode
9
//
10
//-----------------------------------------------------------------------------
11
12
#include "Iex.h"
13
#include "ImfNamespace.h"
14
#include <ImfTimeCode.h>
15
16
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
17
18
TimeCode::TimeCode ()
19
4
{
20
4
    _time = 0;
21
4
    _user = 0;
22
4
}
23
24
TimeCode::TimeCode (
25
    int  hours,
26
    int  minutes,
27
    int  seconds,
28
    int  frame,
29
    bool dropFrame,
30
    bool colorFrame,
31
    bool fieldPhase,
32
    bool bgf0,
33
    bool bgf1,
34
    bool bgf2,
35
    int  binaryGroup1,
36
    int  binaryGroup2,
37
    int  binaryGroup3,
38
    int  binaryGroup4,
39
    int  binaryGroup5,
40
    int  binaryGroup6,
41
    int  binaryGroup7,
42
    int  binaryGroup8)
43
0
{
44
0
    setHours (hours);
45
0
    setMinutes (minutes);
46
0
    setSeconds (seconds);
47
0
    setFrame (frame);
48
0
    setDropFrame (dropFrame);
49
0
    setColorFrame (colorFrame);
50
0
    setFieldPhase (fieldPhase);
51
0
    setBgf0 (bgf0);
52
0
    setBgf1 (bgf1);
53
0
    setBgf2 (bgf2);
54
0
    setBinaryGroup (1, binaryGroup1);
55
0
    setBinaryGroup (2, binaryGroup2);
56
0
    setBinaryGroup (3, binaryGroup3);
57
0
    setBinaryGroup (4, binaryGroup4);
58
0
    setBinaryGroup (5, binaryGroup5);
59
0
    setBinaryGroup (6, binaryGroup6);
60
0
    setBinaryGroup (7, binaryGroup7);
61
0
    setBinaryGroup (8, binaryGroup8);
62
0
}
63
64
TimeCode::TimeCode (
65
    unsigned int timeAndFlags, unsigned int userData, Packing packing)
66
4
{
67
4
    setTimeAndFlags (timeAndFlags, packing);
68
4
    setUserData (userData);
69
4
}
70
71
TimeCode::TimeCode (const TimeCode& other)
72
4
{
73
4
    _time = other._time;
74
4
    _user = other._user;
75
4
}
76
77
TimeCode&
78
TimeCode::operator= (const TimeCode& other)
79
4
{
80
4
    if (&other != this)
81
4
    {
82
4
        _time = other._time;
83
4
        _user = other._user;
84
4
    }
85
4
    return *this;
86
4
}
87
88
bool
89
TimeCode::operator== (const TimeCode& c) const
90
0
{
91
0
    return (_time == c._time && _user == c._user);
92
0
}
93
94
bool
95
TimeCode::operator!= (const TimeCode& c) const
96
0
{
97
0
    return (_time != c._time || _user != c._user);
98
0
}
99
100
namespace
101
{
102
103
unsigned int
104
bitField (unsigned int value, int minBit, int maxBit)
105
0
{
106
0
    int          shift = minBit;
107
0
    unsigned int mask  = (~(~0U << (maxBit - minBit + 1)) << minBit);
108
0
    return (value & mask) >> shift;
109
0
}
110
111
void
112
setBitField (unsigned int& value, int minBit, int maxBit, unsigned int field)
113
0
{
114
0
    int          shift = minBit;
115
0
    unsigned int mask  = (~(~0U << (maxBit - minBit + 1)) << minBit);
116
0
    value              = ((value & ~mask) | ((field << shift) & mask));
117
0
}
118
119
int
120
bcdToBinary (unsigned int bcd)
121
0
{
122
0
    return int ((bcd & 0x0f) + 10 * ((bcd >> 4) & 0x0f));
123
0
}
124
125
unsigned int
126
binaryToBcd (int binary)
127
0
{
128
0
    int units = binary % 10;
129
0
    int tens  = (binary / 10) % 10;
130
0
    return (unsigned int) (units | (tens << 4));
131
0
}
132
133
} // namespace
134
135
int
136
TimeCode::hours () const
137
0
{
138
0
    return bcdToBinary (bitField (_time, 24, 29));
139
0
}
140
141
void
142
TimeCode::setHours (int value)
143
0
{
144
0
    if (value < 0 || value > 23)
145
0
        throw IEX_NAMESPACE::ArgExc ("Cannot set hours field in time code. "
146
0
                                     "New value is out of range.");
147
148
0
    setBitField (_time, 24, 29, binaryToBcd (value));
149
0
}
150
151
int
152
TimeCode::minutes () const
153
0
{
154
0
    return bcdToBinary (bitField (_time, 16, 22));
155
0
}
156
157
void
158
TimeCode::setMinutes (int value)
159
0
{
160
0
    if (value < 0 || value > 59)
161
0
        throw IEX_NAMESPACE::ArgExc ("Cannot set minutes field in time code. "
162
0
                                     "New value is out of range.");
163
164
0
    setBitField (_time, 16, 22, binaryToBcd (value));
165
0
}
166
167
int
168
TimeCode::seconds () const
169
0
{
170
0
    return bcdToBinary (bitField (_time, 8, 14));
171
0
}
172
173
void
174
TimeCode::setSeconds (int value)
175
0
{
176
0
    if (value < 0 || value > 59)
177
0
        throw IEX_NAMESPACE::ArgExc ("Cannot set seconds field in time code. "
178
0
                                     "New value is out of range.");
179
180
0
    setBitField (_time, 8, 14, binaryToBcd (value));
181
0
}
182
183
int
184
TimeCode::frame () const
185
0
{
186
0
    return bcdToBinary (bitField (_time, 0, 5));
187
0
}
188
189
void
190
TimeCode::setFrame (int value)
191
0
{
192
0
    if (value < 0 || value > 29)
193
0
        throw IEX_NAMESPACE::ArgExc ("Cannot set frame field in time code. "
194
0
                                     "New value is out of range.");
195
196
0
    setBitField (_time, 0, 5, binaryToBcd (value));
197
0
}
198
199
bool
200
TimeCode::dropFrame () const
201
0
{
202
0
    return !!bitField (_time, 6, 6);
203
0
}
204
205
void
206
TimeCode::setDropFrame (bool value)
207
0
{
208
0
    setBitField (_time, 6, 6, (unsigned int) !!value);
209
0
}
210
211
bool
212
TimeCode::colorFrame () const
213
0
{
214
0
    return !!bitField (_time, 7, 7);
215
0
}
216
217
void
218
TimeCode::setColorFrame (bool value)
219
0
{
220
0
    setBitField (_time, 7, 7, (unsigned int) !!value);
221
0
}
222
223
bool
224
TimeCode::fieldPhase () const
225
0
{
226
0
    return !!bitField (_time, 15, 15);
227
0
}
228
229
void
230
TimeCode::setFieldPhase (bool value)
231
0
{
232
0
    setBitField (_time, 15, 15, (unsigned int) !!value);
233
0
}
234
235
bool
236
TimeCode::bgf0 () const
237
0
{
238
0
    return !!bitField (_time, 23, 23);
239
0
}
240
241
void
242
TimeCode::setBgf0 (bool value)
243
0
{
244
0
    setBitField (_time, 23, 23, (unsigned int) !!value);
245
0
}
246
247
bool
248
TimeCode::bgf1 () const
249
0
{
250
0
    return !!bitField (_time, 30, 30);
251
0
}
252
253
void
254
TimeCode::setBgf1 (bool value)
255
0
{
256
0
    setBitField (_time, 30, 30, (unsigned int) !!value);
257
0
}
258
259
bool
260
TimeCode::bgf2 () const
261
0
{
262
0
    return !!bitField (_time, 31, 31);
263
0
}
264
265
void
266
TimeCode::setBgf2 (bool value)
267
0
{
268
0
    setBitField (_time, 31, 31, (unsigned int) !!value);
269
0
}
270
271
int
272
TimeCode::binaryGroup (int group) const
273
0
{
274
0
    if (group < 1 || group > 8)
275
0
        throw IEX_NAMESPACE::ArgExc (
276
0
            "Cannot extract binary group from time code "
277
0
            "user data.  Group number is out of range.");
278
279
0
    int minBit = 4 * (group - 1);
280
0
    int maxBit = minBit + 3;
281
0
    return int (bitField (_user, minBit, maxBit));
282
0
}
283
284
void
285
TimeCode::setBinaryGroup (int group, int value)
286
0
{
287
0
    if (group < 1 || group > 8)
288
0
        throw IEX_NAMESPACE::ArgExc (
289
0
            "Cannot extract binary group from time code "
290
0
            "user data.  Group number is out of range.");
291
292
0
    int minBit = 4 * (group - 1);
293
0
    int maxBit = minBit + 3;
294
0
    setBitField (_user, minBit, maxBit, (unsigned int) value);
295
0
}
296
297
unsigned int
298
TimeCode::timeAndFlags (Packing packing) const
299
0
{
300
0
    if (packing == TV50_PACKING)
301
0
    {
302
0
        unsigned int t = _time;
303
304
0
        t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
305
306
0
        t |= ((unsigned int) bgf0 () << 15);
307
0
        t |= ((unsigned int) bgf2 () << 23);
308
0
        t |= ((unsigned int) bgf1 () << 30);
309
0
        t |= ((unsigned int) fieldPhase () << 31);
310
311
0
        return t;
312
0
    }
313
0
    if (packing == FILM24_PACKING) { return _time & ~((1 << 6) | (1 << 7)); }
314
0
    else // packing == TV60_PACKING
315
0
    {
316
0
        return _time;
317
0
    }
318
0
}
319
320
void
321
TimeCode::setTimeAndFlags (unsigned int value, Packing packing)
322
4
{
323
4
    if (packing == TV50_PACKING)
324
0
    {
325
0
        _time =
326
0
            value & ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
327
328
0
        if (value & (1 << 15)) setBgf0 (true);
329
330
0
        if (value & (1 << 23)) setBgf2 (true);
331
332
0
        if (value & (1 << 30)) setBgf1 (true);
333
334
0
        if (value & (1 << 31)) setFieldPhase (true);
335
0
    }
336
4
    else if (packing == FILM24_PACKING)
337
0
    {
338
0
        _time = value & ~((1 << 6) | (1 << 7));
339
0
    }
340
4
    else // packing == TV60_PACKING
341
4
    {
342
4
        _time = value;
343
4
    }
344
4
}
345
346
unsigned int
347
TimeCode::userData () const
348
0
{
349
0
    return _user;
350
0
}
351
352
void
353
TimeCode::setUserData (unsigned int value)
354
4
{
355
4
    _user = value;
356
4
}
357
358
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT