FFmpeg
timecode.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * Unit tests for libavutil/timecode.c:
21  * av_timecode_init, av_timecode_init_from_components,
22  * av_timecode_init_from_string, av_timecode_make_string,
23  * av_timecode_get_smpte_from_framenum, av_timecode_get_smpte,
24  * av_timecode_make_smpte_tc_string, av_timecode_make_smpte_tc_string2,
25  * av_timecode_make_mpeg_tc_string, av_timecode_adjust_ntsc_framenum2,
26  * av_timecode_check_frame_rate
27  */
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "libavutil/macros.h"
33 #include "libavutil/rational.h"
34 #include "libavutil/timecode.h"
35 
36 static void test_check_frame_rate(void)
37 {
38  static const AVRational rates[] = {
39  {24, 1}, {25, 1}, {30, 1}, {48, 1}, {50, 1}, {60, 1},
40  {100, 1}, {120, 1}, {150, 1},
41  {30000, 1001}, {15, 1}, {12, 1},
42  {0, 0}, {30, 0},
43  };
44  for (int i = 0; i < FF_ARRAY_ELEMS(rates); i++)
45  printf("check_frame_rate %d/%d: %d\n",
46  rates[i].num, rates[i].den,
48 }
49 
50 static void test_init(void)
51 {
52  AVTimecode tc;
53  static const struct {
54  AVRational rate;
55  int flags;
56  int start;
57  } cases[] = {
58  { {25, 1}, 0, 0 },
59  { {30, 1}, AV_TIMECODE_FLAG_DROPFRAME, 0 },
60  { {24, 1}, 0, 100 },
61  { {0, 1}, 0, 0 },
62  { {25, 1}, AV_TIMECODE_FLAG_DROPFRAME, 0 },
63  { {30000, 1001}, AV_TIMECODE_FLAG_DROPFRAME, 0 },
64  { {25, 1}, AV_TIMECODE_FLAG_ALLOWNEGATIVE, -100 },
65  };
66 
67  for (int i = 0; i < FF_ARRAY_ELEMS(cases); i++) {
68  int ret = av_timecode_init(&tc, cases[i].rate, cases[i].flags, cases[i].start, NULL);
69  printf("init %d/%d flags:%d start:%d: ",
70  cases[i].rate.num, cases[i].rate.den, cases[i].flags, cases[i].start);
71  if (ret < 0) {
72  printf("error\n");
73  } else {
74  printf("ok fps=%d start=%d rate=%d/%d\n",
75  tc.fps, tc.start, tc.rate.num, tc.rate.den);
76  }
77  }
78 }
79 
80 static void test_init_from_components(void)
81 {
82  AVTimecode tc;
83  int ret;
84 
86  0, 0, 0, 0, 0, NULL);
87  printf("from_components 25/1 00:00:00:00: %d start=%d\n", ret, tc.start);
88 
90  0, 1, 0, 0, 0, NULL);
91  printf("from_components 25/1 01:00:00:00: %d start=%d\n", ret, tc.start);
92 
94  0, 1, 2, 3, 4, NULL);
95  printf("from_components 30/1 01:02:03:04: %d start=%d\n", ret, tc.start);
96 
97  ret = av_timecode_init_from_components(&tc, (AVRational){30000, 1001},
99  1, 0, 0, 0, NULL);
100  printf("from_components 30000/1001 drop 01:00:00;00: %d start=%d\n",
101  ret, tc.start);
102 }
103 
104 static void test_init_from_string(void)
105 {
106  AVTimecode tc;
107  int ret;
108 
110  "00:01:02:03", NULL);
111  printf("from_string 30/1 00:01:02:03: %d drop=%d start=%d\n",
112  ret, !!(tc.flags & AV_TIMECODE_FLAG_DROPFRAME), tc.start);
113 
114  ret = av_timecode_init_from_string(&tc, (AVRational){30000, 1001},
115  "00:01:00;02", NULL);
116  printf("from_string 30000/1001 00:01:00;02: %d drop=%d\n",
118 
119  ret = av_timecode_init_from_string(&tc, (AVRational){30000, 1001},
120  "01:00:00.00", NULL);
121  printf("from_string 30000/1001 01:00:00.00: %d drop=%d\n",
123 
125  "notvalid", NULL);
126  printf("from_string 25/1 notvalid: %s\n", ret < 0 ? "error" : "ok");
127 }
128 
129 static void test_make_string(void)
130 {
131  AVTimecode tc;
132  char buf[AV_TIMECODE_STR_SIZE];
133 
134  av_timecode_init(&tc, (AVRational){25, 1}, 0, 0, NULL);
135  printf("make_string 25/1 35: %s\n", av_timecode_make_string(&tc, buf, 35));
136  printf("make_string 25/1 0: %s\n", av_timecode_make_string(&tc, buf, 0));
137 
138  av_timecode_init(&tc, (AVRational){30, 1}, 0, 0, NULL);
139  printf("make_string 30/1 30: %s\n", av_timecode_make_string(&tc, buf, 30));
140 
141  av_timecode_init(&tc, (AVRational){25, 1},
143  printf("make_string 25/1 24hwrap %d: %s\n",
144  25 * 3600 * 25, av_timecode_make_string(&tc, buf, 25 * 3600 * 25));
145 
146  av_timecode_init(&tc, (AVRational){30000, 1001},
148  printf("make_string 30000/1001 drop 0: %s\n",
149  av_timecode_make_string(&tc, buf, 0));
150 
151  av_timecode_init(&tc, (AVRational){25, 1},
153  printf("make_string 25/1 negative start -100 frame 0: %s\n",
154  av_timecode_make_string(&tc, buf, 0));
155 }
156 
157 static void test_make_smpte_tc_string(void)
158 {
159  char buf[AV_TIMECODE_STR_SIZE];
160  AVTimecode tc;
161  uint32_t smpte;
162 
163  smpte = av_timecode_get_smpte((AVRational){30, 1}, 0, 1, 2, 3, 4);
164  printf("smpte_tc 30/1 01:02:03:04: %s\n",
165  av_timecode_make_smpte_tc_string(buf, smpte, 1));
166 
167  av_timecode_init(&tc, (AVRational){25, 1}, 0, 0, NULL);
169  25 * 3600 + 25 * 60 + 25 + 5);
170  printf("smpte_from_framenum 25/1 91530: %s\n",
171  av_timecode_make_smpte_tc_string(buf, smpte, 1));
172 }
173 
174 static void test_make_smpte_tc_string2(void)
175 {
176  char buf[AV_TIMECODE_STR_SIZE];
177  uint32_t smpte;
178 
179  smpte = av_timecode_get_smpte((AVRational){50, 1}, 0, 0, 0, 0, 0);
180  printf("smpte_tc2 50/1 00:00:00:00: %s\n",
182  smpte, 1, 0));
183 
184  smpte = av_timecode_get_smpte((AVRational){60, 1}, 0, 1, 0, 0, 0);
185  printf("smpte_tc2 60/1 01:00:00:00: %s\n",
187  smpte, 1, 0));
188 }
189 
190 static void test_make_mpeg_tc_string(void)
191 {
192  char buf[AV_TIMECODE_STR_SIZE];
193 
194  uint32_t tc25 = (1u << 19) | (2u << 13) | (3u << 6) | 4u;
195  printf("mpeg_tc 01:02:03:04: %s\n",
197 
198  uint32_t tc25_drop = tc25 | (1u << 24);
199  printf("mpeg_tc drop 01:02:03:04: %s\n",
200  av_timecode_make_mpeg_tc_string(buf, tc25_drop));
201 }
202 
203 static void test_adjust_ntsc(void)
204 {
205  static const struct {
206  int framenum;
207  int fps;
208  } cases[] = {
209  { 0, 30 },
210  { 1800, 30 },
211  { 1000, 25 },
212  { 1000, 0 },
213  { 3600, 60 },
214  };
215 
216  for (int i = 0; i < FF_ARRAY_ELEMS(cases); i++) {
217  printf("adjust_ntsc %d %d: %d\n",
218  cases[i].framenum, cases[i].fps,
219  av_timecode_adjust_ntsc_framenum2(cases[i].framenum,
220  cases[i].fps));
221  }
222 }
223 
224 static void test_get_smpte_roundtrip(void)
225 {
226  char buf[AV_TIMECODE_STR_SIZE];
227  char buf2[AV_TIMECODE_STR_SIZE];
228  uint32_t smpte;
229 
230  smpte = av_timecode_get_smpte((AVRational){30, 1}, 0, 12, 34, 56, 7);
231  printf("smpte_roundtrip 30/1 12:34:56:07: %s / %s\n",
232  av_timecode_make_smpte_tc_string(buf, smpte, 1),
234  smpte, 1, 0));
235 
236  smpte = av_timecode_get_smpte((AVRational){30, 1}, 0, 0, 0, 0, 0);
237  printf("smpte_roundtrip 30/1 00:00:00:00: %s / %s\n",
238  av_timecode_make_smpte_tc_string(buf, smpte, 1),
240  smpte, 1, 0));
241 
242  smpte = av_timecode_get_smpte((AVRational){30000, 1001}, 1, 0, 1, 0, 2);
243  printf("smpte_roundtrip 30000/1001 drop bit30=%d: %s / %s\n",
244  !!(smpte & (1u << 30)),
245  av_timecode_make_smpte_tc_string(buf, smpte, 0),
246  av_timecode_make_smpte_tc_string2(buf2, (AVRational){30000, 1001},
247  smpte, 0, 0));
248 
249  /* >30 fps SMPTE field bit handling test */
250  smpte = av_timecode_get_smpte((AVRational){50, 1}, 0, 0, 0, 0, 49);
251  printf("smpte_roundtrip 50/1 field bit7=%d: %s / %s\n",
252  !!(smpte & (1u << 7)),
253  av_timecode_make_smpte_tc_string(buf, smpte, 0),
255  smpte, 0, 0));
256 
257  smpte = av_timecode_get_smpte((AVRational){60000, 1001}, 0, 0, 0, 0, 59);
258  printf("smpte_roundtrip 60000/1001 field bit23=%d: %s / %s\n",
259  !!(smpte & (1u << 23)),
260  av_timecode_make_smpte_tc_string(buf, smpte, 0),
261  av_timecode_make_smpte_tc_string2(buf2, (AVRational){60000, 1001},
262  smpte, 0, 0));
263 }
264 
265 int main(void)
266 {
268  test_init();
277  return 0;
278 }
flags
const SwsFlags flags[]
Definition: swscale.c:72
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
test_make_string
static void test_make_string(void)
Definition: timecode.c:129
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:196
printf
__device__ int printf(const char *,...)
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:142
test_get_smpte_roundtrip
static void test_get_smpte_roundtrip(void)
Definition: timecode.c:224
rational.h
u
#define u(width, name, range_min, range_max)
Definition: cbs_apv.c:68
AVTimecode::flags
uint32_t flags
flags such as drop frame, +24 hours support, ...
Definition: timecode.h:43
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:70
macros.h
timecode.h
AVTimecode::start
int start
timecode frame start (first base frame number)
Definition: timecode.h:42
AVRational::num
int num
Numerator.
Definition: rational.h:59
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:201
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:36
main
int main(void)
Definition: timecode.c:265
test_adjust_ntsc
static void test_adjust_ntsc(void)
Definition: timecode.c:203
NULL
#define NULL
Definition: coverity.c:32
test_make_smpte_tc_string
static void test_make_smpte_tc_string(void)
Definition: timecode.c:157
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
test_init_from_components
static void test_init_from_components(void)
Definition: timecode.c:80
AVTimecode::fps
unsigned fps
frame per second; must be consistent with the rate field
Definition: timecode.h:45
AVTimecode::rate
AVRational rate
frame rate in rational form
Definition: timecode.h:44
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:211
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
test_init
static void test_init(void)
Definition: timecode.c:50
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:54
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:131
test_make_smpte_tc_string2
static void test_make_smpte_tc_string2(void)
Definition: timecode.c:174
AV_TIMECODE_FLAG_ALLOWNEGATIVE
@ AV_TIMECODE_FLAG_ALLOWNEGATIVE
negative time values are allowed
Definition: timecode.h:38
test_make_mpeg_tc_string
static void test_make_mpeg_tc_string(void)
Definition: timecode.c:190
test_init_from_string
static void test_init_from_string(void)
Definition: timecode.c:104
AV_TIMECODE_FLAG_DROPFRAME
@ AV_TIMECODE_FLAG_DROPFRAME
timecode is drop frame
Definition: timecode.h:36
ret
ret
Definition: filter_design.txt:187
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:147
rates
static const int rates[]
Definition: swresample.c:101
AVRational::den
int den
Denominator.
Definition: rational.h:60
test_check_frame_rate
static void test_check_frame_rate(void)
Unit tests for libavutil/timecode.c: av_timecode_init, av_timecode_init_from_components,...
Definition: timecode.c:36
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:241
AVTimecode
Definition: timecode.h:41
av_timecode_make_string
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum_arg)
Load timecode string in buf.
Definition: timecode.c:104