remux.c 3.4 KB
Newer Older
Julian Rother's avatar
Julian Rother committed
1
2
3
4
5
6
7
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#include "util.h"

int main(int argc, char *argv[])
{
Julian Rother's avatar
Julian Rother committed
8
	int i, err;
Julian Rother's avatar
Julian Rother committed
9
	int *idxmap;
10
	char *p, *path, *srcpath, *tmp;
Julian Rother's avatar
Julian Rother committed
11
12
13
	AVFormatContext *demux, *mux;
	AVPacket pkt;
	AVStream *stream;
14
	AVDictionary *muxopts;
Julian Rother's avatar
Julian Rother committed
15
16
17
	if (argc != 5)
		return 1;
	av_register_all();
18
	init_env();
Julian Rother's avatar
Julian Rother committed
19
	init_avlogbuf();
Julian Rother's avatar
Julian Rother committed
20
21
22
23
	memset(&pkt, 0, sizeof(pkt));
	av_init_packet(&pkt);

	jobid = atoi(argv[1]);
24
	path = mprintf("%s/%s", getenv(WORKER_RELEASED), jstr(jlookup(argv[4], "path"), ""));
25
	srcpath = mprintf("%s/%s", getenv(WORKER_RAW), jstr(jlookup(argv[4], "srcpath"), ""));
26
	tmp = mprintf("%s/.tmp-%i", getenv(WORKER_TMP), jobid);
27
	overwrite_check(path, srcpath, jstr(jlookup(argv[4], "srchash"), ""));
Julian Rother's avatar
Julian Rother committed
28
29
30
	ping_job(jobid, "running", 0);

	demux = 0;
Julian Rother's avatar
Julian Rother committed
31
32
	if (err = avformat_open_input(&demux, path, 0, 0))
		job_failed("Opening input file failed: %s", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
33
	avformat_find_stream_info(demux, 0);
34
	avformat_alloc_output_context2(&mux, 0, jstr(jlookup(argv[4], "format"), 0), path);
Julian Rother's avatar
Julian Rother committed
35
	av_dict_copy(&mux->metadata, demux->metadata, 0);
Julian Rother's avatar
Julian Rother committed
36
	parse_dict(&mux->metadata, jlookup(argv[4], "metadata"));
37
	parse_chapters(mux, jlookup(argv[4], "chapters"), demux->duration);
Julian Rother's avatar
Julian Rother committed
38
39
40
	idxmap = malloc(sizeof(int)*demux->nb_streams);
	for (i = 0; i < demux->nb_streams; i ++)
	{
Julian Rother's avatar
Julian Rother committed
41
		idxmap[i] = -1;
Julian Rother's avatar
Julian Rother committed
42
43
44
45
46
		if (demux->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO
				&& demux->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO
				&& demux->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
			continue;
		stream = avformat_new_stream(mux, 0);
Julian Rother's avatar
Julian Rother committed
47
		av_dict_copy(&stream->metadata, mux->streams[i]->metadata, 0);
Julian Rother's avatar
Julian Rother committed
48
49
50
51
52
53
54
		idxmap[i] = stream->index;
		avcodec_parameters_copy(mux->streams[i]->codecpar,
				demux->streams[i]->codecpar);
		mux->streams[i]->codecpar->codec_tag = 0;
		mux->streams[i]->time_base = demux->streams[i]->time_base;
	}
	avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE);
55
56
	muxopts = 0;
	parse_dict(&muxopts, jlookup(argv[4], "options"));
Julian Rother's avatar
Julian Rother committed
57
58
	if ((err = avformat_write_header(mux, &muxopts)) < 0)
		job_failed("Writing temporary file failed: %s", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
59
60
	while (!av_read_frame(demux, &pkt))
	{
61
62
		if (!checktime(30))
			ping_job(jobid, "running", 0);
Julian Rother's avatar
Julian Rother committed
63
64
65
66
67
68
69
70
71
72
73
		if (pkt.stream_index >= demux->nb_streams
				|| idxmap[pkt.stream_index] == -1)
			continue;
		pkt.stream_index = idxmap[pkt.stream_index];
		pkt.pts = av_rescale_q_rnd(pkt.pts, demux->streams[pkt.stream_index]->time_base,
				mux->streams[pkt.stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
		pkt.dts = av_rescale_q_rnd(pkt.dts, demux->streams[pkt.stream_index]->time_base,
				mux->streams[pkt.stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
		pkt.duration = av_rescale_q(pkt.duration, demux->streams[pkt.stream_index]->time_base,
				mux->streams[pkt.stream_index]->time_base);
		pkt.pos = -1;
Julian Rother's avatar
Julian Rother committed
74
75
		if (err = av_interleaved_write_frame(mux, &pkt))
			job_failed("Could not write frame: %s", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
76
77
	}
	av_interleaved_write_frame(mux, 0);
Julian Rother's avatar
Julian Rother committed
78
79
	if (err = av_write_trailer(mux))
		job_failed("Error writing trailer to temporary file", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
80
	avio_closep(&mux->pb);
Julian Rother's avatar
Julian Rother committed
81
82
	if (!filesize(tmp))
		job_failed("Sanity check failed: Output file is empty");
83
	overwrite_check(path, srcpath, jstr(jlookup(argv[4], "srchash"), ""));
Julian Rother's avatar
Julian Rother committed
84
	if (rename(tmp, path))
Julian Rother's avatar
Julian Rother committed
85
		job_failed("Overwriting output file failed: %s", strerror(errno));
Julian Rother's avatar
Julian Rother committed
86
	unlink(tmp);
Julian Rother's avatar
Julian Rother committed
87
88
	ping_job(jobid, "finished", "{%s, \"log\": \"%s\"}", json_fileinfo(path),
			jescape(get_avlogbuf()));
Julian Rother's avatar
Julian Rother committed
89
90
	return 0;
}