* qatar/master: FATE: add tests for targa ARM: fix Thumb-mode simple_idct_arm ARM: 4-byte align start of all asm functions rgb2rgb: rgb12to15() swscale-test: fix stack overread. swscale: fix invalid conversions and memory problems. cabac: split cabac.h into declarations and function definitions cabac: Mark ff_h264_mps_state array as static, it is only used within cabac.c. cabac: Remove ff_h264_lps_state array. Conflicts: libswscale/rgb2rgb.h libswscale/swscale_unscaled.c tests/fate/image.mak Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.10
@@ -68,6 +68,7 @@ ELF .size \name, . - \name | |||||
.purgem endfunc | .purgem endfunc | ||||
.endm | .endm | ||||
.text | .text | ||||
.align 2 | |||||
.if \export | .if \export | ||||
.global EXTERN_ASM\name | .global EXTERN_ASM\name | ||||
EXTERN_ASM\name: | EXTERN_ASM\name: | ||||
@@ -491,8 +491,8 @@ __end_bef_a_evaluation: | |||||
bal __end_a_evaluation | bal __end_a_evaluation | ||||
__constant_ptr__: @@ see #defines at the beginning of the source code for values. | |||||
.align | .align | ||||
__constant_ptr__: @@ see #defines at the beginning of the source code for values. | |||||
.word W1 | .word W1 | ||||
.word W2 | .word W2 | ||||
.word W3 | .word W3 | ||||
@@ -29,6 +29,7 @@ | |||||
#include "libavutil/common.h" | #include "libavutil/common.h" | ||||
#include "get_bits.h" | #include "get_bits.h" | ||||
#include "cabac.h" | #include "cabac.h" | ||||
#include "cabac_functions.h" | |||||
static const uint8_t lps_range[64][4]= { | static const uint8_t lps_range[64][4]= { | ||||
{128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205}, | {128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205}, | ||||
@@ -51,8 +52,7 @@ static const uint8_t lps_range[64][4]= { | |||||
uint8_t ff_h264_mlps_state[4*64]; | uint8_t ff_h264_mlps_state[4*64]; | ||||
uint8_t ff_h264_lps_range[4*2*64]; | uint8_t ff_h264_lps_range[4*2*64]; | ||||
uint8_t ff_h264_lps_state[2*64]; | |||||
uint8_t ff_h264_mps_state[2*64]; | |||||
static uint8_t h264_mps_state[2 * 64]; | |||||
static const uint8_t mps_state[64]= { | static const uint8_t mps_state[64]= { | ||||
1, 2, 3, 4, 5, 6, 7, 8, | 1, 2, 3, 4, 5, 6, 7, 8, | ||||
@@ -141,9 +141,9 @@ void ff_init_cabac_states(CABACContext *c){ | |||||
} | } | ||||
ff_h264_mlps_state[128+2*i+0]= | ff_h264_mlps_state[128+2*i+0]= | ||||
ff_h264_mps_state[2*i+0]= 2*mps_state[i]+0; | |||||
h264_mps_state[2 * i + 0] = 2 * mps_state[i] + 0; | |||||
ff_h264_mlps_state[128+2*i+1]= | ff_h264_mlps_state[128+2*i+1]= | ||||
ff_h264_mps_state[2*i+1]= 2*mps_state[i]+1; | |||||
h264_mps_state[2 * i + 1] = 2 * mps_state[i] + 1; | |||||
if( i ){ | if( i ){ | ||||
ff_h264_lps_state[2*i+0]= | ff_h264_lps_state[2*i+0]= | ||||
@@ -196,11 +196,10 @@ static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ | |||||
if(bit == ((*state)&1)){ | if(bit == ((*state)&1)){ | ||||
c->range -= RangeLPS; | c->range -= RangeLPS; | ||||
*state= ff_h264_mps_state[*state]; | |||||
*state = h264_mps_state[*state]; | |||||
}else{ | }else{ | ||||
c->low += c->range - RangeLPS; | c->low += c->range - RangeLPS; | ||||
c->range = RangeLPS; | c->range = RangeLPS; | ||||
*state= ff_h264_lps_state[*state]; | |||||
} | } | ||||
renorm_cabac_encoder(c); | renorm_cabac_encoder(c); | ||||
@@ -27,13 +27,10 @@ | |||||
#ifndef AVCODEC_CABAC_H | #ifndef AVCODEC_CABAC_H | ||||
#define AVCODEC_CABAC_H | #define AVCODEC_CABAC_H | ||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include "put_bits.h" | #include "put_bits.h" | ||||
//#undef NDEBUG | |||||
#include <assert.h> | |||||
#define CABAC_BITS 16 | #define CABAC_BITS 16 | ||||
#define CABAC_MASK ((1<<CABAC_BITS)-1) | #define CABAC_MASK ((1<<CABAC_BITS)-1) | ||||
@@ -47,136 +44,8 @@ typedef struct CABACContext{ | |||||
PutBitContext pb; | PutBitContext pb; | ||||
}CABACContext; | }CABACContext; | ||||
extern uint8_t ff_h264_mlps_state[4*64]; | |||||
extern uint8_t ff_h264_lps_range[4*2*64]; ///< rangeTabLPS | |||||
extern uint8_t ff_h264_mps_state[2*64]; ///< transIdxMPS | |||||
extern uint8_t ff_h264_lps_state[2*64]; ///< transIdxLPS | |||||
extern const uint8_t ff_h264_norm_shift[512]; | |||||
#if ARCH_X86 | |||||
# include "x86/cabac.h" | |||||
#endif | |||||
void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size); | void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size); | ||||
void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size); | void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size); | ||||
void ff_init_cabac_states(CABACContext *c); | void ff_init_cabac_states(CABACContext *c); | ||||
static void refill(CABACContext *c){ | |||||
#if CABAC_BITS == 16 | |||||
c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); | |||||
#else | |||||
c->low+= c->bytestream[0]<<1; | |||||
#endif | |||||
c->low -= CABAC_MASK; | |||||
c->bytestream+= CABAC_BITS/8; | |||||
} | |||||
static inline void renorm_cabac_decoder_once(CABACContext *c){ | |||||
int shift= (uint32_t)(c->range - 0x100)>>31; | |||||
c->range<<= shift; | |||||
c->low <<= shift; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
} | |||||
#ifndef get_cabac_inline | |||||
static void refill2(CABACContext *c){ | |||||
int i, x; | |||||
x= c->low ^ (c->low-1); | |||||
i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)]; | |||||
x= -CABAC_MASK; | |||||
#if CABAC_BITS == 16 | |||||
x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); | |||||
#else | |||||
x+= c->bytestream[0]<<1; | |||||
#endif | |||||
c->low += x<<i; | |||||
c->bytestream+= CABAC_BITS/8; | |||||
} | |||||
static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){ | |||||
int s = *state; | |||||
int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s]; | |||||
int bit, lps_mask; | |||||
c->range -= RangeLPS; | |||||
lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31; | |||||
c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; | |||||
c->range += (RangeLPS - c->range) & lps_mask; | |||||
s^=lps_mask; | |||||
*state= (ff_h264_mlps_state+128)[s]; | |||||
bit= s&1; | |||||
lps_mask= ff_h264_norm_shift[c->range]; | |||||
c->range<<= lps_mask; | |||||
c->low <<= lps_mask; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill2(c); | |||||
return bit; | |||||
} | |||||
#endif | |||||
static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){ | |||||
return get_cabac_inline(c,state); | |||||
} | |||||
static int av_unused get_cabac(CABACContext *c, uint8_t * const state){ | |||||
return get_cabac_inline(c,state); | |||||
} | |||||
static int av_unused get_cabac_bypass(CABACContext *c){ | |||||
int range; | |||||
c->low += c->low; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
range= c->range<<(CABAC_BITS+1); | |||||
if(c->low < range){ | |||||
return 0; | |||||
}else{ | |||||
c->low -= range; | |||||
return 1; | |||||
} | |||||
} | |||||
#ifndef get_cabac_bypass_sign | |||||
static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ | |||||
int range, mask; | |||||
c->low += c->low; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
range= c->range<<(CABAC_BITS+1); | |||||
c->low -= range; | |||||
mask= c->low >> 31; | |||||
range &= mask; | |||||
c->low += range; | |||||
return (val^mask)-mask; | |||||
} | |||||
#endif | |||||
/** | |||||
* | |||||
* @return the number of bytes read or 0 if no end | |||||
*/ | |||||
static int av_unused get_cabac_terminate(CABACContext *c){ | |||||
c->range -= 2; | |||||
if(c->low < c->range<<(CABAC_BITS+1)){ | |||||
renorm_cabac_decoder_once(c); | |||||
return 0; | |||||
}else{ | |||||
return c->bytestream - c->bytestream_start; | |||||
} | |||||
} | |||||
#endif /* AVCODEC_CABAC_H */ | #endif /* AVCODEC_CABAC_H */ |
@@ -0,0 +1,160 @@ | |||||
/* | |||||
* H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder | |||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> | |||||
* | |||||
* This file is part of Libav. | |||||
* | |||||
* Libav is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public | |||||
* License as published by the Free Software Foundation; either | |||||
* version 2.1 of the License, or (at your option) any later version. | |||||
* | |||||
* Libav is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
* Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public | |||||
* License along with Libav; if not, write to the Free Software | |||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
*/ | |||||
/** | |||||
* @file | |||||
* Context Adaptive Binary Arithmetic Coder inline functions | |||||
*/ | |||||
#ifndef AVCODEC_CABAC_FUNCTIONS_H | |||||
#define AVCODEC_CABAC_FUNCTIONS_H | |||||
#include <stdint.h> | |||||
#include "cabac.h" | |||||
#include "config.h" | |||||
#if ARCH_X86 | |||||
# include "x86/cabac.h" | |||||
#endif | |||||
extern const uint8_t ff_h264_norm_shift[512]; | |||||
extern uint8_t ff_h264_mlps_state[4*64]; | |||||
extern uint8_t ff_h264_lps_range[4*2*64]; ///< rangeTabLPS | |||||
static void refill(CABACContext *c){ | |||||
#if CABAC_BITS == 16 | |||||
c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); | |||||
#else | |||||
c->low+= c->bytestream[0]<<1; | |||||
#endif | |||||
c->low -= CABAC_MASK; | |||||
c->bytestream+= CABAC_BITS/8; | |||||
} | |||||
static inline void renorm_cabac_decoder_once(CABACContext *c){ | |||||
int shift= (uint32_t)(c->range - 0x100)>>31; | |||||
c->range<<= shift; | |||||
c->low <<= shift; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
} | |||||
#ifndef get_cabac_inline | |||||
static void refill2(CABACContext *c){ | |||||
int i, x; | |||||
x= c->low ^ (c->low-1); | |||||
i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)]; | |||||
x= -CABAC_MASK; | |||||
#if CABAC_BITS == 16 | |||||
x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); | |||||
#else | |||||
x+= c->bytestream[0]<<1; | |||||
#endif | |||||
c->low += x<<i; | |||||
c->bytestream+= CABAC_BITS/8; | |||||
} | |||||
static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){ | |||||
int s = *state; | |||||
int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s]; | |||||
int bit, lps_mask; | |||||
c->range -= RangeLPS; | |||||
lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31; | |||||
c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; | |||||
c->range += (RangeLPS - c->range) & lps_mask; | |||||
s^=lps_mask; | |||||
*state= (ff_h264_mlps_state+128)[s]; | |||||
bit= s&1; | |||||
lps_mask= ff_h264_norm_shift[c->range]; | |||||
c->range<<= lps_mask; | |||||
c->low <<= lps_mask; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill2(c); | |||||
return bit; | |||||
} | |||||
#endif | |||||
static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){ | |||||
return get_cabac_inline(c,state); | |||||
} | |||||
static int av_unused get_cabac(CABACContext *c, uint8_t * const state){ | |||||
return get_cabac_inline(c,state); | |||||
} | |||||
static int av_unused get_cabac_bypass(CABACContext *c){ | |||||
int range; | |||||
c->low += c->low; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
range= c->range<<(CABAC_BITS+1); | |||||
if(c->low < range){ | |||||
return 0; | |||||
}else{ | |||||
c->low -= range; | |||||
return 1; | |||||
} | |||||
} | |||||
#ifndef get_cabac_bypass_sign | |||||
static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ | |||||
int range, mask; | |||||
c->low += c->low; | |||||
if(!(c->low & CABAC_MASK)) | |||||
refill(c); | |||||
range= c->range<<(CABAC_BITS+1); | |||||
c->low -= range; | |||||
mask= c->low >> 31; | |||||
range &= mask; | |||||
c->low += range; | |||||
return (val^mask)-mask; | |||||
} | |||||
#endif | |||||
/** | |||||
* | |||||
* @return the number of bytes read or 0 if no end | |||||
*/ | |||||
static int av_unused get_cabac_terminate(CABACContext *c){ | |||||
c->range -= 2; | |||||
if(c->low < c->range<<(CABAC_BITS+1)){ | |||||
renorm_cabac_decoder_once(c); | |||||
return 0; | |||||
}else{ | |||||
return c->bytestream - c->bytestream_start; | |||||
} | |||||
} | |||||
#endif /* AVCODEC_CABAC_FUNCTIONS_H */ |
@@ -30,6 +30,8 @@ | |||||
#include "libavutil/imgutils.h" | #include "libavutil/imgutils.h" | ||||
#include "libavutil/opt.h" | #include "libavutil/opt.h" | ||||
#include "internal.h" | #include "internal.h" | ||||
#include "cabac.h" | |||||
#include "cabac_functions.h" | |||||
#include "dsputil.h" | #include "dsputil.h" | ||||
#include "avcodec.h" | #include "avcodec.h" | ||||
#include "mpegvideo.h" | #include "mpegvideo.h" | ||||
@@ -43,8 +45,6 @@ | |||||
#include "vdpau_internal.h" | #include "vdpau_internal.h" | ||||
#include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
#include "cabac.h" | |||||
//#undef NDEBUG | //#undef NDEBUG | ||||
#include <assert.h> | #include <assert.h> | ||||
@@ -28,6 +28,9 @@ | |||||
#define CABAC 1 | #define CABAC 1 | ||||
#define UNCHECKED_BITSTREAM_READER 1 | #define UNCHECKED_BITSTREAM_READER 1 | ||||
#include "config.h" | |||||
#include "cabac.h" | |||||
#include "cabac_functions.h" | |||||
#include "internal.h" | #include "internal.h" | ||||
#include "dsputil.h" | #include "dsputil.h" | ||||
#include "avcodec.h" | #include "avcodec.h" | ||||
@@ -36,7 +39,6 @@ | |||||
#include "h264_mvpred.h" | #include "h264_mvpred.h" | ||||
#include "golomb.h" | #include "golomb.h" | ||||
#include "cabac.h" | |||||
#if ARCH_X86 | #if ARCH_X86 | ||||
#include "x86/h264_i386.h" | #include "x86/h264_i386.h" | ||||
#endif | #endif | ||||
@@ -183,6 +183,25 @@ void rgb16tobgr32(const uint8_t *src, uint8_t *dst, int src_size) | |||||
} | } | ||||
} | } | ||||
void rgb12to15(const uint8_t *src, uint8_t *dst, int src_size) | |||||
{ | |||||
const uint16_t *end; | |||||
uint16_t *d = (uint16_t *)dst; | |||||
const uint16_t *s = (const uint16_t *)src; | |||||
uint16_t rgb, r, g, b; | |||||
end = s + src_size / 2; | |||||
while (s < end) { | |||||
rgb = *s++; | |||||
r = rgb & 0xF00; | |||||
g = rgb & 0x0F0; | |||||
b = rgb & 0x00F; | |||||
r = (r << 3) | ((r & 0x800) >> 1); | |||||
g = (g << 2) | ((g & 0x080) >> 2); | |||||
b = (b << 1) | ( b >> 3); | |||||
*d++ = r | g | b; | |||||
} | |||||
} | |||||
void rgb16to24(const uint8_t *src, uint8_t *dst, int src_size) | void rgb16to24(const uint8_t *src, uint8_t *dst, int src_size) | ||||
{ | { | ||||
const uint16_t *end; | const uint16_t *end; | ||||
@@ -63,6 +63,7 @@ void rgb15to24(const uint8_t *src, uint8_t *dst, int src_size); | |||||
void rgb15tobgr16(const uint8_t *src, uint8_t *dst, int src_size); | void rgb15tobgr16(const uint8_t *src, uint8_t *dst, int src_size); | ||||
void rgb15tobgr15(const uint8_t *src, uint8_t *dst, int src_size); | void rgb15tobgr15(const uint8_t *src, uint8_t *dst, int src_size); | ||||
void rgb12tobgr12(const uint8_t *src, uint8_t *dst, int src_size); | void rgb12tobgr12(const uint8_t *src, uint8_t *dst, int src_size); | ||||
void rgb12to15(const uint8_t *src, uint8_t *dst, int src_size); | |||||
void shuffle_bytes_0321(const uint8_t *src, uint8_t *dst, int src_size); | void shuffle_bytes_0321(const uint8_t *src, uint8_t *dst, int src_size); | ||||
void shuffle_bytes_1230(const uint8_t *src, uint8_t *dst, int src_size); | void shuffle_bytes_1230(const uint8_t *src, uint8_t *dst, int src_size); | ||||
@@ -340,8 +340,8 @@ int main(int argc, char **argv) | |||||
enum PixelFormat srcFormat = PIX_FMT_NONE; | enum PixelFormat srcFormat = PIX_FMT_NONE; | ||||
enum PixelFormat dstFormat = PIX_FMT_NONE; | enum PixelFormat dstFormat = PIX_FMT_NONE; | ||||
uint8_t *rgb_data = av_malloc(W * H * 4); | uint8_t *rgb_data = av_malloc(W * H * 4); | ||||
uint8_t *rgb_src[3] = { rgb_data, NULL, NULL }; | |||||
int rgb_stride[3] = { 4 * W, 0, 0 }; | |||||
uint8_t *rgb_src[4] = { rgb_data, NULL, NULL, NULL }; | |||||
int rgb_stride[4] = { 4 * W, 0, 0, 0 }; | |||||
uint8_t *data = av_malloc(4 * W * H); | uint8_t *data = av_malloc(4 * W * H); | ||||
uint8_t *src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; | uint8_t *src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; | ||||
int stride[4] = { W, W, W, W }; | int stride[4] = { W, W, W, W }; | ||||
@@ -396,17 +396,22 @@ static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStr | |||||
) | ) | ||||
/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ | /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ | ||||
static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], | |||||
int srcSliceY, int srcSliceH, uint8_t *dst[], | |||||
int dstStride[]) | |||||
typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int); | |||||
static rgbConvFn findRgbConvFn(SwsContext *c) | |||||
{ | { | ||||
const enum PixelFormat srcFormat = c->srcFormat; | const enum PixelFormat srcFormat = c->srcFormat; | ||||
const enum PixelFormat dstFormat = c->dstFormat; | const enum PixelFormat dstFormat = c->dstFormat; | ||||
const int srcBpp = (c->srcFormatBpp + 7) >> 3; | |||||
const int dstBpp = (c->dstFormatBpp + 7) >> 3; | |||||
const int srcId = c->srcFormatBpp; | const int srcId = c->srcFormatBpp; | ||||
const int dstId = c->dstFormatBpp; | const int dstId = c->dstFormatBpp; | ||||
void (*conv)(const uint8_t *src, uint8_t *dst, int src_size) = NULL; | |||||
rgbConvFn conv = NULL; | |||||
#define IS_NOT_NE(bpp, fmt) \ | |||||
(((bpp + 7) >> 3) == 2 && \ | |||||
(!(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_BE) != !HAVE_BIGENDIAN)) | |||||
/* if this is non-native rgb444/555/565, don't handle it here. */ | |||||
if (IS_NOT_NE(srcId, srcFormat) || IS_NOT_NE(dstId, dstFormat)) | |||||
return NULL; | |||||
#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) | #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) | ||||
@@ -428,6 +433,7 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], | |||||
if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || | if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || | ||||
(isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { | (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { | ||||
switch (srcId | (dstId << 16)) { | switch (srcId | (dstId << 16)) { | ||||
case 0x000F000C: conv = rgb12to15; break; | |||||
case 0x000F0010: conv = rgb16to15; break; | case 0x000F0010: conv = rgb16to15; break; | ||||
case 0x000F0018: conv = rgb24to15; break; | case 0x000F0018: conv = rgb24to15; break; | ||||
case 0x000F0020: conv = rgb32to15; break; | case 0x000F0020: conv = rgb32to15; break; | ||||
@@ -463,6 +469,21 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], | |||||
} | } | ||||
} | } | ||||
return conv; | |||||
} | |||||
/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ | |||||
static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], | |||||
int srcSliceY, int srcSliceH, uint8_t *dst[], | |||||
int dstStride[]) | |||||
{ | |||||
const enum PixelFormat srcFormat = c->srcFormat; | |||||
const enum PixelFormat dstFormat = c->dstFormat; | |||||
const int srcBpp = (c->srcFormatBpp + 7) >> 3; | |||||
const int dstBpp = (c->dstFormatBpp + 7) >> 3; | |||||
rgbConvFn conv = findRgbConvFn(c); | |||||
if (!conv) { | if (!conv) { | ||||
av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", | av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", | ||||
av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); | av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); | ||||
@@ -694,6 +715,8 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], | |||||
} else { | } else { | ||||
if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) | if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) | ||||
length *= 2; | length *= 2; | ||||
else if (!av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1) | |||||
length >>= 3; // monowhite/black | |||||
for (i = 0; i < height; i++) { | for (i = 0; i < height; i++) { | ||||
memcpy(dstPtr, srcPtr, length); | memcpy(dstPtr, srcPtr, length); | ||||
srcPtr += srcStride[plane]; | srcPtr += srcStride[plane]; | ||||
@@ -748,24 +771,8 @@ void ff_get_unscaled_swscale(SwsContext *c) | |||||
c->swScale = bgr24ToYv12Wrapper; | c->swScale = bgr24ToYv12Wrapper; | ||||
/* RGB/BGR -> RGB/BGR (no dither needed forms) */ | /* RGB/BGR -> RGB/BGR (no dither needed forms) */ | ||||
if ( isAnyRGB(srcFormat) | |||||
&& isAnyRGB(dstFormat) | |||||
&& srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8 | |||||
&& srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8 | |||||
&& srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4 | |||||
&& srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4 | |||||
&& srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE | |||||
&& srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE | |||||
&& srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK | |||||
&& srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE | |||||
&& srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE | |||||
&& srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE | |||||
&& srcFormat != PIX_FMT_BGR48LE && dstFormat != PIX_FMT_BGR48LE | |||||
&& srcFormat != PIX_FMT_BGR48BE && dstFormat != PIX_FMT_BGR48BE | |||||
&& (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))) | |||||
&& (!(av_pix_fmt_descriptors[srcFormat].flags & PIX_FMT_BE) == !HAVE_BIGENDIAN || (c->srcFormatBpp+7)/8!=2) | |||||
&& (!(av_pix_fmt_descriptors[dstFormat].flags & PIX_FMT_BE) == !HAVE_BIGENDIAN || (c->dstFormatBpp+7)/8!=2) | |||||
) | |||||
if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c) | |||||
&& (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) | |||||
c->swScale= rgbToRgbWrapper; | c->swScale= rgbToRgbWrapper; | ||||
#define isByteRGB(f) (\ | #define isByteRGB(f) (\ | ||||
@@ -30,6 +30,33 @@ fate-sunraster-24bit-raw: CMD = framecrc -i $(SAMPLES)/sunraster/lena-24bit-raw. | |||||
FATE_IMAGE += fate-sunraster-24bit-rle | FATE_IMAGE += fate-sunraster-24bit-rle | ||||
fate-sunraster-24bit-rle: CMD = framecrc -i $(SAMPLES)/sunraster/lena-24bit-rle.sun | fate-sunraster-24bit-rle: CMD = framecrc -i $(SAMPLES)/sunraster/lena-24bit-rle.sun | ||||
FATE_TESTS += $(FATE_IMAGE) | FATE_TESTS += $(FATE_IMAGE) | ||||
fate-image: $(FATE_IMAGE) | fate-image: $(FATE_IMAGE) | ||||
FATE_TARGA = CBW8 \ | |||||
CTC16 \ | |||||
CTC24 \ | |||||
CTC32 \ | |||||
UBW8 \ | |||||
UTC16 \ | |||||
UTC24 \ | |||||
UTC32 | |||||
FATE_TARGA := $(FATE_TARGA:%=fate-targa-conformance-%) \ | |||||
fate-targa-top-to-bottom | |||||
FATE_TESTS += $(FATE_TARGA) | |||||
fate-targa: $(FATE_TARGA) | |||||
fate-targa-conformance-CBW8: CMD = framecrc -i $(SAMPLES)/targa-conformance/CBW8.TGA | |||||
# fate-targa-conformance-CCM8: CMD = framecrc -i $(SAMPLES)/targa-conformance/CCM8.TGA | |||||
fate-targa-conformance-CTC16: CMD = framecrc -i $(SAMPLES)/targa-conformance/CTC16.TGA | |||||
fate-targa-conformance-CTC24: CMD = framecrc -i $(SAMPLES)/targa-conformance/CTC24.TGA | |||||
fate-targa-conformance-CTC32: CMD = framecrc -i $(SAMPLES)/targa-conformance/CTC32.TGA | |||||
fate-targa-conformance-UBW8: CMD = framecrc -i $(SAMPLES)/targa-conformance/UBW8.TGA | |||||
# fate-targa-conformance-UCM8: CMD = framecrc -i $(SAMPLES)/targa-conformance/UCM8.TGA | |||||
fate-targa-conformance-UTC16: CMD = framecrc -i $(SAMPLES)/targa-conformance/UTC16.TGA | |||||
fate-targa-conformance-UTC24: CMD = framecrc -i $(SAMPLES)/targa-conformance/UTC24.TGA | |||||
fate-targa-conformance-UTC32: CMD = framecrc -i $(SAMPLES)/targa-conformance/UTC32.TGA | |||||
fate-targa-top-to-bottom: CMD = framecrc -i $(SAMPLES)/targa/lena-top-to-bottom.tga |
@@ -0,0 +1 @@ | |||||
0, 0, 16384, 0x267e21ef |
@@ -0,0 +1 @@ | |||||
0, 0, 32768, 0xa6b3d20d |
@@ -0,0 +1 @@ | |||||
0, 0, 49152, 0xaca4bc29 |
@@ -0,0 +1 @@ | |||||
0, 0, 65536, 0xcf98bc29 |
@@ -0,0 +1 @@ | |||||
0, 0, 16384, 0x267e21ef |
@@ -0,0 +1 @@ | |||||
0, 0, 32768, 0xa6b3d20d |
@@ -0,0 +1 @@ | |||||
0, 0, 49152, 0xaca4bc29 |
@@ -0,0 +1 @@ | |||||
0, 0, 65536, 0xcf98bc29 |
@@ -0,0 +1 @@ | |||||
0, 0, 196608, 0xb29ec51a |