mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
mpeg1 slice encoding support
Originally committed as revision 1720 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
5acaa5e1df
commit
9b8709d135
@ -275,12 +275,18 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void encode_mb_skip_run(MpegEncContext *s, int run){
|
||||
while (run >= 33) {
|
||||
put_bits(&s->pb, 11, 0x008);
|
||||
run -= 33;
|
||||
}
|
||||
put_bits(&s->pb, mbAddrIncrTable[run][1],
|
||||
mbAddrIncrTable[run][0]);
|
||||
}
|
||||
|
||||
/* insert a fake P picture */
|
||||
static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
|
||||
{
|
||||
unsigned int mb_incr;
|
||||
|
||||
/* mpeg1 picture header */
|
||||
put_header(s, PICTURE_START_CODE);
|
||||
/* temporal reference */
|
||||
@ -299,9 +305,7 @@ static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
|
||||
put_bits(&s->pb, 5, 1); /* quantizer scale */
|
||||
put_bits(&s->pb, 1, 0); /* slice extra information */
|
||||
|
||||
mb_incr = 1;
|
||||
put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
|
||||
mbAddrIncrTable[mb_incr - 1][0]);
|
||||
encode_mb_skip_run(s, 0);
|
||||
|
||||
/* empty macroblock */
|
||||
put_bits(&s->pb, 3, 1); /* motion only */
|
||||
@ -311,13 +315,7 @@ static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
|
||||
put_bits(&s->pb, 1, 1);
|
||||
|
||||
/* output a number of empty slice */
|
||||
mb_incr = s->mb_width * s->mb_height - 1;
|
||||
while (mb_incr > 33) {
|
||||
put_bits(&s->pb, 11, 0x008);
|
||||
mb_incr -= 33;
|
||||
}
|
||||
put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
|
||||
mbAddrIncrTable[mb_incr - 1][0]);
|
||||
encode_mb_skip_run(s, s->mb_width * s->mb_height - 2);
|
||||
|
||||
/* empty macroblock */
|
||||
put_bits(&s->pb, 3, 1); /* motion only */
|
||||
@ -334,6 +332,20 @@ static void common_init(MpegEncContext *s)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ENCODERS
|
||||
|
||||
void ff_mpeg1_encode_slice_header(MpegEncContext *s){
|
||||
put_header(s, SLICE_MIN_START_CODE + s->mb_y);
|
||||
put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
|
||||
put_bits(&s->pb, 1, 0); /* slice extra information */
|
||||
}
|
||||
|
||||
void ff_mpeg1_clean_buffers(MpegEncContext *s){
|
||||
s->last_dc[0] = 1 << (7 + s->intra_dc_precision);
|
||||
s->last_dc[1] = s->last_dc[0];
|
||||
s->last_dc[2] = s->last_dc[0];
|
||||
memset(s->last_mv, 0, sizeof(s->last_mv));
|
||||
}
|
||||
|
||||
void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
|
||||
{
|
||||
mpeg1_encode_sequence_header(s);
|
||||
@ -364,20 +376,18 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
|
||||
|
||||
put_bits(&s->pb, 1, 0); /* extra bit picture */
|
||||
|
||||
/* only one slice */
|
||||
put_header(s, SLICE_MIN_START_CODE);
|
||||
put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
|
||||
put_bits(&s->pb, 1, 0); /* slice extra information */
|
||||
s->mb_y=0;
|
||||
ff_mpeg1_encode_slice_header(s);
|
||||
}
|
||||
|
||||
void mpeg1_encode_mb(MpegEncContext *s,
|
||||
DCTELEM block[6][64],
|
||||
int motion_x, int motion_y)
|
||||
{
|
||||
int mb_incr, i, cbp, mb_x, mb_y;
|
||||
|
||||
mb_x = s->mb_x;
|
||||
mb_y = s->mb_y;
|
||||
int i, cbp;
|
||||
const int mb_x = s->mb_x;
|
||||
const int mb_y = s->mb_y;
|
||||
const int first_mb= mb_x == s->resync_mb_x && mb_y == s->resync_mb_y;
|
||||
|
||||
/* compute cbp */
|
||||
cbp = 0;
|
||||
@ -386,26 +396,22 @@ void mpeg1_encode_mb(MpegEncContext *s,
|
||||
cbp |= 1 << (5 - i);
|
||||
}
|
||||
|
||||
// RAL: Skipped macroblocks for B frames...
|
||||
if (cbp == 0 && (!((mb_x | mb_y) == 0 || (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1))) &&
|
||||
if (cbp == 0 && !first_mb && (mb_x != s->mb_width - 1 || mb_y != s->mb_height - 1) &&
|
||||
((s->pict_type == P_TYPE && (motion_x | motion_y) == 0) ||
|
||||
(s->pict_type == B_TYPE && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) ? ((s->mv[0][0][0] - s->last_mv[0][0][0])|(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) |
|
||||
((s->mv_dir & MV_DIR_BACKWARD) ? ((s->mv[1][0][0] - s->last_mv[1][0][0])|(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) {
|
||||
s->mb_incr++;
|
||||
s->mb_skip_run++;
|
||||
s->qscale -= s->dquant;
|
||||
s->skip_count++;
|
||||
s->misc_bits++;
|
||||
s->last_bits++;
|
||||
} else {
|
||||
/* output mb incr */
|
||||
mb_incr = s->mb_incr;
|
||||
|
||||
while (mb_incr > 33) {
|
||||
put_bits(&s->pb, 11, 0x008);
|
||||
mb_incr -= 33;
|
||||
if(first_mb){
|
||||
assert(s->mb_skip_run == 0);
|
||||
encode_mb_skip_run(s, s->mb_x);
|
||||
}else{
|
||||
encode_mb_skip_run(s, s->mb_skip_run);
|
||||
}
|
||||
put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
|
||||
mbAddrIncrTable[mb_incr - 1][0]);
|
||||
|
||||
if (s->pict_type == I_TYPE) {
|
||||
if(s->dquant && cbp){
|
||||
@ -553,7 +559,7 @@ void mpeg1_encode_mb(MpegEncContext *s,
|
||||
mpeg1_encode_block(s, block[i], i);
|
||||
}
|
||||
}
|
||||
s->mb_incr = 1;
|
||||
s->mb_skip_run = 0;
|
||||
if(s->mb_intra)
|
||||
s->i_tex_bits+= get_bits_diff(s);
|
||||
else
|
||||
@ -888,7 +894,7 @@ static int mpeg_decode_mb(MpegEncContext *s,
|
||||
|
||||
assert(s->mb_skiped==0);
|
||||
|
||||
if (--s->mb_incr != 0) {
|
||||
if (s->mb_skip_run-- != 0) {
|
||||
/* skip mb */
|
||||
s->mb_intra = 0;
|
||||
for(i=0;i<6;i++)
|
||||
@ -1795,10 +1801,8 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
|
||||
fprintf(stderr, "slice below image (%d >= %d)\n", start_code, s->mb_height);
|
||||
return DECODE_SLICE_ERROR;
|
||||
}
|
||||
s->last_dc[0] = 1 << (7 + s->intra_dc_precision);
|
||||
s->last_dc[1] = s->last_dc[0];
|
||||
s->last_dc[2] = s->last_dc[0];
|
||||
memset(s->last_mv, 0, sizeof(s->last_mv));
|
||||
|
||||
ff_mpeg1_clean_buffers(s);
|
||||
|
||||
/* start frame decoding */
|
||||
if (s->first_slice) {
|
||||
@ -1863,8 +1867,9 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s->mb_y = start_code;
|
||||
s->mb_incr= 1;
|
||||
s->mb_skip_run= 0;
|
||||
|
||||
for(;;) {
|
||||
s->dsp.clear_blocks(s->block[0]);
|
||||
@ -1892,20 +1897,20 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
|
||||
PRINT_QP("%2d", s->qscale);
|
||||
|
||||
/* skip mb handling */
|
||||
if (s->mb_incr == 0) {
|
||||
if (s->mb_skip_run == -1) {
|
||||
/* read again increment */
|
||||
s->mb_incr = 1;
|
||||
s->mb_skip_run = 0;
|
||||
for(;;) {
|
||||
int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2);
|
||||
if (code < 0)
|
||||
goto eos; /* error = end of slice */
|
||||
if (code >= 33) {
|
||||
if (code == 33) {
|
||||
s->mb_incr += 33;
|
||||
s->mb_skip_run += 33;
|
||||
}
|
||||
/* otherwise, stuffing, nothing to do */
|
||||
} else {
|
||||
s->mb_incr += code;
|
||||
s->mb_skip_run += code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2684,7 +2684,7 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext
|
||||
memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop?
|
||||
|
||||
/* mpeg1 */
|
||||
d->mb_incr= s->mb_incr;
|
||||
d->mb_skip_run= s->mb_skip_run;
|
||||
for(i=0; i<3; i++)
|
||||
d->last_dc[i]= s->last_dc[i];
|
||||
|
||||
@ -2710,7 +2710,7 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *
|
||||
memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop?
|
||||
|
||||
/* mpeg1 */
|
||||
d->mb_incr= s->mb_incr;
|
||||
d->mb_skip_run= s->mb_skip_run;
|
||||
for(i=0; i<3; i++)
|
||||
d->last_dc[i]= s->last_dc[i];
|
||||
|
||||
@ -3023,7 +3023,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
||||
|
||||
s->current_picture_ptr->error[i] = 0;
|
||||
}
|
||||
s->mb_incr = 1;
|
||||
s->mb_skip_run = 0;
|
||||
s->last_mv[0][0][0] = 0;
|
||||
s->last_mv[0][0][1] = 0;
|
||||
s->last_mv[1][0][0] = 0;
|
||||
@ -3094,6 +3094,13 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
||||
ff_mpeg4_clean_buffers(s);
|
||||
is_gob_start=1;
|
||||
}
|
||||
}else if(s->codec_id==CODEC_ID_MPEG1VIDEO){
|
||||
if( current_packet_size >= s->rtp_payload_size
|
||||
&& s->mb_y + s->mb_x>0 && s->mb_skip_run==0){
|
||||
ff_mpeg1_encode_slice_header(s);
|
||||
ff_mpeg1_clean_buffers(s);
|
||||
is_gob_start=1;
|
||||
}
|
||||
}else{
|
||||
if(current_packet_size >= s->rtp_payload_size
|
||||
&& s->mb_x==0 && s->mb_y>0 && s->mb_y%s->gob_index==0){
|
||||
|
@ -338,7 +338,7 @@ typedef struct MpegEncContext {
|
||||
|
||||
/* macroblock layer */
|
||||
int mb_x, mb_y;
|
||||
int mb_incr;
|
||||
int mb_skip_run;
|
||||
int mb_intra;
|
||||
uint8_t *mb_type; ///< Table for MB type
|
||||
#define MB_TYPE_INTRA 0x01
|
||||
@ -685,6 +685,8 @@ void mpeg1_encode_mb(MpegEncContext *s,
|
||||
DCTELEM block[6][64],
|
||||
int motion_x, int motion_y);
|
||||
void ff_mpeg1_encode_init(MpegEncContext *s);
|
||||
void ff_mpeg1_encode_slice_header(MpegEncContext *s);
|
||||
void ff_mpeg1_clean_buffers(MpegEncContext *s);
|
||||
|
||||
|
||||
/** RLTable. */
|
||||
|
Loading…
Reference in New Issue
Block a user