summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorDirk Ausserhaus <dausserhaus@gmail.com>2014-05-29 13:30:37 +0200
committerMichael Niedermayer <michaelni@gmx.at>2014-05-30 13:49:42 +0200
commit8bfb4d72dd9324fda14bb49dda3468ccba5873e2 (patch)
tree3e28e92deb34a715eda4f0e98eaeff0f03c38412 /libavcodec
parentd24673a2c80418c3c14dad523619f44f3ca8cb58 (diff)
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>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/indeo4.c4
-rw-r--r--libavcodec/ivi_common.c57
-rw-r--r--libavcodec/ivi_common.h3
3 files changed, 46 insertions, 18 deletions
diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
index cee9badbf8..ada44af17f 100644
--- a/libavcodec/indeo4.c
+++ b/libavcodec/indeo4.c
@@ -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;
}
diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c
index 55843efa92..53f71c7a37 100644
--- a/libavcodec/ivi_common.c
+++ b/libavcodec/ivi_common.c
@@ -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;
}
diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi_common.h
index 76d1b61c6a..b0bdfe5337 100644
--- a/libavcodec/ivi_common.h
+++ b/libavcodec/ivi_common.h
@@ -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 */