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*60) % 60;
65 hh = framenum / (fps*3600) % 24;
67 }
68
70 {
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) {
79 else
81 }
82 ff /= 2;
83 }
84
85 hh = hh % 24;
88 ff = ff % 40;
89
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;
99
101 }
102
104 {
107 int hh, mm,
ss, ff, ff_len, neg = 0;
108
109 framenum +=
tc->start;
110 if (drop)
112 if (framenum < 0) {
113 framenum = -framenum;
115 }
116 ff = framenum % fps;
117 ss = framenum / fps % 60;
118 mm = framenum / (fps*60LL) % 60;
119 hh = framenum / (fps*3600LL);
121 hh = hh % 24;
122 ff_len = fps > 10000 ? 5 : fps > 1000 ? 4 : fps > 100 ? 3 : fps > 10 ? 2 : 1;
124 neg ? "-" : "",
125 hh, mm,
ss, drop ?
';' :
':', ff_len, ff);
126 return buf;
127 }
128
130 {
131 unsigned low = bcd & 0xf;
132 unsigned high = bcd >> 4;
133 if (low > 9 || high > 9)
134 return 0;
135 return low + 10*high;
136 }
137
139 {
140 unsigned hh =
bcd2uint(tcsmpte & 0x3f);
// 6-bit hours
141 unsigned mm =
bcd2uint(tcsmpte>>8 & 0x7f);
// 7-bit minutes
142 unsigned ss =
bcd2uint(tcsmpte>>16 & 0x7f);
// 7-bit seconds
143 unsigned ff =
bcd2uint(tcsmpte>>24 & 0x3f);
// 6-bit frames
144 unsigned drop = tcsmpte & 1<<30 && !prevent_df; // 1-bit drop if not arbitrary bit
145
147 ff <<= 1;
148 if (!skip_field) {
150 ff += !!(tcsmpte & 1 << 7);
151 else
152 ff += !!(tcsmpte & 1 << 23);
153 }
154 }
155
157 hh, mm,
ss, drop ?
';' :
':', ff);
158 return buf;
159
160 }
161
163 {
165 }
166
168 {
170 "%02"PRIu32":%02"PRIu32":%02"PRIu32"%c%02"PRIu32,
171 tc25bit>>19 & 0x1f, // 5-bit hours
172 tc25bit>>13 & 0x3f, // 6-bit minutes
173 tc25bit>>6 & 0x3f, // 6-bit seconds
174 tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag
175 tc25bit & 0x3f); // 6-bit frames
176 return buf;
177 }
178
180 {
182 static const int supported_fps[] = {
183 24, 25, 30, 48, 50, 60, 100, 120, 150,
184 };
185
187 if (fps == supported_fps[
i])
188 return 0;
189 return -1;
190 }
191
193 {
194 if ((
int)
tc->fps <= 0) {
195 av_log(log_ctx,
AV_LOG_ERROR,
"Valid timecode frame rate must be specified. Minimum value is 1\n");
197 }
199 av_log(log_ctx,
AV_LOG_ERROR,
"Drop frame is only allowed with multiples of 30000/1001 FPS\n");
201 }
204 tc->rate.num,
tc->rate.den);
205 }
206 return 0;
207 }
208
210 {
211 if (!rate.
den || !rate.
num)
212 return -1;
213 return (rate.
num + rate.
den/2) / rate.
den;
214 }
215
217 {
219 }
220
222 {
223 memset(
tc, 0,
sizeof(*
tc));
229 }
230
232 {
234
235 memset(
tc, 0,
sizeof(*
tc));
239
243
244 tc->start = (hh*3600 + mm*60 +
ss) *
tc->fps + ff;
246 int tmins = 60*hh + mm;
247 tc->start -= (
tc->fps / 30 * 2) * (tmins - tmins/10);
248 }
249 return 0;
250 }
251
253 {
256
257 if (sscanf(
str,
"%d:%d:%d%c%d", &hh, &mm, &
ss, &
c, &ff) != 5) {
259 "syntax: hh:mm:ss[:;.]ff\n");
261 }
263
265 }