direct rendering method 1 support

Originally committed as revision 759 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Michael Niedermayer 23 years ago
parent 4f68b0847e
commit 93a21abde5
  1. 23
      libavcodec/avcodec.h
  2. 29
      libavcodec/h263dec.c
  3. 117
      libavcodec/mpegvideo.c
  4. 5
      libavcodec/mpegvideo.h
  5. 2
      libavcodec/rv10.c

@ -5,8 +5,8 @@
#define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION_INT 0x000406
#define LIBAVCODEC_VERSION "0.4.6" #define LIBAVCODEC_VERSION "0.4.6"
#define LIBAVCODEC_BUILD 4615 #define LIBAVCODEC_BUILD 4616
#define LIBAVCODEC_BUILD_STR "4615" #define LIBAVCODEC_BUILD_STR "4616"
enum CodecID { enum CodecID {
CODEC_ID_NONE, CODEC_ID_NONE,
@ -101,11 +101,13 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG,
#define CODEC_FLAG_PASS2 0x0400 /* use internal 2pass ratecontrol in second pass mode */ #define CODEC_FLAG_PASS2 0x0400 /* use internal 2pass ratecontrol in second pass mode */
#define CODEC_FLAG_EXTERN_HUFF 0x1000 /* use external huffman table (for mjpeg) */ #define CODEC_FLAG_EXTERN_HUFF 0x1000 /* use external huffman table (for mjpeg) */
#define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */ #define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */
#define CODEC_FLAG_EMU_EDGE 0x4000/* dont draw edges */
#define CODEC_FLAG_DR1 0x8000 /* dr1 */
/* codec capabilities */ /* codec capabilities */
/* decoder can use draw_horiz_band callback */ /* decoder can use draw_horiz_band callback */
#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 #define CODEC_CAP_DRAW_HORIZ_BAND 0x0001
#define CODEC_CAP_DR1 0x0002 /* direct rendering method 1 */
#define FRAME_RATE_BASE 10000 #define FRAME_RATE_BASE 10000
@ -248,8 +250,16 @@ typedef struct AVCodecContext {
#define MBC 128 #define MBC 128
#define MBR 96 #define MBR 96
#endif #endif
int *quant_store; /* field for communicating with external postprocessing */ #define QP_TYPE int //FIXME note xxx this might be changed to int8_t
QP_TYPE *quant_store; /* field for communicating with external postprocessing */
unsigned qstride; unsigned qstride;
uint8_t *dr_buffer[3];
int dr_stride;
void *dr_opaque_frame;
void (*get_buffer_callback)(struct AVCodecContext *c, int width, int height, int pict_type);
//FIXME this should be reordered after kabis API is finished ... //FIXME this should be reordered after kabis API is finished ...
/* /*
Note: Below are located reserved fields for further usage Note: Below are located reserved fields for further usage
@ -267,13 +277,12 @@ typedef struct AVCodecContext {
flt_res6,flt_res7,flt_res8,flt_res9,flt_res10,flt_res11; flt_res6,flt_res7,flt_res8,flt_res9,flt_res10,flt_res11;
void void
*ptr_res0,*ptr_res1,*ptr_res2,*ptr_res3,*ptr_res4,*ptr_res5, *ptr_res0,*ptr_res1,*ptr_res2,*ptr_res3,*ptr_res4,*ptr_res5,
*ptr_res6,*ptr_res7,*ptr_res8,*ptr_res9,*ptr_res10,*ptr_res11; *ptr_res6;
unsigned long int unsigned long int
ul_res0,ul_res1,ul_res2,ul_res3,ul_res4,ul_res5, ul_res0,ul_res1,ul_res2,ul_res3,ul_res4,ul_res5,
ul_res6,ul_res7,ul_res8,ul_res9,ul_res10,ul_res11,ul_res12; ul_res6,ul_res7,ul_res8,ul_res9,ul_res10,ul_res11,ul_res12;
unsigned int unsigned int
ui_res0,ui_res1,ui_res2,ui_res3,ui_res4,ui_res5, ui_res0,ui_res1,ui_res2,ui_res3,ui_res4,ui_res5;
ui_res6;
unsigned short int unsigned short int
us_res0,us_res1,us_res2,us_res3,us_res4,us_res5, us_res0,us_res1,us_res2,us_res3,us_res4,us_res5,
us_res6,us_res7,us_res8,us_res9,us_res10,us_res11,us_res12; us_res6,us_res7,us_res8,us_res9,us_res10,us_res11,us_res12;

@ -155,21 +155,22 @@ uint64_t time= rdtsc();
ret = h263_decode_picture_header(s); ret = h263_decode_picture_header(s);
} }
/* After H263 & mpeg4 header decode we have the height, width,*/ /* After H263 & mpeg4 header decode we have the height, width,*/
/* and other parameters. So then we could init the picture */ /* and other parameters. So then we could init the picture */
/* FIXME: By the way H263 decoder is evolving it should have */ /* FIXME: By the way H263 decoder is evolving it should have */
/* an H263EncContext */ /* an H263EncContext */
if (s->width != avctx->width || s->height != avctx->height) {
/* H.263 could change picture size any time */
MPV_common_end(s);
s->context_initialized=0;
}
if (!s->context_initialized) { if (!s->context_initialized) {
avctx->width = s->width; avctx->width = s->width;
avctx->height = s->height; avctx->height = s->height;
avctx->aspect_ratio_info= s->aspect_ratio_info; avctx->aspect_ratio_info= s->aspect_ratio_info;
if (MPV_common_init(s) < 0) if (MPV_common_init(s) < 0)
return -1; return -1;
} else if (s->width != avctx->width || s->height != avctx->height) {
/* H.263 could change picture size any time */
MPV_common_end(s);
if (MPV_common_init(s) < 0)
return -1;
} }
if(ret==FRAME_SKIPED) return buf_size; if(ret==FRAME_SKIPED) return buf_size;
@ -190,7 +191,7 @@ uint64_t time= rdtsc();
s->next_p_frame_damaged=0; s->next_p_frame_damaged=0;
} }
MPV_frame_start(s); MPV_frame_start(s, avctx);
#ifdef DEBUG #ifdef DEBUG
printf("qscale=%d\n", s->qscale); printf("qscale=%d\n", s->qscale);
@ -459,7 +460,7 @@ AVCodec mpeg4_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec h263_decoder = { AVCodec h263_decoder = {
@ -471,7 +472,7 @@ AVCodec h263_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec msmpeg4v1_decoder = { AVCodec msmpeg4v1_decoder = {
@ -483,7 +484,7 @@ AVCodec msmpeg4v1_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec msmpeg4v2_decoder = { AVCodec msmpeg4v2_decoder = {
@ -495,7 +496,7 @@ AVCodec msmpeg4v2_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec msmpeg4v3_decoder = { AVCodec msmpeg4v3_decoder = {
@ -507,7 +508,7 @@ AVCodec msmpeg4v3_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec wmv1_decoder = { AVCodec wmv1_decoder = {
@ -519,7 +520,7 @@ AVCodec wmv1_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec wmv2_decoder = { AVCodec wmv2_decoder = {
@ -531,7 +532,7 @@ AVCodec wmv2_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };
AVCodec h263i_decoder = { AVCodec h263i_decoder = {
@ -543,6 +544,6 @@ AVCodec h263i_decoder = {
NULL, NULL,
h263_decode_end, h263_decode_end,
h263_decode_frame, h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
}; };

@ -144,6 +144,7 @@ int MPV_common_init(MpegEncContext *s)
s->mb_width = (s->width + 15) / 16; s->mb_width = (s->width + 15) / 16;
s->mb_height = (s->height + 15) / 16; s->mb_height = (s->height + 15) / 16;
s->mb_num = s->mb_width * s->mb_height; s->mb_num = s->mb_width * s->mb_height;
if(!(s->flags&CODEC_FLAG_DR1)){
s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH; s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH;
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
@ -174,6 +175,9 @@ int MPV_common_init(MpegEncContext *s)
if(i>0) memset(s->aux_picture_base[i], 128, c_size); if(i>0) memset(s->aux_picture_base[i], 128, c_size);
} }
} }
}
CHECKED_ALLOCZ(s->edge_emu_buffer, (s->width+32)*2*17);
if (s->encoding) { if (s->encoding) {
int j; int j;
@ -315,11 +319,22 @@ void MPV_common_end(MpegEncContext *s)
av_freep(&s->bitstream_buffer); av_freep(&s->bitstream_buffer);
av_freep(&s->tex_pb_buffer); av_freep(&s->tex_pb_buffer);
av_freep(&s->pb2_buffer); av_freep(&s->pb2_buffer);
av_freep(&s->edge_emu_buffer);
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
int j; int j;
if(!(s->flags&CODEC_FLAG_DR1)){
av_freep(&s->last_picture_base[i]); av_freep(&s->last_picture_base[i]);
av_freep(&s->next_picture_base[i]); av_freep(&s->next_picture_base[i]);
av_freep(&s->aux_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++){ for(j=0; j<REORDER_BUFFER_SIZE; j++){
av_freep(&s->picture_buffer[j][i]); av_freep(&s->picture_buffer[j][i]);
} }
@ -595,7 +610,7 @@ 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 */ /* generic function for encode/decode called before a frame is coded/decoded */
void MPV_frame_start(MpegEncContext *s) void MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
{ {
int i; int i;
UINT8 *tmp; UINT8 *tmp;
@ -603,17 +618,39 @@ void MPV_frame_start(MpegEncContext *s)
s->mb_skiped = 0; s->mb_skiped = 0;
s->decoding_error=0; s->decoding_error=0;
if(avctx->flags&CODEC_FLAG_DR1){
int i;
avctx->get_buffer_callback(avctx, s->width, s->height, s->pict_type);
s->linesize= avctx->dr_stride;
}
if (s->pict_type == B_TYPE) { if (s->pict_type == B_TYPE) {
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
if(avctx->flags&CODEC_FLAG_DR1)
s->aux_picture[i]= avctx->dr_buffer[i];
s->current_picture[i] = s->aux_picture[i]; s->current_picture[i] = s->aux_picture[i];
} }
} else { } else {
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
/* swap next and last */ /* swap next and last */
if(avctx->flags&CODEC_FLAG_DR1)
tmp= avctx->dr_buffer[i];
else
tmp = s->last_picture[i]; tmp = s->last_picture[i];
s->last_picture[i] = s->next_picture[i]; s->last_picture[i] = s->next_picture[i];
s->next_picture[i] = tmp; s->next_picture[i] = tmp;
s->current_picture[i] = tmp; s->current_picture[i] = tmp;
s->last_dr_opaque= s->next_dr_opaque;
s->next_dr_opaque= avctx->dr_opaque_frame;
if(s->has_b_frames && s->last_dr_opaque)
avctx->dr_opaque_frame= s->last_dr_opaque;
else
avctx->dr_opaque_frame= s->next_dr_opaque;
} }
} }
} }
@ -624,7 +661,7 @@ void MPV_frame_end(MpegEncContext *s)
// if((s->picture_number%100)==0 && s->encoding) printf("sads:%d //\n", sads); // if((s->picture_number%100)==0 && s->encoding) printf("sads:%d //\n", sads);
/* draw edge for correct motion prediction if outside */ /* draw edge for correct motion prediction if outside */
if (s->pict_type != B_TYPE && !s->intra_only) { if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4 || s->divx_version>=500){ if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4 || s->divx_version>=500){
draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH); draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH);
draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2);
@ -776,7 +813,7 @@ int MPV_encode_picture(AVCodecContext *avctx,
s->picture_in_gop_number= s->coded_order[0].picture_in_gop_number; s->picture_in_gop_number= s->coded_order[0].picture_in_gop_number;
s->picture_number= s->coded_order[0].picture_number; s->picture_number= s->coded_order[0].picture_number;
MPV_frame_start(s); MPV_frame_start(s, avctx);
encode_picture(s, s->picture_number); encode_picture(s, s->picture_number);
avctx->key_frame = (s->pict_type == I_TYPE); avctx->key_frame = (s->pict_type == I_TYPE);
@ -879,6 +916,60 @@ static inline void gmc1_motion(MpegEncContext *s,
return; return;
} }
static void emulated_edge_mc(UINT8 *buf, UINT8 *src, int linesize, int block_w, int block_h,
int src_x, int src_y, int w, int h){
int x, y;
int start_y, start_x, end_y, end_x;
if(src_y>= h){
src+= (h-1-src_y)*linesize;
src_y=h-1;
}
if(src_x>= w){
src+= (w-1-src_x);
src_x=w-1;
}
start_y= MAX(0, -src_y);
start_x= MAX(0, -src_x);
end_y= MIN(block_h, h-src_y);
end_x= MIN(block_w, w-src_x);
// copy existing part
for(y=start_y; y<end_y; y++){
for(x=start_x; x<end_x; x++){
buf[x + y*linesize]= src[x + y*linesize];
}
}
//top
for(y=0; y<start_y; y++){
for(x=start_x; x<end_x; x++){
buf[x + y*linesize]= buf[x + start_y*linesize];
}
}
//bottom
for(y=end_y; y<block_h; y++){
for(x=start_x; x<end_x; x++){
buf[x + y*linesize]= buf[x + (end_y-1)*linesize];
}
}
for(y=0; y<block_h; y++){
//left
for(x=0; x<start_x; x++){
buf[x + y*linesize]= buf[start_x + y*linesize];
}
//right
for(x=end_x; x<block_w; x++){
buf[x + y*linesize]= buf[end_x - 1 + y*linesize];
}
}
}
/* apply one mpeg motion vector to the three components */ /* apply one mpeg motion vector to the three components */
static inline void mpeg_motion(MpegEncContext *s, static inline void mpeg_motion(MpegEncContext *s,
UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr,
@ -889,6 +980,8 @@ static inline void mpeg_motion(MpegEncContext *s,
{ {
UINT8 *ptr; UINT8 *ptr;
int dxy, offset, mx, my, src_x, src_y, height, linesize; int dxy, offset, mx, my, src_x, src_y, height, linesize;
int emu=0;
if(s->quarter_sample) if(s->quarter_sample)
{ {
motion_x>>=1; motion_x>>=1;
@ -909,6 +1002,15 @@ if(s->quarter_sample)
linesize = s->linesize << field_based; linesize = s->linesize << field_based;
ptr = ref_picture[0] + (src_y * linesize) + (src_x) + src_offset; ptr = ref_picture[0] + (src_y * linesize) + (src_x) + src_offset;
dest_y += dest_offset; dest_y += dest_offset;
if(s->flags&CODEC_FLAG_EMU_EDGE){
if(src_x<0 || src_y<0 || src_x + (motion_x&1) + 16 > s->width
|| src_y + (motion_y&1) + h > height){
emulated_edge_mc(s->edge_emu_buffer, ptr, linesize, 17, h+1, src_x, src_y, s->width, height);
ptr= s->edge_emu_buffer;
emu=1;
}
}
pix_op[dxy](dest_y, ptr, linesize, h); pix_op[dxy](dest_y, ptr, linesize, h);
pix_op[dxy](dest_y + 8, ptr + 8, linesize, h); pix_op[dxy](dest_y + 8, ptr + 8, linesize, h);
@ -941,8 +1043,17 @@ if(s->quarter_sample)
offset = (src_y * (linesize >> 1)) + src_x + (src_offset >> 1); offset = (src_y * (linesize >> 1)) + src_x + (src_offset >> 1);
ptr = ref_picture[1] + offset; ptr = ref_picture[1] + offset;
if(emu){
emulated_edge_mc(s->edge_emu_buffer, ptr, linesize>>1, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1);
ptr= s->edge_emu_buffer;
}
pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, linesize >> 1, h >> 1); pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, linesize >> 1, h >> 1);
ptr = ref_picture[2] + offset; ptr = ref_picture[2] + offset;
if(emu){
emulated_edge_mc(s->edge_emu_buffer, ptr, linesize>>1, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1);
ptr= s->edge_emu_buffer;
}
pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, linesize >> 1, h >> 1); pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, linesize >> 1, h >> 1);
} }

@ -143,6 +143,8 @@ typedef struct MpegEncContext {
UINT8 *aux_picture[3]; /* aux picture (for B frames only) */ UINT8 *aux_picture[3]; /* aux picture (for B frames only) */
UINT8 *aux_picture_base[3]; /* real start of the picture */ UINT8 *aux_picture_base[3]; /* real start of the picture */
UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */ UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */
void *last_dr_opaque;
void *next_dr_opaque;
int num_available_buffers; /* is 0 at the start & after seeking, after the first I frame its 1 after next I/P 2 */ 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 */ int last_dc[3]; /* last DC values for MPEG1 */
INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */ INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */
@ -159,6 +161,7 @@ typedef struct MpegEncContext {
UINT8 *cbp_table; /* used to store cbp, ac_pred for partitioned 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 */ UINT8 *pred_dir_table; /* used to store pred_dir for partitioned decoding */
INT8 *qscale_table; /* used to store qscale for partitioned decoding (& postprocessing FIXME export) */ INT8 *qscale_table; /* used to store qscale for partitioned decoding (& postprocessing FIXME export) */
UINT8 *edge_emu_buffer;
int input_qscale; /* qscale prior to reordering of frames */ int input_qscale; /* qscale prior to reordering of frames */
int input_pict_type; /* pict_type prior to reordering of frames */ int input_pict_type; /* pict_type prior to reordering of frames */
@ -447,7 +450,7 @@ typedef struct MpegEncContext {
int MPV_common_init(MpegEncContext *s); int MPV_common_init(MpegEncContext *s);
void MPV_common_end(MpegEncContext *s); void MPV_common_end(MpegEncContext *s);
void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]); void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
void MPV_frame_start(MpegEncContext *s); void MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx);
void MPV_frame_end(MpegEncContext *s); void MPV_frame_end(MpegEncContext *s);
#ifdef HAVE_MMX #ifdef HAVE_MMX
void MPV_common_init_mmx(MpegEncContext *s); void MPV_common_init_mmx(MpegEncContext *s);

@ -419,7 +419,7 @@ static int rv10_decode_frame(AVCodecContext *avctx,
} }
if (s->mb_x == 0 && s->mb_y == 0) { if (s->mb_x == 0 && s->mb_y == 0) {
MPV_frame_start(s); MPV_frame_start(s, avctx);
} }
#ifdef DEBUG #ifdef DEBUG

Loading…
Cancel
Save