[FFmpeg-devel] [PATCH] CrystalHD: Use mp4toannexb bitstream filter.

Philip Langdale philipl at overt.org
Sat Jun 11 20:07:21 CEST 2011


The H.264 parser that we use to detect interlacing can only handle
an Annex B stream, so we need to actually use the filter. This may
seem unfortunate as it requires an extra copy, but I suspect the
crystalhd library is doing it internally for non-Annex B streams
anyway.

This diff seems functional in that it prevents the parser errors
I was seeing when playing non-Annex B streams, but it apparently
doesn't fix the memory leak that wallak saw. In additional testing,
he showed that the filter was the source of the leak, so I must
be using it incorrectly, but I'm not sure what I should be doing
different.
---
 libavcodec/crystalhd.c |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 3c80217..82fcbe8 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -124,6 +124,7 @@ typedef struct {
     AVFrame pic;
     HANDLE dev;
 
+    AVBitStreamFilterContext *bsfc;
     AVCodecParserContext *parser;
 
     uint8_t is_70012;
@@ -338,6 +339,9 @@ static av_cold int uninit(AVCodecContext *avctx)
     DtsDeviceClose(device);
 
     av_parser_close(priv->parser);
+    if (priv->bsfc) {
+        av_bitstream_filter_close(priv->bsfc);
+    }
 
     av_free(priv->sps_pps_buf);
 
@@ -397,7 +401,6 @@ static av_cold int init(AVCodecContext *avctx)
         {
             uint8_t *dummy_p;
             int dummy_int;
-            AVBitStreamFilterContext *bsfc;
 
             uint32_t orig_data_size = avctx->extradata_size;
             uint8_t *orig_data = av_malloc(orig_data_size);
@@ -409,16 +412,15 @@ static av_cold int init(AVCodecContext *avctx)
             memcpy(orig_data, avctx->extradata, orig_data_size);
 
 
-            bsfc = av_bitstream_filter_init("h264_mp4toannexb");
-            if (!bsfc) {
+            priv->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
+            if (!priv->bsfc) {
                 av_log(avctx, AV_LOG_ERROR,
                        "Cannot open the h264_mp4toannexb BSF!\n");
                 av_free(orig_data);
                 return AVERROR_BSF_NOT_FOUND;
             }
-            av_bitstream_filter_filter(bsfc, avctx, NULL, &dummy_p,
+            av_bitstream_filter_filter(priv->bsfc, avctx, NULL, &dummy_p,
                                        &dummy_int, NULL, 0, 0);
-            av_bitstream_filter_close(bsfc);
 
             priv->sps_pps_buf     = avctx->extradata;
             priv->sps_pps_size    = avctx->extradata_size;
@@ -512,6 +514,7 @@ static av_cold int init(AVCodecContext *avctx)
             av_log(avctx, AV_LOG_WARNING,
                    "Cannot open the h.264 parser! Interlaced h.264 content "
                    "will not be detected reliably.\n");
+        priv->parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
     }
     av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
 
@@ -831,6 +834,17 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a
         int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
 
         if (priv->parser) {
+            if (priv->bsfc) {
+                /*
+                 * The filter API will always realloc and replace the input
+                 * buffer, whether you want it to or not.
+                 */
+                av_bitstream_filter_filter(priv->bsfc, avctx, NULL,
+                                           &avpkt->data, &avpkt->size,
+                                           avpkt->data, avpkt->size, 0);
+                len = avpkt->size;
+            }
+
             uint8_t *pout;
             int psize;
             const uint8_t *in_data = avpkt->data;
-- 
1.7.4.1



More information about the ffmpeg-devel mailing list