Merge branch 'misc' into feature

This commit is contained in:
arch1t3cht 2024-10-25 17:58:53 +02:00
commit 0f8a7c0973
4 changed files with 136 additions and 66 deletions

View File

@ -81,11 +81,15 @@ public:
DialogProgressSink(DialogProgress *dialog) : dialog(dialog) { }
void SetTitle(std::string const& title) override {
Main().Async([=]{ dialog->title->SetLabelText(to_wx(title)); });
Main().Async([=]{ dialog->title->SetLabelText(to_wx(title)); dialog->Layout(); });
}
void SetMessage(std::string const& msg) override {
Main().Async([=]{ dialog->text->SetLabelText(to_wx(msg)); });
Main().Async([=]{
dialog->text->SetLabelText(to_wx(msg));
dialog->text->Wrap(dialog->GetMinWidth());
dialog->Fit();
});
}
void SetProgress(int64_t cur, int64_t max) override {
@ -127,7 +131,7 @@ DialogProgress::DialogProgress(wxWindow *parent, wxString const& title_text, wxS
{
title = new wxStaticText(this, -1, title_text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE);
gauge = new wxGauge(this, -1, 300, wxDefaultPosition, wxSize(300,20));
text = new wxStaticText(this, -1, message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE);
text = new wxStaticText(this, -1, message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
cancel_button = new wxButton(this, wxID_CANCEL);
log_output = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(600, 240), wxTE_MULTILINE | wxTE_READONLY);

View File

@ -41,6 +41,45 @@
struct VideoFrame;
/// Color matrix constants matching the constants in ffmpeg
/// (specifically libavutil's AVColorSpace) and/or H.273.
typedef enum AGI_ColorSpaces {
AGI_CS_RGB = 0,
AGI_CS_BT709 = 1,
AGI_CS_UNSPECIFIED = 2,
AGI_CS_FCC = 4,
AGI_CS_BT470BG = 5,
AGI_CS_SMPTE170M = 6,
AGI_CS_SMPTE240M = 7,
AGI_CS_YCOCG = 8,
AGI_CS_BT2020_NCL = 9,
AGI_CS_BT2020_CL = 10,
AGI_CS_SMPTE2085 = 11,
AGI_CS_CHROMATICITY_DERIVED_NCL = 12,
AGI_CS_CHROMATICITY_DERIVED_CL = 13,
AGI_CS_ICTCP = 14
} AGI_ColorSpaces;
/// Color matrix constants matching the constants in ffmpeg
/// (specifically libavutil's AVColorRange) and/or H.273.
typedef enum AGI_ColorRanges {
AGI_CR_UNSPECIFIED = 0,
AGI_CR_MPEG = 1, // 219*2^(n-8), i.e. 16-235 with 8-bit samples
AGI_CR_JPEG = 2 // 2^n-1, or "fullrange"
} AGI_ColorRanges;
namespace ColorMatrix {
std::string colormatrix_description(int CS, int CR);
std::pair<int, int> parse_colormatrix(std::string matrix);
void guess_colorspace(int &CS, int &CR, int Width, int Height);
void override_colormatrix(int &CS, int &CR, std::string matrix, int Width, int Height);
}
class VideoProvider {
public:
virtual ~VideoProvider() = default;

View File

@ -44,23 +44,6 @@
#include <libaegisub/make_unique.h>
namespace {
typedef enum AGI_ColorSpaces {
AGI_CS_RGB = 0,
AGI_CS_BT709 = 1,
AGI_CS_UNSPECIFIED = 2,
AGI_CS_FCC = 4,
AGI_CS_BT470BG = 5,
AGI_CS_SMPTE170M = 6,
AGI_CS_SMPTE240M = 7,
AGI_CS_YCOCG = 8,
AGI_CS_BT2020_NCL = 9,
AGI_CS_BT2020_CL = 10,
AGI_CS_SMPTE2085 = 11,
AGI_CS_CHROMATICITY_DERIVED_NCL = 12,
AGI_CS_CHROMATICITY_DERIVED_CL = 13,
AGI_CS_ICTCP = 14
} AGI_ColorSpaces;
/// @class FFmpegSourceVideoProvider
/// @brief Implements video loading through the FFMS library.
class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvider {
@ -70,13 +53,12 @@ class FFmpegSourceVideoProvider final : public VideoProvider, FFmpegSourceProvid
int Width = -1; ///< width in pixels
int Height = -1; ///< height in pixels
int CS = -1; ///< Reported colorspace of first frame
int CR = -1; ///< Reported colorrange of first frame
int VideoCS = -1; ///< Reported colorspace of first frame (or guessed if unspecified)
int VideoCR = -1; ///< Reported colorrange of first frame (or guessed if unspecified)
double DAR; ///< display aspect ratio
std::vector<int> KeyFramesList; ///< list of keyframes
agi::vfr::Framerate Timecodes; ///< vfr object
std::string ColorSpace; ///< Colorspace name
std::string RealColorSpace; ///< Colorspace name
char FFMSErrMsg[1024]; ///< FFMS error message
FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages
@ -91,12 +73,14 @@ public:
void SetColorSpace(std::string const& matrix) override {
if (matrix == ColorSpace) return;
if (matrix == RealColorSpace)
FFMS_SetInputFormatV(VideoSource, CS, CR, FFMS_GetPixFmt(""), nullptr);
else if (matrix == "TV.601")
FFMS_SetInputFormatV(VideoSource, AGI_CS_BT470BG, CR, FFMS_GetPixFmt(""), nullptr);
else
return;
int CS = VideoCS;
int CR = VideoCR;
ColorMatrix::override_colormatrix(CS, CR, matrix, Width, Height);
if (FFMS_SetInputFormatV(VideoSource, CS, CR, FFMS_GetPixFmt(""), &ErrInfo))
throw VideoOpenError(std::string("Failed to set input format: ") + ErrInfo.Buffer);
ColorSpace = matrix;
}
@ -114,34 +98,19 @@ public:
agi::vfr::Framerate GetFPS() const override { return Timecodes; }
std::string GetColorSpace() const override { return ColorSpace; }
std::string GetRealColorSpace() const override { return RealColorSpace; }
std::string GetRealColorSpace() const override {
std::string result = ColorMatrix::colormatrix_description(VideoCS, VideoCR);
if (result == "") {
return "None";
}
return result;
}
std::vector<int> GetKeyFrames() const override { return KeyFramesList; };
std::string GetDecoderName() const override { return "FFmpegSource"; }
bool WantsCaching() const override { return true; }
bool HasAudio() const override { return has_audio; }
};
std::string colormatrix_description(int cs, int cr) {
// Assuming TV for unspecified
std::string str = cr == FFMS_CR_JPEG ? "PC" : "TV";
switch (cs) {
case AGI_CS_RGB:
return "None";
case AGI_CS_BT709:
return str + ".709";
case AGI_CS_FCC:
return str + ".FCC";
case AGI_CS_BT470BG:
case AGI_CS_SMPTE170M:
return str + ".601";
case AGI_CS_SMPTE240M:
return str + ".240M";
default:
throw VideoOpenError("Unknown video color space");
}
}
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(agi::fs::path const& filename, std::string const& colormatrix, agi::BackgroundRunner *br) try
: FFmpegSourceProvider(br)
, VideoSource(nullptr, FFMS_DestroyVideoSource)
@ -260,22 +229,11 @@ void FFmpegSourceVideoProvider::LoadVideo(agi::fs::path const& filename, std::st
else
DAR = double(Width) / Height;
int VideoCS = CS = TempFrame->ColorSpace;
CR = TempFrame->ColorRange;
VideoCS = TempFrame->ColorSpace;
VideoCR = TempFrame->ColorRange;
ColorMatrix::guess_colorspace(VideoCS, VideoCR, Width, Height);
if (CS == AGI_CS_UNSPECIFIED)
CS = Width > 1024 || Height >= 600 ? AGI_CS_BT709 : AGI_CS_BT470BG;
RealColorSpace = ColorSpace = colormatrix_description(CS, CR);
if (CS != AGI_CS_RGB && CS != AGI_CS_BT470BG && ColorSpace != colormatrix && colormatrix == "TV.601") {
CS = AGI_CS_BT470BG;
ColorSpace = colormatrix_description(AGI_CS_BT470BG, CR);
}
if (CS != VideoCS) {
if (FFMS_SetInputFormatV(VideoSource, CS, CR, FFMS_GetPixFmt(""), &ErrInfo))
throw VideoOpenError(std::string("Failed to set input format: ") + ErrInfo.Buffer);
}
SetColorSpace(colormatrix);
const int TargetFormat[] = { FFMS_GetPixFmt("bgra"), -1 };
if (FFMS_SetOutputFormatV2(VideoSource, TargetFormat, Width, Height, FFMS_RESIZER_BICUBIC, &ErrInfo))

View File

@ -23,6 +23,7 @@
#include <libaegisub/log.h>
#include <libaegisub/format.h>
#include <libaegisub/split.h>
#include <boost/range/iterator_range.hpp>
@ -37,6 +38,74 @@ std::unique_ptr<VideoProvider> CreateVapourSynthVideoProvider(agi::fs::path cons
std::unique_ptr<VideoProvider> CreateCacheVideoProvider(std::unique_ptr<VideoProvider>);
namespace ColorMatrix {
std::string colormatrix_description(int cs, int cr) {
// Assuming TV for unspecified
std::string str = cr == AGI_CR_JPEG ? "PC" : "TV";
switch (cs) {
case AGI_CS_RGB:
return "None";
case AGI_CS_BT709:
return str + ".709";
case AGI_CS_FCC:
return str + ".FCC";
case AGI_CS_BT470BG:
case AGI_CS_SMPTE170M:
return str + ".601";
case AGI_CS_SMPTE240M:
return str + ".240M";
default:
return "";
}
}
std::pair<int, int> parse_colormatrix(std::string matrix) {
int cs = AGI_CS_UNSPECIFIED;
int cr = AGI_CR_UNSPECIFIED;
std::vector<std::string> parts;
agi::Split(parts, matrix, '.');
if (parts.size() == 2) {
if (parts[0] == "TV") {
cr = AGI_CR_MPEG;
} else if (parts[0] == "PC") {
cr = AGI_CR_JPEG;
}
if (parts[1] == "709") {
cs = AGI_CS_BT709;
} else if (parts[1] == "601") {
cs = AGI_CS_BT470BG;
} else if (parts[1] == "FCC") {
cs = AGI_CS_FCC;
} else if (parts[1] == "240M") {
cs = AGI_CS_SMPTE240M;
}
}
return std::make_pair(cs, cr);
}
void guess_colorspace(int &CS, int &CR, int Width, int Height) {
if (CS == AGI_CS_UNSPECIFIED)
CS = Width > 1024 || Height >= 600 ? AGI_CS_BT709 : AGI_CS_BT470BG;
if (CR != AGI_CR_MPEG)
CR = AGI_CR_MPEG;
}
void override_colormatrix(int &CS, int &CR, std::string matrix, int Width, int Height) {
guess_colorspace(CS, CR, Width, Height);
auto [oCS, oCR] = parse_colormatrix(matrix);
if (oCS != AGI_CS_UNSPECIFIED && oCR != AGI_CR_UNSPECIFIED) {
CS = oCS;
CR = oCR;
}
}
}
namespace {
struct factory {
const char *name;