summaryrefslogtreecommitdiff
path: root/src/lib/image.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/image.cc')
-rw-r--r--src/lib/image.cc62
1 files changed, 35 insertions, 27 deletions
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 95de4bc03..d5212fc78 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -190,7 +190,8 @@ Image::crop_source_pointers(Crop crop) const
corrected_crop.bottom = size().height - 4;
}
- std::vector<uint8_t*> pointers(planes());
+ /* FFmpeg memcpy()s this array and assumes it has 4 entries */
+ std::vector<uint8_t*> pointers(4);
for (int c = 0; c < planes(); ++c) {
int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
pointers[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
@@ -286,7 +287,8 @@ Image::crop_scale_window(
round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
);
- std::vector<uint8_t*> scale_out_data(out->planes());
+ /* FFmpeg memcpy()s this array and assumes it has 4 entries */
+ std::vector<uint8_t*> scale_out_data(4);
for (int c = 0; c < out->planes(); ++c) {
int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
@@ -403,15 +405,15 @@ void
Image::yuv_16_black(uint16_t v, bool alpha)
{
memset(data()[0], 0, sample_size(0).height * stride()[0]);
+ auto const uv = copy_16_bit_words_to_64_bit(v);
for (int i = 1; i < 3; ++i) {
auto p = reinterpret_cast<int16_t*>(data()[i]);
int const lines = sample_size(i).height;
+ auto const comp_line_size = line_size()[i];
+ auto const comp_stride = stride()[i] / 2;
for (int y = 0; y < lines; ++y) {
- /* We divide by 2 here because we are writing 2 bytes at a time */
- for (int x = 0; x < line_size()[i] / 2; ++x) {
- p[x] = v;
- }
- p += stride()[i] / 2;
+ fill_memory(p, comp_line_size, uv);
+ p += comp_stride;
}
}
@@ -466,13 +468,12 @@ Image::make_part_black(int const start, int const width)
case AV_PIX_FMT_YUV420P:
{
y_part();
+ auto const uv = copy_bytes_to_64_bit(eight_bit_uv);
for (int i = 1; i < 3; ++i) {
auto p = data()[i];
int const h = sample_size(i).height;
for (int y = 0; y < h; ++y) {
- for (int x = start / 2; x < (start + width) / 2; ++x) {
- p[x] = eight_bit_uv;
- }
+ fill_memory(p + start / 2, width / 2, uv);
p += stride()[i];
}
}
@@ -481,13 +482,12 @@ Image::make_part_black(int const start, int const width)
case AV_PIX_FMT_YUV422P10LE:
{
y_part();
+ auto const uv = copy_16_bit_words_to_64_bit(ten_bit_uv);
for (int i = 1; i < 3; ++i) {
auto p = reinterpret_cast<int16_t*>(data()[i]);
int const h = sample_size(i).height;
for (int y = 0; y < h; ++y) {
- for (int x = start / 2; x < (start + width) / 2; ++x) {
- p[x] = ten_bit_uv;
- }
+ fill_memory(p + start / 2, width, uv);
p += stride()[i] / 2;
}
}
@@ -496,13 +496,12 @@ Image::make_part_black(int const start, int const width)
case AV_PIX_FMT_YUV444P10LE:
{
y_part();
+ auto const uv = copy_16_bit_words_to_64_bit(ten_bit_uv);
for (int i = 1; i < 3; ++i) {
auto p = reinterpret_cast<int16_t*>(data()[i]);
int const h = sample_size(i).height;
for (int y = 0; y < h; ++y) {
- for (int x = start; x < (start + width); ++x) {
- p[x] = ten_bit_uv;
- }
+ fill_memory(p + start, width * 2, uv);
p += stride()[i] / 2;
}
}
@@ -610,17 +609,15 @@ Image::make_black()
case AV_PIX_FMT_UYVY422:
{
- int const Y = sample_size(0).height;
- int const X = line_size()[0];
- uint8_t* p = data()[0];
- for (int y = 0; y < Y; ++y) {
- for (int x = 0; x < X / 4; ++x) {
- *p++ = eight_bit_uv; // Cb
- *p++ = 0; // Y0
- *p++ = eight_bit_uv; // Cr
- *p++ = 0; // Y1
- }
- }
+ fill_memory(
+ data()[0],
+ sample_size(0).height * line_size()[0],
+ /* Cb/Cr is eight_bit_uv, Y0/Y1 is 0 */
+ static_cast<uint64_t>(eight_bit_uv) |
+ (static_cast<uint64_t>(eight_bit_uv) << 16) |
+ (static_cast<uint64_t>(eight_bit_uv) << 32) |
+ (static_cast<uint64_t>(eight_bit_uv) << 48)
+ );
break;
}
@@ -1219,6 +1216,17 @@ Image::bytes_per_pixel(int component) const
}
#endif
+ if (
+ _pixel_format == AV_PIX_FMT_0RGB ||
+ _pixel_format == AV_PIX_FMT_RGB0 ||
+ _pixel_format == AV_PIX_FMT_0BGR ||
+ _pixel_format == AV_PIX_FMT_BGR0) {
+ /* Each pixel has an empty byte which we need to account for when allocating,
+ * otherwise we'll corrupt the image.
+ */
+ bpp[3] = bpp[0];
+ }
+
if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
/* Not planar; sum them up */
return bpp[0] + bpp[1] + bpp[2] + bpp[3];