Quoting Martin Storsjö (2016-06-23 13:06:41)
> While it is less featureful (and slower) than the built-in H264
> decoder, one could potentially want to use it to take advantage
> of the cisco patent license offer.
> ---
> I got a user explicitly requesting this feature, so apparently there
> is (some) demand for it.
> 
> The decoder is very simple; it doesn't handle B-frames, so there's
> no decoding delay, and the decoder doesn't allow decoding into
> user-supplied buffers.
> ---
> +static int init_bsf(AVCodecContext *avctx)
> +{
> +    SVCContext *s = avctx->priv_data;
> +    const AVBitStreamFilter *filter;
> +    int ret;
> +
> +    if (s->bsf)
> +        return 0;
> +
> +    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)
> +{
> +    SVCContext *s = avctx->priv_data;
> +    SBufferInfo info = { 0 };
> +    uint8_t* ptrs[3];
> +    int linesize[3];
> +    AVFrame *avframe = data;
> +    int ret;
> +    DECODING_STATE state;
> +
> +    init_bsf(avctx);

The return value should probably be checked.
> +
> +    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);
> +    }
> +
> +    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;
> +        }
> +
> +        avctx->width = info.UsrData.sSystemBuffer.iWidth;
> +        avctx->height = info.UsrData.sSystemBuffer.iHeight;
> +        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;
> +#if FF_API_PKT_PTS
> +FF_DISABLE_DEPRECATION_WARNINGS
> +        avframe->pkt_pts = s->pkt_filtered.pts;
> +FF_ENABLE_DEPRECATION_WARNINGS
> +#endif
> +
> +        *got_frame = 1;
> +    }
> +    return avpkt->size;
> +}
> +
> +AVCodec ff_libopenh264_decoder = {
> +    .name           = "libopenh264",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_H264,
> +    .priv_data_size = sizeof(SVCContext),
> +    .init           = svc_decode_init,
> +    .decode         = svc_decode_frame,
> +    .close          = svc_decode_close,
> +    .long_name      = NULL_IF_CONFIG_SMALL("OpenH264"),
> +    .capabilities   = AV_CODEC_CAP_DELAY, // The decoder itself doesn't have 
> delay, but the BSF might

It does call ff_get_buffer(), so it should be flagged as DR I think.
Even though it's not "proper" DR.

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to