all repos — mgba @ ec626d723fbb4716a697ad3cac0b0b29943dba00

mGBA Game Boy Advance Emulator

src/feature/ffmpeg/ffmpeg-encoder.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "ffmpeg-encoder.h"
  7
  8#include <mgba/core/core.h>
  9#include <mgba/gba/interface.h>
 10#include <mgba/internal/gba/gba.h>
 11#include <mgba-util/math.h>
 12
 13#include <libavcodec/version.h>
 14#include <libavcodec/avcodec.h>
 15
 16#include <libavfilter/buffersink.h>
 17#include <libavfilter/buffersrc.h>
 18
 19#include <libavutil/version.h>
 20#if LIBAVUTIL_VERSION_MAJOR >= 53
 21#include <libavutil/buffer.h>
 22#endif
 23#include <libavutil/imgutils.h>
 24#include <libavutil/mathematics.h>
 25#include <libavutil/opt.h>
 26
 27#ifdef USE_LIBAVRESAMPLE
 28#include <libavresample/avresample.h>
 29#else
 30#include <libswresample/swresample.h>
 31#endif
 32#include <libswscale/swscale.h>
 33
 34static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);
 35static void _ffmpegPostAudioFrame(struct mAVStream*, int16_t left, int16_t right);
 36static void _ffmpegSetVideoDimensions(struct mAVStream*, unsigned width, unsigned height);
 37static void _ffmpegSetVideoFrameRate(struct mAVStream*, unsigned numerator, unsigned denominator);
 38
 39static bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame);
 40static bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame);
 41
 42enum {
 43	PREFERRED_SAMPLE_RATE = 0x8000
 44};
 45
 46void FFmpegEncoderInit(struct FFmpegEncoder* encoder) {
 47#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
 48	av_register_all();
 49#endif
 50
 51	encoder->d.videoDimensionsChanged = _ffmpegSetVideoDimensions;
 52	encoder->d.postVideoFrame = _ffmpegPostVideoFrame;
 53	encoder->d.postAudioFrame = _ffmpegPostAudioFrame;
 54	encoder->d.postAudioBuffer = 0;
 55	encoder->d.videoFrameRateChanged = _ffmpegSetVideoFrameRate;
 56
 57	encoder->audioCodec = NULL;
 58	encoder->videoCodec = NULL;
 59	encoder->containerFormat = NULL;
 60	FFmpegEncoderSetAudio(encoder, "flac", 0);
 61	FFmpegEncoderSetVideo(encoder, "libx264", 0, 0);
 62	FFmpegEncoderSetContainer(encoder, "matroska");
 63	FFmpegEncoderSetDimensions(encoder, GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS);
 64	encoder->iwidth = GBA_VIDEO_HORIZONTAL_PIXELS;
 65	encoder->iheight = GBA_VIDEO_VERTICAL_PIXELS;
 66	encoder->frameCycles = VIDEO_TOTAL_LENGTH;
 67	encoder->cycles = GBA_ARM7TDMI_FREQUENCY;
 68	encoder->frameskip = 1;
 69	encoder->skipResidue = 0;
 70	encoder->loop = false;
 71	encoder->ipixFormat =
 72#ifdef COLOR_16_BIT
 73#ifdef COLOR_5_6_5
 74	    AV_PIX_FMT_RGB565;
 75#else
 76	    AV_PIX_FMT_BGR555;
 77#endif
 78#else
 79#ifndef USE_LIBAV
 80	    AV_PIX_FMT_0BGR32;
 81#else
 82	    AV_PIX_FMT_BGR32;
 83#endif
 84#endif
 85	encoder->resampleContext = NULL;
 86	encoder->absf = NULL;
 87	encoder->context = NULL;
 88	encoder->scaleContext = NULL;
 89	encoder->audio = NULL;
 90	encoder->audioStream = NULL;
 91	encoder->audioFrame = NULL;
 92	encoder->audioBuffer = NULL;
 93	encoder->postaudioBuffer = NULL;
 94	encoder->video = NULL;
 95	encoder->videoStream = NULL;
 96	encoder->videoFrame = NULL;
 97	encoder->graph = NULL;
 98	encoder->source = NULL;
 99	encoder->sink = NULL;
100	encoder->sinkFrame = NULL;
101	FFmpegEncoderSetInputFrameRate(encoder, VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY);
102
103	int i;
104	for (i = 0; i < FFMPEG_FILTERS_MAX; ++i) {
105		encoder->filters[i] = NULL;
106	}
107}
108
109bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, unsigned abr) {
110	static const struct {
111		int format;
112		int priority;
113	} priorities[] = {
114		{ AV_SAMPLE_FMT_S16, 0 },
115		{ AV_SAMPLE_FMT_S16P, 1 },
116		{ AV_SAMPLE_FMT_S32, 2 },
117		{ AV_SAMPLE_FMT_S32P, 2 },
118		{ AV_SAMPLE_FMT_FLT, 3 },
119		{ AV_SAMPLE_FMT_FLTP, 3 },
120		{ AV_SAMPLE_FMT_DBL, 4 },
121		{ AV_SAMPLE_FMT_DBLP, 4 }
122	};
123
124	if (!acodec) {
125		encoder->audioCodec = 0;
126		return true;
127	}
128
129	AVCodec* codec = avcodec_find_encoder_by_name(acodec);
130	if (!codec) {
131		return false;
132	}
133
134	if (!codec->sample_fmts) {
135		return false;
136	}
137	size_t i;
138	size_t j;
139	int priority = INT_MAX;
140	encoder->sampleFormat = AV_SAMPLE_FMT_NONE;
141	for (i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) {
142		for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) {
143			if (codec->sample_fmts[i] == priorities[j].format && priority > priorities[j].priority) {
144				priority = priorities[j].priority;
145				encoder->sampleFormat = codec->sample_fmts[i];
146			}
147		}
148	}
149	if (encoder->sampleFormat == AV_SAMPLE_FMT_NONE) {
150		return false;
151	}
152	encoder->sampleRate = PREFERRED_SAMPLE_RATE;
153	if (codec->supported_samplerates) {
154		for (i = 0; codec->supported_samplerates[i]; ++i) {
155			if (codec->supported_samplerates[i] < PREFERRED_SAMPLE_RATE) {
156				continue;
157			}
158			if (encoder->sampleRate == PREFERRED_SAMPLE_RATE || encoder->sampleRate > codec->supported_samplerates[i]) {
159				encoder->sampleRate = codec->supported_samplerates[i];
160			}
161		}
162	} else if (codec->id == AV_CODEC_ID_AAC) {
163		// HACK: AAC doesn't support 32768Hz (it rounds to 32000), but libfaac doesn't tell us that
164		encoder->sampleRate = 44100;
165	}
166	encoder->audioCodec = acodec;
167	encoder->audioBitrate = abr;
168	return true;
169}
170
171bool FFmpegEncoderSetVideo(struct FFmpegEncoder* encoder, const char* vcodec, unsigned vbr, int frameskip) {
172	static const struct {
173		enum AVPixelFormat format;
174		int priority;
175	} priorities[] = {
176		{ AV_PIX_FMT_RGB555, 0 },
177		{ AV_PIX_FMT_BGR555, 0 },
178		{ AV_PIX_FMT_RGB565, 1 },
179		{ AV_PIX_FMT_BGR565, 1 },
180		{ AV_PIX_FMT_RGB24, 2 },
181		{ AV_PIX_FMT_BGR24, 2 },
182#ifndef USE_LIBAV
183		{ AV_PIX_FMT_BGR0, 3 },
184		{ AV_PIX_FMT_RGB0, 3 },
185		{ AV_PIX_FMT_0BGR, 3 },
186		{ AV_PIX_FMT_0RGB, 3 },
187#endif
188		{ AV_PIX_FMT_RGB32, 4},
189		{ AV_PIX_FMT_BGR32, 4},
190		{ AV_PIX_FMT_YUV444P, 5 },
191		{ AV_PIX_FMT_YUV422P, 6 },
192		{ AV_PIX_FMT_YUV420P, 7 },
193		{ AV_PIX_FMT_PAL8, 8 },
194	};
195
196	if (!vcodec) {
197		encoder->videoCodec = 0;
198		return true;
199	}
200
201	AVCodec* codec = avcodec_find_encoder_by_name(vcodec);
202	if (!codec) {
203		return false;
204	}
205
206	size_t i;
207	size_t j;
208	int priority = INT_MAX;
209	encoder->pixFormat = AV_PIX_FMT_NONE;
210	for (i = 0; codec->pix_fmts[i] != AV_PIX_FMT_NONE; ++i) {
211		for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) {
212			if (codec->pix_fmts[i] == priorities[j].format && priority > priorities[j].priority) {
213				priority = priorities[j].priority;
214				encoder->pixFormat = codec->pix_fmts[i];
215			}
216		}
217	}
218	if (encoder->pixFormat == AV_PIX_FMT_NONE) {
219		return false;
220	}
221	encoder->videoCodec = vcodec;
222	encoder->videoBitrate = vbr;
223	encoder->frameskip = frameskip + 1;
224	return true;
225}
226
227bool FFmpegEncoderSetContainer(struct FFmpegEncoder* encoder, const char* container) {
228	AVOutputFormat* oformat = av_guess_format(container, 0, 0);
229	if (!oformat) {
230		return false;
231	}
232	encoder->containerFormat = container;
233	return true;
234}
235
236void FFmpegEncoderSetDimensions(struct FFmpegEncoder* encoder, int width, int height) {
237	encoder->width = width > 0 ? width : GBA_VIDEO_HORIZONTAL_PIXELS;
238	encoder->height = height > 0 ? height : GBA_VIDEO_VERTICAL_PIXELS;
239}
240
241void FFmpegEncoderSetLooping(struct FFmpegEncoder* encoder, bool loop) {
242	encoder->loop = loop;
243}
244
245bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) {
246	AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0);
247	AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);
248	AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec);
249	if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat || (!acodec && !vcodec)) {
250		return false;
251	}
252	if (encoder->audioCodec && !avformat_query_codec(oformat, acodec->id, FF_COMPLIANCE_EXPERIMENTAL)) {
253		return false;
254	}
255	if (encoder->videoCodec && !avformat_query_codec(oformat, vcodec->id, FF_COMPLIANCE_EXPERIMENTAL)) {
256		return false;
257	}
258	return true;
259}
260
261bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
262	AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);
263	AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec);
264	if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !FFmpegEncoderVerifyContainer(encoder)) {
265		return false;
266	}
267
268	if (encoder->context) {
269		return false;
270	}
271
272	encoder->currentAudioSample = 0;
273	encoder->currentAudioFrame = 0;
274	encoder->currentVideoFrame = 0;
275	encoder->skipResidue = 0;
276
277	AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0);
278#ifndef USE_LIBAV
279	avformat_alloc_output_context2(&encoder->context, oformat, 0, outfile);
280#else
281	encoder->context = avformat_alloc_context();
282	strncpy(encoder->context->filename, outfile, sizeof(encoder->context->filename) - 1);
283	encoder->context->filename[sizeof(encoder->context->filename) - 1] = '\0';
284	encoder->context->oformat = oformat;
285#endif
286
287	if (acodec) {
288#ifdef FFMPEG_USE_CODECPAR
289		encoder->audioStream = avformat_new_stream(encoder->context, NULL);
290		encoder->audio = avcodec_alloc_context3(acodec);
291#else
292		encoder->audioStream = avformat_new_stream(encoder->context, acodec);
293		encoder->audio = encoder->audioStream->codec;
294#endif
295		encoder->audio->bit_rate = encoder->audioBitrate;
296		encoder->audio->channels = 2;
297		encoder->audio->channel_layout = AV_CH_LAYOUT_STEREO;
298		encoder->audio->sample_rate = encoder->sampleRate;
299		encoder->audio->sample_fmt = encoder->sampleFormat;
300		AVDictionary* opts = 0;
301		av_dict_set(&opts, "strict", "-2", 0);
302		if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
303#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
304			encoder->audio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
305#else
306			encoder->audio->flags |= CODEC_FLAG_GLOBAL_HEADER;
307#endif
308		}
309		int res = avcodec_open2(encoder->audio, acodec, &opts);
310		av_dict_free(&opts);
311		if (res < 0) {
312			FFmpegEncoderClose(encoder);
313			return false;
314		}
315#if LIBAVCODEC_VERSION_MAJOR >= 55
316		encoder->audioFrame = av_frame_alloc();
317#else
318		encoder->audioFrame = avcodec_alloc_frame();
319#endif
320		if (!encoder->audio->frame_size) {
321			encoder->audio->frame_size = 1;
322		}
323		encoder->audioFrame->nb_samples = encoder->audio->frame_size;
324		encoder->audioFrame->format = encoder->audio->sample_fmt;
325		encoder->audioFrame->pts = 0;
326#ifdef USE_LIBAVRESAMPLE
327		encoder->resampleContext = avresample_alloc_context();
328		av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
329		av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
330		av_opt_set_int(encoder->resampleContext, "in_sample_rate", PREFERRED_SAMPLE_RATE, 0);
331		av_opt_set_int(encoder->resampleContext, "out_sample_rate", encoder->sampleRate, 0);
332		av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
333		av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0);
334		avresample_open(encoder->resampleContext);
335#else
336		encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate,
337		                                              AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL);
338		swr_init(encoder->resampleContext);
339#endif
340		encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4;
341		encoder->audioBuffer = av_malloc(encoder->audioBufferSize);
342		encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
343		encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize);
344		avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0);
345
346		if (encoder->audio->codec->id == AV_CODEC_ID_AAC &&
347		    (strcasecmp(encoder->containerFormat, "mp4") ||
348		        strcasecmp(encoder->containerFormat, "m4v") ||
349		        strcasecmp(encoder->containerFormat, "mov"))) {
350			// MP4 container doesn't support the raw ADTS AAC format that the encoder spits out
351#ifdef FFMPEG_USE_NEW_BSF
352			av_bsf_alloc(av_bsf_get_by_name("aac_adtstoasc"), &encoder->absf);
353			avcodec_parameters_from_context(encoder->absf->par_in, encoder->audio);
354			av_bsf_init(encoder->absf);
355#else
356			encoder->absf = av_bitstream_filter_init("aac_adtstoasc");
357#endif
358		}
359#ifdef FFMPEG_USE_CODECPAR
360		avcodec_parameters_from_context(encoder->audioStream->codecpar, encoder->audio);
361#endif
362	}
363
364	if (vcodec) {
365#ifdef FFMPEG_USE_CODECPAR
366		encoder->videoStream = avformat_new_stream(encoder->context, NULL);
367		encoder->video = avcodec_alloc_context3(vcodec);
368#else
369		encoder->videoStream = avformat_new_stream(encoder->context, vcodec);
370		encoder->video = encoder->videoStream->codec;
371#endif
372		encoder->video->bit_rate = encoder->videoBitrate;
373		encoder->video->width = encoder->width;
374		encoder->video->height = encoder->height;
375		encoder->video->time_base = (AVRational) { encoder->frameCycles * encoder->frameskip, encoder->cycles };
376		encoder->video->framerate = (AVRational) { encoder->cycles, encoder->frameCycles * encoder->frameskip };
377		encoder->videoStream->time_base = encoder->video->time_base;
378		encoder->videoStream->avg_frame_rate = encoder->video->framerate;
379		encoder->video->pix_fmt = encoder->pixFormat;
380		encoder->video->gop_size = 60;
381		encoder->video->max_b_frames = 3;
382		if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
383#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
384			encoder->video->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
385#else
386			encoder->video->flags |= CODEC_FLAG_GLOBAL_HEADER;
387#endif
388		}
389
390		if (encoder->video->codec->id == AV_CODEC_ID_H264 &&
391		    (strcasecmp(encoder->containerFormat, "mp4") ||
392		        strcasecmp(encoder->containerFormat, "m4v") ||
393		        strcasecmp(encoder->containerFormat, "mov"))) {
394			// QuickTime and a few other things require YUV420
395			encoder->video->pix_fmt = AV_PIX_FMT_YUV420P;
396		}
397		if (encoder->video->codec->id == AV_CODEC_ID_FFV1) {
398#if LIBAVCODEC_VERSION_MAJOR >= 57
399			av_opt_set(encoder->video->priv_data, "coder", "range_tab", 0);
400			av_opt_set_int(encoder->video->priv_data, "context", 1, 0);
401#endif
402			encoder->video->gop_size = 128;
403			encoder->video->level = 3;
404		}
405
406		if (encoder->video->codec->id == AV_CODEC_ID_PNG) {
407			encoder->video->compression_level = 8;
408		}
409#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 48, 100)
410		if (encoder->video->codec->id == AV_CODEC_ID_ZMBV) {
411			encoder->video->compression_level = 5;
412			encoder->video->pix_fmt = AV_PIX_FMT_BGR0;
413		}
414#endif
415		if (strcmp(vcodec->name, "libx264") == 0) {
416			// Try to adaptively figure out when you can use a slower encoder
417			if (encoder->width * encoder->height > 1000000) {
418				av_opt_set(encoder->video->priv_data, "preset", "superfast", 0);
419			} else if (encoder->width * encoder->height > 500000) {
420				av_opt_set(encoder->video->priv_data, "preset", "veryfast", 0);
421			} else {
422				av_opt_set(encoder->video->priv_data, "preset", "faster", 0);
423			}
424			if (encoder->videoBitrate == 0) {
425				av_opt_set(encoder->video->priv_data, "qp", "0", 0);
426				encoder->video->pix_fmt = AV_PIX_FMT_YUV444P;
427			}
428		}
429		if (strcmp(vcodec->name, "libvpx-vp9") == 0 && encoder->videoBitrate == 0) {
430			av_opt_set_int(encoder->video->priv_data, "lossless", 1, 0);
431			av_opt_set_int(encoder->video->priv_data, "crf", 0, 0);
432			encoder->video->gop_size = 120;
433			encoder->video->pix_fmt = AV_PIX_FMT_GBRP;
434		}
435		if (strcmp(vcodec->name, "libwebp_anim") == 0 && encoder->videoBitrate == 0) {
436			av_opt_set(encoder->video->priv_data, "lossless", "1", 0);
437			encoder->video->pix_fmt = AV_PIX_FMT_RGB32;
438		}
439
440		if (encoder->pixFormat == AV_PIX_FMT_PAL8) {
441			encoder->graph = avfilter_graph_alloc();
442
443			const struct AVFilter* source = avfilter_get_by_name("buffer");
444			const struct AVFilter* sink = avfilter_get_by_name("buffersink");
445			const struct AVFilter* split = avfilter_get_by_name("split");
446			const struct AVFilter* palettegen = avfilter_get_by_name("palettegen");
447			const struct AVFilter* paletteuse = avfilter_get_by_name("paletteuse");
448
449			if (!source || !sink || !split || !palettegen || !paletteuse || !encoder->graph) {
450				FFmpegEncoderClose(encoder);
451				return false;
452			}
453
454			char args[256];
455			snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d",
456			         encoder->video->width, encoder->video->height, encoder->ipixFormat,
457			         encoder->video->time_base.num, encoder->video->time_base.den);
458
459			int res = 0;
460			res |= avfilter_graph_create_filter(&encoder->source, source, NULL, args, NULL, encoder->graph);
461			res |= avfilter_graph_create_filter(&encoder->sink, sink, NULL, NULL, NULL, encoder->graph);
462			res |= avfilter_graph_create_filter(&encoder->filters[0], split, NULL, NULL, NULL, encoder->graph);
463			res |= avfilter_graph_create_filter(&encoder->filters[1], palettegen, NULL, "reserve_transparent=off", NULL, encoder->graph);
464			res |= avfilter_graph_create_filter(&encoder->filters[2], paletteuse, NULL, "dither=none", NULL, encoder->graph);
465			if (res < 0) {
466				FFmpegEncoderClose(encoder);
467				return false;
468			}
469
470			res = 0;
471			res |= avfilter_link(encoder->source, 0, encoder->filters[0], 0);
472			res |= avfilter_link(encoder->filters[0], 0, encoder->filters[1], 0);
473			res |= avfilter_link(encoder->filters[0], 1, encoder->filters[2], 0);
474			res |= avfilter_link(encoder->filters[1], 0, encoder->filters[2], 1);
475			res |= avfilter_link(encoder->filters[2], 0, encoder->sink, 0);
476			if (res < 0 || avfilter_graph_config(encoder->graph, NULL) < 0) {
477				FFmpegEncoderClose(encoder);
478				return false;
479			}
480
481#if LIBAVCODEC_VERSION_MAJOR >= 55
482			encoder->sinkFrame = av_frame_alloc();
483#else
484			encoder->sinkFrame = avcodec_alloc_frame();
485#endif
486		}
487		AVDictionary* opts = 0;
488		av_dict_set(&opts, "strict", "-2", 0);
489		int res = avcodec_open2(encoder->video, vcodec, &opts);
490		av_dict_free(&opts);
491		if (res < 0) {
492			FFmpegEncoderClose(encoder);
493			return false;
494		}
495#if LIBAVCODEC_VERSION_MAJOR >= 55
496		encoder->videoFrame = av_frame_alloc();
497#else
498		encoder->videoFrame = avcodec_alloc_frame();
499#endif
500		encoder->videoFrame->format = encoder->video->pix_fmt != AV_PIX_FMT_PAL8 ? encoder->video->pix_fmt : encoder->ipixFormat;
501		encoder->videoFrame->width = encoder->video->width;
502		encoder->videoFrame->height = encoder->video->height;
503		encoder->videoFrame->pts = 0;
504		_ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight);
505		av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->videoFrame->width, encoder->videoFrame->height, encoder->videoFrame->format, 32);
506#ifdef FFMPEG_USE_CODECPAR
507		avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video);
508#endif
509	}
510
511	if (strcmp(encoder->containerFormat, "gif") == 0) {
512		av_opt_set(encoder->context->priv_data, "loop", encoder->loop ? "0" : "-1", 0);
513	} else if (strcmp(encoder->containerFormat, "apng") == 0) {
514		av_opt_set(encoder->context->priv_data, "plays", encoder->loop ? "0" : "1", 0);
515	} else if (strcmp(encoder->containerFormat, "webp") == 0) {
516		av_opt_set(encoder->context->priv_data, "loop", encoder->loop ? "0" : "1", 0);
517	}
518
519	AVDictionary* opts = 0;
520	av_dict_set(&opts, "strict", "-2", 0);
521	bool res = avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, &opts) < 0;
522	av_dict_free(&opts);
523	if (res) {
524		FFmpegEncoderClose(encoder);
525		return false;
526	}
527	return true;
528}
529
530void FFmpegEncoderClose(struct FFmpegEncoder* encoder) {
531	if (encoder->audio) {
532		while (true) {
533			if (!_ffmpegWriteAudioFrame(encoder, NULL)) {
534				break;
535			}
536		}
537	}
538	if (encoder->video) {
539		if (encoder->graph) {
540			if (av_buffersrc_add_frame(encoder->source, NULL) >= 0) {
541				while (true) {
542					int res = av_buffersink_get_frame(encoder->sink, encoder->sinkFrame);
543					if (res < 0) {
544						break;
545					}
546					_ffmpegWriteVideoFrame(encoder, encoder->sinkFrame);
547					av_frame_unref(encoder->sinkFrame);
548				}
549			}
550		}
551		while (true) {
552			if (!_ffmpegWriteVideoFrame(encoder, NULL)) {
553				break;
554			}
555		}
556	}
557
558	if (encoder->context && encoder->context->pb) {
559		av_write_trailer(encoder->context);
560		avio_close(encoder->context->pb);
561	}
562
563	if (encoder->postaudioBuffer) {
564		av_free(encoder->postaudioBuffer);
565		encoder->postaudioBuffer = NULL;
566	}
567	if (encoder->audioBuffer) {
568		av_free(encoder->audioBuffer);
569		encoder->audioBuffer = NULL;
570	}
571
572	if (encoder->audioFrame) {
573#if LIBAVCODEC_VERSION_MAJOR >= 55
574		av_frame_free(&encoder->audioFrame);
575#else
576		avcodec_free_frame(&encoder->audioFrame);
577#endif
578	}
579	if (encoder->audio) {
580#ifdef FFMPEG_USE_CODECPAR
581		avcodec_free_context(&encoder->audio);
582#else
583		avcodec_close(encoder->audio);
584		encoder->audio = NULL;
585#endif
586	}
587
588	if (encoder->resampleContext) {
589#ifdef USE_LIBAVRESAMPLE
590		avresample_close(encoder->resampleContext);
591		encoder->resampleContext = NULL;
592#else
593		swr_free(&encoder->resampleContext);
594#endif
595	}
596
597	if (encoder->absf) {
598#ifdef FFMPEG_USE_NEW_BSF
599		av_bsf_free(&encoder->absf);
600#else
601		av_bitstream_filter_close(encoder->absf);
602		encoder->absf = NULL;
603#endif
604	}
605
606	if (encoder->videoFrame) {
607		av_freep(encoder->videoFrame->data);
608#if LIBAVCODEC_VERSION_MAJOR >= 55
609		av_frame_free(&encoder->videoFrame);
610#else
611		avcodec_free_frame(&encoder->videoFrame);
612#endif
613	}
614
615	if (encoder->sinkFrame) {
616#if LIBAVCODEC_VERSION_MAJOR >= 55
617		av_frame_free(&encoder->sinkFrame);
618#else
619		avcodec_free_frame(&encoder->sinkFrame);
620#endif
621		encoder->sinkFrame = NULL;
622	}
623
624	if (encoder->video) {
625#ifdef FFMPEG_USE_CODECPAR
626		avcodec_free_context(&encoder->video);
627#else
628		avcodec_close(encoder->video);
629		encoder->video = NULL;
630#endif
631	}
632
633	if (encoder->scaleContext) {
634		sws_freeContext(encoder->scaleContext);
635		encoder->scaleContext = NULL;
636	}
637
638	if (encoder->graph) {
639		avfilter_graph_free(&encoder->graph);
640		encoder->graph = NULL;
641		encoder->source = NULL;
642		encoder->sink = NULL;
643
644		int i;
645		for (i = 0; i < FFMPEG_FILTERS_MAX; ++i) {
646			encoder->filters[i] = NULL;
647		}
648	}
649
650	if (encoder->context) {
651		avformat_free_context(encoder->context);
652		encoder->context = NULL;
653	}
654}
655
656bool FFmpegEncoderIsOpen(struct FFmpegEncoder* encoder) {
657	return !!encoder->context;
658}
659
660void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) {
661	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
662	if (!encoder->context || !encoder->audioCodec) {
663		return;
664	}
665
666	if (encoder->absf && !left) {
667		// XXX: AVBSF doesn't like silence. Figure out why.
668		left = 1;
669	}
670
671	encoder->audioBuffer[encoder->currentAudioSample * 2] = left;
672	encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right;
673
674	++encoder->currentAudioSample;
675
676	if (encoder->currentAudioSample * 4 < encoder->audioBufferSize) {
677		return;
678	}
679
680	int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
681	encoder->currentAudioSample = 0;
682#ifdef USE_LIBAVRESAMPLE
683	avresample_convert(encoder->resampleContext, 0, 0, 0,
684	                   (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);
685
686	if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
687		return;
688	}
689#if LIBAVCODEC_VERSION_MAJOR >= 55
690	av_frame_make_writable(encoder->audioFrame);
691#endif
692	int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
693#else
694#if LIBAVCODEC_VERSION_MAJOR >= 55
695	av_frame_make_writable(encoder->audioFrame);
696#endif
697	if (swr_get_out_samples(encoder->resampleContext, 1) < encoder->audioFrame->nb_samples) {
698		swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
699		return;
700	}
701	int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize,
702	                          (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
703#endif
704
705	encoder->audioFrame->pts = encoder->currentAudioFrame;
706	encoder->currentAudioFrame += samples;
707
708	_ffmpegWriteAudioFrame(encoder, encoder->audioFrame);
709}
710
711bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame) {
712	AVPacket packet;
713	av_init_packet(&packet);
714	packet.data = 0;
715	packet.size = 0;
716
717	int gotData;
718#ifdef FFMPEG_USE_PACKETS
719	avcodec_send_frame(encoder->audio, audioFrame);
720	gotData = avcodec_receive_packet(encoder->audio, &packet);
721	gotData = (gotData == 0) && packet.size;
722#else
723	avcodec_encode_audio2(encoder->audio, &packet, audioFrame, &gotData);
724#endif
725	packet.pts = av_rescale_q(packet.pts, encoder->audio->time_base, encoder->audioStream->time_base);
726	packet.dts = packet.pts;
727
728	if (gotData) {
729		if (encoder->absf) {
730			AVPacket tempPacket;
731
732#ifdef FFMPEG_USE_NEW_BSF
733			int success = av_bsf_send_packet(encoder->absf, &packet);
734			if (success >= 0) {
735				success = av_bsf_receive_packet(encoder->absf, &tempPacket);
736			}
737#else
738			int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0,
739			    &tempPacket.data, &tempPacket.size,
740			    packet.data, packet.size, 0);
741#endif
742
743			if (success >= 0) {
744#if LIBAVUTIL_VERSION_MAJOR >= 53
745				tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0);
746#endif
747
748#ifdef FFMPEG_USE_PACKET_UNREF
749				av_packet_move_ref(&packet, &tempPacket);
750#else
751				av_free_packet(&packet);
752				packet = tempPacket;
753#endif
754
755				packet.stream_index = encoder->audioStream->index;
756				av_interleaved_write_frame(encoder->context, &packet);
757			}
758		} else {
759			packet.stream_index = encoder->audioStream->index;
760			av_interleaved_write_frame(encoder->context, &packet);
761		}
762	}
763#ifdef FFMPEG_USE_PACKET_UNREF
764	av_packet_unref(&packet);
765#else
766	av_free_packet(&packet);
767#endif
768	return gotData;
769}
770
771void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size_t stride) {
772	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
773	if (!encoder->context || !encoder->videoCodec) {
774		return;
775	}
776	encoder->skipResidue = (encoder->skipResidue + 1) % encoder->frameskip;
777	if (encoder->skipResidue) {
778		return;
779	}
780	stride *= BYTES_PER_PIXEL;
781
782#if LIBAVCODEC_VERSION_MAJOR >= 55
783	av_frame_make_writable(encoder->videoFrame);
784#endif
785	if (encoder->video->codec->id == AV_CODEC_ID_WEBP) {
786		// TODO: Figure out why WebP is rescaling internally (should video frames not be rescaled externally?)
787		encoder->videoFrame->pts = encoder->currentVideoFrame;
788	} else {
789		encoder->videoFrame->pts = av_rescale_q(encoder->currentVideoFrame, encoder->video->time_base, encoder->videoStream->time_base);
790	}
791	++encoder->currentVideoFrame;
792
793	sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, encoder->iheight, encoder->videoFrame->data, encoder->videoFrame->linesize);
794
795	if (encoder->graph) {
796		if (av_buffersrc_add_frame(encoder->source, encoder->videoFrame) < 0) {
797			return;
798		}
799		while (true) {
800			int res = av_buffersink_get_frame(encoder->sink, encoder->sinkFrame);
801			if (res < 0) {
802				break;
803			}
804			_ffmpegWriteVideoFrame(encoder, encoder->sinkFrame);
805			av_frame_unref(encoder->sinkFrame);
806		}
807	} else {
808		_ffmpegWriteVideoFrame(encoder, encoder->videoFrame);
809	}
810}
811
812bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame) {
813	AVPacket packet;
814
815	av_init_packet(&packet);
816	packet.data = 0;
817	packet.size = 0;
818
819	int gotData;
820#ifdef FFMPEG_USE_PACKETS
821	avcodec_send_frame(encoder->video, videoFrame);
822	gotData = avcodec_receive_packet(encoder->video, &packet) == 0;
823#else
824	avcodec_encode_video2(encoder->video, &packet, videoFrame, &gotData);
825#endif
826	if (gotData) {
827#ifndef FFMPEG_USE_PACKET_UNREF
828		if (encoder->video->coded_frame->key_frame) {
829			packet.flags |= AV_PKT_FLAG_KEY;
830		}
831#endif
832		packet.stream_index = encoder->videoStream->index;
833		av_interleaved_write_frame(encoder->context, &packet);
834	}
835#ifdef FFMPEG_USE_PACKET_UNREF
836	av_packet_unref(&packet);
837#else
838	av_free_packet(&packet);
839#endif
840
841	return gotData;
842}
843
844static void _ffmpegSetVideoDimensions(struct mAVStream* stream, unsigned width, unsigned height) {
845	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
846	if (!encoder->context || !encoder->videoCodec) {
847		return;
848	}
849	encoder->iwidth = width;
850	encoder->iheight = height;
851	if (encoder->scaleContext) {
852		sws_freeContext(encoder->scaleContext);
853	}
854	encoder->scaleContext = sws_getContext(encoder->iwidth, encoder->iheight, encoder->ipixFormat,
855	    encoder->videoFrame->width, encoder->videoFrame->height, encoder->videoFrame->format,
856	    SWS_POINT, 0, 0, 0);
857}
858
859static void _ffmpegSetVideoFrameRate(struct mAVStream* stream, unsigned numerator, unsigned denominator) {
860	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
861	FFmpegEncoderSetInputFrameRate(encoder, numerator, denominator);
862}
863
864void FFmpegEncoderSetInputFrameRate(struct FFmpegEncoder* encoder, int numerator, int denominator) {
865	reduceFraction(&numerator, &denominator);
866	encoder->frameCycles = numerator;
867	encoder->cycles = denominator;
868	if (encoder->video) {
869		encoder->video->framerate = (AVRational) { denominator, numerator * encoder->frameskip };
870	}
871}