- Preliminary RTP friendly mode for H.263.

- 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/trunk
This commit is contained in:
Juanjo 2001-11-19 02:13:14 +00:00
parent 652cb0f57a
commit 644d98a4f2
6 changed files with 138 additions and 35 deletions

View File

@ -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:

View File

@ -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

View File

@ -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_gob_header(MpegEncContext *s)
{
unsigned int val, gfid;
/* Check for GOB Start Code */
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);
#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 */
#ifdef DEBUG
fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
#endif
return 1;
}
return 0;
}
int h263_decode_mb(MpegEncContext *s,
DCTELEM block[6][64])
{
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;
/* 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 */
#ifdef DEBUG
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 */
#ifdef DEBUG
fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
#endif
}
}
/* 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;
}
if (s->pict_type == P_TYPE) {
if (get_bits1(&s->gb)) {
/* skip mb */

View File

@ -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);

View File

@ -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,

View File

@ -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,