Browse Source

avcodec/indeo4: Decode both parts of IP frames

Fixes part of Ticket845

av_frame_move_ref() idea by Anton Khirnov

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
tags/n2.3
Dirk Ausserhaus Michael Niedermayer 11 years ago
parent
commit
8bfb4d72dd
3 changed files with 46 additions and 18 deletions
  1. +4
    -0
      libavcodec/indeo4.c
  2. +39
    -18
      libavcodec/ivi_common.c
  3. +3
    -0
      libavcodec/ivi_common.h

+ 4
- 0
libavcodec/indeo4.c View File

@@ -663,6 +663,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
ctx->switch_buffers = switch_buffers;
ctx->is_nonnull_frame = is_nonnull_frame;

ctx->p_frame = av_frame_alloc();
if (!ctx->p_frame)
return AVERROR(ENOMEM);

return 0;
}



+ 39
- 18
libavcodec/ivi_common.c View File

@@ -997,6 +997,18 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
if (ctx->gop_invalid)
return AVERROR_INVALIDDATA;

if (avctx->codec_id == AV_CODEC_ID_INDEO4 &&
ctx->frame_type == IVI4_FRAMETYPE_NULL_LAST) {
if (ctx->got_p_frame) {
av_frame_move_ref(data, ctx->p_frame);
*got_frame = 1;
ctx->got_p_frame = 0;
} else {
*got_frame = 0;
}
return buf_size;
}

if (ctx->gop_flags & IVI5_IS_PROTECTED) {
avpriv_report_missing_feature(avctx, "Password-protected clip!\n");
return AVERROR_PATCHWELCOME;
@@ -1038,24 +1050,6 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,

//STOP_TIMER("decode_planes"); }

/* If the bidirectional mode is enabled, next I and the following P
* frame will be sent together. Unfortunately the approach below seems
* to be the only way to handle the B-frames mode.
* That's exactly the same Intel decoders do.
*/
if (avctx->codec_id == AV_CODEC_ID_INDEO4 &&
ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
// skip version string
while (get_bits(&ctx->gb, 8)) {
if (get_bits_left(&ctx->gb) < 8)
return AVERROR_INVALIDDATA;
}

skip_bits_long(&ctx->gb, 64); // skip padding, TODO: implement correct 8-bytes alignment
if (get_bits_left(&ctx->gb) > 18 && show_bits(&ctx->gb, 18) == 0x3FFF8)
av_log(avctx, AV_LOG_ERROR, "Buffer contains IP frames!\n");
}

if (!ctx->is_nonnull_frame(ctx))
return buf_size;

@@ -1080,6 +1074,31 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,

*got_frame = 1;

/* If the bidirectional mode is enabled, next I and the following P
* frame will be sent together. Unfortunately the approach below seems
* to be the only way to handle the B-frames mode.
* That's exactly the same Intel decoders do.
*/
if (avctx->codec_id == AV_CODEC_ID_INDEO4 &&
ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
int left;

// skip version string
while (get_bits(&ctx->gb, 8)) {
if (get_bits_left(&ctx->gb) < 8)
return AVERROR_INVALIDDATA;
}
left = get_bits_count(&ctx->gb) & 0x18;
skip_bits_long(&ctx->gb, 64 - left);
if (get_bits_left(&ctx->gb) > 18 &&
show_bits_long(&ctx->gb, 21) == 0xBFFF8) { // syncheader + inter type
AVPacket pkt;
pkt.data = avpkt->data + (get_bits_count(&ctx->gb) >> 3);
pkt.size = get_bits_left(&ctx->gb) >> 3;
ff_ivi_decode_frame(avctx, ctx->p_frame, &ctx->got_p_frame, &pkt);
}
}

return buf_size;
}

@@ -1112,6 +1131,8 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx)
}
#endif

av_frame_free(&ctx->p_frame);

return 0;
}



+ 3
- 0
libavcodec/ivi_common.h View File

@@ -262,6 +262,9 @@ typedef struct IVI45DecContext {

int gop_invalid;
int buf_invalid[3];

AVFrame *p_frame;
int got_p_frame;
} IVI45DecContext;

/** compare some properties of two pictures */


Loading…
Cancel
Save