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 "timecode.h"
31 #include "log.h"
32 #include "error.h"
33 
34 int av_timecode_adjust_ntsc_framenum2(int framenum, int fps)
35 {
36  /* only works for NTSC 29.97 and 59.94 */
37  int drop_frames = 0;
38  int d, m, frames_per_10mins;
39 
40  if (fps == 30) {
41  drop_frames = 2;
42  frames_per_10mins = 17982;
43  } else if (fps == 60) {
44  drop_frames = 4;
45  frames_per_10mins = 35964;
46  } else
47  return framenum;
48 
49  d = framenum / frames_per_10mins;
50  m = framenum % frames_per_10mins;
51 
52  return framenum + 9U * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10));
53 }
54 
55 uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum)
56 {
57  unsigned fps = tc->fps;
58  int drop = !!(tc->flags & AV_TIMECODE_FLAG_DROPFRAME);
59  int hh, mm, ss, ff;
60 
61  framenum += tc->start;
62  if (drop)
63  framenum = av_timecode_adjust_ntsc_framenum2(framenum, tc->fps);
64  ff = framenum % fps;
65  ss = framenum / fps % 60;
66  mm = framenum / (fps*60) % 60;
67  hh = framenum / (fps*3600) % 24;
68  return 0 << 31 | // color frame flag (0: unsync mode, 1: sync mode)
69  drop << 30 | // drop frame flag (0: non drop, 1: drop)
70  (ff / 10) << 28 | // tens of frames
71  (ff % 10) << 24 | // units of frames
72  0 << 23 | // PC (NTSC) or BGF0 (PAL)
73  (ss / 10) << 20 | // tens of seconds
74  (ss % 10) << 16 | // units of seconds
75  0 << 15 | // BGF0 (NTSC) or BGF2 (PAL)
76  (mm / 10) << 12 | // tens of minutes
77  (mm % 10) << 8 | // units of minutes
78  0 << 7 | // BGF2 (NTSC) or PC (PAL)
79  0 << 6 | // BGF1
80  (hh / 10) << 4 | // tens of hours
81  (hh % 10); // units of hours
82 }
83 
84 char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
85 {
86  int fps = tc->fps;
87  int drop = tc->flags & AV_TIMECODE_FLAG_DROPFRAME;
88  int hh, mm, ss, ff, neg = 0;
89 
90  framenum += tc->start;
91  if (drop)
92  framenum = av_timecode_adjust_ntsc_framenum2(framenum, fps);
93  if (framenum < 0) {
94  framenum = -framenum;
95  neg = tc->flags & AV_TIMECODE_FLAG_ALLOWNEGATIVE;
96  }
97  ff = framenum % fps;
98  ss = framenum / fps % 60;
99  mm = framenum / (fps*60LL) % 60;
100  hh = framenum / (fps*3600LL);
101  if (tc->flags & AV_TIMECODE_FLAG_24HOURSMAX)
102  hh = hh % 24;
103  snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%02d",
104  neg ? "-" : "",
105  hh, mm, ss, drop ? ';' : ':', ff);
106  return buf;
107 }
108 
109 static unsigned bcd2uint(uint8_t bcd)
110 {
111  unsigned low = bcd & 0xf;
112  unsigned high = bcd >> 4;
113  if (low > 9 || high > 9)
114  return 0;
115  return low + 10*high;
116 }
117 
118 char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df)
119 {
120  unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours
121  unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes
122  unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds
123  unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames
124  unsigned drop = tcsmpte & 1<<30 && !prevent_df; // 1-bit drop if not arbitrary bit
125  snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u",
126  hh, mm, ss, drop ? ';' : ':', ff);
127  return buf;
128 }
129 
130 char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit)
131 {
133  "%02"PRIu32":%02"PRIu32":%02"PRIu32"%c%02"PRIu32,
134  tc25bit>>19 & 0x1f, // 5-bit hours
135  tc25bit>>13 & 0x3f, // 6-bit minutes
136  tc25bit>>6 & 0x3f, // 6-bit seconds
137  tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag
138  tc25bit & 0x3f); // 6-bit frames
139  return buf;
140 }
141 
142 static int check_fps(int fps)
143 {
144  int i;
145  static const int supported_fps[] = {
146  24, 25, 30, 48, 50, 60, 100, 120, 150,
147  };
148 
149  for (i = 0; i < FF_ARRAY_ELEMS(supported_fps); i++)
150  if (fps == supported_fps[i])
151  return 0;
152  return -1;
153 }
154 
155 static int check_timecode(void *log_ctx, AVTimecode *tc)
156 {
157  if ((int)tc->fps <= 0) {
158  av_log(log_ctx, AV_LOG_ERROR, "Valid timecode frame rate must be specified. Minimum value is 1\n");
159  return AVERROR(EINVAL);
160  }
161  if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps != 30 && tc->fps != 60) {
162  av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with 30000/1001 or 60000/1001 FPS\n");
163  return AVERROR(EINVAL);
164  }
165  if (check_fps(tc->fps) < 0) {
166  av_log(log_ctx, AV_LOG_WARNING, "Using non-standard frame rate %d/%d\n",
167  tc->rate.num, tc->rate.den);
168  }
169  return 0;
170 }
171 
173 {
174  if (!rate.den || !rate.num)
175  return -1;
176  return (rate.num + rate.den/2) / rate.den;
177 }
178 
180 {
181  return check_fps(fps_from_frame_rate(rate));
182 }
183 
184 int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx)
185 {
186  memset(tc, 0, sizeof(*tc));
187  tc->start = frame_start;
188  tc->flags = flags;
189  tc->rate = rate;
190  tc->fps = fps_from_frame_rate(rate);
191  return check_timecode(log_ctx, tc);
192 }
193 
194 int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
195 {
196  char c;
197  int hh, mm, ss, ff, ret;
198 
199  if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) {
200  av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, "
201  "syntax: hh:mm:ss[:;.]ff\n");
202  return AVERROR_INVALIDDATA;
203  }
204 
205  memset(tc, 0, sizeof(*tc));
206  tc->flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ...
207  tc->rate = rate;
208  tc->fps = fps_from_frame_rate(rate);
209 
210  ret = check_timecode(log_ctx, tc);
211  if (ret < 0)
212  return ret;
213 
214  tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff;
215  if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */
216  int tmins = 60*hh + mm;
217  tc->start -= (tc->fps == 30 ? 2 : 4) * (tmins - tmins/10);
218  }
219  return 0;
220 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
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:179
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:118
bcd2uint
static unsigned bcd2uint(uint8_t bcd)
Definition: timecode.c:109
U
#define U(x)
Definition: vp56_arith.h:37
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:84
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
AVRational::num
int num
Numerator.
Definition: rational.h:59
check_timecode
static int check_timecode(void *log_ctx, AVTimecode *tc)
Definition: timecode.c:155
frame_start
static int frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1751
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
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:184
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:34
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_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:55
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
fps_from_frame_rate
static int fps_from_frame_rate(AVRational rate)
Definition: timecode.c:172
uint8_t
uint8_t
Definition: audio_convert.c:194
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:142
AV_TIMECODE_FLAG_DROPFRAME
@ AV_TIMECODE_FLAG_DROPFRAME
timecode is drop frame
Definition: timecode.h:36
ret
ret
Definition: filter_design.txt:187
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
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:130
AVRational::den
int den
Denominator.
Definition: rational.h:60
tc
#define tc
Definition: regdef.h:69
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
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:194
AVTimecode
Definition: timecode.h:41
snprintf
#define snprintf
Definition: snprintf.h:34