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
Frame: Fix interlaced AddImage #418
Conversation
src/Frame.cpp
Outdated
if (image == new_image || image->size() != image->size() || image->format() != image->format()) | ||
ret=true; | ||
if (ret) | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignoring the weird use of the ret
boolean here, what's up with those conditions!?!?
if ( image->size() != image->size() )
!? if ( image->format() != image->format() )
!?
Clearly the first was supposed to be image->size() != new_image->size()
, so I fixed it to that. The second was presumably supposed to be image->format() != new_image->format()
, but since we can format-convert with QImage, instead of doing that test I convert new_image
to the format of image
if it doesn't match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignoring the weird use of the
ret
boolean here,
(Aha, it seems there's a reason for that, due to OpenMP's weird semantics.)
const unsigned char *pixels = image->constBits(); | ||
unsigned char *pixels = image->bits(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
s are nice and all, when appropriate, but when you're modifying the pixels in the buffer I'm pretty sure we're not supposed to use constBits()
since it suppresses Qt's copy-on-write handling for shared QImage
buffers.
for (int row = start; row < image->height(); row += 2) { | ||
memcpy((unsigned char *) pixels, new_pixels + (row * image->bytesPerLine()), image->bytesPerLine()); | ||
new_pixels += image->bytesPerLine(); | ||
int offset = row * image->bytesPerLine(); | ||
memcpy(pixels + offset, new_pixels + offset, image->bytesPerLine()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where things really break.
The way that loop was previously written, it would go through every other row (odd or even) in new_pixels
, and copy that row's data to the first row of pixels
— every time! Nothing was ever offsetting the pixels
location to advance it by the row
stride, and nothing would have ever written to any part of pixels
(and therefore image
) beyond the first scanline/row.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Oh, yeah — the telltale cast on pixels
— to cast away its const
status, which it shouldn't have had in the first place — is also fun, in the previous code.)
491dc13
to
f4f1bb5
Compare
f4f1bb5
to
86bfa2f
Compare
(Needless to say, this part of the code could really use some unit tests to ensure that my new version is actually correct. But it almost can't be any worse.) |
Codecov Report
@@ Coverage Diff @@
## develop #418 +/- ##
===========================================
- Coverage 42.37% 42.37% -0.01%
===========================================
Files 129 129
Lines 13276 13278 +2
===========================================
Hits 5626 5626
- Misses 7650 7652 +2
Continue to review full report at Codecov.
|
Good catch! LGTM. This method just disintegrated over time. |
Reading through the
openshot::Frame
code trying to debug the image-format switch, I came across the mess that was the current version of this method:It's a good thing it's only called from one spot in the FrameMapper code, because holy crap is it broken! Over the years, changes piled up that just kept moving it further away from what it was supposed to be doing, and because there are no unit tests for interlaced video, they were never noticed. I'm not surprised our interlaced support is broken! I don't know that this will fix it, but it should at least un-break this particular method.
I had to go way, way back in the git history to find the ImageMagick version that it evolved from. Here's the original code, for comparison:
I'll leave some inline comments below about the new version (prior to this PR), for comparison purposes.