Remove some FFmpeg-related warnings by using AVStream::codecpar.
[dcpomatic.git] / src / lib / ffmpeg_file_encoder.cc
index 05b6b7fe51aaee8923b5deda1124b3e4d9a994d6..18b90e0b599b54cb6d1b13d866d45387122d11c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2017-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -18,6 +18,7 @@
 
 */
 
+
 #include "ffmpeg_encoder.h"
 #include "film.h"
 #include "job.h"
 
 #include "i18n.h"
 
-using std::string;
-using std::runtime_error;
+
 using std::cout;
+using std::make_shared;
 using std::pair;
-using boost::shared_ptr;
+using std::runtime_error;
+using std::shared_ptr;
+using std::string;
+using std::weak_ptr;
 using boost::bind;
-using boost::weak_ptr;
 using boost::optional;
 using namespace dcpomatic;
 #if BOOST_VERSION >= 106100
 using namespace boost::placeholders;
 #endif
 
+
 int FFmpegFileEncoder::_video_stream_index = 0;
 int FFmpegFileEncoder::_audio_stream_index_base = 1;
 
 
-class ExportAudioStream : public boost::noncopyable
+class ExportAudioStream
 {
 public:
        ExportAudioStream (string codec_name, int channels, int frame_rate, AVSampleFormat sample_format, AVFormatContext* format_context, int stream_index)
@@ -80,6 +84,7 @@ public:
                }
 
                _stream->id = stream_index;
+               _stream->disposition |= AV_DISPOSITION_DEFAULT;
 DCPOMATIC_DISABLE_WARNINGS
                _stream->codec = _codec_context;
 DCPOMATIC_ENABLE_WARNINGS
@@ -97,6 +102,9 @@ DCPOMATIC_ENABLE_WARNINGS
                avcodec_close (_codec_context);
        }
 
+       ExportAudioStream (ExportAudioStream const&) = delete;
+       ExportAudioStream& operator= (ExportAudioStream const&) = delete;
+
        int frame_size () const {
                return _codec_context->frame_size;
        }
