📄 h263enc.c
字号:
/*
* H263 backend for ffmpeg encoder
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include "common.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "h263data.h"
#include "mpeg4data.h"
#define NDEBUG
#include <assert.h>
static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
int n);
static void h263_encode_motion(MpegEncContext * s, int val);
static void h263_pred_motion(MpegEncContext * s, int block, int *px, int *py);
static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
int n);
void h263_picture_header(MpegEncContext * s, int picture_number)
{
int format;
align_put_bits(&s->pb);
put_bits(&s->pb, 22, 0x20);
put_bits(&s->pb, 8, ((s->picture_number * 30) / s->frame_rate) & 0xff);
put_bits(&s->pb, 1, 1); /* marker */
put_bits(&s->pb, 1, 0); /* h263 id */
put_bits(&s->pb, 1, 0); /* split screen off */
put_bits(&s->pb, 1, 0); /* camera off */
put_bits(&s->pb, 1, 0); /* freeze picture release off */
if (s->width == 128 && s->height == 96)
format = 1;
else if (s->width == 176 && s->height == 144)
format = 2;
else if (s->width == 352 && s->height == 288)
format = 3;
else if (s->width == 704 && s->height == 576)
format = 4;
else if (s->width == 1408 && s->height == 1152)
format = 5;
else
abort();
put_bits(&s->pb, 3, format);
put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
put_bits(&s->pb, 1, 0); /* unrestricted motion vector: off */
put_bits(&s->pb, 1, 0); /* SAC: off */
put_bits(&s->pb, 1, 0); /* advanced prediction mode: off */
put_bits(&s->pb, 1, 0); /* not PB frame */
put_bits(&s->pb, 5, s->qscale);
put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */
put_bits(&s->pb, 1, 0); /* no PEI */
}
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;
if (!s->mb_intra) {
/* compute cbp */
cbp = 0;
for (i = 0; i < 6; i++) {
if (s->block_last_index[i] >= 0)
cbp |= 1 << (5 - i);
}
if ((cbp | motion_x | motion_y) == 0) {
/* skip macroblock */
put_bits(&s->pb, 1, 1);
return;
}
put_bits(&s->pb, 1, 0); /* mb coded */
cbpc = cbp & 3;
put_bits(&s->pb,
inter_MCBPC_bits[cbpc],
inter_MCBPC_code[cbpc]);
cbpy = cbp >> 2;
cbpy ^= 0xf;
put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
/* motion vectors: 16x16 mode only now */
h263_pred_motion(s, 0, &pred_x, &pred_y);
h263_encode_motion(s, motion_x - pred_x);
h263_encode_motion(s, motion_y - pred_y);
} else {
/* compute cbp */
cbp = 0;
for (i = 0; i < 6; i++) {
if (s->block_last_index[i] >= 1)
cbp |= 1 << (5 - i);
}
cbpc = cbp & 3;
if (s->pict_type == I_TYPE) {
put_bits(&s->pb,
intra_MCBPC_bits[cbpc],
intra_MCBPC_code[cbpc]);
} else {
put_bits(&s->pb, 1, 0); /* mb coded */
put_bits(&s->pb,
inter_MCBPC_bits[cbpc + 4],
inter_MCBPC_code[cbpc + 4]);
}
if (s->h263_pred) {
/* XXX: currently, we do not try to use ac prediction */
put_bits(&s->pb, 1, 0); /* no ac prediction */
}
cbpy = cbp >> 2;
put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
}
/* encode each block */
if (s->h263_pred) {
for (i = 0; i < 6; i++) {
mpeg4_encode_block(s, block[i], i);
}
} else {
for (i = 0; i < 6; i++) {
h263_encode_block(s, block[i], i);
}
}
}
static inline int mid_pred(int a, int b, int c)
{
int vmin, vmax;
vmin = a;
if (b < vmin)
vmin = b;
if (c < vmin)
vmin = c;
vmax = a;
if (b > vmax)
vmax = b;
if (c > vmax)
vmax = c;
return a + b + c - vmin - vmax;
}
static void h263_pred_motion(MpegEncContext * s, int block, int *px, int *py)
{
int x, y, wrap;
INT16 *A, *B, *C;
x = 2 * s->mb_x + 1 + (block & 1);
y = 2 * s->mb_y + 1 + ((block >> 1) & 1);
wrap = 2 * s->mb_width + 2;
/* special case for first line */
if (y == 1) {
A = s->motion_val[(x-1) + (y) * wrap];
*px = A[0];
*py = A[1];
return;
}
switch(block) {
default:
case 0:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x) + (y-1) * wrap];
C = s->motion_val[(x+2) + (y-1) * wrap];
break;
case 1:
case 2:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x) + (y-1) * wrap];
C = s->motion_val[(x+1) + (y-1) * wrap];
break;
case 3:
A = s->motion_val[(x-1) + (y) * wrap];
B = s->motion_val[(x-1) + (y-1) * wrap];
C = s->motion_val[(x) + (y-1) * wrap];
break;
}
*px = mid_pred(A[0], B[0], C[0]);
*py = mid_pred(A[1], B[1], C[1]);
}
static void h263_encode_motion(MpegEncContext * s, int val)
{
int range, l, m, bit_size, sign, code, bits;
if (val == 0) {
/* zero vector */
code = 0;
put_bits(&s->pb, mvtab[code][1], mvtab[code][0]);
} else {
bit_size = s->f_code - 1;
range = 1 << bit_size;
/* modulo encoding */
l = range * 32;
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);
sign = 0;
} else {
val = -val;
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
sign = 1;
}
put_bits(&s->pb, mvtab[code][1] + 1, (mvtab[code][0] << 1) | sign);
if (bit_size > 0) {
put_bits(&s->pb, bit_size, bits);
}
}
}
#define CODE_INTRA(run, level, last) \
{ \
if (last == 0) { \
if (run == 0 && level < 28) { \
code = coeff_tab4[level - 1][0]; \
len = coeff_tab4[level - 1][1]; \
} else if (run == 1 && level < 11) { \
code = coeff_tab5[level - 1][0]; \
len = coeff_tab5[level - 1][1]; \
} else if (run > 1 && run < 10 && level < 6) { \
code = coeff_tab6[run - 2][level - 1][0]; \
len = coeff_tab6[run - 2][level - 1][1]; \
} else if (run > 9 && run < 15 && level == 1) { \
code = coeff_tab7[run - 10][0]; \
len = coeff_tab7[run - 10][1]; \
} \
} else { \
if (run == 0 && level < 9) { \
code = coeff_tab8[level - 1][0]; \
len = coeff_tab8[level - 1][1]; \
} else if (run > 0 && run < 7 && level < 4) { \
code = coeff_tab9[run - 1][level - 1][0]; \
len = coeff_tab9[run - 1][level - 1][1]; \
} else if (run > 6 && run < 21 && level == 1) { \
code = coeff_tab10[run - 7][0]; \
len = coeff_tab10[run - 7][1]; \
} \
} \
}
#define CODE_INTER(run, level, last) \
{ \
if (last == 0) { \
if (run < 2 && level < 13) { \
len = coeff_tab0[run][level - 1][1]; \
code = coeff_tab0[run][level - 1][0]; \
} else if (run >= 2 && run < 27 && level < 5) { \
len = coeff_tab1[run - 2][level - 1][1]; \
code = coeff_tab1[run - 2][level - 1][0]; \
} \
} else { \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -