/*
* VC-1 and WMV3 decoder
- * Copyright (c) 2006 Konstantin Shishkov
+ * Copyright (c) 2006-2007 Konstantin Shishkov
* Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
*
* This file is part of FFmpeg.
uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
- src_x = clip( src_x, -16, s->mb_width * 16);
- src_y = clip( src_y, -16, s->mb_height * 16);
- uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
- uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+ if(v->profile != PROFILE_ADVANCED){
+ src_x = av_clip( src_x, -16, s->mb_width * 16);
+ src_y = av_clip( src_y, -16, s->mb_height * 16);
+ uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8);
+ }else{
+ src_x = av_clip( src_x, -17, s->avctx->coded_width);
+ src_y = av_clip( src_y, -18, s->avctx->coded_height + 1);
+ uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+ }
srcY += src_y * s->linesize + src_x;
srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
src_x = s->mb_x * 16 + (n&1) * 8 + (mx >> 2);
src_y = s->mb_y * 16 + (n&2) * 4 + (my >> 2);
- src_x = clip( src_x, -16, s->mb_width * 16);
- src_y = clip( src_y, -16, s->mb_height * 16);
+ if(v->profile != PROFILE_ADVANCED){
+ src_x = av_clip( src_x, -16, s->mb_width * 16);
+ src_y = av_clip( src_y, -16, s->mb_height * 16);
+ }else{
+ src_x = av_clip( src_x, -17, s->avctx->coded_width);
+ src_y = av_clip( src_y, -18, s->avctx->coded_height + 1);
+ }
srcY += src_y * s->linesize + src_x;
for(i= t1+1; i<4; i++)if(!intra[i]) {t2 = i; break;}
tx = (mvx[t1] + mvx[t2]) / 2;
ty = (mvy[t1] + mvy[t2]) / 2;
- } else
+ } else {
+ s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
+ s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
return; //no need to do MC for inter blocks
+ }
s->current_picture.motion_val[1][s->block_index[0]][0] = tx;
s->current_picture.motion_val[1][s->block_index[0]][1] = ty;
uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
- uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
- uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+ if(v->profile != PROFILE_ADVANCED){
+ uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8);
+ }else{
+ uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+ }
+
srcU = s->last_picture.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
srcV = s->last_picture.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
if(v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP)
av_log(avctx, AV_LOG_DEBUG, "Header: %0X\n", show_bits(gb, 32));
v->profile = get_bits(gb, 2);
- if (v->profile == 2)
+ if (v->profile == PROFILE_COMPLEX)
{
- av_log(avctx, AV_LOG_ERROR, "Profile value 2 is forbidden (and WMV3 Complex Profile is unsupported)\n");
- return -1;
+ av_log(avctx, AV_LOG_ERROR, "WMV3 Complex Profile is not fully supported\n");
}
if (v->profile == PROFILE_ADVANCED)
"Old WMV3 version detected, only I-frames will be decoded\n");
//return -1;
}
+ //TODO: figure out what they mean (always 0x402F)
+ if(!v->res_fasttx) skip_bits(gb, 16);
av_log(avctx, AV_LOG_DEBUG,
"Profile %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n"
"LoopFilter=%i, MultiRes=%i, FastUVMC=%i, Extended MV=%i\n"
v->s.avctx->coded_width = (get_bits(gb, 12) + 1) << 1;
v->s.avctx->coded_height = (get_bits(gb, 12) + 1) << 1;
+ v->s.avctx->width = v->s.avctx->coded_width;
+ v->s.avctx->height = v->s.avctx->coded_height;
v->broadcast = get_bits1(gb);
v->interlace = get_bits1(gb);
- if(v->interlace){
- av_log(v->s.avctx, AV_LOG_ERROR, "Interlaced mode not supported (yet)\n");
- return -1;
- }
v->tfcntrflag = get_bits1(gb);
v->finterpflag = get_bits1(gb);
get_bits1(gb); // reserved
+ v->s.h_edge_pos = v->s.avctx->coded_width;
+ v->s.v_edge_pos = v->s.avctx->coded_height;
+
av_log(v->s.avctx, AV_LOG_DEBUG,
"Advanced Profile level %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n"
"LoopFilter=%i, ChromaFormat=%i, Pulldown=%i, Interlace: %i\n"
av_log(v->s.avctx, AV_LOG_ERROR, "Progressive Segmented Frame mode: not supported (yet)\n");
return -1;
}
+ v->s.max_b_frames = v->s.avctx->max_b_frames = 7;
if(get_bits1(gb)) { //Display Info - decoding is not affected by it
int w, h, ar = 0;
- av_log(v->s.avctx, AV_LOG_INFO, "Display extended info:\n");
- w = get_bits(gb, 14) + 1;
- h = get_bits(gb, 14) + 1;
- av_log(v->s.avctx, AV_LOG_INFO, "Display dimensions: %ix%i\n", w, h);
+ av_log(v->s.avctx, AV_LOG_DEBUG, "Display extended info:\n");
+ v->s.avctx->width = v->s.width = w = get_bits(gb, 14) + 1;
+ v->s.avctx->height = v->s.height = h = get_bits(gb, 14) + 1;
+ av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", w, h);
if(get_bits1(gb))
ar = get_bits(gb, 4);
if(ar && ar < 14){
if(get_bits1(gb)){ //framerate stuff
if(get_bits1(gb)) {
- get_bits(gb, 16);
+ v->s.avctx->time_base.num = 32;
+ v->s.avctx->time_base.den = get_bits(gb, 16) + 1;
} else {
- get_bits(gb, 8);
- get_bits(gb, 4);
+ int nr, dr;
+ nr = get_bits(gb, 8);
+ dr = get_bits(gb, 4);
+ if(nr && nr < 8 && dr && dr < 3){
+ v->s.avctx->time_base.num = fps_dr[dr - 1];
+ v->s.avctx->time_base.den = fps_nr[nr - 1] * 1000;
+ }
}
}
static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb)
{
VC1Context *v = avctx->priv_data;
- int i, blink, refdist;
+ int i, blink, clentry, refdist;
av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32));
blink = get_bits1(gb); // broken link
- avctx->max_b_frames = 1 - get_bits1(gb); // 'closed entry' also signalize possible B-frames
+ clentry = get_bits1(gb); // closed entry
v->panscanflag = get_bits1(gb);
refdist = get_bits1(gb); // refdist flag
v->s.loop_filter = get_bits1(gb);
"BrokenLink=%i, ClosedEntry=%i, PanscanFlag=%i\n"
"RefDist=%i, Postproc=%i, FastUVMC=%i, ExtMV=%i\n"
"DQuant=%i, VSTransform=%i, Overlap=%i, Qmode=%i\n",
- blink, 1 - avctx->max_b_frames, v->panscanflag, refdist, v->s.loop_filter,
+ blink, clentry, v->panscanflag, refdist, v->s.loop_filter,
v->fastuvmc, v->extended_mv, v->dquant, v->vstransform, v->overlap, v->quantizer_mode);
return 0;
else
if (v->multires && v->s.pict_type != B_TYPE) v->respic = get_bits(gb, 2);
+ if(v->res_x8 && (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)){
+ if(get_bits1(gb))return -1;
+ }
//av_log(v->s.avctx, AV_LOG_INFO, "%c Frame: QP=[%i]%i (+%i/2) %i\n",
// (v->s.pict_type == P_TYPE) ? 'P' : ((v->s.pict_type == I_TYPE) ? 'I' : 'B'), pqindex, v->pq, v->halfpq, v->rangeredfrm);
shift = v->lumshift << 6;
}
for(i = 0; i < 256; i++) {
- v->luty[i] = clip_uint8((scale * i + shift + 32) >> 6);
- v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
+ v->luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6);
+ v->lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
}
}
if(v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN)
static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
{
- int fcm;
int pqindex, lowquant;
int status;
v->p_frame_skipped = 0;
- if(v->interlace)
- fcm = decode012(gb);
+ if(v->interlace){
+ v->fcm = decode012(gb);
+ if(v->fcm) return -1; // interlaced frames/fields are not implemented
+ }
switch(get_prefix(gb, 0, 4)) {
case 0:
v->s.pict_type = P_TYPE;
if(v->tfcntrflag)
get_bits(gb, 8);
if(v->broadcast) {
- if(!v->interlace || v->panscanflag) {
- get_bits(gb, 2);
+ if(!v->interlace || v->psf) {
+ v->rptfrm = get_bits(gb, 2);
} else {
- get_bits1(gb);
- get_bits1(gb);
+ v->tff = get_bits1(gb);
+ v->rptfrm = get_bits1(gb);
}
}
if(v->panscanflag) {
if (v->quantizer_mode == QUANT_FRAME_EXPLICIT)
v->pquantizer = get_bits(gb, 1);
+ if(v->s.pict_type == I_TYPE || v->s.pict_type == P_TYPE) v->use_ic = 0;
+
switch(v->s.pict_type) {
case I_TYPE:
case BI_TYPE:
shift = v->lumshift << 6;
}
for(i = 0; i < 256; i++) {
- v->luty[i] = clip_uint8((scale * i + shift + 32) >> 6);
- v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
+ v->luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6);
+ v->lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
}
+ v->use_ic = 1;
}
if(v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN)
v->s.quarter_sample = 0;
if(s->mb_intra){
s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0;
s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0;
+ s->current_picture.motion_val[1][xy][0] = 0;
+ s->current_picture.motion_val[1][xy][1] = 0;
if(mv1) { /* duplicate motion data for 1-MV block */
s->current_picture.motion_val[0][xy + 1][0] = 0;
s->current_picture.motion_val[0][xy + 1][1] = 0;
s->current_picture.motion_val[0][xy + wrap][1] = 0;
s->current_picture.motion_val[0][xy + wrap + 1][0] = 0;
s->current_picture.motion_val[0][xy + wrap + 1][1] = 0;
+ s->current_picture.motion_val[1][xy + 1][0] = 0;
+ s->current_picture.motion_val[1][xy + 1][1] = 0;
+ s->current_picture.motion_val[1][xy + wrap][0] = 0;
+ s->current_picture.motion_val[1][xy + wrap][1] = 0;
+ s->current_picture.motion_val[1][xy + wrap + 1][0] = 0;
+ s->current_picture.motion_val[1][xy + wrap + 1][1] = 0;
}
return;
}
uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
- src_x = clip( src_x, -16, s->mb_width * 16);
- src_y = clip( src_y, -16, s->mb_height * 16);
- uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
- uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+ if(v->profile != PROFILE_ADVANCED){
+ src_x = av_clip( src_x, -16, s->mb_width * 16);
+ src_y = av_clip( src_y, -16, s->mb_height * 16);
+ uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8);
+ }else{
+ src_x = av_clip( src_x, -17, s->avctx->coded_width);
+ src_y = av_clip( src_y, -18, s->avctx->coded_height + 1);
+ uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1);
+ uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+ }
srcY += src_y * s->linesize + src_x;
srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
B = s->current_picture.motion_val[0][xy - wrap*2 + off];
+ if(!s->mb_x) C[0] = C[1] = 0;
if(!s->first_slice_line) { // predictor A is not out of bounds
if(s->mb_width == 1) {
px = A[0];
off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
B = s->current_picture.motion_val[1][xy - wrap*2 + off];
+ if(!s->mb_x) C[0] = C[1] = 0;
if(!s->first_slice_line) { // predictor A is not out of bounds
if(s->mb_width == 1) {
px = A[0];
q1 = s->current_picture.qscale_table[mb_pos];
if(dc_pred_dir && c_avail && mb_pos) q2 = s->current_picture.qscale_table[mb_pos - 1];
if(!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride];
- if(n && n<4) q2 = q1;
+ if(dc_pred_dir && n==1) q2 = q1;
+ if(!dc_pred_dir && n==2) q2 = q1;
+ if(n==3) q2 = q1;
if(coded) {
int last = 0, skip, value;
q1 = s->current_picture.qscale_table[mb_pos];
if(dc_pred_dir && c_avail && mb_pos) q2 = s->current_picture.qscale_table[mb_pos - 1];
if(!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride];
- if(n && n<4) q2 = q1;
+ if(dc_pred_dir && n==1) q2 = q1;
+ if(!dc_pred_dir && n==2) q2 = q1;
+ if(n==3) q2 = q1;
if(coded) {
int last = 0, skip, value;
s->dsp.vc1_inv_trans_8x8(s->block[i]);
if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
for(j = 0; j < 64; j++) s->block[i][j] += 128;
+ if(!v->res_fasttx && v->res_x8) for(j = 0; j < 64; j++) s->block[i][j] += 16;
s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
if(v->pq >= 9 && v->overlap) {
if(v->c_avail)
s->dsp.vc1_inv_trans_8x8(s->block[i]);
if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
for(j = 0; j < 64; j++) s->block[i][j] += 128;
+ if(!v->res_fasttx && v->res_x8) for(j = 0; j < 64; j++) s->block[i][j] += 16;
s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize);
if(v->pq >= 9 && v->overlap) {
if(v->c_avail)
vc1_decode_i_block(v, s->block[k], k, val, (k<4)? v->codingset : v->codingset2);
s->dsp.vc1_inv_trans_8x8(s->block[k]);
+ if(!v->res_fasttx && !v->res_x8) for(j = 0; j < 64; j++) s->block[k][j] -= 16;
if(v->pq >= 9 && v->overlap) {
for(j = 0; j < 64; j++) s->block[k][j] += 128;
}
CODEC_CAP_DELAY,
NULL
};
+
+#ifdef CONFIG_VC1_PARSER
+/**
+ * finds the end of the current frame in the bitstream.
+ * @return the position of the first byte of the next frame, or -1
+ */
+static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf,
+ int buf_size) {
+ int pic_found, i;
+ uint32_t state;
+
+ pic_found= pc->frame_start_found;
+ state= pc->state;
+
+ i=0;
+ if(!pic_found){
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == VC1_CODE_FRAME || state == VC1_CODE_FIELD){
+ i++;
+ pic_found=1;
+ break;
+ }
+ }
+ }
+
+ if(pic_found){
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(IS_MARKER(state) && state != VC1_CODE_FIELD && state != VC1_CODE_SLICE){
+ pc->frame_start_found=0;
+ pc->state=-1;
+ return i-3;
+ }
+ }
+ }
+ pc->frame_start_found= pic_found;
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+static int vc1_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext *pc = s->priv_data;
+ int next;
+
+ if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
+ next= buf_size;
+ }else{
+ next= vc1_find_frame_end(pc, buf, buf_size);
+
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+ }
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+
+static int vc1_split(AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ int i;
+ uint32_t state= -1;
+
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(IS_MARKER(state) && state != VC1_CODE_SEQHDR && state != VC1_CODE_ENTRYPOINT)
+ return i-3;
+ }
+ return 0;
+}
+
+AVCodecParser vc1_parser = {
+ { CODEC_ID_VC1 },
+ sizeof(ParseContext1),
+ NULL,
+ vc1_parse,
+ ff_parse1_close,
+ vc1_split,
+};
+#endif /* CONFIG_VC1_PARSER */