libavutil/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 + 9 * 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;
96  }
97  ff = framenum % fps;
98  ss = framenum / fps % 60;
99  mm = framenum / (fps*60) % 60;
100  hh = framenum / (fps*3600);
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 {
132  snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u",
133  tc25bit>>19 & 0x1f, // 5-bit hours
134  tc25bit>>13 & 0x3f, // 6-bit minutes
135  tc25bit>>6 & 0x3f, // 6-bit seconds
136  tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag
137  tc25bit & 0x3f); // 6-bit frames
138  return buf;
139 }
140 
141 static int check_fps(int fps)
142 {
143  int i;
144  static const int supported_fps[] = {24, 25, 30, 50, 60};
145 
146  for (i = 0; i < FF_ARRAY_ELEMS(supported_fps); i++)
147  if (fps == supported_fps[i])
148  return 0;
149  return -1;
150 }
151 
152 static int check_timecode(void *log_ctx, AVTimecode *tc)
153 {
154  if (tc->fps <= 0) {
155  av_log(log_ctx, AV_LOG_ERROR, "Timecode frame rate must be specified\n");
156  return AVERROR(EINVAL);
157  }
158  if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps != 30 && tc->fps != 60) {
159  av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with 30000/1001 or 60000/1001 FPS\n");
160  return AVERROR(EINVAL);
161  }
162  if (check_fps(tc->fps) < 0) {
163  av_log(log_ctx, AV_LOG_ERROR, "Timecode frame rate %d/%d not supported\n",
164  tc->rate.num, tc->rate.den);
165  return AVERROR_PATCHWELCOME;
166  }
167  return 0;
168 }
169 
171 {
172  if (!rate.den || !rate.num)
173  return -1;
174  return (rate.num + rate.den/2) / rate.den;
175 }
176 
178 {
179  return check_fps(fps_from_frame_rate(rate));
180 }
181 
182 int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx)
183 {
184  memset(tc, 0, sizeof(*tc));
185  tc->start = frame_start;
186  tc->flags = flags;
187  tc->rate = rate;
188  tc->fps = fps_from_frame_rate(rate);
189  return check_timecode(log_ctx, tc);
190 }
191 
192 int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
193 {
194  char c;
195  int hh, mm, ss, ff, ret;
196 
197  if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) {
198  av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, "
199  "syntax: hh:mm:ss[:;.]ff\n");
200  return AVERROR_INVALIDDATA;
201  }
202 
203  memset(tc, 0, sizeof(*tc));
204  tc->flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ...
205  tc->rate = rate;
206  tc->fps = fps_from_frame_rate(rate);
207 
208  ret = check_timecode(log_ctx, tc);
209  if (ret < 0)
210  return ret;
211 
212  tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff;
213  if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */
214  int tmins = 60*hh + mm;
215  tc->start -= 2 * (tmins - tmins/10);
216  }
217  return 0;
218 }
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int num
numerator
Definition: rational.h:44
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
#define tc
Definition: regdef.h:69
#define FF_ARRAY_ELEMS(a)
negative time values are allowed
Timecode helpers header.
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).
set threshold d
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
static int check_fps(int fps)
uint8_t
window constants for m
int start
timecode frame start (first base frame number)
int av_timecode_check_frame_rate(AVRational rate)
Check if the timecode feature is available for the given frame rate.
#define AV_TIMECODE_STR_SIZE
static int fps_from_frame_rate(AVRational rate)
error code definitions
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
unsigned fps
frame per second; must be consistent with the rate field
ret
Definition: avfilter.c:821
int av_timecode_adjust_ntsc_framenum2(int framenum, int fps)
Adjust frame number for NTSC drop frame time code.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static int check_timecode(void *log_ctx, AVTimecode *tc)
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
timecode wraps after 24 hours
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
AVRational rate
frame rate in rational form
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
rational number numerator/denominator
Definition: rational.h:43
#define snprintf
Definition: snprintf.h:34
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum)
Convert frame number to SMPTE 12M binary representation.
static int flags
Definition: cpu.c:23
int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx)
Init a timecode struct with the passed parameters.
static double c[64]
int den
denominator
Definition: rational.h:45
char * av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df)
Get the timecode string from the SMPTE timecode format.
uint32_t flags
flags such as drop frame, +24 hours support, ...
static unsigned bcd2uint(uint8_t bcd)
timecode is drop frame