@ -21,6 +21,8 @@
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*
* yuva , gray , 4 : 4 : 4 , 4 : 1 : 1 , 4 : 1 : 0 and > 8 bit per sample support sponsored by NOA
*/
/**
@ -88,16 +90,16 @@ static const unsigned char classic_add_chroma[256] = {
6 , 12 , 8 , 10 , 7 , 9 , 6 , 4 , 6 , 2 , 2 , 3 , 3 , 3 , 3 , 2 ,
} ;
static int read_len_table ( uint8_t * dst , GetBitContext * gb )
static int read_len_table ( uint8_t * dst , GetBitContext * gb , int n )
{
int i , val , repeat ;
for ( i = 0 ; i < 256 ; ) {
for ( i = 0 ; i < n ; ) {
repeat = get_bits ( gb , 3 ) ;
val = get_bits ( gb , 5 ) ;
if ( repeat = = 0 )
repeat = get_bits ( gb , 8 ) ;
if ( i + repeat > 256 | | get_bits_left ( gb ) < 0 ) {
if ( i + repeat > n | | get_bits_left ( gb ) < 0 ) {
av_log ( NULL , AV_LOG_ERROR , " Error reading huffman table \n " ) ;
return - 1 ;
}
@ -118,19 +120,19 @@ static int generate_joint_tables(HYuvContext *s)
int p , i , y , u ;
for ( p = 0 ; p < 4 ; p + + ) {
int p0 = s - > version > 2 ? p : 0 ;
for ( i = y = 0 ; y < 256 ; y + + ) {
for ( i = y = 0 ; y < s - > n ; y + + ) {
int len0 = s - > len [ p0 ] [ y ] ;
int limit = VLC_BITS - len0 ;
if ( limit < = 0 | | ! len0 )
continue ;
for ( u = 0 ; u < 256 ; u + + ) {
for ( u = 0 ; u < s - > n ; u + + ) {
int len1 = s - > len [ p ] [ u ] ;
if ( len1 > limit | | ! len1 )
continue ;
av_assert0 ( i < ( 1 < < VLC_BITS ) ) ;
len [ i ] = len0 + len1 ;
bits [ i ] = ( s - > bits [ p0 ] [ y ] < < len1 ) + s - > bits [ p ] [ u ] ;
symbols [ i ] = ( y < < 8 ) + u ;
symbols [ i ] = ( y < < 8 ) + u ; //FIXME
if ( symbols [ i ] ! = 0xffff ) // reserved to mean "invalid"
i + + ;
}
@ -199,13 +201,13 @@ static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
count = 1 + s - > alpha + 2 * s - > chroma ;
for ( i = 0 ; i < count ; i + + ) {
if ( read_len_table ( s - > len [ i ] , & gb ) < 0 )
if ( read_len_table ( s - > len [ i ] , & gb , s - > n ) < 0 )
return - 1 ;
if ( ff_huffyuv_generate_bits_table ( s - > bits [ i ] , s - > len [ i ] ) < 0 ) {
if ( ff_huffyuv_generate_bits_table ( s - > bits [ i ] , s - > len [ i ] , s - > n ) < 0 ) {
return - 1 ;
}
ff_free_vlc ( & s - > vlc [ i ] ) ;
if ( ( ret = init_vlc ( & s - > vlc [ i ] , VLC_BITS , 256 , s - > len [ i ] , 1 , 1 ,
if ( ( ret = init_vlc ( & s - > vlc [ i ] , VLC_BITS , s - > n , s - > len [ i ] , 1 , 1 ,
s - > bits [ i ] , 4 , 4 , 0 ) ) < 0 )
return ret ;
}
@ -224,12 +226,12 @@ static int read_old_huffman_tables(HYuvContext *s)
init_get_bits ( & gb , classic_shift_luma ,
classic_shift_luma_table_size * 8 ) ;
if ( read_len_table ( s - > len [ 0 ] , & gb ) < 0 )
if ( read_len_table ( s - > len [ 0 ] , & gb , 256 ) < 0 )
return - 1 ;
init_get_bits ( & gb , classic_shift_chroma ,
classic_shift_chroma_table_size * 8 ) ;
if ( read_len_table ( s - > len [ 1 ] , & gb ) < 0 )
if ( read_len_table ( s - > len [ 1 ] , & gb , 256 ) < 0 )
return - 1 ;
for ( i = 0 ; i < 256 ; i + + ) s - > bits [ 0 ] [ i ] = classic_add_luma [ i ] ;
@ -397,6 +399,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
case 0x675 :
avctx - > pix_fmt = AV_PIX_FMT_YUV420P ;
break ;
case 0x695 :
avctx - > pix_fmt = AV_PIX_FMT_YUV420P10 ;
break ;
case 0x67A :
avctx - > pix_fmt = AV_PIX_FMT_YUV410P ;
break ;
@ -409,6 +414,11 @@ static av_cold int decode_init(AVCodecContext *avctx)
case 0x775 :
avctx - > pix_fmt = AV_PIX_FMT_YUVA420P ;
break ;
case 0x795 :
avctx - > pix_fmt = AV_PIX_FMT_YUVA420P10 ;
break ;
default :
return AVERROR_INVALIDDATA ;
}
}
@ -499,19 +509,35 @@ static void decode_422_bitstream(HYuvContext *s, int count)
dst1 = get_vlc2 ( & s - > gb , s - > vlc [ plane ] . table , VLC_BITS , 3 ) ; \
} \
}
# define READ_2PIX_PLANE16(dst0, dst1, plane){\
dst0 = get_vlc2 ( & s - > gb , s - > vlc [ plane ] . table , VLC_BITS , 3 ) ; \
dst1 = get_vlc2 ( & s - > gb , s - > vlc [ plane ] . table , VLC_BITS , 3 ) ; \
}
static void decode_plane_bitstream ( HYuvContext * s , int count , int plane )
{
int i ;
count / = 2 ;
if ( count > = ( get_bits_left ( & s - > gb ) ) / ( 31 * 2 ) ) {
for ( i = 0 ; i < count & & get_bits_left ( & s - > gb ) > 0 ; i + + ) {
READ_2PIX_PLANE ( s - > temp [ 0 ] [ 2 * i ] , s - > temp [ 0 ] [ 2 * i + 1 ] , plane ) ;
if ( s - > bps < = 8 ) {
if ( count > = ( get_bits_left ( & s - > gb ) ) / ( 31 * 2 ) ) {
for ( i = 0 ; i < count & & get_bits_left ( & s - > gb ) > 0 ; i + + ) {
READ_2PIX_PLANE ( s - > temp [ 0 ] [ 2 * i ] , s - > temp [ 0 ] [ 2 * i + 1 ] , plane ) ;
}
} else {
for ( i = 0 ; i < count ; i + + ) {
READ_2PIX_PLANE ( s - > temp [ 0 ] [ 2 * i ] , s - > temp [ 0 ] [ 2 * i + 1 ] , plane ) ;
}
}
} else {
for ( i = 0 ; i < count ; i + + ) {
READ_2PIX_PLANE ( s - > temp [ 0 ] [ 2 * i ] , s - > temp [ 0 ] [ 2 * i + 1 ] , plane ) ;
if ( count > = ( get_bits_left ( & s - > gb ) ) / ( 31 * 2 ) ) {
for ( i = 0 ; i < count & & get_bits_left ( & s - > gb ) > 0 ; i + + ) {
READ_2PIX_PLANE16 ( s - > temp16 [ 0 ] [ 2 * i ] , s - > temp16 [ 0 ] [ 2 * i + 1 ] , plane ) ;
}
} else {
for ( i = 0 ; i < count ; i + + ) {
READ_2PIX_PLANE16 ( s - > temp16 [ 0 ] [ 2 * i ] , s - > temp16 [ 0 ] [ 2 * i + 1 ] , plane ) ;
}
}
}
}
@ -601,6 +627,56 @@ static void draw_slice(HYuvContext *s, AVFrame *frame, int y)
s - > last_slice_end = y + h ;
}
static int left_prediction ( HYuvContext * s , uint8_t * dst , const uint8_t * src , int w , int acc )
{
if ( s - > bps < = 8 ) {
return s - > dsp . add_hfyu_left_prediction ( dst , src , w , acc ) ;
} else {
//FIXME optimize
unsigned mask = s - > n - 1 ;
int i ;
const uint16_t * src16 = ( const uint16_t * ) src ;
uint16_t * dst16 = ( uint16_t * ) dst ;
for ( i = 0 ; i < w - 1 ; i + + ) {
acc + = src16 [ i ] ;
dst16 [ i ] = acc & mask ;
i + + ;
acc + = src16 [ i ] ;
dst16 [ i ] = acc & mask ;
}
for ( ; i < w ; i + + ) {
acc + = src16 [ i ] ;
dst16 [ i ] = acc & mask ;
}
return acc ;
}
}
static void add_bytes ( HYuvContext * s , uint8_t * dst , uint8_t * src , int w )
{
if ( s - > bps < = 8 ) {
s - > dsp . add_bytes ( dst , src , w ) ;
} else {
//FIXME optimize
const uint16_t * src16 = ( const uint16_t * ) src ;
uint16_t * dst16 = ( uint16_t * ) dst ;
long i ;
unsigned long msb = 0x1000100010001ULL < < ( s - > bps - 1 ) ;
unsigned long lsb = msb - 0x1000100010001ULL ;
unsigned long mask = lsb + msb ;
for ( i = 0 ; i < = w - ( int ) sizeof ( long ) / 2 ; i + = sizeof ( long ) / 2 ) {
long a = * ( long * ) ( src16 + i ) ;
long b = * ( long * ) ( dst16 + i ) ;
* ( long * ) ( dst16 + i ) = ( ( a & lsb ) + ( b & lsb ) ) ^ ( ( a ^ b ) & msb ) ;
}
for ( ; i < w ; i + + )
dst16 [ i ] = ( dst16 [ i ] + src16 [ i ] ) & mask ;
}
}
static int decode_frame ( AVCodecContext * avctx , void * data , int * got_frame ,
AVPacket * avpkt )
{
@ -663,16 +739,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
case LEFT :
case PLANE :
decode_plane_bitstream ( s , w , plane ) ;
left = s - > dsp . add_hfyu_left_prediction ( p - > data [ plane ] , s - > temp [ 0 ] , w , 0 ) ;
left = left_prediction ( s , p - > data [ plane ] , s - > temp [ 0 ] , w , 0 ) ;
for ( y = 1 ; y < h ; y + + ) {
uint8_t * dst = p - > data [ plane ] + p - > linesize [ plane ] * y ;
decode_plane_bitstream ( s , w , plane ) ;
left = s - > dsp . add_hfyu_left_prediction ( dst , s - > temp [ 0 ] , w , left ) ;
left = left_prediction ( s , dst , s - > temp [ 0 ] , w , left ) ;
if ( s - > predictor = = PLANE ) {
if ( y > s - > interlaced ) {
s - > dsp . add_bytes ( dst , dst - fake_stride , w ) ;
add_bytes ( s , dst , dst - fake_stride , w ) ;
}
}
}
@ -680,14 +756,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
break ;
case MEDIAN :
decode_plane_bitstream ( s , w , plane ) ;
left = s - > dsp . add_hfyu_left_prediction ( p - > data [ plane ] , s - > temp [ 0 ] , w , 0 ) ;
left = left_prediction ( s , p - > data [ plane ] , s - > temp [ 0 ] , w , 0 ) ;
y = 1 ;
/* second line is left predicted for interlaced case */
if ( s - > interlaced ) {
decode_plane_bitstream ( s , w , plane ) ;
left = s - > dsp . add_hfyu_left_prediction ( p - > data [ plane ] + p - > linesize [ plane ] , s - > temp [ 0 ] , w , left ) ;
left = left_prediction ( s , p - > data [ plane ] + p - > linesize [ plane ] , s - > temp [ 0 ] , w , left ) ;
y + + ;
}