Skip to content

Commit 81c62a9

Browse files
add initial remuxing
1 parent 6563e98 commit 81c62a9

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

2_remuxing.c

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// based on https://ffmpeg.org/doxygen/trunk/remuxing_8c-example.html
2+
#include <libavutil/timestamp.h>
3+
#include <libavformat/avformat.h>
4+
5+
int main(int argc, char **argv)
6+
{
7+
AVFormatContext *input_format_context = NULL, *output_format_context = NULL;
8+
AVPacket packet;
9+
const char *in_filename, *out_filename;
10+
int ret, i;
11+
int stream_index = 0;
12+
int *streams_list = NULL;
13+
int number_of_streams = 0;
14+
15+
in_filename = argv[1];
16+
out_filename = argv[2];
17+
18+
if ((ret = avformat_open_input(&input_format_context, in_filename, NULL, NULL)) < 0) {
19+
fprintf(stderr, "Could not open input file '%s'", in_filename);
20+
goto end;
21+
}
22+
if ((ret = avformat_find_stream_info(input_format_context, NULL)) < 0) {
23+
fprintf(stderr, "Failed to retrieve input stream information");
24+
goto end;
25+
}
26+
27+
avformat_alloc_output_context2(&output_format_context, NULL, NULL, out_filename);
28+
if (!output_format_context) {
29+
fprintf(stderr, "Could not create output context\n");
30+
ret = AVERROR_UNKNOWN;
31+
goto end;
32+
}
33+
34+
number_of_streams = input_format_context->nb_streams;
35+
streams_list = av_mallocz_array(number_of_streams, sizeof(*streams_list));
36+
37+
if (!streams_list) {
38+
ret = AVERROR(ENOMEM);
39+
goto end;
40+
}
41+
42+
for (i = 0; i < input_format_context->nb_streams; i++) {
43+
AVStream *out_stream;
44+
AVStream *in_stream = input_format_context->streams[i];
45+
AVCodecParameters *in_codecpar = in_stream->codecpar;
46+
if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
47+
in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
48+
in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
49+
streams_list[i] = -1;
50+
continue;
51+
}
52+
streams_list[i] = stream_index++;
53+
out_stream = avformat_new_stream(output_format_context, NULL);
54+
if (!out_stream) {
55+
fprintf(stderr, "Failed allocating output stream\n");
56+
ret = AVERROR_UNKNOWN;
57+
goto end;
58+
}
59+
ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
60+
if (ret < 0) {
61+
fprintf(stderr, "Failed to copy codec parameters\n");
62+
goto end;
63+
}
64+
}
65+
// https://ffmpeg.org/doxygen/trunk/group__lavf__misc.html#gae2645941f2dc779c307eb6314fd39f10
66+
av_dump_format(output_format_context, 0, out_filename, 1);
67+
68+
// unless it's a no file (we'll talk later about that) write to the disk (FLAG_WRITE)
69+
// but basically it's a way to save the file to a buffer so you can store it
70+
// wherever you want.
71+
if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) {
72+
ret = avio_open(&output_format_context->pb, out_filename, AVIO_FLAG_WRITE);
73+
if (ret < 0) {
74+
fprintf(stderr, "Could not open output file '%s'", out_filename);
75+
goto end;
76+
}
77+
}
78+
// https://ffmpeg.org/doxygen/trunk/group__lavf__encoding.html#ga18b7b10bb5b94c4842de18166bc677cb
79+
ret = avformat_write_header(output_format_context, NULL);
80+
if (ret < 0) {
81+
fprintf(stderr, "Error occurred when opening output file\n");
82+
goto end;
83+
}
84+
while (1) {
85+
AVStream *in_stream, *out_stream;
86+
ret = av_read_frame(input_format_context, &packet);
87+
if (ret < 0)
88+
break;
89+
in_stream = input_format_context->streams[packet.stream_index];
90+
if (packet.stream_index >= number_of_streams || streams_list[packet.stream_index] < 0) {
91+
av_packet_unref(&packet);
92+
continue;
93+
}
94+
packet.stream_index = streams_list[packet.stream_index];
95+
out_stream = output_format_context->streams[packet.stream_index];
96+
/* copy packet */
97+
packet.pts = av_rescale_q_rnd(packet.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
98+
packet.dts = av_rescale_q_rnd(packet.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
99+
packet.duration = av_rescale_q(packet.duration, in_stream->time_base, out_stream->time_base);
100+
// https://ffmpeg.org/doxygen/trunk/structAVPacket.html#ab5793d8195cf4789dfb3913b7a693903
101+
packet.pos = -1;
102+
103+
//https://ffmpeg.org/doxygen/trunk/group__lavf__encoding.html#ga37352ed2c63493c38219d935e71db6c1
104+
ret = av_interleaved_write_frame(output_format_context, &packet);
105+
if (ret < 0) {
106+
fprintf(stderr, "Error muxing packet\n");
107+
break;
108+
}
109+
av_packet_unref(&packet);
110+
}
111+
//https://ffmpeg.org/doxygen/trunk/group__lavf__encoding.html#ga7f14007e7dc8f481f054b21614dfec13
112+
av_write_trailer(output_format_context);
113+
end:
114+
avformat_close_input(&input_format_context);
115+
/* close output */
116+
if (output_format_context && !(output_format_context->oformat->flags & AVFMT_NOFILE))
117+
avio_closep(&output_format_context->pb);
118+
avformat_free_context(output_format_context);
119+
av_freep(&streams_list);
120+
if (ret < 0 && ret != AVERROR_EOF) {
121+
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
122+
return 1;
123+
}
124+
return 0;
125+
}
126+

Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,13 @@ make_hello: clean
99

1010
run_hello: make_hello
1111
docker run -w /files --rm -it -v `pwd`:/files leandromoreira/ffmpeg-devel /files/build/hello /files/small_bunny_1080p_60fps.mp4
12+
13+
make_remuxing: clean
14+
docker run -w /files --rm -it -v `pwd`:/files leandromoreira/ffmpeg-devel \
15+
gcc -L/opt/ffmpeg/lib -I/opt/ffmpeg/include/ /files/2_0_remuxing.c \
16+
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil \
17+
-o /files/build/remuxing
18+
19+
run_remuxing: make_remuxing
20+
docker run -w /files --rm -it -v `pwd`:/files leandromoreira/ffmpeg-devel /files/build/remuxing /files/small_bunny_1080p_60fps.mp4 /files/remuxed_small_bunny_1080p_60fps.ts
21+

0 commit comments

Comments
 (0)