Quoting wm4 (2017-07-16 12:41:59)
> Black isn't always just memset(ptr, 0, size). Limited YUV in particular
> requires relatively non-obvious values, and filling a frame with
> repeating 0 bytes is disallowed in some contexts. With component sizes
> larger than 8 or packed YUV, this can become relatively complicated. So
> having a generic function for this seems helpful.
> 
> In order to handle the complex cases in a generic way without destroying
> performance, this code attempts to compute a black pixel, and then uses
> that value to clear the image data quickly by using a function like
> memset.
> 
> Common cases like yuv410p10 or rgba can't be handled with a simple
> memset, so there is some code to fill memory with 2 and 4 byte patterns.
> For the remaining cases, a generic slow fallback is used. This code
> should probably have a 8 byte case too, to deal with rgba64.
> 
> ---
> Fixed:
> - simply reduction to memset code
> - fix monow/monob handling
> - change alpha range
> - add 8 bytes path (untested)
> - allow dst_data==NULL with special semantics
> TODO: APIchanges, version bumps, FATE test
> ---
>  libavutil/imgutils.c | 167 
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  libavutil/imgutils.h |  27 +++++++++
>  2 files changed, 194 insertions(+)
> 
> diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
> index 84abb11656..c43185ccff 100644
> --- a/libavutil/imgutils.c
> +++ b/libavutil/imgutils.c
> @@ -435,3 +435,170 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
>  
>      return size;
>  }
> +
> +// Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
> +// bytes are repeated until dst_size is reached. If dst_size is unaligned 
> (i.e.
> +// dst_size%clear_size!=0), the remaining data will be filled with the 
> beginning
> +// of the clear data only.
> +static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear,
> +                         size_t clear_size)
> +{
> +    size_t pos = 0;
> +    int same = 1;
> +    int i;
> +
> +    if (!clear_size)
> +        return;
> +
> +    // Reduce to memset() if possible.
> +    for (i = 0; i < clear_size; i++) {
> +        if (clear[i] != clear[0]) {
> +            same = 0;
> +            break;
> +        }
> +    }
> +    if (same)
> +        clear_size = 1;
> +
> +    if (clear_size == 1) {
> +        memset(dst, clear[0], dst_size);
> +        dst_size = 0;
> +    } else if (clear_size == 2) {
> +        uint16_t val = AV_RN16(clear);
> +        for (; dst_size >= 2; dst_size -= 2) {
> +            AV_WN16(dst, val);
> +            dst += 2;
> +        }
> +    } else if (clear_size == 4) {
> +        uint32_t val = AV_RN32(clear);
> +        for (; dst_size >= 4; dst_size -= 4) {
> +            AV_WN32(dst, val);
> +            dst += 4;
> +        }
> +    } else if (clear_size == 8) {
> +        uint32_t val = AV_RN64(clear);
> +        for (; dst_size >= 8; dst_size -= 8) {
> +            AV_WN64(dst, val);
> +            dst += 8;
> +        }
> +    }
> +
> +    for (; dst_size; dst_size--)
> +        *dst++ = clear[pos++ % clear_size];
> +}
> +
> +// Maximum size in bytes of a plane element (usually a pixel, or multiple 
> pixels
> +// if it's a subsampled packed format).
> +#define MAX_PIXEL_SIZE 32
> +
> +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t 
> dst_linesize[4],
> +                        enum AVPixelFormat pix_fmt, enum AVColorRange range,
> +                        int width, int height)
> +{
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
> +    int nb_planes = av_pix_fmt_count_planes(pix_fmt);
> +    // A pixel on each plane, with a value that represents black.
> +    // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
> +    uint8_t pixel[4][MAX_PIXEL_SIZE] = {0}; // clear padding with 0
> +    int pixel_size[4] = {0};

The naming is a bit confusing, since those are not individual pixels,
but blocks of "maximum step size". How about block_val / block_size for
those two.

Otherwise looks ok-ish. Not exactly pretty, but that's probably
unavoidable for such code.

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to