📄 mpegvideo.c
字号:
mb_incr -= 33;
}
put_bits(&s->pb, mbAddrIncrTable[mb_incr][1],
mbAddrIncrTable[mb_incr][0]);
/* empty macroblock */
put_bits(&s->pb, 3, 1); /* motion only */
/* zero motion x & y */
put_bits(&s->pb, 1, 1);
put_bits(&s->pb, 1, 1);
}
static int dct_quantize(MpegEncContext *s, DCTELEM *block, int n, int qscale);
static void encode_block(MpegEncContext *s,
DCTELEM *block,
int component);
static void dct_unquantize(MpegEncContext *s, DCTELEM *block, int n, int qscale);
static void mpeg1_encode_mb(MpegEncContext *s, int mb_x, int mb_y,
DCTELEM block[6][64],
int motion_x, int motion_y);
static void encode_picture(MpegEncContext *s, int picture_number)
{
int mb_x, mb_y;
UINT8 *ptr;
DCTELEM block[6][64];
int i, motion_x, motion_y;
s->picture_number = picture_number;
#if 1
s->qscale = rate_estimate_qscale(s);
#else
s->qscale = 10;
#endif
/* precompute matrix */
if (s->out_format == FMT_MJPEG) {
/* for mjpeg, we do include qscale in the matrix */
s->init_intra_matrix[0] = default_intra_matrix[0];
for(i=1;i<64;i++)
s->init_intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3;
convert_matrix(s->intra_matrix, s->init_intra_matrix, 8);
} else {
convert_matrix(s->intra_matrix, default_intra_matrix, s->qscale);
convert_matrix(s->non_intra_matrix, default_non_intra_matrix, s->qscale);
}
switch(s->out_format) {
case FMT_MJPEG:
mjpeg_picture_header(s);
break;
case FMT_H263:
if (s->h263_pred)
mpeg4_encode_picture_header(s, picture_number);
else if (s->h263_rv10)
rv10_encode_picture_header(s, picture_number);
else
h263_picture_header(s, picture_number);
break;
case FMT_MPEG1:
/* mpeg1 picture header */
put_header(s, PICTURE_START_CODE);
/* temporal reference */
put_bits(&s->pb, 10, (s->fake_picture_number -
s->gop_picture_number) & 0x3ff);
put_bits(&s->pb, 3, s->pict_type);
put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */
if (s->pict_type == P_TYPE) {
put_bits(&s->pb, 1, 0); /* half pel coordinates */
put_bits(&s->pb, 3, s->f_code); /* forward_f_code */
}
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 */
break;
}
/* init last dc values */
/* note: quant matrix value (8) is implied here */
s->last_dc[0] = 128;
s->last_dc[1] = 128;
s->last_dc[2] = 128;
s->mb_incr = 1;
s->last_motion_x = 0;
s->last_motion_y = 0;
for(mb_y=0; mb_y < s->mb_height; mb_y++) {
for(mb_x=0; mb_x < s->mb_width; mb_x++) {
s->mb_x = mb_x;
s->mb_y = mb_y;
/* compute motion vector and macro block type (intra or non intra) */
motion_x = 0;
motion_y = 0;
if (s->pict_type == P_TYPE) {
s->mb_intra = estimate_motion(s, mb_x, mb_y,
&motion_x,
&motion_y);
} else {
s->mb_intra = 1;
}
/* get the pixels */
ptr = s->new_picture[0] + (mb_y * 16 * s->width) + mb_x * 16;
get_pixels(block[0], ptr, s->width);
get_pixels(block[1], ptr + 8, s->width);
get_pixels(block[2], ptr + 8 * s->width, s->width);
get_pixels(block[3], ptr + 8 * s->width + 8, s->width);
ptr = s->new_picture[1] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8;
get_pixels(block[4],ptr, s->width >> 1);
ptr = s->new_picture[2] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8;
get_pixels(block[5],ptr, s->width >> 1);
/* subtract previous frame if non intra */
if (!s->mb_intra) {
int dxy, offset, mx, my;
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
ptr = s->last_picture[0] +
((mb_y * 16 + (motion_y >> 1)) * s->width) +
(mb_x * 16 + (motion_x >> 1));
sub_pixels_2(block[0], ptr, s->width, dxy);
sub_pixels_2(block[1], ptr + 8, s->width, dxy);
sub_pixels_2(block[2], ptr + s->width * 8, s->width, dxy);
sub_pixels_2(block[3], ptr + 8 + s->width * 8, s->width ,dxy);
if (s->out_format == FMT_H263) {
/* special rounding for h263 */
dxy = 0;
if ((motion_x & 3) != 0)
dxy |= 1;
if ((motion_y & 3) != 0)
dxy |= 2;
mx = motion_x >> 2;
my = motion_y >> 2;
} else {
mx = motion_x / 2;
my = motion_y / 2;
dxy = ((my & 1) << 1) | (mx & 1);
mx >>= 1;
my >>= 1;
}
offset = ((mb_y * 8 + my) * (s->width >> 1)) + (mb_x * 8 + mx);
ptr = s->last_picture[1] + offset;
sub_pixels_2(block[4], ptr, s->width >> 1, dxy);
ptr = s->last_picture[2] + offset;
sub_pixels_2(block[5], ptr, s->width >> 1, dxy);
}
/* DCT & quantize */
if (s->h263_pred) {
h263_dc_scale(s);
} else {
/* default quantization values */
s->y_dc_scale = 8;
s->c_dc_scale = 8;
}
for(i=0;i<6;i++) {
int last_index;
last_index = dct_quantize(s, block[i], i, s->qscale);
s->block_last_index[i] = last_index;
}
/* huffman encode */
switch(s->out_format) {
case FMT_MPEG1:
mpeg1_encode_mb(s, mb_x, mb_y, block, motion_x, motion_y);
break;
case FMT_H263:
h263_encode_mb(s, block, motion_x, motion_y);
break;
case FMT_MJPEG:
mjpeg_encode_mb(s, block);
break;
}
/* update DC predictors for P macroblocks */
if (!s->mb_intra) {
if (s->h263_pred) {
int wrap, x, y;
wrap = 2 * s->mb_width + 2;
x = 2 * mb_x + 1;
y = 2 * mb_y + 1;
s->dc_val[0][(x) + (y) * wrap] = 1024;
s->dc_val[0][(x + 1) + (y) * wrap] = 1024;
s->dc_val[0][(x) + (y + 1) * wrap] = 1024;
s->dc_val[0][(x + 1) + (y + 1) * wrap] = 1024;
wrap = s->mb_width + 2;
x = mb_x + 1;
y = mb_y + 1;
s->dc_val[1][(x) + (y) * wrap] = 1024;
s->dc_val[2][(x) + (y) * wrap] = 1024;
} else {
s->last_dc[0] = 128;
s->last_dc[1] = 128;
s->last_dc[2] = 128;
}
}
/* update motion predictor */
if (s->out_format == FMT_H263) {
int x, y, wrap;
x = 2 * mb_x + 1;
y = 2 * mb_y + 1;
wrap = 2 * s->mb_width + 2;
s->motion_val[(x) + (y) * wrap][0] = motion_x;
s->motion_val[(x) + (y) * wrap][1] = motion_y;
s->motion_val[(x + 1) + (y) * wrap][0] = motion_x;
s->motion_val[(x + 1) + (y) * wrap][1] = motion_y;
s->motion_val[(x) + (y + 1) * wrap][0] = motion_x;
s->motion_val[(x) + (y + 1) * wrap][1] = motion_y;
s->motion_val[(x + 1) + (y + 1) * wrap][0] = motion_x;
s->motion_val[(x + 1) + (y + 1) * wrap][1] = motion_y;
} else {
s->last_motion_x = motion_x;
s->last_motion_y = motion_y;
}
/* decompress blocks so that we keep the state of the decoder */
if (!s->intra_only) {
for(i=0;i<6;i++) {
if (s->block_last_index[i] >= 0) {
dct_unquantize(s, block[i], i, s->qscale);
j_rev_dct (block[i]);
}
}
if (!s->mb_intra) {
int dxy, offset, mx, my;
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
ptr = s->last_picture[0] +
((mb_y * 16 + (motion_y >> 1)) * s->width) +
(mb_x * 16 + (motion_x >> 1));
add_pixels_2(block[0], ptr, s->width, dxy);
add_pixels_2(block[1], ptr + 8, s->width, dxy);
add_pixels_2(block[2], ptr + s->width * 8, s->width, dxy);
add_pixels_2(block[3], ptr + 8 + s->width * 8, s->width, dxy);
if (s->out_format == FMT_H263) {
/* special rounding for h263 */
dxy = 0;
if ((motion_x & 3) != 0)
dxy |= 1;
if ((motion_y & 3) != 0)
dxy |= 2;
mx = motion_x >> 2;
my = motion_y >> 2;
} else {
mx = motion_x / 2;
my = motion_y / 2;
dxy = ((my & 1) << 1) | (mx & 1);
mx >>= 1;
my >>= 1;
}
offset = ((mb_y * 8 + my) * (s->width >> 1)) + (mb_x * 8 + mx);
ptr = s->last_picture[1] + offset;
add_pixels_2(block[4], ptr, s->width >> 1, dxy);
ptr = s->last_picture[2] + offset;
add_pixels_2(block[5], ptr, s->width >> 1, dxy);
}
/* write the pixels */
ptr = s->current_picture[0] + (mb_y * 16 * s->width) + mb_x * 16;
put_pixels(block[0], ptr, s->width);
put_pixels(block[1], ptr + 8, s->width);
put_pixels(block[2], ptr + 8 * s->width, s->width);
put_pixels(block[3], ptr + 8 * s->width + 8, s->width);
ptr = s->current_picture[1] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8;
put_pixels(block[4],ptr, s->width >> 1);
ptr = s->current_picture[2] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8;
put_pixels(block[5],ptr, s->width >> 1);
}
}
}
}
static void mpeg1_encode_motion(MpegEncContext *s, int val)
{
int code, bit_size, l, m, bits, range;
if (val == 0) {
/* zero vector */
code = 0;
put_bits(&s->pb,
mbMotionVectorTable[code + 16][1],
mbMotionVectorTable[code + 16][0]);
} else {
bit_size = s->f_code - 1;
range = 1 << bit_size;
/* modulo encoding */
l = 16 * range;
m = 2 * l;
if (val < -l) {
val += m;
} else if (val >= l) {
val -= m;
}
if (val >= 0) {
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
} else {
val = -val;
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
code = -code;
}
put_bits(&s->pb,
mbMotionVectorTable[code + 16][1],
mbMotionVectorTable[code + 16][0]);
if (bit_size > 0) {
put_bits(&s->pb, bit_size, bits);
}
}
}
static void mpeg1_encode_mb(MpegEncContext *s, int mb_x, int mb_y,
DCTELEM block[6][64],
int motion_x, int motion_y)
{
int mb_incr, i, cbp;
/* compute cbp */
cbp = 0;
for(i=0;i<6;i++) {
if (s->block_last_index[i] >= 0)
cbp |= 1 << (5 - i);
}
/* skip macroblock, except if first or last macroblock of a slice */
if ((cbp | motion_x | motion_y) == 0 &&
(!((mb_x | mb_y) == 0 ||
(mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1)))) {
s->mb_incr++;
} else {
/* output mb incr */
mb_incr = s->mb_incr;
while (mb_incr > 33) {
put_bits(&s->pb, 11, 0x008);
mb_incr -= 33;
}
put_bits(&s->pb, mbAddrIncrTable[mb_incr][1],
mbAddrIncrTable[mb_incr][0]);
if (s->pict_type == I_TYPE) {
put_bits(&s->pb, 1, 1); /* macroblock_type : macroblock_quant = 0 */
} else {
if (s->mb_intra) {
put_bits(&s->pb, 5, 0x03);
} else {
if (cbp != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -