@ -134,12 +134,21 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
ctx - > chroma_factor = ( buf [ 12 ] > > 6 ) & 3 ;
ctx - > mb_chroma_factor = ctx - > chroma_factor + 2 ;
ctx - > num_chroma_blocks = ( 1 < < ctx - > chroma_factor ) > > 1 ;
ctx - > alpha_info = buf [ 17 ] & 0xf ;
if ( ctx - > alpha_info > 2 ) {
av_log ( avctx , AV_LOG_ERROR , " Invalid alpha mode %d \n " , ctx - > alpha_info ) ;
return AVERROR_INVALIDDATA ;
}
switch ( ctx - > chroma_factor ) {
case 2 :
avctx - > pix_fmt = AV_PIX_FMT_YUV422P10 ;
avctx - > pix_fmt = ctx - > alpha_info ? AV_PIX_FMT_YUVA422P10
: AV_PIX_FMT_YUV422P10 ;
break ;
case 3 :
avctx - > pix_fmt = AV_PIX_FMT_YUV444P10 ;
avctx - > pix_fmt = ctx - > alpha_info ? AV_PIX_FMT_YUVA444P10
: AV_PIX_FMT_YUV444P10 ;
break ;
default :
av_log ( avctx , AV_LOG_ERROR ,
@ -168,10 +177,6 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
avctx - > color_trc = buf [ 15 ] ;
avctx - > colorspace = buf [ 16 ] ;
ctx - > alpha_info = buf [ 17 ] & 0xf ;
if ( ctx - > alpha_info )
avpriv_report_missing_feature ( avctx , " Alpha channel " ) ;
ctx - > qmat_changed = 0 ;
ptr = buf + 20 ;
flags = buf [ 19 ] ;
@ -466,6 +471,78 @@ static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td,
}
static void unpack_alpha ( GetBitContext * gb , uint16_t * dst , int num_coeffs ,
const int num_bits )
{
const int mask = ( 1 < < num_bits ) - 1 ;
int i , idx , val , alpha_val ;
idx = 0 ;
alpha_val = mask ;
do {
do {
if ( get_bits1 ( gb ) )
val = get_bits ( gb , num_bits ) ;
else {
int sign ;
val = get_bits ( gb , num_bits = = 16 ? 7 : 4 ) ;
sign = val & 1 ;
val = ( val + 2 ) > > 1 ;
if ( sign )
val = - val ;
}
alpha_val = ( alpha_val + val ) & mask ;
if ( num_bits = = 16 )
dst [ idx + + ] = alpha_val > > 6 ;
else
dst [ idx + + ] = ( alpha_val < < 2 ) | ( alpha_val > > 6 ) ;
if ( idx = = num_coeffs - 1 )
break ;
} while ( get_bits1 ( gb ) ) ;
val = get_bits ( gb , 4 ) ;
if ( ! val )
val = get_bits ( gb , 11 ) ;
if ( idx + val > num_coeffs )
val = num_coeffs - idx ;
if ( num_bits = = 16 )
for ( i = 0 ; i < val ; i + + )
dst [ idx + + ] = alpha_val > > 6 ;
else
for ( i = 0 ; i < val ; i + + )
dst [ idx + + ] = ( alpha_val < < 2 ) | ( alpha_val > > 6 ) ;
} while ( idx < num_coeffs ) ;
}
/**
* Decode alpha slice plane .
*/
static void decode_alpha_plane ( ProresContext * ctx , ProresThreadData * td ,
const uint8_t * buf , int data_size ,
uint16_t * out_ptr , int linesize ,
int mbs_per_slice )
{
GetBitContext gb ;
int i ;
uint16_t * block_ptr ;
memset ( td - > blocks , 0 , 8 * 4 * 64 * sizeof ( * td - > blocks ) ) ;
init_get_bits ( & gb , buf , data_size < < 3 ) ;
if ( ctx - > alpha_info = = 2 )
unpack_alpha ( & gb , td - > blocks , mbs_per_slice * 4 * 64 , 16 ) ;
else
unpack_alpha ( & gb , td - > blocks , mbs_per_slice * 4 * 64 , 8 ) ;
block_ptr = td - > blocks ;
for ( i = 0 ; i < 16 ; i + + ) {
memcpy ( out_ptr , block_ptr , 16 * mbs_per_slice * sizeof ( * out_ptr ) ) ;
out_ptr + = linesize > > 1 ;
block_ptr + = 16 * mbs_per_slice ;
}
}
static int decode_slice ( AVCodecContext * avctx , void * tdata )
{
ProresThreadData * td = tdata ;
@ -476,11 +553,12 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
int slice_num = td - > slice_num ;
int mbs_per_slice = td - > slice_width ;
const uint8_t * buf ;
uint8_t * y_data , * u_data , * v_data ;
uint8_t * y_data , * u_data , * v_data , * a_data ;
AVFrame * pic = ctx - > frame ;
int i , sf , slice_width_factor ;
int slice_data_size , hdr_size , y_data_size , u_data_size , v_data_size ;
int y_linesize , u_linesize , v_linesize ;
int slice_data_size , hdr_size ;
int y_data_size , u_data_size , v_data_size , a_data_size ;
int y_linesize , u_linesize , v_linesize , a_linesize ;
buf = ctx - > slice_data [ slice_num ] . index ;
slice_data_size = ctx - > slice_data [ slice_num + 1 ] . index - buf ;
@ -490,19 +568,23 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
y_data = pic - > data [ 0 ] ;
u_data = pic - > data [ 1 ] ;
v_data = pic - > data [ 2 ] ;
a_data = pic - > data [ 3 ] ;
y_linesize = pic - > linesize [ 0 ] ;
u_linesize = pic - > linesize [ 1 ] ;
v_linesize = pic - > linesize [ 2 ] ;
a_linesize = pic - > linesize [ 3 ] ;
if ( pic - > interlaced_frame ) {
if ( ! ( pic_num ^ pic - > top_field_first ) ) {
y_data + = y_linesize ;
u_data + = u_linesize ;
v_data + = v_linesize ;
a_data + = a_linesize ;
}
y_linesize < < = 1 ;
u_linesize < < = 1 ;
v_linesize < < = 1 ;
a_linesize < < = 1 ;
}
if ( slice_data_size < 6 ) {
@ -516,6 +598,8 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
u_data_size = AV_RB16 ( buf + 4 ) ;
v_data_size = hdr_size > 7 ? AV_RB16 ( buf + 6 ) :
slice_data_size - y_data_size - u_data_size - hdr_size ;
a_data_size = slice_data_size - y_data_size - u_data_size -
v_data_size - hdr_size ;
if ( hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size | |
v_data_size < 0 | | hdr_size < 6 ) {
@ -560,6 +644,16 @@ static int decode_slice(AVCodecContext *avctx, void *tdata)
slice_width_factor + ctx - > chroma_factor - 1 ,
td - > qmat_chroma_scaled , 1 ) ;
/* decode alpha plane if available */
if ( a_data & & a_data_size )
decode_alpha_plane ( ctx , td ,
buf + hdr_size + y_data_size +
u_data_size + v_data_size ,
a_data_size ,
( uint16_t * ) ( a_data + ( mb_y_pos < < 4 ) * a_linesize +
( mb_x_pos < < 5 ) ) , a_linesize ,
mbs_per_slice ) ;
return 0 ;
}