Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions YUViewLib/src/playlistitem/playlistItemRawFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,15 +457,13 @@ void playlistItemRawFile::setFormatFromFileName()
const auto frameFormat = filesource::frameFormatGuess::guessFrameFormat(fileInfoForGuess);

if (frameFormat.frameSize)
{
this->video->setFrameSize(*frameFormat.frameSize);

// We were able to extract width and height from the file name using
// regular expressions. Try to get the pixel format by checking with the file size.
this->video->guessAndSetPixelFormat(frameFormat, fileInfoForGuess);
if (frameFormat.frameRate)
this->prop.frameRate = *frameFormat.frameRate;
}
// Try to get the pixel format. If we know a frame size, we will check the format
// against the file size.
this->video->guessAndSetPixelFormat(frameFormat, fileInfoForGuess);
if (frameFormat.frameRate)
this->prop.frameRate = *frameFormat.frameRate;
}

void playlistItemRawFile::createPropertiesWidget()
Expand Down
69 changes: 37 additions & 32 deletions YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ using filesource::frameFormatGuess::GuessedFrameFormat;
namespace video::yuv
{

namespace
{

Subsampling findSubsamplingTypeIndicatorInName(const std::string &name)
{
std::string matcher = "(?:_|\\.|-)(";
Expand Down Expand Up @@ -94,13 +97,13 @@ std::vector<Subsampling> getDetectionSubsamplingList(Subsampling subsamplingToFo
}

bool doesPixelFormatMatchFileSize(const PixelFormatYUV &pixelFormat,
const Size &frameSize,
const std::optional<Size> &frameSize,
const std::optional<int64_t> &fileSize)
{
if (!fileSize)
if (!fileSize || !frameSize)
return true;

const auto bytesPerFrame = pixelFormat.bytesPerFrame(frameSize);
const auto bytesPerFrame = pixelFormat.bytesPerFrame(*frameSize);
if (bytesPerFrame <= 0)
return false;

Expand Down Expand Up @@ -143,9 +146,9 @@ PixelFormatYUV testFormatFromSizeAndNamePlanar(const std::string &nam
formatName << bitDepth << endianness;
formatName << interlacedString;
auto fmt = PixelFormatYUV(
subsampling, bitDepth, entry.second, endianness == "be", {}, interlaced);
subsampling, bitDepth, entry.second, endianness == "be", {}, interlaced);
if (name.find(formatName.str()) != std::string::npos &&
doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileSize))
doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileSize))
return fmt;
}

Expand All @@ -158,9 +161,9 @@ PixelFormatYUV testFormatFromSizeAndNamePlanar(const std::string &nam
formatName << bitDepth << endianness;
formatName << interlacedString;
auto fmt = PixelFormatYUV(
subsampling, bitDepth, entry.second, endianness == "be", {}, interlaced);
subsampling, bitDepth, entry.second, endianness == "be", {}, interlaced);
if (name.find(formatName.str()) != std::string::npos &&
doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileSize))
doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileSize))
return fmt;
}
}
Expand All @@ -182,7 +185,7 @@ PixelFormatYUV testFormatFromSizeAndNamePacked(const std::string &nam
if (std::regex_search(name, sm, strExpr))
{
const auto fmt = PixelFormatYUV(PredefinedPixelFormat::V210);
if (doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileSize))
if (doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileSize))
return fmt;
}

Expand All @@ -209,7 +212,7 @@ PixelFormatYUV testFormatFromSizeAndNamePacked(const std::string &nam
formatName << std::to_string(bitDepth) + endianness;
auto fmt = PixelFormatYUV(subsampling, bitDepth, packing, false, endianness == "be");
if (name.find(formatName.str()) != std::string::npos &&
doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileSize))
doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileSize))
return fmt;
}

Expand All @@ -222,7 +225,7 @@ PixelFormatYUV testFormatFromSizeAndNamePacked(const std::string &nam
formatName << bitDepth << endianness;
auto fmt = PixelFormatYUV(subsampling, bitDepth, packing, false, endianness == "be");
if (name.find(formatName.str()) != std::string::npos &&
doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileSize))
doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileSize))
return fmt;
}
}
Expand All @@ -242,24 +245,24 @@ checkSpecificFileExtensions(const GuessedFrameFormat &guessedFrameFormat,
if (fileExtension == ".raw")
{
const auto rawBayerFormat =
PixelFormatYUV(Subsampling::YUV_400, guessedFrameFormat.bitDepth.value_or(8));
PixelFormatYUV(Subsampling::YUV_400, guessedFrameFormat.bitDepth.value_or(8));
if (doesPixelFormatMatchFileSize(
rawBayerFormat, *guessedFrameFormat.frameSize, fileInfo.fileSize))
rawBayerFormat, guessedFrameFormat.frameSize, fileInfo.fileSize))
return rawBayerFormat;
}

