1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

better/cleaner error resilience (done in a 2nd pass after decoding)

h263/mpeg4 out of order slice decoding

Originally committed as revision 1030 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer 2002-10-13 13:16:04 +00:00
parent 46de8b7334
commit 4d2858deac
12 changed files with 1714 additions and 681 deletions

View File

@ -114,8 +114,9 @@ static int b_frames = 0;
static int use_hq = 0; static int use_hq = 0;
static int use_4mv = 0; static int use_4mv = 0;
static int do_deinterlace = 0; static int do_deinterlace = 0;
static int workaround_bugs = 0; static int workaround_bugs = FF_BUG_AUTODETECT;
static int error_resilience = 0; static int error_resilience = 2;
static int error_concealment = 3;
static int dct_algo = 0; static int dct_algo = 0;
static int idct_algo = 0; static int idct_algo = 0;
static int use_part = 0; static int use_part = 0;
@ -1462,6 +1463,12 @@ void opt_error_resilience(const char *arg)
error_resilience = atoi(arg); error_resilience = atoi(arg);
} }
void opt_error_concealment(const char *arg)
{
error_concealment = atoi(arg);
}
void opt_frame_rate(const char *arg) void opt_frame_rate(const char *arg)
{ {
frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE); frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
@ -1823,6 +1830,7 @@ void opt_input_file(const char *filename)
rfps = ic->streams[i]->r_frame_rate; rfps = ic->streams[i]->r_frame_rate;
enc->workaround_bugs = workaround_bugs; enc->workaround_bugs = workaround_bugs;
enc->error_resilience = error_resilience; enc->error_resilience = error_resilience;
enc->error_concealment = error_concealment;
enc->idct_algo= idct_algo; enc->idct_algo= idct_algo;
if (enc->frame_rate != rfps) { if (enc->frame_rate != rfps) {
fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n", fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
@ -2394,6 +2402,7 @@ const OptionDef options[] = {
{ "dct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_dct_algo}, "set dct algo", "algo" }, { "dct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_dct_algo}, "set dct algo", "algo" },
{ "idct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_idct_algo}, "set idct algo", "algo" }, { "idct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_idct_algo}, "set idct algo", "algo" },
{ "er", HAS_ARG | OPT_EXPERT, {(void*)opt_error_resilience}, "set error resilience", "" }, { "er", HAS_ARG | OPT_EXPERT, {(void*)opt_error_resilience}, "set error resilience", "" },
{ "ec", HAS_ARG | OPT_EXPERT, {(void*)opt_error_resilience}, "set error concealment", "" },
{ "bf", HAS_ARG | OPT_EXPERT, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" }, { "bf", HAS_ARG | OPT_EXPERT, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" },
{ "hq", OPT_BOOL | OPT_EXPERT, {(void*)&use_hq}, "activate high quality settings" }, { "hq", OPT_BOOL | OPT_EXPERT, {(void*)&use_hq}, "activate high quality settings" },
{ "4mv", OPT_BOOL | OPT_EXPERT, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" }, { "4mv", OPT_BOOL | OPT_EXPERT, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" },

View File

@ -15,7 +15,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \
mpegaudio.o ac3enc.o mjpeg.o resample.o dsputil.o \ mpegaudio.o ac3enc.o mjpeg.o resample.o dsputil.o \
motion_est.o imgconvert.o imgresample.o msmpeg4.o \ motion_est.o imgconvert.o imgresample.o msmpeg4.o \
mpeg12.o h263dec.o svq1.o rv10.o mpegaudiodec.o pcm.o simple_idct.o \ mpeg12.o h263dec.o svq1.o rv10.o mpegaudiodec.o pcm.o simple_idct.o \
ratecontrol.o adpcm.o eval.o dv.o ratecontrol.o adpcm.o eval.o dv.o error_resilience.o
ASM_OBJS= ASM_OBJS=
# currently using liba52 for ac3 decoding # currently using liba52 for ac3 decoding

View File

@ -5,8 +5,8 @@
#define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION_INT 0x000406
#define LIBAVCODEC_VERSION "0.4.6" #define LIBAVCODEC_VERSION "0.4.6"
#define LIBAVCODEC_BUILD 4630 #define LIBAVCODEC_BUILD 4631
#define LIBAVCODEC_BUILD_STR "4630" #define LIBAVCODEC_BUILD_STR "4631"
enum CodecID { enum CodecID {
CODEC_ID_NONE, CODEC_ID_NONE,
@ -414,11 +414,18 @@ typedef struct AVCodecContext {
unsigned int codec_tag; /* codec tag, only used if unknown codec */ unsigned int codec_tag; /* codec tag, only used if unknown codec */
/** /**
* workaround bugs in encoders which cannot be detected automatically * workaround bugs in encoders which sometimes cannot be detected automatically
* encoding: unused * encoding: unused
* decoding: set by user * decoding: set by user
*/ */
int workaround_bugs; int workaround_bugs;
#define FF_BUG_AUTODETECT 1 //autodetection
#define FF_BUG_OLD_MSMPEG4 2
#define FF_BUG_XVID_ILACE 4
#define FF_BUG_UMP4 8
#define FF_BUG_NO_PADDING 16
#define FF_BUG_AC_VLC 32
//#define FF_BUG_FAKE_SCALABILITY 16 //autodetection should work 100%
/** /**
* encoding: set by user * encoding: set by user
@ -715,6 +722,15 @@ typedef struct AVCodecContext {
*/ */
int *slice_offset; int *slice_offset;
/**
* error concealment flags
* encoding: unused
* decoding: set by user
*/
int error_concealment;
#define FF_EC_GUESS_MVS 1
#define FF_EC_DEBLOCK 2
//FIXME this should be reordered after kabis API is finished ... //FIXME this should be reordered after kabis API is finished ...
//TODO kill kabi //TODO kill kabi
/* /*

View File

@ -0,0 +1,885 @@
/*
* Error resilience / concealment
*
* Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
/**
* replaces the current MB with a flat dc only version.
*/
static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
{
int dc, dcu, dcv, y, i;
for(i=0; i<4; i++){
dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
if(dc<0) dc=0;
else if(dc>2040) dc=2040;
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
}
}
}
dcu = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
dcv = s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
if (dcu<0 ) dcu=0;
else if(dcu>2040) dcu=2040;
if (dcv<0 ) dcv=0;
else if(dcv>2040) dcv=2040;
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dest_cb[x + y*(s->uvlinesize)]= dcu/8;
dest_cr[x + y*(s->uvlinesize)]= dcv/8;
}
}
}
static void filter181(INT16 *data, int width, int height, int stride){
int x,y;
/* horizontal filter */
for(y=1; y<height-1; y++){
int prev_dc= data[0 + y*stride];
for(x=1; x<width-1; x++){
int dc;
dc= - prev_dc
+ data[x + y*stride]*8
- data[x + 1 + y*stride];
dc= (dc*10923 + 32768)>>16;
prev_dc= data[x + y*stride];
data[x + y*stride]= dc;
}
}
/* vertical filter */
for(x=1; x<width-1; x++){
int prev_dc= data[x];
for(y=1; y<height-1; y++){
int dc;
dc= - prev_dc
+ data[x + y *stride]*8
- data[x + (y+1)*stride];
dc= (dc*10923 + 32768)>>16;
prev_dc= data[x + y*stride];
data[x + y*stride]= dc;
}
}
}
/**
* guess the dc of blocks which dont have a undamaged dc
* @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks
*/
static void guess_dc(MpegEncContext *s, INT16 *dc, int w, int h, int stride, int is_luma){
int b_x, b_y;
for(b_y=0; b_y<h; b_y++){
for(b_x=0; b_x<w; b_x++){
int color[4]={1024,1024,1024,1024};
int distance[4]={9999,9999,9999,9999};
int mb_index, error, j;
INT64 guess, weight_sum;
mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_width;
error= s->error_status_table[mb_index];
if(!(s->mb_type[mb_index]&MB_TYPE_INTRA)) continue; //inter
if(!(error&DC_ERROR)) continue; //dc-ok
/* right block */
for(j=b_x+1; j<w; j++){
int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
int error_j= s->error_status_table[mb_index_j];
int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
if(intra_j==0 || !(error_j&DC_ERROR)){
color[0]= dc[j + b_y*stride];
distance[0]= j-b_x;
break;
}
}
/* left block */
for(j=b_x-1; j>=0; j--){
int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
int error_j= s->error_status_table[mb_index_j];
int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
if(intra_j==0 || !(error_j&DC_ERROR)){
color[1]= dc[j + b_y*stride];
distance[1]= b_x-j;
break;
}
}
/* bottom block */
for(j=b_y+1; j<h; j++){
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
int error_j= s->error_status_table[mb_index_j];
int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
if(intra_j==0 || !(error_j&DC_ERROR)){
color[2]= dc[b_x + j*stride];
distance[2]= j-b_y;
break;
}
}
/* top block */
for(j=b_y-1; j>=0; j--){
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
int error_j= s->error_status_table[mb_index_j];
int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
if(intra_j==0 || !(error_j&DC_ERROR)){
color[3]= dc[b_x + j*stride];
distance[3]= b_y-j;
break;
}
}
weight_sum=0;
guess=0;
for(j=0; j<4; j++){
INT64 weight= 256*256*256*16/distance[j];
guess+= weight*(INT64)color[j];
weight_sum+= weight;
}
guess= (guess + weight_sum/2) / weight_sum;
dc[b_x + b_y*stride]= guess;
}
}
}
/**
* simple horizontal deblocking filter used for error resilience
* @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks
*/
static void h_block_filter(MpegEncContext *s, UINT8 *dst, int w, int h, int stride, int is_luma){
int b_x, b_y;
UINT8 *cm = cropTbl + MAX_NEG_CROP;
for(b_y=0; b_y<h; b_y++){
for(b_x=0; b_x<w-1; b_x++){
int y;
int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_width];
int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width];
int left_intra= s->mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
int right_intra= s->mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
int offset= b_x*8 + b_y*stride*8;
INT16 *left_mv= s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ( b_x <<(1-is_luma))];
INT16 *right_mv= s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ((b_x+1)<<(1-is_luma))];
if(!(left_damage||right_damage)) continue; // both undamaged
if( (!left_intra) && (!right_intra)
&& ABS(left_mv[0]-right_mv[0]) + ABS(left_mv[1]+right_mv[1]) < 2) continue;
for(y=0; y<8; y++){
int a,b,c,d;
a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
d= ABS(b) - ((ABS(a) + ABS(c) + 1)>>1);
d= MAX(d, 0);
if(b<0) d= -d;
if(d==0) continue;
if(!(left_damage && right_damage))
d= d*16/9;
if(left_damage){
dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
}
if(right_damage){
dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
}
}
}
}
}
/**
* simple vertical deblocking filter used for error resilience
* @param w width in 8 pixel blocks
* @param h height in 8 pixel blocks
*/
static void v_block_filter(MpegEncContext *s, UINT8 *dst, int w, int h, int stride, int is_luma){
int b_x, b_y;
UINT8 *cm = cropTbl + MAX_NEG_CROP;
for(b_y=0; b_y<h-1; b_y++){
for(b_x=0; b_x<w; b_x++){
int x;
int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_width];
int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width];
int top_intra= s->mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_width]&MB_TYPE_INTRA;
int bottom_intra= s->mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
int offset= b_x*8 + b_y*stride*8;
INT16 *top_mv= s->motion_val[s->block_wrap[0]*(( b_y <<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
INT16 *bottom_mv= s->motion_val[s->block_wrap[0]*(((b_y+1)<<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
if(!(top_damage||bottom_damage)) continue; // both undamaged
if( (!top_intra) && (!bottom_intra)
&& ABS(top_mv[0]-bottom_mv[0]) + ABS(top_mv[1]+bottom_mv[1]) < 2) continue;
for(x=0; x<8; x++){
int a,b,c,d;
a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
d= ABS(b) - ((ABS(a) + ABS(c)+1)>>1);
d= MAX(d, 0);
if(b<0) d= -d;
if(d==0) continue;
if(!(top_damage && bottom_damage))
d= d*16/9;
if(top_damage){
dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)];
dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)];
dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)];
dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)];
}
if(bottom_damage){
dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)];
dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)];
dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
}
}
}
}
}
static void guess_mv(MpegEncContext *s){
UINT8 fixed[s->mb_num];
#define MV_FROZEN 3
#define MV_CHANGED 2
#define MV_UNCHANGED 1
const int mb_width = s->mb_width;
const int mb_height= s->mb_height;
int i, depth, num_avail;
num_avail=0;
for(i=0; i<s->mb_num; i++){
int f=0;
int error= s->error_status_table[i];
if(s->mb_type[i]&MB_TYPE_INTRA) f=MV_FROZEN; //intra //FIXME check
if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
fixed[i]= f;
if(f==MV_FROZEN)
num_avail++;
}
if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
int mb_x, mb_y;
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
i++;
if(s->mb_type[i]&MB_TYPE_INTRA) continue;
if(!(s->error_status_table[i]&MV_ERROR)) continue;
s->mv_dir = MV_DIR_FORWARD;
s->mb_intra=0;
s->mv_type = MV_TYPE_16X16;
s->mb_skiped=0;
clear_blocks(s->block[0]);
s->mb_x= mb_x;
s->mb_y= mb_y;
s->mv[0][0][0]= 0;
s->mv[0][0][1]= 0;
MPV_decode_mb(s, s->block);
}
}
return;
}
for(depth=0;; depth++){
int changed, pass, none_left;
none_left=1;
changed=1;
for(pass=0; (changed || pass<2) && pass<10; pass++){
int i,mb_x, mb_y;
int score_sum=0;
changed=0;
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
int mv_predictor[8][2]={{0}};
int pred_count=0;
int j;
int best_score=256*256*256*64;
int best_pred=0;
const int mot_stride= mb_width*2+2;
const int mot_index= mb_x*2 + 1 + (mb_y*2+1)*mot_stride;
int prev_x= s->motion_val[mot_index][0];
int prev_y= s->motion_val[mot_index][1];
i++;
if((mb_x^mb_y^pass)&1) continue;
if(fixed[i]==MV_FROZEN) continue;
j=0;
if(mb_x>0 && fixed[i-1 ]==MV_FROZEN) j=1;
if(mb_x+1<mb_width && fixed[i+1 ]==MV_FROZEN) j=1;
if(mb_y>0 && fixed[i-mb_width]==MV_FROZEN) j=1;
if(mb_y+1<mb_height && fixed[i+mb_width]==MV_FROZEN) j=1;
if(j==0) continue;
j=0;
if(mb_x>0 && fixed[i-1 ]==MV_CHANGED) j=1;
if(mb_x+1<mb_width && fixed[i+1 ]==MV_CHANGED) j=1;
if(mb_y>0 && fixed[i-mb_width]==MV_CHANGED) j=1;
if(mb_y+1<mb_height && fixed[i+mb_width]==MV_CHANGED) j=1;
if(j==0 && pass>1) continue;
none_left=0;
if(mb_x>0 && fixed[i-1]){
mv_predictor[pred_count][0]= s->motion_val[mot_index - 2][0];
mv_predictor[pred_count][1]= s->motion_val[mot_index - 2][1];
pred_count++;
}
if(mb_x+1<mb_width && fixed[i+1]){
mv_predictor[pred_count][0]= s->motion_val[mot_index + 2][0];
mv_predictor[pred_count][1]= s->motion_val[mot_index + 2][1];
pred_count++;
}
if(mb_y>0 && fixed[i-mb_width]){
mv_predictor[pred_count][0]= s->motion_val[mot_index - mot_stride*2][0];
mv_predictor[pred_count][1]= s->motion_val[mot_index - mot_stride*2][1];
pred_count++;
}
if(mb_y+1<mb_height && fixed[i+mb_width]){
mv_predictor[pred_count][0]= s->motion_val[mot_index + mot_stride*2][0];
mv_predictor[pred_count][1]= s->motion_val[mot_index + mot_stride*2][1];
pred_count++;
}
if(pred_count==0) continue;
if(pred_count>1){
int sum_x=0, sum_y=0;
int max_x, max_y, min_x, min_y;
for(j=0; j<pred_count; j++){
sum_x+= mv_predictor[j][0];
sum_y+= mv_predictor[j][1];
}
/* mean */
mv_predictor[pred_count][0] = sum_x/j;
mv_predictor[pred_count][1] = sum_y/j;
/* median */
if(pred_count>=3){
min_y= min_x= 99999;
max_y= max_x=-99999;
}else{
min_x=min_y=max_x=max_y=0;
}
for(j=0; j<pred_count; j++){
max_x= MAX(max_x, mv_predictor[j][0]);
max_y= MAX(max_y, mv_predictor[j][1]);
min_x= MIN(min_x, mv_predictor[j][0]);
min_y= MIN(min_y, mv_predictor[j][1]);
}
mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
if(pred_count==4){
mv_predictor[pred_count+1][0] /= 2;
mv_predictor[pred_count+1][1] /= 2;
}
pred_count+=2;
}
/* zero MV */
pred_count++;
/* last MV */
mv_predictor[pred_count][0]= s->motion_val[mot_index][0];
mv_predictor[pred_count][1]= s->motion_val[mot_index][1];
pred_count++;
s->mv_dir = MV_DIR_FORWARD;
s->mb_intra=0;
s->mv_type = MV_TYPE_16X16;
s->mb_skiped=0;
clear_blocks(s->block[0]);
s->mb_x= mb_x;
s->mb_y= mb_y;
for(j=0; j<pred_count; j++){
int score=0;
UINT8 *src= s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
MPV_decode_mb(s, s->block);
if(mb_x>0 && fixed[i-1]){
int k;
for(k=0; k<16; k++)
score += ABS(src[k*s->linesize-1 ]-src[k*s->linesize ]);
}
if(mb_x+1<mb_width && fixed[i+1]){
int k;
for(k=0; k<16; k++)
score += ABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
}
if(mb_y>0 && fixed[i-mb_width]){
int k;
for(k=0; k<16; k++)
score += ABS(src[k-s->linesize ]-src[k ]);
}
if(mb_y+1<mb_height && fixed[i+mb_width]){
int k;
for(k=0; k<16; k++)
score += ABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
}
if(score <= best_score){ // <= will favor the last MV
best_score= score;
best_pred= j;
}
}
score_sum+= best_score;
//FIXME no need to set s->motion_val[mot_index][0] explicit
s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[best_pred][0];
s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[best_pred][1];
MPV_decode_mb(s, s->block);
if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
fixed[i]=MV_CHANGED;
changed++;
}else
fixed[i]=MV_UNCHANGED;
}
}
// printf(".%d/%d", changed, score_sum); fflush(stdout);
}
if(none_left)
return;
for(i=0; i<s->mb_num; i++){
if(fixed[i])
fixed[i]=MV_FROZEN;
}
// printf(":"); fflush(stdout);
}
}
static int is_intra_more_likely(MpegEncContext *s){
int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
undamaged_count=0;
for(i=0; i<s->mb_num; i++){
int error= s->error_status_table[i];
if(!((error&DC_ERROR) && (error&MV_ERROR)))
undamaged_count++;
}
if(undamaged_count < 5) return 0; //allmost all MBs damaged -> use temporal prediction
skip_amount= MAX(undamaged_count/50, 1); //check only upto 50 MBs
is_intra_likely=0;
j=0;
i=-1;
for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
for(mb_x= 0; mb_x<s->mb_width; mb_x++){
int error;
i++;
error= s->error_status_table[i];
if((error&DC_ERROR) && (error&MV_ERROR))
continue; //skip damaged
j++;
if((j%skip_amount) != 0) continue; //skip a few to speed things up
if(s->pict_type==I_TYPE){
UINT8 *mb_ptr = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
UINT8 *last_mb_ptr= s->last_picture [0] + mb_x*16 + mb_y*16*s->linesize;
is_intra_likely += pix_abs16x16(last_mb_ptr, mb_ptr , s->linesize);
is_intra_likely -= pix_abs16x16(last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize);
}else{
if(s->mbintra_table[i]) //HACK (this is allways inited but we should use mb_type[])
is_intra_likely++;
else
is_intra_likely--;
}
}
}
//printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
return is_intra_likely > 0;
}
void ff_error_resilience(MpegEncContext *s){
int i, mb_x, mb_y, error, error_type;
int distance;
int threshold_part[4]= {100,100,100};
int threshold= 50;
int is_intra_likely;
#if 1
/* handle overlapping slices */
for(error_type=1; error_type<=3; error_type++){
int end_ok=0;
for(i=s->mb_num-1; i>=0; i--){
int error= s->error_status_table[i];
if(error&(1<<error_type))
end_ok=1;
if(error&(8<<error_type))
end_ok=1;
if(!end_ok)
s->error_status_table[i]|= 1<<error_type;
if(error&VP_START)
end_ok=0;
}
}
#endif
#if 1
/* handle slices with partitions of different length */
if(s->partitioned_frame){
int end_ok=0;
for(i=s->mb_num-1; i>=0; i--){
int error= s->error_status_table[i];
if(error&AC_END)
end_ok=0;
if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
end_ok=1;
if(!end_ok)
s->error_status_table[i]|= AC_ERROR;
if(error&VP_START)
end_ok=0;
}
}
#endif
/* handle missing slices */
if(s->error_resilience>=4){
int end_ok=1;
for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
int error1= s->error_status_table[i ];
int error2= s->error_status_table[i+1];
if(error1&VP_START)
end_ok=1;
if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
&& error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
&& ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninited
end_ok=0;
}
if(!end_ok)
s->error_status_table[i]|= DC_ERROR|AC_ERROR|MV_ERROR;
}
}
#if 1
/* backward mark errors */
distance=9999999;
for(error_type=1; error_type<=3; error_type++){
for(i=s->mb_num-1; i>=0; i--){
int error= s->error_status_table[i];
if(!s->mbskip_table[i]) //FIXME partition specific
distance++;
if(error&(1<<error_type))
distance= 0;
if(s->partitioned_frame){
if(distance < threshold_part[error_type-1])
s->error_status_table[i]|= 1<<error_type;
}else{
if(distance < threshold)
s->error_status_table[i]|= 1<<error_type;
}
if(error&VP_START)
distance= 9999999;
}
}
#endif
/* forward mark errors */
error=0;
for(i=0; i<s->mb_num; i++){
int old_error= s->error_status_table[i];
if(old_error&VP_START)
error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
else{
error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
s->error_status_table[i]|= error;
}
}
#if 1
/* handle not partitioned case */
if(!s->partitioned_frame){
for(i=0; i<s->mb_num; i++){
error= s->error_status_table[i];
if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
error|= AC_ERROR|DC_ERROR|MV_ERROR;
s->error_status_table[i]= error;
}
}
#endif
is_intra_likely= is_intra_more_likely(s);
/* set unknown mb-type to most likely */
for(i=0; i<s->mb_num; i++){
int intra;
error= s->error_status_table[i];
if((error&DC_ERROR) && (error&MV_ERROR))
intra= is_intra_likely;
else
intra= s->mbintra_table[i];
if(intra)
s->mb_type[i]|= MB_TYPE_INTRA;
else
s->mb_type[i]&= ~MB_TYPE_INTRA;
}
/* handle inter blocks with damaged AC */
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
i++;
error= s->error_status_table[i];
if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
if(error&MV_ERROR) continue; //inter with damaged MV
if(!(error&AC_ERROR)) continue; //undamaged inter
s->mv_dir = MV_DIR_FORWARD;
s->mb_intra=0;
s->mb_skiped=0;
if(s->mb_type[i]&MB_TYPE_INTER4V){
int mb_index= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
int j;
s->mv_type = MV_TYPE_8X8;
for(j=0; j<4; j++){
s->mv[0][j][0] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][0];
s->mv[0][j][1] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][1];
}
}else{
s->mv_type = MV_TYPE_16X16;
s->mv[0][0][0] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][0];
s->mv[0][0][1] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][1];
}
clear_blocks(s->block[0]);
s->mb_x= mb_x;
s->mb_y= mb_y;
MPV_decode_mb(s, s->block);
}
}
/* guess MVs */
if(s->pict_type==B_TYPE){
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
int xy= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
i++;
error= s->error_status_table[i];
if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
if(!(error&MV_ERROR)) continue; //inter with undamaged MV
if(!(error&AC_ERROR)) continue; //undamaged inter
s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
s->mb_intra=0;
s->mv_type = MV_TYPE_16X16;
s->mb_skiped=0;
if(s->pp_time){
int time_pp= s->pp_time;
int time_pb= s->pb_time;
s->mv[0][0][0] = s->motion_val[xy][0]*time_pb/time_pp;
s->mv[0][0][1] = s->motion_val[xy][1]*time_pb/time_pp;
s->mv[1][0][0] = s->motion_val[xy][0]*(time_pb - time_pp)/time_pp;
s->mv[1][0][1] = s->motion_val[xy][1]*(time_pb - time_pp)/time_pp;
}else{
s->mv[0][0][0]= 0;
s->mv[0][0][1]= 0;
s->mv[1][0][0]= 0;
s->mv[1][0][1]= 0;
}
clear_blocks(s->block[0]);
s->mb_x= mb_x;
s->mb_y= mb_y;
MPV_decode_mb(s, s->block);
}
}
}else
guess_mv(s);
/* fill DC for inter blocks */
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
int dc, dcu, dcv, y, n;
INT16 *dc_ptr;
UINT8 *dest_y, *dest_cb, *dest_cr;
i++;
error= s->error_status_table[i];
if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
// if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
dest_y = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
dest_cb= s->current_picture[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
dest_cr= s->current_picture[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
dc_ptr= &s->dc_val[0][mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2)];
for(n=0; n<4; n++){
dc=0;
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
}
}
dc_ptr[(n&1) + (n>>1)*(s->mb_width*2+2)]= (dc+4)>>3;
}
dcu=dcv=0;
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dcu+=dest_cb[x + y*(s->uvlinesize)];
dcv+=dest_cr[x + y*(s->uvlinesize)];
}
}
s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcu+4)>>3;
s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcv+4)>>3;
}
}
#if 1
/* guess DC for damaged blocks */
guess_dc(s, s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2, 1);
guess_dc(s, s->dc_val[1] + s->mb_width +3, s->mb_width , s->mb_height , s->mb_width +2, 0);
guess_dc(s, s->dc_val[2] + s->mb_width +3, s->mb_width , s->mb_height , s->mb_width +2, 0);
#endif
/* filter luma DC */
filter181(s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2);
#if 1
/* render DC only intra */
i= -1;
for(mb_y=0; mb_y<s->mb_height; mb_y++){
for(mb_x=0; mb_x<s->mb_width; mb_x++){
UINT8 *dest_y, *dest_cb, *dest_cr;
i++;
error= s->error_status_table[i];
if(!(s->mb_type[i]&MB_TYPE_INTRA)) continue; //inter
if(!(error&AC_ERROR)) continue; //undamaged
dest_y = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
dest_cb= s->current_picture[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
dest_cr= s->current_picture[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
}
}
#endif
if(s->avctx->error_concealment&FF_EC_DEBLOCK){
/* filter horizontal block boundaries */
h_block_filter(s, s->current_picture[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
h_block_filter(s, s->current_picture[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
h_block_filter(s, s->current_picture[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
/* filter vertical block boundaries */
v_block_filter(s, s->current_picture[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
v_block_filter(s, s->current_picture[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
v_block_filter(s, s->current_picture[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
}
/* clean a few tables */
for(i=0; i<s->mb_num; i++){
int error= s->error_status_table[i];
if(s->pict_type!=B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
s->mbskip_table[i]=0;
}
s->mbintra_table[i]=1;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,12 @@
#include "dsputil.h" #include "dsputil.h"
#include "mpegvideo.h" #include "mpegvideo.h"
#if 1
#define PRINT_QP(a, b) {}
#else
#define PRINT_QP(a, b) printf(a, b)
#endif
//#define DEBUG //#define DEBUG
//#define PRINT_FRAME_TIME //#define PRINT_FRAME_TIME
#ifdef PRINT_FRAME_TIME #ifdef PRINT_FRAME_TIME
@ -34,6 +40,8 @@ static inline long long rdtsc()
} }
#endif #endif
const UINT16 ff_mpeg4_resync_prefix[8];
static int h263_decode_init(AVCodecContext *avctx) static int h263_decode_init(AVCodecContext *avctx)
{ {
MpegEncContext *s = avctx->priv_data; MpegEncContext *s = avctx->priv_data;
@ -45,6 +53,11 @@ static int h263_decode_init(AVCodecContext *avctx)
s->height = avctx->height; s->height = avctx->height;
s->workaround_bugs= avctx->workaround_bugs; s->workaround_bugs= avctx->workaround_bugs;
// set defaults
s->quant_precision=5;
s->progressive_sequence=1;
s->decode_mb= ff_h263_decode_mb;
/* select sub codec */ /* select sub codec */
switch(avctx->codec->id) { switch(avctx->codec->id) {
case CODEC_ID_H263: case CODEC_ID_H263:
@ -115,7 +128,6 @@ static int h263_decode_end(AVCodecContext *avctx)
*/ */
static int get_consumed_bytes(MpegEncContext *s, int buf_size){ static int get_consumed_bytes(MpegEncContext *s, int buf_size){
int pos= (get_bits_count(&s->gb)+7)>>3; int pos= (get_bits_count(&s->gb)+7)>>3;
if(s->divx_version>=500){ if(s->divx_version>=500){
//we would have to scan through the whole buf to handle the weird reordering ... //we would have to scan through the whole buf to handle the weird reordering ...
return buf_size; return buf_size;
@ -127,12 +139,144 @@ static int get_consumed_bytes(MpegEncContext *s, int buf_size){
} }
} }
static int decode_slice(MpegEncContext *s){
s->last_resync_gb= s->gb;
s->first_slice_line= 1;
s->resync_mb_x= s->mb_x;
s->resync_mb_y= s->mb_y;
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
if(s->partitioned_frame){
const int qscale= s->qscale;
if(s->codec_id==CODEC_ID_MPEG4){
if(ff_mpeg4_decode_partitions(s) < 0)
return -1;
}
/* restore variables which where modified */
s->first_slice_line=1;
s->mb_x= s->resync_mb_x;
s->mb_y= s->resync_mb_y;
s->qscale= qscale;
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
}
for(; s->mb_y < s->mb_height; s->mb_y++) {
/* per-row end of slice checks */
if(s->msmpeg4_version){
if(s->resync_mb_y + s->slice_height == s->mb_y){
const int xy= s->mb_x + s->mb_y*s->mb_width;
s->error_status_table[xy-1]|= AC_END|DC_END|MV_END;
return 0;
}
}
if(s->msmpeg4_version==1){
s->last_dc[0]=
s->last_dc[1]=
s->last_dc[2]= 128;
}
ff_init_block_index(s);
for(; s->mb_x < s->mb_width; s->mb_x++) {
int ret;
ff_update_block_index(s);
if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
s->first_slice_line=0;
}
/* DCT & quantize */
clear_blocks(s->block[0]);
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
ret= s->decode_mb(s, s->block);
PRINT_QP("%2d", s->qscale);
MPV_decode_mb(s, s->block);
if(ret<0){
const int xy= s->mb_x + s->mb_y*s->mb_width;
if(ret==SLICE_END){
//printf("%d %d %06X\n", s->mb_x, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));
s->error_status_table[xy]|= AC_END;
if(!s->partitioned_frame)
s->error_status_table[xy]|= MV_END|DC_END;
if(++s->mb_x >= s->mb_width){
s->mb_x=0;
ff_draw_horiz_band(s);
s->mb_y++;
}
return 0;
}else if(ret==SLICE_NOEND){
fprintf(stderr,"Slice mismatch at MB: %d\n", xy);
return -1;
}
fprintf(stderr,"Error at MB: %d\n", xy);
s->error_status_table[xy]|= AC_ERROR;
if(!s->partitioned_frame)
s->error_status_table[xy]|= DC_ERROR|MV_ERROR;
return -1;
}
}
ff_draw_horiz_band(s);
PRINT_QP("%s", "\n");
s->mb_x= 0;
}
assert(s->mb_x==0 && s->mb_y==s->mb_height);
// handle formats which dont have unique end markers
if(s->msmpeg4_version || (s->workaround_bugs&FF_BUG_NO_PADDING)){ //FIXME perhaps solve this more cleanly
int left= s->gb.size*8 - get_bits_count(&s->gb);
int max_extra=7;
/* no markers in M$ crap */
if(s->msmpeg4_version && s->pict_type==I_TYPE)
max_extra+= 17;
/* buggy padding but the frame should still end approximately at the bitstream end */
if((s->workaround_bugs&FF_BUG_NO_PADDING) && s->error_resilience>=3)
max_extra+= 48;
else if((s->workaround_bugs&FF_BUG_NO_PADDING))
max_extra+= 256*256*256*64;
if(left>max_extra){
fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));
}
else if(left<0){
fprintf(stderr, "overreading %d bits\n", -left);
}else
s->error_status_table[s->mb_num-1]|= AC_END|MV_END|DC_END;
return 0;
}
fprintf(stderr, "slice end not reached but screenspace end (%d left %06X)\n",
s->gb.size*8 - get_bits_count(&s->gb),
show_bits(&s->gb, 24));
return -1;
}
static int h263_decode_frame(AVCodecContext *avctx, static int h263_decode_frame(AVCodecContext *avctx,
void *data, int *data_size, void *data, int *data_size,
UINT8 *buf, int buf_size) UINT8 *buf, int buf_size)
{ {
MpegEncContext *s = avctx->priv_data; MpegEncContext *s = avctx->priv_data;
int ret; int ret,i;
AVPicture *pict = data; AVPicture *pict = data;
#ifdef PRINT_FRAME_TIME #ifdef PRINT_FRAME_TIME
uint64_t time= rdtsc(); uint64_t time= rdtsc();
@ -145,10 +289,6 @@ uint64_t time= rdtsc();
s->hurry_up= avctx->hurry_up; s->hurry_up= avctx->hurry_up;
s->error_resilience= avctx->error_resilience; s->error_resilience= avctx->error_resilience;
s->workaround_bugs= avctx->workaround_bugs;
if(s->avctx->fourcc == ff_get_fourcc("XVIX") && s->workaround_bugs==0)
s->workaround_bugs=2;
s->flags= avctx->flags; s->flags= avctx->flags;
*data_size = 0; *data_size = 0;
@ -165,7 +305,7 @@ uint64_t time= rdtsc();
s->bitstream_buffer_size=0; s->bitstream_buffer_size=0;
if (!s->context_initialized) { if (!s->context_initialized) {
if (MPV_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix if (DCT_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix
return -1; return -1;
} }
@ -181,6 +321,37 @@ uint64_t time= rdtsc();
ret = h263_decode_picture_header(s); ret = h263_decode_picture_header(s);
} }
avctx->has_b_frames= s->has_b_frames; avctx->has_b_frames= s->has_b_frames;
if(s->workaround_bugs&FF_BUG_AUTODETECT){
if(s->avctx->fourcc == ff_get_fourcc("XVIX"))
s->workaround_bugs|= FF_BUG_XVID_ILACE;
if(s->avctx->fourcc == ff_get_fourcc("MP4S"))
s->workaround_bugs|= FF_BUG_AC_VLC;
if(s->avctx->fourcc == ff_get_fourcc("M4S2"))
s->workaround_bugs|= FF_BUG_AC_VLC;
if(s->avctx->fourcc == ff_get_fourcc("UMP4")){
s->workaround_bugs|= FF_BUG_UMP4;
s->workaround_bugs|= FF_BUG_AC_VLC;
}
if(s->divx_version==500)
s->workaround_bugs|= FF_BUG_NO_PADDING;
/* very ugly XVID padding bug detection FIXME/XXX solve this differently
* lets hope this at least works
*/
if( s->resync_marker==0 && s->data_partitioning==0 && s->divx_version==0
&& s->codec_id==CODEC_ID_MPEG4 && s->vo_type==0)
s->workaround_bugs|= FF_BUG_NO_PADDING;
if(s->lavc_build && s->lavc_build<4609) //FIXME not sure about the version num but a 4609 file seems ok
s->workaround_bugs|= FF_BUG_NO_PADDING;
}
#if 0 // dump bits per frame / qp / complexity #if 0 // dump bits per frame / qp / complexity
{ {
static FILE *f=NULL; static FILE *f=NULL;
@ -210,6 +381,10 @@ uint64_t time= rdtsc();
avctx->aspected_width = s->aspected_width; avctx->aspected_width = s->aspected_width;
avctx->aspected_height = s->aspected_height; avctx->aspected_height = s->aspected_height;
} }
if (s->codec_id==CODEC_ID_H263 && s->codec_id==CODEC_ID_H263)
s->gob_index = ff_h263_get_gob_height(s);
if (MPV_common_init(s) < 0) if (MPV_common_init(s) < 0)
return -1; return -1;
} }
@ -238,11 +413,8 @@ uint64_t time= rdtsc();
printf("qscale=%d\n", s->qscale); printf("qscale=%d\n", s->qscale);
#endif #endif
/* init resync/ error resilience specific variables */ if(s->error_resilience)
s->next_resync_qscale= s->qscale; memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_num*sizeof(UINT8));
s->next_resync_gb= s->gb;
if(s->resync_marker) s->mb_num_left= 0;
else s->mb_num_left= s->mb_num;
/* decode each macroblock */ /* decode each macroblock */
s->block_wrap[0]= s->block_wrap[0]=
@ -251,143 +423,25 @@ uint64_t time= rdtsc();
s->block_wrap[3]= s->mb_width*2 + 2; s->block_wrap[3]= s->mb_width*2 + 2;
s->block_wrap[4]= s->block_wrap[4]=
s->block_wrap[5]= s->mb_width + 2; s->block_wrap[5]= s->mb_width + 2;
for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) { s->mb_x=0;
/* Check for GOB headers on H.263 */ s->mb_y=0;
/* FIXME: In the future H.263+ will have intra prediction */
/* and we are gonna need another way to detect MPEG4 */ decode_slice(s);
if (s->mb_y && !s->h263_pred) { s->error_status_table[0]|= VP_START;
s->first_slice_line = h263_decode_gob_header(s); while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>32){
if(s->msmpeg4_version){
if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0)
break;
}else{
if(ff_h263_resync(s)<0)
break;
} }
if(s->msmpeg4_version==1){ if(s->msmpeg4_version!=4)
s->last_dc[0]=
s->last_dc[1]=
s->last_dc[2]= 128;
}
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1);
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1;
s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2);
s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1) + s->block_wrap[0]*(s->mb_height*2 + 2);
s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2);
for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
s->block_index[0]+=2;
s->block_index[1]+=2;
s->block_index[2]+=2;
s->block_index[3]+=2;
s->block_index[4]++;
s->block_index[5]++;
#ifdef DEBUG
printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
#endif
if(s->resync_marker){
if(s->mb_num_left<=0){
/* except the first block */
if(s->mb_x!=0 || s->mb_y!=0){
/* did we miss the next resync marker without noticing an error yet */
if(((get_bits_count(&s->gb)+8)&(~7)) != s->next_resync_pos && s->decoding_error==0){
fprintf(stderr, "slice end missmatch x:%d y:%d %d %d\n",
s->mb_x, s->mb_y, get_bits_count(&s->gb), s->next_resync_pos);
ff_conceal_past_errors(s, 1);
}
}
s->qscale= s->next_resync_qscale;
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
s->gb= s->next_resync_gb;
s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it
s->resync_mb_y= s->mb_y;
s->first_slice_line=1;
if(s->codec_id==CODEC_ID_MPEG4){
ff_mpeg4_clean_buffers(s); ff_mpeg4_clean_buffers(s);
ff_mpeg4_resync(s);
}
}
if( s->resync_mb_x==s->mb_x decode_slice(s);
&& s->resync_mb_y==s->mb_y && s->decoding_error!=0){ s->error_status_table[s->resync_mb_x + s->resync_mb_y*s->mb_width]|= VP_START;
fprintf(stderr, "resynced at %d %d\n", s->mb_x, s->mb_y);
s->decoding_error= 0;
}
}
//fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x);
/* DCT & quantize */
if(s->decoding_error!=DECODING_DESYNC){
int last_error= s->decoding_error;
clear_blocks(s->block[0]);
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
if (s->h263_msmpeg4) {
if (msmpeg4_decode_mb(s, s->block) < 0) {
fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
s->decoding_error=DECODING_DESYNC;
}
} else {
if (h263_decode_mb(s, s->block) < 0) {
fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
s->decoding_error=DECODING_DESYNC;
}
}
if(s->decoding_error!=last_error){
ff_conceal_past_errors(s, 0);
}
}
/* conceal errors */
if( s->decoding_error==DECODING_DESYNC
|| (s->decoding_error==DECODING_ACDC_LOST && s->mb_intra)){
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
s->mb_skiped=0;
s->mb_intra=0;
s->mv[0][0][0]=0; //FIXME this is not optimal
s->mv[0][0][1]=0;
clear_blocks(s->block[0]);
}else if(s->decoding_error && !s->mb_intra){
clear_blocks(s->block[0]);
}
//FIXME remove AC for intra
MPV_decode_mb(s, s->block);
s->mb_num_left--;
}
if ( avctx->draw_horiz_band
&& (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
UINT8 *src_ptr[3];
int y, h, offset;
y = s->mb_y * 16;
h = s->height - y;
if (h > 16)
h = 16;
if(s->pict_type==B_TYPE)
offset = 0;
else
offset = y * s->linesize;
if(s->pict_type==B_TYPE || (!s->has_b_frames)){
src_ptr[0] = s->current_picture[0] + offset;
src_ptr[1] = s->current_picture[1] + (offset >> 2);
src_ptr[2] = s->current_picture[2] + (offset >> 2);
} else {
src_ptr[0] = s->last_picture[0] + offset;
src_ptr[1] = s->last_picture[1] + (offset >> 2);
src_ptr[2] = s->last_picture[2] + (offset >> 2);
}
avctx->draw_horiz_band(avctx, src_ptr, s->linesize,
y, s->width, h);
}
} }
if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE) if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE)
@ -414,21 +468,34 @@ uint64_t time= rdtsc();
} }
} }
if(s->bitstream_buffer_size==0 && s->error_resilience>0){ if(s->error_resilience){
int left= s->gb.size*8 - get_bits_count(&s->gb); int error=0, num_end_markers=0;
int max_extra=8; for(i=0; i<s->mb_num; i++){
int status= s->error_status_table[i];
#if 0
if(i%s->mb_width == 0) printf("\n");
printf("%2X ", status);
#endif
if(status==0) continue;
if(s->codec_id==CODEC_ID_MPEG4) max_extra+=32; if(status&(DC_ERROR|AC_ERROR|MV_ERROR))
error=1;
if(left>max_extra){ if(status&VP_START){
fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24)); if(num_end_markers)
if(s->decoding_error==0) error=1;
ff_conceal_past_errors(s, 1); num_end_markers=3;
} }
if(left<0){ if(status&AC_END)
fprintf(stderr, "overreading %d bits\n", -left); num_end_markers--;
if(s->decoding_error==0) if(status&DC_END)
ff_conceal_past_errors(s, 1); num_end_markers--;
if(status&MV_END)
num_end_markers--;
}
if(num_end_markers || error){
fprintf(stderr, "concealing errors\n");
//printf("type:%d\n", s->pict_type);
ff_error_resilience(s);
} }
} }

