1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2017 - Daniel De Matteis
4 * Copyright (C) 2017-2019 - Andrés Suárez
5 *
6 * RetroArch is free software: you can redistribute it and/or modify it under the terms
7 * of the GNU General Public License as published by the Free Software Found-
8 * ation, either version 3 of the License, or (at your option) any later version.
9 *
10 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with RetroArch.
15 * If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <retro_assert.h>
23 #include <compat/msvc.h>
24 #include <compat/strl.h>
25
26 #include <boolean.h>
27 #include <queues/fifo_queue.h>
28 #include <rthreads/rthreads.h>
29 #include <gfx/scaler/scaler.h>
30 #include <gfx/video_frame.h>
31 #include <file/config_file.h>
32 #include <audio/audio_resampler.h>
33 #include <string/stdstring.h>
34 #include <audio/conversion/float_to_s16.h>
35 #include <audio/conversion/s16_to_float.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include "../../config.h"
39 #endif
40
41 #ifdef FFEMU_PERF
42 #include <time.h>
43 #endif
44
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48
49 #include <libavcodec/avcodec.h>
50 #include <libavutil/imgutils.h>
51 #include <libavutil/mathematics.h>
52 #include <libavutil/avutil.h>
53 #include <libavutil/avstring.h>
54 #include <libavutil/opt.h>
55 #include <libavutil/version.h>
56 #include <libavformat/avformat.h>
57 #ifdef HAVE_AV_CHANNEL_LAYOUT
58 #include <libavutil/channel_layout.h>
59 #endif
60 #include <libavutil/avconfig.h>
61 #include <libavutil/pixdesc.h>
62 #include <libswscale/swscale.h>
63
64 #ifdef __cplusplus
65 }
66 #endif
67
68 #include "../../retroarch.h"
69 #include "../../verbosity.h"
70
71 #ifndef AV_CODEC_FLAG_QSCALE
72 #define AV_CODEC_FLAG_QSCALE CODEC_FLAG_QSCALE
73 #endif
74
75 #ifndef AV_CODEC_FLAG_GLOBAL_HEADER
76 #define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER
77 #endif
78
79 #ifndef AV_INPUT_BUFFER_MIN_SIZE
80 #define AV_INPUT_BUFFER_MIN_SIZE FF_MIN_BUFFER_SIZE
81 #endif
82
83 #ifndef PIX_FMT_RGB32
84 #define PIX_FMT_RGB32 AV_PIX_FMT_RGB32
85 #endif
86
87 #ifndef PIX_FMT_YUV444P
88 #define PIX_FMT_YUV444P AV_PIX_FMT_YUV444P
89 #endif
90
91 #ifndef PIX_FMT_YUV420P
92 #define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
93 #endif
94
95 #ifndef PIX_FMT_BGR24
96 #define PIX_FMT_BGR24 AV_PIX_FMT_BGR24
97 #endif
98
99 #ifndef PIX_FMT_RGB24
100 #define PIX_FMT_RGB24 AV_PIX_FMT_RGB24
101 #endif
102
103 #ifndef PIX_FMT_RGB8
104 #define PIX_FMT_RGB8 AV_PIX_FMT_RGB8
105 #endif
106
107 #ifndef PIX_FMT_RGB565
108 #define PIX_FMT_RGB565 AV_PIX_FMT_RGB565
109 #endif
110
111 #ifndef PIX_FMT_RGBA
112 #define PIX_FMT_RGBA AV_PIX_FMT_RGBA
113 #endif
114
115 #ifndef PIX_FMT_NONE
116 #define PIX_FMT_NONE AV_PIX_FMT_NONE
117 #endif
118
119 #ifndef PixelFormat
120 #define PixelFormat AVPixelFormat
121 #endif
122
123 #if LIBAVUTIL_VERSION_INT <= AV_VERSION_INT(52, 9, 0)
124 #define av_frame_alloc avcodec_alloc_frame
125 #define av_frame_free avcodec_free_frame
126 #endif
127
128 struct ff_video_info
129 {
130 AVCodecContext *codec;
131 AVCodec *encoder;
132
133 AVFrame *conv_frame;
134 uint8_t *conv_frame_buf;
135 int64_t frame_cnt;
136
137 uint8_t *outbuf;
138 size_t outbuf_size;
139
140 /* Output pixel format. */
141 enum PixelFormat pix_fmt;
142 /* Input pixel format. Only used by sws. */
143 enum PixelFormat in_pix_fmt;
144
145 unsigned frame_drop_ratio;
146 unsigned frame_drop_count;
147
148 /* Input pixel size. */
149 size_t pix_size;
150
151 AVFormatContext *format;
152
153 struct scaler_ctx scaler;
154 struct SwsContext *sws;
155 bool use_sws;
156 };
157
158 struct ff_audio_info
159 {
160 AVCodecContext *codec;
161 AVCodec *encoder;
162
163 uint8_t *buffer;
164 size_t frames_in_buffer;
165
166 int64_t frame_cnt;
167
168 uint8_t *outbuf;
169 size_t outbuf_size;
170
171 /* Most lossy audio codecs only support certain sampling rates.
172 * Could use libswresample, but it doesn't support floating point ratios.
173 * Use either S16 or (planar) float for simplicity.
174 */
175 const retro_resampler_t *resampler;
176 void *resampler_data;
177
178 bool use_float;
179 bool is_planar;
180 unsigned sample_size;
181
182 float *float_conv;
183 size_t float_conv_frames;
184
185 float *resample_out;
186 size_t resample_out_frames;
187
188 int16_t *fixed_conv;
189 size_t fixed_conv_frames;
190
191 void *planar_buf;
192 size_t planar_buf_frames;
193
194 double ratio;
195 };
196
197 struct ff_muxer_info
198 {
199 AVFormatContext *ctx;
200 AVStream *astream;
201 AVStream *vstream;
202 };
203
204 struct ff_config_param
205 {
206 config_file_t *conf;
207 char vcodec[64];
208 char acodec[64];
209 char format[64];
210 enum PixelFormat out_pix_fmt;
211 unsigned threads;
212 unsigned frame_drop_ratio;
213 unsigned sample_rate;
214 float scale_factor;
215
216 bool audio_enable;
217 /* Keep same naming conventions as libavcodec. */
218 bool audio_qscale;
219 int audio_global_quality;
220 int audio_bit_rate;
221 bool video_qscale;
222 int video_global_quality;
223 int video_bit_rate;
224
225 AVDictionary *video_opts;
226 AVDictionary *audio_opts;
227 };
228
229 typedef struct ffmpeg
230 {
231 struct ff_video_info video;
232 struct ff_audio_info audio;
233 struct ff_muxer_info muxer;
234 struct ff_config_param config;
235
236 struct record_params params;
237
238 scond_t *cond;
239 slock_t *cond_lock;
240 slock_t *lock;
241 fifo_buffer_t *audio_fifo;
242 fifo_buffer_t *video_fifo;
243 fifo_buffer_t *attr_fifo;
244 sthread_t *thread;
245
246 volatile bool alive;
247 volatile bool can_sleep;
248 } ffmpeg_t;
249
250 AVFormatContext *ctx;
251
ffmpeg_codec_has_sample_format(enum AVSampleFormat fmt,const enum AVSampleFormat * fmts)252 static bool ffmpeg_codec_has_sample_format(enum AVSampleFormat fmt,
253 const enum AVSampleFormat *fmts)
254 {
255 unsigned i;
256
257 for (i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++)
258 if (fmt == fmts[i])
259 return true;
260 return false;
261 }
262
ffmpeg_audio_resolve_format(struct ff_audio_info * audio,const AVCodec * codec)263 static void ffmpeg_audio_resolve_format(struct ff_audio_info *audio,
264 const AVCodec *codec)
265 {
266 audio->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
267
268 if (ffmpeg_codec_has_sample_format(AV_SAMPLE_FMT_FLTP, codec->sample_fmts))
269 {
270 audio->codec->sample_fmt = AV_SAMPLE_FMT_FLTP;
271 audio->use_float = true;
272 audio->is_planar = true;
273 RARCH_LOG("[FFmpeg]: Using sample format FLTP.\n");
274 }
275 else if (ffmpeg_codec_has_sample_format(AV_SAMPLE_FMT_FLT, codec->sample_fmts))
276 {
277 audio->codec->sample_fmt = AV_SAMPLE_FMT_FLT;
278 audio->use_float = true;
279 audio->is_planar = false;
280 RARCH_LOG("[FFmpeg]: Using sample format FLT.\n");
281 }
282 else if (ffmpeg_codec_has_sample_format(AV_SAMPLE_FMT_S16P, codec->sample_fmts))
283 {
284 audio->codec->sample_fmt = AV_SAMPLE_FMT_S16P;
285 audio->use_float = false;
286 audio->is_planar = true;
287 RARCH_LOG("[FFmpeg]: Using sample format S16P.\n");
288 }
289 else if (ffmpeg_codec_has_sample_format(AV_SAMPLE_FMT_S16, codec->sample_fmts))
290 {
291 audio->codec->sample_fmt = AV_SAMPLE_FMT_S16;
292 audio->use_float = false;
293 audio->is_planar = false;
294 RARCH_LOG("[FFmpeg]: Using sample format S16.\n");
295 }
296 audio->sample_size = audio->use_float ? sizeof(float) : sizeof(int16_t);
297 }
298
ffmpeg_audio_resolve_sample_rate(ffmpeg_t * handle,const AVCodec * codec)299 static void ffmpeg_audio_resolve_sample_rate(ffmpeg_t *handle,
300 const AVCodec *codec)
301 {
302 struct ff_config_param *params = &handle->config;
303 struct record_params *param = &handle->params;
304
305 /* We'll have to force resampling to some supported sampling rate. */
306 if (codec->supported_samplerates && !params->sample_rate)
307 {
308 unsigned i;
309 int input_rate = (int)param->samplerate;
310
311 /* Favor closest sampling rate, but always prefer ratio > 1.0. */
312 int best_rate = codec->supported_samplerates[0];
313 int best_diff = best_rate - input_rate;
314
315 for (i = 1; codec->supported_samplerates[i]; i++)
316 {
317 bool better_rate = false;
318 int diff = codec->supported_samplerates[i] - input_rate;
319
320 if (best_diff < 0)
321 better_rate = (diff > best_diff);
322 else
323 better_rate = ((diff >= 0) && (diff < best_diff));
324
325 if (better_rate)
326 {
327 best_rate = codec->supported_samplerates[i];
328 best_diff = diff;
329 }
330 }
331
332 params->sample_rate = best_rate;
333 RARCH_LOG("[FFmpeg]: Using output sampling rate: %d.\n", best_rate);
334 }
335 }
336
ffmpeg_init_audio(ffmpeg_t * handle,const char * audio_resampler)337 static bool ffmpeg_init_audio(ffmpeg_t *handle, const char *audio_resampler)
338 {
339 struct ff_config_param *params = &handle->config;
340 struct ff_audio_info *audio = &handle->audio;
341 struct record_params *param = &handle->params;
342 AVCodec *codec = avcodec_find_encoder_by_name(
343 *params->acodec ? params->acodec : "flac");
344 if (!codec)
345 {
346 RARCH_ERR("[FFmpeg]: Cannot find acodec %s.\n",
347 *params->acodec ? params->acodec : "flac");
348 return false;
349 }
350
351 audio->encoder = codec;
352
353 audio->codec = avcodec_alloc_context3(codec);
354
355 audio->codec->codec_type = AVMEDIA_TYPE_AUDIO;
356 audio->codec->channels = param->channels;
357 audio->codec->channel_layout = (param->channels > 1)
358 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
359
360 ffmpeg_audio_resolve_format(audio, codec);
361 ffmpeg_audio_resolve_sample_rate(handle, codec);
362
363 if (params->sample_rate)
364 {
365 audio->ratio = (double)params->sample_rate
366 / param->samplerate;
367 audio->codec->sample_rate = params->sample_rate;
368 audio->codec->time_base = av_d2q(1.0 / params->sample_rate, 1000000);
369
370 retro_resampler_realloc(
371 &audio->resampler_data,
372 &audio->resampler,
373 audio_resampler,
374 RESAMPLER_QUALITY_DONTCARE,
375 audio->ratio);
376 }
377 else
378 {
379 audio->codec->sample_fmt = AV_SAMPLE_FMT_S16;
380 audio->codec->sample_rate = (int)roundf(param->samplerate);
381 audio->codec->time_base = av_d2q(1.0 / param->samplerate, 1000000);
382 }
383
384 if (params->audio_qscale)
385 {
386 audio->codec->flags |= AV_CODEC_FLAG_QSCALE;
387 audio->codec->global_quality = params->audio_global_quality;
388 }
389 else if (params->audio_bit_rate)
390 audio->codec->bit_rate = params->audio_bit_rate;
391
392 /* Allow experimental codecs. */
393 audio->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
394
395 if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER)
396 audio->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
397
398 if (avcodec_open2(audio->codec, codec,
399 params->audio_opts ? ¶ms->audio_opts : NULL) != 0)
400 return false;
401
402 /* If not set (PCM), just set something. */
403 if (!audio->codec->frame_size)
404 audio->codec->frame_size = 1024;
405
406 audio->buffer = (uint8_t*)av_malloc(
407 audio->codec->frame_size *
408 audio->codec->channels *
409 audio->sample_size);
410
411 #if 0
412 RARCH_LOG("[FFmpeg]: Audio frame size: %d.\n", audio->codec->frame_size);
413 #endif
414
415 if (!audio->buffer)
416 return false;
417
418 audio->outbuf_size = AV_INPUT_BUFFER_MIN_SIZE;
419 audio->outbuf = (uint8_t*)av_malloc(audio->outbuf_size);
420
421 if (!audio->outbuf)
422 return false;
423
424 return true;
425 }
426
ffmpeg_init_video(ffmpeg_t * handle)427 static bool ffmpeg_init_video(ffmpeg_t *handle)
428 {
429 size_t size;
430 struct ff_config_param *params = &handle->config;
431 struct ff_video_info *video = &handle->video;
432 struct record_params *param = &handle->params;
433 AVCodec *codec = NULL;
434
435 if (*params->vcodec)
436 codec = avcodec_find_encoder_by_name(params->vcodec);
437 else
438 {
439 /* By default, lossless video. */
440 av_dict_set(¶ms->video_opts, "qp", "0", 0);
441 codec = avcodec_find_encoder_by_name("libx264rgb");
442 }
443
444 if (!codec)
445 {
446 RARCH_ERR("[FFmpeg]: Cannot find vcodec %s.\n",
447 *params->vcodec ? params->vcodec : "libx264rgb");
448 return false;
449 }
450
451 video->encoder = codec;
452
453 /* Don't use swscaler unless format is not something "in-house" scaler
454 * supports.
455 *
456 * libswscale doesn't scale RGB -> RGB correctly (goes via YUV first),
457 * and it's non-trivial to fix upstream as it's heavily geared towards YUV.
458 * If we're dealing with strange formats or YUV, just use libswscale.
459 */
460 if (params->out_pix_fmt != PIX_FMT_NONE)
461 {
462 video->pix_fmt = params->out_pix_fmt;
463 if (video->pix_fmt != PIX_FMT_BGR24 && video->pix_fmt != PIX_FMT_RGB32)
464 video->use_sws = true;
465
466 switch (video->pix_fmt)
467 {
468 case PIX_FMT_BGR24:
469 video->scaler.out_fmt = SCALER_FMT_BGR24;
470 break;
471
472 case PIX_FMT_RGB32:
473 video->scaler.out_fmt = SCALER_FMT_ARGB8888;
474 break;
475
476 default:
477 break;
478 }
479 }
480 else /* Use BGR24 as default out format. */
481 {
482 video->pix_fmt = PIX_FMT_BGR24;
483 video->scaler.out_fmt = SCALER_FMT_BGR24;
484 }
485
486 switch (param->pix_fmt)
487 {
488 case FFEMU_PIX_RGB565:
489 video->scaler.in_fmt = SCALER_FMT_RGB565;
490 video->in_pix_fmt = PIX_FMT_RGB565;
491 video->pix_size = 2;
492 break;
493
494 case FFEMU_PIX_BGR24:
495 video->scaler.in_fmt = SCALER_FMT_BGR24;
496 video->in_pix_fmt = PIX_FMT_BGR24;
497 video->pix_size = 3;
498 break;
499
500 case FFEMU_PIX_ARGB8888:
501 video->scaler.in_fmt = SCALER_FMT_ARGB8888;
502 video->in_pix_fmt = PIX_FMT_RGB32;
503 video->pix_size = 4;
504 break;
505
506 default:
507 return false;
508 }
509
510 video->codec = avcodec_alloc_context3(codec);
511
512 /* Useful to set scale_factor to 2 for chroma subsampled formats to
513 * maintain full chroma resolution. (Or just use 4:4:4 or RGB ...)
514 */
515 param->out_width = (float)param->out_width * params->scale_factor;
516 param->out_height = (float)param->out_height * params->scale_factor;
517
518 video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
519 video->codec->width = param->out_width;
520 video->codec->height = param->out_height;
521 video->codec->time_base = av_d2q((double)
522 params->frame_drop_ratio /param->fps, 1000000); /* Arbitrary big number. */
523 video->codec->sample_aspect_ratio = av_d2q(
524 param->aspect_ratio * param->out_height / param->out_width, 255);
525 video->codec->pix_fmt = video->pix_fmt;
526
527 video->codec->thread_count = params->threads;
528
529 if (params->video_qscale)
530 {
531 video->codec->flags |= AV_CODEC_FLAG_QSCALE;
532 video->codec->global_quality = params->video_global_quality;
533 }
534 else if (params->video_bit_rate)
535 video->codec->bit_rate = params->video_bit_rate;
536
537 if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER)
538 video->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
539
540 if (avcodec_open2(video->codec, codec, params->video_opts ?
541 ¶ms->video_opts : NULL) != 0)
542 return false;
543
544 /* Allocate a big buffer. ffmpeg API doesn't seem to give us some
545 * clues how big this buffer should be. */
546 video->outbuf_size = 1 << 23;
547 video->outbuf = (uint8_t*)av_malloc(video->outbuf_size);
548
549 video->frame_drop_ratio = params->frame_drop_ratio;
550
551 size = avpicture_get_size(video->pix_fmt, param->out_width,
552 param->out_height);
553 video->conv_frame_buf = (uint8_t*)av_malloc(size);
554 video->conv_frame = av_frame_alloc();
555
556 avpicture_fill((AVPicture*)video->conv_frame, video->conv_frame_buf,
557 video->pix_fmt, param->out_width, param->out_height);
558
559 video->conv_frame->width = param->out_width;
560 video->conv_frame->height = param->out_height;
561 video->conv_frame->format = video->pix_fmt;
562
563 return true;
564 }
565
ffmpeg_init_config_common(struct ff_config_param * params,unsigned preset,bool video_gpu_record,unsigned video_record_scale_factor,unsigned video_stream_scale_factor,unsigned streaming_mode,unsigned video_record_threads)566 static bool ffmpeg_init_config_common(struct ff_config_param *params,
567 unsigned preset,
568 bool video_gpu_record,
569 unsigned video_record_scale_factor,
570 unsigned video_stream_scale_factor,
571 unsigned streaming_mode,
572 unsigned video_record_threads)
573 {
574 switch (preset)
575 {
576 case RECORD_CONFIG_TYPE_RECORDING_LOW_QUALITY:
577 case RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY:
578 params->threads = video_record_threads;
579 params->frame_drop_ratio = 1;
580 params->audio_enable = true;
581 params->audio_global_quality = 75;
582 params->out_pix_fmt = PIX_FMT_YUV420P;
583
584 strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
585 strlcpy(params->acodec, "aac", sizeof(params->acodec));
586
587 av_dict_set(¶ms->video_opts, "preset", "ultrafast", 0);
588 av_dict_set(¶ms->video_opts, "tune", "film", 0);
589 av_dict_set(¶ms->video_opts, "crf", "35", 0);
590 av_dict_set(¶ms->audio_opts, "audio_global_quality", "75", 0);
591 break;
592 case RECORD_CONFIG_TYPE_RECORDING_MED_QUALITY:
593 case RECORD_CONFIG_TYPE_STREAMING_MED_QUALITY:
594 params->threads = video_record_threads;
595 params->frame_drop_ratio = 1;
596 params->audio_enable = true;
597 params->audio_global_quality = 75;
598 params->out_pix_fmt = PIX_FMT_YUV420P;
599
600 strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
601 strlcpy(params->acodec, "aac", sizeof(params->acodec));
602
603 av_dict_set(¶ms->video_opts, "preset", "superfast", 0);
604 av_dict_set(¶ms->video_opts, "tune", "film", 0);
605 av_dict_set(¶ms->video_opts, "crf", "25", 0);
606 av_dict_set(¶ms->audio_opts, "audio_global_quality", "75", 0);
607 break;
608 case RECORD_CONFIG_TYPE_RECORDING_HIGH_QUALITY:
609 case RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY:
610 params->threads = video_record_threads;
611 params->frame_drop_ratio = 1;
612 params->audio_enable = true;
613 params->audio_global_quality = 100;
614 params->out_pix_fmt = PIX_FMT_YUV420P;
615
616 strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
617 strlcpy(params->acodec, "aac", sizeof(params->acodec));
618
619 av_dict_set(¶ms->video_opts, "preset", "superfast", 0);
620 av_dict_set(¶ms->video_opts, "tune", "film", 0);
621 av_dict_set(¶ms->video_opts, "crf", "15", 0);
622 av_dict_set(¶ms->audio_opts, "audio_global_quality", "100", 0);
623 break;
624 case RECORD_CONFIG_TYPE_RECORDING_LOSSLESS_QUALITY:
625 params->threads = video_record_threads;
626 params->frame_drop_ratio = 1;
627 params->audio_enable = true;
628 params->audio_global_quality = 80;
629 params->out_pix_fmt = PIX_FMT_BGR24;
630
631 strlcpy(params->vcodec, "libx264rgb", sizeof(params->vcodec));
632 strlcpy(params->acodec, "flac", sizeof(params->acodec));
633
634 av_dict_set(¶ms->video_opts, "qp", "0", 0);
635 av_dict_set(¶ms->audio_opts, "audio_global_quality", "100", 0);
636 break;
637 case RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST:
638 params->threads = video_record_threads;
639 params->frame_drop_ratio = 1;
640 params->audio_enable = true;
641 params->audio_global_quality = 50;
642 params->out_pix_fmt = PIX_FMT_YUV420P;
643
644 strlcpy(params->vcodec, "libvpx", sizeof(params->vcodec));
645 strlcpy(params->acodec, "libopus", sizeof(params->acodec));
646
647 av_dict_set(¶ms->video_opts, "deadline", "realtime", 0);
648 av_dict_set(¶ms->video_opts, "crf", "14", 0);
649 av_dict_set(¶ms->audio_opts, "audio_global_quality", "50", 0);
650 break;
651 case RECORD_CONFIG_TYPE_RECORDING_WEBM_HIGH_QUALITY:
652 params->threads = video_record_threads;
653 params->frame_drop_ratio = 1;
654 params->audio_enable = true;
655 params->audio_global_quality = 75;
656 params->out_pix_fmt = PIX_FMT_YUV420P;
657
658 strlcpy(params->vcodec, "libvpx", sizeof(params->vcodec));
659 strlcpy(params->acodec, "libopus", sizeof(params->acodec));
660
661 av_dict_set(¶ms->video_opts, "deadline", "realtime", 0);
662 av_dict_set(¶ms->video_opts, "crf", "4", 0);
663 av_dict_set(¶ms->audio_opts, "audio_global_quality", "75", 0);
664 break;
665 case RECORD_CONFIG_TYPE_RECORDING_GIF:
666 params->threads = video_record_threads;
667 params->frame_drop_ratio = 4;
668 params->audio_enable = false;
669 params->audio_global_quality = 0;
670 params->out_pix_fmt = PIX_FMT_RGB8;
671
672 strlcpy(params->vcodec, "gif", sizeof(params->vcodec));
673 strlcpy(params->acodec, "", sizeof(params->acodec));
674
675 av_dict_set(¶ms->video_opts, "framerate", "30", 0);
676 av_dict_set(¶ms->audio_opts, "audio_global_quality", "0", 0);
677 break;
678 case RECORD_CONFIG_TYPE_RECORDING_APNG:
679 params->threads = video_record_threads;
680 params->frame_drop_ratio = 1;
681 params->audio_enable = false;
682 params->audio_global_quality = 0;
683 params->out_pix_fmt = PIX_FMT_RGB24;
684
685 strlcpy(params->vcodec, "apng", sizeof(params->vcodec));
686 strlcpy(params->acodec, "", sizeof(params->acodec));
687
688 av_dict_set(¶ms->video_opts, "pred", "avg", 0);
689 av_dict_set(¶ms->audio_opts, "audio_global_quality", "0", 0);
690 break;
691 case RECORD_CONFIG_TYPE_STREAMING_NETPLAY:
692 params->threads = video_record_threads;
693 params->frame_drop_ratio = 1;
694 params->audio_enable = true;
695 params->audio_global_quality = 50;
696 params->out_pix_fmt = PIX_FMT_YUV420P;
697
698 strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
699 strlcpy(params->acodec, "aac", sizeof(params->acodec));
700
701 av_dict_set(¶ms->video_opts, "preset", "ultrafast", 0);
702 av_dict_set(¶ms->video_opts, "tune", "zerolatency", 0);
703 av_dict_set(¶ms->video_opts, "crf", "20", 0);
704 av_dict_set(¶ms->audio_opts, "audio_global_quality", "50", 0);
705
706 /* TO-DO: detect if hwaccel is available and use it instead of the preset above
707 strlcpy(params->vcodec, "h264_nvenc", sizeof(params->vcodec));
708 strlcpy(params->acodec, "aac", sizeof(params->acodec));
709
710 av_dict_set(¶ms->video_opts, "preset", "llhp", 0);
711 av_dict_set(¶ms->video_opts, "tune", "zerolatency", 0);
712 av_dict_set(¶ms->video_opts, "zerolatency", "1", 0);
713 av_dict_set(¶ms->video_opts, "-rc-lookahead", "0", 0);
714 av_dict_set(¶ms->video_opts, "x264-params", "threads=0:intra-refresh=1:b-frames=0", 0);
715 av_dict_set(¶ms->audio_opts, "audio_global_quality", "100", 0);
716 */
717
718 break;
719 default:
720 break;
721 }
722
723 if (preset <= RECORD_CONFIG_TYPE_RECORDING_LOSSLESS_QUALITY)
724 {
725 if (!video_gpu_record)
726 params->scale_factor = (video_record_scale_factor > 0) ?
727 video_record_scale_factor : 1;
728 else
729 params->scale_factor = 1;
730 strlcpy(params->format, "matroska", sizeof(params->format));
731 }
732 else if (preset >= RECORD_CONFIG_TYPE_RECORDING_WEBM_FAST && preset < RECORD_CONFIG_TYPE_RECORDING_GIF)
733 {
734 if (!video_gpu_record)
735 params->scale_factor = (video_record_scale_factor > 0) ?
736 video_record_scale_factor : 1;
737 else
738 params->scale_factor = 1;
739 strlcpy(params->format, "webm", sizeof(params->format));
740 }
741 else if (preset >= RECORD_CONFIG_TYPE_RECORDING_GIF && preset < RECORD_CONFIG_TYPE_RECORDING_APNG)
742 {
743 if (!video_gpu_record)
744 params->scale_factor = (video_record_scale_factor > 0) ?
745 video_record_scale_factor : 1;
746 else
747 params->scale_factor = 1;
748 strlcpy(params->format, "gif", sizeof(params->format));
749 }
750 else if (preset < RECORD_CONFIG_TYPE_STREAMING_LOW_QUALITY)
751 {
752 params->scale_factor = 1;
753 strlcpy(params->format, "apng", sizeof(params->format));
754 }
755 else if (preset <= RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY)
756 {
757 if (!video_gpu_record)
758 params->scale_factor = (video_stream_scale_factor > 0) ?
759 video_stream_scale_factor : 1;
760 else
761 params->scale_factor = 1;
762 if ( streaming_mode == STREAMING_MODE_YOUTUBE ||
763 streaming_mode == STREAMING_MODE_TWITCH ||
764 streaming_mode == STREAMING_MODE_FACEBOOK)
765 strlcpy(params->format, "flv", sizeof(params->format));
766 else
767 strlcpy(params->format, "mpegts", sizeof(params->format));
768 }
769 else if (preset == RECORD_CONFIG_TYPE_STREAMING_NETPLAY)
770 {
771 params->scale_factor = 1;
772 strlcpy(params->format, "mpegts", sizeof(params->format));
773 }
774
775 return true;
776 }
777
778 /*
779 static bool ffmpeg_init_config_recording(struct ff_config_param *params)
780 {
781 return true;
782 params->threads = 0;
783 params->audio_global_quality = 100;
784
785 strlcpy(params->vcodec, "libx264rgb", sizeof(params->vcodec));
786 strlcpy(params->format, "matroska", sizeof(params->format));
787
788 av_dict_set(¶ms->video_opts, "video_preset", "slow", 0);
789 av_dict_set(¶ms->video_opts, "video_tune", "film", 0);
790 av_dict_set(¶ms->video_opts, "video_crf", "10", 0);
791 av_dict_set(¶ms->audio_opts, "audio_global_quality", "100", 0);
792
793 return true;
794 }
795 */
796
ffmpeg_init_config(struct ff_config_param * params,const char * config)797 static bool ffmpeg_init_config(struct ff_config_param *params,
798 const char *config)
799 {
800 struct config_file_entry entry;
801 char pix_fmt[64] = {0};
802
803 params->out_pix_fmt = PIX_FMT_NONE;
804 params->scale_factor = 1;
805 params->threads = 1;
806 params->frame_drop_ratio = 1;
807 params->audio_enable = true;
808
809 if (!config)
810 return true;
811
812 RARCH_LOG("[FFmpeg] Loading FFmpeg config \"%s\".\n", config);
813
814 if (!(params->conf = config_file_new_from_path_to_string(config)))
815 {
816 RARCH_ERR("[FFmpeg] Failed to load FFmpeg config \"%s\".\n", config);
817 return false;
818 }
819
820 config_get_array(params->conf, "vcodec", params->vcodec,
821 sizeof(params->vcodec));
822 config_get_array(params->conf, "acodec", params->acodec,
823 sizeof(params->acodec));
824 config_get_array(params->conf, "format", params->format,
825 sizeof(params->format));
826
827 config_get_uint(params->conf, "threads", ¶ms->threads);
828
829 if (!config_get_uint(params->conf, "frame_drop_ratio",
830 ¶ms->frame_drop_ratio) || !params->frame_drop_ratio)
831 params->frame_drop_ratio = 1;
832
833 if (!config_get_bool(params->conf, "audio_enable", ¶ms->audio_enable))
834 params->audio_enable = true;
835
836 config_get_uint(params->conf, "sample_rate", ¶ms->sample_rate);
837 config_get_float(params->conf, "scale_factor", ¶ms->scale_factor);
838
839 params->audio_qscale = config_get_int(params->conf, "audio_global_quality",
840 ¶ms->audio_global_quality);
841 config_get_int(params->conf, "audio_bit_rate", ¶ms->audio_bit_rate);
842 params->video_qscale = config_get_int(params->conf, "video_global_quality",
843 ¶ms->video_global_quality);
844 config_get_int(params->conf, "video_bit_rate", ¶ms->video_bit_rate);
845
846 if (config_get_array(params->conf, "pix_fmt", pix_fmt, sizeof(pix_fmt)))
847 {
848 params->out_pix_fmt = av_get_pix_fmt(pix_fmt);
849 if (params->out_pix_fmt == PIX_FMT_NONE)
850 {
851 RARCH_ERR("[FFmpeg] Cannot find pix_fmt \"%s\".\n", pix_fmt);
852 return false;
853 }
854 }
855
856 if (!config_get_entry_list_head(params->conf, &entry))
857 return true;
858
859 do
860 {
861 if (strstr(entry.key, "video_") == entry.key)
862 {
863 const char *key = entry.key + STRLEN_CONST("video_");
864 av_dict_set(¶ms->video_opts, key, entry.value, 0);
865 }
866 else if (strstr(entry.key, "audio_") == entry.key)
867 {
868 const char *key = entry.key + STRLEN_CONST("audio_");
869 av_dict_set(¶ms->audio_opts, key, entry.value, 0);
870 }
871 } while (config_get_entry_list_next(&entry));
872
873 return true;
874 }
875
ffmpeg_init_muxer_pre(ffmpeg_t * handle)876 static bool ffmpeg_init_muxer_pre(ffmpeg_t *handle)
877 {
878 ctx = avformat_alloc_context();
879 av_strlcpy(ctx->filename, handle->params.filename, sizeof(ctx->filename));
880
881 if (*handle->config.format)
882 ctx->oformat = av_guess_format(handle->config.format, NULL, NULL);
883 else
884 ctx->oformat = av_guess_format(NULL, ctx->filename, NULL);
885
886 if (!ctx->oformat)
887 return false;
888
889 if (avio_open(&ctx->pb, ctx->filename, AVIO_FLAG_WRITE) < 0)
890 {
891 av_free(ctx);
892 return false;
893 }
894
895 handle->muxer.ctx = ctx;
896 return true;
897 }
898
ffmpeg_init_muxer_post(ffmpeg_t * handle)899 static bool ffmpeg_init_muxer_post(ffmpeg_t *handle)
900 {
901 AVStream *stream = avformat_new_stream(handle->muxer.ctx,
902 handle->video.encoder);
903
904 stream->codec = handle->video.codec;
905 stream->time_base = stream->codec->time_base;
906 handle->muxer.vstream = stream;
907 handle->muxer.vstream->sample_aspect_ratio =
908 handle->video.codec->sample_aspect_ratio;
909
910 if (handle->config.audio_enable)
911 {
912 stream = avformat_new_stream(handle->muxer.ctx,
913 handle->audio.encoder);
914 stream->codec = handle->audio.codec;
915 stream->time_base = stream->codec->time_base;
916 handle->muxer.astream = stream;
917 }
918
919 av_dict_set(&handle->muxer.ctx->metadata, "title",
920 "RetroArch Video Dump", 0);
921
922 return avformat_write_header(handle->muxer.ctx, NULL) >= 0;
923 }
924
925 #define MAX_FRAMES 32
926
927 static void ffmpeg_thread(void *data);
928
init_thread(ffmpeg_t * handle)929 static bool init_thread(ffmpeg_t *handle)
930 {
931 handle->lock = slock_new();
932 handle->cond_lock = slock_new();
933 handle->cond = scond_new();
934 handle->audio_fifo = fifo_new(32000 * sizeof(int16_t) *
935 handle->params.channels * MAX_FRAMES / 60); /* Some arbitrary max size. */
936 handle->attr_fifo = fifo_new(sizeof(struct record_video_data) * MAX_FRAMES);
937 handle->video_fifo = fifo_new(handle->params.fb_width * handle->params.fb_height *
938 handle->video.pix_size * MAX_FRAMES);
939
940 handle->alive = true;
941 handle->can_sleep = true;
942 handle->thread = sthread_create(ffmpeg_thread, handle);
943
944 retro_assert(handle->lock && handle->cond_lock &&
945 handle->cond && handle->audio_fifo &&
946 handle->attr_fifo && handle->video_fifo && handle->thread);
947
948 return true;
949 }
950
deinit_thread(ffmpeg_t * handle)951 static void deinit_thread(ffmpeg_t *handle)
952 {
953 if (!handle->thread)
954 return;
955
956 slock_lock(handle->cond_lock);
957 handle->alive = false;
958 handle->can_sleep = false;
959 slock_unlock(handle->cond_lock);
960
961 scond_signal(handle->cond);
962 sthread_join(handle->thread);
963
964 slock_free(handle->lock);
965 slock_free(handle->cond_lock);
966 scond_free(handle->cond);
967
968 handle->thread = NULL;
969 }
970
deinit_thread_buf(ffmpeg_t * handle)971 static void deinit_thread_buf(ffmpeg_t *handle)
972 {
973 if (handle->audio_fifo)
974 {
975 fifo_free(handle->audio_fifo);
976 handle->audio_fifo = NULL;
977 }
978
979 if (handle->attr_fifo)
980 {
981 fifo_free(handle->attr_fifo);
982 handle->attr_fifo = NULL;
983 }
984
985 if (handle->video_fifo)
986 {
987 fifo_free(handle->video_fifo);
988 handle->video_fifo = NULL;
989 }
990 }
991
ffmpeg_free(void * data)992 static void ffmpeg_free(void *data)
993 {
994 ffmpeg_t *handle = (ffmpeg_t*)data;
995 if (!handle)
996 return;
997
998 deinit_thread(handle);
999 deinit_thread_buf(handle);
1000
1001 if (handle->audio.codec)
1002 {
1003 avcodec_close(handle->audio.codec);
1004 av_free(handle->audio.codec);
1005 }
1006
1007 av_free(handle->audio.buffer);
1008
1009 if (handle->video.codec)
1010 {
1011 avcodec_close(handle->video.codec);
1012 av_free(handle->video.codec);
1013 }
1014
1015 av_frame_free(&handle->video.conv_frame);
1016 av_free(handle->video.conv_frame_buf);
1017
1018 scaler_ctx_gen_reset(&handle->video.scaler);
1019
1020 if (handle->video.sws)
1021 sws_freeContext(handle->video.sws);
1022
1023 if (handle->config.conf)
1024 config_file_free(handle->config.conf);
1025 if (handle->config.video_opts)
1026 av_dict_free(&handle->config.video_opts);
1027 if (handle->config.audio_opts)
1028 av_dict_free(&handle->config.audio_opts);
1029
1030 if (handle->audio.resampler && handle->audio.resampler_data)
1031 handle->audio.resampler->free(handle->audio.resampler_data);
1032 handle->audio.resampler = NULL;
1033 handle->audio.resampler_data = NULL;
1034
1035 av_free(handle->audio.float_conv);
1036 av_free(handle->audio.resample_out);
1037 av_free(handle->audio.fixed_conv);
1038 av_free(handle->audio.planar_buf);
1039
1040 free(handle);
1041 }
1042
ffmpeg_new(const struct record_params * params)1043 static void *ffmpeg_new(const struct record_params *params)
1044 {
1045 ffmpeg_t *handle = (ffmpeg_t*)calloc(1, sizeof(*handle));
1046 if (!handle)
1047 return NULL;
1048
1049 av_register_all();
1050 avformat_network_init();
1051
1052 handle->params = *params;
1053
1054 switch (params->preset)
1055 {
1056 case RECORD_CONFIG_TYPE_RECORDING_CUSTOM:
1057 case RECORD_CONFIG_TYPE_STREAMING_CUSTOM:
1058 if (!ffmpeg_init_config(
1059 &handle->config,
1060 params->config))
1061 goto error;
1062 break;
1063 default:
1064 ffmpeg_init_config_common(
1065 &handle->config,
1066 params->preset,
1067 params->video_gpu_record,
1068 params->video_record_scale_factor,
1069 params->video_stream_scale_factor,
1070 params->streaming_mode,
1071 params->video_record_threads
1072 );
1073 break;
1074 }
1075
1076 if (!ffmpeg_init_muxer_pre(handle))
1077 goto error;
1078
1079 if (!ffmpeg_init_video(handle))
1080 goto error;
1081
1082 if (handle->config.audio_enable &&
1083 !ffmpeg_init_audio(handle,
1084 params->audio_resampler))
1085 goto error;
1086
1087 if (!ffmpeg_init_muxer_post(handle))
1088 goto error;
1089
1090 if (!init_thread(handle))
1091 goto error;
1092
1093 return handle;
1094
1095 error:
1096 ffmpeg_free(handle);
1097 return NULL;
1098 }
1099
ffmpeg_push_video(void * data,const struct record_video_data * vid)1100 static bool ffmpeg_push_video(void *data,
1101 const struct record_video_data *vid)
1102 {
1103 unsigned y;
1104 struct record_video_data attr_data;
1105 bool drop_frame = false;
1106 ffmpeg_t *handle = (ffmpeg_t*)data;
1107 int offset = 0;
1108
1109 if (!handle || !vid)
1110 return false;
1111
1112 drop_frame = handle->video.frame_drop_count++ %
1113 handle->video.frame_drop_ratio;
1114
1115 handle->video.frame_drop_count %= handle->video.frame_drop_ratio;
1116
1117 if (drop_frame)
1118 return true;
1119
1120 for (;;)
1121 {
1122 unsigned avail;
1123
1124 slock_lock(handle->lock);
1125 avail = FIFO_WRITE_AVAIL(handle->attr_fifo);
1126 slock_unlock(handle->lock);
1127
1128 if (!handle->alive)
1129 return false;
1130
1131 if (avail >= sizeof(*vid))
1132 break;
1133
1134 slock_lock(handle->cond_lock);
1135 if (handle->can_sleep)
1136 {
1137 handle->can_sleep = false;
1138 scond_wait(handle->cond, handle->cond_lock);
1139 handle->can_sleep = true;
1140 }
1141 else
1142 scond_signal(handle->cond);
1143
1144 slock_unlock(handle->cond_lock);
1145 }
1146
1147 slock_lock(handle->lock);
1148
1149 /* Tightly pack our frame to conserve memory.
1150 * libretro tends to use a very large pitch.
1151 */
1152 attr_data = *vid;
1153
1154 if (attr_data.is_dupe)
1155 attr_data.width = attr_data.height = attr_data.pitch = 0;
1156 else
1157 attr_data.pitch = attr_data.width * handle->video.pix_size;
1158
1159 fifo_write(handle->attr_fifo, &attr_data, sizeof(attr_data));
1160
1161 for (y = 0; y < attr_data.height; y++, offset += vid->pitch)
1162 fifo_write(handle->video_fifo,
1163 (const uint8_t*)vid->data + offset, attr_data.pitch);
1164
1165 slock_unlock(handle->lock);
1166 scond_signal(handle->cond);
1167
1168 return true;
1169 }
1170
ffmpeg_push_audio(void * data,const struct record_audio_data * audio_data)1171 static bool ffmpeg_push_audio(void *data,
1172 const struct record_audio_data *audio_data)
1173 {
1174 ffmpeg_t *handle = (ffmpeg_t*)data;
1175
1176 if (!handle || !audio_data)
1177 return false;
1178
1179 if (!handle->config.audio_enable)
1180 return true;
1181
1182 for (;;)
1183 {
1184 unsigned avail;
1185
1186 slock_lock(handle->lock);
1187 avail = FIFO_WRITE_AVAIL(handle->audio_fifo);
1188 slock_unlock(handle->lock);
1189
1190 if (!handle->alive)
1191 return false;
1192
1193 if (avail >= audio_data->frames * handle->params.channels
1194 * sizeof(int16_t))
1195 break;
1196
1197 slock_lock(handle->cond_lock);
1198 if (handle->can_sleep)
1199 {
1200 handle->can_sleep = false;
1201 scond_wait(handle->cond, handle->cond_lock);
1202 handle->can_sleep = true;
1203 }
1204 else
1205 scond_signal(handle->cond);
1206
1207 slock_unlock(handle->cond_lock);
1208 }
1209
1210 slock_lock(handle->lock);
1211 fifo_write(handle->audio_fifo, audio_data->data,
1212 audio_data->frames * handle->params.channels * sizeof(int16_t));
1213 slock_unlock(handle->lock);
1214 scond_signal(handle->cond);
1215
1216 return true;
1217 }
1218
encode_video(ffmpeg_t * handle,AVFrame * frame)1219 static bool encode_video(ffmpeg_t *handle, AVFrame *frame)
1220 {
1221 AVPacket pkt;
1222 int ret;
1223
1224 av_init_packet(&pkt);
1225 pkt.data = handle->video.outbuf;
1226 pkt.size = handle->video.outbuf_size;
1227
1228 ret = avcodec_send_frame(handle->video.codec, frame);
1229 if (ret < 0)
1230 {
1231 #ifdef __cplusplus
1232 RARCH_ERR("[FFmpeg]: Cannot send video frame. Error code: %d.\n", ret);
1233 #else
1234 RARCH_ERR("[FFmpeg]: Cannot send video frame. Error code: %s.\n", av_err2str(ret));
1235 #endif
1236 return false;
1237 }
1238
1239 while (ret >= 0)
1240 {
1241 ret = avcodec_receive_packet(handle->video.codec, &pkt);
1242 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
1243 break;
1244 else if (ret < 0)
1245 {
1246 #ifdef __cplusplus
1247 RARCH_ERR("[FFmpeg]: Cannot receive video packet. Error code: %d.\n", ret);
1248 #else
1249 RARCH_ERR("[FFmpeg]: Cannot receive video packet. Error code: %s.\n", av_err2str(ret));
1250 #endif
1251 return false;
1252 }
1253
1254 pkt.pts = av_rescale_q(pkt.pts, handle->video.codec->time_base,
1255 handle->muxer.vstream->time_base);
1256
1257 pkt.dts = av_rescale_q(pkt.dts,
1258 handle->video.codec->time_base,
1259 handle->muxer.vstream->time_base);
1260
1261 pkt.stream_index = handle->muxer.vstream->index;
1262
1263 ret = av_interleaved_write_frame(handle->muxer.ctx, &pkt);
1264 if (ret < 0)
1265 {
1266 #ifdef __cplusplus
1267 RARCH_ERR("[FFmpeg]: Cannot write video packet to output file. Error code: %d.\n", ret);
1268 #else
1269 RARCH_ERR("[FFmpeg]: Cannot write video packet to output file. Error code: %s.\n", av_err2str(ret));
1270 #endif
1271 return false;
1272 }
1273 }
1274 return true;
1275 }
1276
ffmpeg_scale_input(ffmpeg_t * handle,const struct record_video_data * vid)1277 static void ffmpeg_scale_input(ffmpeg_t *handle,
1278 const struct record_video_data *vid)
1279 {
1280 /* Attempt to preserve more information if we scale down. */
1281 bool shrunk = handle->params.out_width < vid->width
1282 || handle->params.out_height < vid->height;
1283
1284 if (handle->video.use_sws)
1285 {
1286 int linesize = vid->pitch;
1287
1288 handle->video.sws = sws_getCachedContext(handle->video.sws,
1289 vid->width, vid->height, handle->video.in_pix_fmt,
1290 handle->params.out_width, handle->params.out_height,
1291 handle->video.pix_fmt,
1292 shrunk ? SWS_BILINEAR : SWS_POINT, NULL, NULL, NULL);
1293
1294 sws_scale(handle->video.sws, (const uint8_t* const*)&vid->data,
1295 &linesize, 0, vid->height, handle->video.conv_frame->data,
1296 handle->video.conv_frame->linesize);
1297 }
1298 else
1299 video_frame_record_scale(
1300 &handle->video.scaler,
1301 handle->video.conv_frame->data[0],
1302 vid->data,
1303 handle->params.out_width,
1304 handle->params.out_height,
1305 handle->video.conv_frame->linesize[0],
1306 vid->width,
1307 vid->height,
1308 vid->pitch,
1309 shrunk);
1310 }
1311
ffmpeg_push_video_thread(ffmpeg_t * handle,const struct record_video_data * vid)1312 static bool ffmpeg_push_video_thread(ffmpeg_t *handle,
1313 const struct record_video_data *vid)
1314 {
1315 if (!vid->is_dupe)
1316 ffmpeg_scale_input(handle, vid);
1317
1318 handle->video.conv_frame->pts = handle->video.frame_cnt;
1319
1320 if (!encode_video(handle, handle->video.conv_frame))
1321 return false;
1322
1323 handle->video.frame_cnt++;
1324 return true;
1325 }
1326
planarize_float(float * out,const float * in,size_t frames)1327 static void planarize_float(float *out, const float *in, size_t frames)
1328 {
1329 size_t i;
1330
1331 for (i = 0; i < frames; i++)
1332 {
1333 out[i] = in[2 * i + 0];
1334 out[i + frames] = in[2 * i + 1];
1335 }
1336 }
1337
planarize_s16(int16_t * out,const int16_t * in,size_t frames)1338 static void planarize_s16(int16_t *out, const int16_t *in, size_t frames)
1339 {
1340 size_t i;
1341
1342 for (i = 0; i < frames; i++)
1343 {
1344 out[i] = in[2 * i + 0];
1345 out[i + frames] = in[2 * i + 1];
1346 }
1347 }
1348
planarize_audio(ffmpeg_t * handle)1349 static void planarize_audio(ffmpeg_t *handle)
1350 {
1351 if (!handle->audio.is_planar)
1352 return;
1353
1354 if (handle->audio.frames_in_buffer > handle->audio.planar_buf_frames)
1355 {
1356 handle->audio.planar_buf = av_realloc(handle->audio.planar_buf,
1357 handle->audio.frames_in_buffer * handle->params.channels *
1358 handle->audio.sample_size);
1359 if (!handle->audio.planar_buf)
1360 return;
1361
1362 handle->audio.planar_buf_frames = handle->audio.frames_in_buffer;
1363 }
1364
1365 if (handle->audio.use_float)
1366 planarize_float((float*)handle->audio.planar_buf,
1367 (const float*)handle->audio.buffer,
1368 handle->audio.frames_in_buffer);
1369 else
1370 planarize_s16((int16_t*)handle->audio.planar_buf,
1371 (const int16_t*)handle->audio.buffer,
1372 handle->audio.frames_in_buffer);
1373 }
1374
encode_audio(ffmpeg_t * handle,bool dry)1375 static bool encode_audio(ffmpeg_t *handle, bool dry)
1376 {
1377 AVFrame *frame;
1378 AVPacket pkt;
1379 int samples_size;
1380 int ret;
1381
1382 av_init_packet(&pkt);
1383
1384 pkt.data = handle->audio.outbuf;
1385 pkt.size = handle->audio.outbuf_size;
1386
1387 frame = av_frame_alloc();
1388
1389 if (!frame)
1390 return false;
1391
1392 frame->nb_samples = handle->audio.frames_in_buffer;
1393 frame->format = handle->audio.codec->sample_fmt;
1394 frame->channel_layout = handle->audio.codec->channel_layout;
1395 frame->pts = handle->audio.frame_cnt;
1396
1397 planarize_audio(handle);
1398
1399 samples_size = av_samples_get_buffer_size(
1400 NULL,
1401 handle->audio.codec->channels,
1402 handle->audio.frames_in_buffer,
1403 handle->audio.codec->sample_fmt, 0);
1404
1405 avcodec_fill_audio_frame(frame,
1406 handle->audio.codec->channels,
1407 handle->audio.codec->sample_fmt,
1408 handle->audio.is_planar
1409 ? (uint8_t*)handle->audio.planar_buf :
1410 handle->audio.buffer,
1411 samples_size, 0);
1412
1413 ret = avcodec_send_frame(handle->audio.codec, dry ? NULL : frame);
1414 if (ret < 0)
1415 {
1416 av_frame_free(&frame);
1417 #ifdef __cplusplus
1418 RARCH_ERR("[FFmpeg]: Cannot send audio frame. Return code: %d.\n", ret);
1419 #else
1420 RARCH_ERR("[FFmpeg]: Cannot send audio frame. Return code: %s.\n", av_err2str(ret));
1421 #endif
1422 return false;
1423 }
1424
1425 while (ret >= 0)
1426 {
1427 ret = avcodec_receive_packet(handle->audio.codec, &pkt);
1428 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
1429 break;
1430 else if (ret < 0)
1431 {
1432 av_frame_free(&frame);
1433 #ifdef __cplusplus
1434 RARCH_ERR("[FFmpeg]: Cannot receive audio packet. Return code: %d.\n", ret);
1435 #else
1436 RARCH_ERR("[FFmpeg]: Cannot receive audio packet. Return code: %s.\n", av_err2str(ret));
1437 #endif
1438 return false;
1439 }
1440
1441 pkt.pts = av_rescale_q(pkt.pts,
1442 handle->audio.codec->time_base,
1443 handle->muxer.astream->time_base);
1444
1445 pkt.dts = av_rescale_q(pkt.dts,
1446 handle->audio.codec->time_base,
1447 handle->muxer.astream->time_base);
1448
1449 pkt.stream_index = handle->muxer.astream->index;
1450
1451 ret = av_interleaved_write_frame(handle->muxer.ctx, &pkt);
1452 if (ret < 0)
1453 {
1454 av_frame_free(&frame);
1455 #ifdef __cplusplus
1456 RARCH_ERR("[FFmpeg]: Cannot write video packet to output file. Error code: %d.\n", ret);
1457 #else
1458 RARCH_ERR("[FFmpeg]: Cannot write video packet to output file. Error code: %s.\n", av_err2str(ret));
1459 #endif
1460 return false;
1461 }
1462 }
1463
1464 av_frame_free(&frame);
1465 return true;
1466 }
1467
ffmpeg_audio_resample(ffmpeg_t * handle,struct record_audio_data * aud)1468 static void ffmpeg_audio_resample(ffmpeg_t *handle,
1469 struct record_audio_data *aud)
1470 {
1471 if (!handle->audio.use_float && !handle->audio.resampler)
1472 return;
1473
1474 if (aud->frames > handle->audio.float_conv_frames)
1475 {
1476 handle->audio.float_conv = (float*)av_realloc(handle->audio.float_conv,
1477 aud->frames * handle->params.channels * sizeof(float));
1478 if (!handle->audio.float_conv)
1479 return;
1480
1481 handle->audio.float_conv_frames = aud->frames;
1482 /* To make sure we don't accidentially overflow. */
1483 handle->audio.resample_out_frames = aud->frames
1484 * handle->audio.ratio + 16;
1485 handle->audio.resample_out = (float*)
1486 av_realloc(handle->audio.resample_out,
1487 handle->audio.resample_out_frames *
1488 handle->params.channels * sizeof(float));
1489 if (!handle->audio.resample_out)
1490 return;
1491
1492 handle->audio.fixed_conv_frames = MAX(
1493 handle->audio.resample_out_frames,
1494 handle->audio.float_conv_frames);
1495 handle->audio.fixed_conv = (int16_t*)av_realloc(
1496 handle->audio.fixed_conv,
1497 handle->audio.fixed_conv_frames *
1498 handle->params.channels * sizeof(int16_t));
1499
1500 if (!handle->audio.fixed_conv)
1501 return;
1502 }
1503
1504 if (handle->audio.use_float || handle->audio.resampler)
1505 {
1506 convert_s16_to_float(handle->audio.float_conv,
1507 (const int16_t*)aud->data, aud->frames
1508 * handle->params.channels, 1.0);
1509 aud->data = handle->audio.float_conv;
1510 }
1511
1512 if (handle->audio.resampler)
1513 {
1514 /* It's always two channels ... */
1515 struct resampler_data info = {0};
1516
1517 info.data_in = (const float*)aud->data;
1518 info.data_out = handle->audio.resample_out;
1519 info.input_frames = aud->frames;
1520 info.ratio = handle->audio.ratio;
1521
1522 handle->audio.resampler->process(handle->audio.resampler_data, &info);
1523
1524 aud->data = handle->audio.resample_out;
1525 aud->frames = info.output_frames;
1526
1527 if (!handle->audio.use_float)
1528 {
1529 convert_float_to_s16(handle->audio.fixed_conv,
1530 handle->audio.resample_out,
1531 aud->frames * handle->params.channels);
1532 aud->data = handle->audio.fixed_conv;
1533 }
1534 }
1535 }
1536
ffmpeg_push_audio_thread(ffmpeg_t * handle,struct record_audio_data * aud,bool require_block)1537 static bool ffmpeg_push_audio_thread(ffmpeg_t *handle,
1538 struct record_audio_data *aud, bool require_block)
1539 {
1540 size_t written_frames = 0;
1541
1542 ffmpeg_audio_resample(handle, aud);
1543
1544 while (written_frames < aud->frames)
1545 {
1546 size_t can_write = handle->audio.codec->frame_size -
1547 handle->audio.frames_in_buffer;
1548 size_t write_left = aud->frames - written_frames;
1549 size_t write_frames = write_left > can_write ? can_write : write_left;
1550 size_t write_size = write_frames *
1551 handle->params.channels * handle->audio.sample_size;
1552 size_t bytes_in_buffer = handle->audio.frames_in_buffer *
1553 handle->params.channels * handle->audio.sample_size;
1554 size_t written_bytes = written_frames *
1555 handle->params.channels * handle->audio.sample_size;
1556
1557 if (handle->audio.buffer)
1558 memcpy(handle->audio.buffer + bytes_in_buffer,
1559 (const uint8_t*)aud->data + written_bytes,
1560 write_size);
1561
1562 written_frames += write_frames;
1563 handle->audio.frames_in_buffer += write_frames;
1564
1565 if ((handle->audio.frames_in_buffer
1566 < (size_t)handle->audio.codec->frame_size)
1567 && require_block)
1568 break;
1569
1570 if (!encode_audio(handle, false))
1571 return false;
1572
1573 handle->audio.frame_cnt += handle->audio.frames_in_buffer;
1574 handle->audio.frames_in_buffer = 0;
1575 }
1576 return true;
1577 }
1578
ffmpeg_flush_audio(ffmpeg_t * handle,void * audio_buf,size_t audio_buf_size)1579 static void ffmpeg_flush_audio(ffmpeg_t *handle, void *audio_buf,
1580 size_t audio_buf_size)
1581 {
1582 size_t avail = FIFO_READ_AVAIL(handle->audio_fifo);
1583
1584 if (avail)
1585 {
1586 struct record_audio_data aud = {0};
1587
1588 fifo_read(handle->audio_fifo, audio_buf, avail);
1589
1590 aud.frames = avail / (sizeof(int16_t) * handle->params.channels);
1591 aud.data = audio_buf;
1592
1593 ffmpeg_push_audio_thread(handle, &aud, false);
1594 }
1595
1596 encode_audio(handle, true);
1597 }
1598
ffmpeg_flush_video(ffmpeg_t * handle)1599 static void ffmpeg_flush_video(ffmpeg_t *handle)
1600 {
1601 encode_video(handle, NULL);
1602
1603 }
1604
ffmpeg_flush_buffers(ffmpeg_t * handle)1605 static void ffmpeg_flush_buffers(ffmpeg_t *handle)
1606 {
1607 void *audio_buf = NULL;
1608 bool did_work = false;
1609 void *video_buf = av_malloc(2 * handle->params.fb_width *
1610 handle->params.fb_height * handle->video.pix_size);
1611 size_t audio_buf_size = handle->config.audio_enable ?
1612 (handle->audio.codec->frame_size *
1613 handle->params.channels * sizeof(int16_t)) : 0;
1614
1615 if (audio_buf_size)
1616 audio_buf = av_malloc(audio_buf_size);
1617 /* Try pushing data in an interleaving pattern to
1618 * ease the work of the muxer a bit. */
1619
1620 do
1621 {
1622 struct record_video_data attr_buf;
1623
1624 did_work = false;
1625
1626 if (handle->config.audio_enable)
1627 {
1628 if (FIFO_READ_AVAIL(handle->audio_fifo) >= audio_buf_size)
1629 {
1630 struct record_audio_data aud = {0};
1631
1632 fifo_read(handle->audio_fifo, audio_buf, audio_buf_size);
1633 aud.frames = handle->audio.codec->frame_size;
1634 aud.data = audio_buf;
1635 ffmpeg_push_audio_thread(handle, &aud, true);
1636
1637 did_work = true;
1638 }
1639 }
1640
1641 if (FIFO_READ_AVAIL(handle->attr_fifo) >= sizeof(attr_buf))
1642 {
1643 fifo_read(handle->attr_fifo, &attr_buf, sizeof(attr_buf));
1644 fifo_read(handle->video_fifo, video_buf,
1645 attr_buf.height * attr_buf.pitch);
1646 attr_buf.data = video_buf;
1647 ffmpeg_push_video_thread(handle, &attr_buf);
1648
1649 did_work = true;
1650 }
1651 }while (did_work);
1652
1653 /* Flush out last audio. */
1654 if (handle->config.audio_enable)
1655 ffmpeg_flush_audio(handle, audio_buf, audio_buf_size);
1656
1657 /* Flush out last video. */
1658 ffmpeg_flush_video(handle);
1659
1660 av_free(video_buf);
1661 av_free(audio_buf);
1662 }
1663
ffmpeg_finalize(void * data)1664 static bool ffmpeg_finalize(void *data)
1665 {
1666 ffmpeg_t *handle = (ffmpeg_t*)data;
1667 if (!handle)
1668 return false;
1669
1670 deinit_thread(handle);
1671
1672 /* Flush out data still in buffers (internal, and FFmpeg internal). */
1673 ffmpeg_flush_buffers(handle);
1674
1675 deinit_thread_buf(handle);
1676
1677 /* Write final data. */
1678 av_write_trailer(handle->muxer.ctx);
1679
1680 avio_close(ctx->pb);
1681
1682 return true;
1683 }
1684
ffmpeg_thread(void * data)1685 static void ffmpeg_thread(void *data)
1686 {
1687 size_t audio_buf_size;
1688 void *audio_buf = NULL;
1689 ffmpeg_t *ff = (ffmpeg_t*)data;
1690 /* For some reason, FFmpeg has a tendency to crash
1691 * if we don't overallocate a bit. */
1692 void *video_buf = av_malloc(2 * ff->params.fb_width *
1693 ff->params.fb_height * ff->video.pix_size);
1694
1695 retro_assert(video_buf);
1696
1697 audio_buf_size = ff->config.audio_enable ?
1698 (ff->audio.codec->frame_size * ff->params.channels * sizeof(int16_t)) : 0;
1699 audio_buf = audio_buf_size ? av_malloc(audio_buf_size) : NULL;
1700
1701 while (ff->alive)
1702 {
1703 struct record_video_data attr_buf;
1704
1705 bool avail_video = false;
1706 bool avail_audio = false;
1707
1708 slock_lock(ff->lock);
1709 if (FIFO_READ_AVAIL(ff->attr_fifo) >= sizeof(attr_buf))
1710 avail_video = true;
1711
1712 if (ff->config.audio_enable)
1713 if (FIFO_READ_AVAIL(ff->audio_fifo) >= audio_buf_size)
1714 avail_audio = true;
1715 slock_unlock(ff->lock);
1716
1717 if (!avail_video && !avail_audio)
1718 {
1719 slock_lock(ff->cond_lock);
1720 if (ff->can_sleep)
1721 {
1722 ff->can_sleep = false;
1723 scond_wait(ff->cond, ff->cond_lock);
1724 ff->can_sleep = true;
1725 }
1726 else
1727 scond_signal(ff->cond);
1728
1729 slock_unlock(ff->cond_lock);
1730 }
1731
1732 if (avail_video && video_buf)
1733 {
1734 slock_lock(ff->lock);
1735 fifo_read(ff->attr_fifo, &attr_buf, sizeof(attr_buf));
1736 fifo_read(ff->video_fifo, video_buf,
1737 attr_buf.height * attr_buf.pitch);
1738 slock_unlock(ff->lock);
1739 scond_signal(ff->cond);
1740
1741 attr_buf.data = video_buf;
1742 ffmpeg_push_video_thread(ff, &attr_buf);
1743 }
1744
1745 if (avail_audio && audio_buf)
1746 {
1747 struct record_audio_data aud = {0};
1748
1749 slock_lock(ff->lock);
1750 fifo_read(ff->audio_fifo, audio_buf, audio_buf_size);
1751 slock_unlock(ff->lock);
1752 scond_signal(ff->cond);
1753
1754 aud.frames = ff->audio.codec->frame_size;
1755 aud.data = audio_buf;
1756
1757 ffmpeg_push_audio_thread(ff, &aud, true);
1758 }
1759 }
1760
1761 av_free(video_buf);
1762 av_free(audio_buf);
1763 }
1764
1765 const record_driver_t record_ffmpeg = {
1766 ffmpeg_new,
1767 ffmpeg_free,
1768 ffmpeg_push_video,
1769 ffmpeg_push_audio,
1770 ffmpeg_finalize,
1771 "ffmpeg",
1772 };
1773