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>
35
37 {
38 /* only works for multiples of NTSC 29.97 */
39 int drop_frames = 0;
40 int d, m, frames_per_10mins;
41
42 if (fps && fps % 30 == 0) {
43 drop_frames = fps / 30 * 2;
44 frames_per_10mins = fps / 30 * 17982;
45 } else
46 return framenum;
47
48 d = framenum / frames_per_10mins;
49 m = framenum % frames_per_10mins;
50
51 return framenum + 9
U * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10));
52 }
53
55 {
56 unsigned fps = tc->
fps;
59
60 framenum += tc->
start;
61 if (drop)
63 ff = framenum % fps;
64 ss = framenum / fps % 60;
65 mm = framenum / (fps*60LL) % 60;
66 hh = framenum / (fps*3600LL) % 24;
68 }
69
71 {
72 uint32_t tc = 0;
73
74 /* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS.
75 See SMPTE ST 12-1:2014 Sec 12.1 for more info. */
77 if (ff % 2 == 1) {
79 tc |= (1 << 7);
80 else
81 tc |= (1 << 23);
82 }
83 ff /= 2;
84 }
85
86 hh = hh % 24;
89 ff = ff % 40;
90
91 tc |= drop << 30;
92 tc |= (ff / 10) << 28;
93 tc |= (ff % 10) << 24;
94 tc |= (
ss / 10) << 20;
95 tc |= (
ss % 10) << 16;
96 tc |= (mm / 10) << 12;
97 tc |= (mm % 10) << 8;
98 tc |= (hh / 10) << 4;
99 tc |= (hh % 10);
100
101 return tc;
102 }
103
105 {
106 unsigned fps = tc->
fps;
108 int hh, mm,
ss, ff, ff_len, neg = 0;
109 int64_t framenum = framenum_arg;
110
111 framenum += tc->
start;
112 if (drop)
114 if (framenum < 0) {
115 framenum = -framenum;
117 }
118 ff = framenum % fps;
119 ss = framenum / fps % 60;
120 mm = framenum / (fps*60LL) % 60;
121 hh = framenum / (fps*3600LL);
123 hh = hh % 24;
124 ff_len = fps > 10000 ? 5 : fps > 1000 ? 4 : fps > 100 ? 3 : fps > 10 ? 2 : 1;
126 neg ? "-" : "",
127 hh, mm,
ss, drop ?
';' :
':', ff_len, ff);
128 return buf;
129 }
130
132 {
133 unsigned hh, mm,
ss, ff, drop;
135
137 hh, mm,
ss, drop ?
';' :
':', ff);
138 return buf;
139
140 }
141
143 {
145 }
146
148 {
150 "%02"PRIu32":%02"PRIu32":%02"PRIu32"%c%02"PRIu32,
151 tc25bit>>19 & 0x1f, // 5-bit hours
152 tc25bit>>13 & 0x3f, // 6-bit minutes
153 tc25bit>>6 & 0x3f, // 6-bit seconds
154 tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag
155 tc25bit & 0x3f); // 6-bit frames
156 return buf;
157 }
158
160 {
162 static const int supported_fps[] = {
163 24, 25, 30, 48, 50, 60, 100, 120, 150,
164 };
165
167 if (fps == supported_fps[
i])
168 return 0;
169 return -1;
170 }
171
173 {
174 if ((
int)tc->
fps <= 0) {
175 av_log(log_ctx,
AV_LOG_ERROR,
"Valid timecode frame rate must be specified. Minimum value is 1\n");
177 }
179 av_log(log_ctx,
AV_LOG_ERROR,
"Drop frame is only allowed with multiples of 30000/1001 FPS\n");
181 }
185 }
186 return 0;
187 }
188
190 {
191 if (!rate.
den || !rate.
num)
192 return -1;
193 return (rate.
num + rate.
den/2LL) / rate.
den;
194 }
195
197 {
199 }
200
202 {
203 memset(tc, 0, sizeof(*tc));
209 }
210
212 {
214
215 memset(tc, 0, sizeof(*tc));
219
223
224 tc->
start = (hh*3600 + mm*60 +
ss) * tc->
fps + ff;
226 int tmins = 60*hh + mm;
227 tc->
start -= (tc->
fps / 30 * 2) * (tmins - tmins/10);
228 }
229 return 0;
230 }
231
233 {
236
237 if (sscanf(str,
"%d:%d:%d%c%d", &hh, &mm, &
ss, &
c, &ff) != 5) {
239 "syntax: hh:mm:ss[:;.]ff\n");
241 }
243
245 }