- GOB headers for H.263 coding on RTP mode. - Improved GOB header detection for H.263 decoder. Originally committed as revision 222 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -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: | |||
| @@ -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 | |||
| @@ -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 */ | |||
| @@ -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); | |||
| @@ -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, | |||
| @@ -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, | |||