X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fconsumer%2Fffmpeg_consumer.cpp;h=0b38701253151cb00c20dd797d9284f0c5d01dae;hb=b17a5351a13075978b5e5d4c817fb683224d9d38;hp=2a60c6721a1e5a0243ce7e9306fb83ac4b4df21e;hpb=752794f2b6a072f5ea2ce9e85b12c55ee4591af3;p=casparcg diff --git a/modules/ffmpeg/consumer/ffmpeg_consumer.cpp b/modules/ffmpeg/consumer/ffmpeg_consumer.cpp index 2a60c6721..0b3870125 100644 --- a/modules/ffmpeg/consumer/ffmpeg_consumer.cpp +++ b/modules/ffmpeg/consumer/ffmpeg_consumer.cpp @@ -1,813 +1,1227 @@ -/* -* Copyright (c) 2011 Sveriges Television AB -* -* This file is part of CasparCG (www.casparcg.com). -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -* Author: Robert Nagy, ronag89@gmail.com -*/ - #include "../StdAfx.h" -#include "../ffmpeg_error.h" - #include "ffmpeg_consumer.h" -#include "../producer/tbb_avcodec.h" - -#include -#include -#include -#include +#include "../ffmpeg_error.h" +#include "../producer/util/util.h" +#include "../producer/filter/filter.h" +#include "../producer/filter/audio_filter.h" -#include -#include #include #include +#include +#include #include #include -#include -#include +#include +#include +#include #include -#include -#include -#include +#include -#include -#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include -#include -#include -#include -#include -#include +#pragma warning(push) +#pragma warning(disable: 4244) +#pragma warning(disable: 4245) +#include +#pragma warning(pop) + +#include +#include +#include +#include #include -#if defined(_MSC_VER) -#pragma warning (push) -#pragma warning (disable : 4244) -#endif -extern "C" +#pragma warning(push) +#pragma warning(disable: 4244) + +extern "C" { #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS #include - #include + #include + #include + #include #include - #include + #include #include - #include - #include + #include + #include + #include } -#if defined(_MSC_VER) -#pragma warning (pop) -#endif + +#pragma warning(pop) namespace caspar { namespace ffmpeg { - -int av_opt_set(void *obj, const char *name, const char *val, int search_flags) + +void set_pixel_format(AVFilterContext* sink, AVPixelFormat pix_fmt) { - AVClass* av_class = *(AVClass**)obj; +#pragma warning (push) +#pragma warning (disable : 4245) + + FF(av_opt_set_int_list( + sink, + "pix_fmts", + std::vector({ pix_fmt, AVPixelFormat::AV_PIX_FMT_NONE }).data(), + -1, + AV_OPT_SEARCH_CHILDREN)); + +#pragma warning (pop) +} - if((strcmp(name, "pix_fmt") == 0 || strcmp(name, "pixel_format") == 0) && strcmp(av_class->class_name, "AVCodecContext") == 0) +void adjust_video_filter(const AVCodec& codec, const core::video_format_desc& in_format, AVFilterContext* sink, std::string& filter) +{ + switch (codec.id) { - AVCodecContext* c = (AVCodecContext*)obj; - auto pix_fmt = av_get_pix_fmt(val); - if(pix_fmt == PIX_FMT_NONE) - return -1; - c->pix_fmt = pix_fmt; - return 0; + case AV_CODEC_ID_DVVIDEO: + // Crop + if (in_format.format == core::video_format::ntsc) + filter = u8(append_filter(u16(filter), L"crop=720:480:0:2")); + + // Pixel format selection + if (in_format.format == core::video_format::ntsc) + set_pixel_format(sink, AVPixelFormat::AV_PIX_FMT_YUV411P); + else if (in_format.format == core::video_format::pal) + set_pixel_format(sink, AVPixelFormat::AV_PIX_FMT_YUV420P); + else + set_pixel_format(sink, AVPixelFormat::AV_PIX_FMT_YUV422P); + + // Scale + if (in_format.height == 1080) + filter = u8(append_filter(u16(filter), in_format.duration == 1001 + ? L"scale=1280:1080" + : L"scale=1440:1080")); + else if (in_format.height == 720) + filter = u8(append_filter(u16(filter), L"scale=960:720")); + + break; } - //if((strcmp(name, "r") == 0 || strcmp(name, "frame_rate") == 0) && strcmp(av_class->class_name, "AVCodecContext") == 0) - //{ - // AVCodecContext* c = (AVCodecContext*)obj; +} + +void setup_codec_defaults(AVCodecContext& encoder) +{ + static const int MEGABIT = 1000000; - // if(c->codec_type != AVMEDIA_TYPE_VIDEO) - // return -1; + switch (encoder.codec_id) + { + case AV_CODEC_ID_DNXHD: + encoder.bit_rate = 220 * MEGABIT; + + break; + case AV_CODEC_ID_PRORES: + encoder.bit_rate = encoder.width < 1280 + ? 63 * MEGABIT + : 220 * MEGABIT; + + break; + case AV_CODEC_ID_H264: + av_opt_set(encoder.priv_data, "preset", "ultrafast", 0); + av_opt_set(encoder.priv_data, "tune", "fastdecode", 0); + av_opt_set(encoder.priv_data, "crf", "5", 0); + + break; + } +} - // AVRational rate; - // int ret = av_parse_video_rate(&rate, val); - // if(ret < 0) - // return ret; +bool is_pcm_s24le_not_supported(const AVFormatContext& container) +{ + auto name = std::string(container.oformat->name); - // c->time_base.num = rate.den; - // c->time_base.den = rate.num; - // return 0; - //} + if (name == "mp4" || name == "dv") + return true; - return ::av_opt_set(obj, name, val, search_flags); + return false; } -struct option +template +std::vector from_terminated_array(const In* array, In terminator) { - std::string name; - std::string value; + std::vector result; - option(std::string name, std::string value) - : name(std::move(name)) - , value(std::move(value)) + while (array != nullptr && *array != terminator) { + In val = *array; + Out casted = static_cast(val); + + result.push_back(casted); + + ++array; } -}; - -struct output_format + + return result; +} + +class ffmpeg_consumer { - AVOutputFormat* format; - int width; - int height; - AVCodecID vcodec; - AVCodecID acodec; - int croptop; - int cropbot; - - output_format(const core::video_format_desc& format_desc, const std::string& filename, std::vector