diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-12-06 01:55:32 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-12-06 01:55:32 +0000 |
commit | 6109b56de74cfcda6321fcd5e37cac988734119c (patch) | |
tree | 29c91c901481a67a7a9e6d3c3b2f122fc919efa2 | |
parent | 4ae936639132b75872ee84444c59d1914cc2292d (diff) | |
download | xine-lib-6109b56de74cfcda6321fcd5e37cac988734119c.tar.gz xine-lib-6109b56de74cfcda6321fcd5e37cac988734119c.tar.bz2 |
- sync with ffmpeg (that must fix heiko stream, thanks Michael Niedermayer)
- improve ffmpeg support (passing extra data)
- aspect ratio still need to be updated to new syntax
- use our svq1 decoder since ffmpeg one is segfaulting
(buffer overrun - more investigation needed)
- img->copy no more
CVS patchset: 3437
CVS date: 2002/12/06 01:55:32
-rw-r--r-- | src/libffmpeg/libavcodec/avcodec.h | 314 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/dsputil.c | 34 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/dv.c | 73 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/error_resilience.c | 32 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/h263.c | 123 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/h263dec.c | 35 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/i386/motion_est_mmx.c | 3 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/mjpeg.c | 24 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/motion_est.c | 49 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/mpeg12.c | 63 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/mpegvideo.c | 764 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/mpegvideo.h | 72 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/msmpeg4.c | 4 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/ratecontrol.c | 40 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/rv10.c | 12 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/svq1.c | 25 | ||||
-rw-r--r-- | src/libffmpeg/libavcodec/utils.c | 177 | ||||
-rw-r--r-- | src/libffmpeg/xine_decoder.c | 97 |
18 files changed, 1087 insertions, 854 deletions
diff --git a/src/libffmpeg/libavcodec/avcodec.h b/src/libffmpeg/libavcodec/avcodec.h index 963e5f100..470fbc3d9 100644 --- a/src/libffmpeg/libavcodec/avcodec.h +++ b/src/libffmpeg/libavcodec/avcodec.h @@ -5,8 +5,8 @@ #define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION "0.4.6" -#define LIBAVCODEC_BUILD 4640 -#define LIBAVCODEC_BUILD_STR "4640" +#define LIBAVCODEC_BUILD 4643 +#define LIBAVCODEC_BUILD_STR "4643" enum CodecID { CODEC_ID_NONE, @@ -140,7 +140,7 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, #define CODEC_FLAG_EXTERN_HUFF 0x1000 /* use external huffman table (for mjpeg) */ #define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */ #define CODEC_FLAG_EMU_EDGE 0x4000/* dont draw edges */ -#define CODEC_FLAG_DR1 0x8000 /* direct renderig type 1 (store internal frames in external buffers) */ +#define CODEC_FLAG_PSNR 0x8000 /* error[?] variables will be set during encoding */ #define CODEC_FLAG_TRUNCATED 0x00010000 /* input bitstream might be truncated at a random location instead of only at frame boundaries */ #define CODEC_FLAG_NORMALIZE_AQP 0x00020000 /* normalize adaptive quantization */ @@ -159,6 +159,117 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, #define FRAME_RATE_BASE 10000 +#define FF_COMMON_PICTURE \ + uint8_t *data[4];\ + int linesize[4];\ + /**\ + * pointer to the first allocated byte of the picture. can be used in get_buffer/release_buffer + * this isnt used by lavc unless the default get/release_buffer() is used\ + * encoding: \ + * decoding: \ + */\ + uint8_t *base[4];\ + /**\ + * 1 -> keyframe, 0-> not\ + * encoding: set by lavc\ + * decoding: set by lavc\ + */\ + int key_frame;\ +\ + /**\ + * picture type of the frame, see ?_TYPE below\ + * encoding: set by lavc for coded_picture (and set by user for input)\ + * decoding: set by lavc\ + */\ + int pict_type;\ +\ + /**\ + * presentation timestamp in micro seconds (time when frame should be shown to user)\ + * if 0 then the frame_rate will be used as reference\ + * encoding: MUST be set by user\ + * decoding: set by lavc\ + */\ + long long int pts;\ +\ + /**\ + * picture number in bitstream order.\ + * encoding: set by\ + * decoding: set by lavc\ + */\ + int coded_picture_number;\ + /**\ + * encoding: set by\ + * decoding: set by lavc\ + * picture number in display order.\ + */\ + int display_picture_number;\ +\ + /**\ + * quality (between 1 (good) and 31 (bad)) \ + * encoding: set by lavc for coded_picture (and set by user for input)\ + * decoding: set by lavc\ + */\ + float quality; \ +\ + /**\ + * buffer age (1->was last buffer and dint change, 2->..., ...).\ + * set to something large if the buffer has not been used yet \ + * encoding: unused\ + * decoding: MUST be set by get_buffer()\ + */\ + int age;\ +\ + /**\ + * is this picture used as reference\ + * encoding: unused\ + * decoding: set by lavc (before get_buffer() call))\ + */\ + int reference;\ +\ + /**\ + * QP table\ + * encoding: unused\ + * decoding: set by lavc\ + */\ + int8_t *qscale_table;\ + /**\ + * QP store stride\ + * encoding: unused\ + * decoding: set by lavc\ + */\ + int qstride;\ +\ + /**\ + * mbskip_table[mb]>=1 if MB didnt change\ + * stride= mb_width = (width+15)>>4\ + * encoding: unused\ + * decoding: set by lavc\ + */\ + uint8_t *mbskip_table;\ +\ + /**\ + * for some private data of the user\ + * encoding: unused\ + * decoding: set by user\ + */\ + void *opaque;\ +\ + /**\ + * error\ + * encoding: set by lavc if flags&CODEC_FLAG_PSNR\ + * decoding: unused\ + */\ + uint64_t error[4];\ + +#define FF_I_TYPE 1 // Intra +#define FF_P_TYPE 2 // Predicted +#define FF_B_TYPE 3 // Bi-dir predicted +#define FF_S_TYPE 4 // S(GMC)-VOP MPEG4 + +typedef struct AVVideoFrame { + FF_COMMON_PICTURE +} AVVideoFrame; + typedef struct AVCodecContext { /** * the average bitrate @@ -191,7 +302,7 @@ typedef struct AVCodecContext { /** * motion estimation algorithm used for video coding - * encoding: set by user. + * encoding: MUST be set by user. * decoding: unused */ int me_method; @@ -212,21 +323,17 @@ typedef struct AVCodecContext { * frames per sec multiplied by FRAME_RATE_BASE * for variable fps this is the precission, so if the timestamps * can be specified in msec precssion then this is 1000*FRAME_RATE_BASE - * encoding: set by user + * encoding: MUST be set by user * decoding: set by lavc. 0 or the frame_rate if available */ int frame_rate; /** - * encoding: set by user. + * encoding: MUST be set by user. * decoding: set by user, some codecs might override / change it during playback */ int width, height; - /** - * Obsolete, will be removed - */ - int aspect_ratio_info; #define FF_ASPECT_SQUARE 1 #define FF_ASPECT_4_3_625 2 #define FF_ASPECT_4_3_525 3 @@ -274,52 +381,23 @@ typedef struct AVCodecContext { int frame_number; /* audio or video frame number */ int real_pict_num; /* returns the real picture number of previous encoded frame */ - + /** - * 1 -> keyframe, 0-> not + * 1 -> keyframe, 0-> not (this if for audio only, for video, AVVideoFrame.key_frame should be used) * encoding: set by lavc (for the outputed bitstream, not the input frame) * decoding: set by lavc (for the decoded bitstream, not the displayed frame) */ int key_frame; /** - * picture type of the previous en/decoded frame, see ?_TYPE below - * encoding: set by lavc (for the outputed bitstream, not the input frame) - * decoding: set by lavc (for the decoded bitstream, not the displayed frame) - */ - int pict_type; -/* FIXME: these should have FF_ */ -#define I_TYPE 1 // Intra -#define P_TYPE 2 // Predicted -#define B_TYPE 3 // Bi-dir predicted -#define S_TYPE 4 // S(GMC)-VOP MPEG4 - - /** * number of frames the decoded output will be delayed relative to * the encoded input * encoding: set by lavc. * decoding: unused */ int delay; - - /** - * mbskip_table[mb]=1 if MB didnt change, is only valid for I/P frames - * stride= mb_width = (width+15)>>4 (FIXME export stride?) - * encoding: unused - * decoding: set by lavc - */ - uint8_t *mbskip_table; /* encoding parameters */ - /** - * quality (between 1 (good) and 31 (bad)) - * encoding: set by user if CODEC_FLAG_QSCALE is set otherwise set by lavc - * decoding: set by lavc - */ - int quality; /* quality of the previous encoded frame - - this is allso used to set the quality in vbr mode - and the per frame quality in CODEC_FLAG_TYPE (second pass mode) */ float qcompress; /* amount of qscale change between easy & hard scenes (0.0-1.0)*/ float qblur; /* amount of qscale smoothing over time (0.0-1.0) */ @@ -393,17 +471,6 @@ typedef struct AVCodecContext { /* with a Start Code (it should) H.263 does */ void (*rtp_callback)(void *data, int size, int packet_number); - /** - * if you set get_psnr to 1 then after encoding you will have the - * PSNR on psnr_y/cb/cr - * encoding: set by user (1-> on, 0-> off) - * decoding: unused - */ - int get_psnr; - float psnr_y; - float psnr_cb; - float psnr_cr; - /* statistics, used for 2-pass encoding */ int mv_bits; int header_bits; @@ -477,54 +544,33 @@ typedef struct AVCodecContext { float b_quant_offset; /** - * error resilience {-1,0,1} higher values will detect more errors but may missdetect + * error resilience higher values will detect more errors but may missdetect * some more or less valid parts as errors * encoding: unused * decoding: set by user */ int error_resilience; +#define FF_ER_CAREFULL 1 +#define FF_ER_COMPLIANT 2 +#define FF_ER_AGGRESSIVE 3 +#define FF_ER_VERY_AGGRESSIVE 4 /** - * obsolete, just here to keep ABI compatible (should be removed perhaps, dunno) - */ - int *quant_store; - - /** - * QP store stride + * called at the beginning of each frame to get a buffer for it. + * if pic.reference is set then the frame will be read later by lavc * encoding: unused - * decoding: set by lavc + * decoding: set by lavc, user can override */ - int qstride; + int (*get_buffer)(struct AVCodecContext *c, AVVideoFrame *pic); /** - * buffer, where the next picture should be decoded into + * called to release buffers which where allocated with get_buffer. + * a released buffer can be reused in get_buffer() + * pic.data[*] must be set to NULL * encoding: unused - * decoding: set by user in get_buffer_callback to a buffer into which the next part - * of the bitstream will be decoded, and set by lavc at end of frame to the - * next frame which needs to be displayed - */ - uint8_t *dr_buffer[3]; - - /** - * stride of the luminance part of the dr buffer - * encoding: unused - * decoding: set by user + * decoding: set by lavc, user can override */ - int dr_stride; - - /** - * same behavior as dr_buffer, just for some private data of the user - * encoding: unused - * decoding: set by user in get_buffer_callback, and set by lavc at end of frame - */ - void *dr_opaque_frame; - - /** - * called at the beginning of each frame to get a buffer for it - * encoding: unused - * decoding: set by user - */ - int (*get_buffer_callback)(struct AVCodecContext *c, int width, int height, int pict_type); + void (*release_buffer)(struct AVCodecContext *c, AVVideoFrame *pic); /** * is 1 if the decoded stream contains b frames, 0 otherwise @@ -532,20 +578,6 @@ typedef struct AVCodecContext { * decoding: set by lavc */ int has_b_frames; - - /** - * stride of the chrominance part of the dr buffer - * encoding: unused - * decoding: set by user - */ - int dr_uvstride; - - /** - * number of dr buffers - * encoding: unused - * decoding: set by user - */ - int dr_ip_buffer_count; int block_align; /* used by some WAV based audio codecs */ @@ -647,12 +679,6 @@ typedef struct AVCodecContext { float rc_initial_cplx; /** - * Obsolete, will be removed - */ - int aspected_width; - int aspected_height; - - /** * dct algorithm, see FF_DCT_* below * encoding: set by user * decoding: unused @@ -664,14 +690,6 @@ typedef struct AVCodecContext { #define FF_DCT_MMX 3 #define FF_DCT_MLIB 4 #define FF_DCT_ALTIVEC 5 - - /** - * presentation timestamp in micro seconds (time when frame should be shown to user) - * if 0 then the frame_rate will be used as reference - * encoding: set by user - * decoding; set by lavc - */ - long long int pts; /** * luminance masking (0-> disabled) @@ -755,24 +773,6 @@ typedef struct AVCodecContext { #define FF_EC_DEBLOCK 2 /** - * QP table of the currently decoded frame - * encoding; unused - * decoding: set by lavc - */ - int8_t *current_qscale_table; - /** - * QP table of the currently displayed frame - * encoding; unused - * decoding: set by lavc - */ - int8_t *display_qscale_table; - /** - * force specific pict_type. - * encoding; set by user (I/P/B_TYPE) - * decoding: unused - */ - int force_type; - /** * dsp_mask could be used to disable unwanted * CPU features (i.e. MMX, SSE. ...) */ @@ -780,14 +780,14 @@ typedef struct AVCodecContext { /** * bits per sample/pixel from the demuxer (needed for huffyuv) - * encoding; set by lavc + * encoding: set by lavc * decoding: set by user */ int bits_per_sample; /** * prediction method (needed for huffyuv) - * encoding; set by user + * encoding: set by user * decoding: unused */ int prediction_method; @@ -801,6 +801,34 @@ typedef struct AVCodecContext { * decoding: set by lavc. */ float aspect_ratio; + + /** + * the picture in the bitstream + * encoding: set by lavc + * decoding: set by lavc + */ + AVVideoFrame *coded_picture; + + /** + * debug + * encoding: set by user. + * decoding: set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_MV 32 +#define FF_DEBUG_VIS_MV 64 + + /** + * error + * encoding: set by lavc if flags&CODEC_FLAG_PSNR + * decoding: unused + */ + uint64_t error[4]; } AVCodecContext; typedef struct AVCodec { @@ -928,6 +956,7 @@ void img_resample_close(ImgReSampleContext *s); void avpicture_fill(AVPicture *picture, UINT8 *ptr, int pix_fmt, int width, int height); int avpicture_get_size(int pix_fmt, int width, int height); +void avcodec_get_chroma_sub_sample(int fmt, int *h_shift, int *v_shift); /* convert among pixel formats */ int img_convert(AVPicture *dst, int dst_pix_fmt, @@ -957,12 +986,18 @@ AVCodec *avcodec_find_decoder(enum CodecID id); AVCodec *avcodec_find_decoder_by_name(const char *name); void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); +void avcodec_get_context_defaults(AVCodecContext *s); AVCodecContext *avcodec_alloc_context(void); +AVVideoFrame *avcodec_alloc_picture(void); + +int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic); +void avcodec_default_release_buffer(AVCodecContext *s, AVVideoFrame *pic); + int avcodec_open(AVCodecContext *avctx, AVCodec *codec); int avcodec_decode_audio(AVCodecContext *avctx, INT16 *samples, int *frame_size_ptr, UINT8 *buf, int buf_size); -int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture, +int avcodec_decode_video(AVCodecContext *avctx, AVVideoFrame *picture, int *got_picture_ptr, UINT8 *buf, int buf_size); int avcodec_parse_frame(AVCodecContext *avctx, UINT8 **pdata, @@ -971,7 +1006,7 @@ int avcodec_parse_frame(AVCodecContext *avctx, UINT8 **pdata, int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size, const short *samples); int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, - const AVPicture *pict); + const AVVideoFrame *pict); int avcodec_close(AVCodecContext *avctx); @@ -1061,5 +1096,10 @@ void *av_mallocz(unsigned int size); void av_free(void *ptr); void __av_freep(void **ptr); #define av_freep(p) __av_freep((void **)(p)) +/* for static data only */ +/* call av_free_static to release all staticaly allocated tables */ +void av_free_static(); +void *__av_mallocz_static(void** location, unsigned int size); +#define av_mallocz_static(p, s) __av_mallocz_static((void **)(p), s) #endif /* AVCODEC_H */ diff --git a/src/libffmpeg/libavcodec/dsputil.c b/src/libffmpeg/libavcodec/dsputil.c index 9039d2625..1e177116a 100644 --- a/src/libffmpeg/libavcodec/dsputil.c +++ b/src/libffmpeg/libavcodec/dsputil.c @@ -1528,37 +1528,3 @@ void avcodec_set_bit_exact(void) // dsputil_set_bit_exact_mmx(); #endif } - -void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3], - int orig_linesize[3], int coded_linesize, - AVCodecContext *avctx) -{ - int quad, diff, x, y; - UINT8 *orig, *coded; - UINT32 *sq = squareTbl + 256; - - quad = 0; - diff = 0; - - /* Luminance */ - orig = orig_image[0]; - coded = coded_image[0]; - - for (y=0;y<avctx->height;y++) { - for (x=0;x<avctx->width;x++) { - diff = *(orig + x) - *(coded + x); - quad += sq[diff]; - } - orig += orig_linesize[0]; - coded += coded_linesize; - } - - avctx->psnr_y = (float) quad / (float) (avctx->width * avctx->height); - - if (avctx->psnr_y) { - avctx->psnr_y = (float) (255 * 255) / avctx->psnr_y; - avctx->psnr_y = 10 * (float) log10 (avctx->psnr_y); - } else - avctx->psnr_y = 99.99; -} - diff --git a/src/libffmpeg/libavcodec/dv.c b/src/libffmpeg/libavcodec/dv.c index 1492d6854..05128aee4 100644 --- a/src/libffmpeg/libavcodec/dv.c +++ b/src/libffmpeg/libavcodec/dv.c @@ -33,6 +33,7 @@ typedef struct DVVideoDecodeContext { int sampling_411; /* 0 = 420, 1 = 411 */ int width, height; UINT8 *current_picture[3]; /* picture structure */ + AVVideoFrame picture; int linesize[3]; DCTELEM block[5*6][64] __align8; UINT8 dv_zigzag[2][64]; @@ -128,7 +129,7 @@ static int dvvideo_decode_init(AVCodecContext *avctx) /* XXX: do it only for constant case */ dv_build_unquantize_tables(s); - + return 0; } @@ -499,7 +500,6 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, unsigned size; UINT8 *buf_ptr; const UINT16 *mb_pos_ptr; - AVPicture *picture; /* parse id */ init_get_bits(&s->gb, buf, buf_size); @@ -561,45 +561,20 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, avctx->width = width; avctx->height = height; - if (avctx->flags & CODEC_FLAG_DR1) - { - s->width = -1; - avctx->dr_buffer[0] = avctx->dr_buffer[1] = avctx->dr_buffer[2] = 0; - if(avctx->get_buffer_callback(avctx, width, height, I_TYPE) < 0 - && avctx->flags & CODEC_FLAG_DR1) { - fprintf(stderr, "get_buffer() failed\n"); - return -1; - } + s->picture.reference= 0; + if(avctx->get_buffer(avctx, &s->picture) < 0) { + fprintf(stderr, "get_buffer() failed\n"); + return -1; } - /* (re)alloc picture if needed */ - if (s->width != width || s->height != height) { - if (!(avctx->flags & CODEC_FLAG_DR1)) - for(i=0;i<3;i++) { - if (avctx->dr_buffer[i] != s->current_picture[i]) - av_freep(&s->current_picture[i]); - avctx->dr_buffer[i] = 0; - } - - for(i=0;i<3;i++) { - if (avctx->dr_buffer[i]) { - s->current_picture[i] = avctx->dr_buffer[i]; - s->linesize[i] = (i == 0) ? avctx->dr_stride : avctx->dr_uvstride; - } else { - size = width * height; - s->linesize[i] = width; - if (i >= 1) { - size >>= 2; - s->linesize[i] >>= s->sampling_411 ? 2 : 1; - } - s->current_picture[i] = av_malloc(size); - } - if (!s->current_picture[i]) - return -1; - } - s->width = width; - s->height = height; + for(i=0;i<3;i++) { + s->current_picture[i] = s->picture.data[i]; + s->linesize[i] = s->picture.linesize[i]; + if (!s->current_picture[i]) + return -1; } + s->width = width; + s->height = height; /* for each DIF segment */ buf_ptr = buf; @@ -620,12 +595,11 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, emms_c(); /* return image */ - *data_size = sizeof(AVPicture); - picture = data; - for(i=0;i<3;i++) { - picture->data[i] = s->current_picture[i]; - picture->linesize[i] = s->linesize[i]; - } + *data_size = sizeof(AVVideoFrame); + *(AVVideoFrame*)data= s->picture; + + avctx->release_buffer(avctx, &s->picture); + return packet_size; } @@ -633,10 +607,15 @@ static int dvvideo_decode_end(AVCodecContext *avctx) { DVVideoDecodeContext *s = avctx->priv_data; int i; + + if(avctx->get_buffer == avcodec_default_get_buffer){ + for(i=0; i<4; i++){ + av_freep(&s->picture.base[i]); + s->picture.data[i]= NULL; + } + av_freep(&s->picture.opaque); + } - for(i=0;i<3;i++) - if (avctx->dr_buffer[i] != s->current_picture[i]) - av_freep(&s->current_picture[i]); return 0; } diff --git a/src/libffmpeg/libavcodec/error_resilience.c b/src/libffmpeg/libavcodec/error_resilience.c index 519674496..3cb8d40bc 100644 --- a/src/libffmpeg/libavcodec/error_resilience.c +++ b/src/libffmpeg/libavcodec/error_resilience.c @@ -464,7 +464,7 @@ int score_sum=0; 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; + UINT8 *src= s->current_picture.data[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]; @@ -528,6 +528,8 @@ score_sum+= best_score; static int is_intra_more_likely(MpegEncContext *s){ int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; + + if(s->last_picture.data[0]==NULL) return 1; //no previous frame available -> use spatial prediction undamaged_count=0; for(i=0; i<s->mb_num; i++){ @@ -556,8 +558,8 @@ static int is_intra_more_likely(MpegEncContext *s){ 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; + UINT8 *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; + UINT8 *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize; is_intra_likely += s->dsp.pix_abs16x16(last_mb_ptr, mb_ptr , s->linesize); is_intra_likely -= s->dsp.pix_abs16x16(last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize); @@ -802,9 +804,9 @@ void ff_error_resilience(MpegEncContext *s){ 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; + dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; + dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize; + dest_cr= s->current_picture.data[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++){ @@ -852,9 +854,9 @@ void ff_error_resilience(MpegEncContext *s){ 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; + dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; + dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize; + dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize; put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); } @@ -863,14 +865,14 @@ void ff_error_resilience(MpegEncContext *s){ 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); + h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); + h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); + h_block_filter(s, s->current_picture.data[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); + v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); + v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); + v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); } /* clean a few tables */ diff --git a/src/libffmpeg/libavcodec/h263.c b/src/libffmpeg/libavcodec/h263.c index 0083ca280..98b29ad0b 100644 --- a/src/libffmpeg/libavcodec/h263.c +++ b/src/libffmpeg/libavcodec/h263.c @@ -272,6 +272,7 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d { int score0=0, score1=0; int i, n; + int8_t * const qscale_table= s->current_picture.qscale_table; for(n=0; n<6; n++){ INT16 *ac_val, *ac_val1; @@ -282,7 +283,7 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d const int xy= s->mb_x + s->mb_y*s->mb_width - s->mb_width; /* top prediction */ ac_val-= s->block_wrap[n]*16; - if(s->mb_y==0 || s->qscale == s->qscale_table[xy] || n==2 || n==3){ + if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ /* same qscale */ for(i=1; i<8; i++){ const int level= block[n][s->idct_permutation[i ]]; @@ -296,7 +297,7 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d for(i=1; i<8; i++){ const int level= block[n][s->idct_permutation[i ]]; score0+= ABS(level); - score1+= ABS(level - ROUNDED_DIV(ac_val[i + 8]*s->qscale_table[xy], s->qscale)); + score1+= ABS(level - ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale)); ac_val1[i ]= block[n][s->idct_permutation[i<<3]]; ac_val1[i+8]= level; } @@ -305,7 +306,7 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d const int xy= s->mb_x-1 + s->mb_y*s->mb_width; /* left prediction */ ac_val-= 16; - if(s->mb_x==0 || s->qscale == s->qscale_table[xy] || n==1 || n==3){ + if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ /* same qscale */ for(i=1; i<8; i++){ const int level= block[n][s->idct_permutation[i<<3]]; @@ -319,7 +320,7 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d for(i=1; i<8; i++){ const int level= block[n][s->idct_permutation[i<<3]]; score0+= ABS(level); - score1+= ABS(level - ROUNDED_DIV(ac_val[i]*s->qscale_table[xy], s->qscale)); + score1+= ABS(level - ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale)); ac_val1[i ]= level; ac_val1[i+8]= block[n][s->idct_permutation[i ]]; } @@ -335,14 +336,15 @@ static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], int d */ void ff_clean_h263_qscales(MpegEncContext *s){ int i; + int8_t * const qscale_table= s->current_picture.qscale_table; for(i=1; i<s->mb_num; i++){ - if(s->qscale_table[i] - s->qscale_table[i-1] >2) - s->qscale_table[i]= s->qscale_table[i-1]+2; + if(qscale_table[i] - qscale_table[i-1] >2) + qscale_table[i]= qscale_table[i-1]+2; } for(i=s->mb_num-2; i>=0; i--){ - if(s->qscale_table[i] - s->qscale_table[i+1] >2) - s->qscale_table[i]= s->qscale_table[i+1]+2; + if(qscale_table[i] - qscale_table[i+1] >2) + qscale_table[i]= qscale_table[i+1]+2; } } @@ -351,11 +353,12 @@ void ff_clean_h263_qscales(MpegEncContext *s){ */ void ff_clean_mpeg4_qscales(MpegEncContext *s){ int i; - + int8_t * const qscale_table= s->current_picture.qscale_table; + ff_clean_h263_qscales(s); for(i=1; i<s->mb_num; i++){ - if(s->qscale_table[i] != s->qscale_table[i-1] && (s->mb_type[i]&MB_TYPE_INTER4V)){ + if(qscale_table[i] != qscale_table[i-1] && (s->mb_type[i]&MB_TYPE_INTER4V)){ s->mb_type[i]&= ~MB_TYPE_INTER4V; s->mb_type[i]|= MB_TYPE_INTER; } @@ -367,21 +370,21 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s){ for the actual adaptive quantization */ for(i=0; i<s->mb_num; i++){ - odd += s->qscale_table[i]&1; + odd += qscale_table[i]&1; } if(2*odd > s->mb_num) odd=1; else odd=0; for(i=0; i<s->mb_num; i++){ - if((s->qscale_table[i]&1) != odd) - s->qscale_table[i]++; - if(s->qscale_table[i] > 31) - s->qscale_table[i]= 31; + if((qscale_table[i]&1) != odd) + qscale_table[i]++; + if(qscale_table[i] > 31) + qscale_table[i]= 31; } for(i=1; i<s->mb_num; i++){ - if(s->qscale_table[i] != s->qscale_table[i-1] && (s->mb_type[i]&MB_TYPE_DIRECT)){ + if(qscale_table[i] != qscale_table[i-1] && (s->mb_type[i]&MB_TYPE_DIRECT)){ s->mb_type[i]&= ~MB_TYPE_DIRECT; s->mb_type[i]|= MB_TYPE_BIDIR; } @@ -427,7 +430,7 @@ void mpeg4_encode_mb(MpegEncContext * s, assert(mb_type>=0); /* nothing to do if this MB was skiped in the next P Frame */ - if(s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]){ //FIXME avoid DCT & ... + if(s->next_picture.mbskip_table[s->mb_y * s->mb_width + s->mb_x]){ //FIXME avoid DCT & ... s->skip_count++; s->mv[0][0][0]= s->mv[0][0][1]= @@ -435,6 +438,8 @@ void mpeg4_encode_mb(MpegEncContext * s, s->mv[1][0][1]= 0; s->mv_dir= MV_DIR_FORWARD; //doesnt matter s->qscale -= s->dquant; +// s->mb_skiped=1; + return; } @@ -451,6 +456,7 @@ void mpeg4_encode_mb(MpegEncContext * s, s->skip_count++; return; } + put_bits(&s->pb, 1, 0); /* mb coded modb1=0 */ put_bits(&s->pb, 1, cbp ? 0 : 1); /* modb2 */ //FIXME merge put_bits(&s->pb, mb_type+1, 1); // this table is so simple that we dont need it :) @@ -547,16 +553,17 @@ void mpeg4_encode_mb(MpegEncContext * s, if(y+16 > s->height) y= s->height-16; offset= x + y*s->linesize; - p_pic= s->new_picture[0] + offset; + p_pic= s->new_picture.data[0] + offset; s->mb_skiped=1; for(i=0; i<s->max_b_frames; i++){ uint8_t *b_pic; int diff; + Picture *pic= s->reordered_input_picture[i+1]; - if(s->coded_order[i+1].pict_type!=B_TYPE) break; + if(pic==NULL || pic->pict_type!=B_TYPE) break; - b_pic= s->coded_order[i+1].picture[0] + offset; + b_pic= pic->data[0] + offset + 16; //FIXME +16 diff= s->dsp.pix_abs16x16(p_pic, b_pic, s->linesize); if(diff>s->qscale*70){ //FIXME check that 70 is optimal s->mb_skiped=0; @@ -1493,8 +1500,8 @@ void ff_set_mpeg4_time(MpegEncContext * s, int picture_number){ s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1; } - if(s->avctx->pts) - s->time= (s->avctx->pts*s->time_increment_resolution + 500*1000)/(1000*1000); + if(s->current_picture.pts) + s->time= (s->current_picture.pts*s->time_increment_resolution + 500*1000)/(1000*1000); else s->time= picture_number*(INT64)FRAME_RATE_BASE*s->time_increment_resolution/s->frame_rate; time_div= s->time/s->time_increment_resolution; @@ -1736,6 +1743,7 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, { int i; INT16 *ac_val, *ac_val1; + int8_t * const qscale_table= s->current_picture.qscale_table; /* find prediction */ ac_val = s->ac_val[0][0] + s->block_index[n] * 16; @@ -1746,7 +1754,7 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, /* left prediction */ ac_val -= 16; - if(s->mb_x==0 || s->qscale == s->qscale_table[xy] || n==1 || n==3){ + if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ /* same qscale */ for(i=1;i<8;i++) { block[s->idct_permutation[i<<3]] += ac_val[i]; @@ -1754,7 +1762,7 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, }else{ /* different qscale, we must rescale */ for(i=1;i<8;i++) { - block[s->idct_permutation[i<<3]] += ROUNDED_DIV(ac_val[i]*s->qscale_table[xy], s->qscale); + block[s->idct_permutation[i<<3]] += ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); } } } else { @@ -1762,7 +1770,7 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, /* top prediction */ ac_val -= 16 * s->block_wrap[n]; - if(s->mb_y==0 || s->qscale == s->qscale_table[xy] || n==2 || n==3){ + if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ /* same qscale */ for(i=1;i<8;i++) { block[s->idct_permutation[i]] += ac_val[i + 8]; @@ -1770,7 +1778,7 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, }else{ /* different qscale, we must rescale */ for(i=1;i<8;i++) { - block[s->idct_permutation[i]] += ROUNDED_DIV(ac_val[i + 8]*s->qscale_table[xy], s->qscale); + block[s->idct_permutation[i]] += ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); } } } @@ -1790,6 +1798,7 @@ static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, { int i; INT16 *ac_val; + int8_t * const qscale_table= s->current_picture.qscale_table; /* find prediction */ ac_val = s->ac_val[0][0] + s->block_index[n] * 16; @@ -1798,7 +1807,7 @@ static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, const int xy= s->mb_x-1 + s->mb_y*s->mb_width; /* left prediction */ ac_val -= 16; - if(s->mb_x==0 || s->qscale == s->qscale_table[xy] || n==1 || n==3){ + if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ /* same qscale */ for(i=1;i<8;i++) { block[s->idct_permutation[i<<3]] -= ac_val[i]; @@ -1806,14 +1815,14 @@ static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, }else{ /* different qscale, we must rescale */ for(i=1;i<8;i++) { - block[s->idct_permutation[i<<3]] -= ROUNDED_DIV(ac_val[i]*s->qscale_table[xy], s->qscale); + block[s->idct_permutation[i<<3]] -= ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); } } } else { const int xy= s->mb_x + s->mb_y*s->mb_width - s->mb_width; /* top prediction */ ac_val -= 16 * s->block_wrap[n]; - if(s->mb_y==0 || s->qscale == s->qscale_table[xy] || n==2 || n==3){ + if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ /* same qscale */ for(i=1;i<8;i++) { block[s->idct_permutation[i]] -= ac_val[i + 8]; @@ -1821,7 +1830,7 @@ static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, }else{ /* different qscale, we must rescale */ for(i=1;i<8;i++) { - block[s->idct_permutation[i]] -= ROUNDED_DIV(ac_val[i + 8]*s->qscale_table[xy], s->qscale); + block[s->idct_permutation[i]] -= ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); } } } @@ -2532,7 +2541,7 @@ static int mpeg4_decode_partition_a(MpegEncContext *s){ if(cbpc & 4) { change_qscale(s, quant_tab[get_bits(&s->gb, 2)]); } - s->qscale_table[xy]= s->qscale; + s->current_picture.qscale_table[xy]= s->qscale; s->mbintra_table[xy]= 1; for(i=0; i<6; i++){ @@ -2704,7 +2713,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ if(s->cbp_table[xy] & 8) { change_qscale(s, quant_tab[get_bits(&s->gb, 2)]); } - s->qscale_table[xy]= s->qscale; + s->current_picture.qscale_table[xy]= s->qscale; for(i=0; i<6; i++){ int dc_pred_dir; @@ -2721,7 +2730,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ s->pred_dir_table[xy]= dir | (ac_pred<<7); s->error_status_table[xy]&= ~DC_ERROR; }else if(s->mb_type[xy]&MB_TYPE_SKIPED){ - s->qscale_table[xy]= s->qscale; + s->current_picture.qscale_table[xy]= s->qscale; s->cbp_table[xy]= 0; }else{ int cbpy = get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1); @@ -2734,7 +2743,7 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ if(s->cbp_table[xy] & 8) { change_qscale(s, quant_tab[get_bits(&s->gb, 2)]); } - s->qscale_table[xy]= s->qscale; + s->current_picture.qscale_table[xy]= s->qscale; s->cbp_table[xy]&= 3; //remove dquant s->cbp_table[xy]|= (cbpy^0xf)<<2; @@ -2801,8 +2810,8 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, DCTELEM block[6][64]) mb_type= s->mb_type[xy]; cbp = s->cbp_table[xy]; - if(s->qscale_table[xy] != s->qscale){ - s->qscale= s->qscale_table[xy]; + if(s->current_picture.qscale_table[xy] != s->qscale){ + s->qscale= s->current_picture.qscale_table[xy]; s->y_dc_scale= s->y_dc_scale_table[ s->qscale ]; s->c_dc_scale= s->c_dc_scale_table[ s->qscale ]; } @@ -3054,7 +3063,7 @@ int ff_h263_decode_mb(MpegEncContext *s, } /* if we skipped it in the future P Frame than skip it now too */ - s->mb_skiped= s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]; // Note, skiptab=0 if last was GMC + s->mb_skiped= s->next_picture.mbskip_table[s->mb_y * s->mb_width + s->mb_x]; // Note, skiptab=0 if last was GMC if(s->mb_skiped){ /* skip mb */ @@ -3287,7 +3296,7 @@ end: /* per-MB end of slice check */ if(s->codec_id==CODEC_ID_MPEG4){ if(mpeg4_is_resync(s)){ - if(s->pict_type==B_TYPE && s->mbskip_table[s->mb_y * s->mb_width + s->mb_x+1]) + if(s->pict_type==B_TYPE && s->next_picture.mbskip_table[s->mb_y * s->mb_width + s->mb_x+1]) return SLICE_OK; return SLICE_END; } @@ -3615,19 +3624,21 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, #if 1 { const int abs_level= ABS(level); - if(abs_level<=MAX_LEVEL && run<=MAX_RUN && ((s->workaround_bugs&FF_BUG_AC_VLC)==0)){ + if(abs_level<=MAX_LEVEL && run<=MAX_RUN){ const int run1= run - rl->max_run[last][abs_level] - 1; if(abs_level <= rl->max_level[last][run]){ fprintf(stderr, "illegal 3. esc, vlc encoding possible\n"); return -1; } - if(abs_level <= rl->max_level[last][run]*2){ - fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n"); - return -1; - } - if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){ - fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n"); - return -1; + if(s->error_resilience > FF_ER_COMPLIANT){ + if(abs_level <= rl->max_level[last][run]*2){ + fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n"); + return -1; + } + if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){ + fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n"); + return -1; + } } } } @@ -4441,7 +4452,7 @@ static int decode_vop_header(MpegEncContext *s, GetBitContext *gb){ - ROUNDED_DIV(s->last_non_b_time - s->pp_time, s->t_frame))*2; } - s->avctx->pts= s->time*1000LL*1000LL / s->time_increment_resolution; + s->current_picture.pts= s->time*1000LL*1000LL / s->time_increment_resolution; if(check_marker(gb, "before vop_coded")==0 && s->picture_number==0){ printf("hmm, seems the headers arnt complete, trying to guess time_increment_bits\n"); @@ -4535,14 +4546,16 @@ static int decode_vop_header(MpegEncContext *s, GetBitContext *gb){ s->b_code = get_bits(gb, 3); }else s->b_code=1; -#if 0 -printf("qp:%d fc:%d bc:%d type:%s size:%d pro:%d alt:%d top:%d qpel:%d part:%d resync:%d w:%d a:%d\n", - s->qscale, s->f_code, s->b_code, - s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")), - gb->size,s->progressive_sequence, s->alternate_scan, s->top_field_first, - s->quarter_sample, s->data_partitioning, s->resync_marker, s->num_sprite_warping_points, - s->sprite_warping_accuracy); -#endif + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + printf("qp:%d fc:%d bc:%d type:%s size:%d pro:%d alt:%d top:%d qpel:%d part:%d resync:%d w:%d a:%d\n", + s->qscale, s->f_code, s->b_code, + s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")), + gb->size,s->progressive_sequence, s->alternate_scan, s->top_field_first, + s->quarter_sample, s->data_partitioning, s->resync_marker, s->num_sprite_warping_points, + s->sprite_warping_accuracy); + } + if(!s->scalability){ if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) { skip_bits1(gb); // vop shape coding type diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c index 0c88cd758..1f8fb44a8 100644 --- a/src/libffmpeg/libavcodec/h263dec.c +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -199,6 +199,7 @@ static int decode_slice(MpegEncContext *s){ s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; +// s->mb_skiped = 0; //printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24)); ret= s->decode_mb(s, s->block); @@ -347,7 +348,7 @@ static int h263_decode_frame(AVCodecContext *avctx, { MpegEncContext *s = avctx->priv_data; int ret,i; - AVPicture *pict = data; + AVVideoFrame *pict = data; float new_aspect; #ifdef PRINT_FRAME_TIME @@ -357,7 +358,6 @@ uint64_t time= rdtsc(); printf("*****frame %d size=%d\n", avctx->frame_number, buf_size); printf("bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); #endif - s->flags= avctx->flags; *data_size = 0; @@ -461,6 +461,9 @@ retry: if(s->avctx->fourcc == ff_get_fourcc("XVID") && s->xvid_build==0) s->workaround_bugs|= FF_BUG_QPEL_CHROMA; + if(s->avctx->fourcc == ff_get_fourcc("XVID") && s->xvid_build==0) + s->padding_bug_score= 256*256*256*64; + if(s->xvid_build && s->xvid_build<=1) s->workaround_bugs|= FF_BUG_QPEL_CHROMA; @@ -523,8 +526,9 @@ retry: return -1; } - s->avctx->key_frame = (s->pict_type == I_TYPE); - s->avctx->pict_type = s->pict_type; + // 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 dont have reference frames */ if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size); @@ -580,7 +584,9 @@ retry: } if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE) - if(msmpeg4_decode_ext_header(s, buf_size) < 0) return -1; + if(msmpeg4_decode_ext_header(s, buf_size) < 0){ + s->error_status_table[s->mb_num-1]= AC_ERROR|DC_ERROR|MV_ERROR; + } /* divx 5.01+ bistream reorder stuff */ if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0 && s->divx_version>=500){ @@ -644,7 +650,7 @@ retry: int y= mb_y*16 + 8; for(mb_x=0; mb_x<s->mb_width; mb_x++){ int x= mb_x*16 + 8; - uint8_t *ptr= s->last_picture[0]; + uint8_t *ptr= s->last_picture.data[0]; int xy= 1 + mb_x*2 + (mb_y*2 + 1)*(s->mb_width*2 + 2); int mx= (s->motion_val[xy][0]>>1) + x; int my= (s->motion_val[xy][1]>>1) + y; @@ -669,21 +675,12 @@ retry: } } -#endif +#endif if(s->pict_type==B_TYPE || (!s->has_b_frames)){ - pict->data[0] = s->current_picture[0]; - pict->data[1] = s->current_picture[1]; - pict->data[2] = s->current_picture[2]; + *pict= *(AVVideoFrame*)&s->current_picture; } else { - pict->data[0] = s->last_picture[0]; - pict->data[1] = s->last_picture[1]; - pict->data[2] = s->last_picture[2]; + *pict= *(AVVideoFrame*)&s->last_picture; } - pict->linesize[0] = s->linesize; - pict->linesize[1] = s->uvlinesize; - pict->linesize[2] = s->uvlinesize; - - avctx->quality = s->qscale; /* Return the Picture timestamp as the frame number */ /* we substract 1 because it is added on utils.c */ @@ -692,7 +689,7 @@ retry: /* dont output the last pic after seeking note we allready added +1 for the current pix in MPV_frame_end(s) */ if(s->num_available_buffers>=2 || (!s->has_b_frames)) - *data_size = sizeof(AVPicture); + *data_size = sizeof(AVVideoFrame); #ifdef PRINT_FRAME_TIME printf("%Ld\n", rdtsc()-time); #endif diff --git a/src/libffmpeg/libavcodec/i386/motion_est_mmx.c b/src/libffmpeg/libavcodec/i386/motion_est_mmx.c index 9b76cdb07..3368e7333 100644 --- a/src/libffmpeg/libavcodec/i386/motion_est_mmx.c +++ b/src/libffmpeg/libavcodec/i386/motion_est_mmx.c @@ -263,6 +263,7 @@ static inline int sum_mmx2() return ret; } + #define PIX_SAD(suf)\ int pix_abs8x8_ ## suf(UINT8 *blk2, UINT8 *blk1, int stride)\ {\ @@ -282,7 +283,7 @@ int pix_abs8x8_x2_ ## suf(UINT8 *blk2, UINT8 *blk1, int stride)\ :: "m"(round_tab[1]) \ );\ \ - sad8_2_ ## suf(blk1, blk2+1, blk2, stride, 3);\ + sad8_2_ ## suf(blk1, blk1+1, blk2, stride, 3);\ \ return sum_ ## suf();\ }\ diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c index 899aa06e5..eed155c19 100644 --- a/src/libffmpeg/libavcodec/mjpeg.c +++ b/src/libffmpeg/libavcodec/mjpeg.c @@ -877,8 +877,12 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s) if (s->interlaced) w *= 2; s->linesize[i] = w; - /* memory test is done in mjpeg_decode_sos() */ s->current_picture[i] = av_mallocz(w * h); + if (!s->current_picture[i]) + { + dprintf("error: no picture buffers allocated\n"); + return -1; + } } s->first_picture = 0; } @@ -1176,9 +1180,11 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) get_bits(&s->gb, 8), get_bits(&s->gb, 8)); if (get_bits(&s->gb, 8) == 0) { - s->avctx->aspect_ratio_info = FF_ASPECT_EXTENDED; - s->avctx->aspected_width = get_bits(&s->gb, 16); - s->avctx->aspected_height = get_bits(&s->gb, 16); + int x_density = get_bits(&s->gb, 16); + int y_density = get_bits(&s->gb, 16); + + //MN: needs to be checked + s->avctx->aspect_ratio= s->width*y_density/((float)s->height*x_density); } else { @@ -1419,7 +1425,8 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, mjpeg_decode_dht(s); break; case SOF0: - mjpeg_decode_sof0(s); + if (mjpeg_decode_sof0(s) < 0) + return -1; break; case EOI: eoi_parser: @@ -1463,7 +1470,7 @@ eoi_parser: } /* dummy quality */ /* XXX: infer it with matrix */ - avctx->quality = 3; +// avctx->quality = 3; goto the_end; } break; @@ -1578,7 +1585,8 @@ read_header: { init_get_bits(&s->gb, buf+sof_offs, buf_end - (buf+sof_offs)); s->start_code = SOF0; - mjpeg_decode_sof0(s); + if (mjpeg_decode_sof0(s) < 0) + return -1; } sos_offs = get_bits(&hgb, 32); @@ -1629,7 +1637,7 @@ read_header: } /* dummy quality */ /* XXX: infer it with matrix */ - avctx->quality = 3; +// avctx->quality = 3; return buf_ptr - buf; } diff --git a/src/libffmpeg/libavcodec/motion_est.c b/src/libffmpeg/libavcodec/motion_est.c index b1a3c61f7..fa6c3ee6b 100644 --- a/src/libffmpeg/libavcodec/motion_est.c +++ b/src/libffmpeg/libavcodec/motion_est.c @@ -92,7 +92,7 @@ static int full_motion_search(MpegEncContext * s, y2 = yy + range - 1; if (y2 > ymax) y2 = ymax; - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; dmin = 0x7fffffff; mx = 0; my = 0; @@ -155,7 +155,7 @@ static int log_motion_search(MpegEncContext * s, if (y2 > ymax) y2 = ymax; - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; dmin = 0x7fffffff; mx = 0; my = 0; @@ -231,7 +231,7 @@ static int phods_motion_search(MpegEncContext * s, if (y2 > ymax) y2 = ymax; - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; mx = 0; my = 0; @@ -560,7 +560,7 @@ static int epzs_motion_search(MpegEncContext * s, uint16_t *score_map= s->me_score_map; int map_generation; - new_pic = s->new_picture[0] + pic_xy; + new_pic = s->new_picture.data[0] + pic_xy; old_pic = ref_picture + pic_xy; map_generation= update_map_generation(s); @@ -649,7 +649,7 @@ static int epzs_motion_search4(MpegEncContext * s, int block, uint16_t *score_map= s->me_score_map; int map_generation; - new_pic = s->new_picture[0] + pic_xy; + new_pic = s->new_picture.data[0] + pic_xy; old_pic = ref_picture + pic_xy; map_generation= update_map_generation(s); @@ -723,7 +723,7 @@ static inline int halfpel_motion_search(MpegEncContext * s, xx = 16 * s->mb_x + 8*(n&1); yy = 16 * s->mb_y + 8*(n>>1); - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; mx = *mx_ptr; my = *my_ptr; @@ -789,7 +789,7 @@ static inline int fast_halfpel_motion_search(MpegEncContext * s, xx = 16 * s->mb_x + 8*(n&1); yy = 16 * s->mb_y + 8*(n>>1); - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; mx = *mx_ptr; my = *my_ptr; @@ -931,7 +931,7 @@ static inline int mv4_search(MpegEncContext *s, int xmin, int ymin, int xmax, in { int block; int P[10][2]; - uint8_t *ref_picture= s->last_picture[0]; + uint8_t *ref_picture= s->last_picture.data[0]; int dmin_sum=0; for(block=0; block<4; block++){ @@ -1019,7 +1019,8 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, int P[10][2]; const int shift= 1+s->quarter_sample; int mb_type=0; - uint8_t *ref_picture= s->last_picture[0]; + uint8_t *ref_picture= s->last_picture.data[0]; + Picture * const pic= &s->current_picture; get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code); rel_xmin= xmin - mb_x*16; @@ -1104,7 +1105,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, xx = mb_x * 16; yy = mb_y * 16; - pix = s->new_picture[0] + (yy * s->linesize) + xx; + pix = s->new_picture.data[0] + (yy * s->linesize) + xx; /* At this point (mx,my) are full-pell and the relative displacement */ ppix = ref_picture + ((yy+my) * s->linesize) + (xx+mx); @@ -1115,11 +1116,11 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, vard = (s->dsp.pix_norm(pix, ppix, s->linesize)+128)>>8; //printf("%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout); - s->mb_var [s->mb_width * mb_y + mb_x] = varc; - s->mc_mb_var[s->mb_width * mb_y + mb_x] = vard; - s->mb_mean [s->mb_width * mb_y + mb_x] = (sum+128)>>8; - s->mb_var_sum += varc; - s->mc_mb_var_sum += vard; + pic->mb_var [s->mb_width * mb_y + mb_x] = varc; + pic->mc_mb_var[s->mb_width * mb_y + mb_x] = vard; + pic->mb_mean [s->mb_width * mb_y + mb_x] = (sum+128)>>8; + pic->mb_var_sum += varc; + pic->mc_mb_var_sum += vard; //printf("E%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout); #if 0 @@ -1318,7 +1319,7 @@ static inline int check_bidir_mv(MpegEncContext * s, if (src_y == s->height) dxy&= 1; - ptr = s->last_picture[0] + (src_y * s->linesize) + src_x; + ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); fbmin += (mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->qscale; @@ -1333,10 +1334,10 @@ static inline int check_bidir_mv(MpegEncContext * s, if (src_y == s->height) dxy&= 1; - ptr = s->next_picture[0] + (src_y * s->linesize) + src_x; + ptr = s->next_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); - fbmin += s->dsp.pix_abs16x16(s->new_picture[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize); + fbmin += s->dsp.pix_abs16x16(s->new_picture.data[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize); return fbmin; } @@ -1418,7 +1419,7 @@ static inline int direct_search(MpegEncContext * s, src_y = clip(src_y, -16, height); if (src_y == height) dxy &= ~2; - ptr = s->last_picture[0] + (src_y * s->linesize) + src_x; + ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x; s->dsp.put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16); dxy = ((motion_by & 1) << 1) | (motion_bx & 1); @@ -1511,8 +1512,8 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, dmin= direct_search(s, mb_x, mb_y); - fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code); - bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code) - quant; + fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture.data[0], s->f_code); + bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture.data[0], s->b_code) - quant; //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); fbmin= bidir_refine(s, mb_x, mb_y); @@ -1534,8 +1535,8 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, type= MB_TYPE_BIDIR; } score= ((unsigned)(score*score + 128*256))>>16; - s->mc_mb_var_sum += score; - s->mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD + s->current_picture.mc_mb_var_sum += score; + s->current_picture.mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD } if(s->flags&CODEC_FLAG_HQ){ @@ -1581,7 +1582,7 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) int j; for(j=0; j<fcode && j<8; j++){ - if(s->pict_type==B_TYPE || s->mc_mb_var[i] < s->mb_var[i]) + if(s->pict_type==B_TYPE || s->current_picture.mc_mb_var[i] < s->current_picture.mb_var[i]) score[j]-= 170; } } diff --git a/src/libffmpeg/libavcodec/mpeg12.c b/src/libffmpeg/libavcodec/mpeg12.c index c55259974..e625a7262 100644 --- a/src/libffmpeg/libavcodec/mpeg12.c +++ b/src/libffmpeg/libavcodec/mpeg12.c @@ -134,7 +134,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) int n; UINT64 time_code; - if (s->picture_in_gop_number == 0) { + if (s->current_picture.key_frame) { /* mpeg1 header repeated every gop */ put_header(s, SEQ_START_CODE); @@ -1359,7 +1359,6 @@ static int mpeg_decode_init(AVCodecContext *avctx) s->mpeg_enc_ctx.picture_number = 0; s->repeat_field = 0; s->mpeg_enc_ctx.codec_id= avctx->codec->id; - avctx->mbskip_table= s->mpeg_enc_ctx.mbskip_table; return 0; } @@ -1403,9 +1402,6 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, s->pict_type = get_bits(&s->gb, 3); dprintf("pict_type=%d number=%d\n", s->pict_type, s->picture_number); - avctx->pict_type= s->pict_type; - avctx->key_frame= s->pict_type == I_TYPE; - skip_bits(&s->gb, 16); if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) { s->full_pel[0] = get_bits1(&s->gb); @@ -1423,6 +1419,9 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, s->mpeg_f_code[1][0] = f_code; s->mpeg_f_code[1][1] = f_code; } + s->current_picture.pict_type= s->pict_type; + s->current_picture.key_frame= s->pict_type == I_TYPE; + s->y_dc_scale = 8; s->c_dc_scale = 8; s->first_slice = 1; @@ -1576,7 +1575,7 @@ static void mpeg_decode_extension(AVCodecContext *avctx, * DECODE_SLICE_EOP if the end of the picture is reached */ static int mpeg_decode_slice(AVCodecContext *avctx, - AVPicture *pict, + AVVideoFrame *pict, int start_code, UINT8 *buf, int buf_size) { @@ -1677,38 +1676,25 @@ eos: //end of slice if (/*s->mb_x == 0 &&*/ s->mb_y == s->mb_height) { /* end of image */ - UINT8 **picture; + + if(s->mpeg2) + s->qscale >>=1; MPV_frame_end(s); if (s->pict_type == B_TYPE) { - picture = s->current_picture; - avctx->quality = s->qscale; + *pict= *(AVVideoFrame*)&s->current_picture; } else { + s->picture_number++; /* latency of 1 frame for I and P frames */ /* XXX: use another variable than picture_number */ - if (s->picture_number == 0) { - picture = NULL; + if (s->picture_number == 1) { + return DECODE_SLICE_OK; } else { - picture = s->last_picture; - avctx->quality = s->last_qscale; + *pict= *(AVVideoFrame*)&s->last_picture; } - s->last_qscale = s->qscale; - s->picture_number++; - } - if(s->mpeg2) - avctx->quality>>=1; - if (picture) { - pict->data[0] = picture[0]; - pict->data[1] = picture[1]; - pict->data[2] = picture[2]; - pict->linesize[0] = s->linesize; - pict->linesize[1] = s->uvlinesize; - pict->linesize[2] = s->uvlinesize; - return DECODE_SLICE_EOP; - } else { - return DECODE_SLICE_OK; } + return DECODE_SLICE_EOP; } else { return DECODE_SLICE_OK; } @@ -1827,7 +1813,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, Mpeg1Context *s = avctx->priv_data; UINT8 *buf_end, *buf_ptr, *buf_start; int len, start_code_found, ret, code, start_code, input_size; - AVPicture *picture = data; + AVVideoFrame *picture = data; MpegEncContext *s2 = &s->mpeg_enc_ctx; dprintf("fill_buffer\n"); @@ -1837,13 +1823,9 @@ static int mpeg_decode_frame(AVCodecContext *avctx, /* special case for last picture */ if (buf_size == 0) { if (s2->picture_number > 0) { - picture->data[0] = s2->next_picture[0]; - picture->data[1] = s2->next_picture[1]; - picture->data[2] = s2->next_picture[2]; - picture->linesize[0] = s2->linesize; - picture->linesize[1] = s2->uvlinesize; - picture->linesize[2] = s2->uvlinesize; - *data_size = sizeof(AVPicture); + *picture= *(AVVideoFrame*)&s2->next_picture; + + *data_size = sizeof(AVVideoFrame); } return 0; } @@ -1914,8 +1896,15 @@ static int mpeg_decode_frame(AVCodecContext *avctx, s->buffer, input_size); break; default: + /* skip b frames if we dont have reference frames */ + if(s2->last_picture.data[0]==NULL && s2->pict_type==B_TYPE) break; + /* skip b frames if we are in a hurry */ + if(avctx->hurry_up && s2->pict_type==B_TYPE) break; + /* skip everything if we are in a hurry>=5 */ + if(avctx->hurry_up>=5) break; + if (start_code >= SLICE_MIN_START_CODE && - start_code <= SLICE_MAX_START_CODE && avctx->hurry_up<5) { + start_code <= SLICE_MAX_START_CODE) { ret = mpeg_decode_slice(avctx, picture, start_code, s->buffer, input_size); if (ret == DECODE_SLICE_EOP) { diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index b3565d3cc..c1a0b0b55 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -46,7 +46,6 @@ void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edg static void emulated_edge_mc(MpegEncContext *s, UINT8 *src, int linesize, int block_w, int block_h, int src_x, int src_y, int w, int h); -#define EDGE_WIDTH 16 /* enable all paranoid tests for rounding, overflows, etc... */ //#define PARANOID @@ -268,10 +267,47 @@ int DCT_common_init(MpegEncContext *s) return 0; } +/** + * allocates various arrays for a Picture structure, except the pixels themself. + * The pixels are allocated/set in te get_buffer() + */ +static int alloc_picture(MpegEncContext *s, Picture *pic){ + if (s->encoding) { + CHECKED_ALLOCZ(pic->mb_var , s->mb_num * sizeof(INT16)) + CHECKED_ALLOCZ(pic->mc_mb_var, s->mb_num * sizeof(INT16)) + CHECKED_ALLOCZ(pic->mb_mean , s->mb_num * sizeof(INT8)) + } + + CHECKED_ALLOCZ(pic->mbskip_table , s->mb_num * sizeof(UINT8)+1) //the +1 is for the slice end check + CHECKED_ALLOCZ(pic->qscale_table , s->mb_num * sizeof(UINT8)) + pic->qstride= s->mb_width; + + return 0; +fail: //for the CHECKED_ALLOCZ macro + return -1; +} + +static void free_picture(MpegEncContext *s, Picture *pic){ + int i; + + av_freep(&pic->mb_var); + av_freep(&pic->mc_mb_var); + av_freep(&pic->mb_mean); + av_freep(&pic->mbskip_table); + av_freep(&pic->qscale_table); + + if(s->avctx->get_buffer == avcodec_default_get_buffer){ + for(i=0; i<4; i++){ + av_freep(&pic->base[i]); + pic->data[i]= NULL; + } + av_freep(&pic->opaque); + } +} + /* init common structure for both encoder and decoder */ int MPV_common_init(MpegEncContext *s) { - UINT8 *pict; int y_size, c_size, yc_size, i; dsputil_init(&s->dsp, s->avctx->dsp_mask); @@ -279,7 +315,7 @@ int MPV_common_init(MpegEncContext *s) s->flags= s->avctx->flags; - s->mb_width = (s->width + 15) / 16; + s->mb_width = (s->width + 15) / 16; s->mb_height = (s->height + 15) / 16; /* set default edge pos, will be overriden in decode_header if needed */ @@ -298,51 +334,12 @@ int MPV_common_init(MpegEncContext *s) + (toupper((s->avctx->fourcc>>16)&0xFF)<<16) + (toupper((s->avctx->fourcc>>24)&0xFF)<<24); - if(!(s->flags&CODEC_FLAG_DR1)){ - s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH; - s->uvlinesize = s->mb_width * 8 + EDGE_WIDTH; - - for(i=0;i<3;i++) { - int w, h, shift, pict_start; - unsigned size; - - w = s->linesize; - h = s->mb_height * 16 + 2 * EDGE_WIDTH; - shift = (i == 0) ? 0 : 1; - size = (s->linesize>>shift) * (h >> shift); - pict_start = (s->linesize>>shift) * (EDGE_WIDTH >> shift) + (EDGE_WIDTH >> shift); - - CHECKED_ALLOCZ(pict, size) - s->last_picture_base[i] = pict; - s->last_picture[i] = pict + pict_start; - if(i>0) memset(s->last_picture_base[i], 128, size); - - CHECKED_ALLOCZ(pict, size) - s->next_picture_base[i] = pict; - s->next_picture[i] = pict + pict_start; - if(i>0) memset(s->next_picture_base[i], 128, size); - - if (s->has_b_frames || s->codec_id==CODEC_ID_MPEG4) { - /* Note the MPEG4 stuff is here cuz of buggy encoders which dont set the low_delay flag but - do low-delay encoding, so we cant allways distinguish b-frame containing streams from low_delay streams */ - CHECKED_ALLOCZ(pict, size) - s->aux_picture_base[i] = pict; - s->aux_picture[i] = pict + pict_start; - if(i>0) memset(s->aux_picture_base[i], 128, size); - } - } - s->ip_buffer_count= 2; - } - CHECKED_ALLOCZ(s->edge_emu_buffer, (s->width+64)*2*17*2); //(width + edge + align)*interlaced*MBsize*tolerance - + + s->avctx->coded_picture= (AVVideoFrame*)&s->current_picture; + if (s->encoding) { - int j; int mv_table_size= (s->mb_width+2)*(s->mb_height+2); - - CHECKED_ALLOCZ(s->mb_var , s->mb_num * sizeof(INT16)) - CHECKED_ALLOCZ(s->mc_mb_var, s->mb_num * sizeof(INT16)) - CHECKED_ALLOCZ(s->mb_mean , s->mb_num * sizeof(INT8)) /* Allocate MV tables */ CHECKED_ALLOCZ(s->p_mv_table , mv_table_size * 2 * sizeof(INT16)) @@ -354,28 +351,12 @@ int MPV_common_init(MpegEncContext *s) CHECKED_ALLOCZ(s->b_direct_back_mv_table, mv_table_size * 2 * sizeof(INT16)) CHECKED_ALLOCZ(s->b_direct_mv_table , mv_table_size * 2 * sizeof(INT16)) - CHECKED_ALLOCZ(s->me_scratchpad, s->linesize*16*3*sizeof(uint8_t)) + //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer() + CHECKED_ALLOCZ(s->me_scratchpad, s->width*2*16*3*sizeof(uint8_t)) CHECKED_ALLOCZ(s->me_map , ME_MAP_SIZE*sizeof(uint32_t)) CHECKED_ALLOCZ(s->me_score_map, ME_MAP_SIZE*sizeof(uint16_t)) - if(s->max_b_frames){ - for(j=0; j<REORDER_BUFFER_SIZE; j++){ - int i; - for(i=0;i<3;i++) { - int w, h, shift, size; - - w = s->linesize; - h = s->mb_height * 16; - shift = (i == 0) ? 0 : 1; - size = (w >> shift) * (h >> shift); - - CHECKED_ALLOCZ(pict, size); - s->picture_buffer[j][i] = pict; - } - } - } - if(s->codec_id==CODEC_ID_MPEG4){ CHECKED_ALLOCZ(s->tex_pb_buffer, PB_BUFFER_SIZE); CHECKED_ALLOCZ( s->pb2_buffer, PB_BUFFER_SIZE); @@ -434,12 +415,6 @@ int MPV_common_init(MpegEncContext *s) s->dc_val[0][i] = 1024; } - CHECKED_ALLOCZ(s->next_qscale_table , s->mb_num * sizeof(UINT8)) - CHECKED_ALLOCZ(s->last_qscale_table , s->mb_num * sizeof(UINT8)) - CHECKED_ALLOCZ(s->aux_qscale_table , s->mb_num * sizeof(UINT8)) - s->qscale_table= s->next_qscale_table; - s->avctx->qstride= s->mb_width; - /* which mb is a intra block */ CHECKED_ALLOCZ(s->mbintra_table, s->mb_num); memset(s->mbintra_table, 1, s->mb_num); @@ -470,10 +445,13 @@ void MPV_common_end(MpegEncContext *s) { int i; + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0]){ + s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]); + } + } + av_freep(&s->mb_type); - av_freep(&s->mb_var); - av_freep(&s->mc_mb_var); - av_freep(&s->mb_mean); av_freep(&s->p_mv_table); av_freep(&s->b_forw_mv_table); av_freep(&s->b_back_mv_table); @@ -489,9 +467,6 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->mbintra_table); av_freep(&s->cbp_table); av_freep(&s->pred_dir_table); - av_freep(&s->next_qscale_table); - av_freep(&s->last_qscale_table); - av_freep(&s->aux_qscale_table); av_freep(&s->me_scratchpad); av_freep(&s->me_map); av_freep(&s->me_score_map); @@ -507,24 +482,9 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); av_freep(&s->error_status_table); - - for(i=0;i<3;i++) { - int j; - if(!(s->flags&CODEC_FLAG_DR1)){ - av_freep(&s->last_picture_base[i]); - av_freep(&s->next_picture_base[i]); - av_freep(&s->aux_picture_base[i]); - } - s->last_picture_base[i]= - s->next_picture_base[i]= - s->aux_picture_base [i] = NULL; - s->last_picture[i]= - s->next_picture[i]= - s->aux_picture [i] = NULL; - for(j=0; j<REORDER_BUFFER_SIZE; j++){ - av_freep(&s->picture_buffer[j][i]); - } + for(i=0; i<MAX_PICTURE_COUNT; i++){ + free_picture(s, &s->picture[i]); } s->context_initialized = 0; } @@ -813,70 +773,76 @@ static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w) /* generic function for encode/decode called before a frame is coded/decoded */ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) { - int i; - UINT8 *tmp; + int i, r; + AVVideoFrame *pic; s->mb_skiped = 0; - avctx->mbskip_table= s->mbskip_table; - - s->hurry_up= s->avctx->hurry_up; - s->error_resilience= avctx->error_resilience; - - if(avctx->flags&CODEC_FLAG_DR1){ - if(avctx->get_buffer_callback(avctx, s->width, s->height, s->pict_type) < 0){ - fprintf(stderr, "get_buffer() failed\n"); - return -1; + + /* mark&release old frames */ + if (s->pict_type != B_TYPE && s->last_picture.data[0]) { + Picture *pic= NULL; + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0] == s->last_picture.data[0]){ +// s->picture[i].reference=0; + avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]); + break; + } + } + assert(i<MAX_PICTURE_COUNT); + + /* release forgotten pictures */ + /* if(mpeg124/h263) */ + if(!s->encoding){ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0] && s->picture[i].data[0] != s->next_picture.data[0] && s->picture[i].reference){ + fprintf(stderr, "releasing zombie picture\n"); + avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]); + } + } } - - s->linesize = avctx->dr_stride; - s->uvlinesize= avctx->dr_uvstride; - s->ip_buffer_count= avctx->dr_ip_buffer_count; } - avctx->dr_ip_buffer_count= s->ip_buffer_count; +alloc: + if(!s->encoding){ + /* find unused Picture */ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0]==NULL) break; + } + assert(i<MAX_PICTURE_COUNT); - if (s->pict_type == B_TYPE) { - for(i=0;i<3;i++) { - if(avctx->flags&CODEC_FLAG_DR1) - s->aux_picture[i]= avctx->dr_buffer[i]; - - //FIXME the following should never be needed, the decoder should drop b frames if no reference is available - if(s->next_picture[i]==NULL) - s->next_picture[i]= s->aux_picture[i]; - if(s->last_picture[i]==NULL) - s->last_picture[i]= s->next_picture[i]; - - s->current_picture[i] = s->aux_picture[i]; + pic= (AVVideoFrame*)&s->picture[i]; + pic->reference= s->pict_type != B_TYPE; + pic->coded_picture_number= s->current_picture.coded_picture_number+1; + + r= avctx->get_buffer(avctx, pic); + + if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){ + fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n"); + return -1; } - s->avctx->display_qscale_table= - s->avctx->current_qscale_table= - s->qscale_table= s->aux_qscale_table; - } else { - for(i=0;i<3;i++) { - /* swap next and last */ - if(avctx->flags&CODEC_FLAG_DR1) - tmp= avctx->dr_buffer[i]; - else - tmp = s->last_picture[i]; - s->last_picture[i] = s->next_picture[i]; - s->next_picture[i] = tmp; - s->current_picture[i] = tmp; - - if(s->last_picture[i]==NULL) - s->last_picture[i]= s->next_picture[i]; + s->linesize = pic->linesize[0]; + s->uvlinesize= pic->linesize[1]; + + if(pic->qscale_table==NULL) + alloc_picture(s, (Picture*)pic); - s->last_dr_opaque= s->next_dr_opaque; - s->next_dr_opaque= avctx->dr_opaque_frame; + s->current_picture= s->picture[i]; + } - if(s->has_b_frames && s->last_dr_opaque && s->codec_id!=CODEC_ID_SVQ1) - avctx->dr_opaque_frame= s->last_dr_opaque; - else - avctx->dr_opaque_frame= s->next_dr_opaque; - } - s->avctx->current_qscale_table= s->qscale_table = s->last_qscale_table; - s->avctx->display_qscale_table= s->last_qscale_table = s->next_qscale_table; - s->next_qscale_table= s->qscale_table; + if (s->pict_type != B_TYPE) { + s->last_picture= s->next_picture; + s->next_picture= s->current_picture; } + + if(s->pict_type != I_TYPE && s->last_picture.data[0]==NULL){ + fprintf(stderr, "warning: first frame is no keyframe\n"); + assert(s->pict_type != B_TYPE); //these should have been dropped if we dont have a reference + goto alloc; + } + + s->hurry_up= s->avctx->hurry_up; + s->error_resilience= avctx->error_resilience; + /* set dequantizer, we cant do it during init as it might change for mpeg4 and we cant do it in the header decode as init isnt called for mpeg4 there yet */ if(s->out_format == FMT_H263){ @@ -893,14 +859,15 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* generic function for encode/decode called after a frame has been coded/decoded */ void MPV_frame_end(MpegEncContext *s) { - s->avctx->key_frame = (s->pict_type == I_TYPE); - s->avctx->pict_type = s->pict_type; + int i; /* draw edge for correct motion prediction if outside */ - if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) { - draw_edges(s->current_picture[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH ); - draw_edges(s->current_picture[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); - draw_edges(s->current_picture[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); + if(s->codec_id!=CODEC_ID_SVQ1){ + if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) { + draw_edges(s->current_picture.data[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH ); + draw_edges(s->current_picture.data[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); + draw_edges(s->current_picture.data[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); + } } emms_c(); @@ -910,84 +877,182 @@ void MPV_frame_end(MpegEncContext *s) s->num_available_buffers++; if(s->num_available_buffers>2) s->num_available_buffers= 2; } + + s->current_picture.quality= s->qscale; //FIXME get average of qscale_table + s->current_picture.pict_type= s->pict_type; + s->current_picture.key_frame= s->pict_type == I_TYPE; + + /* copy back current_picture variables */ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0] == s->current_picture.data[0]){ + s->picture[i]= s->current_picture; + break; + } + } + assert(i<MAX_PICTURE_COUNT); + + /* release non refernce frames */ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0] && !s->picture[i].reference) + s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]); + } } -/* reorder input for encoding */ -void reorder_input(MpegEncContext *s, AVPicture *pict) -{ - int i, j, index; - - if(s->max_b_frames > FF_MAX_B_FRAMES) s->max_b_frames= FF_MAX_B_FRAMES; - -// delay= s->max_b_frames+1; (or 0 if no b frames cuz decoder diff) - - for(j=0; j<REORDER_BUFFER_SIZE-1; j++){ - s->coded_order[j]= s->coded_order[j+1]; - } - s->coded_order[j].picture[0]= s->coded_order[j].picture[1]= s->coded_order[j].picture[2]= NULL; //catch uninitalized buffers - s->coded_order[j].pict_type=0; - - switch(s->input_pict_type){ - default: - case I_TYPE: - case S_TYPE: - case P_TYPE: - index= s->max_b_frames - s->b_frames_since_non_b; - s->b_frames_since_non_b=0; - break; - case B_TYPE: - index= s->max_b_frames + 1; - s->b_frames_since_non_b++; - break; - } -//printf("index:%d type:%d strides: %d %d\n", index, s->input_pict_type, pict->linesize[0], s->linesize); - if( (index==0 || (s->flags&CODEC_FLAG_INPUT_PRESERVED)) - && pict->linesize[0] == s->linesize - && pict->linesize[1] == s->uvlinesize - && pict->linesize[2] == s->uvlinesize){ -//printf("ptr\n"); - for(i=0; i<3; i++){ - s->coded_order[index].picture[i]= pict->data[i]; - } +static int load_input_picture(MpegEncContext *s, AVVideoFrame *pic_arg){ + AVVideoFrame *pic; + int i,r; + const int encoding_delay= s->max_b_frames; + + /* find unused Picture */ + for(i=0; i<MAX_PICTURE_COUNT; i++){ + if(s->picture[i].data[0]==NULL) break; + } + assert(i<MAX_PICTURE_COUNT); + + pic= (AVVideoFrame*)&s->picture[i]; + pic->reference= 1; + +// assert(avctx->get_buffer == default_get_buffer || avctx->get_buffer==NULL); + r= s->avctx->get_buffer(s->avctx, pic); + + if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){ + fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n"); + return -1; + } + + assert(s->linesize==0 || s->linesize ==pic->linesize[0]); + assert(s->uvlinesize==0 || s->uvlinesize==pic->linesize[1]); + assert(pic->linesize[1] == pic->linesize[2]); + s->linesize = pic->linesize[0]; + s->uvlinesize= pic->linesize[1]; + + if(pic->qscale_table==NULL) + alloc_picture(s, (Picture*)pic); + +// assert(s->input_picture[0]==NULL || s->input_picture[0]->data[0]==NULL); + + if(s->input_picture[encoding_delay]) + pic->display_picture_number= s->input_picture[encoding_delay]->display_picture_number + 1; +//printf("dpn2:%d\n", pic->display_picture_number); + + /* shift buffer entries */ + for(i=1; i<MAX_PICTURE_COUNT /*s->encoding_delay+1*/; i++) + s->input_picture[i-1]= s->input_picture[i]; + + s->input_picture[encoding_delay]= (Picture*)pic; + pic->pict_type= pic_arg->pict_type; + pic->quality= pic_arg->quality; + + if( pic->data[0] == pic_arg->data[0] + && pic->data[1] == pic_arg->data[1] + && pic->data[2] == pic_arg->data[2]){ + // empty }else{ -//printf("copy\n"); + int h_chroma_shift, v_chroma_shift; + + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + for(i=0; i<3; i++){ - uint8_t *src = pict->data[i]; - uint8_t *dest; - int src_wrap = pict->linesize[i]; - int dest_wrap = s->linesize; - int w = s->width; - int h = s->height; - - if(index==0) dest= s->last_picture[i]+16; //is current_picture indeed but the switch hapens after reordering - else dest= s->picture_buffer[s->picture_buffer_index][i]; - - if (i >= 1) { - dest_wrap >>= 1; - w >>= 1; - h >>= 1; + int src_stride= pic_arg->linesize[i]; + int dst_stride= i ? s->uvlinesize : s->linesize; + int h_shift= i ? h_chroma_shift : 0; + int v_shift= i ? v_chroma_shift : 0; + int w= s->width >>h_shift; + int h= s->height>>v_shift; + uint8_t *src= pic_arg->data[i]; + uint8_t *dst= pic->data[i] + 16; + + if(src_stride==dst_stride) + memcpy(dst, src, src_stride*h); + else{ + while(h--){ + memcpy(dst, src, w); + dst += dst_stride; + src += src_stride; + } } + } + } - s->coded_order[index].picture[i]= dest; - for(j=0;j<h;j++) { - memcpy(dest, src, w); - dest += dest_wrap; - src += src_wrap; + return 0; +} + +static void select_input_picture(MpegEncContext *s){ + int i; + const int encoding_delay= s->max_b_frames; + int coded_pic_num=0; + + if(s->reordered_input_picture[0]) + coded_pic_num= s->reordered_input_picture[0]->coded_picture_number + 1; +//printf("cpn:%d\n", coded_pic_num); + for(i=1; i<MAX_PICTURE_COUNT; i++) + s->reordered_input_picture[i-1]= s->reordered_input_picture[i]; + s->reordered_input_picture[MAX_PICTURE_COUNT-1]= NULL; + + /* set next picture types & ordering */ + if(s->reordered_input_picture[0]==NULL && s->input_picture[0]){ + if(s->input_picture[0]->pict_type){ + /* user selected pict_type */ + if(s->input_picture[0]->pict_type == I_TYPE){ + s->reordered_input_picture[0]= s->input_picture[0]; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + }else{ + int b_frames; + + for(b_frames=0; b_frames<s->max_b_frames+1; b_frames++){ + if(s->input_picture[b_frames]->pict_type!=B_TYPE) break; + } + + if(b_frames > s->max_b_frames){ + fprintf(stderr, "warning, too many bframes in a row\n"); + b_frames = s->max_b_frames; + s->input_picture[b_frames]->pict_type= I_TYPE; + } + + s->reordered_input_picture[0]= s->input_picture[b_frames]; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + for(i=0; i<b_frames; i++){ + coded_pic_num++; + s->reordered_input_picture[i+1]= s->input_picture[i]; + s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num; + } + } + }else{ + if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture.data[0]==NULL || s->intra_only){ + s->reordered_input_picture[0]= s->input_picture[0]; + s->reordered_input_picture[0]->pict_type= I_TYPE; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + }else{ + s->reordered_input_picture[0]= s->input_picture[s->max_b_frames]; + if(s->picture_in_gop_number + s->max_b_frames >= s->gop_size) + s->reordered_input_picture[0]->pict_type= I_TYPE; + else + s->reordered_input_picture[0]->pict_type= P_TYPE; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + for(i=0; i<s->max_b_frames; i++){ + coded_pic_num++; + s->reordered_input_picture[i+1]= s->input_picture[i]; + s->reordered_input_picture[i+1]->pict_type= B_TYPE; + s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num; + } } - } - if(index!=0){ - s->picture_buffer_index++; - if(s->picture_buffer_index >= REORDER_BUFFER_SIZE) s->picture_buffer_index=0; } } - s->coded_order[index].pict_type = s->input_pict_type; - s->coded_order[index].qscale = s->input_qscale; - s->coded_order[index].force_type= s->force_input_type; - s->coded_order[index].picture_in_gop_number= s->input_picture_in_gop_number; - s->coded_order[index].picture_number= s->input_picture_number; - - for(i=0; i<3; i++){ - s->new_picture[i]= s->coded_order[0].picture[i]; + + if(s->reordered_input_picture[0]){ + if(s->reordered_input_picture[0]->pict_type==B_TYPE){ + s->reordered_input_picture[0]->reference=0; + } + s->current_picture= *s->reordered_input_picture[0]; + s->new_picture= s->current_picture; + s->new_picture.data[0]+=16; + s->new_picture.data[1]+=16; + s->new_picture.data[2]+=16; + + s->picture_number= s->new_picture.display_picture_number; +//printf("dpn:%d\n", s->picture_number); + }else{ + memset(&s->new_picture, 0, sizeof(Picture)); } } @@ -995,52 +1060,27 @@ int MPV_encode_picture(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) { MpegEncContext *s = avctx->priv_data; - AVPicture *pict = data; - - s->input_qscale = avctx->quality; + AVVideoFrame *pic_arg = data; + int i; init_put_bits(&s->pb, buf, buf_size, NULL, NULL); - if(avctx->force_type){ - s->input_pict_type= - s->force_input_type= avctx->force_type; - }else if(s->flags&CODEC_FLAG_PASS2){ - s->input_pict_type= - s->force_input_type= s->rc_context.entry[s->input_picture_number].new_pict_type; - }else{ - s->force_input_type=0; - if (!s->intra_only) { - /* first picture of GOP is intra */ - if (s->input_picture_in_gop_number % s->gop_size==0){ - s->input_pict_type = I_TYPE; - }else if(s->max_b_frames==0){ - s->input_pict_type = P_TYPE; - }else{ - if(s->b_frames_since_non_b < s->max_b_frames) //FIXME more IQ - s->input_pict_type = B_TYPE; - else - s->input_pict_type = P_TYPE; - } - } else { - s->input_pict_type = I_TYPE; - } - } + s->picture_in_gop_number++; - if(s->input_pict_type==I_TYPE) - s->input_picture_in_gop_number=0; + load_input_picture(s, pic_arg); - reorder_input(s, pict); + select_input_picture(s); /* output? */ - if(s->coded_order[0].picture[0]){ - - s->pict_type= s->coded_order[0].pict_type; - if (s->fixed_qscale) /* the ratecontrol needs the last qscale so we dont touch it for CBR */ - s->qscale= s->coded_order[0].qscale; - s->force_type= s->coded_order[0].force_type; - s->picture_in_gop_number= s->coded_order[0].picture_in_gop_number; - s->picture_number= s->coded_order[0].picture_number; + if(s->new_picture.data[0]){ + s->pict_type= s->new_picture.pict_type; + if (s->fixed_qscale){ /* the ratecontrol needs the last qscale so we dont touch it for CBR */ + s->qscale= (int)(s->new_picture.quality+0.5); + assert(s->qscale); + } +//emms_c(); +//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale); MPV_frame_start(s, avctx); encode_picture(s, s->picture_number); @@ -1059,43 +1099,23 @@ int MPV_encode_picture(AVCodecContext *avctx, if (s->out_format == FMT_MJPEG) mjpeg_picture_trailer(s); - - if(!s->fixed_qscale) - avctx->quality = s->qscale; if(s->flags&CODEC_FLAG_PASS1) ff_write_pass1_stats(s); - } s->input_picture_number++; - s->input_picture_in_gop_number++; flush_put_bits(&s->pb); s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; -//printf("fcode: %d, type: %d, head: %d, mv: %d, misc: %d, frame: %d, itex: %d, ptex: %d\n", -//s->f_code, avctx->key_frame, s->header_bits, s->mv_bits, s->misc_bits, s->frame_bits, s->i_tex_bits, s->p_tex_bits); -#if 0 //dump some stats to stats.txt for testing/debuging -if(s->max_b_frames==0) -{ - static FILE *f=NULL; - if(!f) f= fopen("stats.txt", "wb"); - get_psnr(pict->data, s->current_picture, - pict->linesize, s->linesize, avctx); - fprintf(f, "%7d, %7d, %2.4f\n", pbBufPtr(&s->pb) - s->pb.buf, s->qscale, avctx->psnr_y); -} -#endif - if (avctx->get_psnr) { - /* At this point pict->data should have the original frame */ - /* an s->current_picture should have the coded/decoded frame */ - get_psnr(pict->data, s->current_picture, - pict->linesize, s->linesize, avctx); -// printf("%f\n", avctx->psnr_y); + for(i=0; i<4; i++){ + avctx->error[i] += s->current_picture.error[i]; } + return pbBufPtr(&s->pb) - s->pb.buf; } @@ -1757,7 +1777,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) mb_x = s->mb_x; mb_y = s->mb_y; - s->qscale_table[mb_xy]= s->qscale; + s->current_picture.qscale_table[mb_xy]= s->qscale; /* update DC predictors for P macroblocks */ if (!s->mb_intra) { @@ -1817,39 +1837,53 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) } } - if (!(s->encoding && (s->intra_only || s->pict_type==B_TYPE))) { + if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==B_TYPE))) { //FIXME precalc UINT8 *dest_y, *dest_cb, *dest_cr; int dct_linesize, dct_offset; op_pixels_func (*op_pix)[4]; qpel_mc_func (*op_qpix)[16]; - /* avoid copy if macroblock skipped in last frame too - dont touch it for B-frames as they need the skip info from the next p-frame */ + /* avoid copy if macroblock skipped in last frame too */ if (s->pict_type != B_TYPE) { + s->current_picture.mbskip_table[mb_xy]= s->mb_skiped; + } + + /* skip only during decoding as we might trash the buffers during encoding a bit */ + if(!s->encoding){ UINT8 *mbskip_ptr = &s->mbskip_table[mb_xy]; - if (s->mb_skiped) { - s->mb_skiped = 0; + const int age= s->current_picture.age; + assert(age); + + if (s->mb_skiped) { + s->mb_skiped= 0; + assert(s->pict_type!=I_TYPE); + (*mbskip_ptr) ++; /* indicate that this time we skiped it */ if(*mbskip_ptr >99) *mbskip_ptr= 99; - /* if previous was skipped too, then nothing to do ! - skip only during decoding as we might trash the buffers during encoding a bit */ - if (*mbskip_ptr >= s->ip_buffer_count && !s->encoding) - return; + /* if previous was skipped too, then nothing to do ! */ + if (*mbskip_ptr >= age){ +//if(s->pict_type!=B_TYPE && s->mb_x==0) printf("\n"); +//if(s->pict_type!=B_TYPE) printf("%d%d ", *mbskip_ptr, age); + if(s->pict_type!=B_TYPE) return; + if(s->avctx->draw_horiz_band==NULL && *mbskip_ptr > age) return; + /* we dont draw complete frames here so we cant skip */ + } } else { *mbskip_ptr = 0; /* not skipped */ } - } + }else + s->mb_skiped= 0; if(s->pict_type==B_TYPE && s->avctx->draw_horiz_band){ - dest_y = s->current_picture [0] + mb_x * 16; - dest_cb = s->current_picture[1] + mb_x * 8; - dest_cr = s->current_picture[2] + mb_x * 8; + dest_y = s->current_picture.data[0] + mb_x * 16; + dest_cb = s->current_picture.data[1] + mb_x * 8; + dest_cr = s->current_picture.data[2] + mb_x * 8; }else{ - dest_y = s->current_picture [0] + (mb_y * 16* s->linesize ) + mb_x * 16; - dest_cb = s->current_picture[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8; - dest_cr = s->current_picture[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8; + dest_y = s->current_picture.data[0] + (mb_y * 16* s->linesize ) + mb_x * 16; + dest_cb = s->current_picture.data[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8; + dest_cr = s->current_picture.data[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8; } if (s->interlaced_dct) { @@ -1873,12 +1907,12 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) } if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); + MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix); op_pix = s->dsp.avg_pixels_tab; op_qpix= s->dsp.avg_qpel_pixels_tab; } if (s->mv_dir & MV_DIR_BACKWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); + MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix); } } @@ -2154,13 +2188,13 @@ void ff_draw_horiz_band(MpegEncContext *s){ 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); + src_ptr[0] = s->current_picture.data[0] + offset; + src_ptr[1] = s->current_picture.data[1] + (offset >> 2); + src_ptr[2] = s->current_picture.data[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); + src_ptr[0] = s->last_picture.data[0] + offset; + src_ptr[1] = s->last_picture.data[1] + (offset >> 2); + src_ptr[2] = s->last_picture.data[2] + (offset >> 2); } emms_c(); @@ -2180,7 +2214,7 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) for(i=0; i<6; i++) skip_dct[i]=0; if(s->adaptive_quant){ - s->dquant= s->qscale_table[mb_x + mb_y*s->mb_width] - s->qscale; + s->dquant= s->current_picture.qscale_table[mb_x + mb_y*s->mb_width] - s->qscale; if(s->out_format==FMT_H263){ if (s->dquant> 2) s->dquant= 2; @@ -2206,7 +2240,7 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) int emu=0; wrap_y = s->linesize; - ptr = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16; + ptr = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){ emulated_edge_mc(s, ptr, wrap_y, 16, 16, mb_x*16, mb_y*16, s->width, s->height); @@ -2239,14 +2273,14 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) skip_dct[5]= 1; }else{ int wrap_c = s->uvlinesize; - ptr = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8; if(emu){ emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); ptr= s->edge_emu_buffer; } s->dsp.get_pixels(s->block[4], ptr, wrap_c); - ptr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8; if(emu){ emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); ptr= s->edge_emu_buffer; @@ -2261,14 +2295,14 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) int wrap_y, wrap_c; int emu=0; - dest_y = s->current_picture[0] + (mb_y * 16 * s->linesize ) + mb_x * 16; - dest_cb = s->current_picture[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8; - dest_cr = s->current_picture[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8; + dest_y = s->current_picture.data[0] + (mb_y * 16 * s->linesize ) + mb_x * 16; + dest_cb = s->current_picture.data[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8; + dest_cr = s->current_picture.data[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8; wrap_y = s->linesize; wrap_c = s->uvlinesize; - ptr_y = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16; - ptr_cb = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8; - ptr_cr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr_y = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; + ptr_cb = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr_cr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8; if ((!s->no_rounding) || s->pict_type==B_TYPE){ op_pix = s->dsp.put_pixels_tab; @@ -2279,12 +2313,12 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) } if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); + MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix); op_pix = s->dsp.avg_pixels_tab; op_qpix= s->dsp.avg_qpel_pixels_tab; } if (s->mv_dir & MV_DIR_BACKWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); + MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix); } if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){ @@ -2330,16 +2364,15 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) } s->dsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); } - /* pre quantization */ - if(s->mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){ + if(s->current_picture.mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){ //FIXME optimize if(s->dsp.pix_abs8x8(ptr_y , dest_y , wrap_y) < 20*s->qscale) skip_dct[0]= 1; if(s->dsp.pix_abs8x8(ptr_y + 8, dest_y + 8, wrap_y) < 20*s->qscale) skip_dct[1]= 1; if(s->dsp.pix_abs8x8(ptr_y +dct_offset , dest_y +dct_offset , wrap_y) < 20*s->qscale) skip_dct[2]= 1; if(s->dsp.pix_abs8x8(ptr_y +dct_offset+ 8, dest_y +dct_offset+ 8, wrap_y) < 20*s->qscale) skip_dct[3]= 1; - if(s->dsp.pix_abs8x8(ptr_cb , dest_cb , wrap_y) < 20*s->qscale) skip_dct[4]= 1; - if(s->dsp.pix_abs8x8(ptr_cr , dest_cr , wrap_y) < 20*s->qscale) skip_dct[5]= 1; + if(s->dsp.pix_abs8x8(ptr_cb , dest_cb , wrap_c) < 20*s->qscale) skip_dct[4]= 1; + if(s->dsp.pix_abs8x8(ptr_cr , dest_cr , wrap_c) < 20*s->qscale) skip_dct[5]= 1; #if 0 { static int stat[7]; @@ -2461,6 +2494,7 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext d->last_bits= 0; d->mb_skiped= s->mb_skiped; + d->qscale= s->qscale; } static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *s, int type){ @@ -2497,6 +2531,7 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext * for(i=0; i<6; i++) d->block_last_index[i]= s->block_last_index[i]; d->interlaced_dct= s->interlaced_dct; + d->qscale= s->qscale; } static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegEncContext *best, int type, @@ -2529,6 +2564,22 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE copy_context_after_encode(best, s, type); } } + +static inline int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride){ + uint32_t *sq = squareTbl + 256; + int acc=0; + int x,y; + + if(w==16 && h==16) + return s->dsp.pix_norm(src1, src2, stride); + + for(y=0; y<h; y++){ + for(x=0; x<w; x++){ + acc+= sq[src1[x + y*stride] - src2[x + y*stride]]; + } + } + return acc; +} static void encode_picture(MpegEncContext *s, int picture_number) { @@ -2557,8 +2608,8 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->block_wrap[5]= s->mb_width + 2; /* Reset the average MB variance */ - s->mb_var_sum = 0; - s->mc_mb_var_sum = 0; + s->current_picture.mb_var_sum = 0; + s->current_picture.mc_mb_var_sum = 0; /* we need to initialize some time vars before we can encode b-frames */ if (s->h263_pred && !s->h263_msmpeg4) @@ -2604,15 +2655,15 @@ static void encode_picture(MpegEncContext *s, int picture_number) for(mb_x=0; mb_x < s->mb_width; mb_x++) { int xx = mb_x * 16; int yy = mb_y * 16; - uint8_t *pix = s->new_picture[0] + (yy * s->linesize) + xx; + uint8_t *pix = s->new_picture.data[0] + (yy * s->linesize) + xx; int varc; int sum = s->dsp.pix_sum(pix, s->linesize); varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8; - s->mb_var [s->mb_width * mb_y + mb_x] = varc; - s->mb_mean[s->mb_width * mb_y + mb_x] = (sum+128)>>8; - s->mb_var_sum += varc; + s->current_picture.mb_var [s->mb_width * mb_y + mb_x] = varc; + s->current_picture.mb_mean[s->mb_width * mb_y + mb_x] = (sum+128)>>8; + s->current_picture.mb_var_sum += varc; } } } @@ -2622,13 +2673,9 @@ static void encode_picture(MpegEncContext *s, int picture_number) if(s->scene_change_score > 0 && s->pict_type == P_TYPE){ s->pict_type= I_TYPE; memset(s->mb_type , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height); - if(s->max_b_frames==0){ - s->input_pict_type= I_TYPE; - s->input_picture_in_gop_number=0; - } -//printf("Scene change detected, encoding as I Frame %d %d\n", s->mb_var_sum, s->mc_mb_var_sum); +//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); } - + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); ff_fix_long_p_mvs(s); @@ -2643,7 +2690,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) } if (s->fixed_qscale) - s->frame_qscale = s->avctx->quality; + s->frame_qscale = s->current_picture.quality; else s->frame_qscale = ff_rate_estimate_qscale(s); @@ -2658,7 +2705,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) break; } - s->qscale= s->qscale_table[0]; + s->qscale= s->current_picture.qscale_table[0]; }else s->qscale= (int)(s->frame_qscale + 0.5); @@ -2673,6 +2720,13 @@ static void encode_picture(MpegEncContext *s, int picture_number) convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, s->q_intra_matrix16_bias, s->intra_matrix, s->intra_quant_bias, 8, 8); } + + //FIXME var duplication + s->current_picture.key_frame= s->pict_type == I_TYPE; + s->current_picture.pict_type= s->pict_type; + + if(s->current_picture.key_frame) + s->picture_in_gop_number=0; s->last_bits= get_bit_count(&s->pb); switch(s->out_format) { @@ -2705,11 +2759,13 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->b_count=0; s->skip_count=0; - /* init last dc values */ - /* note: quant matrix value (8) is implied here */ - s->last_dc[0] = 128; - s->last_dc[1] = 128; - s->last_dc[2] = 128; + for(i=0; i<3; i++){ + /* init last dc values */ + /* note: quant matrix value (8) is implied here */ + s->last_dc[i] = 128; + + s->current_picture.error[i] = 0; + } s->mb_incr = 1; s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; @@ -2974,6 +3030,30 @@ static void encode_picture(MpegEncContext *s, int picture_number) } MPV_decode_mb(s, s->block); + + if(s->flags&CODEC_FLAG_PSNR){ + int w= 16; + int h= 16; + + if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; + if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; + + s->current_picture.error[0] += sse( + s, + s->new_picture .data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + s->current_picture.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + w, h, s->linesize); + s->current_picture.error[1] += sse( + s, + s->new_picture .data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + s->current_picture.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + w>>1, h>>1, s->uvlinesize); + s->current_picture.error[2] += sse( + s, + s->new_picture .data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + s->current_picture.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + w>>1, h>>1, s->uvlinesize); + } //printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_width, get_bit_count(&s->pb)); } diff --git a/src/libffmpeg/libavcodec/mpegvideo.h b/src/libffmpeg/libavcodec/mpegvideo.h index 73092b9c1..46e19d4b1 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.h +++ b/src/libffmpeg/libavcodec/mpegvideo.h @@ -28,6 +28,8 @@ enum OutputFormat { FMT_MJPEG, }; +#define EDGE_WIDTH 16 + #define MPEG_BUF_SIZE (16 * 1024) #define QMAT_SHIFT_MMX 16 @@ -35,7 +37,8 @@ enum OutputFormat { #define MAX_FCODE 7 #define MAX_MV 2048 -#define REORDER_BUFFER_SIZE (FF_MAX_B_FRAMES+2) + +#define MAX_PICTURE_COUNT 7 #define ME_MAP_SIZE 64 #define ME_MAP_SHIFT 3 @@ -45,6 +48,11 @@ enum OutputFormat { #define MAX_RUN 64 #define MAX_LEVEL 64 +#define I_TYPE FF_I_TYPE // Intra +#define P_TYPE FF_P_TYPE // Predicted +#define B_TYPE FF_B_TYPE // Bi-dir predicted +#define S_TYPE FF_S_TYPE // S(GMC)-VOP MPEG4 + typedef struct Predictor{ double coeff; double count; @@ -90,14 +98,6 @@ typedef struct RateControlContext{ int last_non_b_pict_type; }RateControlContext; -typedef struct ReorderBuffer{ - UINT8 *picture[3]; - int pict_type; - int qscale; - int force_type; - int picture_number; - int picture_in_gop_number; -} ReorderBuffer; typedef struct ScanTable{ const UINT8 *scantable; @@ -109,6 +109,16 @@ typedef struct ScanTable{ #endif } ScanTable; +typedef struct Picture{ + FF_COMMON_PICTURE + + int mb_var_sum; /* sum of MB variance for current frame */ + int mc_mb_var_sum; /* motion compensated MB variance for current frame */ + uint16_t *mb_var; /* Table for MB variances */ + uint16_t *mc_mb_var; /* Table for motion compensated MB variances */ + uint8_t *mb_mean; /* Table for MB luminance */ +} Picture; + typedef struct ParseContext{ UINT8 *buffer; int index; @@ -145,7 +155,6 @@ typedef struct MpegEncContext { int max_qdiff; /* max qscale difference between frames */ int encoding; /* true if we are encoding (vs decoding) */ int flags; /* AVCodecContext.flags (HQ, MV4, ...) */ - int force_input_type;/* 0= no force, otherwise I_TYPE, P_TYPE, ... */ int max_b_frames; /* max number of b-frames for encoding */ int b_frame_strategy; int luma_elim_threshold; @@ -160,10 +169,7 @@ typedef struct MpegEncContext { /* sequence parameters */ int context_initialized; int input_picture_number; - int input_picture_in_gop_number; /* 0-> first pic in gop, ... */ int picture_number; - int fake_picture_number; /* picture number at the bitstream frame rate */ - int gop_picture_number; /* index of the first picture of a GOP based on fake_pic_num & mpeg1 specific */ int picture_in_gop_number; /* 0-> first pic in gop, ... */ int b_frames_since_non_b; /* used for encoding, relative to not yet reordered input */ int mb_width, mb_height; /* number of MBs horizontally & vertically */ @@ -171,20 +177,13 @@ typedef struct MpegEncContext { int mb_num; /* number of MBs of a picture */ int linesize; /* line size, in bytes, may be different from width */ int uvlinesize; /* line size, for chroma in bytes, may be different from width */ - UINT8 *new_picture[3]; /* picture to be compressed */ - UINT8 *picture_buffer[REORDER_BUFFER_SIZE][3]; /* internal buffers used for reordering of input pictures */ - int picture_buffer_index; - ReorderBuffer coded_order[REORDER_BUFFER_SIZE]; - UINT8 *last_picture[3]; /* previous picture */ - UINT8 *last_picture_base[3]; /* real start of the picture */ - UINT8 *next_picture[3]; /* previous picture (for bidir pred) */ - UINT8 *next_picture_base[3]; /* real start of the picture */ - UINT8 *aux_picture[3]; /* aux picture (for B frames only) */ - UINT8 *aux_picture_base[3]; /* real start of the picture */ - UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */ - void *last_dr_opaque; - void *next_dr_opaque; - int ip_buffer_count; /* number of buffers, currently only >2 if dr1 is used */ + Picture picture[MAX_PICTURE_COUNT]; /* main picture buffer */ + Picture *input_picture[MAX_PICTURE_COUNT]; /* next pictures on display order for encoding*/ + Picture *reordered_input_picture[MAX_PICTURE_COUNT]; /* pointer to the next pictures in codedorder for encoding*/ + Picture last_picture; /* previous picture */ + Picture next_picture; /* previous picture (for bidir pred) */ + Picture new_picture; /* source picture for encoding */ + Picture current_picture; /* buffer to store the decompressed current picture */ int num_available_buffers; /* is 0 at the start & after seeking, after the first I frame its 1 after next I/P 2 */ int last_dc[3]; /* last DC values for MPEG1 */ INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */ @@ -200,17 +199,10 @@ typedef struct MpegEncContext { UINT8 *mbintra_table; /* used to avoid setting {ac, dc, cbp}-pred stuff to zero on inter MB decoding */ UINT8 *cbp_table; /* used to store cbp, ac_pred for partitioned decoding */ UINT8 *pred_dir_table; /* used to store pred_dir for partitioned decoding */ - INT8 *qscale_table; /* used to store qscale */ - INT8 *aux_qscale_table; - INT8 *next_qscale_table; - INT8 *last_qscale_table; //FIXME move these into some picture struct (MpegEncContext.aux.qscale_table[]) UINT8 *edge_emu_buffer; - int input_qscale; /* qscale prior to reordering of frames */ - int input_pict_type; /* pict_type prior to reordering of frames */ - int force_type; /* 0= no force, otherwise I_TYPE, P_TYPE, ... */ int qscale; /* QP */ - float frame_qscale; /* qscale from the frame level rc */ + float frame_qscale; /* qscale from the frame level rc FIXME remove*/ int adaptive_quant; /* use adaptive quantization */ int dquant; /* qscale difference to prev qscale */ int pict_type; /* I_TYPE, P_TYPE, B_TYPE, ... */ @@ -272,9 +264,6 @@ typedef struct MpegEncContext { int mb_x, mb_y; int mb_incr; int mb_intra; - UINT16 *mb_var; /* Table for MB variances */ - UINT16 *mc_mb_var; /* Table for motion compensated MB variances */ - UINT8 *mb_mean; /* Table for MB luminance */ UINT8 *mb_type; /* Table for MB type */ #define MB_TYPE_INTRA 0x01 #define MB_TYPE_INTER 0x02 @@ -325,8 +314,6 @@ typedef struct MpegEncContext { /* bit rate control */ int I_frame_bits; //FIXME used in mpeg12 ... - int mb_var_sum; /* sum of MB variance for current frame */ - int mc_mb_var_sum; /* motion compensated MB variance for current frame */ INT64 wanted_bits; INT64 total_bits; int frame_bits; /* bits used for the current frame */ @@ -476,6 +463,10 @@ typedef struct MpegEncContext { /* decompression specific */ GetBitContext gb; + /* Mpeg1 specific */ + int fake_picture_number; /* picture number at the bitstream frame rate */ + int gop_picture_number; /* index of the first picture of a GOP based on fake_pic_num & mpeg1 specific */ + /* MPEG2 specific - I wish I had not to support this mess. */ int progressive_sequence; int mpeg_f_code[2][2]; @@ -498,7 +489,6 @@ typedef struct MpegEncContext { int mpeg2; int full_pel[2]; int interlaced_dct; - int last_qscale; int first_slice; /* RTP specific */ diff --git a/src/libffmpeg/libavcodec/msmpeg4.c b/src/libffmpeg/libavcodec/msmpeg4.c index f1746b4f6..76fa3c2d4 100644 --- a/src/libffmpeg/libavcodec/msmpeg4.c +++ b/src/libffmpeg/libavcodec/msmpeg4.c @@ -759,10 +759,10 @@ static inline int msmpeg4_pred_dc(MpegEncContext * s, int n, }else{ if(n<4){ wrap= s->linesize; - dest= s->current_picture[0] + (((n>>1) + 2*s->mb_y) * 8* wrap ) + ((n&1) + 2*s->mb_x) * 8; + dest= s->current_picture.data[0] + (((n>>1) + 2*s->mb_y) * 8* wrap ) + ((n&1) + 2*s->mb_x) * 8; }else{ wrap= s->uvlinesize; - dest= s->current_picture[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8; + dest= s->current_picture.data[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8; } if(s->mb_x==0) a= (1024 + (scale>>1))/scale; else a= get_dc(dest-8, wrap, scale*8); diff --git a/src/libffmpeg/libavcodec/ratecontrol.c b/src/libffmpeg/libavcodec/ratecontrol.c index 870cd21e3..caea09b24 100644 --- a/src/libffmpeg/libavcodec/ratecontrol.c +++ b/src/libffmpeg/libavcodec/ratecontrol.c @@ -41,7 +41,7 @@ void ff_write_pass1_stats(MpegEncContext *s){ sprintf(s->avctx->stats_out, "in:%d out:%d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d;\n", s->picture_number, s->input_picture_number - s->max_b_frames, s->pict_type, s->frame_qscale, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits, - s->f_code, s->b_code, s->mc_mb_var_sum, s->mb_var_sum, s->i_count); + s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count); } int ff_rate_control_init(MpegEncContext *s) @@ -475,11 +475,12 @@ static void adaptive_quantization(MpegEncContext *s, double q){ float bits_tab[s->mb_num]; const int qmin= 2; //s->avctx->mb_qmin; const int qmax= 31; //s->avctx->mb_qmax; + Picture * const pic= &s->current_picture; for(i=0; i<s->mb_num; i++){ - float temp_cplx= sqrt(s->mc_mb_var[i]); - float spat_cplx= sqrt(s->mb_var[i]); - const int lumi= s->mb_mean[i]; + float temp_cplx= sqrt(pic->mc_mb_var[i]); + float spat_cplx= sqrt(pic->mb_var[i]); + const int lumi= pic->mb_mean[i]; float bits, cplx, factor; if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune @@ -533,8 +534,8 @@ static void adaptive_quantization(MpegEncContext *s, double q){ newq*= bits_sum/cplx_sum; } - if(i && ABS(s->qscale_table[i-1] - newq)<0.75) - intq= s->qscale_table[i-1]; + if(i && ABS(pic->qscale_table[i-1] - newq)<0.75) + intq= pic->qscale_table[i-1]; else intq= (int)(newq + 0.5); @@ -542,7 +543,7 @@ static void adaptive_quantization(MpegEncContext *s, double q){ else if(intq < qmin) intq= qmin; //if(i%s->mb_width==0) printf("\n"); //printf("%2d%3d ", intq, ff_sqrt(s->mc_mb_var[i])); - s->qscale_table[i]= intq; + pic->qscale_table[i]= intq; } } @@ -562,6 +563,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s) double rate_factor; int var; const int pict_type= s->pict_type; + Picture * const pic= &s->current_picture; emms_c(); get_qminmax(&qmin, &qmax, s, pict_type); @@ -588,7 +590,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s) br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance; if(br_compensation<=0.0) br_compensation=0.001; - var= pict_type == I_TYPE ? s->mb_var_sum : s->mc_mb_var_sum; + var= pict_type == I_TYPE ? pic->mb_var_sum : pic->mc_mb_var_sum; if(s->flags&CODEC_FLAG_PASS2){ if(pict_type!=I_TYPE) @@ -599,8 +601,8 @@ float ff_rate_estimate_qscale(MpegEncContext *s) }else{ rce->pict_type= rce->new_pict_type= pict_type; - rce->mc_mb_var_sum= s->mc_mb_var_sum; - rce->mb_var_sum = s-> mb_var_sum; + rce->mc_mb_var_sum= pic->mc_mb_var_sum; + rce->mb_var_sum = pic-> mb_var_sum; rce->qscale = 2; rce->f_code = s->f_code; rce->b_code = s->b_code; @@ -663,10 +665,8 @@ float ff_rate_estimate_qscale(MpegEncContext *s) else if(q>qmax) q=qmax; // printf("%f %d %d %d\n", q, picture_number, (int)wanted_bits, (int)s->total_bits); - -//printf("%f %f %f\n", q, br_compensation, short_term_q); - -//printf("q:%d diff:%d comp:%f st_q:%f last_size:%d type:%d\n", qscale, (int)diff, br_compensation, + +//printf("diff:%d comp:%f st_q:%f last_size:%d type:%d\n", (int)diff, br_compensation, // short_term_q, s->frame_bits, pict_type); //printf("%d %d\n", s->bit_rate, (int)fps); @@ -676,8 +676,16 @@ float ff_rate_estimate_qscale(MpegEncContext *s) q= (int)(q + 0.5); rcc->last_qscale= q; - rcc->last_mc_mb_var_sum= s->mc_mb_var_sum; - rcc->last_mb_var_sum= s->mb_var_sum; + rcc->last_mc_mb_var_sum= pic->mc_mb_var_sum; + rcc->last_mb_var_sum= pic->mb_var_sum; +#if 0 +{ + static int mvsum=0, texsum=0; + mvsum += s->mv_bits; + texsum += s->i_tex_bits + s->p_tex_bits; + printf("%d %d//\n\n", mvsum, texsum); +} +#endif return q; } diff --git a/src/libffmpeg/libavcodec/rv10.c b/src/libffmpeg/libavcodec/rv10.c index 02da93a6c..8039cdb1e 100644 --- a/src/libffmpeg/libavcodec/rv10.c +++ b/src/libffmpeg/libavcodec/rv10.c @@ -472,7 +472,7 @@ static int rv10_decode_frame(AVCodecContext *avctx, { MpegEncContext *s = avctx->priv_data; int i; - AVPicture *pict = data; + AVVideoFrame *pict = data; #ifdef DEBUG printf("*****frame %d size=%d\n", avctx->frame_number, buf_size); @@ -505,15 +505,9 @@ static int rv10_decode_frame(AVCodecContext *avctx, if(s->mb_y>=s->mb_height){ MPV_frame_end(s); - pict->data[0] = s->current_picture[0]; - pict->data[1] = s->current_picture[1]; - pict->data[2] = s->current_picture[2]; - pict->linesize[0] = s->linesize; - pict->linesize[1] = s->uvlinesize; - pict->linesize[2] = s->uvlinesize; + *pict= *(AVVideoFrame*)&s->current_picture; - avctx->quality = s->qscale; - *data_size = sizeof(AVPicture); + *data_size = sizeof(AVVideoFrame); }else{ *data_size = 0; } diff --git a/src/libffmpeg/libavcodec/svq1.c b/src/libffmpeg/libavcodec/svq1.c index f92a61031..86ebd7382 100644 --- a/src/libffmpeg/libavcodec/svq1.c +++ b/src/libffmpeg/libavcodec/svq1.c @@ -1063,7 +1063,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, MpegEncContext *s=avctx->priv_data; uint8_t *current, *previous; int result, i, x, y, width, height; - AVPicture *pict = data; + AVVideoFrame *pict = data; /* initialize bit buffer */ init_get_bits(&s->gb,buf,buf_size); @@ -1084,9 +1084,6 @@ static int svq1_decode_frame(AVCodecContext *avctx, } result = svq1_decode_frame_header (&s->gb, s); - - if(MPV_frame_start(s, avctx) < 0) - return -1; if (result != 0) { @@ -1098,6 +1095,9 @@ static int svq1_decode_frame(AVCodecContext *avctx, if(avctx->hurry_up && s->pict_type==B_TYPE) return buf_size; + if(MPV_frame_start(s, avctx) < 0) + return -1; + /* decode y, u and v components */ for (i=0; i < 3; i++) { int linesize; @@ -1112,12 +1112,12 @@ static int svq1_decode_frame(AVCodecContext *avctx, linesize= s->uvlinesize; } - current = s->current_picture[i]; + current = s->current_picture.data[i]; if(s->pict_type==B_TYPE){ - previous = s->next_picture[i]; + previous = s->next_picture.data[i]; }else{ - previous = s->last_picture[i]; + previous = s->last_picture.data[i]; } if (s->pict_type == I_TYPE) { @@ -1159,12 +1159,14 @@ static int svq1_decode_frame(AVCodecContext *avctx, current += 16*linesize; } } - - pict->data[i] = s->current_picture[i]; - pict->linesize[i] = linesize; } + + *pict = *(AVVideoFrame*)&s->current_picture; - *data_size=sizeof(AVPicture); + + MPV_frame_end(s); + + *data_size=sizeof(AVVideoFrame); return buf_size; } @@ -1176,7 +1178,6 @@ static int svq1_decode_init(AVCodecContext *avctx) s->width = (avctx->width+3)&~3; s->height = (avctx->height+3)&~3; s->codec_id= avctx->codec->id; - avctx->mbskip_table= s->mbskip_table; avctx->pix_fmt = PIX_FMT_YUV410P; avctx->has_b_frames= s->has_b_frames=1; // not true, but DP frames and these behave like unidirectional b frames s->flags= avctx->flags; diff --git a/src/libffmpeg/libavcodec/utils.c b/src/libffmpeg/libavcodec/utils.c index 6797508e1..bc7da83ef 100644 --- a/src/libffmpeg/libavcodec/utils.c +++ b/src/libffmpeg/libavcodec/utils.c @@ -23,6 +23,9 @@ void *av_mallocz(unsigned int size) { void *ptr; + + if(size == 0) fprintf(stderr, "Warning, allocating 0 bytes\n"); + ptr = av_malloc(size); if (!ptr) return NULL; @@ -30,6 +33,43 @@ void *av_mallocz(unsigned int size) return ptr; } +/* allocation of static arrays - do not use for normal allocation */ +static unsigned int last_static = 0; +static char*** array_static = NULL; +static const unsigned int grow_static = 64; // ^2 +void *__av_mallocz_static(void** location, unsigned int size) +{ + int l = (last_static + grow_static) & ~(grow_static - 1); + void *ptr = av_mallocz(size); + if (!ptr) + return NULL; + + if (location) + { + if (l > last_static) + array_static = realloc(array_static, l); + array_static[last_static++] = (char**) location; + *location = ptr; + } + return ptr; +} +/* free all static arrays and reset pointers to 0 */ +void av_free_static() +{ + if (array_static) + { + unsigned i; + for (i = 0; i < last_static; i++) + { + free(*array_static[i]); + *array_static[i] = NULL; + } + free(array_static); + array_static = 0; + } + last_static = 0; +} + /* cannot call it directly because of 'void **' casting is not automatic */ void __av_freep(void **ptr) { @@ -49,6 +89,123 @@ void register_avcodec(AVCodec *format) format->next = NULL; } +void avcodec_get_chroma_sub_sample(int fmt, int *h_shift, int *v_shift){ + switch(fmt){ + case PIX_FMT_YUV410P: + *h_shift=2; + *v_shift=2; + break; + case PIX_FMT_YUV420P: + *h_shift=1; + *v_shift=1; + break; + case PIX_FMT_YUV411P: + *h_shift=2; + *v_shift=0; + break; + case PIX_FMT_YUV422P: + case PIX_FMT_YUV422: + *h_shift=1; + *v_shift=0; + break; + default: //RGB/... + *h_shift=0; + *v_shift=0; + break; + } +} + +typedef struct DefaultPicOpaque{ + int last_pic_num; + uint8_t *data[4]; +}DefaultPicOpaque; + +int avcodec_default_get_buffer(AVCodecContext *s, AVVideoFrame *pic){ + int i; + const int width = s->width; + const int height= s->height; + DefaultPicOpaque *opaque; + + if(pic->opaque){ + opaque= (DefaultPicOpaque *)pic->opaque; + for(i=0; i<3; i++) + pic->data[i]= opaque->data[i]; + +// printf("get_buffer %X coded_pic_num:%d last:%d\n", pic->opaque, pic->coded_picture_number, opaque->last_pic_num); + pic->age= pic->coded_picture_number - opaque->last_pic_num; + opaque->last_pic_num= pic->coded_picture_number; +//printf("age: %d %d %d\n", pic->age, c->picture_number, pic->coded_picture_number); + }else{ + int align, h_chroma_shift, v_chroma_shift; + int w, h, pixel_size; + + avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); + + switch(s->pix_fmt){ + case PIX_FMT_YUV422: + pixel_size=2; + break; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + pixel_size=3; + break; + case PIX_FMT_BGRA32: + case PIX_FMT_RGBA32: + pixel_size=4; + break; + default: + pixel_size=1; + } + + if(s->codec_id==CODEC_ID_SVQ1) align=63; + else align=15; + + w= (width +align)&~align; + h= (height+align)&~align; + + if(!(s->flags&CODEC_FLAG_EMU_EDGE)){ + w+= EDGE_WIDTH*2; + h+= EDGE_WIDTH*2; + } + + opaque= av_mallocz(sizeof(DefaultPicOpaque)); + if(opaque==NULL) return -1; + + pic->opaque= opaque; + opaque->last_pic_num= -256*256*256*64; + + for(i=0; i<3; i++){ + int h_shift= i==0 ? 0 : h_chroma_shift; + int v_shift= i==0 ? 0 : v_chroma_shift; + + pic->linesize[i]= pixel_size*w>>h_shift; + + pic->base[i]= av_mallocz((pic->linesize[i]*h>>v_shift)+16); //FIXME 16 + if(pic->base[i]==NULL) return -1; + + memset(pic->base[i], 128, pic->linesize[i]*h>>v_shift); + + if(s->flags&CODEC_FLAG_EMU_EDGE) + pic->data[i] = pic->base[i]; + else + pic->data[i] = pic->base[i] + (pic->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift); + + opaque->data[i]= pic->data[i]; + } + pic->age= 256*256*256*64; + } + + return 0; +} + +void avcodec_default_release_buffer(AVCodecContext *s, AVVideoFrame *pic){ + int i; + + for(i=0; i<3; i++) + pic->data[i]=NULL; +//printf("R%X\n", pic->opaque); +} + void avcodec_get_context_defaults(AVCodecContext *s){ s->bit_rate= 800*1000; s->bit_rate_tolerance= s->bit_rate*10; @@ -67,6 +224,8 @@ void avcodec_get_context_defaults(AVCodecContext *s){ s->frame_rate = 25 * FRAME_RATE_BASE; s->gop_size= 50; s->me_method= ME_EPZS; + s->get_buffer= avcodec_default_get_buffer; + s->release_buffer= avcodec_default_release_buffer; } /** @@ -83,6 +242,16 @@ AVCodecContext *avcodec_alloc_context(void){ return avctx; } +/** + * allocates a AVPicture and set it to defaults. + * this can be deallocated by simply calling free() + */ +AVVideoFrame *avcodec_alloc_picture(void){ + AVVideoFrame *pic= av_mallocz(sizeof(AVVideoFrame)); + + return pic; +} + int avcodec_open(AVCodecContext *avctx, AVCodec *codec) { int ret; @@ -115,7 +284,7 @@ int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size, } int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, - const AVPicture *pict) + const AVVideoFrame *pict) { int ret; @@ -130,17 +299,17 @@ int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size, /* decode a frame. return -1 if error, otherwise return the number of bytes used. If no frame could be decompressed, *got_picture_ptr is zero. Otherwise, it is non zero */ -int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture, +int avcodec_decode_video(AVCodecContext *avctx, AVVideoFrame *picture, int *got_picture_ptr, UINT8 *buf, int buf_size) { int ret; - + ret = avctx->codec->decode(avctx, picture, got_picture_ptr, buf, buf_size); emms_c(); //needed to avoid a emms_c() call before every return; - + if (*got_picture_ptr) avctx->frame_number++; return ret; diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c index a3e6ced91..b6004b07e 100644 --- a/src/libffmpeg/xine_decoder.c +++ b/src/libffmpeg/xine_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_decoder.c,v 1.74 2002/12/04 05:51:46 tmmm Exp $ + * $Id: xine_decoder.c,v 1.75 2002/12/06 01:55:32 miguelfreitas Exp $ * * xine decoder plugin using ffmpeg * @@ -68,7 +68,7 @@ typedef struct ff_decoder_s { int size; int skipframes; - AVPicture av_picture; + AVVideoFrame *av_picture; AVCodecContext *context; /* mpeg sequence header parsing, stolen from libmpeg2 */ @@ -114,18 +114,29 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT; #define AUDIOBUFSIZE VIDEOBUFSIZE -static void init_video_codec (ff_video_decoder_t *this, AVCodec *codec) { +static void init_video_codec (ff_video_decoder_t *this, AVCodec *codec, xine_bmiheader *bih) { +#if 0 /* now we have strides, i don't think this is needed anymore */ /* force (width % 8 == 0), otherwise there will be - * display problems with Xv. - */ + * display problems with Xv. + */ this->bih.biWidth = (this->bih.biWidth + 7) & (~7); - +#endif + + this->av_picture = avcodec_alloc_picture(); this->context = avcodec_alloc_context(); this->context->width = this->bih.biWidth; this->context->height = this->bih.biHeight; this->context->fourcc = this->stream->stream_info[XINE_STREAM_INFO_VIDEO_FOURCC]; + if( bih && bih->biSize > sizeof(xine_bmiheader) ) { + this->context->extradata_size = bih->biSize - sizeof(xine_bmiheader); + this->context->extradata = malloc(this->context->extradata_size); + memcpy( this->context->extradata, + (uint8_t *)bih + sizeof(xine_bmiheader), + this->context->extradata_size ); + } + if (avcodec_open (this->context, codec) < 0) { printf ("ffmpeg: couldn't open decoder\n"); free(this->context); @@ -273,7 +284,7 @@ static void find_sequence_header (ff_video_decoder_t *this, } this->is_continous = 1; - init_video_codec (this, codec); + init_video_codec (this, codec, NULL); } } } @@ -302,7 +313,6 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_HEADER) { AVCodec *codec = NULL; - xine_bmiheader *bih; int codec_type; #ifdef LOG @@ -311,8 +321,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { /* init package containing bih */ - bih = (xine_bmiheader *)buf->content; - memcpy ( &this->bih, bih, sizeof (xine_bmiheader)); + memcpy ( &this->bih, buf->content, sizeof (xine_bmiheader)); this->video_step = buf->decoder_info[1]; this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->bih.biWidth; @@ -399,16 +408,8 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { return; } - init_video_codec (this, codec); + init_video_codec (this, codec, (xine_bmiheader *)buf->content ); - if( bih->biSize > sizeof(xine_bmiheader) ) { - this->context->extradata_size = bih->biSize - sizeof(xine_bmiheader); - this->context->extradata = malloc(this->context->extradata_size); - memcpy( this->context->extradata, - (uint8_t *)bih + sizeof(xine_bmiheader), - this->context->extradata_size ); - } - } else if (this->decoder_ok) { if( this->size + buf->size > this->bufsize ) { @@ -439,7 +440,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { offset = 0; while (this->size>0) { - len = avcodec_decode_video (this->context, &this->av_picture, + len = avcodec_decode_video (this->context, this->av_picture, &got_picture, &this->buf[offset], this->size); if (len<0) { @@ -469,6 +470,10 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { emms_c (); #endif + /* FIXME: ffmpeg has changed, now we must use this->context->aspect_ratio + * which is a float value. for now, set ASPECT_DONT_TOUCH. + */ +#if 0 switch(this->context->aspect_ratio_info) { case FF_ASPECT_SQUARE: ratio = XINE_VO_ASPECT_SQUARE; @@ -484,6 +489,9 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { default: ratio = XINE_VO_ASPECT_DONT_TOUCH; } +#else + ratio = XINE_VO_ASPECT_DONT_TOUCH; +#endif img = this->stream->video_out->get_frame (this->stream->video_out, /* this->av_picture.linesize[0], */ @@ -506,26 +514,26 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { dy = img->base[0]; du = img->base[1]; dv = img->base[2]; - sy = this->av_picture.data[0]; - su = this->av_picture.data[1]; - sv = this->av_picture.data[2]; + sy = this->av_picture->data[0]; + su = this->av_picture->data[1]; + sv = this->av_picture->data[2]; if (this->context->pix_fmt == PIX_FMT_YUV410P) { yuv9_to_yv12( /* Y */ - this->av_picture.data[0], - this->av_picture.linesize[0], + this->av_picture->data[0], + this->av_picture->linesize[0], img->base[0], img->pitches[0], /* U */ - this->av_picture.data[1], - this->av_picture.linesize[1], + this->av_picture->data[1], + this->av_picture->linesize[1], img->base[1], img->pitches[1], /* V */ - this->av_picture.data[2], - this->av_picture.linesize[2], + this->av_picture->data[2], + this->av_picture->linesize[2], img->base[2], img->pitches[2], /* width x height */ @@ -539,7 +547,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { dy += img->pitches[0]; - sy += this->av_picture.linesize[0]; + sy += this->av_picture->linesize[0]; } if (this->context->pix_fmt != PIX_FMT_YUV410P) @@ -577,27 +585,11 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { dv += img->pitches[2]; if (this->context->pix_fmt != PIX_FMT_YUV420P) { - su += 2*this->av_picture.linesize[1]; - sv += 2*this->av_picture.linesize[2]; + su += 2*this->av_picture->linesize[1]; + sv += 2*this->av_picture->linesize[2]; } else { - su += this->av_picture.linesize[1]; - sv += this->av_picture.linesize[2]; - } - } - - if (img->copy) { - int height = img->height; - uint8_t *src[3]; - - src[0] = img->base[0]; - src[1] = img->base[1]; - src[2] = img->base[2]; - - while ((height -= 16) >= 0) { - img->copy(img, src); - src[0] += 16 * img->pitches[0]; - src[1] += 8 * img->pitches[1]; - src[2] += 8 * img->pitches[2]; + su += this->av_picture->linesize[1]; + sv += this->av_picture->linesize[2]; } } } @@ -686,6 +678,9 @@ static void ff_dispose (video_decoder_t *this_gen) { if( this->context ) free( this->context ); + + if( this->av_picture ) + free( this->av_picture ); if (this->buf) free(this->buf); @@ -1016,7 +1011,7 @@ static uint32_t supported_video_types[] = { BUF_VIDEO_MJPEG, BUF_VIDEO_H263, BUF_VIDEO_RV10, - BUF_VIDEO_SORENSON_V1, + /* BUF_VIDEO_SORENSON_V1, -- ffmpeg svq1 decoder is segfaulting */ BUF_VIDEO_JPEG, BUF_VIDEO_MPEG, BUF_VIDEO_DV, |