@@ -127,13 +135,13 @@ DCPOMATIC_ENABLE_WARNINGS
        {
                DCPOMATIC_ASSERT (size);
 
-               AVFrame* frame = av_frame_alloc ();
+               auto frame = av_frame_alloc ();
                DCPOMATIC_ASSERT (frame);
 
                int const buffer_size = av_samples_get_buffer_size (0, channels, size, _codec_context->sample_fmt, 0);
                DCPOMATIC_ASSERT (buffer_size >= 0);
 
-               void* samples = av_malloc (buffer_size);
+               auto samples = av_malloc (buffer_size);
                DCPOMATIC_ASSERT (samples);
 
                frame->nb_samples = size;
@@ -217,37 +225,31 @@ FFmpegFileEncoder::FFmpegFileEncoder (
        bool audio_stream_per_channel,
        int x264_crf,
        boost::filesystem::path output
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-       , optional<dcp::Key> key
-       , optional<string> id
-#endif
        )
        : _audio_stream_per_channel (audio_stream_per_channel)
-       , _video_options (0)
        , _audio_channels (channels)
        , _output (output)
        , _video_frame_size (video_frame_size)
        , _video_frame_rate (video_frame_rate)
        , _audio_frame_rate (audio_frame_rate)
-       , _audio_frames (0)
 {
        _pixel_format = pixel_format (format);
 
        switch (format) {
-       case EXPORT_FORMAT_PRORES:
+       case ExportFormat::PRORES:
                _sample_format = AV_SAMPLE_FMT_S16;
                _video_codec_name = "prores_ks";
                _audio_codec_name = "pcm_s16le";
                av_dict_set (&_video_options, "profile", "3", 0);
                av_dict_set (&_video_options, "threads", "auto", 0);
                break;
-       case EXPORT_FORMAT_H264_AAC:
+       case ExportFormat::H264_AAC:
                _sample_format = AV_SAMPLE_FMT_FLTP;
                _video_codec_name = "libx264";
                _audio_codec_name = "aac";
                av_dict_set_int (&_video_options, "crf", x264_crf, 0);
                break;
-       case EXPORT_FORMAT_H264_PCM:
+       case ExportFormat::H264_PCM:
                _sample_format = AV_SAMPLE_FMT_S32;
                _video_codec_name = "libx264";
                _audio_codec_name = "pcm_s24le";
@@ -257,11 +259,7 @@ FFmpegFileEncoder::FFmpegFileEncoder (
                DCPOMATIC_ASSERT (false);
        }
 
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-       int r = avformat_alloc_output_context2 (&_format_context, av_guess_format("mov", 0, 0), 0, 0);
-#else
        int r = avformat_alloc_output_context2 (&_format_context, 0, 0, _output.string().c_str());
-#endif
        if (!_format_context) {
                throw runtime_error (String::compose("could not allocate FFmpeg format context (%1)", r));
        }
@@ -274,22 +272,7 @@ FFmpegFileEncoder::FFmpegFileEncoder (
                throw runtime_error (String::compose("could not open FFmpeg output file %1 (%2)", _output.string(), r));
        }
 
-       AVDictionary* options = 0;
-
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-       if (key) {
-               av_dict_set (&options, "encryption_key", key->hex().c_str(), 0);
-               /* XXX: is this OK? */
-               av_dict_set (&options, "encryption_kid", "00000000000000000000000000000000", 0);
-               av_dict_set (&options, "encryption_scheme", "cenc-aes-ctr", 0);
-       }
-
-       if (id) {
-               if (av_dict_set(&_format_context->metadata, SWAROOP_ID_TAG, id->c_str(), 0) < 0) {
-                       throw runtime_error ("Could not write ID to output");
-               }
-       }
-#endif
+       AVDictionary* options = nullptr;
 
        if (avformat_write_header (_format_context, &options) < 0) {
                throw runtime_error ("could not write header to FFmpeg output file");
@@ -311,10 +294,10 @@ AVPixelFormat
 FFmpegFileEncoder::pixel_format (ExportFormat format)
 {
        switch (format) {
-       case EXPORT_FORMAT_PRORES:
+       case ExportFormat::PRORES:
                return AV_PIX_FMT_YUV422P10;
-       case EXPORT_FORMAT_H264_AAC:
-       case EXPORT_FORMAT_H264_PCM:
+       case ExportFormat::H264_AAC:
+       case ExportFormat::H264_PCM:
                return AV_PIX_FMT_YUV420P;
        default:
                DCPOMATIC_ASSERT (false);
@@ -323,6 +306,7 @@ FFmpegFileEncoder::pixel_format (ExportFormat format)
        return AV_PIX_FMT_YUV422P10;
 }
 
+
 void
 FFmpegFileEncoder::setup_video ()
 {
@@ -351,8 +335,8 @@ FFmpegFileEncoder::setup_video ()
                throw runtime_error ("could not create FFmpeg output video stream");
        }
 
-DCPOMATIC_DISABLE_WARNINGS
        _video_stream->id = _video_stream_index;
+DCPOMATIC_DISABLE_WARNINGS
        _video_stream->codec = _video_codec_context;
 DCPOMATIC_ENABLE_WARNINGS
 
@@ -370,8 +354,8 @@ FFmpegFileEncoder::setup_audio ()
 
        for (int i = 0; i < streams; ++i) {
                _audio_streams.push_back(
-                       shared_ptr<ExportAudioStream>(
-                               new ExportAudioStream(_audio_codec_name, channels_per_stream, _audio_frame_rate, _sample_format, _format_context, _audio_stream_index_base + i)
+                       make_shared<ExportAudioStream>(
+                               _audio_codec_name, channels_per_stream, _audio_frame_rate, _sample_format, _format_context, _audio_stream_index_base + i
                                )
                        );
        }
@@ -407,7 +391,7 @@ DCPOMATIC_ENABLE_WARNINGS
                av_packet_unref (&packet);
 
                flushed_audio = true;
-               BOOST_FOREACH (shared_ptr<ExportAudioStream> i, _audio_streams) {
+               for (auto i: _audio_streams) {
                        if (!i->flush()) {
                                flushed_audio = false;
                        }
@@ -417,18 +401,19 @@ DCPOMATIC_ENABLE_WARNINGS
        av_write_trailer (_format_context);
 }
 
+
 void
 FFmpegFileEncoder::video (shared_ptr<PlayerVideo> video, DCPTime time)
 {
        /* All our output formats are video range at the moment */
-       shared_ptr<Image> image = video->image (
+       auto image = video->image (
                bind (&PlayerVideo::force, _1, _pixel_format),
-               VIDEO_RANGE_VIDEO,
+               VideoRange::VIDEO,
                true,
                false
                );
 
-       AVFrame* frame = av_frame_alloc ();
+       auto frame = av_frame_alloc ();
        DCPOMATIC_ASSERT (frame);
 
        {
@@ -472,6 +457,7 @@ DCPOMATIC_ENABLE_WARNINGS
 
 }
 
+
 /** Called when the player gives us some audio */
 void
 FFmpegFileEncoder::audio (shared_ptr<AudioBuffers> audio)
@@ -490,12 +476,13 @@ FFmpegFileEncoder::audio (shared_ptr<AudioBuffers> audio)
        }
 }
 
+
 void
 FFmpegFileEncoder::audio_frame (int size)
 {
        if (_audio_stream_per_channel) {
                int offset = 0;
-               BOOST_FOREACH (shared_ptr<ExportAudioStream> i, _audio_streams) {
+               for (auto i: _audio_streams) {
                        i->write (size, offset, 1, _pending_audio->data(), _audio_frames);
                        ++offset;
                }
@@ -509,18 +496,21 @@ FFmpegFileEncoder::audio_frame (int size)
        _audio_frames += size;
 }
 
+
 void
 FFmpegFileEncoder::subtitle (PlayerText, DCPTimePeriod)
 {
 
 }
 
+
 void
 FFmpegFileEncoder::buffer_free (void* opaque, uint8_t* data)
 {
        reinterpret_cast<FFmpegFileEncoder*>(opaque)->buffer_free2(data);
 }
 
+
 void
 FFmpegFileEncoder::buffer_free2 (uint8_t* data)
 {