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 ? &params->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(&params->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             &params->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(&params->video_opts, "preset", "ultrafast", 0);
588          av_dict_set(&params->video_opts, "tune", "film", 0);
589          av_dict_set(&params->video_opts, "crf", "35", 0);
590          av_dict_set(&params->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(&params->video_opts, "preset", "superfast", 0);
604          av_dict_set(&params->video_opts, "tune", "film", 0);
605          av_dict_set(&params->video_opts, "crf", "25", 0);
606          av_dict_set(&params->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(&params->video_opts, "preset", "superfast", 0);
620          av_dict_set(&params->video_opts, "tune", "film", 0);
621          av_dict_set(&params->video_opts, "crf", "15", 0);
622          av_dict_set(&params->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(&params->video_opts, "qp", "0", 0);
635          av_dict_set(&params->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(&params->video_opts, "deadline", "realtime", 0);
648          av_dict_set(&params->video_opts, "crf", "14", 0);
649          av_dict_set(&params->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(&params->video_opts, "deadline", "realtime", 0);
662          av_dict_set(&params->video_opts, "crf", "4", 0);
663          av_dict_set(&params->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(&params->video_opts, "framerate", "30", 0);
676          av_dict_set(&params->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(&params->video_opts, "pred", "avg", 0);
689          av_dict_set(&params->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(&params->video_opts, "preset", "ultrafast", 0);
702          av_dict_set(&params->video_opts, "tune", "zerolatency", 0);
703          av_dict_set(&params->video_opts, "crf", "20", 0);
704          av_dict_set(&params->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(&params->video_opts, "preset", "llhp", 0);
711          av_dict_set(&params->video_opts, "tune", "zerolatency", 0);
712          av_dict_set(&params->video_opts, "zerolatency", "1", 0);
713          av_dict_set(&params->video_opts, "-rc-lookahead", "0", 0);
714          av_dict_set(&params->video_opts, "x264-params", "threads=0:intra-refresh=1:b-frames=0", 0);
715          av_dict_set(&params->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(&params->video_opts, "video_preset", "slow", 0);
789    av_dict_set(&params->video_opts, "video_tune", "film", 0);
790    av_dict_set(&params->video_opts, "video_crf", "10", 0);
791    av_dict_set(&params->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", &params->threads);
828 
829    if (!config_get_uint(params->conf, "frame_drop_ratio",
830             &params->frame_drop_ratio) || !params->frame_drop_ratio)
831       params->frame_drop_ratio = 1;
832 
833    if (!config_get_bool(params->conf, "audio_enable", &params->audio_enable))
834       params->audio_enable = true;
835 
836    config_get_uint(params->conf, "sample_rate", &params->sample_rate);
837    config_get_float(params->conf, "scale_factor", &params->scale_factor);
838 
839    params->audio_qscale = config_get_int(params->conf, "audio_global_quality",
840          &params->audio_global_quality);
841    config_get_int(params->conf, "audio_bit_rate", &params->audio_bit_rate);
842    params->video_qscale = config_get_int(params->conf, "video_global_quality",
843          &params->video_global_quality);
844    config_get_int(params->conf, "video_bit_rate", &params->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(&params->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(&params->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