Newer
Older
Kostya Shishkov
committed
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
/* select codingmode used for VLC tables selection */
switch(v->c_ac_table_index){
case 0:
v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
break;
case 1:
v->codingset = CS_HIGH_MOT_INTRA;
break;
case 2:
v->codingset = CS_MID_RATE_INTRA;
break;
}
switch(v->c_ac_table_index){
case 0:
v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
break;
case 1:
v->codingset2 = CS_HIGH_MOT_INTER;
break;
case 2:
v->codingset2 = CS_MID_RATE_INTER;
break;
}
ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
s->first_slice_line = 1;
for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
ff_init_block_index(s);
ff_update_block_index(s);
s->dsp.clear_blocks(s->block[0]);
vc1_decode_b_mb(v);
if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);
return;
}
}
ff_draw_horiz_band(s, s->mb_y * 16, 16);
s->first_slice_line = 0;
}
}
static void vc1_decode_skip_blocks(VC1Context *v)
{
MpegEncContext *s = &v->s;
ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
s->first_slice_line = 1;
for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
s->mb_x = 0;
ff_init_block_index(s);
ff_update_block_index(s);
memcpy(s->dest[0], s->last_picture.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
memcpy(s->dest[1], s->last_picture.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
memcpy(s->dest[2], s->last_picture.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
ff_draw_horiz_band(s, s->mb_y * 16, 16);
s->first_slice_line = 0;
}
s->pict_type = P_TYPE;
}
static void vc1_decode_blocks(VC1Context *v)
Alex Beregszaszi
committed
{
v->s.esc3_level_length = 0;
switch(v->s.pict_type) {
case I_TYPE:
if(v->profile == PROFILE_ADVANCED)
vc1_decode_i_blocks_adv(v);
else
vc1_decode_i_blocks(v);
break;
case P_TYPE:
if(v->p_frame_skipped)
vc1_decode_skip_blocks(v);
else
vc1_decode_p_blocks(v);
break;
Kostya Shishkov
committed
case B_TYPE:
if(v->bi_type)
vc1_decode_i_blocks(v);
else
vc1_decode_b_blocks(v);
Kostya Shishkov
committed
break;
Alex Beregszaszi
committed
}
}
Alex Beregszaszi
committed
/** Initialize a VC1/WMV3 decoder
* @todo TODO: Handle VC-1 IDUs (Transport level?)
* @todo TODO: Decypher remaining bits in extra_data
*/
static int vc1_decode_init(AVCodecContext *avctx)
Alex Beregszaszi
committed
{
VC1Context *v = avctx->priv_data;
Alex Beregszaszi
committed
GetBitContext gb;
if (!avctx->extradata_size || !avctx->extradata) return -1;
if (!(avctx->flags & CODEC_FLAG_GRAY))
avctx->pix_fmt = PIX_FMT_YUV420P;
else
avctx->pix_fmt = PIX_FMT_GRAY8;
avctx->flags |= CODEC_FLAG_EMU_EDGE;
v->s.flags |= CODEC_FLAG_EMU_EDGE;
Alex Beregszaszi
committed
if (vc1_init_common(v) < 0) return -1;
Alex Beregszaszi
committed
avctx->coded_width = avctx->width;
avctx->coded_height = avctx->height;
Alex Beregszaszi
committed
if (avctx->codec_id == CODEC_ID_WMV3)
{
int count = 0;
// looks like WMV3 has a sequence header stored in the extradata
// advanced sequence header may be before the first frame
// the last byte of the extradata is a version number, 1 for the
// samples we can decode
Alex Beregszaszi
committed
init_get_bits(&gb, avctx->extradata, avctx->extradata_size*8);
if (decode_sequence_header(avctx, &gb) < 0)
return -1;
Alex Beregszaszi
committed
count = avctx->extradata_size*8 - get_bits_count(&gb);
if (count>0)
{
av_log(avctx, AV_LOG_INFO, "Extra data: %i bits left, value: %X\n",
count, get_bits(&gb, count));
}
else if (count < 0)
{
av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count);
}
} else { // VC1/WVC1
int edata_size = avctx->extradata_size;
uint8_t *edata = avctx->extradata;
if(avctx->extradata_size < 16) {
av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", edata_size);
return -1;
}
while(edata_size > 8) {
// test if we've found header
if(AV_RB32(edata) == 0x0000010F) {
edata += 4;
edata_size -= 4;
break;
}
edata_size--;
edata++;
}
init_get_bits(&gb, edata, edata_size*8);
if (decode_sequence_header(avctx, &gb) < 0)
return -1;
while(edata_size > 8) {
// test if we've found entry point
if(AV_RB32(edata) == 0x0000010E) {
edata += 4;
edata_size -= 4;
break;
}
edata_size--;
edata++;
}
init_get_bits(&gb, edata, edata_size*8);
if (decode_entry_point(avctx, &gb) < 0)
return -1;
Alex Beregszaszi
committed
}
s->low_delay = !avctx->has_b_frames;
Alex Beregszaszi
committed
s->mb_width = (avctx->coded_width+15)>>4;
s->mb_height = (avctx->coded_height+15)>>4;
Alex Beregszaszi
committed
/* Allocate mb bitplanes */
v->mv_type_mb_plane = av_malloc(s->mb_stride * s->mb_height);
Kostya Shishkov
committed
v->direct_mb_plane = av_malloc(s->mb_stride * s->mb_height);
v->acpred_plane = av_malloc(s->mb_stride * s->mb_height);
v->over_flags_plane = av_malloc(s->mb_stride * s->mb_height);
/* allocate block type info in that way so it could be used with s->block_index[] */
v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2);
v->mb_type[0] = v->mb_type_base + s->b8_stride + 1;
v->mb_type[1] = v->mb_type_base + s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride + 1;
v->mb_type[2] = v->mb_type[1] + s->mb_stride * (s->mb_height + 1);
/* Init coded blocks info */
if (v->profile == PROFILE_ADVANCED)
Alex Beregszaszi
committed
{
// if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0)
// return -1;
// if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0)
// return -1;
Alex Beregszaszi
committed
}
return 0;
}
Alex Beregszaszi
committed
/** Decode a VC1/WMV3 frame
* @todo TODO: Handle VC-1 IDUs (Transport level?)
static int vc1_decode_frame(AVCodecContext *avctx,
Alex Beregszaszi
committed
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
VC1Context *v = avctx->priv_data;
Alex Beregszaszi
committed
AVFrame *pict = data;
uint8_t *buf2 = NULL;
/* no supplementary picture */
if (buf_size == 0) {
/* special case for last picture */
if (s->low_delay==0 && s->next_picture_ptr) {
*pict= *(AVFrame*)s->next_picture_ptr;
s->next_picture_ptr= NULL;
*data_size = sizeof(AVFrame);
}
return 0;
}
//we need to set current_picture_ptr before reading the header, otherwise we cant store anyting im there
if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
int i= ff_find_unused_picture(s, 0);
s->current_picture_ptr= &s->picture[i];
//for advanced profile we need to unescape buffer
if (avctx->codec_id == CODEC_ID_VC1) {
int i, buf_size2;
buf2 = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
buf_size2 = 0;
for(i = 0; i < buf_size; i++) {
if(buf[i] == 3 && i >= 2 && !buf[i-1] && !buf[i-2] && i < buf_size-1 && buf[i+1] < 4) {
buf2[buf_size2++] = buf[i+1];
i++;
} else
buf2[buf_size2++] = buf[i];
}
init_get_bits(&s->gb, buf2, buf_size2*8);
} else
init_get_bits(&s->gb, buf, buf_size*8);
// do parse frame header
if(v->profile < PROFILE_ADVANCED) {
if(vc1_parse_frame_header(v, &s->gb) == -1) {
Kostya Shishkov
committed
av_free(buf2);
return -1;
}
} else {
if(vc1_parse_frame_header_adv(v, &s->gb) == -1) {
Kostya Shishkov
committed
av_free(buf2);
return -1;
}
}
if(s->pict_type != I_TYPE && !v->res_rtm_flag){
Kostya Shishkov
committed
av_free(buf2);
return -1;
}
// for hurry_up==5
s->current_picture.pict_type= s->pict_type;
s->current_picture.key_frame= s->pict_type == I_TYPE;
/* skip B-frames if we don't have reference frames */
if(s->last_picture_ptr==NULL && (s->pict_type==B_TYPE || s->dropable)){
Kostya Shishkov
committed
av_free(buf2);
return -1;//buf_size;
}
if(avctx->hurry_up && s->pict_type==B_TYPE) return -1;//buf_size;
if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
|| (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
|| avctx->skip_frame >= AVDISCARD_ALL) {
Kostya Shishkov
committed
av_free(buf2);
return buf_size;
}
if(avctx->hurry_up>=5) {
Kostya Shishkov
committed
av_free(buf2);
return -1;//buf_size;
}
return buf_size;
if(MPV_frame_start(s, avctx) < 0) {
Kostya Shishkov
committed
av_free(buf2);
}
v->bits = buf_size * 8;
vc1_decode_blocks(v);
//av_log(s->avctx, AV_LOG_INFO, "Consumed %i/%i bits\n", get_bits_count(&s->gb), buf_size*8);
// if(get_bits_count(&s->gb) > buf_size * 8)
// return -1;
assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
assert(s->current_picture.pict_type == s->pict_type);
if (s->pict_type == B_TYPE || s->low_delay) {
*pict= *(AVFrame*)s->current_picture_ptr;
} else if (s->last_picture_ptr != NULL) {
*pict= *(AVFrame*)s->last_picture_ptr;
}
if(s->last_picture_ptr || s->low_delay){
*data_size = sizeof(AVFrame);
ff_print_debug_info(s, pict);
}
/* Return the Picture timestamp as the frame number */
/* we substract 1 because it is added on utils.c */
avctx->frame_number = s->picture_number - 1;
Kostya Shishkov
committed
av_free(buf2);
return buf_size;
Alex Beregszaszi
committed
}
/** Close a VC1/WMV3 decoder
* @warning Initial try at using MpegEncContext stuff
*/
static int vc1_decode_end(AVCodecContext *avctx)
Alex Beregszaszi
committed
{
VC1Context *v = avctx->priv_data;
Alex Beregszaszi
committed
av_freep(&v->hrd_rate);
av_freep(&v->hrd_buffer);
av_freep(&v->mv_type_mb_plane);
Kostya Shishkov
committed
av_freep(&v->direct_mb_plane);
av_freep(&v->acpred_plane);
av_freep(&v->over_flags_plane);
Alex Beregszaszi
committed
return 0;
}
AVCodec vc1_decoder = {
"vc1",
Alex Beregszaszi
committed
CODEC_TYPE_VIDEO,
CODEC_ID_VC1,
sizeof(VC1Context),
vc1_decode_init,
Alex Beregszaszi
committed
NULL,
vc1_decode_end,
vc1_decode_frame,
Alex Beregszaszi
committed
NULL
};
AVCodec wmv3_decoder = {
"wmv3",
CODEC_TYPE_VIDEO,
CODEC_ID_WMV3,
sizeof(VC1Context),
vc1_decode_init,
Alex Beregszaszi
committed
NULL,
vc1_decode_end,
vc1_decode_frame,