Skip to content

Commit

Permalink
Fix #360: plane fill wrongly assumed that pitch is rowsize, which is …
Browse files Browse the repository at this point in the history
…not always the case after a Crop
  • Loading branch information
pinterf committed Jun 4, 2023
1 parent 237c450 commit 534d495
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 60 deletions.
7 changes: 4 additions & 3 deletions avs_core/convert/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,20 +649,21 @@ PVideoFrame AddAlphaPlane::GetFrame(int n, IScriptEnvironment* env)
}
else {
// default constant
const int rowsizeA = dst->GetRowSize(PLANAR_A);
const int dst_pitchA = dst->GetPitch(PLANAR_A);
BYTE* dstp_a = dst->GetWritePtr(PLANAR_A);
const int heightA = dst->GetHeight(PLANAR_A);

switch (vi.ComponentSize())
{
case 1:
fill_plane<BYTE>(dstp_a, heightA, dst_pitchA, mask);
fill_plane<BYTE>(dstp_a, heightA, rowsizeA, dst_pitchA, mask);
break;
case 2:
fill_plane<uint16_t>(dstp_a, heightA, dst_pitchA, mask);
fill_plane<uint16_t>(dstp_a, heightA, rowsizeA, dst_pitchA, mask);
break;
case 4:
fill_plane<float>(dstp_a, heightA, dst_pitchA, mask_f);
fill_plane<float>(dstp_a, heightA, rowsizeA, dst_pitchA, mask_f);
break;
}
}
Expand Down
67 changes: 45 additions & 22 deletions avs_core/convert/convert_planar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,47 @@
static ResamplingFunction* getResampler( const char* resampler, AVSValue param1, AVSValue param2, AVSValue param3, IScriptEnvironment* env);

template <typename pixel_t>
void fill_chroma(uint8_t * dstp_u, uint8_t * dstp_v, int height, int pitch, pixel_t val)
void fill_chroma(uint8_t * dstp_u, uint8_t * dstp_v, int height, int row_size, int pitch, pixel_t val)
{
size_t size = height * pitch / sizeof(pixel_t);
std::fill_n(reinterpret_cast<pixel_t*>(dstp_u), size, val);
std::fill_n(reinterpret_cast<pixel_t*>(dstp_v), size, val);
if (pitch == row_size) {
size_t size = height * pitch / sizeof(pixel_t);
std::fill_n(reinterpret_cast<pixel_t*>(dstp_u), size, val);
std::fill_n(reinterpret_cast<pixel_t*>(dstp_v), size, val);
}
else {
size_t size = row_size / sizeof(pixel_t);
for (int i = 0; i < height; i++) {
std::fill_n(reinterpret_cast<pixel_t*>(dstp_u), size, val);
std::fill_n(reinterpret_cast<pixel_t*>(dstp_v), size, val);
dstp_u += pitch;
dstp_v += pitch;
}
}
}

template <typename pixel_t>
void fill_plane(uint8_t * dstp, int height, int pitch, pixel_t val)
void fill_plane(uint8_t * dstp, int height, int row_size, int pitch, pixel_t val)
{
size_t size = height * pitch / sizeof(pixel_t);
std::fill_n(reinterpret_cast<pixel_t*>(dstp), size, val);
if (pitch == row_size) {
size_t size = height * pitch / sizeof(pixel_t);
std::fill_n(reinterpret_cast<pixel_t*>(dstp), size, val);
}
else {
size_t size = row_size / sizeof(pixel_t);
for (int i = 0; i < height; i++) {
std::fill_n(reinterpret_cast<pixel_t*>(dstp), size, val);
dstp += pitch;
}
}
}

