Commit 5ec6d152 authored by Dirk Ausserhaus's avatar Dirk Ausserhaus Committed by Kostya Shishkov

indeo4: B-frames decoding

Signed-off-by: 's avatarKostya Shishkov <kostya.shishkov@gmail.com>
parent 422e14f7
......@@ -194,7 +194,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx)
/* check if picture layout was changed and reallocate buffers */
if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf)) {
if (ff_ivi_init_planes(ctx->planes, &pic_conf)) {
if (ff_ivi_init_planes(ctx->planes, &pic_conf, 1)) {
av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n");
ctx->pic_conf.luma_bands = 0;
return AVERROR(ENOMEM);
......@@ -462,6 +462,8 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
mb->xpos = x;
mb->ypos = y;
mb->buf_offs = mb_offset;
mb->b_mv_x =
mb->b_mv_y = 0;
if (get_bits1(&ctx->gb)) {
if (ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
......@@ -537,6 +539,24 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
mv_x += IVI_TOSIGNED(mv_delta);
mb->mv_x = mv_x;
mb->mv_y = mv_y;
if (mb->type == 3) {
mv_delta = get_vlc2(&ctx->gb,
ctx->mb_vlc.tab->table,
IVI_VLC_BITS, 1);
mv_y += IVI_TOSIGNED(mv_delta);
mv_delta = get_vlc2(&ctx->gb,
ctx->mb_vlc.tab->table,
IVI_VLC_BITS, 1);
mv_x += IVI_TOSIGNED(mv_delta);
mb->b_mv_x = -mv_x;
mb->b_mv_y = -mv_y;
}
}
if (mb->type == 2) {
mb->b_mv_x = -mb->mv_x;
mb->b_mv_y = -mb->mv_y;
mb->mv_x = 0;
mb->mv_y = 0;
}
}
}
......@@ -563,32 +583,30 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
*/
static void switch_buffers(IVI45DecContext *ctx)
{
int is_prev_ref = 0, is_ref = 0;
switch (ctx->prev_frame_type) {
case IVI4_FRAMETYPE_INTRA:
case IVI4_FRAMETYPE_INTRA1:
case IVI4_FRAMETYPE_INTER:
ctx->buf_switch ^= 1;
ctx->dst_buf = ctx->buf_switch;
ctx->ref_buf = ctx->buf_switch ^ 1;
break;
case IVI4_FRAMETYPE_INTER_NOREF:
is_prev_ref = 1;
break;
}
switch (ctx->frame_type) {
case IVI4_FRAMETYPE_INTRA:
case IVI4_FRAMETYPE_INTRA1:
ctx->buf_switch = 0;
/* FALLTHROUGH */
case IVI4_FRAMETYPE_INTER:
ctx->dst_buf = ctx->buf_switch;
ctx->ref_buf = ctx->buf_switch ^ 1;
break;
case IVI4_FRAMETYPE_INTER_NOREF:
case IVI4_FRAMETYPE_NULL_FIRST:
case IVI4_FRAMETYPE_NULL_LAST:
is_ref = 1;
break;
}
if (is_prev_ref && is_ref) {
FFSWAP(int, ctx->dst_buf, ctx->ref_buf);
} else if (is_prev_ref) {
FFSWAP(int, ctx->ref_buf, ctx->b_ref_buf);
FFSWAP(int, ctx->dst_buf, ctx->ref_buf);
}
}
......@@ -622,6 +640,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
ctx->is_indeo4 = 1;
ctx->dst_buf = 0;
ctx->ref_buf = 1;
ctx->b_ref_buf = 3; /* buffer 2 is used for scalability mode */
ctx->p_frame = av_frame_alloc();
if (!ctx->p_frame)
return AVERROR(ENOMEM);
......
......@@ -113,7 +113,7 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx)
/* check if picture layout was changed and reallocate buffers */
if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf) || ctx->gop_invalid) {
result = ff_ivi_init_planes(ctx->planes, &pic_conf);
result = ff_ivi_init_planes(ctx->planes, &pic_conf, 0);
if (result < 0) {
av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n");
return result;
......@@ -625,7 +625,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
ctx->pic_conf.tile_height = avctx->height;
ctx->pic_conf.luma_bands = ctx->pic_conf.chroma_bands = 1;
result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf);
result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf, 0);
if (result) {
av_log(avctx, AV_LOG_ERROR, "Couldn't allocate color planes!\n");
return AVERROR_INVALIDDATA;
......
This diff is collapsed.
......@@ -117,6 +117,8 @@ typedef struct IVIMbInfo {
int8_t q_delta; ///< quant delta
int8_t mv_x; ///< motion vector (x component)
int8_t mv_y; ///< motion vector (y component)
int8_t b_mv_x; ///< second motion vector (x component)
int8_t b_mv_y; ///< second motion vector (y component)
} IVIMbInfo;
......@@ -150,7 +152,8 @@ typedef struct IVIBandDesc {
int data_size; ///< size of the band data
int16_t *buf; ///< pointer to the output buffer for this band
int16_t *ref_buf; ///< pointer to the reference frame buffer (for motion compensation)
int16_t *bufs[3]; ///< array of pointers to the band buffers
int16_t *b_ref_buf; ///< pointer to the second reference frame buffer (for motion compensation)
int16_t *bufs[4]; ///< array of pointers to the band buffers
int pitch; ///< pitch associated with the buffers above
int is_empty; ///< = 1 if this band doesn't contain any data
int mb_size; ///< macroblock size
......@@ -231,6 +234,7 @@ typedef struct IVI45DecContext {
int dst_buf; ///< buffer index for the currently decoded frame
int ref_buf; ///< inter frame reference buffer index
int ref2_buf; ///< temporal storage for switching buffers
int b_ref_buf; ///< second reference frame buffer index
IVIHuffTab mb_vlc; ///< current macroblock table descriptor
IVIHuffTab blk_vlc; ///< current block table descriptor
......@@ -314,11 +318,13 @@ int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab,
/**
* Initialize planes (prepares descriptors, allocates buffers etc).
*
* @param[in,out] planes pointer to the array of the plane descriptors
* @param[in] cfg pointer to the ivi_pic_config structure describing picture layout
* @param[in,out] planes pointer to the array of the plane descriptors
* @param[in] cfg pointer to the ivi_pic_config structure describing picture layout
* @param[in] is_indeo4 flag signalling if it is Indeo 4 or not
* @return result code: 0 - OK
*/
int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg);
int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg,
int is_indeo4);
/**
* Initialize tile and macroblock descriptors.
......
......@@ -762,39 +762,66 @@ void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch,
}
#define IVI_MC_TEMPLATE(size, suffix, OP) \
void ff_ivi_mc_ ## size ##x## size ## suffix (int16_t *buf, const int16_t *ref_buf, \
uint32_t pitch, int mc_type) \
static void ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, \
uint32_t dpitch, \
const int16_t *ref_buf, \
uint32_t pitch, int mc_type) \
{ \
int i, j; \
const int16_t *wptr; \
\
switch (mc_type) { \
case 0: /* fullpel (no interpolation) */ \
for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) { \
for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) { \
for (j = 0; j < size; j++) {\
OP(buf[j], ref_buf[j]); \
} \
} \
break; \
case 1: /* horizontal halfpel interpolation */ \
for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) \
for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) \
for (j = 0; j < size; j++) \
OP(buf[j], (ref_buf[j] + ref_buf[j+1]) >> 1); \
break; \
case 2: /* vertical halfpel interpolation */ \
wptr = ref_buf + pitch; \
for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \
for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \
for (j = 0; j < size; j++) \
OP(buf[j], (ref_buf[j] + wptr[j]) >> 1); \
break; \
case 3: /* vertical and horizontal halfpel interpolation */ \
wptr = ref_buf + pitch; \
for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \
for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \
for (j = 0; j < size; j++) \
OP(buf[j], (ref_buf[j] + ref_buf[j+1] + wptr[j] + wptr[j+1]) >> 2); \
break; \
} \
} \
\
void ff_ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, const int16_t *ref_buf, \
uint32_t pitch, int mc_type) \
{ \
ivi_mc_ ## size ##x## size ## suffix(buf, pitch, ref_buf, pitch, mc_type); \
} \
#define IVI_MC_AVG_TEMPLATE(size, suffix, OP) \
void ff_ivi_mc_avg_ ## size ##x## size ## suffix(int16_t *buf, \
const int16_t *ref_buf, \
const int16_t *ref_buf2, \
uint32_t pitch, \
int mc_type, int mc_type2) \
{ \
int16_t tmp[size * size]; \
int i, j; \
\
ivi_mc_ ## size ##x## size ## _no_delta(tmp, size, ref_buf, pitch, mc_type); \
ivi_mc_ ## size ##x## size ## _delta(tmp, size, ref_buf2, pitch, mc_type2); \
for (i = 0; i < size; i++, buf += pitch) { \
for (j = 0; j < size; j++) {\
OP(buf[j], tmp[i * size + j] >> 1); \
} \
} \
} \
#define OP_PUT(a, b) (a) = (b)
#define OP_ADD(a, b) (a) += (b)
......@@ -803,3 +830,7 @@ IVI_MC_TEMPLATE(8, _no_delta, OP_PUT)
IVI_MC_TEMPLATE(8, _delta, OP_ADD)
IVI_MC_TEMPLATE(4, _no_delta, OP_PUT)
IVI_MC_TEMPLATE(4, _delta, OP_ADD)
IVI_MC_AVG_TEMPLATE(8, _no_delta, OP_PUT)
IVI_MC_AVG_TEMPLATE(8, _delta, OP_ADD)
IVI_MC_AVG_TEMPLATE(4, _no_delta, OP_PUT)
IVI_MC_AVG_TEMPLATE(4, _delta, OP_ADD)
......@@ -291,4 +291,52 @@ void ff_ivi_mc_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch
*/
void ff_ivi_mc_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type);
/**
* 8x8 block motion compensation with adding delta
*
* @param[in,out] buf pointer to the block in the current frame buffer containing delta
* @param[in] ref_buf pointer to the corresponding block in the backward reference frame
* @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame
* @param[in] pitch pitch for moving to the next y line
* @param[in] mc_type interpolation type for backward reference
* @param[in] mc_type2 interpolation type for forward reference
*/
void ff_ivi_mc_avg_8x8_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
/**
* 4x4 block motion compensation with adding delta
*
* @param[in,out] buf pointer to the block in the current frame buffer containing delta
* @param[in] ref_buf pointer to the corresponding block in the backward reference frame
* @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame
* @param[in] pitch pitch for moving to the next y line
* @param[in] mc_type interpolation type for backward reference
* @param[in] mc_type2 interpolation type for forward reference
*/
void ff_ivi_mc_avg_4x4_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
/**
* motion compensation without adding delta for B-frames
*
* @param[in,out] buf pointer to the block in the current frame receiving the result
* @param[in] ref_buf pointer to the corresponding block in the backward reference frame
* @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame
* @param[in] pitch pitch for moving to the next y line
* @param[in] mc_type interpolation type for backward reference
* @param[in] mc_type2 interpolation type for forward reference
*/
void ff_ivi_mc_avg_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
/**
* 4x4 block motion compensation without adding delta for B-frames
*
* @param[in,out] buf pointer to the block in the current frame receiving the result
* @param[in] ref_buf pointer to the corresponding block in the backward reference frame
* @param[in] ref_buf2 pointer to the corresponding block in the forward reference frame
* @param[in] pitch pitch for moving to the next y line
* @param[in] mc_type interpolation type for backward reference
* @param[in] mc_type2 interpolation type for forward reference
*/
void ff_ivi_mc_avg_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
#endif /* AVCODEC_IVI_DSP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment