Newer
Older
/* 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,
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 may need to parse and unescape data
if (avctx->codec_id == CODEC_ID_VC1) {
int buf_size2 = 0;
buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
if(IS_MARKER(AV_RB32(buf))){ /* frame starts with marker and needs to be parsed */
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
int size;
next = buf;
for(start = buf, end = buf + buf_size; next < end; start = next){
next = find_next_marker(start + 4, end);
size = next - start - 4;
if(size <= 0) continue;
switch(AV_RB32(start)){
case VC1_CODE_FRAME:
buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
break;
case VC1_CODE_ENTRYPOINT: /* it should be before frame data */
buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
init_get_bits(&s->gb, buf2, buf_size2*8);
decode_entry_point(avctx, &s->gb);
break;
case VC1_CODE_SLICE:
av_log(avctx, AV_LOG_ERROR, "Sliced decoding is not implemented (yet)\n");
av_free(buf2);
return -1;
}
}
}else if(v->interlace && ((buf[0] & 0xC0) == 0xC0)){ /* WVC1 interlaced stores both fields divided by marker */
uint8_t *divider;
divider = find_next_marker(buf, buf + buf_size);
if((divider == (buf + buf_size)) || AV_RB32(divider) != VC1_CODE_FIELD){
av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n");
return -1;
}
buf_size2 = vc1_unescape_buffer(buf, divider - buf, buf2);
// TODO
av_free(buf2);return -1;
}else{
buf_size2 = vc1_unescape_buffer(buf, buf_size, buf2);
}
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,