summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2003-05-31 07:56:58 +0000
committerMike Melanson <mike@multimedia.cx>2003-05-31 07:56:58 +0000
commit642d7e842e7280e0fc5cde1fb2677172bc5f10d6 (patch)
tree8a670ed13768c6cb04cb3c084738bf13e8f9cae5
parentba88675b1d2a381abf5fe40250786dfc960969e0 (diff)
revising and fixing motion vectors, squished block unpacking bug that
led to memory stomps, added support for funky arbitrary dimensions Originally committed as revision 1922 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/vp3.c148
1 files changed, 64 insertions, 84 deletions
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 91e6fbb111..711679000b 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -139,9 +139,6 @@ typedef struct Vp3Fragment {
int last_coeff;
int motion_x;
int motion_y;
- /* this indicates which ffmpeg put_pixels() function to use:
- * 00b = no halfpel, 01b = x halfpel, 10b = y halfpel, 11b = both halfpel */
- int motion_halfpel_index;
/* address of first pixel taking into account which plane the fragment
* lives on as well as the plane stride */
int first_pixel;
@@ -816,6 +813,8 @@ static void init_frame(Vp3DecodeContext *s, GetBitContext *gb)
memset(s->all_fragments[i].coeffs, 0, 64 * sizeof(DCTELEM));
s->all_fragments[i].coeff_count = 0;
s->all_fragments[i].last_coeff = 0;
+s->all_fragments[i].motion_x = 0xbeef;
+s->all_fragments[i].motion_y = 0xbeef;
}
}
@@ -1161,14 +1160,14 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
/* if any of the superblocks are not partially coded, flag
* a boolean to decode the list of fully-coded superblocks */
- if (bit == 0)
+ if (bit == 0) {
decode_fully_flags = 1;
- } else {
-
- /* make a note of the fact that there are partially coded
- * superblocks */
- decode_partial_blocks = 1;
+ } else {
+ /* make a note of the fact that there are partially coded
+ * superblocks */
+ decode_partial_blocks = 1;
+ }
}
s->superblock_coding[current_superblock++] =
(bit) ? SB_PARTIALLY_CODED : SB_NOT_CODED;
@@ -1309,7 +1308,7 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
/* only Y fragments coded in this frame */
s->last_coded_y_fragment = s->coded_fragment_list_index - 1;
else
- /* end the list of coded fragments */
+ /* end the list of coded C fragments */
s->last_coded_c_fragment = s->coded_fragment_list_index - 1;
debug_block_coding(" %d total coded fragments, y: %d -> %d, c: %d -> %d\n",
@@ -1407,55 +1406,6 @@ static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb)
}
/*
- * This function adjusts the components of a motion vector for the halfpel
- * motion grid. c_plane indicates whether the vector applies to the U or V
- * plane. The function returns the halfpel function index to be used in
- * ffmpeg's put_pixels[]() array of functions.
- */
-static inline int adjust_vector(int *x, int *y, int c_plane)
-{
- int motion_halfpel_index = 0;
- int x_halfpel;
- int y_halfpel;
-
- if (!c_plane) {
-
- x_halfpel = *x & 1;
- motion_halfpel_index |= x_halfpel;
- if (*x >= 0)
- *x >>= 1;
- else
- *x = -( (-(*x) >> 1) + x_halfpel);
-
- y_halfpel = *y & 1;
- motion_halfpel_index |= (y_halfpel << 1);
- if (*y >= 0)
- *y >>= 1;
- else
- *y = -( (-(*y) >> 1) + y_halfpel);
-
- } else {
-
- x_halfpel = ((*x & 0x03) != 0);
- motion_halfpel_index |= x_halfpel;
- if (*x >= 0)
- *x >>= 2;
- else
- *x = -( (-(*x) >> 2) + x_halfpel);
-
- y_halfpel = ((*y & 0x03) != 0);
- motion_halfpel_index |= (y_halfpel << 1);
- if (*y >= 0)
- *y >>= 2;
- else
- *y = -( (-(*y) >> 2) + y_halfpel);
-
- }
-
- return motion_halfpel_index;
-}
-
-/*
* This function unpacks all the motion vectors for the individual
* macroblocks from the bitstream.
*/
@@ -1527,7 +1477,7 @@ static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
}
/* vector maintenance, only on MODE_INTER_PLUS_MV */
- if (s->all_fragments[current_fragment].coding_method ==
+ if (s->macroblock_coding[current_macroblock] ==
MODE_INTER_PLUS_MV) {
prior_last_motion_x = last_motion_x;
prior_last_motion_y = last_motion_y;
@@ -1614,7 +1564,7 @@ static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
/* assign the motion vectors to the correct fragments */
debug_vectors(" vectors for macroblock starting @ fragment %d (coding method %d):\n",
current_fragment,
- s->all_fragments[current_fragment].coding_method);
+ s->macroblock_coding[current_macroblock]);
for (k = 0; k < 6; k++) {
current_fragment =
s->macroblock_fragments[current_macroblock * 6 + k];
@@ -1625,14 +1575,10 @@ static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
current_fragment, s->fragment_count);
return 1;
}
- s->all_fragments[current_fragment].motion_halfpel_index =
- adjust_vector(&motion_x[k], &motion_y[k],
- ((k == 4) || (k == 5)));
s->all_fragments[current_fragment].motion_x = motion_x[k];
s->all_fragments[current_fragment].motion_y = motion_y[k];
- debug_vectors(" vector %d: fragment %d = (%d, %d), index %d\n",
- k, current_fragment, motion_x[k], motion_y[k],
- s->all_fragments[current_fragment].motion_halfpel_index);
+ debug_vectors(" vector %d: fragment %d = (%d, %d)\n",
+ k, current_fragment, motion_x[k], motion_y[k]);
}
}
}
@@ -2141,22 +2087,45 @@ static void render_fragments(Vp3DecodeContext *s,
/* transform if this block was coded */
if (s->all_fragments[i].coding_method != MODE_COPY) {
- /* sort out the motion vector */
- motion_x = s->all_fragments[i].motion_x;
- motion_y = s->all_fragments[i].motion_y;
- motion_halfpel_index = s->all_fragments[i].motion_halfpel_index;
-
motion_source = s->all_fragments[i].first_pixel;
- motion_source += motion_x;
- motion_source += (motion_y * stride);
-
- /* if the are any problems with a motion vector, refuse
- * to render the block */
- if ((motion_source < upper_motion_limit) ||
- (motion_source > lower_motion_limit)) {
-// printf (" vp3: help! motion source (%d) out of range (%d..%d)\n",
-// motion_source, upper_motion_limit, lower_motion_limit);
- continue;
+ motion_halfpel_index = 0;
+
+ /* sort out the motion vector if this fragment is coded
+ * using a motion vector method */
+ if ((s->all_fragments[i].coding_method > MODE_INTRA) &&
+ (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) {
+ motion_x = s->all_fragments[i].motion_x;
+ motion_y = s->all_fragments[i].motion_y;
+if ((motion_x == 0xbeef) || (motion_y == 0xbeef))
+printf (" help! got beefy vector! (%X, %X)\n", motion_x, motion_y);
+
+ if (motion_x >= 0) {
+ motion_halfpel_index = motion_x & 0x01;
+ motion_source += (motion_x >> 1);
+ } else {
+ motion_x = -motion_x;
+ motion_halfpel_index = motion_x & 0x01;
+ motion_source -= ((motion_x + 1) >> 1);
+ }
+
+// motion_y = -motion_y;
+ if (motion_y >= 0) {
+ motion_halfpel_index |= (motion_y & 0x01) << 1;
+ motion_source += ((motion_y >> 1) * stride);
+ } else {
+ motion_y = -motion_y;
+ motion_halfpel_index |= (motion_y & 0x01) << 1;
+ motion_source -= (((motion_y + 1) >> 1) * stride);
+ }
+
+ /* if the are any problems with a motion vector, refuse
+ * to render the block */
+ if ((motion_source < upper_motion_limit) ||
+ (motion_source > lower_motion_limit)) {
+// printf (" vp3: help! motion source (%d) out of range (%d..%d)\n",
+// motion_source, upper_motion_limit, lower_motion_limit);
+ continue;
+ }
}
/* first, take care of copying a block from either the
@@ -2304,8 +2273,13 @@ static int vp3_decode_init(AVCodecContext *avctx)
int c_superblock_count;
s->avctx = avctx;
+#if 0
s->width = avctx->width;
s->height = avctx->height;
+#else
+ s->width = (avctx->width + 15) & 0xFFFFFFF0;
+ s->height = (avctx->height + 15) & 0xFFFFFFF0;
+#endif
avctx->pix_fmt = PIX_FMT_YUV420P;
avctx->has_b_frames = 0;
dsputil_init(&s->dsp, avctx);
@@ -2432,12 +2406,13 @@ static int vp3_decode_frame(AVCodecContext *avctx,
skip_bits(&gb, 1);
s->last_quality_index = s->quality_index;
s->quality_index = get_bits(&gb, 6);
- if (s->quality_index != s->last_quality_index)
- init_dequantizer(s);
debug_vp3(" VP3 frame #%d: Q index = %d", counter, s->quality_index);
counter++;
+ if (s->quality_index != s->last_quality_index)
+ init_dequantizer(s);
+
if (s->keyframe) {
debug_vp3(", keyframe\n");
@@ -2510,8 +2485,13 @@ if (!s->keyframe) {
s->fragment_width / 2, s->fragment_height / 2);
render_fragments(s, 0, s->width, s->height, 0);
+#if 1
render_fragments(s, s->u_fragment_start, s->width / 2, s->height / 2, 1);
render_fragments(s, s->v_fragment_start, s->width / 2, s->height / 2, 2);
+#else
+memset(s->current_frame.data[1], 0x80, s->width * s->height / 4);
+memset(s->current_frame.data[2], 0x80, s->width * s->height / 4);
+#endif
#if KEYFRAMES_ONLY
}