1 /*
2 * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier <baptiste.coudurier@gmail.com>
3 * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch <clement.boesch@smartjog.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Timecode helpers
25 * @see https://en.wikipedia.org/wiki/SMPTE_time_code
26 * @see http://www.dropframetimecode.org
27 */
28
29 #include <stdio.h>
34
36 {
37 /* only works for multiples of NTSC 29.97 */
38 int drop_frames = 0;
39 int d, m, frames_per_10mins;
40
41 if (fps && fps % 30 == 0) {
42 drop_frames = fps / 30 * 2;
43 frames_per_10mins = fps / 30 * 17982;
44 } else
45 return framenum;
46
47 d = framenum / frames_per_10mins;
48 m = framenum % frames_per_10mins;
49
50 return framenum + 9
U * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10));
51 }
52
54 {
55 unsigned fps = tc->
fps;
58
59 framenum += tc->
start;
60 if (drop)
62 ff = framenum % fps;
63 ss = framenum / fps % 60;
64 mm = framenum / (fps*60LL) % 60;
65 hh = framenum / (fps*3600LL) % 24;
67 }
68
70 {
71 uint32_t tc = 0;
72
73 /* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS.
74 See SMPTE ST 12-1:2014 Sec 12.1 for more info. */
76 if (ff % 2 == 1) {
78 tc |= (1 << 7);
79 else
80 tc |= (1 << 23);
81 }
82 ff /= 2;
83 }
84
85 hh = hh % 24;
88 ff = ff % 40;
89
90 tc |= drop << 30;
91 tc |= (ff / 10) << 28;
92 tc |= (ff % 10) << 24;
93 tc |= (
ss / 10) << 20;
94 tc |= (
ss % 10) << 16;
95 tc |= (mm / 10) << 12;
96 tc |= (mm % 10) << 8;
97 tc |= (hh / 10) << 4;
98 tc |= (hh % 10);
99
100 return tc;
101 }
102
104 {
107 int hh, mm,
ss, ff, ff_len, neg = 0;
108 int64_t framenum = framenum_arg;
109
110 framenum += tc->
start;
111 if (drop)
113 if (framenum < 0) {
114 framenum = -framenum;
116 }
117 ff = framenum % fps;
118 ss = framenum / fps % 60;
119 mm = framenum / (fps*60LL) % 60;
120 hh = framenum / (fps*3600LL);
122 hh = hh % 24;
123 ff_len = fps > 10000 ? 5 : fps > 1000 ? 4 : fps > 100 ? 3 : fps > 10 ? 2 : 1;
125 neg ? "-" : "",
126 hh, mm,
ss, drop ?
';' :
':', ff_len, ff);
127 return buf;
128 }
129
131 {
132 unsigned low = bcd & 0xf;
133 unsigned high = bcd >> 4;
134 if (low > 9 ||
high > 9)
135 return 0;
136 return low + 10*
high;
137 }
138
140 {
141 unsigned hh =
bcd2uint(tcsmpte & 0x3f);
// 6-bit hours
142 unsigned mm =
bcd2uint(tcsmpte>>8 & 0x7f);
// 7-bit minutes
143 unsigned ss =
bcd2uint(tcsmpte>>16 & 0x7f);
// 7-bit seconds
144 unsigned ff =
bcd2uint(tcsmpte>>24 & 0x3f);
// 6-bit frames
145 unsigned drop = tcsmpte & 1<<30 && !prevent_df; // 1-bit drop if not arbitrary bit
146
148 ff <<= 1;
149 if (!skip_field) {
151 ff += !!(tcsmpte & 1 << 7);
152 else
153 ff += !!(tcsmpte & 1 << 23);
154 }
155 }
156
158 hh, mm,
ss, drop ?
';' :
':', ff);
159 return buf;
160
161 }
162
164 {
166 }
167
169 {
171 "%02"PRIu32":%02"PRIu32":%02"PRIu32"%c%02"PRIu32,
172 tc25bit>>19 & 0x1f, // 5-bit hours
173 tc25bit>>13 & 0x3f, // 6-bit minutes
174 tc25bit>>6 & 0x3f, // 6-bit seconds
175 tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag
176 tc25bit & 0x3f); // 6-bit frames
177 return buf;
178 }
179
181 {
183 static const int supported_fps[] = {
184 24, 25, 30, 48, 50, 60, 100, 120, 150,
185 };
186
188 if (fps == supported_fps[
i])
189 return 0;
190 return -1;
191 }
192
194 {
195 if ((
int)tc->
fps <= 0) {
196 av_log(log_ctx,
AV_LOG_ERROR,
"Valid timecode frame rate must be specified. Minimum value is 1\n");
198 }
200 av_log(log_ctx,
AV_LOG_ERROR,
"Drop frame is only allowed with multiples of 30000/1001 FPS\n");
202 }
206 }
207 return 0;
208 }
209
211 {
212 if (!rate.
den || !rate.
num)
213 return -1;
214 return (rate.
num + rate.
den/2LL) / rate.
den;
215 }
216
218 {
220 }
221
223 {
224 memset(tc, 0, sizeof(*tc));
230 }
231
233 {
235
236 memset(tc, 0, sizeof(*tc));
240
244
245 tc->
start = (hh*3600 + mm*60 +
ss) * tc->
fps + ff;
247 int tmins = 60*hh + mm;
248 tc->
start -= (tc->
fps / 30 * 2) * (tmins - tmins/10);
249 }
250 return 0;
251 }
252
254 {
257
258 if (sscanf(str,
"%d:%d:%d%c%d", &hh, &mm, &
ss, &
c, &ff) != 5) {
260 "syntax: hh:mm:ss[:;.]ff\n");
262 }
264
266 }