X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_file_encoder.cc;h=cd5d473f946efb92eaf13a2840fc865b9b7ce00f;hb=bf19399f8c009ff211d5c7b45b0941417d963c4e;hp=eb7036429fb44bbeb05893bffbfa6f2ab89ee331;hpb=c4403784febdbdd42e9c32e67fadb147f11fe566;p=dcpomatic.git diff --git a/src/lib/ffmpeg_file_encoder.cc b/src/lib/ffmpeg_file_encoder.cc index eb7036429..cd5d473f9 100644 --- a/src/lib/ffmpeg_file_encoder.cc +++ b/src/lib/ffmpeg_file_encoder.cc @@ -38,6 +38,7 @@ using std::pair; using boost::shared_ptr; using boost::bind; using boost::weak_ptr; +using boost::optional; using namespace dcpomatic; int FFmpegFileEncoder::_video_stream_index = 0; @@ -51,6 +52,10 @@ FFmpegFileEncoder::FFmpegFileEncoder ( ExportFormat format, int x264_crf, boost::filesystem::path output +#ifdef DCPOMATIC_VARIANT_SWAROOP + , optional key + , optional id +#endif ) : _video_options (0) , _audio_channels (channels) @@ -69,18 +74,28 @@ FFmpegFileEncoder::FFmpegFileEncoder ( av_dict_set (&_video_options, "profile", "3", 0); av_dict_set (&_video_options, "threads", "auto", 0); break; - case EXPORT_FORMAT_H264: + case EXPORT_FORMAT_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: + _sample_format = AV_SAMPLE_FMT_S32; + _video_codec_name = "libx264"; + _audio_codec_name = "pcm_s24le"; + av_dict_set_int (&_video_options, "crf", x264_crf, 0); + break; } setup_video (); setup_audio (); +#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)); } @@ -116,7 +131,24 @@ FFmpegFileEncoder::FFmpegFileEncoder ( throw runtime_error ("could not open FFmpeg output file"); } - if (avformat_write_header (_format_context, 0) < 0) { + 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 + + if (avformat_write_header (_format_context, &options) < 0) { throw runtime_error ("could not write header to FFmpeg output file"); } @@ -129,7 +161,8 @@ FFmpegFileEncoder::pixel_format (ExportFormat format) switch (format) { case EXPORT_FORMAT_PRORES: return AV_PIX_FMT_YUV422P10; - case EXPORT_FORMAT_H264: + case EXPORT_FORMAT_H264_AAC: + case EXPORT_FORMAT_H264_PCM: return AV_PIX_FMT_YUV420P; default: DCPOMATIC_ASSERT (false); @@ -178,7 +211,7 @@ FFmpegFileEncoder::setup_audio () avcodec_get_context_defaults3 (_audio_codec_context, _audio_codec); /* XXX: configurable */ - _audio_codec_context->bit_rate = 256 * 1024; + _audio_codec_context->bit_rate = _audio_channels * 128 * 1024; _audio_codec_context->sample_fmt = _sample_format; _audio_codec_context->sample_rate = _audio_frame_rate; _audio_codec_context->channel_layout = av_get_default_channel_layout (_audio_channels); @@ -329,6 +362,16 @@ FFmpegFileEncoder::audio_frame (int size) } break; } + case AV_SAMPLE_FMT_S32: + { + int32_t* q = reinterpret_cast (samples); + for (int i = 0; i < size; ++i) { + for (int j = 0; j < channels; ++j) { + *q++ = p[j][i] * 2147483647; + } + } + break; + } case AV_SAMPLE_FMT_FLTP: { float* q = reinterpret_cast (samples);