// specialize it
template void fill_plane<uint8_t>(uint8_t * dstp, int height, int pitch, uint8_t val);
template void fill_plane<uint16_t>(uint8_t * dstp, int height, int pitch, uint16_t val);
template void fill_plane<float>(uint8_t * dstp, int height, int pitch, float val);
template void fill_chroma<uint8_t>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int pitch, uint8_t val);
template void fill_chroma<uint16_t>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int pitch, uint16_t val);
template void fill_chroma<float>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int pitch, float val);
template void fill_plane<uint8_t>(uint8_t * dstp, int height, int row_size, int pitch, uint8_t val);
template void fill_plane<uint16_t>(uint8_t * dstp, int height, int row_size, int pitch, uint16_t val);
template void fill_plane<float>(uint8_t * dstp, int height, int row_size, int pitch, float val);
template void fill_chroma<uint8_t>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int row_size, int pitch, uint8_t val);
template void fill_chroma<uint16_t>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int row_size, int pitch, uint16_t val);
template void fill_chroma<float>(uint8_t * dstp_u, uint8_t * dstp_v, int height, int row_size, int pitch, float val);

ConvertToY::ConvertToY(PClip src, const char *matrix_name, IScriptEnvironment* env) : GenericVideoFilter(src) {
yuy2_input = blit_luma_only = packed_rgb_input = planar_rgb_input = false;
Expand Down Expand Up @@ -866,6 +886,7 @@ PVideoFrame __stdcall ConvertYUV444ToRGB::GetFrame(int n, IScriptEnvironment* en
if (targetHasAlpha) {
dstpA = dst->GetWritePtr(PLANAR_A);
int heightA = dst->GetHeight(PLANAR_A);
int rowsizeA = dst->GetRowSize(PLANAR_A);
int dst_pitchA = dst->GetPitch(PLANAR_A);
// simple copy
if(src->GetRowSize(PLANAR_A)) // vi.IsYUVA() no-no! vi is already the target video type
Expand All @@ -875,13 +896,13 @@ PVideoFrame __stdcall ConvertYUV444ToRGB::GetFrame(int n, IScriptEnvironment* en
switch (vi.ComponentSize())
{
case 1:
fill_plane<BYTE>(dstpA, heightA, dst_pitchA, 255);
fill_plane<BYTE>(dstpA, heightA, rowsizeA, dst_pitchA, 255);
break;
case 2:
fill_plane<uint16_t>(dstpA, heightA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
fill_plane<uint16_t>(dstpA, heightA, rowsizeA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
break;
case 4:
fill_plane<float>(dstpA, heightA, dst_pitchA, 1.0f);
fill_plane<float>(dstpA, heightA, rowsizeA, dst_pitchA, 1.0f);
break;
}
}
Expand Down Expand Up @@ -1407,6 +1428,7 @@ PVideoFrame __stdcall ConvertToPlanarGeneric::GetFrame(int n, IScriptEnvironment
src->GetRowSize(PLANAR_Y_ALIGNED), src->GetHeight(PLANAR_Y));

// alpha. if pitch is zero -> no alpha channel
const int rowsizeA = dst->GetRowSize(PLANAR_A);
const int dst_pitchA = dst->GetPitch(PLANAR_A);
BYTE* dstp_a = (dst_pitchA == 0) ? nullptr : dst->GetWritePtr(PLANAR_A);
const int heightA = dst->GetHeight(PLANAR_A);
Expand All @@ -1421,13 +1443,13 @@ PVideoFrame __stdcall ConvertToPlanarGeneric::GetFrame(int n, IScriptEnvironment
switch (vi.ComponentSize())
{
case 1:
fill_plane<BYTE>(dstp_a, heightA, dst_pitchA, 255);
fill_plane<BYTE>(dstp_a, heightA, rowsizeA, dst_pitchA, 255);
break;
case 2:
fill_plane<uint16_t>(dstp_a, heightA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
fill_plane<uint16_t>(dstp_a, heightA, rowsizeA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
break;
case 4:
fill_plane<float>(dstp_a, heightA, dst_pitchA, 1.0f);
fill_plane<float>(dstp_a, heightA, rowsizeA, dst_pitchA, 1.0f);
break;
}
}
Expand All @@ -1436,20 +1458,21 @@ PVideoFrame __stdcall ConvertToPlanarGeneric::GetFrame(int n, IScriptEnvironment
BYTE* dstp_u = dst->GetWritePtr(PLANAR_U);
BYTE* dstp_v = dst->GetWritePtr(PLANAR_V);
const int height = dst->GetHeight(PLANAR_U);
const int rowsizeUV = dst->GetRowSize(PLANAR_U);
const int dst_pitch = dst->GetPitch(PLANAR_U);

if (Yinput) {
switch (vi.ComponentSize())
{
case 1:
fill_chroma<BYTE>(dstp_u, dstp_v, height, dst_pitch, 0x80);
fill_chroma<BYTE>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, 0x80);
break;
case 2:
fill_chroma<uint16_t>(dstp_u, dstp_v, height, dst_pitch, 1 << (vi.BitsPerComponent() - 1));
fill_chroma<uint16_t>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, 1 << (vi.BitsPerComponent() - 1));
break;
case 4:
const float half = 0.0f;
fill_chroma<float>(dstp_u, dstp_v, height, dst_pitch, half);
fill_chroma<float>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, half);
break;
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions avs_core/convert/convert_planar.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@

// useful functions
template <typename pixel_t>
void fill_chroma(uint8_t * dstp_u, uint8_t * dstp_v, int height, int pitch, pixel_t val);
void fill_chroma(uint8_t * dstp_u, uint8_t * dstp_v, int height, int row_size, int pitch, pixel_t val);

template <typename pixel_t>
void fill_plane(uint8_t * dstp, int height, int pitch, pixel_t val);
void fill_plane(uint8_t * dstp, int height, int row_size, int pitch, pixel_t val);


class ConvertToY : public GenericVideoFilter
Expand Down
7 changes: 4 additions & 3 deletions avs_core/filters/exprfilter/exprfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4624,6 +4624,7 @@ PVideoFrame __stdcall Exprfilter::GetFrame(int n, IScriptEnvironment *env) {
}
else if (d.plane[plane] == poFill) { // avs+
uint8_t *dstp = dst->GetWritePtr(plane_enum_d);
const int dst_rowsize = dst->GetRowSize(plane_enum_d);
const int dst_stride = dst->GetPitch(plane_enum_d);
const int h = dst->GetHeight(plane_enum_d);

Expand All @@ -4637,11 +4638,11 @@ PVideoFrame __stdcall Exprfilter::GetFrame(int n, IScriptEnvironment *env) {
}

if(bits_per_pixel == 8)
fill_plane<BYTE>(dstp, h, dst_stride, val_i);
fill_plane<BYTE>(dstp, h, dst_rowsize, dst_stride, val_i);
else if(bits_per_pixel <= 16)
fill_plane<uint16_t>(dstp, h, dst_stride, val_i);
fill_plane<uint16_t>(dstp, h, dst_rowsize, dst_stride, val_i);
else // 32 bit float
fill_plane<float>(dstp, h, dst_stride, val);
fill_plane<float>(dstp, h, dst_rowsize, dst_stride, val);

} // plane modes
} // for planes
Expand Down
7 changes: 4 additions & 3 deletions avs_core/filters/greyscale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,23 @@ PVideoFrame Greyscale::GetFrame(int n, IScriptEnvironment* env)
BYTE* dstp_u = frame->GetWritePtr(PLANAR_U);
BYTE* dstp_v = frame->GetWritePtr(PLANAR_V);
const int height = frame->GetHeight(PLANAR_U);
const int rowsizeUV = frame->GetRowSize(PLANAR_U);
const int dst_pitch = frame->GetPitch(PLANAR_U);
switch (vi.ComponentSize())
{
case 1:
fill_chroma<BYTE>(dstp_u, dstp_v, height, dst_pitch, 0x80); // in convert_planar
fill_chroma<BYTE>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, 0x80); // in convert_planar
break;
case 2:
fill_chroma<uint16_t>(dstp_u, dstp_v, height, dst_pitch, 1 << (vi.BitsPerComponent() - 1));
fill_chroma<uint16_t>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, 1 << (vi.BitsPerComponent() - 1));
break;
case 4:
#ifdef FLOAT_CHROMA_IS_HALF_CENTERED
const float shift = 0.5f;
#else
const float shift = 0.0f;
#endif
fill_chroma<float>(dstp_u, dstp_v, height, dst_pitch, shift);
fill_chroma<float>(dstp_u, dstp_v, height, rowsizeUV, dst_pitch, shift);
break;
}
return frame;
Expand Down
14 changes: 8 additions & 6 deletions avs_core/filters/histogram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,25 +597,27 @@ PVideoFrame Histogram::DrawModeLuma(int n, IScriptEnvironment* env) {
auto dstp_u = src->GetWritePtr(PLANAR_U);
auto dstp_v = src->GetWritePtr(PLANAR_V);
auto height_uv = src->GetHeight(PLANAR_U);
auto rowsize_uv = src->GetRowSize(PLANAR_U);
auto pitch_uv = src->GetPitch(PLANAR_U);
if (bits_per_pixel == 8)
fill_chroma<uint8_t>(dstp_u, dstp_v, height_uv, pitch_uv, 128);
fill_chroma<uint8_t>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 128);
else if (bits_per_pixel <= 16)
fill_chroma<uint16_t>(dstp_u, dstp_v, height_uv, pitch_uv, 128 << (bits_per_pixel - 8));
fill_chroma<uint16_t>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 128 << (bits_per_pixel - 8));
else // 32)
fill_chroma<float>(dstp_u, dstp_v, height_uv, pitch_uv, 0.0f);
fill_chroma<float>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 0.0f);

// alpha
if (vi.NumComponents() == 4) {
auto dstp_a = src->GetWritePtr(PLANAR_A);
auto height_a = src->GetHeight(PLANAR_A);
auto rowsize_a = src->GetRowSize(PLANAR_A);
auto pitch_a = src->GetPitch(PLANAR_A);
if (bits_per_pixel == 8)
fill_plane<uint8_t>(dstp_a, height_a, pitch_a, 255);
fill_plane<uint8_t>(dstp_a, height_a, rowsize_a, pitch_a, 255);
else if (bits_per_pixel <= 16)
fill_plane<uint16_t>(dstp_a, height_a, pitch_a, (1 << bits_per_pixel) - 1);
fill_plane<uint16_t>(dstp_a, height_a, rowsize_a, pitch_a, (1 << bits_per_pixel) - 1);
else // 32)
fill_chroma<float>(dstp_u, dstp_v, height_uv, pitch_uv, 1.0f);
fill_plane<float>(dstp_a, height_a, rowsize_a, pitch_a, 1.0f);
}
}
}
Expand Down
35 changes: 20 additions & 15 deletions avs_core/filters/layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,20 +459,21 @@ PVideoFrame ResetMask::GetFrame(int n, IScriptEnvironment* env)
env->MakeWritable(&f);