View File

@ -166,4 +166,6 @@ UINT8 ff_mpeg4_c_dc_scale_table[32]={
0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,21,22,23,24,25 0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,21,22,23,24,25
}; };
const UINT16 ff_mpeg4_resync_prefix[8]={
0x7F00, 0x7E00, 0x7C00, 0x7800, 0x7000, 0x6000, 0x4000, 0x0000
};

View File

@ -134,19 +134,7 @@ static void convert_matrix(MpegEncContext *s, int (*qmat)[64], uint16_t (*qmat16
goto fail;\ goto fail;\
}\ }\
} }
/*
static void build_end(void)
{
int lastIndex;
int lastIndexAfterPerm=0;
for(lastIndex=0; lastIndex<64; lastIndex++)
{
if(ff_zigzag_direct[lastIndex] > lastIndexAfterPerm)
lastIndexAfterPerm= ff_zigzag_direct[lastIndex];
zigzag_end[lastIndex]= lastIndexAfterPerm + 1;
}
}
*/
void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable){ void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable){
int i; int i;
int end; int end;
@ -344,6 +332,8 @@ int MPV_common_init(MpegEncContext *s)
CHECKED_ALLOCZ(s->avctx->stats_out, 256); CHECKED_ALLOCZ(s->avctx->stats_out, 256);
} }
CHECKED_ALLOCZ(s->error_status_table, s->mb_num*sizeof(UINT8))
if (s->out_format == FMT_H263 || s->encoding) { if (s->out_format == FMT_H263 || s->encoding) {
int size; int size;
/* Allocate MB type table */ /* Allocate MB type table */
@ -355,11 +345,13 @@ int MPV_common_init(MpegEncContext *s)
} }
if(s->codec_id==CODEC_ID_MPEG4){ if(s->codec_id==CODEC_ID_MPEG4){
/* 4mv and interlaced direct mode decoding tables */ /* interlaced direct mode decoding tables */
CHECKED_ALLOCZ(s->co_located_type_table, s->mb_num * sizeof(UINT8))
CHECKED_ALLOCZ(s->field_mv_table, s->mb_num*2*2 * sizeof(INT16)) CHECKED_ALLOCZ(s->field_mv_table, s->mb_num*2*2 * sizeof(INT16))
CHECKED_ALLOCZ(s->field_select_table, s->mb_num*2* sizeof(INT8)) CHECKED_ALLOCZ(s->field_select_table, s->mb_num*2* sizeof(INT8))
} }
/* 4mv b frame decoding table */
//note this is needed for h263 without b frames too (segfault on damaged streams otherwise)
CHECKED_ALLOCZ(s->co_located_type_table, s->mb_num * sizeof(UINT8))
if (s->h263_pred || s->h263_plus) { if (s->h263_pred || s->h263_plus) {
int y_size, c_size, i, size; int y_size, c_size, i, size;
@ -400,7 +392,8 @@ int MPV_common_init(MpegEncContext *s)
s->picture_structure = PICT_FRAME; s->picture_structure = PICT_FRAME;
/* init macroblock skip table */ /* init macroblock skip table */
CHECKED_ALLOCZ(s->mbskip_table, s->mb_num); CHECKED_ALLOCZ(s->mbskip_table, s->mb_num+1);
//Note the +1 is for a quicker mpeg4 slice_end detection
s->block= s->blocks[0]; s->block= s->blocks[0];
@ -453,6 +446,7 @@ void MPV_common_end(MpegEncContext *s)
av_freep(&s->field_select_table); av_freep(&s->field_select_table);
av_freep(&s->avctx->stats_out); av_freep(&s->avctx->stats_out);
av_freep(&s->ac_stats); av_freep(&s->ac_stats);
av_freep(&s->error_status_table);
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
int j; int j;
@ -767,7 +761,6 @@ void MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
UINT8 *tmp; UINT8 *tmp;
s->mb_skiped = 0; s->mb_skiped = 0;
s->decoding_error=0;
avctx->mbskip_table= s->mbskip_table; avctx->mbskip_table= s->mbskip_table;
if(avctx->flags&CODEC_FLAG_DR1){ if(avctx->flags&CODEC_FLAG_DR1){
@ -1997,6 +1990,36 @@ static int pix_diff_vcmp16x8(UINT8 *s1, UINT8*s2, int stride){ //FIXME move to d
} }
#endif #endif
void ff_draw_horiz_band(MpegEncContext *s){
if ( s->avctx->draw_horiz_band
&& (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
UINT8 *src_ptr[3];
int y, h, offset;
y = s->mb_y * 16;
h = s->height - y;
if (h > 16)
h = 16;
if(s->pict_type==B_TYPE)
offset = 0;
else
offset = y * s->linesize;
if(s->pict_type==B_TYPE || (!s->has_b_frames)){
src_ptr[0] = s->current_picture[0] + offset;
src_ptr[1] = s->current_picture[1] + (offset >> 2);
src_ptr[2] = s->current_picture[2] + (offset >> 2);
} else {
src_ptr[0] = s->last_picture[0] + offset;
src_ptr[1] = s->last_picture[1] + (offset >> 2);
src_ptr[2] = s->last_picture[2] + (offset >> 2);
}
s->avctx->draw_horiz_band(s->avctx, src_ptr, s->linesize,
y, s->width, h);
}
}
static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
{ {
const int mb_x= s->mb_x; const int mb_x= s->mb_x;
@ -2539,23 +2562,17 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->last_mv[0][0][0] = 0; s->last_mv[0][0][0] = 0;
s->last_mv[0][0][1] = 0; s->last_mv[0][0][1] = 0;
/* Get the GOB height based on picture height */ if (s->codec_id==CODEC_ID_H263 && s->codec_id==CODEC_ID_H263)
if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4) { s->gob_index = ff_h263_get_gob_height(s);
if (s->height <= 400)
s->gob_index = 1;
else if (s->height <= 800)
s->gob_index = 2;
else else
s->gob_index = 4; s->gob_index = 1; //FIXME remove
}else if(s->codec_id==CODEC_ID_MPEG4){
s->gob_index = 1;
}
if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE) if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame)
ff_mpeg4_init_partitions(s); ff_mpeg4_init_partitions(s);
s->resync_mb_x=0; s->resync_mb_x=0;
s->resync_mb_y=0; s->resync_mb_y=0;
s->first_slice_line = 1;
for(mb_y=0; mb_y < s->mb_height; mb_y++) { for(mb_y=0; mb_y < s->mb_height; mb_y++) {
/* Put GOB header based on RTP MTU for formats which support it per line (H263*)*/ /* Put GOB header based on RTP MTU for formats which support it per line (H263*)*/
/* TODO: Put all this stuff in a separate generic function */ /* TODO: Put all this stuff in a separate generic function */
@ -2599,7 +2616,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->block_index[3]+=2; s->block_index[3]+=2;
s->block_index[4]++; s->block_index[4]++;
s->block_index[5]++; s->block_index[5]++;
//printf("%d %d %d %d %d\n", s->mb_x, s->mb_y, s->resync_mb_x, s->resync_mb_y, s->first_slice_line);
/* write gob / video packet header for formats which support it at any MB (MPEG4) */ /* write gob / video packet header for formats which support it at any MB (MPEG4) */
if(s->rtp_mode && s->mb_y>0 && s->codec_id==CODEC_ID_MPEG4){ if(s->rtp_mode && s->mb_y>0 && s->codec_id==CODEC_ID_MPEG4){
int pdif= pbBufPtr(&s->pb) - s->ptr_lastgob; int pdif= pbBufPtr(&s->pb) - s->ptr_lastgob;
@ -2607,7 +2624,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
//the *2 is there so we stay below the requested size //the *2 is there so we stay below the requested size
if(pdif + s->mb_line_avgsize/s->mb_width >= s->rtp_payload_size){ if(pdif + s->mb_line_avgsize/s->mb_width >= s->rtp_payload_size){
if(s->codec_id==CODEC_ID_MPEG4){ if(s->codec_id==CODEC_ID_MPEG4){
if(s->data_partitioning && s->pict_type!=B_TYPE){ if(s->partitioned_frame){
ff_mpeg4_merge_partitions(s); ff_mpeg4_merge_partitions(s);
ff_mpeg4_init_partitions(s); ff_mpeg4_init_partitions(s);
} }
@ -2625,12 +2642,12 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->resync_mb_x=mb_x; s->resync_mb_x=mb_x;
s->resync_mb_y=mb_y; s->resync_mb_y=mb_y;
} }
}
if( (s->resync_mb_x == s->mb_x) if( (s->resync_mb_x == s->mb_x)
&& s->resync_mb_y+1 == s->mb_y){ && s->resync_mb_y+1 == s->mb_y){
s->first_slice_line=0; s->first_slice_line=0;
} }
}
if(mb_type & (mb_type-1)){ // more than 1 MB type possible if(mb_type & (mb_type-1)){ // more than 1 MB type possible
int next_block=0; int next_block=0;
@ -2639,6 +2656,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
copy_context_before_encode(&backup_s, s, -1); copy_context_before_encode(&backup_s, s, -1);
backup_s.pb= s->pb; backup_s.pb= s->pb;
best_s.data_partitioning= s->data_partitioning; best_s.data_partitioning= s->data_partitioning;
best_s.partitioned_frame= s->partitioned_frame;
if(s->data_partitioning){ if(s->data_partitioning){
backup_s.pb2= s->pb2; backup_s.pb2= s->pb2;
backup_s.tex_pb= s->tex_pb; backup_s.tex_pb= s->tex_pb;
@ -2827,7 +2845,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
} }
emms_c(); emms_c();
if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE) if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame)
ff_mpeg4_merge_partitions(s); ff_mpeg4_merge_partitions(s);
if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE) if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE)
@ -3090,119 +3108,6 @@ static void dct_unquantize_h263_c(MpegEncContext *s,
} }
} }
static void remove_ac(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
{
int dc, dcb, dcr, y, i;
for(i=0; i<4; i++){
dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
}
}
}
dcb = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
dcr= s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
for(y=0; y<8; y++){
int x;
for(x=0; x<8; x++){
dest_cb[x + y*(s->uvlinesize)]= dcb/8;
dest_cr[x + y*(s->uvlinesize)]= dcr/8;
}
}
}
/**
* will conceal past errors, and allso drop b frames if needed
*
*/
void ff_conceal_past_errors(MpegEncContext *s, int unknown_pos)
{
int mb_x= s->mb_x;
int mb_y= s->mb_y;
int mb_dist=0;
int i, intra_count=0, inter_count=0;
int intra_conceal= s->msmpeg4_version ? 50 : 50; //FIXME finetune
int inter_conceal= s->msmpeg4_version ? 50 : 50;
// for last block
if(mb_x>=s->mb_width) mb_x= s->mb_width -1;
if(mb_y>=s->mb_height) mb_y= s->mb_height-1;
if(s->decoding_error==0 && unknown_pos){
if(s->data_partitioning && s->pict_type!=B_TYPE)
s->decoding_error= DECODING_AC_LOST;
else
s->decoding_error= DECODING_DESYNC;
}
if(s->decoding_error==DECODING_DESYNC && s->pict_type!=B_TYPE) s->next_p_frame_damaged=1;
for(i=mb_x + mb_y*s->mb_width; i>=0; i--){
if(s->mbintra_table[i]) intra_count++;
else inter_count++;
}
if(s->decoding_error==DECODING_AC_LOST){
intra_conceal*=2;
inter_conceal*=2;
}else if(s->decoding_error==DECODING_ACDC_LOST){
intra_conceal*=2;
inter_conceal*=2;
}
if(unknown_pos && (intra_count<inter_count)){
intra_conceal= inter_conceal= s->mb_num;
// printf("%d %d\n",intra_count, inter_count);
}
fprintf(stderr, "concealing errors\n");
/* for all MBs from the current one back until the last resync marker */
for(; mb_y>=0 && mb_y>=s->resync_mb_y; mb_y--){
for(; mb_x>=0; mb_x--){
uint8_t *dest_y = s->current_picture[0] + (mb_y * 16* s->linesize ) + mb_x * 16;
uint8_t *dest_cb = s->current_picture[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
uint8_t *dest_cr = s->current_picture[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
int mb_x_backup= s->mb_x; //FIXME pass xy to mpeg_motion
int mb_y_backup= s->mb_y;
s->mb_x=mb_x;
s->mb_y=mb_y;
if(s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<intra_conceal){
if(s->decoding_error==DECODING_AC_LOST){
remove_ac(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
// printf("remove ac to %d %d\n", mb_x, mb_y);
}else{
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
s->last_picture, 0, 0, put_pixels_tab,
0/*mx*/, 0/*my*/, 16);
}
}
else if(!s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<inter_conceal){
int mx=0;
int my=0;
if(s->decoding_error!=DECODING_DESYNC){
int xy= mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2);
mx= s->motion_val[ xy ][0];
my= s->motion_val[ xy ][1];
}
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
s->last_picture, 0, 0, put_pixels_tab,
mx, my, 16);
}
s->mb_x= mb_x_backup;
s->mb_y= mb_y_backup;
if(mb_x== s->resync_mb_x && mb_y== s->resync_mb_y) return;
if(!s->mbskip_table[mb_x + mb_y*s->mb_width]) mb_dist++;
}
mb_x=s->mb_width-1;
}
}
AVCodec mpeg1video_encoder = { AVCodec mpeg1video_encoder = {
"mpeg1video", "mpeg1video",
CODEC_TYPE_VIDEO, CODEC_TYPE_VIDEO,

View File

@ -322,16 +322,20 @@ typedef struct MpegEncContext {
int last_bits; //temp var used for calculating the above vars int last_bits; //temp var used for calculating the above vars
/* error concealment / resync */ /* error concealment / resync */
UINT8 *error_status_table; /* table of the error status of each MB */
#define VP_START 1 /* current MB is the first after a resync marker */
#define AC_ERROR 2
#define DC_ERROR 4
#define MV_ERROR 8
#define AC_END 16
#define DC_END 32
#define MV_END 64
//FIXME some prefix?
int resync_mb_x; /* x position of last resync marker */ int resync_mb_x; /* x position of last resync marker */
int resync_mb_y; /* y position of last resync marker */ int resync_mb_y; /* y position of last resync marker */
int mb_num_left; /* number of MBs left in this video packet */ GetBitContext last_resync_gb; /* used to serach for the next resync marker */
GetBitContext next_resync_gb; /* starts at the next resync marker */ int mb_num_left; /* number of MBs left in this video packet (for partitioned Slices only)*/
int next_resync_qscale; /* qscale of next resync marker */
int next_resync_pos; /* bitstream position of next resync marker */
#define DECODING_AC_LOST -1
#define DECODING_ACDC_LOST -2
#define DECODING_DESYNC -3
int decoding_error;
int next_p_frame_damaged; /* set if the next p frame is damaged, to avoid showing trashed b frames */ int next_p_frame_damaged; /* set if the next p frame is damaged, to avoid showing trashed b frames */
int error_resilience; int error_resilience;
@ -381,7 +385,8 @@ typedef struct MpegEncContext {
int aspected_height; int aspected_height;
int sprite_warping_accuracy; int sprite_warping_accuracy;
int low_latency_sprite; int low_latency_sprite;
int data_partitioning; int data_partitioning; /* data partitioning flag from header */
int partitioned_frame; /* is current frame partitioned */
int rvlc; /* reversible vlc */ int rvlc; /* reversible vlc */
int resync_marker; /* could this stream contain resync markers*/ int resync_marker; /* could this stream contain resync markers*/
int low_delay; /* no reordering needed / has no b-frames */ int low_delay; /* no reordering needed / has no b-frames */
@ -407,6 +412,10 @@ typedef struct MpegEncContext {
UINT8 *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them UINT8 *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them
int bitstream_buffer_size; int bitstream_buffer_size;
/* lavc specific stuff, used to workaround bugs in libavcodec */
int ffmpeg_version;
int lavc_build;
/* RV10 specific */ /* RV10 specific */
int rv10_version; /* RV10 version: 0 or 3 */ int rv10_version; /* RV10 version: 0 or 3 */
int rv10_first_dc_coded[3]; int rv10_first_dc_coded[3];
@ -475,6 +484,12 @@ typedef struct MpegEncContext {
DCTELEM (*block)[64]; /* points to one of the following blocks */ DCTELEM (*block)[64]; /* points to one of the following blocks */
DCTELEM blocks[2][6][64] __align8; // for HQ mode we need to keep the best block DCTELEM blocks[2][6][64] __align8; // for HQ mode we need to keep the best block
int (*decode_mb)(struct MpegEncContext *s, DCTELEM block[6][64]); // used by some codecs to avoid a switch()
#define SLICE_OK 0
#define SLICE_ERROR -1
#define SLICE_END -2 //end marker found
#define SLICE_NOEND -3 //no end marker or error found but mb count exceeded
void (*dct_unquantize_mpeg1)(struct MpegEncContext *s, void (*dct_unquantize_mpeg1)(struct MpegEncContext *s,
DCTELEM *block, int n, int qscale); DCTELEM *block, int n, int qscale);
void (*dct_unquantize_mpeg2)(struct MpegEncContext *s, void (*dct_unquantize_mpeg2)(struct MpegEncContext *s,
@ -489,6 +504,7 @@ typedef struct MpegEncContext {
void (*idct_add)(UINT8 *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/); void (*idct_add)(UINT8 *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
} MpegEncContext; } MpegEncContext;
int DCT_common_init(MpegEncContext *s); int DCT_common_init(MpegEncContext *s);
int MPV_common_init(MpegEncContext *s); int MPV_common_init(MpegEncContext *s);
void MPV_common_end(MpegEncContext *s); void MPV_common_end(MpegEncContext *s);
@ -512,9 +528,30 @@ void ff_conceal_past_errors(MpegEncContext *s, int conceal_all);
void ff_copy_bits(PutBitContext *pb, UINT8 *src, int length); void ff_copy_bits(PutBitContext *pb, UINT8 *src, int length);
void ff_clean_intra_table_entries(MpegEncContext *s); void ff_clean_intra_table_entries(MpegEncContext *s);
void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable); void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable);
void ff_error_resilience(MpegEncContext *s);
void ff_draw_horiz_band(MpegEncContext *s);
extern int ff_bit_exact; extern int ff_bit_exact;
static inline void ff_init_block_index(MpegEncContext *s){
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2;
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1) + s->mb_x*2;
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2) + s->mb_x*2;
s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
}
static inline void ff_update_block_index(MpegEncContext *s){
s->block_index[0]+=2;
s->block_index[1]+=2;
s->block_index[2]+=2;
s->block_index[3]+=2;
s->block_index[4]++;
s->block_index[5]++;
}
/* motion_est.c */ /* motion_est.c */
void ff_estimate_p_frame_motion(MpegEncContext * s, void ff_estimate_p_frame_motion(MpegEncContext * s,
int mb_x, int mb_y); int mb_x, int mb_y);
@ -524,6 +561,7 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type);
void ff_fix_long_p_mvs(MpegEncContext * s); void ff_fix_long_p_mvs(MpegEncContext * s);
void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type); void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type);
/* mpeg12.c */ /* mpeg12.c */
extern const INT16 ff_mpeg1_default_intra_matrix[64]; extern const INT16 ff_mpeg1_default_intra_matrix[64];
extern const INT16 ff_mpeg1_default_non_intra_matrix[64]; extern const INT16 ff_mpeg1_default_non_intra_matrix[64];
@ -535,6 +573,7 @@ void mpeg1_encode_mb(MpegEncContext *s,
int motion_x, int motion_y); int motion_x, int motion_y);
void ff_mpeg1_encode_init(MpegEncContext *s); void ff_mpeg1_encode_init(MpegEncContext *s);
/* h263enc.c */ /* h263enc.c */
typedef struct RLTable { typedef struct RLTable {
int n; /* number of entries of table_vlc minus 1 */ int n; /* number of entries of table_vlc minus 1 */
@ -567,7 +606,6 @@ extern UINT8 ff_mpeg4_y_dc_scale_table[32];
extern UINT8 ff_mpeg4_c_dc_scale_table[32]; extern UINT8 ff_mpeg4_c_dc_scale_table[32];
extern const INT16 ff_mpeg4_default_intra_matrix[64]; extern const INT16 ff_mpeg4_default_intra_matrix[64];
extern const INT16 ff_mpeg4_default_non_intra_matrix[64]; extern const INT16 ff_mpeg4_default_non_intra_matrix[64];
void h263_encode_mb(MpegEncContext *s, void h263_encode_mb(MpegEncContext *s,
DCTELEM block[6][64], DCTELEM block[6][64],
int motion_x, int motion_y); int motion_x, int motion_y);
@ -583,30 +621,32 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
void ff_set_mpeg4_time(MpegEncContext * s, int picture_number); void ff_set_mpeg4_time(MpegEncContext * s, int picture_number);
void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
void h263_encode_init(MpegEncContext *s); void h263_encode_init(MpegEncContext *s);
void h263_decode_init_vlc(MpegEncContext *s); void h263_decode_init_vlc(MpegEncContext *s);
int h263_decode_picture_header(MpegEncContext *s); int h263_decode_picture_header(MpegEncContext *s);
int h263_decode_gob_header(MpegEncContext *s); int ff_h263_decode_gob_header(MpegEncContext *s);
int mpeg4_decode_picture_header(MpegEncContext * s); int mpeg4_decode_picture_header(MpegEncContext * s);
int intel_h263_decode_picture_header(MpegEncContext *s); int intel_h263_decode_picture_header(MpegEncContext *s);
int h263_decode_mb(MpegEncContext *s, int ff_h263_decode_mb(MpegEncContext *s,
DCTELEM block[6][64]); DCTELEM block[6][64]);
int h263_get_picture_format(int width, int height); int h263_get_picture_format(int width, int height);
int ff_mpeg4_decode_video_packet_header(MpegEncContext *s);
int ff_mpeg4_resync(MpegEncContext *s);
void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s);
void ff_mpeg4_clean_buffers(MpegEncContext *s); void ff_mpeg4_clean_buffers(MpegEncContext *s);
void ff_mpeg4_stuffing(PutBitContext * pbc); void ff_mpeg4_stuffing(PutBitContext * pbc);
void ff_mpeg4_init_partitions(MpegEncContext *s); void ff_mpeg4_init_partitions(MpegEncContext *s);
void ff_mpeg4_merge_partitions(MpegEncContext *s); void ff_mpeg4_merge_partitions(MpegEncContext *s);
extern inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr);
void ff_clean_mpeg4_qscales(MpegEncContext *s); void ff_clean_mpeg4_qscales(MpegEncContext *s);
void ff_clean_h263_qscales(MpegEncContext *s); void ff_clean_h263_qscales(MpegEncContext *s);
int ff_mpeg4_decode_partitions(MpegEncContext *s);
int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
int ff_h263_resync(MpegEncContext *s);
int ff_h263_get_gob_height(MpegEncContext *s);
/* rv10.c */ /* rv10.c */
void rv10_encode_picture_header(MpegEncContext *s, int picture_number); void rv10_encode_picture_header(MpegEncContext *s, int picture_number);
int rv_decode_dc(MpegEncContext *s, int n); int rv_decode_dc(MpegEncContext *s, int n);
/* msmpeg4.c */ /* msmpeg4.c */
void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number); void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number);
void msmpeg4_encode_ext_header(MpegEncContext * s); void msmpeg4_encode_ext_header(MpegEncContext * s);
@ -615,13 +655,11 @@ void msmpeg4_encode_mb(MpegEncContext * s,
int motion_x, int motion_y); int motion_x, int motion_y);
int msmpeg4_decode_picture_header(MpegEncContext * s); int msmpeg4_decode_picture_header(MpegEncContext * s);
int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size); int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size);
int msmpeg4_decode_mb(MpegEncContext *s,
DCTELEM block[6][64]);
int ff_msmpeg4_decode_init(MpegEncContext *s); int ff_msmpeg4_decode_init(MpegEncContext *s);
void ff_msmpeg4_encode_init(MpegEncContext *s); void ff_msmpeg4_encode_init(MpegEncContext *s);
/* mjpegenc.c */
/* mjpegenc.c */
int mjpeg_init(MpegEncContext *s); int mjpeg_init(MpegEncContext *s);
void mjpeg_close(MpegEncContext *s); void mjpeg_close(MpegEncContext *s);
void mjpeg_encode_mb(MpegEncContext *s, void mjpeg_encode_mb(MpegEncContext *s,
@ -629,6 +667,7 @@ void mjpeg_encode_mb(MpegEncContext *s,
void mjpeg_picture_header(MpegEncContext *s); void mjpeg_picture_header(MpegEncContext *s);
void mjpeg_picture_trailer(MpegEncContext *s); void mjpeg_picture_trailer(MpegEncContext *s);
/* rate control */ /* rate control */
int ff_rate_control_init(MpegEncContext *s); int ff_rate_control_init(MpegEncContext *s);
float ff_rate_estimate_qscale(MpegEncContext *s); float ff_rate_estimate_qscale(MpegEncContext *s);

View File

@ -61,7 +61,8 @@ static void msmpeg4v2_encode_motion(MpegEncContext * s, int val);
static void init_h263_dc_for_msmpeg4(void); static void init_h263_dc_for_msmpeg4(void);
static inline void msmpeg4_memsetw(short *tab, int val, int n); static inline void msmpeg4_memsetw(short *tab, int val, int n);
static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra); static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra);
static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
extern UINT32 inverse[256]; extern UINT32 inverse[256];
@ -504,26 +505,7 @@ static inline void handle_slices(MpegEncContext *s){
if (s->mb_x == 0) { if (s->mb_x == 0) {
if (s->slice_height && (s->mb_y % s->slice_height) == 0) { if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
if(s->msmpeg4_version != 4){ if(s->msmpeg4_version != 4){
int wrap; ff_mpeg4_clean_buffers(s);
/* reset DC pred (set previous line to 1024) */
wrap = 2 * s->mb_width + 2;
msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap],
1024, 2 * s->mb_width);
wrap = s->mb_width + 2;
msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap],
1024, s->mb_width);
msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap],
1024, s->mb_width);
/* reset AC pred (set previous line to 0) */
wrap = s->mb_width * 2 + 2;
msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
0, 2 * s->mb_width*16);
wrap = s->mb_width + 2;
msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
0, s->mb_width*16);
msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
0, s->mb_width*16);
} }
s->first_slice_line = 1; s->first_slice_line = 1;
} else { } else {
@ -711,6 +693,10 @@ static inline int msmpeg4_pred_dc(MpegEncContext * s, int n,
b = dc_val[ - 1 - wrap]; b = dc_val[ - 1 - wrap];
c = dc_val[ - wrap]; c = dc_val[ - wrap];
if(s->first_slice_line && (n&2)==0){
b=c=1024;
}
/* XXX: the following solution consumes divisions, but it does not /* XXX: the following solution consumes divisions, but it does not
necessitate to modify mpegvideo.c. The problem comes from the necessitate to modify mpegvideo.c. The problem comes from the
fact they decided to store the quantized DC (which would lead fact they decided to store the quantized DC (which would lead
@ -941,6 +927,7 @@ static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int
for(last_index=63; last_index>=0; last_index--){ for(last_index=63; last_index>=0; last_index--){
if(block[scantable[last_index]]) break; if(block[scantable[last_index]]) break;
} }
s->block_last_index[n]= last_index;
}else }else
last_index = s->block_last_index[n]; last_index = s->block_last_index[n];
/* AC coefs */ /* AC coefs */
@ -1170,6 +1157,18 @@ int ff_msmpeg4_decode_init(MpegEncContext *s)
&table_inter_intra[0][1], 2, 1, &table_inter_intra[0][1], 2, 1,
&table_inter_intra[0][0], 2, 1); &table_inter_intra[0][0], 2, 1);
} }
switch(s->msmpeg4_version){
case 1:
case 2:
s->decode_mb= msmpeg4v12_decode_mb;
break;
case 3:
case 4:
s->decode_mb= msmpeg4v34_decode_mb;
break;
}
return 0; return 0;
} }
@ -1444,11 +1443,12 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
return val; return val;
} }
static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
static int msmpeg4v12_decode_mb(MpegEncContext *s,
DCTELEM block[6][64])
{ {
int cbp, code, i; int cbp, code, i;
s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
if (s->pict_type == P_TYPE) { if (s->pict_type == P_TYPE) {
if (s->use_skip_mb_code) { if (s->use_skip_mb_code) {
if (get_bits1(&s->gb)) { if (get_bits1(&s->gb)) {
@ -1530,8 +1530,7 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
return 0; return 0;
} }
int msmpeg4_decode_mb(MpegEncContext *s, static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
DCTELEM block[6][64])
{ {
int cbp, code, i; int cbp, code, i;
UINT8 *coded_val; UINT8 *coded_val;
@ -1542,10 +1541,8 @@ if(s->mb_x==0){
if(s->mb_y==0) printf("\n"); if(s->mb_y==0) printf("\n");
} }
#endif #endif
/* special slice handling */
handle_slices(s);
if(s->msmpeg4_version<=2) return msmpeg4v12_decode_mb(s, block); //FIXME export function & call from outside perhaps s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
if (s->pict_type == P_TYPE) { if (s->pict_type == P_TYPE) {
set_stat(ST_INTER_MB); set_stat(ST_INTER_MB);
@ -1866,7 +1863,7 @@ static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
i-= 192; i-= 192;
if(i&(~63)){ if(i&(~63)){
const int left= s->gb.size*8 - get_bits_count(&s->gb); const int left= s->gb.size*8 - get_bits_count(&s->gb);
if(((i+192 == 64 && level/qmul==-1) || s->error_resilience<0) && left>=0){ if(((i+192 == 64 && level/qmul==-1) || s->error_resilience<=1) && left>=0){
fprintf(stderr, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y); fprintf(stderr, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y);
break; break;
}else{ }else{

View File

@ -365,6 +365,7 @@ static int rv10_decode_init(AVCodecContext *avctx)
s->y_dc_scale_table= s->y_dc_scale_table=
s->c_dc_scale_table= ff_mpeg1_dc_scale_table; s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
s->progressive_sequence=1;
/* init rv vlc */ /* init rv vlc */
if (!done) { if (!done) {
@ -393,7 +394,6 @@ static int rv10_decode_packet(AVCodecContext *avctx,
{ {
MpegEncContext *s = avctx->priv_data; MpegEncContext *s = avctx->priv_data;
int i, mb_count, mb_pos, left; int i, mb_count, mb_pos, left;
DCTELEM block[6][64];
init_get_bits(&s->gb, buf, buf_size); init_get_bits(&s->gb, buf, buf_size);
@ -430,47 +430,35 @@ static int rv10_decode_packet(AVCodecContext *avctx,
s->rv10_first_dc_coded[1] = 0; s->rv10_first_dc_coded[1] = 0;
s->rv10_first_dc_coded[2] = 0; s->rv10_first_dc_coded[2] = 0;
if(s->mb_y==0) s->first_slice_line=1;
s->block_wrap[0]= s->block_wrap[0]=
s->block_wrap[1]= s->block_wrap[1]=
s->block_wrap[2]= s->block_wrap[2]=
s->block_wrap[3]= s->mb_width*2 + 2; s->block_wrap[3]= s->mb_width*2 + 2;
s->block_wrap[4]= s->block_wrap[4]=
s->block_wrap[5]= s->mb_width + 2; s->block_wrap[5]= s->mb_width + 2;
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2; ff_init_block_index(s);
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1) + s->mb_x*2;
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2) + s->mb_x*2;
s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
/* decode each macroblock */ /* decode each macroblock */
for(i=0;i<mb_count;i++) { for(i=0;i<mb_count;i++) {
s->block_index[0]+=2; ff_update_block_index(s);
s->block_index[1]+=2;
s->block_index[2]+=2;
s->block_index[3]+=2;
s->block_index[4]++;
s->block_index[5]++;
#ifdef DEBUG #ifdef DEBUG
printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
#endif #endif
memset(block, 0, sizeof(block)); clear_blocks(s->block[0]);
s->mv_dir = MV_DIR_FORWARD; s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
if (h263_decode_mb(s, block) < 0) { if (ff_h263_decode_mb(s, s->block) == SLICE_ERROR) {
fprintf(stderr, "ERROR at MB %d %d\n", s->mb_x, s->mb_y); fprintf(stderr, "ERROR at MB %d %d\n", s->mb_x, s->mb_y);
return -1; return -1;
} }
MPV_decode_mb(s, block); MPV_decode_mb(s, s->block);
if (++s->mb_x == s->mb_width) { if (++s->mb_x == s->mb_width) {
s->mb_x = 0; s->mb_x = 0;
s->mb_y++; s->mb_y++;
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1; ff_init_block_index(s);
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1); s->first_slice_line=0;
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1;
s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2);
s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1) + s->block_wrap[0]*(s->mb_height*2 + 2);
s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2);
} }
} }

View File

@ -61,6 +61,8 @@ void avcodec_get_context_defaults(AVCodecContext *s){
s->b_quant_offset=1.25; s->b_quant_offset=1.25;
s->i_quant_factor=-0.8; s->i_quant_factor=-0.8;
s->i_quant_offset=0.0; s->i_quant_offset=0.0;
s->error_concealment= 3;
s->workaround_bugs= FF_BUG_AUTODETECT;
} }
/** /**