libopenh264dec: Let the framework use the h264_mp4toannexb bitstream filter
authorMartin Storsjö <martin@martin.st>
Wed, 15 Feb 2017 09:06:17 +0000 (11:06 +0200)
committerMartin Storsjö <martin@martin.st>
Wed, 15 Feb 2017 21:05:58 +0000 (23:05 +0200)
This avoids a lot of boilerplate code within the decoder wrapper itself.

Signed-off-by: Martin Storsjö <martin@martin.st>
libavcodec/libopenh264dec.c

index cc18f24..d65d639 100644 (file)
 
 typedef struct SVCContext {
     ISVCDecoder *decoder;
-    AVBSFContext *bsf;
-    AVFifoBuffer *packet_fifo;
-    AVPacket pkt_filtered;
 } SVCContext;
 
 static av_cold int svc_decode_close(AVCodecContext *avctx)
 {
     SVCContext *s = avctx->priv_data;
-    AVPacket pkt;
 
     if (s->decoder)
         WelsDestroyDecoder(s->decoder);
 
-    while (s->packet_fifo && av_fifo_size(s->packet_fifo) >= sizeof(pkt)) {
-        av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL);
-        av_packet_unref(&pkt);
-    }
-
-    av_bsf_free(&s->bsf);
-    av_packet_unref(&s->pkt_filtered);
-    av_fifo_free(s->packet_fifo);
-
     return 0;
 }
 
@@ -71,10 +58,6 @@ static av_cold int svc_decode_init(AVCodecContext *avctx)
     if ((err = ff_libopenh264_check_version(avctx)) < 0)
         return err;
 
-    s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
-    if (!s->packet_fifo)
-        return AVERROR(ENOMEM);
-
     if (WelsCreateDecoder(&s->decoder)) {
         av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n");
         return AVERROR_UNKNOWN;
@@ -103,38 +86,6 @@ static av_cold int svc_decode_init(AVCodecContext *avctx)
     return 0;
 }
 
-static int init_bsf(AVCodecContext *avctx)
-{
-    SVCContext *s = avctx->priv_data;
-    const AVBitStreamFilter *filter;
-    int ret;
-
-    if (s->bsf)
-        return 0;
-
-    // If the input stream already is annex b, this BSF only passes the
-    // packets through unchanged.
-    filter = av_bsf_get_by_name("h264_mp4toannexb");
-    if (!filter)
-        return AVERROR_BUG;
-
-    ret = av_bsf_alloc(filter, &s->bsf);
-    if (ret < 0)
-        return ret;
-
-    ret = avcodec_parameters_from_context(s->bsf->par_in, avctx);
-    if (ret < 0)
-        return ret;
-
-    s->bsf->time_base_in = avctx->time_base;
-
-    ret = av_bsf_init(s->bsf);
-    if (ret < 0)
-        return ret;
-
-    return ret;
-}
-
 static int svc_decode_frame(AVCodecContext *avctx, void *data,
                             int *got_frame, AVPacket *avpkt)
 {
@@ -143,85 +94,39 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data,
     uint8_t* ptrs[3];
     int linesize[3];
     AVFrame *avframe = data;
-    int ret;
     DECODING_STATE state;
 
-    if ((ret = init_bsf(avctx)) < 0)
-        return ret;
-
-    if (avpkt->size) {
-        AVPacket input_ref = { 0 };
-        if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
-            ret = av_fifo_realloc2(s->packet_fifo,
-                                   av_fifo_size(s->packet_fifo) + sizeof(input_ref));
-            if (ret < 0)
-                return ret;
-        }
-
-        ret = av_packet_ref(&input_ref, avpkt);
-        if (ret < 0)
-            return ret;
-        av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
+    state = (*s->decoder)->DecodeFrame2(s->decoder, avpkt->data, avpkt->size, ptrs, &info);
+    if (state != dsErrorFree) {
+        av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n");
+        return AVERROR_UNKNOWN;
+    }
+    if (info.iBufferStatus != 1) {
+        av_log(avctx, AV_LOG_DEBUG, "No frame produced\n");
+        return avpkt->size;
     }
 
-    while (!*got_frame) {
-        /* prepare the input data -- convert to Annex B if needed */
-        if (s->pkt_filtered.size <= 0) {
-            AVPacket input_ref;
-
-            /* no more data */
-            if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
-                return avpkt->size ? avpkt->size : 0;
-
-            av_packet_unref(&s->pkt_filtered);
-
-            av_fifo_generic_read(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
-            ret = av_bsf_send_packet(s->bsf, &input_ref);
-            if (ret < 0) {
-                av_packet_unref(&input_ref);
-                return ret;
-            }
-
-            ret = av_bsf_receive_packet(s->bsf, &s->pkt_filtered);
-            if (ret < 0)
-                av_packet_move_ref(&s->pkt_filtered, &input_ref);
-            else
-                av_packet_unref(&input_ref);
-        }
-
-        state = (*s->decoder)->DecodeFrame2(s->decoder, s->pkt_filtered.data, s->pkt_filtered.size, ptrs, &info);
-        s->pkt_filtered.size = 0;
-        if (state != dsErrorFree) {
-            av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n");
-            return AVERROR_UNKNOWN;
-        }
-        if (info.iBufferStatus != 1) {
-            av_log(avctx, AV_LOG_DEBUG, "No frame produced\n");
-            continue;
-        }
-
-        ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight);
-        // The decoder doesn't (currently) support decoding into a user
-        // provided buffer, so do a copy instead.
-        if (ff_get_buffer(avctx, avframe, 0) < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n");
-            return AVERROR(ENOMEM);
-        }
-
-        linesize[0] = info.UsrData.sSystemBuffer.iStride[0];
-        linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1];
-        av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height);
-
-        avframe->pts     = s->pkt_filtered.pts;
-        avframe->pkt_dts = s->pkt_filtered.dts;
+    ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight);
+    // The decoder doesn't (currently) support decoding into a user
+    // provided buffer, so do a copy instead.
+    if (ff_get_buffer(avctx, avframe, 0) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n");
+        return AVERROR(ENOMEM);
+    }
+
+    linesize[0] = info.UsrData.sSystemBuffer.iStride[0];
+    linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1];
+    av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height);
+
+    avframe->pts     = avpkt->pts;
+    avframe->pkt_dts = avpkt->dts;
 #if FF_API_PKT_PTS
 FF_DISABLE_DEPRECATION_WARNINGS
-        avframe->pkt_pts = s->pkt_filtered.pts;
+    avframe->pkt_pts = avpkt->pts;
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-        *got_frame = 1;
-    }
+    *got_frame = 1;
     return avpkt->size;
 }
 
@@ -239,4 +144,5 @@ AVCodec ff_libopenh264_decoder = {
     .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
+    .bsfs           = "h264_mp4toannexb",
 };