if (fileExtension == ".v210" || fileExtension == ".V210")
{
const auto v210Format = PixelFormatYUV(PredefinedPixelFormat::V210);
if (doesPixelFormatMatchFileSize(v210Format, *guessedFrameFormat.frameSize, fileInfo.fileSize))
if (doesPixelFormatMatchFileSize(v210Format, guessedFrameFormat.frameSize, fileInfo.fileSize))
return v210Format;
}

return {};
}

std::optional<PixelFormatYUV> checForNVIndicator(const std::string_view name,
const Size &frameSize,
const std::optional<Size> &frameSize,
const std::optional<std::int64_t> &fileSize)
{
if (name.find("nv12") != std::string::npos)
Expand Down Expand Up @@ -298,20 +301,20 @@ checkFFmpegPixelFormatNames(const std::string &name,
const auto checkPackedFormatsFirst = (guessedFrameFormat.dataLayout == DataLayout::Packed);
if (checkPackedFormatsFirst)
{
if (const auto fmt = testFormatFromSizeAndNamePacked(
name, guessedFrameFormat, subsampling, fileInfo.fileSize))
if (const auto fmt =
testFormatFromSizeAndNamePacked(name, guessedFrameFormat, subsampling, fileInfo.fileSize))
return fmt;
if (const auto fmt = testFormatFromSizeAndNamePlanar(
name, guessedFrameFormat, subsampling, fileInfo.fileSize))
if (const auto fmt =
testFormatFromSizeAndNamePlanar(name, guessedFrameFormat, subsampling, fileInfo.fileSize))
return fmt;
}
else
{
if (const auto fmt = testFormatFromSizeAndNamePlanar(
name, guessedFrameFormat, subsampling, fileInfo.fileSize))
if (const auto fmt =
testFormatFromSizeAndNamePlanar(name, guessedFrameFormat, subsampling, fileInfo.fileSize))
return fmt;
if (const auto fmt = testFormatFromSizeAndNamePacked(
name, guessedFrameFormat, subsampling, fileInfo.fileSize))
if (const auto fmt =
testFormatFromSizeAndNamePacked(name, guessedFrameFormat, subsampling, fileInfo.fileSize))
return fmt;
}

Expand All @@ -320,7 +323,7 @@ checkFFmpegPixelFormatNames(const std::string &name,
{
// Check if the format and the file size match
auto fmt = PixelFormatYUV(Subsampling::YUV_444, 16, PackingOrder::AYUV, false, false);
if (doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileInfo.fileSize))
if (doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileInfo.fileSize))
return fmt;
}

Expand All @@ -330,7 +333,7 @@ checkFFmpegPixelFormatNames(const std::string &name,
if (name.find("gray" + std::to_string(bitDepth) + "le") != std::string::npos)
{
auto fmt = PixelFormatYUV(Subsampling::YUV_400, bitDepth);
if (doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileInfo.fileSize))
if (doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileInfo.fileSize))
return fmt;
}
}
Expand Down Expand Up @@ -363,7 +366,7 @@ checkForSubsamplingIndiatorInName(const std::string &name,
fmt = PixelFormatYUV(subsampling, bitDepth, PackingOrder::YUV);
else
fmt = PixelFormatYUV(subsampling, bitDepth, PlaneOrder::YUV);
if (doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileInfo.fileSize))
if (doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileInfo.fileSize))
return fmt;
}
}
Expand All @@ -373,10 +376,10 @@ checkForSubsamplingIndiatorInName(const std::string &name,
}

std::optional<PixelFormatYUV> ignoreNameAndJustCheckIfSomeBasicFormatsMatchTheFileSize(
const GuessedFrameFormat &guessedFrameFormat, const FileInfoForGuess &fileInfo)
const GuessedFrameFormat &guessedFrameFormat, const FileInfoForGuess &fileInfo)
{
const auto testSubsamplings =
std::vector<Subsampling>({Subsampling::YUV_420, Subsampling::YUV_444, Subsampling::YUV_422});
std::vector<Subsampling>({Subsampling::YUV_420, Subsampling::YUV_444, Subsampling::YUV_422});

std::vector<int> testBitDepths;
if (guessedFrameFormat.bitDepth)
Expand All @@ -389,18 +392,20 @@ std::optional<PixelFormatYUV> ignoreNameAndJustCheckIfSomeBasicFormatsMatchTheFi
for (const auto bd : testBitDepths)
{
auto fmt = PixelFormatYUV(subsampling, bd, PlaneOrder::YUV);
if (doesPixelFormatMatchFileSize(fmt, *guessedFrameFormat.frameSize, fileInfo.fileSize))
if (doesPixelFormatMatchFileSize(fmt, guessedFrameFormat.frameSize, fileInfo.fileSize))
return fmt;
}
}

