Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
CrendKing committed Jun 15, 2021
1 parent b8d1f6f commit 55727fb
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 69 deletions.
32 changes: 16 additions & 16 deletions avisynth_filter/src/format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,34 @@ namespace SynthFilter {
// for each group of formats with the same format ID, they should appear with the most preferred -> list preferred order
const std::vector<Format::PixelFormat> Format::PIXEL_FORMATS = {
// 4:2:0
{ .name = L"NV12", .mediaSubtype = MEDIASUBTYPE_NV12, .fsFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_NV12 },
{ .name = L"YV12", .mediaSubtype = MEDIASUBTYPE_YV12, .fsFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YV12 },
{ .name = L"I420", .mediaSubtype = MEDIASUBTYPE_I420, .fsFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_I420 },
{ .name = L"IYUV", .mediaSubtype = MEDIASUBTYPE_IYUV, .fsFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_IYUV },
{ .name = L"NV12", .mediaSubtype = MEDIASUBTYPE_NV12, .frameServerFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_NV12 },
{ .name = L"YV12", .mediaSubtype = MEDIASUBTYPE_YV12, .frameServerFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YV12 },
{ .name = L"I420", .mediaSubtype = MEDIASUBTYPE_I420, .frameServerFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_I420 },
{ .name = L"IYUV", .mediaSubtype = MEDIASUBTYPE_IYUV, .frameServerFormatId = VideoInfo::CS_YV12, .bitCount = 12, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_IYUV },

// P010 has the most significant 6 bits zero-padded, while AviSynth expects the least significant bits padded
// P010 without right shifting 6 bits on every WORD is equivalent to P016, without precision loss
{ .name = L"P016", .mediaSubtype = MEDIASUBTYPE_P016, .fsFormatId = VideoInfo::CS_YUV420P16, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P016 },
{ .name = L"P010", .mediaSubtype = MEDIASUBTYPE_P010, .fsFormatId = VideoInfo::CS_YUV420P16, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P010 },
{ .name = L"P016", .mediaSubtype = MEDIASUBTYPE_P016, .frameServerFormatId = VideoInfo::CS_YUV420P16, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P016 },
{ .name = L"P010", .mediaSubtype = MEDIASUBTYPE_P010, .frameServerFormatId = VideoInfo::CS_YUV420P16, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 2, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P010 },

// 4:2:2
// YUY2 interleaves Y and UV planes together, thus twice as wide as unpacked formats per pixel
{ .name = L"YUY2", .mediaSubtype = MEDIASUBTYPE_YUY2, .fsFormatId = VideoInfo::CS_YUY2, .bitCount = 16, .componentsPerPixel = 2, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YUY2 },
{ .name = L"YUY2", .mediaSubtype = MEDIASUBTYPE_YUY2, .frameServerFormatId = VideoInfo::CS_YUY2, .bitCount = 16, .componentsPerPixel = 2, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YUY2 },
// AviSynth+ does not support UYVY
// P210 has the same problem as P010
{ .name = L"P216", .mediaSubtype = MEDIASUBTYPE_P216, .fsFormatId = VideoInfo::CS_YUV422P16, .bitCount = 32, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P216 },
{ .name = L"P210", .mediaSubtype = MEDIASUBTYPE_P210, .fsFormatId = VideoInfo::CS_YUV422P16, .bitCount = 32, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P210 },
{ .name = L"P216", .mediaSubtype = MEDIASUBTYPE_P216, .frameServerFormatId = VideoInfo::CS_YUV422P16, .bitCount = 32, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P216 },
{ .name = L"P210", .mediaSubtype = MEDIASUBTYPE_P210, .frameServerFormatId = VideoInfo::CS_YUV422P16, .bitCount = 32, .componentsPerPixel = 1, .subsampleWidthRatio = 2, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = true, .resourceId = IDC_INPUT_FORMAT_P210 },

// 4:4:4
{ .name = L"YV24", .mediaSubtype = MEDIASUBTYPE_YV24, .fsFormatId = VideoInfo::CS_YV24, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 1, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YV24 },
{ .name = L"YV24", .mediaSubtype = MEDIASUBTYPE_YV24, .frameServerFormatId = VideoInfo::CS_YV24, .bitCount = 24, .componentsPerPixel = 1, .subsampleWidthRatio = 1, .subsampleHeightRatio = 1, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_YV24 },

// RGB
{ .name = L"RGB24", .mediaSubtype = MEDIASUBTYPE_RGB24, .fsFormatId = VideoInfo::CS_BGR24, .bitCount = 24, .componentsPerPixel = 3, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_RGB24 },
{ .name = L"RGB32", .mediaSubtype = MEDIASUBTYPE_RGB32, .fsFormatId = VideoInfo::CS_BGR32, .bitCount = 32, .componentsPerPixel = 4, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_RGB32 },
{ .name = L"RGB24", .mediaSubtype = MEDIASUBTYPE_RGB24, .frameServerFormatId = VideoInfo::CS_BGR24, .bitCount = 24, .componentsPerPixel = 3, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_RGB24 },
{ .name = L"RGB32", .mediaSubtype = MEDIASUBTYPE_RGB32, .frameServerFormatId = VideoInfo::CS_BGR32, .bitCount = 32, .componentsPerPixel = 4, .subsampleWidthRatio = 0, .subsampleHeightRatio = 0, .areUVPlanesInterleaved = false, .resourceId = IDC_INPUT_FORMAT_RGB32 },
// RGB48 will not work because LAV Filters outputs R-G-B pixel order while AviSynth+ expects B-G-R
};

auto Format::GetVideoFormat(const AM_MEDIA_TYPE &mediaType, const FrameServerBase *scriptInstance) -> VideoFormat {
auto Format::GetVideoFormat(const AM_MEDIA_TYPE &mediaType, const FrameServerBase *frameServerInstance) -> VideoFormat {
const VIDEOINFOHEADER *vih = reinterpret_cast<VIDEOINFOHEADER *>(mediaType.pbFormat);
const REFERENCE_TIME frameDuration = vih->AvgTimePerFrame > 0 ? vih->AvgTimePerFrame : DEFAULT_AVG_TIME_PER_FRAME;

Expand All @@ -56,7 +56,7 @@ auto Format::GetVideoFormat(const AM_MEDIA_TYPE &mediaType, const FrameServerBas
.fps_numerator = UNITS,
.fps_denominator = static_cast<unsigned int>(frameDuration),
.num_frames = NUM_FRAMES_FOR_INFINITE_STREAM,
.pixel_type = ret.pixelFormat->fsFormatId,
.pixel_type = ret.pixelFormat->frameServerFormatId,
};

if (SUCCEEDED(CheckVideoInfo2Type(&mediaType))) {
Expand Down Expand Up @@ -109,7 +109,7 @@ auto Format::CopyFromInput(const VideoFormat &videoFormat, const BYTE *srcBuffer

MainFrameServer::GetInstance().GetEnv()->BitBlt(dstSlices[0], dstStrides[0], srcMainPlane, srcMainPlaneStride, rowSize, height);

if (videoFormat.pixelFormat->fsFormatId & VideoInfo::CS_INTERLEAVED) {
if (videoFormat.pixelFormat->frameServerFormatId & VideoInfo::CS_INTERLEAVED) {
return;
}

Expand Down Expand Up @@ -175,7 +175,7 @@ auto Format::CopyToOutput(const VideoFormat &videoFormat, const std::array<const

MainFrameServer::GetInstance().GetEnv()->BitBlt(dstMainPlane, dstMainPlaneStride, srcSlices[0], srcStrides[0], rowSize, height);

if (videoFormat.pixelFormat->fsFormatId & VideoInfo::CS_INTERLEAVED) {
if (videoFormat.pixelFormat->frameServerFormatId & VideoInfo::CS_INTERLEAVED) {
return;
}

Expand Down
6 changes: 3 additions & 3 deletions filter_common/src/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ auto CSynthFilter::CheckConnect(PIN_DIRECTION direction, IPin *pPin) -> HRESULT
}

// all media types that share the same frameserver format are acceptable for output pin connection
for (const Format::PixelFormat &fsPixelFormat : Format::LookupFsFormatId(AuxFrameServer::GetInstance().GetScriptPixelType())) {
const CMediaType outputMediaType = AuxFrameServer::GetInstance().GenerateMediaType(fsPixelFormat, nextType);
for (const Format::PixelFormat &frameServerPixelFormat : Format::LookupFrameServerFormatId(AuxFrameServer::GetInstance().GetScriptPixelType())) {
const CMediaType outputMediaType = AuxFrameServer::GetInstance().GenerateMediaType(frameServerPixelFormat, nextType);
_compatibleMediaTypes.emplace_back(nextTypePtr, optInputPixelFormat, outputMediaType, MediaTypeToPixelFormat(&outputMediaType));
if (std::ranges::find(_availableOutputMediaTypes, outputMediaType) == _availableOutputMediaTypes.end()) {
_availableOutputMediaTypes.emplace_back(outputMediaType);
}
Environment::GetInstance().Log(L"Add compatible formats: input %s output %s", optInputPixelFormat->name, fsPixelFormat.name);
Environment::GetInstance().Log(L"Add compatible formats: input %s output %s", optInputPixelFormat->name, frameServerPixelFormat.name);
}
}
} else if (hr == VFW_E_ENUM_OUT_OF_SYNC) {
Expand Down
7 changes: 6 additions & 1 deletion filter_common/src/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,14 @@ __declspec(uuid("3ab7506b-fc4a-4144-8ee3-a97fab4f9cb3"))

static auto InputToOutputMediaType(const AM_MEDIA_TYPE *mtIn) {
AuxFrameServer::GetInstance().ReloadScript(*mtIn, true);
return Format::LookupFsFormatId(AuxFrameServer::GetInstance().GetScriptPixelType()) | std::views::transform([mtIn](const Format::PixelFormat &pixelFormat) -> CMediaType {
const int scriptPixelType = AuxFrameServer::GetInstance().GetScriptPixelType();
auto ret = Format::LookupFrameServerFormatId(scriptPixelType) | std::views::transform([mtIn](const Format::PixelFormat &pixelFormat) -> CMediaType {
return AuxFrameServer::GetInstance().GenerateMediaType(pixelFormat, mtIn);
});
if (ret.empty()) {
Environment::GetInstance().Log(L"Unable to find any supported pixel format for script pixel type %i", scriptPixelType);
}
return ret;
}

static auto MediaTypeToPixelFormat(const AM_MEDIA_TYPE *mediaType) -> const Format::PixelFormat *;
Expand Down
12 changes: 6 additions & 6 deletions filter_common/src/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Format {
struct PixelFormat {
const WCHAR *name;
const CLSID &mediaSubtype;
int fsFormatId;
int frameServerFormatId;

// for BITMAPINFOHEADER::biBitCount
uint8_t bitCount;
Expand All @@ -51,7 +51,7 @@ class Format {
int hdrType;
int hdrLuminance;
BITMAPINFOHEADER bmi;
FrameServerInstance fsEnvironment;
FrameServerInstance frameServer;

auto GetCodecFourCC() const -> DWORD {
return FOURCCMap(&pixelFormat->mediaSubtype).GetFOURCC();
Expand All @@ -60,9 +60,9 @@ class Format {

static auto Initialize() -> void;
static auto LookupMediaSubtype(const CLSID &mediaSubtype) -> const PixelFormat *;
static constexpr auto LookupFsFormatId(int fsFormatId) {
return PIXEL_FORMATS | std::views::filter([fsFormatId](const PixelFormat &pixelFormat) -> bool {
return fsFormatId == pixelFormat.fsFormatId;
static constexpr auto LookupFrameServerFormatId(int frameServerFormatId) {
return PIXEL_FORMATS | std::views::filter([frameServerFormatId](const PixelFormat &pixelFormat) -> bool {
return frameServerFormatId == pixelFormat.frameServerFormatId;
});
}

Expand All @@ -79,7 +79,7 @@ class Format {
return nullptr;
}

static auto GetVideoFormat(const AM_MEDIA_TYPE &mediaType, const FrameServerBase *scriptInstance) -> VideoFormat;
static auto GetVideoFormat(const AM_MEDIA_TYPE &mediaType, const FrameServerBase *frameServerInstance) -> VideoFormat;
static auto WriteSample(const VideoFormat &videoFormat, ConstFrameType srcFrame, BYTE *dstBuffer) -> void;
static auto CreateFrame(const VideoFormat &videoFormat, const BYTE *srcBuffer) -> FrameType;
static auto CopyFromInput(const VideoFormat &videoFormat, const BYTE *srcBuffer, const std::array<BYTE *, 3> &dstSlices, const std::array<int, 3> &dstStrides, int rowSize, int height) -> void;
Expand Down
47 changes: 23 additions & 24 deletions filter_common/src/frame_handler_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,30 +66,29 @@ auto FrameHandler::ChangeOutputFormat() -> bool {
_filter._reloadScript = false;

auto potentialOutputMediaTypes = _filter.InputToOutputMediaType(&_filter.m_pInput->CurrentMediaType());
const auto newOutputMediaTypeIter = std::ranges::find_if(potentialOutputMediaTypes, [this](const CMediaType &outputMediaType) -> bool {
/*
* "QueryAccept (Downstream)" forces the downstream to use the new output media type as-is, which may lead to wrong rendering result
* "ReceiveConnection" allows downstream to counter-propose suitable media type for the connection
* after ReceiveConnection(), the next output sample should carry the new output media type, which is handled in PrepareOutputSample()
*/

if (_isFlushing) {
return false;
}

const bool result = SUCCEEDED(_filter.m_pOutput->GetConnected()->ReceiveConnection(_filter.m_pOutput, &outputMediaType));
Environment::GetInstance().Log(L"Attempt to reconnect output pin with media type: output %s result %i", Format::LookupMediaSubtype(outputMediaType.subtype)->name, result);

if (result) {
_filter.m_pOutput->SetMediaType(&outputMediaType);
_filter._outputVideoFormat = Format::GetVideoFormat(outputMediaType, &MainFrameServer::GetInstance());
_notifyChangedOutputMediaType = true;
}

return result;
});

if (newOutputMediaTypeIter == potentialOutputMediaTypes.end()) {
if (const auto newOutputMediaTypeIter = std::ranges::find_if(potentialOutputMediaTypes, [this](const CMediaType &outputMediaType) -> bool {
/*
* "QueryAccept (Downstream)" forces the downstream to use the new output media type as-is, which may lead to wrong rendering result
* "ReceiveConnection" allows downstream to counter-propose suitable media type for the connection
* after ReceiveConnection(), the next output sample should carry the new output media type, which is handled in PrepareOutputSample()
*/

if (_isFlushing) {
return false;
}

const bool result = SUCCEEDED(_filter.m_pOutput->GetConnected()->ReceiveConnection(_filter.m_pOutput, &outputMediaType));
Environment::GetInstance().Log(L"Attempt to reconnect output pin with media type: output %s result %i", Format::LookupMediaSubtype(outputMediaType.subtype)->name, result);

if (result) {
_filter.m_pOutput->SetMediaType(&outputMediaType);
_filter._outputVideoFormat = Format::GetVideoFormat(outputMediaType, &MainFrameServer::GetInstance());
_notifyChangedOutputMediaType = true;
}

return result;
});
newOutputMediaTypeIter == potentialOutputMediaTypes.end()) {
Environment::GetInstance().Log(L"Downstream does not accept any of the new output media types");
_filter.AbortPlayback(VFW_E_TYPE_NOT_ACCEPTED);
return false;
Expand Down
Loading

0 comments on commit 55727fb

Please sign in to comment.