Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix videos with alpha channel #609

Merged
merged 1 commit into from Jan 1, 2021
Merged

Fix videos with alpha channel #609

merged 1 commit into from Jan 1, 2021

Conversation

jonoomph
Copy link
Member

This is a regression from using premultiplied colorspace in Qt. If a video has an alpha channel, we need to convert the RGBA correctly to premultiplied (which is slower), but without the conversion, all the alpha values are wildly wrong.

@codecov
Copy link

codecov bot commented Dec 31, 2020

Codecov Report

Merging #609 (75c4dbb) into develop (2699e7d) will increase coverage by 0.00%.
The diff coverage is 71.42%.

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #609   +/-   ##
========================================
  Coverage    52.31%   52.32%           
========================================
  Files          129      129           
  Lines        10783    10789    +6     
========================================
+ Hits          5641     5645    +4     
- Misses        5142     5144    +2     
Impacted Files Coverage Δ
src/FFmpegReader.cpp 69.20% <66.66%> (-0.04%) ⬇️
src/FFmpegUtilities.h 85.71% <75.00%> (-14.29%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2699e7d...75c4dbb. Read the comment docs.

@jonoomph jonoomph merged commit 0c954b2 into develop Jan 1, 2021
@jonoomph jonoomph deleted the fix-alpha-videos branch January 1, 2021 00:08
f->AddImage(width, height, 4, QImage::Format_RGBA8888_Premultiplied, buffer);
} else {
// Add image with alpha channel (this will be converted to premultipled when needed, but is slower)
f->AddImage(width, height, 4, QImage::Format_RGBA8888, buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. It'd be good to get a test file with alpha channel, if possible, to unit-test this. Presumably someone must have one, if they noticed this in the first place?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've recently learned that there are many formats which can allow an alpha channel, and thus, we can always add a transparent video into our unittests (I like that idea), but it won't test for all possible alpha formats. So, it still leaves the possibility that a format is not working correctly, but I suppose that will just be the case.

Comment on lines +130 to +137
inline static const bool ffmpeg_has_alpha(PixelFormat pix_fmt)
{
if (pix_fmt == AV_PIX_FMT_ARGB || pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || pix_fmt == AV_PIX_FMT_YUVA420P) {
return true;
} else {
return false;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	inline static const bool ffmpeg_has_alpha(PixelFormat pix_fmt)
	{
		if (pix_fmt == AV_PIX_FMT_ARGB || pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || pix_fmt == AV_PIX_FMT_YUVA420P) {
			return true;
		} else {
			return false;
		}
	}

For maintainability this might be better as,

        inline static const bool ffmpeg_has_alpha(PixelFormat pix_fmt) {
            const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(pix_fmt);
            return bool(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
        }

That way it'll support any new pixel formats they add in the future, too. Near as I can tell it'd be compatible with every FFmpeg back to at least 2.4, which is already way farther back than we should worry about going.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the static storage specifier on that may have to come off, if it's going to be taking struct-pointer return values from av_pix_fmt_desc_get() and dereferencing them. But an inline (non-static) function should work fine, I think?

Otherwise, it can always just be added to FFmpegReader.cpp.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonoomph See my previous comment(s), regarding your email question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonoomph Oops. Just realized this had a typo in it, it should've been

        inline static const bool ffmpeg_has_alpha(PixelFormat pix_fmt) {
            const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(pix_fmt);
            return bool(fmt_desc->flags & AV_PIX_FMT_FLAG_ALPHA);
        }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks terrific. I'm gonna test it right now! This is exactly what I was searching for, lol. I have a few transparent videos I've been using to test this, so it should be a quick check.

f->AddImage(width, height, 4, QImage::Format_RGBA8888_Premultiplied, buffer);
} else {
// Add image with alpha channel (this will be converted to premultipled when needed, but is slower)
f->AddImage(width, height, 4, QImage::Format_RGBA8888, buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFmpeg does actually have a premultiply filter (accessible from code as avfilter_get_by_name("premultiply");), which in theory could be imposed into the processing graph to have it produce premultiplied alpha values. But I have a feeling we're better off letting Qt handle that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants