remux.c 3.53 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[])
{
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();
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
	ping_job(jobid, "running", 0);
25 26
	path = buildpath(getenv(WORKER_RELEASED), jstr(jlookup(argv[4], "path"), 0));
	srcpath = buildpath(getenv(WORKER_RAW), jstr(jlookup(argv[4], "srcpath"), 0));
27
	tmp = mprintf("%s/.tmp-%i", getenv(WORKER_TMP), jobid);
28
	overwrite_check(path, srcpath, jstr(jlookup(argv[4], "srchash"), ""));
Julian Rother's avatar
Julian Rother committed
29 30

	demux = 0;
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 35 36 37
	err = avformat_alloc_output_context2(&mux,
			av_guess_format(jstr(jlookup(argv[4], "format"), 0), path, 0), 0, tmp);
	if (err < 0)
		job_failed("Error allocating muxer context: %s", av_err2str(err));
38
	av_dict_copy(&mux->metadata, demux->metadata, 0);
Julian Rother's avatar
Julian Rother committed
39
	parse_dict(&mux->metadata, jlookup(argv[4], "metadata"));
40
	parse_chapters(mux, jlookup(argv[4], "chapters"), demux->duration);
Julian Rother's avatar
Julian Rother committed
41 42 43
	idxmap = malloc(sizeof(int)*demux->nb_streams);
	for (i = 0; i < demux->nb_streams; i ++)
	{
44
		idxmap[i] = -1;
Julian Rother's avatar
Julian Rother committed
45 46 47 48 49
		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);
50
		av_dict_copy(&stream->metadata, mux->streams[i]->metadata, 0);
Julian Rother's avatar
Julian Rother committed
51 52 53 54 55 56 57
		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);
58 59
	muxopts = 0;
	parse_dict(&muxopts, jlookup(argv[4], "options"));
60 61
	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
62 63
	while (!av_read_frame(demux, &pkt))
	{
64 65
		if (!checktime(30))
			ping_job(jobid, "running", 0);
Julian Rother's avatar
Julian Rother committed
66 67 68 69 70 71 72 73 74 75 76
		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;
77 78
		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
79
	}
80
	avformat_close_input(&demux);
Julian Rother's avatar
Julian Rother committed
81
	av_interleaved_write_frame(mux, 0);
82 83
	if (err = av_write_trailer(mux))
		job_failed("Error writing trailer to temporary file", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
84
	avio_closep(&mux->pb);
Julian Rother's avatar
Julian Rother committed
85 86
	if (!filesize(tmp))
		job_failed("Sanity check failed: Output file is empty");
87
	overwrite_check(path, srcpath, jstr(jlookup(argv[4], "srchash"), ""));
Julian Rother's avatar
Julian Rother committed
88
	if (rename(tmp, path))
89
		job_failed("Overwriting output file failed: %s", strerror(errno));
Julian Rother's avatar
Julian Rother committed
90
	unlink(tmp);
91 92
	ping_job(jobid, "finished", "{%s, \"log\": \"%s\"}", json_fileinfo(path),
			jescape(get_avlogbuf()));
Julian Rother's avatar
Julian Rother committed
93 94
	return 0;
}