if (vi.IsPlanarRGBA() || vi.IsYUVA()) {
const int dst_rowsizeA = f->GetRowSize(PLANAR_A);
const int dst_pitchA = f->GetPitch(PLANAR_A);
BYTE* dstp_a = f->GetWritePtr(PLANAR_A);
const int heightA = f->GetHeight(PLANAR_A);

switch (vi.ComponentSize())
{
case 1:
fill_plane<BYTE>(dstp_a, heightA, dst_pitchA, mask);
fill_plane<BYTE>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, mask);
break;
case 2:
fill_plane<uint16_t>(dstp_a, heightA, dst_pitchA, mask);
fill_plane<uint16_t>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, mask);
break;
case 4:
fill_plane<float>(dstp_a, heightA, dst_pitchA, mask_f);
fill_plane<float>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, mask_f);
break;
}
return f;
Expand Down Expand Up @@ -1152,15 +1153,16 @@ PVideoFrame ShowChannel::GetFrame(int n, IScriptEnvironment* env)
// fill chroma neutral
if (!vi.IsY())
{
int uvrowsize = dst->GetRowSize(PLANAR_U);
int uvpitch = dst->GetPitch(PLANAR_U);
int dstheight = dst->GetHeight(PLANAR_U);
BYTE* dstp_u = dst->GetWritePtr(PLANAR_U);
BYTE* dstp_v = dst->GetWritePtr(PLANAR_V);
switch (pixelsize) {
case 1: fill_chroma<BYTE>(dstp_u, dstp_v, dstheight, uvpitch, (BYTE)0x80); break;
case 2: fill_chroma<uint16_t>(dstp_u, dstp_v, dstheight, uvpitch, 1 << (vi.BitsPerComponent() - 1)); break;
case 1: fill_chroma<BYTE>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, (BYTE)0x80); break;
case 2: fill_chroma<uint16_t>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, 1 << (vi.BitsPerComponent() - 1)); break;
case 4:
fill_chroma<float>(dstp_u, dstp_v, dstheight, uvpitch, chroma_center_f);
fill_chroma<float>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, chroma_center_f);
break;
}
}
Expand Down Expand Up @@ -1297,14 +1299,15 @@ PVideoFrame ShowChannel::GetFrame(int n, IScriptEnvironment* env)
// fill UV with neutral
if (!vi.IsY())
{
int uvrowsize = dst->GetRowSize(PLANAR_U);
int uvpitch = dst->GetPitch(PLANAR_U);
int dstheight = dst->GetHeight(PLANAR_U);
BYTE* dstp_u = dst->GetWritePtr(PLANAR_U);
BYTE* dstp_v = dst->GetWritePtr(PLANAR_V);
switch (pixelsize) {
case 1: fill_chroma<uint8_t>(dstp_u, dstp_v, dstheight, uvpitch, (uint8_t)0x80); break;
case 2: fill_chroma<uint16_t>(dstp_u, dstp_v, dstheight, uvpitch, 1 << (vi.BitsPerComponent() - 1)); break;
case 4: fill_chroma<float>(dstp_u, dstp_v, dstheight, uvpitch, chroma_center_f); break;
case 1: fill_chroma<uint8_t>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, (uint8_t)0x80); break;
case 2: fill_chroma<uint16_t>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, 1 << (vi.BitsPerComponent() - 1)); break;
case 4: fill_chroma<float>(dstp_u, dstp_v, dstheight, uvrowsize, uvpitch, chroma_center_f); break;
}
}
}
Expand Down Expand Up @@ -1358,6 +1361,7 @@ PVideoFrame ShowChannel::GetFrame(int n, IScriptEnvironment* env)
}
if (target_hasalpha) {
// fill alpha with transparent
const int dst_rowsizeA = dst->GetRowSize(PLANAR_A);
const int dst_pitchA = dst->GetPitch(PLANAR_A);
BYTE* dstp_a = dst->GetWritePtr(PLANAR_A);
const int heightA = dst->GetHeight(PLANAR_A);
Expand All @@ -1370,13 +1374,13 @@ PVideoFrame ShowChannel::GetFrame(int n, IScriptEnvironment* env)
switch (vi.ComponentSize())
{
case 1:
fill_plane<uint8_t>(dstp_a, heightA, dst_pitchA, 0xFF);
fill_plane<uint8_t>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, 0xFF);
break;
case 2:
fill_plane<uint16_t>(dstp_a, heightA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
fill_plane<uint16_t>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, (1 << vi.BitsPerComponent()) - 1);
break;
case 4:
fill_plane<float>(dstp_a, heightA, dst_pitchA, 1.0f);
fill_plane<float>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, 1.0f);
break;
}
}
Expand Down Expand Up @@ -1724,20 +1728,21 @@ PVideoFrame MergeRGB::GetFrame(int n, IScriptEnvironment* env)
if (p == 3 && !alpha) {
// fill alpha, but not ARGB mode

const int dst_rowsizeA = dst->GetRowSize(PLANAR_A);
const int dst_pitchA = dst->GetPitch(PLANAR_A);
BYTE* dstp_a = dst->GetWritePtr(PLANAR_A);
const int heightA = dst->GetHeight(PLANAR_A);
// unlike in other filters, default alpha value here is 0 instead of max transparent 255
switch (vi.ComponentSize())
{
case 1:
fill_plane<uint8_t>(dstp_a, heightA, dst_pitchA, 0);
fill_plane<uint8_t>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, 0);
break;
case 2:
fill_plane<uint16_t>(dstp_a, heightA, dst_pitchA, 0);
fill_plane<uint16_t>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, 0);
break;
case 4:
fill_plane<float>(dstp_a, heightA, dst_pitchA, 0.0f);
fill_plane<float>(dstp_a, heightA, dst_rowsizeA, dst_pitchA, 0.0f);
break;
}
}
Expand Down
Loading

0 comments on commit 534d495

Please sign in to comment.