CrystalHD: Add auto-detection of packed b-frame bug.
authorPhilip Langdale <philipl@overt.org>
Thu, 21 Apr 2011 04:43:29 +0000 (21:43 -0700)
committerPhilip Langdale <philipl@overt.org>
Sat, 30 Apr 2011 16:47:28 +0000 (09:47 -0700)
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 <philipl@overt.org>
libavcodec/crystalhd.c

index 1a2d60c..3c80217 100644 (file)
@@ -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);