Commit 718044dc authored by Michael Niedermayer's avatar Michael Niedermayer

avutil/pixdesc: Add av_write_image_line2(), av_read_image_line2()

This is needed because of 32bit float formats (which are difficult to
store in 16bits)

This also fixes undefined behavior found by fate
Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent a5d98da4
...@@ -15,6 +15,9 @@ libavutil: 2017-10-21 ...@@ -15,6 +15,9 @@ libavutil: 2017-10-21
API changes, most recent first: API changes, most recent first:
2018-XX-XX - xxxxxxxxxx - lavu 56.21.100 - pixdesc.h
Add av_read_image_line2(), av_write_image_line2()
2018-10-24 - xxxxxxxxxx - lavu 56.20.100 - frame.h 2018-10-24 - xxxxxxxxxx - lavu 56.20.100 - frame.h
Add AV_FRAME_DATA_S12M_TIMECODE Add AV_FRAME_DATA_S12M_TIMECODE
......
...@@ -31,19 +31,22 @@ ...@@ -31,19 +31,22 @@
#include "intreadwrite.h" #include "intreadwrite.h"
#include "version.h" #include "version.h"
void av_read_image_line(uint16_t *dst, void av_read_image_line2(void *dst,
const uint8_t *data[4], const int linesize[4], const uint8_t *data[4], const int linesize[4],
const AVPixFmtDescriptor *desc, const AVPixFmtDescriptor *desc,
int x, int y, int c, int w, int x, int y, int c, int w,
int read_pal_component) int read_pal_component,
int dst_element_size)
{ {
AVComponentDescriptor comp = desc->comp[c]; AVComponentDescriptor comp = desc->comp[c];
int plane = comp.plane; int plane = comp.plane;
int depth = comp.depth; int depth = comp.depth;
int mask = (1 << depth) - 1; unsigned mask = (1ULL << depth) - 1;
int shift = comp.shift; int shift = comp.shift;
int step = comp.step; int step = comp.step;
int flags = desc->flags; int flags = desc->flags;
uint16_t *dst16 = dst;
uint32_t *dst32 = dst;
if (flags & AV_PIX_FMT_FLAG_BITSTREAM) { if (flags & AV_PIX_FMT_FLAG_BITSTREAM) {
int skip = x * step + comp.offset; int skip = x * step + comp.offset;
...@@ -57,38 +60,56 @@ void av_read_image_line(uint16_t *dst, ...@@ -57,38 +60,56 @@ void av_read_image_line(uint16_t *dst,
shift -= step; shift -= step;
p -= shift >> 3; p -= shift >> 3;
shift &= 7; shift &= 7;
*dst++ = val; if (dst_element_size == 4) *dst32++ = val;
else *dst16++ = val;
} }
} else { } else {
const uint8_t *p = data[plane] + y * linesize[plane] + const uint8_t *p = data[plane] + y * linesize[plane] +
x * step + comp.offset; x * step + comp.offset;
int is_8bit = shift + depth <= 8; int is_8bit = shift + depth <= 8;
int is_16bit= shift + depth <=16;
if (is_8bit) if (is_8bit)
p += !!(flags & AV_PIX_FMT_FLAG_BE); p += !!(flags & AV_PIX_FMT_FLAG_BE);
while (w--) { while (w--) {
int val = is_8bit ? *p : unsigned val;
flags & AV_PIX_FMT_FLAG_BE ? AV_RB16(p) : AV_RL16(p); if (is_8bit) val = *p;
else if(is_16bit) val = flags & AV_PIX_FMT_FLAG_BE ? AV_RB16(p) : AV_RL16(p);
else val = flags & AV_PIX_FMT_FLAG_BE ? AV_RB32(p) : AV_RL32(p);
val = (val >> shift) & mask; val = (val >> shift) & mask;
if (read_pal_component) if (read_pal_component)
val = data[1][4 * val + c]; val = data[1][4 * val + c];
p += step; p += step;
*dst++ = val; if (dst_element_size == 4) *dst32++ = val;
else *dst16++ = val;
} }
} }
} }
void av_write_image_line(const uint16_t *src, void av_read_image_line(uint16_t *dst,
const uint8_t *data[4], const int linesize[4],
const AVPixFmtDescriptor *desc,
int x, int y, int c, int w,
int read_pal_component)
{
av_read_image_line2(dst, data, linesize, desc,x, y, c, w,
read_pal_component,
2);
}
void av_write_image_line2(const void *src,
uint8_t *data[4], const int linesize[4], uint8_t *data[4], const int linesize[4],
const AVPixFmtDescriptor *desc, const AVPixFmtDescriptor *desc,
int x, int y, int c, int w) int x, int y, int c, int w, int src_element_size)
{ {
AVComponentDescriptor comp = desc->comp[c]; AVComponentDescriptor comp = desc->comp[c];
int plane = comp.plane; int plane = comp.plane;
int depth = comp.depth; int depth = comp.depth;
int step = comp.step; int step = comp.step;
int flags = desc->flags; int flags = desc->flags;
const uint32_t *src32 = src;
const uint16_t *src16 = src;
if (flags & AV_PIX_FMT_FLAG_BITSTREAM) { if (flags & AV_PIX_FMT_FLAG_BITSTREAM) {
int skip = x * step + comp.offset; int skip = x * step + comp.offset;
...@@ -96,7 +117,7 @@ void av_write_image_line(const uint16_t *src, ...@@ -96,7 +117,7 @@ void av_write_image_line(const uint16_t *src,
int shift = 8 - depth - (skip & 7); int shift = 8 - depth - (skip & 7);
while (w--) { while (w--) {
*p |= *src++ << shift; *p |= (src_element_size == 4 ? *src32++ : *src16++) << shift;
shift -= step; shift -= step;
p -= shift >> 3; p -= shift >> 3;
shift &= 7; shift &= 7;
...@@ -109,17 +130,28 @@ void av_write_image_line(const uint16_t *src, ...@@ -109,17 +130,28 @@ void av_write_image_line(const uint16_t *src,
if (shift + depth <= 8) { if (shift + depth <= 8) {
p += !!(flags & AV_PIX_FMT_FLAG_BE); p += !!(flags & AV_PIX_FMT_FLAG_BE);
while (w--) { while (w--) {
*p |= (*src++ << shift); *p |= ((src_element_size == 4 ? *src32++ : *src16++) << shift);
p += step; p += step;
} }
} else { } else {
while (w--) { while (w--) {
if (flags & AV_PIX_FMT_FLAG_BE) { unsigned s = (src_element_size == 4 ? *src32++ : *src16++);
uint16_t val = AV_RB16(p) | (*src++ << shift); if (shift + depth <= 16) {
AV_WB16(p, val); if (flags & AV_PIX_FMT_FLAG_BE) {
uint16_t val = AV_RB16(p) | (s << shift);
AV_WB16(p, val);
} else {
uint16_t val = AV_RL16(p) | (s << shift);
AV_WL16(p, val);
}
} else { } else {
uint16_t val = AV_RL16(p) | (*src++ << shift); if (flags & AV_PIX_FMT_FLAG_BE) {
AV_WL16(p, val); uint32_t val = AV_RB32(p) | (s << shift);
AV_WB32(p, val);
} else {
uint32_t val = AV_RL32(p) | (s << shift);
AV_WL32(p, val);
}
} }
p += step; p += step;
} }
...@@ -127,6 +159,14 @@ void av_write_image_line(const uint16_t *src, ...@@ -127,6 +159,14 @@ void av_write_image_line(const uint16_t *src,
} }
} }
void av_write_image_line(const uint16_t *src,
uint8_t *data[4], const int linesize[4],
const AVPixFmtDescriptor *desc,
int x, int y, int c, int w)
{
av_write_image_line2(src, data, linesize, desc, x, y, c, w, 2);
}
#if FF_API_PLUS1_MINUS1 #if FF_API_PLUS1_MINUS1
FF_DISABLE_DEPRECATION_WARNINGS FF_DISABLE_DEPRECATION_WARNINGS
#endif #endif
......
...@@ -343,7 +343,13 @@ char *av_get_pix_fmt_string(char *buf, int buf_size, ...@@ -343,7 +343,13 @@ char *av_get_pix_fmt_string(char *buf, int buf_size,
* format writes the values corresponding to the palette * format writes the values corresponding to the palette
* component c in data[1] to dst, rather than the palette indexes in * component c in data[1] to dst, rather than the palette indexes in
* data[0]. The behavior is undefined if the format is not paletted. * data[0]. The behavior is undefined if the format is not paletted.
* @param dst_element_size size of elements in dst array (2 or 4 byte)
*/ */
void av_read_image_line2(void *dst, const uint8_t *data[4],
const int linesize[4], const AVPixFmtDescriptor *desc,
int x, int y, int c, int w, int read_pal_component,
int dst_element_size);
void av_read_image_line(uint16_t *dst, const uint8_t *data[4], void av_read_image_line(uint16_t *dst, const uint8_t *data[4],
const int linesize[4], const AVPixFmtDescriptor *desc, const int linesize[4], const AVPixFmtDescriptor *desc,
int x, int y, int c, int w, int read_pal_component); int x, int y, int c, int w, int read_pal_component);
...@@ -361,7 +367,12 @@ void av_read_image_line(uint16_t *dst, const uint8_t *data[4], ...@@ -361,7 +367,12 @@ void av_read_image_line(uint16_t *dst, const uint8_t *data[4],
* @param y the vertical coordinate of the first pixel to write * @param y the vertical coordinate of the first pixel to write
* @param w the width of the line to write, that is the number of * @param w the width of the line to write, that is the number of
* values to write to the image line * values to write to the image line
* @param src_element_size size of elements in src array (2 or 4 byte)
*/ */
void av_write_image_line2(const void *src, uint8_t *data[4],
const int linesize[4], const AVPixFmtDescriptor *desc,
int x, int y, int c, int w, int src_element_size);
void av_write_image_line(const uint16_t *src, uint8_t *data[4], void av_write_image_line(const uint16_t *src, uint8_t *data[4],
const int linesize[4], const AVPixFmtDescriptor *desc, const int linesize[4], const AVPixFmtDescriptor *desc,
int x, int y, int c, int w); int x, int y, int c, int w);
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
*/ */
#define LIBAVUTIL_VERSION_MAJOR 56 #define LIBAVUTIL_VERSION_MAJOR 56
#define LIBAVUTIL_VERSION_MINOR 20 #define LIBAVUTIL_VERSION_MINOR 21
#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
......
pixdesc-grayf32be 381c8d0f19d286809b91cd6e6c0048ab pixdesc-grayf32be 047d17c62f2e712c6547e4227b427303
pixdesc-grayf32le 381c8d0f19d286809b91cd6e6c0048ab pixdesc-grayf32le cdedfdbaa4e192b9f2c84092f955fb4b
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment