[FFmpeg-soc] [soc]: r550 - dirac/libavcodec/dirac.c
marco
subversion at mplayerhq.hu
Mon Jul 30 10:38:38 CEST 2007
Author: marco
Date: Mon Jul 30 10:38:37 2007
New Revision: 550
Log:
Fix a lot of small bugs in MV unpacking
Modified:
dirac/libavcodec/dirac.c
Modified: dirac/libavcodec/dirac.c
==============================================================================
--- dirac/libavcodec/dirac.c (original)
+++ dirac/libavcodec/dirac.c Mon Jul 30 10:38:37 2007
@@ -579,8 +579,9 @@ static struct dirac_arith_context_set co
static struct dirac_arith_context_set context_set_mv =
{
.follow = { ARITH_CONTEXT_VECTOR_F1, ARITH_CONTEXT_VECTOR_F2,
- ARITH_CONTEXT_VECTOR_F3 },
- .follow_length = 3,
+ ARITH_CONTEXT_VECTOR_F3, ARITH_CONTEXT_VECTOR_F4,
+ ARITH_CONTEXT_VECTOR_F5 },
+ .follow_length = 5,
.data = ARITH_CONTEXT_VECTOR_DATA,
.sign = ARITH_CONTEXT_VECTOR_SIGN
};
@@ -1018,8 +1019,7 @@ static int subband(AVCodecContext *avctx
dirac_arith_flush(&s->arith);
}
- /* XXX: This should be done for intra frames only. */
- if (level == 0)
+ if (level == 0 && s->refs == 0)
intra_dc_prediction(avctx, data);
return 0;
@@ -1065,10 +1065,10 @@ static void dirac_unpack_prediction_para
/* Setup the blen and bsep parameters for the chroma
component. */
- s->frame_decoding.luma_xblen = s->frame_decoding.luma_xblen / s->chroma_hratio;
- s->frame_decoding.luma_yblen = s->frame_decoding.luma_yblen / s->chroma_vratio;
- s->frame_decoding.luma_xbsep = s->frame_decoding.luma_xbsep / s->chroma_hratio;
- s->frame_decoding.luma_ybsep = s->frame_decoding.luma_ybsep / s->chroma_vratio;
+ s->frame_decoding.chroma_xblen = s->frame_decoding.luma_xblen / s->chroma_hratio;
+ s->frame_decoding.chroma_yblen = s->frame_decoding.luma_yblen / s->chroma_vratio;
+ s->frame_decoding.chroma_xbsep = s->frame_decoding.luma_xbsep / s->chroma_hratio;
+ s->frame_decoding.chroma_ybsep = s->frame_decoding.luma_ybsep / s->chroma_vratio;
/* Overrid motion vector precision. */
if (get_bits(gb, 1))
@@ -1077,6 +1077,8 @@ static void dirac_unpack_prediction_para
/* Read the global motion compensation parameters. */
s->globalmc_flag = get_bits(gb, 1);
if (s->globalmc_flag) {
+ int ref;
+ for (ref = 0; ref < s->refs; ref++) {
/* Pan/til parameters. */
if (get_bits(gb, 1)) {
s->globalmc.b[0] = dirac_get_se_golomb(gb);
@@ -1100,7 +1102,6 @@ static void dirac_unpack_prediction_para
s->globalmc.A[1][0] = 0;
s->globalmc.A[1][1] = 0;
}
- }
/* Perspective parameters. */
if (get_bits(gb, 1)) {
@@ -1112,6 +1113,8 @@ static void dirac_unpack_prediction_para
s->globalmc.c[0] = 0;
s->globalmc.c[1] = 0;
}
+ }
+ }
/* Picture prediction mode. XXX: Not used yet in the specification. */
if (get_bits(gb, 1)) {
@@ -1159,7 +1162,8 @@ static inline int mode_prediction(AVCode
cnt = s->blmotion[y * s->blwidth + x - 1].use_ref[ref]
+ s->blmotion[(y - 1) * s->blwidth + x ].use_ref[ref]
+ s->blmotion[(y - 1) * s->blwidth + x - 1].use_ref[ref];
- if (cnt == 2)
+
+ if (cnt >= 2)
return 1;
else
return 0;
@@ -1180,7 +1184,7 @@ static inline int global_mode_prediction
cnt = s->blmotion[y * s->blwidth + x - 1].use_global
+ s->blmotion[(y - 1) * s->blwidth + x ].use_global
+ s->blmotion[(y - 1) * s->blwidth + x - 1].use_global;
- if (cnt == 2)
+ if (cnt >= 2)
return 1;
else
return 0;
@@ -1196,6 +1200,8 @@ static void blockmode_prediction(AVCodec
res = dirac_arith_get_bit(&s->arith, ARITH_CONTEXT_PMODE_REF2);
res ^= mode_prediction(avctx, x, y, 1);
s->blmotion[y * s->blwidth + x].use_ref[1] = res;
+ } else {
+ s->blmotion[y * s->blwidth + x].use_ref[1] = 0;
}
}
@@ -1245,12 +1251,12 @@ static int motion_vector_prediction(AVCo
else
left = s->blmotion[y * s->blwidth + x - 1].ref2[dir];
- /* This is the only reference, return it. */
- if (y == 0)
- return left;
-
cnt++;
}
+
+ /* This is the only reference, return it. */
+ if (y == 0)
+ return left;
}
if (y > 0) {
@@ -1264,12 +1270,12 @@ static int motion_vector_prediction(AVCo
else
top = s->blmotion[(y - 1) * s->blwidth + x].ref2[dir];
- /* This is the only reference, return it. */
- if (x == 0)
- return top;
-
cnt++;
}
+
+ /* This is the only reference, return it. */
+ if (x == 0)
+ return top;
}
if (x > 0 && y > 0) {
@@ -1290,11 +1296,12 @@ static int motion_vector_prediction(AVCo
if (cnt == 0)
return 0;
- assert(cnt == 2 || cnt == 3);
+ if (cnt == 1)
+ return left + top + lefttop;
/* Return the median of two motion vectors. */
if (cnt == 2)
- return (left + top + lefttop) / 2;
+ return (left + top + lefttop + 1) >> 1;
/* Return the median of three motion vectors. */
return mid_pred(left, top, lefttop);
@@ -1330,18 +1337,19 @@ static int block_dc_prediction(AVCodecCo
}
if (cnt == 0)
- return (1 << s->sequence.video_depth) - 1;
+ return 1 << (s->sequence.video_depth - 1);
/* Return the average of all DC values that were counted. */
- return total / cnt;
+ return (total + (cnt >> 1)) / cnt;
}
static void unpack_block_dc(AVCodecContext *avctx, int x, int y, int comp) {
DiracContext *s = avctx->priv_data;
int res;
- if ( !s->blmotion[y * s->blwidth + x].use_ref[0]
- && !s->blmotion[y * s->blwidth + x].use_ref[1])
+ s->blmotion[y * s->blwidth + x].dc[comp] = 0; /* XXX */
+ if ( s->blmotion[y * s->blwidth + x].use_ref[0]
+ || s->blmotion[y * s->blwidth + x].use_ref[1])
return;
res = dirac_arith_read_int(&s->arith, &context_set_dc);
@@ -1369,7 +1377,7 @@ static void dirac_unpack_motion_vector(A
return;
res = dirac_arith_read_int(&s->arith, &context_set_mv);
- res += motion_vector_prediction(avctx, x, y, res, dir);
+ res += motion_vector_prediction(avctx, x, y, ref, dir);
if (ref == 0) /* XXX */
s->blmotion[y * s->blwidth + x].ref1[dir] = res;
else
@@ -1400,10 +1408,10 @@ static void dirac_unpack_motion_vectors(
for (q = 0; q < blkcnt; q++)
for (p = 0; p < blkcnt; p++) {
dirac_unpack_motion_vector(avctx, ref, dir,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
propagate_block_data(avctx, step,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
}
}
@@ -1420,13 +1428,15 @@ static void dirac_unpack_prediction_data
int comp;
int x, y;
- s->blwidth = s->sequence.luma_width / s->frame_decoding.luma_xbsep;
- s->blheight = s->sequence.luma_height / s->frame_decoding.luma_ybsep;
- s->sbwidth = s->blwidth >> 2;
- s->sbheight = s->blheight >> 2;
+#define DIVRNDUP(a, b) ((a + b - 1) / b)
- s->sbsplit = av_mallocz(s->sbwidth * s->sbheight);
- s->blmotion = av_mallocz(s->blwidth * s->blheight);
+ s->sbwidth = DIVRNDUP(s->sequence.luma_width, (s->frame_decoding.luma_xbsep << 2));
+ s->sbheight = DIVRNDUP(s->sequence.luma_height, (s->frame_decoding.luma_ybsep << 2));
+ s->blwidth = s->sbwidth << 2;
+ s->blheight = s->sbheight << 2;
+
+ s->sbsplit = av_mallocz(s->sbwidth * s->sbheight * sizeof(int));
+ s->blmotion = av_mallocz(s->blwidth * s->blheight * sizeof(*s->blmotion));
/* Superblock splitmodes. */
length = dirac_get_ue_golomb(gb);
@@ -1446,18 +1456,18 @@ static void dirac_unpack_prediction_data
for (x = 0; x < s->sbwidth; x++) {
int q, p;
int blkcnt = 1 << s->sbsplit[y * s->sbwidth + x];
- int step = 4 >> s->sbsplit[y * s->sbwidth + x];
+ int step = 4 >> s->sbsplit[y * s->sbwidth + x];
for (q = 0; q < blkcnt; q++)
for (p = 0; p < blkcnt; p++) {
blockmode_prediction(avctx,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
blockglob_prediction(avctx,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
propagate_block_data(avctx, step,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
}
}
@@ -1485,11 +1495,11 @@ static void dirac_unpack_prediction_data
for (q = 0; q < blkcnt; q++)
for (p = 0; p < blkcnt; p++) {
unpack_block_dc(avctx,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step,
comp);
propagate_block_data(avctx, step,
- 4 * y + p * step,
+ 4 * x + p * step,
4 * y + q * step);
}
}
@@ -1667,7 +1677,7 @@ static int dirac_idwt(AVCodecContext *av
*
* @return 0 when successful, otherwise -1 is returned
*/
-static int decode_intra_frame(AVCodecContext *avctx) {
+static int dirac_decode_frame(AVCodecContext *avctx) {
DiracContext *s = avctx->priv_data;
int comp;
int x,y;
@@ -1843,8 +1853,7 @@ static int decode_frame(AVCodecContext *
init_get_bits(&gb, &buf[13], (buf_size - 13) * 8);
s->gb = &gb;
- switch (parse_code) {
- case pc_access_unit_header:
+ if (parse_code == pc_access_unit_header) {
parse_access_unit_header(avctx);
/* Dump the header. */
@@ -1854,34 +1863,39 @@ static int decode_frame(AVCodecContext *
#endif
return 0;
- case pc_intra_ref:
- s->refs = 0;
- parse_frame(avctx);
+ }
- avctx->pix_fmt = PIX_FMT_YUVJ420P; /* XXX */
+ /* If this is not a picture, return. */
+ if ((parse_code & 0x08) != 0x08)
+ return 0;
- if (avcodec_check_dimensions(avctx, s->sequence.luma_width,
- s->sequence.luma_height)) {
- av_log(avctx, AV_LOG_ERROR,
- "avcodec_check_dimensions() failed\n");
- return -1;
- }
+ s->refs = parse_code & 0x03;
- avcodec_set_dimensions(avctx, s->sequence.luma_width,
- s->sequence.luma_height);
+ parse_frame(avctx);
- if (s->picture.data[0] != NULL)
- avctx->release_buffer(avctx, &s->picture);
+ avctx->pix_fmt = PIX_FMT_YUVJ420P; /* XXX */
- if (avctx->get_buffer(avctx, &s->picture) < 0) {
- av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
- return -1;
- }
+ if (avcodec_check_dimensions(avctx, s->sequence.luma_width,
+ s->sequence.luma_height)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "avcodec_check_dimensions() failed\n");
+ return -1;
+ }
- if (decode_intra_frame(avctx))
- return -1;
+ avcodec_set_dimensions(avctx, s->sequence.luma_width,
+ s->sequence.luma_height);
+
+ if (s->picture.data[0] != NULL)
+ avctx->release_buffer(avctx, &s->picture);
+
+ if (avctx->get_buffer(avctx, &s->picture) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
}
+ if (dirac_decode_frame(avctx))
+ return -1;
+
*data_size = sizeof(AVFrame);
*picture = s->picture;
More information about the FFmpeg-soc
mailing list