return {};
}

} // namespace

PixelFormatYUV guessPixelFormatFromSizeAndName(const GuessedFrameFormat &guessedFrameFormat,
const FileInfoForGuess &fileInfo)
{
if (!guessedFrameFormat.frameSize || fileInfo.filename.empty())
if (fileInfo.filename.empty())
return {};

if (const auto pixelFormat = checkSpecificFileExtensions(guessedFrameFormat, fileInfo))
Expand All @@ -410,19 +415,19 @@ PixelFormatYUV guessPixelFormatFromSizeAndName(const GuessedFrameFormat &guessed
{functions::toLower(fileInfo.filename), functions::toLower(fileInfo.parentFolderName)})
{
if (const auto pixelFormat =
checForNVIndicator(name, *guessedFrameFormat.frameSize, fileInfo.fileSize))
checForNVIndicator(name, guessedFrameFormat.frameSize, fileInfo.fileSize))
return *pixelFormat;

if (const auto pixelFormat = checkFFmpegPixelFormatNames(name, guessedFrameFormat, fileInfo))
return *pixelFormat;

if (const auto pixelFormat =
checkForSubsamplingIndiatorInName(name, guessedFrameFormat, fileInfo))
checkForSubsamplingIndiatorInName(name, guessedFrameFormat, fileInfo))
return *pixelFormat;
}

if (const auto pixelFormat =
ignoreNameAndJustCheckIfSomeBasicFormatsMatchTheFileSize(guessedFrameFormat, fileInfo))
ignoreNameAndJustCheckIfSomeBasicFormatsMatchTheFileSize(guessedFrameFormat, fileInfo))
return *pixelFormat;

return {};
Expand Down
17 changes: 16 additions & 1 deletion YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ TEST_P(GuessYUVFormatFromFilenameFrameSizeFileSizeDataLayoutAndBitDepth, TestGue
<< parameters.fileInfoForGuess.fileSize.value_or(-1);
}

constexpr auto BYTES_IRRELEVANT = 123;
constexpr auto BYTES_1080P = 1920 * 1080 * 3 * 6; // 12 frames 420
constexpr auto BYTES_720P = 1280 * 720 * 3 * 6; // 6 frames 444
constexpr auto BYTES_720P_V210 = 1296u * 720 / 6 * 16 * 3; // 3 frames
Expand Down Expand Up @@ -192,7 +193,21 @@ INSTANTIATE_TEST_SUITE_P(
TestParameters({FileInfoForGuess({"VisualAcuityLandolt_3840x2160_60fps_10bit_420p_BT709.yuv",
"",
BYTES_2160p_10bit_420}),
PixelFormatYUV(Subsampling::YUV_420, 10)})
PixelFormatYUV(Subsampling::YUV_420, 10)}),

// Files that do not indicate a frame size. Issue 663.
TestParameters({FileInfoForGuess({"sample_noResolution_something.raw", "", BYTES_IRRELEVANT}),
PixelFormatYUV(Subsampling::YUV_400, 8)}),
TestParameters({FileInfoForGuess({"sample_noResolution_something.v210", "", BYTES_IRRELEVANT}),
PixelFormatYUV(PredefinedPixelFormat::V210)}),
TestParameters({FileInfoForGuess({"sample_noResolution_something.V210", "", BYTES_IRRELEVANT}),
PixelFormatYUV(PredefinedPixelFormat::V210)}),
TestParameters(
{FileInfoForGuess({"sample_noResolution_nv12_something.yuv", "", BYTES_IRRELEVANT}),
PixelFormatYUV(Subsampling::YUV_420, 8, PlaneOrder::YUV, false, {}, true)}),
TestParameters(
{FileInfoForGuess({"sample_noResolution_nv21_something.yuv", "", BYTES_IRRELEVANT}),
PixelFormatYUV(Subsampling::YUV_420, 8, PlaneOrder::YVU, false, {}, true)})

// More tests please :)

Expand Down
Loading