diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2002-12-04 10:04:03 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2002-12-04 10:04:03 +0000 |
commit | 1e491e29c27cf6a6925666e4f4eac41b65e263d7 (patch) | |
tree | 99879470b8deeb55e7d88c62729b62ac27d249ee | |
parent | 855ea723b0ea450137e54674179751c14e8fc6b5 (diff) | |
download | ffmpeg-1e491e29c27cf6a6925666e4f4eac41b65e263d7.tar.gz |
cleanup
adding AVVideoFrame
moving quality, pict_type, key_frame, qscale_table, ... to AVVideoFrame
removing obsolete variables in AVCodecContext
skiping of MBs in b frames
correctly initalizing AVCodecContext
picture buffer cleanup
Originally committed as revision 1302 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | ffmpeg.c | 35 | ||||
-rw-r--r-- | ffserver.c | 4 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 264 | ||||
-rw-r--r-- | libavcodec/dv.c | 73 | ||||
-rw-r--r-- | libavcodec/error_resilience.c | 30 | ||||
-rw-r--r-- | libavcodec/h263.c | 87 | ||||
-rw-r--r-- | libavcodec/h263dec.c | 32 | ||||
-rw-r--r-- | libavcodec/huffyuv.c | 253 | ||||
-rw-r--r-- | libavcodec/mjpeg.c | 12 | ||||
-rw-r--r-- | libavcodec/motion_est.c | 49 | ||||
-rw-r--r-- | libavcodec/mpeg12.c | 53 | ||||
-rw-r--r-- | libavcodec/mpegvideo.c | 652 | ||||
-rw-r--r-- | libavcodec/mpegvideo.h | 67 | ||||
-rw-r--r-- | libavcodec/msmpeg4.c | 4 | ||||
-rw-r--r-- | libavcodec/ratecontrol.c | 40 | ||||
-rw-r--r-- | libavcodec/rv10.c | 12 | ||||
-rw-r--r-- | libavcodec/svq1.c | 25 | ||||
-rw-r--r-- | libavcodec/utils.c | 137 | ||||
-rw-r--r-- | libavformat/asf.c | 3 | ||||
-rw-r--r-- | libavformat/au.c | 2 | ||||
-rw-r--r-- | libavformat/avformat.h | 3 | ||||
-rw-r--r-- | libavformat/avidec.c | 2 | ||||
-rw-r--r-- | libavformat/avienc.c | 2 | ||||
-rw-r--r-- | libavformat/ffm.c | 7 | ||||
-rw-r--r-- | libavformat/jpeg.c | 2 | ||||
-rw-r--r-- | libavformat/rm.c | 3 | ||||
-rw-r--r-- | libavformat/swf.c | 2 | ||||
-rw-r--r-- | libavformat/utils.c | 4 |
28 files changed, 987 insertions, 872 deletions
@@ -285,6 +285,7 @@ int read_ffserver_streams(AVFormatContext *s, const char *filename) s->nb_streams = ic->nb_streams; for(i=0;i<ic->nb_streams;i++) { AVStream *st; + st = av_mallocz(sizeof(AVFormatContext)); memcpy(st, ic->streams[i], sizeof(AVStream)); s->streams[i] = st; @@ -605,15 +606,21 @@ static void do_video_out(AVFormatContext *s, /* XXX: pb because no interleaving */ for(i=0;i<nb_frames;i++) { if (enc->codec_id != CODEC_ID_RAWVIDEO) { + AVVideoFrame big_picture; + + memset(&big_picture, 0, sizeof(AVVideoFrame)); + *(AVPicture*)&big_picture= *picture; + /* handles sameq here. This is not correct because it may not be a global option */ if (same_quality) { - enc->quality = dec->quality; - } + big_picture.quality = ist->st->quality; + }else + big_picture.quality = ost->st->quality; ret = avcodec_encode_video(enc, video_buffer, VIDEO_BUFFER_SIZE, - picture); + &big_picture); //enc->frame_number = enc->real_pict_num; av_write_frame(s, ost->index, video_buffer, ret); *frame_size = ret; @@ -674,7 +681,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost, total_size += frame_size; if (enc->codec_type == CODEC_TYPE_VIDEO) { frame_number = ost->frame_number; - fprintf(fvstats, "frame= %5d q= %2d ", frame_number, enc->quality); + fprintf(fvstats, "frame= %5d q= %2.1f ", frame_number, enc->coded_picture->quality); if (do_psnr) fprintf(fvstats, "PSNR= %6.2f ", enc->psnr_y); @@ -688,7 +695,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost, avg_bitrate = (double)(total_size * 8) / ti1 / 1000.0; fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", (double)total_size / 1024, ti1, bitrate, avg_bitrate); - fprintf(fvstats,"type= %s\n", enc->key_frame == 1 ? "I" : "P"); + fprintf(fvstats,"type= %s\n", enc->coded_picture->key_frame == 1 ? "I" : "P"); } } @@ -731,13 +738,13 @@ void print_report(AVFormatContext **output_files, os = output_files[ost->file_index]; enc = &ost->st->codec; if (vid && enc->codec_type == CODEC_TYPE_VIDEO) { - sprintf(buf + strlen(buf), "q=%2d ", - enc->quality); + sprintf(buf + strlen(buf), "q=%2.1f ", + enc->coded_picture->quality); } if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) { frame_number = ost->frame_number; - sprintf(buf + strlen(buf), "frame=%5d q=%2d ", - frame_number, enc->quality); + sprintf(buf + strlen(buf), "frame=%5d q=%2.1f ", + frame_number, enc->coded_picture ? enc->coded_picture->quality : 0); if (do_psnr) sprintf(buf + strlen(buf), "PSNR=%6.2f ", enc->psnr_y); vid = 1; @@ -1236,9 +1243,13 @@ static int av_encode(AVFormatContext **output_files, ist->st->codec.height); ret = len; } else { + AVVideoFrame big_picture; + data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2; ret = avcodec_decode_video(&ist->st->codec, - &picture, &got_picture, ptr, len); + &big_picture, &got_picture, ptr, len); + picture= *(AVPicture*)&big_picture; + ist->st->quality= big_picture.quality; if (ret < 0) { fail_decode: fprintf(stderr, "Error while decoding stream #%d.%d\n", @@ -2046,6 +2057,7 @@ void opt_output_file(const char *filename) fprintf(stderr, "Could not alloc stream\n"); exit(1); } + avcodec_get_context_defaults(&st->codec); video_enc = &st->codec; if (video_stream_copy) { @@ -2074,7 +2086,7 @@ void opt_output_file(const char *filename) video_enc->gop_size = 0; if (video_qscale || same_quality) { video_enc->flags |= CODEC_FLAG_QSCALE; - video_enc->quality = video_qscale; + st->quality = video_qscale; } if (use_hq) { @@ -2181,6 +2193,7 @@ void opt_output_file(const char *filename) fprintf(stderr, "Could not alloc stream\n"); exit(1); } + avcodec_get_context_defaults(&st->codec); audio_enc = &st->codec; audio_enc->codec_type = CODEC_TYPE_AUDIO; diff --git a/ffserver.c b/ffserver.c index 1d0939d89f..daa5c9de57 100644 --- a/ffserver.c +++ b/ffserver.c @@ -1955,7 +1955,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) /* we use the codec indication because it is more accurate than the demux flags */ pkt->flags = 0; - if (st->codec.key_frame) + if (st->codec.coded_picture->key_frame) pkt->flags |= PKT_FLAG_KEY; return 0; } @@ -3942,7 +3942,7 @@ int parse_ffconfig(const char *filename) } else if (!strcasecmp(cmd, "AudioQuality")) { get_arg(arg, sizeof(arg), &p); if (stream) { - audio_enc.quality = atof(arg) * 1000; +// audio_enc.quality = atof(arg) * 1000; } } else if (!strcasecmp(cmd, "VideoBitRateRange")) { if (stream) { diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7bfdc99a27..e2972696a8 100644 --- a/libavcodec/avcodec.h +++ b/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 4641 +#define LIBAVCODEC_BUILD_STR "4641" enum CodecID { CODEC_ID_NONE, @@ -140,7 +140,6 @@ 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_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 +158,111 @@ 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;\ + +/* 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 + +typedef struct AVVideoFrame { + FF_COMMON_PICTURE +} AVVideoFrame; + typedef struct AVCodecContext { /** * the average bitrate @@ -191,7 +295,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 +316,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 +374,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) */ @@ -485,46 +556,21 @@ typedef struct AVCodecContext { int error_resilience; /** - * obsolete, just here to keep ABI compatible (should be removed perhaps, dunno) - */ - int *quant_store; - - /** - * QP store stride - * encoding: unused - * decoding: set by lavc - */ - int qstride; - - /** - * buffer, where the next picture should be decoded into + * 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 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 + * decoding: set by lavc, user can override */ - uint8_t *dr_buffer[3]; + int (*get_buffer)(struct AVCodecContext *c, AVVideoFrame *pic); /** - * stride of the luminance part of the dr buffer + * 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 + * 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,13 @@ 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; } AVCodecContext; typedef struct AVCodec { @@ -928,6 +935,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 +965,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 +985,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); diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 1492d6854b..05128aee45 100644 --- a/libavcodec/dv.c +++ b/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/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 519674496e..584bac865e 100644 --- a/libavcodec/error_resilience.c +++ b/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]; @@ -556,8 +556,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 +802,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 +852,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 +863,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/libavcodec/h263.c b/libavcodec/h263.c index 0083ca280a..e6578a0c58 100644 --- a/libavcodec/h263.c +++ b/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; } @@ -4441,7 +4450,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"); diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 0c88cd758e..8e1040a5e6 100644 --- a/libavcodec/h263dec.c +++ b/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; @@ -523,8 +523,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 +581,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 +647,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 +672,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 +686,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/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index 48e9ca6ab9..0af05d1500 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -30,7 +30,7 @@ #endif #define VLC_BITS 11 - + typedef enum Predictor{ LEFT= 0, PLANE, @@ -52,13 +52,12 @@ typedef struct HYuvContext{ int flags; int picture_number; int last_slice_end; - int linesize[3]; uint8_t __align8 temp[3][2500]; uint64_t stats[3][256]; uint8_t len[3][256]; uint32_t bits[3][256]; VLC vlc[3]; - uint8_t __align8 *picture[3]; + AVVideoFrame picture; uint8_t __align8 bitstream_buffer[1024*1024*3]; //FIXME dynamic alloc or some other solution DSPContext dsp; }HYuvContext; @@ -324,7 +323,7 @@ static int read_old_huffman_tables(HYuvContext *s){ static int decode_init(AVCodecContext *avctx) { HYuvContext *s = avctx->priv_data; - int width, height, y_size, c_size, stride; + int width, height; s->avctx= avctx; s->flags= avctx->flags; @@ -333,6 +332,8 @@ static int decode_init(AVCodecContext *avctx) width= s->width= avctx->width; height= s->height= avctx->height; + avctx->coded_picture= &s->picture; + s->bgr32=1; assert(width && height); //if(avctx->extradata) @@ -388,52 +389,27 @@ s->bgr32=1; s->interlaced= height > 288; - c_size= 0; switch(s->bitstream_bpp){ case 12: avctx->pix_fmt = PIX_FMT_YUV420P; - stride= (width+15)&~15; - c_size= height*stride/4; break; case 16: if(s->yuy2){ avctx->pix_fmt = PIX_FMT_YUV422; - stride= (width*2+15)&~15; }else{ avctx->pix_fmt = PIX_FMT_YUV422P; - stride= (width+15)&~15; - c_size= height*stride/2; } break; case 24: case 32: if(s->bgr32){ avctx->pix_fmt = PIX_FMT_BGRA32; - stride= (width*4+15)&~15; }else{ avctx->pix_fmt = PIX_FMT_BGR24; - stride= (width*3+15)&~15; } break; default: assert(0); - stride=0; //gcc fix - } - - y_size= height*stride; - - if(!(avctx->flags&CODEC_FLAG_DR1)){ - s->linesize[0]= stride; - s->picture[0]= av_mallocz(y_size); - - if(c_size){ - s->picture[1]= av_mallocz(c_size); - s->picture[2]= av_mallocz(c_size); - s->linesize[1]= s->linesize[2]= stride/2; - - memset(s->picture[1], 128, c_size); - memset(s->picture[2], 128, c_size); - } } // printf("pred:%d bpp:%d hbpp:%d il:%d\n", s->predictor, s->bitstream_bpp, avctx->bits_per_sample, s->interlaced); @@ -484,6 +460,10 @@ static int encode_init(AVCodecContext *avctx) avctx->stats_out= av_mallocz(1024*10); s->version=2; + avctx->coded_picture= &s->picture; + s->picture.pict_type= I_TYPE; + s->picture.key_frame= 1; + switch(avctx->pix_fmt){ case PIX_FMT_YUV420P: if(avctx->strict_std_compliance>=0){ @@ -674,12 +654,12 @@ static void draw_slice(HYuvContext *s, int y){ cy= y; } - src_ptr[0] = s->picture[0] + s->linesize[0]*y; - src_ptr[1] = s->picture[1] + s->linesize[1]*cy; - src_ptr[2] = s->picture[2] + s->linesize[2]*cy; + src_ptr[0] = s->picture.data[0] + s->picture.linesize[0]*y; + src_ptr[1] = s->picture.data[1] + s->picture.linesize[1]*cy; + src_ptr[2] = s->picture.data[2] + s->picture.linesize[2]*cy; emms_c(); - s->avctx->draw_horiz_band(s->avctx, src_ptr, s->linesize[0], y, s->width, h); + s->avctx->draw_horiz_band(s->avctx, src_ptr, s->picture.linesize[0], y, s->width, h); s->last_slice_end= y + h; } @@ -690,9 +670,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 const int width2= s->width>>1; const int height= s->height; int fake_ystride, fake_ustride, fake_vstride; - int i; + AVVideoFrame * const p= &s->picture; - AVPicture *picture = data; + AVVideoFrame *picture = data; *data_size = 0; @@ -704,22 +684,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 init_get_bits(&s->gb, s->bitstream_buffer, buf_size); - if(avctx->flags&CODEC_FLAG_DR1){ - if(avctx->get_buffer_callback(avctx, s->width, s->height, I_TYPE) < 0){ - fprintf(stderr, "get_buffer() failed\n"); - return -1; - } - - s->linesize[0]= avctx->dr_stride; - s->linesize[1]= - s->linesize[2]= avctx->dr_uvstride; - - for(i=0; i<3;i++) - s->picture[i]= avctx->dr_buffer[i]; + p->reference= 0; + if(avctx->get_buffer(avctx, p) < 0){ + fprintf(stderr, "get_buffer() failed\n"); + return -1; } - fake_ystride= s->interlaced ? s->linesize[0]*2 : s->linesize[0]; - fake_ustride= s->interlaced ? s->linesize[1]*2 : s->linesize[1]; - fake_vstride= s->interlaced ? s->linesize[2]*2 : s->linesize[2]; + + fake_ystride= s->interlaced ? p->linesize[0]*2 : p->linesize[0]; + fake_ustride= s->interlaced ? p->linesize[1]*2 : p->linesize[1]; + fake_vstride= s->interlaced ? p->linesize[2]*2 : p->linesize[2]; s->last_slice_end= 0; @@ -729,28 +702,28 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 int lefttopy, lefttopu, lefttopv; if(s->yuy2){ - s->picture[0][3]= get_bits(&s->gb, 8); - s->picture[0][2]= get_bits(&s->gb, 8); - s->picture[0][1]= get_bits(&s->gb, 8); - s->picture[0][0]= get_bits(&s->gb, 8); + p->data[0][3]= get_bits(&s->gb, 8); + p->data[0][2]= get_bits(&s->gb, 8); + p->data[0][1]= get_bits(&s->gb, 8); + p->data[0][0]= get_bits(&s->gb, 8); fprintf(stderr, "YUY2 output isnt implemenetd yet\n"); return -1; }else{ - leftv= s->picture[2][0]= get_bits(&s->gb, 8); - lefty= s->picture[0][1]= get_bits(&s->gb, 8); - leftu= s->picture[1][0]= get_bits(&s->gb, 8); - s->picture[0][0]= get_bits(&s->gb, 8); + leftv= p->data[2][0]= get_bits(&s->gb, 8); + lefty= p->data[0][1]= get_bits(&s->gb, 8); + leftu= p->data[1][0]= get_bits(&s->gb, 8); + p->data[0][0]= get_bits(&s->gb, 8); switch(s->predictor){ case LEFT: case PLANE: decode_422_bitstream(s, width-2); - lefty= add_left_prediction(s->picture[0] + 2, s->temp[0], width-2, lefty); + lefty= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty); if(!(s->flags&CODEC_FLAG_GRAY)){ - leftu= add_left_prediction(s->picture[1] + 1, s->temp[1], width2-1, leftu); - leftv= add_left_prediction(s->picture[2] + 1, s->temp[2], width2-1, leftv); + leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu); + leftv= add_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv); } for(cy=y=1; y<s->height; y++,cy++){ @@ -759,7 +732,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if(s->bitstream_bpp==12){ decode_gray_bitstream(s, width); - ydst= s->picture[0] + s->linesize[0]*y; + ydst= p->data[0] + p->linesize[0]*y; lefty= add_left_prediction(ydst, s->temp[0], width, lefty); if(s->predictor == PLANE){ @@ -772,12 +745,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 draw_slice(s, y); - ydst= s->picture[0] + s->linesize[0]*y; - udst= s->picture[1] + s->linesize[1]*cy; - vdst= s->picture[2] + s->linesize[2]*cy; + ydst= p->data[0] + p->linesize[0]*y; + udst= p->data[1] + p->linesize[1]*cy; + vdst= p->data[2] + p->linesize[2]*cy; decode_422_bitstream(s, width); - lefty= add_left_prediction(ydst, s->temp[0], width, lefty); if(!(s->flags&CODEC_FLAG_GRAY)){ leftu= add_left_prediction(udst, s->temp[1], width2, leftu); @@ -799,10 +771,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 case MEDIAN: /* first line except first 2 pixels is left predicted */ decode_422_bitstream(s, width-2); - lefty= add_left_prediction(s->picture[0] + 2, s->temp[0], width-2, lefty); + lefty= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty); if(!(s->flags&CODEC_FLAG_GRAY)){ - leftu= add_left_prediction(s->picture[1] + 1, s->temp[1], width2-1, leftu); - leftv= add_left_prediction(s->picture[2] + 1, s->temp[2], width2-1, leftv); + leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu); + leftv= add_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv); } cy=y=1; @@ -810,31 +782,31 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 /* second line is left predicted for interlaced case */ if(s->interlaced){ decode_422_bitstream(s, width); - lefty= add_left_prediction(s->picture[0] + s->linesize[0], s->temp[0], width, lefty); + lefty= add_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty); if(!(s->flags&CODEC_FLAG_GRAY)){ - leftu= add_left_prediction(s->picture[1] + s->linesize[2], s->temp[1], width2, leftu); - leftv= add_left_prediction(s->picture[2] + s->linesize[1], s->temp[2], width2, leftv); + leftu= add_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu); + leftv= add_left_prediction(p->data[2] + p->linesize[1], s->temp[2], width2, leftv); } y++; cy++; } /* next 4 pixels are left predicted too */ decode_422_bitstream(s, 4); - lefty= add_left_prediction(s->picture[0] + fake_ystride, s->temp[0], 4, lefty); + lefty= add_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty); if(!(s->flags&CODEC_FLAG_GRAY)){ - leftu= add_left_prediction(s->picture[1] + fake_ustride, s->temp[1], 2, leftu); - leftv= add_left_prediction(s->picture[2] + fake_vstride, s->temp[2], 2, leftv); + leftu= add_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu); + leftv= add_left_prediction(p->data[2] + fake_vstride, s->temp[2], 2, leftv); } /* next line except the first 4 pixels is median predicted */ - lefttopy= s->picture[0][3]; + lefttopy= p->data[0][3]; decode_422_bitstream(s, width-4); - add_median_prediction(s->picture[0] + fake_ystride+4, s->picture[0]+4, s->temp[0], width-4, &lefty, &lefttopy); + add_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy); if(!(s->flags&CODEC_FLAG_GRAY)){ - lefttopu= s->picture[1][1]; - lefttopv= s->picture[2][1]; - add_median_prediction(s->picture[1] + fake_ustride+2, s->picture[1]+2, s->temp[1], width2-2, &leftu, &lefttopu); - add_median_prediction(s->picture[2] + fake_vstride+2, s->picture[2]+2, s->temp[2], width2-2, &leftv, &lefttopv); + lefttopu= p->data[1][1]; + lefttopv= p->data[2][1]; + add_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu); + add_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv); } y++; cy++; @@ -844,7 +816,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if(s->bitstream_bpp==12){ while(2*cy > y){ decode_gray_bitstream(s, width); - ydst= s->picture[0] + s->linesize[0]*y; + ydst= p->data[0] + p->linesize[0]*y; add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); y++; } @@ -854,9 +826,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 decode_422_bitstream(s, width); - ydst= s->picture[0] + s->linesize[0]*y; - udst= s->picture[1] + s->linesize[1]*cy; - vdst= s->picture[2] + s->linesize[2]*cy; + ydst= p->data[0] + p->linesize[0]*y; + udst= p->data[1] + p->linesize[1]*cy; + vdst= p->data[2] + p->linesize[2]*cy; add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); if(!(s->flags&CODEC_FLAG_GRAY)){ @@ -872,17 +844,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 }else{ int y; int leftr, leftg, leftb; - const int last_line= (height-1)*s->linesize[0]; + const int last_line= (height-1)*p->linesize[0]; if(s->bitstream_bpp==32){ - s->picture[0][last_line+3]= get_bits(&s->gb, 8); - leftr= s->picture[0][last_line+2]= get_bits(&s->gb, 8); - leftg= s->picture[0][last_line+1]= get_bits(&s->gb, 8); - leftb= s->picture[0][last_line+0]= get_bits(&s->gb, 8); + p->data[0][last_line+3]= get_bits(&s->gb, 8); + leftr= p->data[0][last_line+2]= get_bits(&s->gb, 8); + leftg= p->data[0][last_line+1]= get_bits(&s->gb, 8); + leftb= p->data[0][last_line+0]= get_bits(&s->gb, 8); }else{ - leftr= s->picture[0][last_line+2]= get_bits(&s->gb, 8); - leftg= s->picture[0][last_line+1]= get_bits(&s->gb, 8); - leftb= s->picture[0][last_line+0]= get_bits(&s->gb, 8); + leftr= p->data[0][last_line+2]= get_bits(&s->gb, 8); + leftg= p->data[0][last_line+1]= get_bits(&s->gb, 8); + leftb= p->data[0][last_line+0]= get_bits(&s->gb, 8); skip_bits(&s->gb, 8); } @@ -891,16 +863,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 case LEFT: case PLANE: decode_bgr_bitstream(s, width-1); - add_left_prediction_bgr32(s->picture[0] + last_line+4, s->temp[0], width-1, &leftr, &leftg, &leftb); + add_left_prediction_bgr32(p->data[0] + last_line+4, s->temp[0], width-1, &leftr, &leftg, &leftb); for(y=s->height-2; y>=0; y--){ //yes its stored upside down decode_bgr_bitstream(s, width); - add_left_prediction_bgr32(s->picture[0] + s->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb); + add_left_prediction_bgr32(p->data[0] + p->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb); if(s->predictor == PLANE){ if((y&s->interlaced)==0){ - s->dsp.add_bytes(s->picture[0] + s->linesize[0]*y, - s->picture[0] + s->linesize[0]*y + fake_ystride, fake_ystride); + s->dsp.add_bytes(p->data[0] + p->linesize[0]*y, + p->data[0] + p->linesize[0]*y + fake_ystride, fake_ystride); } } } @@ -917,12 +889,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 } emms_c(); - for(i=0;i<3;i++) { - picture->data[i] = s->picture[i]; - picture->linesize[i]= s->linesize[i]; - } + *picture= *p; + + avctx->release_buffer(avctx, p); - *data_size = sizeof(AVPicture); + *data_size = sizeof(AVVideoFrame); return (get_bits_count(&s->gb)+7)>>3; } @@ -933,44 +904,47 @@ static int decode_end(AVCodecContext *avctx) int i; for(i=0; i<3; i++){ - if(!(avctx->flags&CODEC_FLAG_DR1)) - av_freep(&s->picture[i]); - free_vlc(&s->vlc[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); + } + return 0; } static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ HYuvContext *s = avctx->priv_data; - AVPicture *pict = data; + AVVideoFrame *pict = data; const int width= s->width; const int width2= s->width>>1; const int height= s->height; const int fake_ystride= s->interlaced ? pict->linesize[0]*2 : pict->linesize[0]; const int fake_ustride= s->interlaced ? pict->linesize[1]*2 : pict->linesize[1]; const int fake_vstride= s->interlaced ? pict->linesize[2]*2 : pict->linesize[2]; + AVVideoFrame * const p= &s->picture; int i, size; init_put_bits(&s->pb, buf, buf_size, NULL, NULL); - for(i=0; i<3; i++){ - s->picture[i]= pict->data[i]; - s->linesize[i]= pict->linesize[i]; - } + *p = *pict; if(avctx->pix_fmt == PIX_FMT_YUV422P || avctx->pix_fmt == PIX_FMT_YUV420P){ int lefty, leftu, leftv, y, cy; - put_bits(&s->pb, 8, leftv= s->picture[2][0]); - put_bits(&s->pb, 8, lefty= s->picture[0][1]); - put_bits(&s->pb, 8, leftu= s->picture[1][0]); - put_bits(&s->pb, 8, s->picture[0][0]); + put_bits(&s->pb, 8, leftv= p->data[2][0]); + put_bits(&s->pb, 8, lefty= p->data[0][1]); + put_bits(&s->pb, 8, leftu= p->data[1][0]); + put_bits(&s->pb, 8, p->data[0][0]); - lefty= sub_left_prediction(s, s->temp[0], s->picture[0]+2, width-2 , lefty); - leftu= sub_left_prediction(s, s->temp[1], s->picture[1]+1, width2-1, leftu); - leftv= sub_left_prediction(s, s->temp[2], s->picture[2]+1, width2-1, leftv); + lefty= sub_left_prediction(s, s->temp[0], p->data[0]+2, width-2 , lefty); + leftu= sub_left_prediction(s, s->temp[1], p->data[1]+1, width2-1, leftu); + leftv= sub_left_prediction(s, s->temp[2], p->data[2]+1, width2-1, leftv); encode_422_bitstream(s, width-2); @@ -978,26 +952,26 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, int lefttopy, lefttopu, lefttopv; cy=y=1; if(s->interlaced){ - lefty= sub_left_prediction(s, s->temp[0], s->picture[0]+s->linesize[0], width , lefty); - leftu= sub_left_prediction(s, s->temp[1], s->picture[1]+s->linesize[1], width2, leftu); - leftv= sub_left_prediction(s, s->temp[2], s->picture[2]+s->linesize[2], width2, leftv); + lefty= sub_left_prediction(s, s->temp[0], p->data[0]+p->linesize[0], width , lefty); + leftu= sub_left_prediction(s, s->temp[1], p->data[1]+p->linesize[1], width2, leftu); + leftv= sub_left_prediction(s, s->temp[2], p->data[2]+p->linesize[2], width2, leftv); encode_422_bitstream(s, width); y++; cy++; } - lefty= sub_left_prediction(s, s->temp[0], s->picture[0]+fake_ystride, 4, lefty); - leftu= sub_left_prediction(s, s->temp[1], s->picture[1]+fake_ystride, 2, leftu); - leftv= sub_left_prediction(s, s->temp[2], s->picture[2]+fake_ystride, 2, leftv); + lefty= sub_left_prediction(s, s->temp[0], p->data[0]+fake_ystride, 4, lefty); + leftu= sub_left_prediction(s, s->temp[1], p->data[1]+fake_ystride, 2, leftu); + leftv= sub_left_prediction(s, s->temp[2], p->data[2]+fake_ystride, 2, leftv); encode_422_bitstream(s, 4); - lefttopy= s->picture[0][3]; - lefttopu= s->picture[1][1]; - lefttopv= s->picture[2][1]; - sub_median_prediction(s->temp[0], s->picture[0]+4, s->picture[0] + fake_ystride+4, width-4 , &lefty, &lefttopy); - sub_median_prediction(s->temp[1], s->picture[1]+2, s->picture[1] + fake_ustride+2, width2-2, &leftu, &lefttopu); - sub_median_prediction(s->temp[2], s->picture[2]+2, s->picture[2] + fake_vstride+2, width2-2, &leftv, &lefttopv); + lefttopy= p->data[0][3]; + lefttopu= p->data[1][1]; + lefttopv= p->data[2][1]; + sub_median_prediction(s->temp[0], p->data[0]+4, p->data[0] + fake_ystride+4, width-4 , &lefty, &lefttopy); + sub_median_prediction(s->temp[1], p->data[1]+2, p->data[1] + fake_ustride+2, width2-2, &leftu, &lefttopu); + sub_median_prediction(s->temp[2], p->data[2]+2, p->data[2] + fake_vstride+2, width2-2, &leftv, &lefttopv); encode_422_bitstream(s, width-4); y++; cy++; @@ -1006,16 +980,16 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, if(s->bitstream_bpp==12){ while(2*cy > y){ - ydst= s->picture[0] + s->linesize[0]*y; + ydst= p->data[0] + p->linesize[0]*y; sub_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); encode_gray_bitstream(s, width); y++; } if(y>=height) break; } - ydst= s->picture[0] + s->linesize[0]*y; - udst= s->picture[1] + s->linesize[1]*cy; - vdst= s->picture[2] + s->linesize[2]*cy; + ydst= p->data[0] + p->linesize[0]*y; + udst= p->data[1] + p->linesize[1]*cy; + vdst= p->data[2] + p->linesize[2]*cy; sub_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); sub_median_prediction(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu); @@ -1029,7 +1003,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, /* encode a luma only line & y++ */ if(s->bitstream_bpp==12){ - ydst= s->picture[0] + s->linesize[0]*y; + ydst= p->data[0] + p->linesize[0]*y; if(s->predictor == PLANE && s->interlaced < y){ s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); @@ -1043,9 +1017,9 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, if(y>=height) break; } - ydst= s->picture[0] + s->linesize[0]*y; - udst= s->picture[1] + s->linesize[1]*cy; - vdst= s->picture[2] + s->linesize[2]*cy; + ydst= p->data[0] + p->linesize[0]*y; + udst= p->data[1] + p->linesize[1]*cy; + vdst= p->data[2] + p->linesize[2]*cy; if(s->predictor == PLANE && s->interlaced < cy){ s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); @@ -1088,11 +1062,8 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, bswap_buf((uint32_t*)buf, (uint32_t*)buf, size); } - avctx->key_frame= 1; - avctx->pict_type= I_TYPE; - s->picture_number++; - + return size*4; } diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c index 490f1ffae3..eed155c196 100644 --- a/libavcodec/mjpeg.c +++ b/libavcodec/mjpeg.c @@ -1180,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 { @@ -1468,7 +1470,7 @@ eoi_parser: } /* dummy quality */ /* XXX: infer it with matrix */ - avctx->quality = 3; +// avctx->quality = 3; goto the_end; } break; @@ -1635,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/libavcodec/motion_est.c b/libavcodec/motion_est.c index b1a3c61f73..fa6c3ee6b1 100644 --- a/libavcodec/motion_est.c +++ b/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/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index c55259974e..328217a253 100644 --- a/libavcodec/mpeg12.c +++ b/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,8 @@ 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 +1574,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 +1675,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 +1812,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 +1822,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; } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 0e07f8d1cf..6b2a376e95 100644 --- a/libavcodec/mpegvideo.c +++ b/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,70 @@ 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; - - 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]; + 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); + + 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; + s->linesize = pic->linesize[0]; + s->uvlinesize= pic->linesize[1]; + + if(pic->qscale_table==NULL) + alloc_picture(s, (Picture*)pic); - if(s->last_picture[i]==NULL) - s->last_picture[i]= s->next_picture[i]; + s->current_picture= s->picture[i]; + } - s->last_dr_opaque= s->next_dr_opaque; - s->next_dr_opaque= avctx->dr_opaque_frame; + s->hurry_up= s->avctx->hurry_up; + s->error_resilience= avctx->error_resilience; - 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; } + /* 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 +853,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 +871,154 @@ 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->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 +1026,26 @@ 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; 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,17 +1064,12 @@ 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; @@ -1088,14 +1088,16 @@ if(s->max_b_frames==0) fprintf(f, "%7d, %7d, %2.4f\n", pbBufPtr(&s->pb) - s->pb.buf, s->qscale, avctx->psnr_y); } #endif - +#if 0 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, + get_psnr(pict->data, s->current_picture.data, pict->linesize, s->linesize, avctx); // printf("%f\n", avctx->psnr_y); } +#endif + return pbBufPtr(&s->pb) - s->pb.buf; } @@ -1757,7 +1759,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) { @@ -1823,33 +1825,47 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) 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 +1889,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 +2170,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 +2196,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 +2222,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 +2255,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 +2277,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 +2295,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,9 +2346,8 @@ 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; @@ -2557,8 +2572,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 +2619,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 +2637,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 +2654,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 +2669,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 +2684,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) { diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 73092b9c11..7a0682fc5a 100644 --- a/libavcodec/mpegvideo.h +++ b/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 @@ -90,14 +93,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 +104,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 +150,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 +164,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 +172,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 +194,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 +259,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 +309,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 +458,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 +484,6 @@ typedef struct MpegEncContext { int mpeg2; int full_pel[2]; int interlaced_dct; - int last_qscale; int first_slice; /* RTP specific */ diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index f1746b4f6d..76fa3c2d49 100644 --- a/libavcodec/msmpeg4.c +++ b/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/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 870cd21e32..caea09b24b 100644 --- a/libavcodec/ratecontrol.c +++ b/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/libavcodec/rv10.c b/libavcodec/rv10.c index 02da93a6c5..8039cdb1ec 100644 --- a/libavcodec/rv10.c +++ b/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/libavcodec/svq1.c b/libavcodec/svq1.c index f92a61031f..86ebd73825 100644 --- a/libavcodec/svq1.c +++ b/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/libavcodec/utils.c b/libavcodec/utils.c index 969507e5ea..d46c51d9cc 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -86,6 +86,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; @@ -104,6 +221,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; } /** @@ -120,6 +239,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; @@ -152,7 +281,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; @@ -167,17 +296,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/libavformat/asf.c b/libavformat/asf.c index 2f1ce12dc3..3635913713 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -556,7 +556,7 @@ static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestam int val; val = stream->num; - if (s->streams[val - 1]->codec.key_frame /* && frag_offset == 0 */) + if (s->streams[val - 1]->codec.coded_picture->key_frame /* && frag_offset == 0 */) val |= 0x80; put_byte(pb, val); put_byte(pb, stream->seq); @@ -793,6 +793,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) st = av_mallocz(sizeof(AVStream)); if (!st) goto fail; + avcodec_get_context_defaults(&st->codec); s->streams[s->nb_streams] = st; asf_st = av_mallocz(sizeof(ASFStream)); if (!asf_st) diff --git a/libavformat/au.c b/libavformat/au.c index 8c3d62a595..b584d8d4f5 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -143,6 +143,8 @@ static int au_read_header(AVFormatContext *s, st = av_malloc(sizeof(AVStream)); if (!st) return -1; + avcodec_get_context_defaults(&st->codec); + s->nb_streams = 1; s->streams[0] = st; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 0ea10f7dfe..86ddee4b52 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -144,6 +144,9 @@ typedef struct AVStream { AVFrac pts; /* ffmpeg.c private use */ int stream_copy; /* if TRUE, just copy stream */ + /* quality, as it has been removed from AVCodecContext and put in AVVideoFrame + * MN:dunno if thats the right place, for it */ + float quality; } AVStream; #define MAX_STREAMS 20 diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 9646408cd1..fc719d3fff 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -103,6 +103,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) AVStream *st = av_mallocz(sizeof(AVStream)); if (!st) goto fail; + avcodec_get_context_defaults(&st->codec); + s->streams[i] = st; } url_fskip(pb, size - 7 * 4); diff --git a/libavformat/avienc.c b/libavformat/avienc.c index b4298b0b39..a9bf3a8d92 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -320,7 +320,7 @@ static int avi_write_packet(AVFormatContext *s, int stream_index, if (enc->codec_type == CODEC_TYPE_VIDEO) { tag[2] = 'd'; tag[3] = 'c'; - flags = enc->key_frame ? 0x10 : 0x00; + flags = enc->coded_picture->key_frame ? 0x10 : 0x00; } else { tag[2] = 'w'; tag[3] = 'b'; diff --git a/libavformat/ffm.c b/libavformat/ffm.c index c21599c69f..cd7a174d06 100644 --- a/libavformat/ffm.c +++ b/libavformat/ffm.c @@ -151,7 +151,7 @@ static int ffm_write_header(AVFormatContext *s) put_be32(pb, codec->codec_id); put_byte(pb, codec->codec_type); put_be32(pb, codec->bit_rate); - put_be32(pb, codec->quality); + put_be32(pb, st->quality); put_be32(pb, codec->flags); /* specific info */ switch(codec->codec_type) { @@ -232,7 +232,7 @@ static int ffm_write_packet(AVFormatContext *s, int stream_index, /* packet size & key_frame */ header[0] = stream_index; header[1] = 0; - if (st->codec.key_frame) + if (st->codec.coded_picture->key_frame) header[1] |= FLAG_KEY_FRAME; header[2] = (size >> 16) & 0xff; header[3] = (size >> 8) & 0xff; @@ -394,6 +394,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) st = av_mallocz(sizeof(AVStream)); if (!st) goto fail; + avcodec_get_context_defaults(&st->codec); s->streams[i] = st; fst = av_mallocz(sizeof(FFMStream)); if (!fst) @@ -405,7 +406,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec.codec_id = get_be32(pb); st->codec.codec_type = get_byte(pb); /* codec_type */ codec->bit_rate = get_be32(pb); - codec->quality = get_be32(pb); + st->quality = get_be32(pb); codec->flags = get_be32(pb); /* specific info */ switch(codec->codec_type) { diff --git a/libavformat/jpeg.c b/libavformat/jpeg.c index 6a19db6d67..e86edfecde 100644 --- a/libavformat/jpeg.c +++ b/libavformat/jpeg.c @@ -170,6 +170,8 @@ static int jpeg_read_header(AVFormatContext *s1, AVFormatParameters *ap) av_free(s); return -ENOMEM; } + avcodec_get_context_defaults(&st->codec); + s1->streams[0] = st; s->img_number = 0; diff --git a/libavformat/rm.c b/libavformat/rm.c index be90a27c89..44e384559d 100644 --- a/libavformat/rm.c +++ b/libavformat/rm.c @@ -352,7 +352,7 @@ static int rm_write_video(AVFormatContext *s, UINT8 *buf, int size) RMContext *rm = s->priv_data; ByteIOContext *pb = &s->pb; StreamInfo *stream = rm->video_stream; - int key_frame = stream->enc->key_frame; + int key_frame = stream->enc->coded_picture->key_frame; /* XXX: this is incorrect: should be a parameter */ @@ -527,6 +527,7 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) st = av_mallocz(sizeof(AVStream)); if (!st) goto fail; + avcodec_get_context_defaults(&st->codec); s->streams[s->nb_streams++] = st; st->id = get_be16(pb); get_be32(pb); /* max bit rate */ diff --git a/libavformat/swf.c b/libavformat/swf.c index 14f8707f96..315219056e 100644 --- a/libavformat/swf.c +++ b/libavformat/swf.c @@ -482,6 +482,8 @@ static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap) st = av_mallocz(sizeof(AVStream)); if (!st) return -ENOMEM; + avcodec_get_context_defaults(&st->codec); + if (v & 0x01) st->codec.channels = 2; else diff --git a/libavformat/utils.c b/libavformat/utils.c index 5a9aa082f4..3388ddc9ef 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -458,7 +458,7 @@ int av_find_stream_info(AVFormatContext *ic) AVCodec *codec; AVStream *st; AVPacket *pkt; - AVPicture picture; + AVVideoFrame picture; AVPacketList *pktl=NULL, **ppktl; short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; UINT8 *ptr; @@ -694,6 +694,8 @@ AVStream *av_new_stream(AVFormatContext *s, int id) st = av_mallocz(sizeof(AVStream)); if (!st) return NULL; + avcodec_get_context_defaults(&st->codec); + st->index = s->nb_streams; st->id = id; s->streams[s->nb_streams++] = st; |