Commit 644d98a4 authored by Juanjo's avatar Juanjo

- 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
parent 652cb0f5
...@@ -5,6 +5,14 @@ version 0.4.6: ...@@ -5,6 +5,14 @@ version 0.4.6:
- recoded dct and motion vector search with gcc (no longer depends on - recoded dct and motion vector search with gcc (no longer depends on
nasm). nasm).
- fix quantization bug in AC3 encoder. - 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: version 0.4.5:
......
...@@ -103,6 +103,19 @@ typedef struct AVCodecContext { ...@@ -103,6 +103,19 @@ typedef struct AVCodecContext {
struct AVCodec *codec; struct AVCodec *codec;
void *priv_data; 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 */ /* the following fields are ignored */
void *opaque; /* can be used to carry app specific stuff */ void *opaque; /* can be used to carry app specific stuff */
char codec_name[32]; char codec_name[32];
...@@ -239,8 +252,8 @@ void avcodec_register_all(void); ...@@ -239,8 +252,8 @@ void avcodec_register_all(void);
#ifdef FF_POSTPROCESS #ifdef FF_POSTPROCESS
#ifndef MBC #ifndef MBC
#define MBC 120 #define MBC 48
#define MBR 72 #define MBR 36
#endif #endif
extern int quant_store[MBR+1][MBC+1]; // [Review] extern int quant_store[MBR+1][MBC+1]; // [Review]
#endif #endif
......
...@@ -140,12 +140,45 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -140,12 +140,45 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
put_bits(&s->pb, 1, 0); /* no PEI */ 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, void h263_encode_mb(MpegEncContext * s,
DCTELEM block[6][64], DCTELEM block[6][64],
int motion_x, int motion_y) int motion_x, int motion_y)
{ {
int cbpc, cbpy, i, cbp, pred_x, pred_y; int cbpc, cbpy, i, cbp, pred_x, pred_y;
// printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
if (!s->mb_intra) { if (!s->mb_intra) {
/* compute cbp */ /* compute cbp */
...@@ -772,42 +805,38 @@ void h263_decode_init_vlc(MpegEncContext *s) ...@@ -772,42 +805,38 @@ void h263_decode_init_vlc(MpegEncContext *s)
} }
} }
int h263_decode_mb(MpegEncContext *s, int h263_decode_gob_header(MpegEncContext *s)
DCTELEM block[6][64])
{ {
int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; unsigned int val, gfid;
unsigned int val;
INT16 *mot_val;
static INT8 quant_tab[4] = { -1, -2, 1, 2 };
unsigned int gfid;
/* Check for GOB Start Code */ /* Check for GOB Start Code */
if (s->mb_x == 0) { val = show_bits(&s->gb, 16);
val = show_bits(&s->gb, 16); if (val == 0) {
if (val == 0) { /* We have a GBSC probably with GSTUFF */
/* We have a GBSC probably with GSTUFF */ skip_bits(&s->gb, 16); /* Drop the zeros */
skip_bits(&s->gb, 16); /* Drop the zeros */ while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr,"\nGOB Start Code at MB %d\n", fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x);
(s->mb_y * s->mb_width) + s->mb_x);
#endif #endif
s->gob_number = get_bits(&s->gb, 5); /* GN */ s->gob_number = get_bits(&s->gb, 5); /* GN */
gfid = get_bits(&s->gb, 2); /* GFID */ gfid = get_bits(&s->gb, 2); /* GFID */
s->qscale = get_bits(&s->gb, 5); /* GQUANT */ s->qscale = get_bits(&s->gb, 5); /* GQUANT */
#ifdef DEBUG #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 #endif
} return 1;
} }
/* FIXME: In the future H.263+ will have intra prediction */ return 0;
/* 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; int h263_decode_mb(MpegEncContext *s,
else DCTELEM block[6][64])
s->first_gob_line = 0; {
} 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 (s->pict_type == P_TYPE) {
if (get_bits1(&s->gb)) { if (get_bits1(&s->gb)) {
/* skip mb */ /* skip mb */
......
...@@ -140,6 +140,12 @@ static int h263_decode_frame(AVCodecContext *avctx, ...@@ -140,6 +140,12 @@ static int h263_decode_frame(AVCodecContext *avctx,
/* decode each macroblock */ /* decode each macroblock */
for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) { 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++) { for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
#ifdef DEBUG #ifdef DEBUG
printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
......
...@@ -249,6 +249,9 @@ int MPV_encode_init(AVCodecContext *avctx) ...@@ -249,6 +249,9 @@ int MPV_encode_init(AVCodecContext *avctx)
s->width = avctx->width; s->width = avctx->width;
s->height = avctx->height; s->height = avctx->height;
s->gop_size = avctx->gop_size; 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) { if (s->gop_size <= 1) {
s->intra_only = 1; s->intra_only = 1;
s->gop_size = 12; s->gop_size = 12;
...@@ -276,6 +279,8 @@ int MPV_encode_init(AVCodecContext *avctx) ...@@ -276,6 +279,8 @@ int MPV_encode_init(AVCodecContext *avctx)
break; break;
case CODEC_ID_H263P: case CODEC_ID_H263P:
s->out_format = FMT_H263; s->out_format = FMT_H263;
s->rtp_mode = 1;
s->rtp_payload_size = 1200;
s->h263_plus = 1; s->h263_plus = 1;
s->unrestricted_mv = 1; s->unrestricted_mv = 1;
...@@ -819,7 +824,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) ...@@ -819,7 +824,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
static void encode_picture(MpegEncContext *s, int picture_number) 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; UINT8 *ptr;
int i, motion_x, motion_y; int i, motion_x, motion_y;
...@@ -869,7 +874,29 @@ static void encode_picture(MpegEncContext *s, int picture_number) ...@@ -869,7 +874,29 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
s->mv_dir = MV_DIR_FORWARD; 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++) { 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++) { for(mb_x=0; mb_x < s->mb_width; mb_x++) {
s->mb_x = mb_x; s->mb_x = mb_x;
...@@ -981,7 +1008,17 @@ static void encode_picture(MpegEncContext *s, int picture_number) ...@@ -981,7 +1008,17 @@ static void encode_picture(MpegEncContext *s, int picture_number)
MPV_decode_mb(s, s->block); 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, static int dct_quantize(MpegEncContext *s,
......
...@@ -131,6 +131,7 @@ typedef struct MpegEncContext { ...@@ -131,6 +131,7 @@ typedef struct MpegEncContext {
/* H.263 specific */ /* H.263 specific */
int gob_number; int gob_number;
int gob_index;
int first_gob_line; int first_gob_line;
/* H.263+ specific */ /* H.263+ specific */
...@@ -185,7 +186,14 @@ typedef struct MpegEncContext { ...@@ -185,7 +186,14 @@ typedef struct MpegEncContext {
int interlaced_dct; int interlaced_dct;
int last_qscale; int last_qscale;
int first_slice; 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; DCTELEM block[6][64] __align8;
void (*dct_unquantize)(struct MpegEncContext *s, void (*dct_unquantize)(struct MpegEncContext *s,
DCTELEM *block, int n, int qscale); DCTELEM *block, int n, int qscale);
...@@ -236,7 +244,7 @@ typedef struct RLTable { ...@@ -236,7 +244,7 @@ typedef struct RLTable {
void init_rl(RLTable *rl); void init_rl(RLTable *rl);
void init_vlc_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; int index;
index = rl->index_run[last][run]; index = rl->index_run[last][run];
...@@ -251,6 +259,7 @@ void h263_encode_mb(MpegEncContext *s, ...@@ -251,6 +259,7 @@ void h263_encode_mb(MpegEncContext *s,
DCTELEM block[6][64], DCTELEM block[6][64],
int motion_x, int motion_y); int motion_x, int motion_y);
void h263_encode_picture_header(MpegEncContext *s, int picture_number); 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); void h263_dc_scale(MpegEncContext *s);
INT16 *h263_pred_motion(MpegEncContext * s, int block, INT16 *h263_pred_motion(MpegEncContext * s, int block,
int *px, int *py); int *px, int *py);
...@@ -261,6 +270,7 @@ void h263_encode_init_vlc(MpegEncContext *s); ...@@ -261,6 +270,7 @@ void h263_encode_init_vlc(MpegEncContext *s);
void h263_decode_init_vlc(MpegEncContext *s); void h263_decode_init_vlc(MpegEncContext *s);
int h263_decode_picture_header(MpegEncContext *s); int h263_decode_picture_header(MpegEncContext *s);
int h263_decode_gob_header(MpegEncContext *s);
int mpeg4_decode_picture_header(MpegEncContext * s); int mpeg4_decode_picture_header(MpegEncContext * s);
int intel_h263_decode_picture_header(MpegEncContext *s); int intel_h263_decode_picture_header(MpegEncContext *s);
int h263_decode_mb(MpegEncContext *s, int h263_decode_mb(MpegEncContext *s,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment