FFmpeg
timecode.c
Go to the documentation of this file.
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>
30 #include "common.h"
31 #include "timecode.h"
32 #include "log.h"
33 #include "error.h"
34 
35 int av_timecode_adjust_ntsc_framenum2(int framenum, int fps)
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 + 9U * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10));
51 }
52 
53 uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum)
54 {
55  unsigned fps = tc->fps;
56  int drop = !!(tc->flags & AV_TIMECODE_FLAG_DROPFRAME);
57  int hh, mm, ss, ff;
58 
59  framenum += tc->start;
60  if (drop)
61  framenum = av_timecode_adjust_ntsc_framenum2(framenum, tc->fps);
62  ff = framenum % fps;
63  ss = framenum / fps % 60;
64  mm = framenum / (fps*60) % 60;
65  hh = framenum / (fps*3600) % 24;
66  return av_timecode_get_smpte(tc->rate, drop, hh, mm, ss, ff);
67 }
68 
69 uint32_t av_timecode_get_smpte(AVRational rate, int drop, int hh, int mm, int ss, int ff)
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. */
75  if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
76  if (ff % 2 == 1) {
77  if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
78  tc |= (1 << 7);
79  else
80  tc |= (1 << 23);
81  }
82  ff /= 2;
83  }
84 
85  hh = hh % 24;
86  mm = av_clip(mm, 0, 59);
87  ss = av_clip(ss, 0, 59);
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 
103 char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
104 {
105  int fps = tc->fps;
106  int drop = tc->flags & AV_TIMECODE_FLAG_DROPFRAME;
107  int hh, mm, ss, ff, ff_len, neg = 0;
108 
109  framenum += tc->start;
110  if (drop)
111  framenum = av_timecode_adjust_ntsc_framenum2(framenum, fps);
112  if (framenum < 0) {
113  framenum = -framenum;
114  neg = tc->flags & AV_TIMECODE_FLAG_ALLOWNEGATIVE;
115  }
116  ff = framenum % fps;
117  ss = framenum / fps % 60;
118  mm = framenum / (fps*60LL) % 60;
119  hh = framenum / (fps*3600LL);
120  if (tc->flags & AV_TIMECODE_FLAG_24HOURSMAX)
121  hh = hh % 24;
122  ff_len = fps > 10000 ? 5 : fps > 1000 ? 4 : fps > 100 ? 3 : fps > 10 ? 2 : 1;
123  snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%0*d",
124  neg ? "-" : "",
125  hh, mm, ss, drop ? ';' : ':', ff_len, ff);
126  return buf;
127 }
128 
129 static unsigned bcd2uint(uint8_t bcd)
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 
138 char *av_timecode_make_smpte_tc_string2(char *buf, AVRational rate, uint32_t tcsmpte, int prevent_df, int skip_field)
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 
146  if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
147  ff <<= 1;
148  if (!skip_field) {
149  if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
150  ff += !!(tcsmpte & 1 << 7);
151  else
152  ff += !!(tcsmpte & 1 << 23);
153  }
154  }
155 
156  snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u",
157  hh, mm, ss, drop ? ';' : ':', ff);
158  return buf;
159 
160 }
161 
162 char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df)
163 {
164  return av_timecode_make_smpte_tc_string2(buf, (AVRational){30, 1}, tcsmpte, prevent_df, 1);
165 }
166 
167 char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit)
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 
179 static int check_fps(int fps)
180 {
181  int i;
182  static const int supported_fps[] = {
183  24, 25, 30, 48, 50, 60, 100, 120, 150,
184  };
185 
186  for (i = 0; i < FF_ARRAY_ELEMS(supported_fps); i++)
187  if (fps == supported_fps[i])
188  return 0;
189  return -1;
190 }
191 
192 static int check_timecode(void *log_ctx, AVTimecode *tc)
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");
196  return AVERROR(EINVAL);
197  }
198  if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps % 30 != 0) {
199  av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with multiples of 30000/1001 FPS\n");
200  return AVERROR(EINVAL);
201  }
202  if (check_fps(tc->fps) < 0) {
203  av_log(log_ctx, AV_LOG_WARNING, "Using non-standard frame rate %d/%d\n",
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 {
218  return check_fps(fps_from_frame_rate(rate));
219 }
220 
221 int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx)
222 {
223  memset(tc, 0, sizeof(*tc));
224  tc->start = frame_start;
225  tc->flags = flags;
226  tc->rate = rate;
227  tc->fps = fps_from_frame_rate(rate);
228  return check_timecode(log_ctx, tc);
229 }
230 
231 int av_timecode_init_from_components(AVTimecode *tc, AVRational rate, int flags, int hh, int mm, int ss, int ff, void *log_ctx)
232 {
233  int ret;
234 
235  memset(tc, 0, sizeof(*tc));
236  tc->flags = flags;
237  tc->rate = rate;
238  tc->fps = fps_from_frame_rate(rate);
239 
240  ret = check_timecode(log_ctx, tc);
241  if (ret < 0)
242  return ret;
243 
244  tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff;
245  if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */
246  int tmins = 60*hh + mm;
247  tc->start -= (tc->fps / 30 * 2) * (tmins - tmins/10);
248  }
249  return 0;
250 }
251 
252 int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
253 {
254  char c;
255  int hh, mm, ss, ff, flags;
256 
257  if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) {
258  av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, "
259  "syntax: hh:mm:ss[:;.]ff\n");
260  return AVERROR_INVALIDDATA;
261  }
262  flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ...
263 
264  return av_timecode_init_from_components(tc, rate, flags, hh, mm, ss, ff, log_ctx);
265 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
av_clip
#define av_clip
Definition: common.h:98
av_timecode_check_frame_rate
int av_timecode_check_frame_rate(AVRational rate)
Check if the timecode feature is available for the given frame rate.
Definition: timecode.c:216
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
av_timecode_make_smpte_tc_string
char * av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df)
Get the timecode string from the SMPTE timecode format.
Definition: timecode.c:162
bcd2uint
static unsigned bcd2uint(uint8_t bcd)
Definition: timecode.c:129
av_timecode_get_smpte
uint32_t av_timecode_get_smpte(AVRational rate, int drop, int hh, int mm, int ss, int ff)
Convert sei info to SMPTE 12M binary representation.
Definition: timecode.c:69
timecode.h
av_timecode_make_string
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
Definition: timecode.c:103
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:202
AVRational::num
int num
Numerator.
Definition: rational.h:59
check_timecode
static int check_timecode(void *log_ctx, AVTimecode *tc)
Definition: timecode.c:192
frame_start
static int frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1708
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_timecode_init
int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx)
Init a timecode struct with the passed parameters.
Definition: timecode.c:221
av_timecode_adjust_ntsc_framenum2
int av_timecode_adjust_ntsc_framenum2(int framenum, int fps)
Adjust frame number for NTSC drop frame time code.
Definition: timecode.c:35
if
if(ret)
Definition: filter_design.txt:179
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
error.h
av_timecode_init_from_components
int av_timecode_init_from_components(AVTimecode *tc, AVRational rate, int flags, int hh, int mm, int ss, int ff, void *log_ctx)
Init a timecode struct from the passed timecode components.
Definition: timecode.c:231
AV_TIMECODE_FLAG_24HOURSMAX
@ AV_TIMECODE_FLAG_24HOURSMAX
timecode wraps after 24 hours
Definition: timecode.h:37
av_timecode_get_smpte_from_framenum
uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum)
Convert frame number to SMPTE 12M binary representation.
Definition: timecode.c:53
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
av_timecode_make_smpte_tc_string2
char * av_timecode_make_smpte_tc_string2(char *buf, AVRational rate, uint32_t tcsmpte, int prevent_df, int skip_field)
Get the timecode string from the SMPTE timecode format.
Definition: timecode.c:138
fps_from_frame_rate
static int fps_from_frame_rate(AVRational rate)
Definition: timecode.c:209
common.h
AV_TIMECODE_FLAG_ALLOWNEGATIVE
@ AV_TIMECODE_FLAG_ALLOWNEGATIVE
negative time values are allowed
Definition: timecode.h:38
check_fps
static int check_fps(int fps)
Definition: timecode.c:179
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
AV_TIMECODE_FLAG_DROPFRAME
@ AV_TIMECODE_FLAG_DROPFRAME
timecode is drop frame
Definition: timecode.h:36
ret
ret
Definition: filter_design.txt:187
U
#define U(x)
Definition: vpx_arith.h:37
av_timecode_make_mpeg_tc_string
char * av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit)
Get the timecode string from the 25-bit timecode format (MPEG GOP format).
Definition: timecode.c:167
AVRational::den
int den
Denominator.
Definition: rational.h:60
tc
#define tc
Definition: regdef.h:69
d
d
Definition: ffmpeg_filter.c:425
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
av_timecode_init_from_string
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
Definition: timecode.c:252
AVTimecode
Definition: timecode.h:41
snprintf
#define snprintf
Definition: snprintf.h:34