Skip to content

Commit e2b42a3

Browse files
committed
add tools/mux_ivf
refers to GH-434
1 parent be1ec3f commit e2b42a3

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

tools/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ astat_test
44
benchmark_ff_convs
55
convert
66
decklink_temperature
7+
mux_ivf
78
thumbnailgen
89
uyvy2yuv422p

tools/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ifeq ($(ARCH), x86_64)
1111
endif
1212

1313
TARGETS=astat_lib astat_test benchmark_ff_convs convert decklink_temperature \
14+
mux_ivf \
1415
thumbnailgen uyvy2yuv422p
1516

1617
COMMON_OBJS = src/color.o src/debug.o src/video_codec.o src/pixfmt_conv.o \
@@ -54,6 +55,9 @@ convert: convert.o $(COMMON_OBJS)
5455
decklink_temperature: decklink_temperature.cpp ext-deps/DeckLink/Linux/DeckLinkAPIDispatch.o
5556
$(CXX) $^ -o $@
5657

58+
mux_ivf: mux_ivf.o
59+
$(CC) $^ -o $@
60+
5761
uyvy2yuv422p: uyvy2yuv422p.c
5862
$(CC) -g -std=c99 -Wall $< -o $@
5963

tools/mux_ivf.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* Simple Duck IVF mixer for VP8/VP9/AV1.
3+
*
4+
* Can be used eg. to process exported (--record) VP9 files, that cannot be
5+
* simply concatenated as eg. H.264 frames. Specification:
6+
* <https://wiki.multimedia.cx/index.php/Duck_IVF>
7+
*/
8+
9+
#include <assert.h>
10+
#include <errno.h>
11+
#include <stdint.h>
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <string.h>
15+
16+
const char *
17+
get_fcc(const char *ext)
18+
{
19+
if (strcasecmp(ext, "vp8") == 0) {
20+
return "VP80";
21+
}
22+
if (strcasecmp(ext, "vp9") == 0) {
23+
return "VP90";
24+
}
25+
if (strcasecmp(ext, "av1") == 0) {
26+
return "av01";
27+
}
28+
fprintf(stderr, "Unsupported extension: %s\n", ext);
29+
exit(EXIT_FAILURE);
30+
}
31+
32+
#define OUTPUT(val) fwrite(&(val), sizeof (val), 1, stdout)
33+
int
34+
main(int argc, char *argv[])
35+
{
36+
if (argc <= 4) {
37+
fprintf(
38+
stderr,
39+
"Usage:\n\t%s <width> <height> <fps> INFILES > out.ivf\n",
40+
argv[0]);
41+
return EXIT_FAILURE;
42+
}
43+
argv += 1; // skip progname
44+
45+
// file header
46+
printf("DKIF");
47+
const uint16_t version = 0;
48+
OUTPUT(version);
49+
const uint16_t hdr_len = 32;
50+
OUTPUT(hdr_len);
51+
printf("%s", get_fcc(strchr(argv[3], '.') + 1)); // codec FourCC
52+
const uint16_t width = atoi(*argv++);
53+
const uint16_t height = atoi(*argv++);
54+
const uint32_t fps = atoi(*argv++);
55+
assert(width * height * fps != 0);
56+
OUTPUT(width);
57+
OUTPUT(height);
58+
const uint32_t fps_den = fps;
59+
OUTPUT(fps_den);
60+
const uint32_t fps_num = 1;
61+
OUTPUT(fps_num);
62+
const uint32_t nr_frames = argc - 3;
63+
OUTPUT(nr_frames);
64+
const uint32_t unused = 0;
65+
OUTPUT(unused);
66+
67+
uint64_t pts = 0;
68+
while (*argv != NULL) { // iterate over files
69+
FILE *f = fopen(*argv++, "rb");
70+
assert(f != NULL);
71+
72+
fseek(f, 0, SEEK_END);
73+
const uint32_t file_len = ftell(f);
74+
fseek(f, 0, SEEK_SET);
75+
76+
// frame header
77+
OUTPUT(file_len);
78+
OUTPUT(pts);
79+
pts += 1;
80+
81+
// copy the content of the file to output
82+
int c = 0;
83+
while ((c = fgetc(f)) != EOF) {
84+
putc(c, stdout);
85+
}
86+
fclose(f);
87+
}
88+
// we do not do much error checking so at least return errno
89+
return errno;
90+
}

0 commit comments

Comments
 (0)