@ -25,6 +25,8 @@
*/
# include "avcodec.h"
# include "dsputil.h"
# include "get_bits.h"
# include "internal.h"
# include "raw.h"
# include "libavutil/avassert.h"
@ -43,6 +45,10 @@ typedef struct RawVideoContext {
int is_yuv2 ;
int is_lt_16bpp ; // 16bpp pixfmt and bits_per_coded_sample < 16
int tff ;
DSPContext dsp ;
void * bitstream_buf ;
unsigned int bitstream_buf_size ;
} RawVideoContext ;
static const AVOption options [ ] = {
@ -106,6 +112,8 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx)
RawVideoContext * context = avctx - > priv_data ;
const AVPixFmtDescriptor * desc ;
ff_dsputil_init ( & context - > dsp , avctx ) ;
if ( avctx - > codec_tag = = MKTAG ( ' r ' , ' a ' , ' w ' , ' ' )
| | avctx - > codec_tag = = MKTAG ( ' N ' , ' O ' , ' 1 ' , ' 6 ' ) )
avctx - > pix_fmt = avpriv_find_pix_fmt ( pix_fmt_bps_mov ,
@ -113,7 +121,7 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx)
else if ( avctx - > codec_tag = = MKTAG ( ' W ' , ' R ' , ' A ' , ' W ' ) )
avctx - > pix_fmt = avpriv_find_pix_fmt ( pix_fmt_bps_avi ,
avctx - > bits_per_coded_sample ) ;
else if ( avctx - > codec_tag )
else if ( avctx - > codec_tag & & ( avctx - > codec_tag & 0xFFFFFF ) ! = MKTAG ( ' B ' , ' I ' , ' T ' , 0 ) )
avctx - > pix_fmt = avpriv_find_pix_fmt ( ff_raw_pix_fmt_tags , avctx - > codec_tag ) ;
else if ( avctx - > pix_fmt = = AV_PIX_FMT_NONE & & avctx - > bits_per_coded_sample )
avctx - > pix_fmt = avpriv_find_pix_fmt ( pix_fmt_bps_avi ,
@ -168,6 +176,34 @@ static void flip(AVCodecContext *avctx, AVPicture *picture)
picture - > linesize [ 0 ] * = - 1 ;
}
/*
* Scale sample to 16 - bit resolution
*/
# define SCALE16(x, bits) (((x) << (16 - (bits))) | ((x) >> (2 * (bits) - 16)))
/**
* Scale buffer to 16 bits per coded sample resolution
*/
# define MKSCALE16(name, r16, w16) \
static void name ( AVCodecContext * avctx , uint8_t * dst , const uint8_t * buf , int buf_size , int packed ) \
{ \
int i ; \
if ( ! packed ) { \
for ( i = 0 ; i + 1 < buf_size ; i + = 2 ) \
w16 ( dst + i , SCALE16 ( r16 ( buf + i ) , avctx - > bits_per_coded_sample ) ) ; \
} else { \
GetBitContext gb ; \
init_get_bits ( & gb , buf , buf_size * 8 ) ; \
for ( i = 0 ; i < avctx - > width * avctx - > height ; i + + ) { \
int sample = get_bits ( & gb , avctx - > bits_per_coded_sample ) ; \
w16 ( dst + i * 2 , SCALE16 ( sample , avctx - > bits_per_coded_sample ) ) ; \
} \
} \
}
MKSCALE16 ( scale16be , AV_RB16 , AV_WB16 )
MKSCALE16 ( scale16le , AV_RL16 , AV_WL16 )
static int raw_decode ( AVCodecContext * avctx , void * data , int * got_frame ,
AVPacket * avpkt )
{
@ -227,15 +263,28 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
}
buf = dst ;
} else if ( context - > is_lt_16bpp ) {
int i ;
uint8_t * dst = frame - > buf [ 0 ] - > data ;
if ( desc - > flags & AV_PIX_FMT_FLAG_BE ) {
for ( i = 0 ; i + 1 < buf_size ; i + = 2 )
AV_WB16 ( dst + i , AV_RB16 ( buf + i ) < < ( 16 - avctx - > bits_per_coded_sample ) ) ;
} else {
for ( i = 0 ; i + 1 < buf_size ; i + = 2 )
AV_WL16 ( dst + i , AV_RL16 ( buf + i ) < < ( 16 - avctx - > bits_per_coded_sample ) ) ;
int packed = ( avctx - > codec_tag & 0xFFFFFF ) = = MKTAG ( ' B ' , ' I ' , ' T ' , 0 ) ;
int swap = avctx - > codec_tag > > 24 ;
if ( packed & & swap ) {
av_fast_padded_malloc ( & context - > bitstream_buf , & context - > bitstream_buf_size , buf_size ) ;
if ( ! context - > bitstream_buf )
return AVERROR ( ENOMEM ) ;
if ( swap = = 16 )
context - > dsp . bswap16_buf ( context - > bitstream_buf , ( const uint16_t * ) buf , buf_size / 2 ) ;
else if ( swap = = 32 )
context - > dsp . bswap_buf ( context - > bitstream_buf , ( const uint32_t * ) buf , buf_size / 4 ) ;
else
return AVERROR_INVALIDDATA ;
buf = context - > bitstream_buf ;
}
if ( desc - > flags & AV_PIX_FMT_FLAG_BE )
scale16be ( avctx , dst , buf , buf_size , packed ) ;
else
scale16le ( avctx , dst , buf , buf_size , packed ) ;
buf = dst ;
} else if ( need_copy ) {
memcpy ( frame - > buf [ 0 ] - > data , buf , buf_size ) ;
@ -247,7 +296,7 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
buf + = buf_size - context - > frame_size ;
len = context - > frame_size - ( avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ? AVPALETTE_SIZE : 0 ) ;
if ( buf_size < len ) {
if ( buf_size < len & & ( avctx - > codec_tag & 0xFFFFFF ) ! = MKTAG ( ' B ' , ' I ' , ' T ' , 0 ) ) {
av_log ( avctx , AV_LOG_ERROR , " Invalid buffer size, packet size %d < expected frame_size %d \n " , buf_size , len ) ;
av_buffer_unref ( & frame - > buf [ 0 ] ) ;
return AVERROR ( EINVAL ) ;