From 8de45adb37bb0591626645e1f7d1303339b2bc9f Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 20 Apr 2011 21:43:29 -0700 Subject: [PATCH] CrystalHD: Add auto-detection of packed b-frame bug. I still don't fully understand the cause but the difference between the samples that trigger the bug and the samples that don't is that the former uses delay frames and the later uses drop frames as placeholders for the packed frame. So, if we see the one type of frame, we can assume the bug will or won't be present. Right now, I'm detecting the frame types by size, which may not be safe in general, but given the specific codec and file type, I expect any scenario where we encounter these frames where they aren't being used for b-frame packing won't care one way or another whether the work around is in effect or not. Signed-off-by: Philip Langdale --- libavcodec/crystalhd.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 1a2d60c672..3c8021748f 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -142,6 +142,7 @@ typedef struct { /* Options */ uint32_t sWidth; + uint8_t bframe_bug; } CHDContext; static const AVOption options[] = { @@ -744,7 +745,7 @@ static inline CopyRet receive_frame(AVCodecContext *avctx, } if (avctx->codec->id == CODEC_ID_MPEG4 && - output.PicInfo.timeStamp == 0) { + output.PicInfo.timeStamp == 0 && priv->bframe_bug) { av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Not returning packed frame twice.\n"); priv->last_picture++; @@ -810,6 +811,22 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n"); + if (avpkt->size == 7 && !priv->bframe_bug) { + /* + * The use of a drop frame triggers the bug + */ + av_log(avctx, AV_LOG_INFO, + "CrystalHD: Enabling work-around for packed b-frame bug\n"); + priv->bframe_bug = 1; + } else if (avpkt->size == 8 && priv->bframe_bug) { + /* + * Delay frames don't trigger the bug + */ + av_log(avctx, AV_LOG_INFO, + "CrystalHD: Disabling work-around for packed b-frame bug\n"); + priv->bframe_bug = 0; + } + if (len) { int32_t tx_free = (int32_t)DtsTxFreeSize(dev);