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
11#include <libavcodec/version.h>
12#include <libavcodec/avcodec.h>
13
14#include <libavutil/version.h>
15#if LIBAVUTIL_VERSION_MAJOR >= 53
16#include <libavutil/buffer.h>
17#endif
18#include <libavutil/imgutils.h>
19#include <libavutil/mathematics.h>
20#include <libavutil/opt.h>
21
22#ifdef USE_LIBAVRESAMPLE
23#include <libavresample/avresample.h>
24#else
25#include <libswresample/swresample.h>
26#endif
27#include <libswscale/swscale.h>
28
29static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);
30static void _ffmpegPostAudioFrame(struct mAVStream*, int16_t left, int16_t right);
31static void _ffmpegSetVideoDimensions(struct mAVStream*, unsigned width, unsigned height);
32
33static bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame);
34static bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame);
35
36enum {
37 PREFERRED_SAMPLE_RATE = 0x8000
38};
39
40void FFmpegEncoderInit(struct FFmpegEncoder* encoder) {
41 av_register_all();
42
43 encoder->d.videoDimensionsChanged = _ffmpegSetVideoDimensions;
44 encoder->d.postVideoFrame = _ffmpegPostVideoFrame;
45 encoder->d.postAudioFrame = _ffmpegPostAudioFrame;
46 encoder->d.postAudioBuffer = 0;
47
48 encoder->audioCodec = NULL;
49 encoder->videoCodec = NULL;
50 encoder->containerFormat = NULL;
51 FFmpegEncoderSetAudio(encoder, "flac", 0);
52 FFmpegEncoderSetVideo(encoder, "png", 0);
53 FFmpegEncoderSetContainer(encoder, "matroska");
54 FFmpegEncoderSetDimensions(encoder, GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS);
55 encoder->iwidth = GBA_VIDEO_HORIZONTAL_PIXELS;
56 encoder->iheight = GBA_VIDEO_VERTICAL_PIXELS;
57 encoder->resampleContext = NULL;
58 encoder->absf = NULL;
59 encoder->context = NULL;
60 encoder->scaleContext = NULL;
61 encoder->audio = NULL;
62 encoder->audioStream = NULL;
63 encoder->audioFrame = NULL;
64 encoder->audioBuffer = NULL;
65 encoder->postaudioBuffer = NULL;
66 encoder->video = NULL;
67 encoder->videoStream = NULL;
68 encoder->videoFrame = NULL;
69}
70
71bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, unsigned abr) {
72 static const struct {
73 int format;
74 int priority;
75 } priorities[] = {
76 { AV_SAMPLE_FMT_S16, 0 },
77 { AV_SAMPLE_FMT_S16P, 1 },
78 { AV_SAMPLE_FMT_S32, 2 },
79 { AV_SAMPLE_FMT_S32P, 2 },
80 { AV_SAMPLE_FMT_FLT, 3 },
81 { AV_SAMPLE_FMT_FLTP, 3 },
82 { AV_SAMPLE_FMT_DBL, 4 },
83 { AV_SAMPLE_FMT_DBLP, 4 }
84 };
85
86 if (!acodec) {
87 encoder->audioCodec = 0;
88 return true;
89 }
90
91 AVCodec* codec = avcodec_find_encoder_by_name(acodec);
92 if (!codec) {
93 return false;
94 }
95
96 if (!codec->sample_fmts) {
97 return false;
98 }
99 size_t i;
100 size_t j;
101 int priority = INT_MAX;
102 encoder->sampleFormat = AV_SAMPLE_FMT_NONE;
103 for (i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) {
104 for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) {
105 if (codec->sample_fmts[i] == priorities[j].format && priority > priorities[j].priority) {
106 priority = priorities[j].priority;
107 encoder->sampleFormat = codec->sample_fmts[i];
108 }
109 }
110 }
111 if (encoder->sampleFormat == AV_SAMPLE_FMT_NONE) {
112 return false;
113 }
114 encoder->sampleRate = PREFERRED_SAMPLE_RATE;
115 if (codec->supported_samplerates) {
116 for (i = 0; codec->supported_samplerates[i]; ++i) {
117 if (codec->supported_samplerates[i] < PREFERRED_SAMPLE_RATE) {
118 continue;
119 }
120 if (encoder->sampleRate == PREFERRED_SAMPLE_RATE || encoder->sampleRate > codec->supported_samplerates[i]) {
121 encoder->sampleRate = codec->supported_samplerates[i];
122 }
123 }
124 } else if (codec->id == AV_CODEC_ID_AAC) {
125 // HACK: AAC doesn't support 32768Hz (it rounds to 32000), but libfaac doesn't tell us that
126 encoder->sampleRate = 44100;
127 }
128 encoder->audioCodec = acodec;
129 encoder->audioBitrate = abr;
130 return true;
131}
132
133bool FFmpegEncoderSetVideo(struct FFmpegEncoder* encoder, const char* vcodec, unsigned vbr) {
134 static const struct {
135 enum AVPixelFormat format;
136 int priority;
137 } priorities[] = {
138 { AV_PIX_FMT_RGB555, 0 },
139 { AV_PIX_FMT_BGR555, 0 },
140 { AV_PIX_FMT_RGB565, 1 },
141 { AV_PIX_FMT_BGR565, 1 },
142 { AV_PIX_FMT_RGB24, 2 },
143 { AV_PIX_FMT_BGR24, 2 },
144#ifndef USE_LIBAV
145 { AV_PIX_FMT_BGR0, 3 },
146 { AV_PIX_FMT_RGB0, 3 },
147 { AV_PIX_FMT_0BGR, 3 },
148 { AV_PIX_FMT_0RGB, 3 },
149#endif
150 { AV_PIX_FMT_YUV422P, 4 },
151 { AV_PIX_FMT_YUV444P, 5 },
152 { AV_PIX_FMT_YUV420P, 6 }
153 };
154
155 if (!vcodec) {
156 encoder->videoCodec = 0;
157 return true;
158 }
159
160 AVCodec* codec = avcodec_find_encoder_by_name(vcodec);
161 if (!codec) {
162 return false;
163 }
164
165 size_t i;
166 size_t j;
167 int priority = INT_MAX;
168 encoder->pixFormat = AV_PIX_FMT_NONE;
169 for (i = 0; codec->pix_fmts[i] != AV_PIX_FMT_NONE; ++i) {
170 for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) {
171 if (codec->pix_fmts[i] == priorities[j].format && priority > priorities[j].priority) {
172 priority = priorities[j].priority;
173 encoder->pixFormat = codec->pix_fmts[i];
174 }
175 }
176 }
177 if (encoder->pixFormat == AV_PIX_FMT_NONE) {
178 return false;
179 }
180 encoder->videoCodec = vcodec;
181 encoder->videoBitrate = vbr;
182 return true;
183}
184
185bool FFmpegEncoderSetContainer(struct FFmpegEncoder* encoder, const char* container) {
186 AVOutputFormat* oformat = av_guess_format(container, 0, 0);
187 if (!oformat) {
188 return false;
189 }
190 encoder->containerFormat = container;
191 return true;
192}
193
194void FFmpegEncoderSetDimensions(struct FFmpegEncoder* encoder, int width, int height) {
195 encoder->width = width > 0 ? width : GBA_VIDEO_HORIZONTAL_PIXELS;
196 encoder->height = height > 0 ? height : GBA_VIDEO_VERTICAL_PIXELS;
197}
198
199bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) {
200 AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0);
201 AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);
202 AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec);
203 if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat) {
204 return false;
205 }
206 if (encoder->audioCodec && !avformat_query_codec(oformat, acodec->id, FF_COMPLIANCE_EXPERIMENTAL)) {
207 return false;
208 }
209 if (encoder->videoCodec && !avformat_query_codec(oformat, vcodec->id, FF_COMPLIANCE_EXPERIMENTAL)) {
210 return false;
211 }
212 return true;
213}
214
215bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
216 AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);
217 AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec);
218 if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !FFmpegEncoderVerifyContainer(encoder)) {
219 return false;
220 }
221
222 if (encoder->context) {
223 return false;
224 }
225
226 encoder->currentAudioSample = 0;
227 encoder->currentAudioFrame = 0;
228 encoder->currentVideoFrame = 0;
229
230 AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0);
231#ifndef USE_LIBAV
232 avformat_alloc_output_context2(&encoder->context, oformat, 0, outfile);
233#else
234 encoder->context = avformat_alloc_context();
235 strncpy(encoder->context->filename, outfile, sizeof(encoder->context->filename) - 1);
236 encoder->context->filename[sizeof(encoder->context->filename) - 1] = '\0';
237 encoder->context->oformat = oformat;
238#endif
239
240 if (acodec) {
241#ifdef FFMPEG_USE_CODECPAR
242 encoder->audioStream = avformat_new_stream(encoder->context, NULL);
243 encoder->audio = avcodec_alloc_context3(acodec);
244#else
245 encoder->audioStream = avformat_new_stream(encoder->context, acodec);
246 encoder->audio = encoder->audioStream->codec;
247#endif
248 encoder->audio->bit_rate = encoder->audioBitrate;
249 encoder->audio->channels = 2;
250 encoder->audio->channel_layout = AV_CH_LAYOUT_STEREO;
251 encoder->audio->sample_rate = encoder->sampleRate;
252 encoder->audio->sample_fmt = encoder->sampleFormat;
253 AVDictionary* opts = 0;
254 av_dict_set(&opts, "strict", "-2", 0);
255 if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
256#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
257 encoder->audio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
258#else
259 encoder->audio->flags |= CODEC_FLAG_GLOBAL_HEADER;
260#endif
261 }
262 int res = avcodec_open2(encoder->audio, acodec, &opts);
263 av_dict_free(&opts);
264 if (res < 0) {
265 FFmpegEncoderClose(encoder);
266 return false;
267 }
268#if LIBAVCODEC_VERSION_MAJOR >= 55
269 encoder->audioFrame = av_frame_alloc();
270#else
271 encoder->audioFrame = avcodec_alloc_frame();
272#endif
273 if (!encoder->audio->frame_size) {
274 encoder->audio->frame_size = 1;
275 }
276 encoder->audioFrame->nb_samples = encoder->audio->frame_size;
277 encoder->audioFrame->format = encoder->audio->sample_fmt;
278 encoder->audioFrame->pts = 0;
279#ifdef USE_LIBAVRESAMPLE
280 encoder->resampleContext = avresample_alloc_context();
281 av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
282 av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
283 av_opt_set_int(encoder->resampleContext, "in_sample_rate", PREFERRED_SAMPLE_RATE, 0);
284 av_opt_set_int(encoder->resampleContext, "out_sample_rate", encoder->sampleRate, 0);
285 av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
286 av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0);
287 avresample_open(encoder->resampleContext);
288#else
289 encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate,
290 AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL);
291 swr_init(encoder->resampleContext);
292#endif
293 encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4;
294 encoder->audioBuffer = av_malloc(encoder->audioBufferSize);
295 encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
296 encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize);
297 avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0);
298
299 if (encoder->audio->codec->id == AV_CODEC_ID_AAC &&
300 (strcasecmp(encoder->containerFormat, "mp4") ||
301 strcasecmp(encoder->containerFormat, "m4v") ||
302 strcasecmp(encoder->containerFormat, "mov"))) {
303 // MP4 container doesn't support the raw ADTS AAC format that the encoder spits out
304#ifdef FFMPEG_USE_NEW_BSF
305 av_bsf_alloc(av_bsf_get_by_name("aac_adtstoasc"), &encoder->absf);
306 avcodec_parameters_from_context(encoder->absf->par_in, encoder->audio);
307 av_bsf_init(encoder->absf);
308#else
309 encoder->absf = av_bitstream_filter_init("aac_adtstoasc");
310#endif
311 }
312#ifdef FFMPEG_USE_CODECPAR
313 avcodec_parameters_from_context(encoder->audioStream->codecpar, encoder->audio);
314#endif
315 }
316
317 if (vcodec) {
318#ifdef FFMPEG_USE_CODECPAR
319 encoder->videoStream = avformat_new_stream(encoder->context, NULL);
320 encoder->video = avcodec_alloc_context3(vcodec);
321#else
322 encoder->videoStream = avformat_new_stream(encoder->context, vcodec);
323 encoder->video = encoder->videoStream->codec;
324#endif
325 encoder->video->bit_rate = encoder->videoBitrate;
326 encoder->video->width = encoder->width;
327 encoder->video->height = encoder->height;
328 encoder->video->time_base = (AVRational) { VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY };
329 encoder->video->framerate = (AVRational) { GBA_ARM7TDMI_FREQUENCY, VIDEO_TOTAL_LENGTH };
330 encoder->video->pix_fmt = encoder->pixFormat;
331 encoder->video->gop_size = 60;
332 encoder->video->max_b_frames = 3;
333 if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
334#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
335 encoder->video->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
336#else
337 encoder->video->flags |= CODEC_FLAG_GLOBAL_HEADER;
338#endif
339 }
340
341 if (encoder->video->codec->id == AV_CODEC_ID_H264 &&
342 (strcasecmp(encoder->containerFormat, "mp4") ||
343 strcasecmp(encoder->containerFormat, "m4v") ||
344 strcasecmp(encoder->containerFormat, "mov"))) {
345 // QuickTime and a few other things require YUV420
346 encoder->video->pix_fmt = AV_PIX_FMT_YUV420P;
347 }
348
349 if (strcmp(vcodec->name, "libx264") == 0) {
350 // Try to adaptively figure out when you can use a slower encoder
351 if (encoder->width * encoder->height > 1000000) {
352 av_opt_set(encoder->video->priv_data, "preset", "superfast", 0);
353 } else if (encoder->width * encoder->height > 500000) {
354 av_opt_set(encoder->video->priv_data, "preset", "veryfast", 0);
355 } else {
356 av_opt_set(encoder->video->priv_data, "preset", "faster", 0);
357 }
358 if (encoder->videoBitrate == 0) {
359 av_opt_set(encoder->video->priv_data, "crf", "0", 0);
360 encoder->video->pix_fmt = AV_PIX_FMT_YUV444P;
361 }
362 }
363 if (strcmp(vcodec->name, "libvpx-vp9") == 0 && encoder->videoBitrate == 0) {
364 av_opt_set(encoder->video->priv_data, "lossless", "1", 0);
365 encoder->video->pix_fmt = AV_PIX_FMT_YUV444P;
366 }
367
368 if (avcodec_open2(encoder->video, vcodec, 0) < 0) {
369 FFmpegEncoderClose(encoder);
370 return false;
371 }
372#if LIBAVCODEC_VERSION_MAJOR >= 55
373 encoder->videoFrame = av_frame_alloc();
374#else
375 encoder->videoFrame = avcodec_alloc_frame();
376#endif
377 encoder->videoFrame->format = encoder->video->pix_fmt;
378 encoder->videoFrame->width = encoder->video->width;
379 encoder->videoFrame->height = encoder->video->height;
380 encoder->videoFrame->pts = 0;
381 _ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight);
382 av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->video->width, encoder->video->height, encoder->video->pix_fmt, 32);
383#ifdef FFMPEG_USE_CODECPAR
384 avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video);
385#endif
386 }
387
388 if (avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, 0) < 0) {
389 FFmpegEncoderClose(encoder);
390 return false;
391 }
392 return true;
393}
394
395void FFmpegEncoderClose(struct FFmpegEncoder* encoder) {
396 if (encoder->audio) {
397 while (true) {
398 if (!_ffmpegWriteAudioFrame(encoder, NULL)) {
399 break;
400 }
401 }
402 }
403 if (encoder->video) {
404 while (true) {
405 if (!_ffmpegWriteVideoFrame(encoder, NULL)) {
406 break;
407 }
408 }
409 }
410
411 if (encoder->context && encoder->context->pb) {
412 av_write_trailer(encoder->context);
413 avio_close(encoder->context->pb);
414 }
415
416 if (encoder->postaudioBuffer) {
417 av_free(encoder->postaudioBuffer);
418 encoder->postaudioBuffer = NULL;
419 }
420 if (encoder->audioBuffer) {
421 av_free(encoder->audioBuffer);
422 encoder->audioBuffer = NULL;
423 }
424
425 if (encoder->audioFrame) {
426#if LIBAVCODEC_VERSION_MAJOR >= 55
427 av_frame_free(&encoder->audioFrame);
428#else
429 avcodec_free_frame(&encoder->audioFrame);
430#endif
431 }
432 if (encoder->audio) {
433 avcodec_close(encoder->audio);
434 encoder->audio = NULL;
435 }
436
437 if (encoder->resampleContext) {
438#ifdef USE_LIBAVRESAMPLE
439 avresample_close(encoder->resampleContext);
440 encoder->resampleContext = NULL;
441#else
442 swr_free(&encoder->resampleContext);
443#endif
444 }
445
446 if (encoder->absf) {
447#ifdef FFMPEG_USE_NEW_BSF
448 av_bsf_free(&encoder->absf);
449#else
450 av_bitstream_filter_close(encoder->absf);
451 encoder->absf = NULL;
452#endif
453 }
454
455 if (encoder->videoFrame) {
456#if LIBAVCODEC_VERSION_MAJOR >= 55
457 av_frame_free(&encoder->videoFrame);
458#else
459 avcodec_free_frame(&encoder->videoFrame);
460#endif
461 }
462
463 if (encoder->video) {
464 avcodec_close(encoder->video);
465 encoder->video = NULL;
466 }
467
468 if (encoder->scaleContext) {
469 sws_freeContext(encoder->scaleContext);
470 encoder->scaleContext = NULL;
471 }
472
473 if (encoder->context) {
474 avformat_free_context(encoder->context);
475 encoder->context = NULL;
476 }
477}
478
479bool FFmpegEncoderIsOpen(struct FFmpegEncoder* encoder) {
480 return !!encoder->context;
481}
482
483void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) {
484 struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
485 if (!encoder->context || !encoder->audioCodec) {
486 return;
487 }
488
489 if (encoder->absf && !left) {
490 // XXX: AVBSF doesn't like silence. Figure out why.
491 left = 1;
492 }
493
494 encoder->audioBuffer[encoder->currentAudioSample * 2] = left;
495 encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right;
496
497 ++encoder->currentAudioSample;
498
499 if (encoder->currentAudioSample * 4 < encoder->audioBufferSize) {
500 return;
501 }
502
503 int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
504 encoder->currentAudioSample = 0;
505#ifdef USE_LIBAVRESAMPLE
506 avresample_convert(encoder->resampleContext, 0, 0, 0,
507 (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);
508
509 if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
510 return;
511 }
512#if LIBAVCODEC_VERSION_MAJOR >= 55
513 av_frame_make_writable(encoder->audioFrame);
514#endif
515 int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
516#else
517#if LIBAVCODEC_VERSION_MAJOR >= 55
518 av_frame_make_writable(encoder->audioFrame);
519#endif
520 if (swr_get_out_samples(encoder->resampleContext, 1) < encoder->audioFrame->nb_samples) {
521 swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
522 return;
523 }
524 int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize,
525 (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
526#endif
527
528 encoder->audioFrame->pts = encoder->currentAudioFrame;
529 encoder->currentAudioFrame += samples;
530
531 _ffmpegWriteAudioFrame(encoder, encoder->audioFrame);
532}
533
534bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame) {
535 AVPacket packet;
536 av_init_packet(&packet);
537 packet.data = 0;
538 packet.size = 0;
539
540 int gotData;
541#ifdef FFMPEG_USE_PACKETS
542 avcodec_send_frame(encoder->audio, audioFrame);
543 gotData = avcodec_receive_packet(encoder->audio, &packet);
544 gotData = (gotData == 0) && packet.size;
545#else
546 avcodec_encode_audio2(encoder->audio, &packet, audioFrame, &gotData);
547#endif
548 packet.pts = av_rescale_q(packet.pts, encoder->audio->time_base, encoder->audioStream->time_base);
549 packet.dts = packet.pts;
550
551 if (gotData) {
552 if (encoder->absf) {
553 AVPacket tempPacket;
554
555#ifdef FFMPEG_USE_NEW_BSF
556 int success = av_bsf_send_packet(encoder->absf, &packet);
557 if (success >= 0) {
558 success = av_bsf_receive_packet(encoder->absf, &tempPacket);
559 }
560#else
561 int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0,
562 &tempPacket.data, &tempPacket.size,
563 packet.data, packet.size, 0);
564#endif
565
566 if (success >= 0) {
567#if LIBAVUTIL_VERSION_MAJOR >= 53
568 tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0);
569#endif
570
571#ifdef FFMPEG_USE_PACKET_UNREF
572 av_packet_move_ref(&packet, &tempPacket);
573#else
574 av_free_packet(&packet);
575 packet = tempPacket;
576#endif
577
578 packet.stream_index = encoder->audioStream->index;
579 av_interleaved_write_frame(encoder->context, &packet);
580 }
581 } else {
582 packet.stream_index = encoder->audioStream->index;
583 av_interleaved_write_frame(encoder->context, &packet);
584 }
585 }
586#ifdef FFMPEG_USE_PACKET_UNREF
587 av_packet_unref(&packet);
588#else
589 av_free_packet(&packet);
590#endif
591 return gotData;
592}
593
594void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size_t stride) {
595 struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
596 if (!encoder->context || !encoder->videoCodec) {
597 return;
598 }
599 stride *= BYTES_PER_PIXEL;
600
601#if LIBAVCODEC_VERSION_MAJOR >= 55
602 av_frame_make_writable(encoder->videoFrame);
603#endif
604 encoder->videoFrame->pts = av_rescale_q(encoder->currentVideoFrame, encoder->video->time_base, encoder->videoStream->time_base);
605 ++encoder->currentVideoFrame;
606
607 sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, encoder->iheight, encoder->videoFrame->data, encoder->videoFrame->linesize);
608
609 _ffmpegWriteVideoFrame(encoder, encoder->videoFrame);
610}
611
612bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame) {
613 AVPacket packet;
614
615 av_init_packet(&packet);
616 packet.data = 0;
617 packet.size = 0;
618
619 int gotData;
620#ifdef FFMPEG_USE_PACKETS
621 avcodec_send_frame(encoder->video, videoFrame);
622 gotData = avcodec_receive_packet(encoder->video, &packet) == 0;
623#else
624 avcodec_encode_video2(encoder->video, &packet, videoFrame, &gotData);
625#endif
626 if (gotData) {
627#ifndef FFMPEG_USE_PACKET_UNREF
628 if (encoder->video->coded_frame->key_frame) {
629 packet.flags |= AV_PKT_FLAG_KEY;
630 }
631#endif
632 packet.stream_index = encoder->videoStream->index;
633 av_interleaved_write_frame(encoder->context, &packet);
634 }
635#ifdef FFMPEG_USE_PACKET_UNREF
636 av_packet_unref(&packet);
637#else
638 av_free_packet(&packet);
639#endif
640
641 return gotData;
642}
643
644static void _ffmpegSetVideoDimensions(struct mAVStream* stream, unsigned width, unsigned height) {
645 struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
646 if (!encoder->context || !encoder->videoCodec) {
647 return;
648 }
649 encoder->iwidth = width;
650 encoder->iheight = height;
651 if (encoder->scaleContext) {
652 sws_freeContext(encoder->scaleContext);
653 }
654 encoder->scaleContext = sws_getContext(encoder->iwidth, encoder->iheight,
655#ifdef COLOR_16_BIT
656#ifdef COLOR_5_6_5
657 AV_PIX_FMT_RGB565,
658#else
659 AV_PIX_FMT_BGR555,
660#endif
661#else
662#ifndef USE_LIBAV
663 AV_PIX_FMT_0BGR32,
664#else
665 AV_PIX_FMT_BGR32,
666#endif
667#endif
668 encoder->videoFrame->width, encoder->videoFrame->height, encoder->video->pix_fmt,
669 SWS_POINT, 0, 0, 0);
670}