/*** Olive - Non-Linear Video Editor Copyright (C) 2021 Olive Team This program 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. This program 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 this program. If not, see . ***/ #include "encoder.h" #include #include "common/timecodefunctions.h" #include "ffmpeg/ffmpegencoder.h" #include "oiio/oiioencoder.h" namespace olive { const QRegularExpression Encoder::kImageSequenceContainsDigits = QRegularExpression(QStringLiteral("\\[[#]+\\]")); const QRegularExpression Encoder::kImageSequenceRemoveDigits = QRegularExpression(QStringLiteral("[\\-\\.\\ \\_]?\\[[#]+\\]")); Encoder::Encoder(const EncodingParams ¶ms) : params_(params) { } const EncodingParams &Encoder::params() const { return params_; } QString Encoder::GetFilenameForFrame(const rational &frame) { if (params().video_is_image_sequence()) { // Transform! int64_t frame_index = Timecode::time_to_timestamp(frame, params().video_params().frame_rate_as_time_base()); int digits = GetImageSequencePlaceholderDigitCount(params().filename()); QString frame_index_str = QStringLiteral("%1").arg(frame_index, digits, 10, QChar('0')); QString f = params_.filename(); f.replace(kImageSequenceContainsDigits, frame_index_str); return f; } else { // Keep filename return params_.filename(); } } int Encoder::GetImageSequencePlaceholderDigitCount(const QString &filename) { int start = filename.indexOf(kImageSequenceContainsDigits); int digit_count = 0; for (int i=start+1; i &EncodingParams::video_opts() const { return video_opts_; } const int64_t &EncodingParams::video_bit_rate() const { return video_bit_rate_; } const int64_t &EncodingParams::video_min_bit_rate() const { return video_min_bit_rate_; } const int64_t &EncodingParams::video_max_bit_rate() const { return video_max_bit_rate_; } const int64_t &EncodingParams::video_buffer_size() const { return video_buffer_size_; } const int &EncodingParams::video_threads() const { return video_threads_; } const QString &EncodingParams::video_pix_fmt() const { return video_pix_fmt_; } bool EncodingParams::audio_enabled() const { return audio_enabled_; } const ExportCodec::Codec &EncodingParams::audio_codec() const { return audio_codec_; } const AudioParams &EncodingParams::audio_params() const { return audio_params_; } bool EncodingParams::subtitles_enabled() const { return subtitles_enabled_; } ExportCodec::Codec EncodingParams::subtitles_codec() const { return subtitles_codec_; } const rational &EncodingParams::GetExportLength() const { return export_length_; } void EncodingParams::SetExportLength(const rational &export_length) { export_length_ = export_length; } void EncodingParams::Save(QXmlStreamWriter *writer) const { writer->writeTextElement(QStringLiteral("filename"), filename_); writer->writeStartElement(QStringLiteral("video")); writer->writeAttribute(QStringLiteral("enabled"), QString::number(video_enabled_)); if (video_enabled_) { writer->writeTextElement(QStringLiteral("codec"), QString::number(video_codec_)); writer->writeTextElement(QStringLiteral("width"), QString::number(video_params_.width())); writer->writeTextElement(QStringLiteral("height"), QString::number(video_params_.height())); writer->writeTextElement(QStringLiteral("format"), QString::number(video_params_.format())); writer->writeTextElement(QStringLiteral("timebase"), video_params_.time_base().toString()); writer->writeTextElement(QStringLiteral("divider"), QString::number(video_params_.divider())); writer->writeTextElement(QStringLiteral("bitrate"), QString::number(video_bit_rate_)); writer->writeTextElement(QStringLiteral("minbitrate"), QString::number(video_max_bit_rate_)); writer->writeTextElement(QStringLiteral("maxbitrate"), QString::number(video_max_bit_rate_)); writer->writeTextElement(QStringLiteral("bufsize"), QString::number(video_buffer_size_)); writer->writeTextElement(QStringLiteral("threads"), QString::number(video_threads_)); if (!video_opts_.isEmpty()) { writer->writeStartElement(QStringLiteral("opts")); QHash::const_iterator i; for (i=video_opts_.constBegin(); i!=video_opts_.constEnd(); i++) { writer->writeStartElement(QStringLiteral("entry")); writer->writeTextElement(QStringLiteral("key"), i.key()); writer->writeTextElement(QStringLiteral("value"), i.value()); writer->writeEndElement(); // entry } writer->writeEndElement(); // opts } } writer->writeEndElement(); // video writer->writeStartElement(QStringLiteral("audio")); writer->writeAttribute(QStringLiteral("enabled"), QString::number(audio_enabled_)); if (audio_enabled_) { writer->writeTextElement(QStringLiteral("codec"), QString::number(audio_codec_)); writer->writeTextElement(QStringLiteral("samplerate"), QString::number(audio_params_.sample_rate())); writer->writeTextElement(QStringLiteral("channellayout"), QString::number(audio_params_.channel_layout())); writer->writeTextElement(QStringLiteral("format"), QString::number(audio_params_.format())); } writer->writeEndElement(); // audio } Encoder* Encoder::CreateFromID(Type id, const EncodingParams& params) { switch (id) { case kEncoderTypeNone: break; case kEncoderTypeFFmpeg: return new FFmpegEncoder(params); case kEncoderTypeOIIO: return new OIIOEncoder(params); } return nullptr; } Encoder::Type Encoder::GetTypeFromFormat(ExportFormat::Format f) { switch (f) { case ExportFormat::kFormatDNxHD: case ExportFormat::kFormatMatroska: case ExportFormat::kFormatQuickTime: case ExportFormat::kFormatMPEG4Video: case ExportFormat::kFormatMPEG4Audio: case ExportFormat::kFormatWAV: case ExportFormat::kFormatAIFF: case ExportFormat::kFormatMP3: case ExportFormat::kFormatFLAC: case ExportFormat::kFormatOgg: case ExportFormat::kFormatWebM: case ExportFormat::kFormatSRT: return kEncoderTypeFFmpeg; case ExportFormat::kFormatOpenEXR: case ExportFormat::kFormatPNG: case ExportFormat::kFormatTIFF: return kEncoderTypeOIIO; case ExportFormat::kFormatCount: break; } return kEncoderTypeNone; } Encoder *Encoder::CreateFromFormat(ExportFormat::Format f, const EncodingParams ¶ms) { return CreateFromID(GetTypeFromFormat(f), params); } QStringList Encoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const { return QStringList(); } std::vector Encoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const { return std::vector(); } }