[FFmpeg-cvslog] crystalhd: Use mpeg4_unpack_bframes to avoid buggy crystalhd handling

Philip Langdale git at videolan.org
Wed Oct 12 17:46:51 EEST 2016


ffmpeg | branch: master | Philip Langdale <philipl at overt.org> | Sat Oct  8 20:34:00 2016 -0700| [03d6d5f3760e2b06e3ef1f68de62c79c2e8fb173] | committer: Philip Langdale

crystalhd: Use mpeg4_unpack_bframes to avoid buggy crystalhd handling

The hardware handling of packed bframes was always questionable but
it used to ok with my workaround. Today, not so much. But today we
have a bsf to unpack the bframes, so let's just use that and be
done with it.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=03d6d5f3760e2b06e3ef1f68de62c79c2e8fb173
---

 libavcodec/crystalhd.c | 127 ++++++++++++++++++++++++-------------------------
 1 file changed, 63 insertions(+), 64 deletions(-)

diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 83be8e5..9120940 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -150,7 +150,6 @@ typedef struct {
 
     /* Options */
     uint32_t sWidth;
-    uint8_t bframe_bug;
 } CHDContext;
 
 static const AVOption options[] = {
@@ -379,9 +378,59 @@ static av_cold int uninit(AVCodecContext *avctx)
 }
 
 
+static av_cold int init_bsf(AVCodecContext *avctx, const char *bsf_name)
+{
+    CHDContext *priv = avctx->priv_data;
+    const AVBitStreamFilter *bsf;
+    int avret;
+    void *extradata = NULL;
+    size_t size = 0;
+
+    bsf = av_bsf_get_by_name(bsf_name);
+    if (!bsf) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Cannot open the %s BSF!\n", bsf_name);
+        return AVERROR_BSF_NOT_FOUND;
+    }
+
+    avret = av_bsf_alloc(bsf, &priv->bsfc);
+    if (avret != 0) {
+        return avret;
+    }
+
+    avret = avcodec_parameters_from_context(priv->bsfc->par_in, avctx);
+    if (avret != 0) {
+        return avret;
+    }
+
+    avret = av_bsf_init(priv->bsfc);
+    if (avret != 0) {
+        return avret;
+    }
+
+    /* Back up the extradata so it can be restored at close time. */
+    priv->orig_extradata = avctx->extradata;
+    priv->orig_extradata_size = avctx->extradata_size;
+
+    size = priv->bsfc->par_out->extradata_size;
+    extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!extradata) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Failed to allocate copy of extradata\n");
+        return AVERROR(ENOMEM);
+    }
+    memcpy(extradata, priv->bsfc->par_out->extradata, size);
+
+    avctx->extradata = extradata;
+    avctx->extradata_size = size;
+
+    return 0;
+}
+
 static av_cold int init(AVCodecContext *avctx)
 {
     CHDContext* priv;
+    int avret;
     BC_STATUS ret;
     BC_INFO_CRYSTAL version;
     BC_INPUT_FORMAT format = {
@@ -417,46 +466,22 @@ static av_cold int init(AVCodecContext *avctx)
     subtype = id2subtype(priv, avctx->codec->id);
     switch (subtype) {
     case BC_MSUBTYPE_AVC1:
-        {
-            const AVBitStreamFilter *bsf;
-            int avret;
-
-            bsf = av_bsf_get_by_name("h264_mp4toannexb");
-            if (!bsf) {
-                av_log(avctx, AV_LOG_ERROR,
-                       "Cannot open the h264_mp4toannexb BSF!\n");
-                return AVERROR_BSF_NOT_FOUND;
-            }
-            avret = av_bsf_alloc(bsf, &priv->bsfc);
-            if (avret != 0) {
-                return AVERROR(ENOMEM);
-            }
-            avret = avcodec_parameters_from_context(priv->bsfc->par_in, avctx);
-            if (avret != 0) {
-                return AVERROR(ENOMEM);
-            }
-            avret = av_bsf_init(priv->bsfc);
-            if (avret != 0) {
-                return AVERROR(ENOMEM);
-            }
-
-            format.metaDataSz = priv->bsfc->par_out->extradata_size;
-            format.pMetaData = av_malloc(format.metaDataSz + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!format.pMetaData) {
-                av_log(avctx, AV_LOG_ERROR,
-                       "Failed to allocate copy of extradata\n");
-                return AVERROR(ENOMEM);
-            }
-            memcpy(format.pMetaData, priv->bsfc->par_out->extradata, format.metaDataSz);
-
-            /* Back up the extradata so it can be restored at close time. */
-            priv->orig_extradata = avctx->extradata;
-            priv->orig_extradata_size = avctx->extradata_size;
-            avctx->extradata = format.pMetaData;
-            avctx->extradata_size = format.metaDataSz;
+        avret = init_bsf(avctx, "h264_mp4toannexb");
+        if (avret != 0) {
+            return avret;
         }
         subtype = BC_MSUBTYPE_H264;
         format.startCodeSz = 4;
+        format.pMetaData  = avctx->extradata;
+        format.metaDataSz = avctx->extradata_size;
+        break;
+    case BC_MSUBTYPE_DIVX:
+        avret = init_bsf(avctx, "mpeg4_unpack_bframes");
+        if (avret != 0) {
+            return avret;
+        }
+        format.pMetaData  = avctx->extradata;
+        format.metaDataSz = avctx->extradata_size;
         break;
     case BC_MSUBTYPE_H264:
         format.startCodeSz = 4;
@@ -466,7 +491,6 @@ static av_cold int init(AVCodecContext *avctx)
     case BC_MSUBTYPE_WMV3:
     case BC_MSUBTYPE_WMVA:
     case BC_MSUBTYPE_MPEG2VIDEO:
-    case BC_MSUBTYPE_DIVX:
     case BC_MSUBTYPE_DIVX311:
         format.pMetaData  = avctx->extradata;
         format.metaDataSz = avctx->extradata_size;
@@ -839,15 +863,6 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
                 priv->last_picture = output.PicInfo.picture_number - 1;
             }
 
-            if (avctx->codec->id == AV_CODEC_ID_MPEG4 &&
-                output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
-                av_log(avctx, AV_LOG_VERBOSE,
-                       "CrystalHD: Not returning packed frame twice.\n");
-                priv->last_picture++;
-                DtsReleaseOutputBuffs(dev, NULL, FALSE);
-                return RET_COPY_AGAIN;
-            }
-
             print_frame_info(priv, &output);
 
             if (priv->last_picture + 1 < output.PicInfo.picture_number) {
@@ -908,22 +923,6 @@ static int decode(AVCodecContext *avctx, void *data, int *got_frame, 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);
 



More information about the ffmpeg-cvslog mailing list