summaryrefslogtreecommitdiff
path: root/src/libffmpeg/libavcodec/h263.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libffmpeg/libavcodec/h263.c')
-rw-r--r--src/libffmpeg/libavcodec/h263.c353
1 files changed, 281 insertions, 72 deletions
diff --git a/src/libffmpeg/libavcodec/h263.c b/src/libffmpeg/libavcodec/h263.c
index 29e6ab191..da694411f 100644
--- a/src/libffmpeg/libavcodec/h263.c
+++ b/src/libffmpeg/libavcodec/h263.c
@@ -1,7 +1,7 @@
/*
* H263/MPEG4 backend for ffmpeg encoder and decoder
* Copyright (c) 2000,2001 Gerard Lantau.
- * H263+ support for custom picture format.
+ * H263+ support.
* Copyright (c) 2001 Juan J. Sierralta P.
*
* This program is free software; you can redistribute it and/or modify
@@ -28,9 +28,11 @@
static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
int n);
static void h263_encode_motion(MpegEncContext * s, int val);
+static void h263p_encode_umotion(MpegEncContext * s, int val);
static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
int n);
static int h263_decode_motion(MpegEncContext * s, int pred);
+static int h263p_decode_umotion(MpegEncContext * s, int pred);
static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded);
static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
@@ -57,7 +59,7 @@ int h263_get_picture_format(int width, int height)
void h263_encode_picture_header(MpegEncContext * s, int picture_number)
{
- int format, umvplus;
+ int format;
align_put_bits(&s->pb);
put_bits(&s->pb, 22, 0x20);
@@ -69,10 +71,10 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
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 */
-
+
+ format = h263_get_picture_format(s->width, s->height);
if (!s->h263_plus) {
/* H.263v1 */
- format = h263_get_picture_format(s->width, s->height);
put_bits(&s->pb, 3, format);
put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
/* By now UMV IS DISABLED ON H.263v1, since the restrictions
@@ -89,10 +91,14 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* H.263 Plus PTYPE */
put_bits(&s->pb, 3, 7);
put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */
- put_bits(&s->pb,3,6); /* Custom Source Format */
+ if (format == 7)
+ put_bits(&s->pb,3,6); /* Custom Source Format */
+ else
+ put_bits(&s->pb, 3, format);
+
put_bits(&s->pb,1,0); /* Custom PCF: off */
- umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;
- put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */
+ s->umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;
+ put_bits(&s->pb, 1, s->umvplus); /* Unrestricted Motion Vector */
put_bits(&s->pb,1,0); /* SAC: off */
put_bits(&s->pb,1,0); /* Advanced Prediction Mode: off */
put_bits(&s->pb,1,0); /* Advanced Intra Coding: off */
@@ -116,14 +122,17 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* This should be here if PLUSPTYPE */
put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */
- /* Custom Picture Format (CPFMT) */
+ if (format == 7) {
+ /* Custom Picture Format (CPFMT) */
- put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */
- put_bits(&s->pb,9,(s->width >> 2) - 1);
- put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
- put_bits(&s->pb,9,(s->height >> 2));
+ put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */
+ put_bits(&s->pb,9,(s->width >> 2) - 1);
+ put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
+ put_bits(&s->pb,9,(s->height >> 2));
+ }
+
/* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
- if (umvplus)
+ if (s->umvplus)
put_bits(&s->pb,1,1); /* Limited according tables of Annex D */
put_bits(&s->pb, 5, s->qscale);
}
@@ -131,40 +140,82 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
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,
DCTELEM block[6][64],
int motion_x, int motion_y)
{
int cbpc, cbpy, i, cbp, pred_x, pred_y;
-
+
// printf("**mb x=%d y=%d\n", s->mb_x, s->mb_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 {
+ 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);
+
+ if (!s->umvplus) {
+ h263_encode_motion(s, motion_x - pred_x);
+ h263_encode_motion(s, motion_y - pred_y);
+ }
+ else {
+ h263p_encode_umotion(s, motion_x - pred_x);
+ h263p_encode_umotion(s, motion_y - pred_y);
+ if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1))
+ /* To prevent Start Code emulation */
+ put_bits(&s->pb,1,1);
+ }
+ } else {
/* compute cbp */
cbp = 0;
for (i = 0; i < 6; i++) {
@@ -234,7 +285,7 @@ INT16 *h263_pred_motion(MpegEncContext * s, int block,
mot_val = s->motion_val[(x) + (y) * wrap];
/* special case for first line */
- if (y == 1 || s->first_slice_line) {
+ if (y == 1 || s->first_slice_line || s->first_gob_line) {
A = s->motion_val[(x-1) + (y) * wrap];
*px = A[0];
*py = A[1];
@@ -305,6 +356,45 @@ static void h263_encode_motion(MpegEncContext * s, int val)
}
}
+/* Encode MV differences on H.263+ with Unrestricted MV mode */
+static void h263p_encode_umotion(MpegEncContext * s, int val)
+{
+ short sval = 0;
+ short i = 0;
+ short n_bits = 0;
+ short temp_val;
+ int code = 0;
+ int tcode;
+
+ if ( val == 0)
+ put_bits(&s->pb, 1, 1);
+ else if (val == 1)
+ put_bits(&s->pb, 3, 0);
+ else if (val == -1)
+ put_bits(&s->pb, 3, 2);
+ else {
+
+ sval = ((val < 0) ? (short)(-val):(short)val);
+ temp_val = sval;
+
+ while (temp_val != 0) {
+ temp_val = temp_val >> 1;
+ n_bits++;
+ }
+
+ i = n_bits - 1;
+ while (i > 0) {
+ tcode = (sval & (1 << (i-1))) >> (i-1);
+ tcode = (tcode << 1) | 1;
+ code = (code << 2) | tcode;
+ i--;
+ }
+ code = ((code << 1) | (val < 0)) << 1;
+ put_bits(&s->pb, (2*n_bits)+1, code);
+ //printf("\nVal = %d\tCode = %d", sval, code);
+ }
+}
+
void h263_encode_init_vlc(MpegEncContext *s)
{
static int done = 0;
@@ -464,7 +554,7 @@ static int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *di
return pred;
}
-void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
+void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
int dir)
{
int x, y, wrap, i;
@@ -489,22 +579,22 @@ void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
/* left prediction */
ac_val -= 16;
for(i=1;i<8;i++) {
- block[i*8] += ac_val[i];
+ block[block_permute_op(i*8)] += ac_val[i];
}
} else {
/* top prediction */
ac_val -= 16 * wrap;
for(i=1;i<8;i++) {
- block[i] += ac_val[i + 8];
+ block[block_permute_op(i)] += ac_val[i + 8];
}
}
}
/* left copy */
for(i=1;i<8;i++)
- ac_val1[i] = block[i * 8];
+ ac_val1[i] = block[block_permute_op(i * 8)];
/* top copy */
for(i=1;i<8;i++)
- ac_val1[8 + i] = block[i];
+ ac_val1[8 + i] = block[block_permute_op(i)];
}
static inline void mpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr)
@@ -693,7 +783,7 @@ void h263_decode_init_vlc(MpegEncContext *s)
init_vlc(&intra_MCBPC_vlc, 6, 8,
intra_MCBPC_bits, 1, 1,
intra_MCBPC_code, 1, 1);
- init_vlc(&inter_MCBPC_vlc, 9, 20,
+ init_vlc(&inter_MCBPC_vlc, 9, 25,
inter_MCBPC_bits, 1, 1,
inter_MCBPC_code, 1, 1);
init_vlc(&cbpy_vlc, 6, 16,
@@ -715,13 +805,38 @@ void h263_decode_init_vlc(MpegEncContext *s)
}
}
+int h263_decode_gob_header(MpegEncContext *s)
+{
+ unsigned int val, gfid;
+
+ /* Check for GOB Start Code */
+ val = show_bits(&s->gb, 16);
+ if (val == 0) {
+ /* We have a GBSC probably with GSTUFF */
+ skip_bits(&s->gb, 16); /* Drop the zeros */
+ while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
+#ifdef DEBUG
+ fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+#endif
+ s->gob_number = get_bits(&s->gb, 5); /* GN */
+ gfid = get_bits(&s->gb, 2); /* GFID */
+ s->qscale = get_bits(&s->gb, 5); /* GQUANT */
+#ifdef DEBUG
+ fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale);
+#endif
+ return 1;
+ }
+ return 0;
+
+}
+
int h263_decode_mb(MpegEncContext *s,
DCTELEM block[6][64])
{
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 (get_bits1(&s->gb)) {
/* skip mb */
@@ -736,8 +851,14 @@ int h263_decode_mb(MpegEncContext *s,
return 0;
}
cbpc = get_vlc(&s->gb, &inter_MCBPC_vlc);
+ //fprintf(stderr, "\tCBPC: %d", cbpc);
if (cbpc < 0)
return -1;
+ if (cbpc > 20)
+ cbpc+=3;
+ else if (cbpc == 20)
+ fprintf(stderr, "Stuffing !");
+
dquant = cbpc & 8;
s->mb_intra = ((cbpc & 4) != 0);
} else {
@@ -763,33 +884,55 @@ int h263_decode_mb(MpegEncContext *s,
/* 16x16 motion prediction */
s->mv_type = MV_TYPE_16X16;
h263_pred_motion(s, 0, &pred_x, &pred_y);
- mx = h263_decode_motion(s, pred_x);
+ if (s->umvplus_dec)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x);
if (mx >= 0xffff)
return -1;
- my = h263_decode_motion(s, pred_y);
+
+ if (s->umvplus_dec)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = h263_decode_motion(s, pred_y);
if (my >= 0xffff)
return -1;
s->mv[0][0][0] = mx;
s->mv[0][0][1] = my;
+ /*fprintf(stderr, "\n MB %d", (s->mb_y * s->mb_width) + s->mb_x);
+ fprintf(stderr, "\n\tmvx: %d\t\tpredx: %d", mx, pred_x);
+ fprintf(stderr, "\n\tmvy: %d\t\tpredy: %d", my, pred_y);*/
+ if (s->umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1)
+ skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */
+
} else {
s->mv_type = MV_TYPE_8X8;
for(i=0;i<4;i++) {
mot_val = h263_pred_motion(s, i, &pred_x, &pred_y);
- mx = h263_decode_motion(s, pred_x);
+ if (s->umvplus_dec)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x);
if (mx >= 0xffff)
return -1;
- my = h263_decode_motion(s, pred_y);
+
+ if (s->umvplus_dec)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = h263_decode_motion(s, pred_y);
if (my >= 0xffff)
return -1;
s->mv[0][i][0] = mx;
s->mv[0][i][1] = my;
+ if (s->umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1)
+ skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */
mot_val[0] = mx;
mot_val[1] = my;
}
}
} else {
s->ac_pred = 0;
- if (s->h263_pred) {
+ if (s->h263_pred) {
s->ac_pred = get_bits1(&s->gb);
}
cbpy = get_vlc(&s->gb, &cbpy_vlc);
@@ -853,10 +996,37 @@ static int h263_decode_motion(MpegEncContext * s, int pred)
val += 64;
if (pred > 32 && val > 63)
val -= 64;
+
}
return val;
}
+/* Decodes RVLC of H.263+ UMV */
+static int h263p_decode_umotion(MpegEncContext * s, int pred)
+{
+ int code = 0, sign;
+
+ if (get_bits1(&s->gb)) /* Motion difference = 0 */
+ return pred;
+
+ code = 2 + get_bits1(&s->gb);
+
+ while (get_bits1(&s->gb))
+ {
+ code <<= 1;
+ code += get_bits1(&s->gb);
+ }
+ sign = code & 1;
+ code >>= 1;
+
+ code = (sign) ? (pred - code) : (pred + code);
+#ifdef DEBUG
+ fprintf(stderr,"H.263+ UMV Motion = %d\n", code);
+#endif
+ return code;
+
+}
+
static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded)
{
@@ -1081,16 +1251,21 @@ int h263_decode_picture_header(MpegEncContext *s)
skip_bits1(&s->gb); /* camera off */
skip_bits1(&s->gb); /* freeze picture release off */
+ /* Reset GOB number */
+ s->gob_number = 0;
+
format = get_bits(&s->gb, 3);
- if (format != 7) {
+ if (format != 7 && format != 6) {
s->h263_plus = 0;
/* H.263v1 */
width = h263_format[format][0];
height = h263_format[format][1];
if (!width)
return -1;
-
+
+ s->width = width;
+ s->height = height;
s->pict_type = I_TYPE + get_bits1(&s->gb);
s->unrestricted_mv = get_bits1(&s->gb);
@@ -1098,33 +1273,68 @@ int h263_decode_picture_header(MpegEncContext *s)
if (get_bits1(&s->gb) != 0)
return -1; /* SAC: off */
- if (get_bits1(&s->gb) != 0)
- return -1; /* advanced prediction mode: off */
+ if (get_bits1(&s->gb) != 0) {
+ s->mv_type = MV_TYPE_8X8; /* Advanced prediction mode */
+ }
+
if (get_bits1(&s->gb) != 0)
return -1; /* not PB frame */
s->qscale = get_bits(&s->gb, 5);
skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */
} else {
- s->h263_plus = 1;
+ int ufep;
+
/* H.263v2 */
- if (get_bits(&s->gb, 3) != 1)
- return -1;
- if (get_bits(&s->gb, 3) != 6) /* custom source format */
+ s->h263_plus = 1;
+ ufep = get_bits(&s->gb, 3); /* Update Full Extended PTYPE */
+
+ if (ufep == 1) {
+ /* OPPTYPE */
+ format = get_bits(&s->gb, 3);
+ skip_bits(&s->gb,1); /* Custom PCF */
+ s->umvplus_dec = get_bits(&s->gb, 1); /* Unrestricted Motion Vector */
+ skip_bits1(&s->gb); /* Syntax-based Arithmetic Coding (SAC) */
+ if (get_bits1(&s->gb) != 0) {
+ s->mv_type = MV_TYPE_8X8; /* Advanced prediction mode */
+ }
+ skip_bits(&s->gb, 8);
+ skip_bits(&s->gb, 3); /* Reserved */
+ } else if (ufep != 0)
return -1;
- skip_bits(&s->gb, 12);
- skip_bits(&s->gb, 3);
+
+ /* MPPTYPE */
s->pict_type = get_bits(&s->gb, 3) + 1;
if (s->pict_type != I_TYPE &&
s->pict_type != P_TYPE)
return -1;
skip_bits(&s->gb, 7);
- skip_bits(&s->gb, 4); /* aspect ratio */
- width = (get_bits(&s->gb, 9) + 1) * 4;
- skip_bits1(&s->gb);
- height = get_bits(&s->gb, 9) * 4;
- if (height == 0)
- return -1;
+
+ /* Get the picture dimensions */
+ if (ufep) {
+ if (format == 6) {
+ /* Custom Picture Format (CPFMT) */
+ skip_bits(&s->gb, 4); /* aspect ratio */
+ width = (get_bits(&s->gb, 9) + 1) * 4;
+ skip_bits1(&s->gb);
+ height = get_bits(&s->gb, 9) * 4;
+#ifdef DEBUG
+ fprintf(stderr,"\nH.263+ Custom picture: %dx%d\n",width,height);
+#endif
+ }
+ else {
+ width = h263_format[format][0];
+ height = h263_format[format][1];
+ }
+ if ((width == 0) || (height == 0))
+ return -1;
+ s->width = width;
+ s->height = height;
+ if (s->umvplus_dec) {
+ skip_bits1(&s->gb); /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
+ }
+ }
+
s->qscale = get_bits(&s->gb, 5);
}
/* PEI */
@@ -1132,8 +1342,6 @@ int h263_decode_picture_header(MpegEncContext *s)
skip_bits(&s->gb, 8);
}
s->f_code = 1;
- s->width = width;
- s->height = height;
return 0;
}
@@ -1335,3 +1543,4 @@ int intel_h263_decode_picture_header(MpegEncContext *s)
s->f_code = 1;
return 0;
}
+