- Fixes on RTP and GOB headers for H.263.
- RTP callback system implemented for H.263/H.263+. - Bug fix on DC coefficients of H.263. - H.263 decoder now returns PTS on picture number. Originally committed as revision 292 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
3cb32e3d1f
commit
81401c1fbc
@ -7,6 +7,7 @@ version 0.4.6:
|
|||||||
- fix quantization bug in AC3 encoder.
|
- fix quantization bug in AC3 encoder.
|
||||||
- added GOB header parsing on H.263/H.263+ decoder. (Juanjo)
|
- added GOB header parsing on H.263/H.263+ decoder. (Juanjo)
|
||||||
- bug fix on MCBPC tables of H.263. (Juanjo)
|
- bug fix on MCBPC tables of H.263. (Juanjo)
|
||||||
|
- bug fix on DC coefficients of H.263. (Juanjo)
|
||||||
- added Advanced Prediction Mode on H.263/H.263+ decoder. (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 QuickTime files. (Juanjo)
|
||||||
- now we can decode H.263 streams found on VIVO v1 files.(Juanjo)
|
- now we can decode H.263 streams found on VIVO v1 files.(Juanjo)
|
||||||
|
@ -115,6 +115,14 @@ typedef struct AVCodecContext {
|
|||||||
/* with a start code on some codecs like H.263 */
|
/* with a start code on some codecs like H.263 */
|
||||||
/* This doesn't take account of any particular */
|
/* This doesn't take account of any particular */
|
||||||
/* headers inside the transmited RTP payload */
|
/* headers inside the transmited RTP payload */
|
||||||
|
|
||||||
|
|
||||||
|
/* The RTP callcack: This function is called */
|
||||||
|
/* every time the encoder as a packet to send */
|
||||||
|
/* Depends on the encoder if the data starts */
|
||||||
|
/* with a Start Code (it should) H.263 does */
|
||||||
|
void (*rtp_callback)(void *data, int size, int packet_number);
|
||||||
|
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
@ -62,7 +62,12 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
|
|||||||
int format;
|
int format;
|
||||||
|
|
||||||
align_put_bits(&s->pb);
|
align_put_bits(&s->pb);
|
||||||
put_bits(&s->pb, 22, 0x20);
|
|
||||||
|
/* Update the pointer to last GOB */
|
||||||
|
s->ptr_lastgob = s->pb.buf_ptr;
|
||||||
|
s->gob_number = 0;
|
||||||
|
|
||||||
|
put_bits(&s->pb, 22, 0x20); /* PSC */
|
||||||
put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) /
|
put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) /
|
||||||
s->frame_rate) & 0xff);
|
s->frame_rate) & 0xff);
|
||||||
|
|
||||||
@ -151,22 +156,36 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line)
|
|||||||
if (pdif >= s->rtp_payload_size) {
|
if (pdif >= s->rtp_payload_size) {
|
||||||
/* Bad luck, packet must be cut before */
|
/* Bad luck, packet must be cut before */
|
||||||
align_put_bits(&s->pb);
|
align_put_bits(&s->pb);
|
||||||
|
flush_put_bits(&s->pb);
|
||||||
|
/* Call the RTP callback to send the last GOB */
|
||||||
|
if (s->rtp_callback) {
|
||||||
|
pdif = s->pb.buf_ptr - s->ptr_lastgob;
|
||||||
|
s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
|
||||||
|
}
|
||||||
s->ptr_lastgob = s->pb.buf_ptr;
|
s->ptr_lastgob = s->pb.buf_ptr;
|
||||||
put_bits(&s->pb, 17, 1); /* GBSC */
|
put_bits(&s->pb, 17, 1); /* GBSC */
|
||||||
s->gob_number = mb_line;
|
s->gob_number = mb_line / s->gob_index;
|
||||||
put_bits(&s->pb, 5, s->gob_number); /* GN */
|
put_bits(&s->pb, 5, s->gob_number); /* GN */
|
||||||
put_bits(&s->pb, 2, 1); /* GFID */
|
put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */
|
||||||
put_bits(&s->pb, 5, s->qscale); /* GQUANT */
|
put_bits(&s->pb, 5, s->qscale); /* GQUANT */
|
||||||
|
//fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif);
|
||||||
return pdif;
|
return pdif;
|
||||||
} else if (pdif + s->mb_line_avgsize >= s->rtp_payload_size) {
|
} else if (pdif + s->mb_line_avgsize >= s->rtp_payload_size) {
|
||||||
/* Cut the packet before we can't */
|
/* Cut the packet before we can't */
|
||||||
align_put_bits(&s->pb);
|
align_put_bits(&s->pb);
|
||||||
|
flush_put_bits(&s->pb);
|
||||||
|
/* Call the RTP callback to send the last GOB */
|
||||||
|
if (s->rtp_callback) {
|
||||||
|
pdif = s->pb.buf_ptr - s->ptr_lastgob;
|
||||||
|
s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
|
||||||
|
}
|
||||||
s->ptr_lastgob = s->pb.buf_ptr;
|
s->ptr_lastgob = s->pb.buf_ptr;
|
||||||
put_bits(&s->pb, 17, 1); /* GBSC */
|
put_bits(&s->pb, 17, 1); /* GBSC */
|
||||||
s->gob_number = mb_line;
|
s->gob_number = mb_line / s->gob_index;
|
||||||
put_bits(&s->pb, 5, s->gob_number); /* GN */
|
put_bits(&s->pb, 5, s->gob_number); /* GN */
|
||||||
put_bits(&s->pb, 2, 1); /* GFID */
|
put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */
|
||||||
put_bits(&s->pb, 5, s->qscale); /* GQUANT */
|
put_bits(&s->pb, 5, s->qscale); /* GQUANT */
|
||||||
|
//fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif);
|
||||||
return pdif;
|
return pdif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,20 +432,25 @@ static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n)
|
|||||||
RLTable *rl = &rl_inter;
|
RLTable *rl = &rl_inter;
|
||||||
|
|
||||||
if (s->mb_intra) {
|
if (s->mb_intra) {
|
||||||
/* DC coef */
|
/* DC coef */
|
||||||
level = block[0];
|
level = block[0];
|
||||||
/* 255 cannot be represented, so we clamp */
|
/* 255 cannot be represented, so we clamp */
|
||||||
if (level > 254) {
|
if (level > 254) {
|
||||||
level = 254;
|
level = 254;
|
||||||
block[0] = 254;
|
block[0] = 254;
|
||||||
}
|
}
|
||||||
if (level == 128)
|
/* 0 cannot be represented also */
|
||||||
put_bits(&s->pb, 8, 0xff);
|
else if (!level) {
|
||||||
else
|
level = 1;
|
||||||
put_bits(&s->pb, 8, level & 0xff);
|
block[0] = 1;
|
||||||
i = 1;
|
}
|
||||||
|
if (level == 128)
|
||||||
|
put_bits(&s->pb, 8, 0xff);
|
||||||
|
else
|
||||||
|
put_bits(&s->pb, 8, level & 0xff);
|
||||||
|
i = 1;
|
||||||
} else {
|
} else {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AC coefs */
|
/* AC coefs */
|
||||||
@ -1241,8 +1265,8 @@ int h263_decode_picture_header(MpegEncContext *s)
|
|||||||
/* picture header */
|
/* picture header */
|
||||||
if (get_bits(&s->gb, 22) != 0x20)
|
if (get_bits(&s->gb, 22) != 0x20)
|
||||||
return -1;
|
return -1;
|
||||||
skip_bits(&s->gb, 8); /* picture timestamp */
|
s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */
|
||||||
|
|
||||||
if (get_bits1(&s->gb) != 1)
|
if (get_bits1(&s->gb) != 1)
|
||||||
return -1; /* marker */
|
return -1; /* marker */
|
||||||
if (get_bits1(&s->gb) != 0)
|
if (get_bits1(&s->gb) != 0)
|
||||||
|
@ -225,6 +225,11 @@ static int h263_decode_frame(AVCodecContext *avctx,
|
|||||||
pict->linesize[2] = s->linesize / 2;
|
pict->linesize[2] = s->linesize / 2;
|
||||||
|
|
||||||
avctx->quality = s->qscale;
|
avctx->quality = s->qscale;
|
||||||
|
|
||||||
|
/* Return the Picture timestamp as the frame number */
|
||||||
|
/* we substract 1 because it is added on utils.c */
|
||||||
|
avctx->frame_number = s->picture_number - 1;
|
||||||
|
|
||||||
*data_size = sizeof(AVPicture);
|
*data_size = sizeof(AVPicture);
|
||||||
return buf_size;
|
return buf_size;
|
||||||
}
|
}
|
||||||
|
@ -264,6 +264,8 @@ int MPV_encode_init(AVCodecContext *avctx)
|
|||||||
s->gop_size = avctx->gop_size;
|
s->gop_size = avctx->gop_size;
|
||||||
s->rtp_mode = avctx->rtp_mode;
|
s->rtp_mode = avctx->rtp_mode;
|
||||||
s->rtp_payload_size = avctx->rtp_payload_size;
|
s->rtp_payload_size = avctx->rtp_payload_size;
|
||||||
|
if (avctx->rtp_callback)
|
||||||
|
s->rtp_callback = avctx->rtp_callback;
|
||||||
s->avctx = avctx;
|
s->avctx = avctx;
|
||||||
|
|
||||||
if (s->gop_size <= 1) {
|
if (s->gop_size <= 1) {
|
||||||
@ -868,7 +870,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, last_gob;
|
int mb_x, mb_y, wrap, last_gob, pdif = 0;
|
||||||
UINT8 *ptr;
|
UINT8 *ptr;
|
||||||
int i, motion_x, motion_y;
|
int i, motion_x, motion_y;
|
||||||
|
|
||||||
@ -919,7 +921,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
s->mv_dir = MV_DIR_FORWARD;
|
s->mv_dir = MV_DIR_FORWARD;
|
||||||
|
|
||||||
/* Get the GOB height based on picture height */
|
/* Get the GOB height based on picture height */
|
||||||
if (s->out_format == FMT_H263 && s->h263_plus) {
|
if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4) {
|
||||||
if (s->height <= 400)
|
if (s->height <= 400)
|
||||||
s->gob_index = 1;
|
s->gob_index = 1;
|
||||||
else if (s->height <= 800)
|
else if (s->height <= 800)
|
||||||
@ -930,16 +932,17 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
|
|
||||||
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 */
|
/* Put GOB header based on RTP MTU */
|
||||||
if (!mb_y) {
|
/* TODO: Put all this stuff in a separate generic function */
|
||||||
s->ptr_lastgob = s->pb.buf_ptr;
|
if (s->rtp_mode) {
|
||||||
s->ptr_last_mb_line = s->pb.buf_ptr;
|
if (!mb_y) {
|
||||||
} else if (s->out_format == FMT_H263 && s->h263_plus) {
|
s->ptr_lastgob = s->pb.buf;
|
||||||
last_gob = h263_encode_gob_header(s, mb_y);
|
s->ptr_last_mb_line = s->pb.buf;
|
||||||
if (last_gob) {
|
} else if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4 && !(mb_y % s->gob_index)) {
|
||||||
//fprintf(stderr,"\nLast GOB size: %d", last_gob);
|
last_gob = h263_encode_gob_header(s, mb_y);
|
||||||
s->first_gob_line = 1;
|
if (last_gob) {
|
||||||
} else
|
s->first_gob_line = 1;
|
||||||
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++) {
|
||||||
|
|
||||||
@ -1046,14 +1049,18 @@ 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 */
|
/* Obtain average GOB size for RTP */
|
||||||
if (!mb_y)
|
if (s->rtp_mode) {
|
||||||
s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line;
|
if (!mb_y)
|
||||||
else
|
s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line;
|
||||||
s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1;
|
else if (!(mb_y % s->gob_index)) {
|
||||||
//fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y,
|
s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1;
|
||||||
// (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize);
|
s->ptr_last_mb_line = s->pb.buf_ptr;
|
||||||
s->ptr_last_mb_line = s->pb.buf_ptr;
|
}
|
||||||
|
//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->first_gob_line = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->h263_msmpeg4)
|
if (s->h263_msmpeg4)
|
||||||
@ -1061,6 +1068,18 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
|
|
||||||
//if (s->gob_number)
|
//if (s->gob_number)
|
||||||
// fprintf(stderr,"\nNumber of GOB: %d", s->gob_number);
|
// fprintf(stderr,"\nNumber of GOB: %d", s->gob_number);
|
||||||
|
|
||||||
|
/* Send the last GOB if RTP */
|
||||||
|
if (s->rtp_mode) {
|
||||||
|
flush_put_bits(&s->pb);
|
||||||
|
pdif = s->pb.buf_ptr - s->ptr_lastgob;
|
||||||
|
/* Call the RTP callback to send the last GOB */
|
||||||
|
if (s->rtp_callback)
|
||||||
|
s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number);
|
||||||
|
s->ptr_lastgob = s->pb.buf_ptr;
|
||||||
|
//fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dct_quantize_c(MpegEncContext *s,
|
static int dct_quantize_c(MpegEncContext *s,
|
||||||
|
@ -201,8 +201,10 @@ typedef struct MpegEncContext {
|
|||||||
int first_slice;
|
int first_slice;
|
||||||
|
|
||||||
/* RTP specific */
|
/* RTP specific */
|
||||||
|
/* These are explained on avcodec.h */
|
||||||
int rtp_mode;
|
int rtp_mode;
|
||||||
int rtp_payload_size;
|
int rtp_payload_size;
|
||||||
|
void (*rtp_callback)(void *data, int size, int packet_number);
|
||||||
UINT8 *ptr_lastgob;
|
UINT8 *ptr_lastgob;
|
||||||
UINT8 *ptr_last_mb_line;
|
UINT8 *ptr_last_mb_line;
|
||||||
UINT32 mb_line_avgsize;
|
UINT32 mb_line_avgsize;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user