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