diff --git a/Changelog b/Changelog index 103de166f6..95422897aa 100644 --- a/Changelog +++ b/Changelog @@ -5,6 +5,14 @@ version 0.4.6: - recoded dct and motion vector search with gcc (no longer depends on nasm). - fix quantization bug in AC3 encoder. +- added GOB header parsing on H.263/H.263+ decoder. (Juanjo) +- bug fix on MCBPC tables of H.263. (Juanjo) +- added Advanced Prediction Mode on H.263/H.263+ decoder. (Juanjo) +- now we can decode H.263 streams found on QuickTime files. (Juanjo) +- now we can decode H.263 streams found on VIVO v1 files.(Juanjo) +- preliminary RTP "friendly" mode for H.263/H.263+ coding. (Juanjo) +- added GOB header for H.263/H.263+ coding on RTP mode. (Juanjo) +- now H.263 picture size is returned on the first decoded frame. (Juanjo) version 0.4.5: diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b85db2d558..10d19a9c31 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -103,6 +103,19 @@ typedef struct AVCodecContext { struct AVCodec *codec; void *priv_data; + /* The following data is for RTP friendly coding */ + /* By now only H.263/H.263+ coder honours this */ + int rtp_mode; /* 1 for activate RTP friendly-mode */ + /* highers numbers represent more error-prone */ + /* enviroments, by now just "1" exist */ + + int rtp_payload_size; /* The size of the RTP payload, the coder will */ + /* do it's best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263 */ + /* This doesn't take account of any particular */ + /* headers inside the transmited RTP payload */ + /* the following fields are ignored */ void *opaque; /* can be used to carry app specific stuff */ char codec_name[32]; @@ -239,8 +252,8 @@ void avcodec_register_all(void); #ifdef FF_POSTPROCESS #ifndef MBC -#define MBC 120 -#define MBR 72 +#define MBC 48 +#define MBR 36 #endif extern int quant_store[MBR+1][MBC+1]; // [Review] #endif diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 4aaf5d6ad4..3461b4f676 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -140,12 +140,45 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) put_bits(&s->pb, 1, 0); /* no PEI */ } +int h263_encode_gob_header(MpegEncContext * s, int mb_line) +{ + int pdif=0; + + /* Check to see if we need to put a new GBSC */ + /* for RTP packetization */ + if (s->rtp_mode) { + pdif = s->pb.buf_ptr - s->ptr_lastgob; + if (pdif >= s->rtp_payload_size) { + /* Bad luck, packet must be cut before */ + align_put_bits(&s->pb); + s->ptr_lastgob = s->pb.buf_ptr; + put_bits(&s->pb, 17, 1); /* GBSC */ + s->gob_number = mb_line; + put_bits(&s->pb, 5, s->gob_number); /* GN */ + put_bits(&s->pb, 2, 1); /* GFID */ + put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + return pdif; + } else if (pdif + s->mb_line_avgsize >= s->rtp_payload_size) { + /* Cut the packet before we can't */ + align_put_bits(&s->pb); + s->ptr_lastgob = s->pb.buf_ptr; + put_bits(&s->pb, 17, 1); /* GBSC */ + s->gob_number = mb_line; + put_bits(&s->pb, 5, s->gob_number); /* GN */ + put_bits(&s->pb, 2, 1); /* GFID */ + put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + return pdif; + } + } + return 0; +} + void h263_encode_mb(MpegEncContext * s, DCTELEM block[6][64], int motion_x, int motion_y) { int cbpc, cbpy, i, cbp, pred_x, pred_y; - + // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); if (!s->mb_intra) { /* compute cbp */ @@ -772,42 +805,38 @@ void h263_decode_init_vlc(MpegEncContext *s) } } -int h263_decode_mb(MpegEncContext *s, - DCTELEM block[6][64]) +int h263_decode_gob_header(MpegEncContext *s) { - int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; - unsigned int val; - INT16 *mot_val; - static INT8 quant_tab[4] = { -1, -2, 1, 2 }; - unsigned int gfid; + unsigned int val, gfid; /* Check for GOB Start Code */ - if (s->mb_x == 0) { - val = show_bits(&s->gb, 16); - if (val == 0) { - /* We have a GBSC probably with GSTUFF */ - skip_bits(&s->gb, 16); /* Drop the zeros */ - while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */ + val = show_bits(&s->gb, 16); + if (val == 0) { + /* We have a GBSC probably with GSTUFF */ + skip_bits(&s->gb, 16); /* Drop the zeros */ + while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */ #ifdef DEBUG - fprintf(stderr,"\nGOB Start Code at MB %d\n", - (s->mb_y * s->mb_width) + s->mb_x); + fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x); #endif - s->gob_number = get_bits(&s->gb, 5); /* GN */ - gfid = get_bits(&s->gb, 2); /* GFID */ - s->qscale = get_bits(&s->gb, 5); /* GQUANT */ + s->gob_number = get_bits(&s->gb, 5); /* GN */ + gfid = get_bits(&s->gb, 2); /* GFID */ + s->qscale = get_bits(&s->gb, 5); /* GQUANT */ #ifdef DEBUG - fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale); + fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale); #endif - } + return 1; } - /* FIXME: In the future H.263+ will have intra prediction */ - /* and we are gonna need another way to detect MPEG4 */ - if (!s->h263_pred) { - if (s->mb_y == s->gob_number) - s->first_gob_line = 1; - else - s->first_gob_line = 0; - } + return 0; + +} + +int h263_decode_mb(MpegEncContext *s, + DCTELEM block[6][64]) +{ + int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; + INT16 *mot_val; + static INT8 quant_tab[4] = { -1, -2, 1, 2 }; + if (s->pict_type == P_TYPE) { if (get_bits1(&s->gb)) { /* skip mb */ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index d56bc8252b..be76e3030f 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -140,6 +140,12 @@ static int h263_decode_frame(AVCodecContext *avctx, /* decode each macroblock */ for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) { + /* Check for GOB headers on H.263 */ + /* FIXME: In the future H.263+ will have intra prediction */ + /* and we are gonna need another way to detect MPEG4 */ + if (s->mb_y && !s->h263_pred) { + s->first_gob_line = h263_decode_gob_header(s); + } for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) { #ifdef DEBUG printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 148d7e142c..11ac7dcafc 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -249,6 +249,9 @@ int MPV_encode_init(AVCodecContext *avctx) s->width = avctx->width; s->height = avctx->height; s->gop_size = avctx->gop_size; + s->rtp_mode = avctx->rtp_mode; + s->rtp_payload_size = avctx->rtp_payload_size; + if (s->gop_size <= 1) { s->intra_only = 1; s->gop_size = 12; @@ -276,6 +279,8 @@ int MPV_encode_init(AVCodecContext *avctx) break; case CODEC_ID_H263P: s->out_format = FMT_H263; + s->rtp_mode = 1; + s->rtp_payload_size = 1200; s->h263_plus = 1; s->unrestricted_mv = 1; @@ -819,7 +824,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) static void encode_picture(MpegEncContext *s, int picture_number) { - int mb_x, mb_y, wrap; + int mb_x, mb_y, wrap, last_gob; UINT8 *ptr; int i, motion_x, motion_y; @@ -869,7 +874,29 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->mv_type = MV_TYPE_16X16; s->mv_dir = MV_DIR_FORWARD; + /* Get the GOB height based on picture height */ + if (s->out_format == FMT_H263 && s->h263_plus) { + if (s->height <= 400) + s->gob_index = 1; + else if (s->height <= 800) + s->gob_index = 2; + else + s->gob_index = 4; + } + for(mb_y=0; mb_y < s->mb_height; mb_y++) { + /* Put GOB header based on RTP MTU */ + if (!mb_y) { + s->ptr_lastgob = s->pb.buf_ptr; + s->ptr_last_mb_line = s->pb.buf_ptr; + } else if (s->out_format == FMT_H263 && s->h263_plus) { + last_gob = h263_encode_gob_header(s, mb_y); + if (last_gob) { + //fprintf(stderr,"\nLast GOB size: %d", last_gob); + s->first_gob_line = 1; + } else + s->first_gob_line = 0; + } for(mb_x=0; mb_x < s->mb_width; mb_x++) { s->mb_x = mb_x; @@ -981,7 +1008,17 @@ static void encode_picture(MpegEncContext *s, int picture_number) MPV_decode_mb(s, s->block); } + /* Obtain average MB line size for RTP */ + if (!mb_y) + s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line; + else + s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1; + //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, + // (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize); + s->ptr_last_mb_line = s->pb.buf_ptr; } + //if (s->gob_number) + // fprintf(stderr,"\nNumber of GOB: %d", s->gob_number); } static int dct_quantize(MpegEncContext *s, diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 7b473aaa5a..e653edb9b4 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -131,6 +131,7 @@ typedef struct MpegEncContext { /* H.263 specific */ int gob_number; + int gob_index; int first_gob_line; /* H.263+ specific */ @@ -185,7 +186,14 @@ typedef struct MpegEncContext { int interlaced_dct; int last_qscale; int first_slice; - + + /* RTP specific */ + int rtp_mode; + int rtp_payload_size; + UINT8 *ptr_lastgob; + UINT8 *ptr_last_mb_line; + UINT32 mb_line_avgsize; + DCTELEM block[6][64] __align8; void (*dct_unquantize)(struct MpegEncContext *s, DCTELEM *block, int n, int qscale); @@ -236,7 +244,7 @@ typedef struct RLTable { void init_rl(RLTable *rl); void init_vlc_rl(RLTable *rl); -static inline int get_rl_index(const RLTable *rl, int last, int run, int level) +extern inline int get_rl_index(const RLTable *rl, int last, int run, int level) { int index; index = rl->index_run[last][run]; @@ -251,6 +259,7 @@ void h263_encode_mb(MpegEncContext *s, DCTELEM block[6][64], int motion_x, int motion_y); void h263_encode_picture_header(MpegEncContext *s, int picture_number); +int h263_encode_gob_header(MpegEncContext * s, int mb_line); void h263_dc_scale(MpegEncContext *s); INT16 *h263_pred_motion(MpegEncContext * s, int block, int *px, int *py); @@ -261,6 +270,7 @@ void h263_encode_init_vlc(MpegEncContext *s); void h263_decode_init_vlc(MpegEncContext *s); int h263_decode_picture_header(MpegEncContext *s); +int h263_decode_gob_header(MpegEncContext *s); int mpeg4_decode_picture_header(MpegEncContext * s); int intel_h263_decode_picture_header(MpegEncContext *s); int h263_decode_mb(MpegEncContext *s,