On Thu,  8 Aug 2013 11:48:56 +0200, Luca Barbato <[email protected]> wrote:
> ---
>  configure              |   7 +
>  libavcodec/Makefile    |   3 +
>  libavcodec/allcodecs.c |   1 +
>  libavcodec/qsv.c       | 377 
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/qsv.h       |  63 +++++++++
>  libavcodec/qsv_h264.c  | 132 +++++++++++++++++
>  6 files changed, 583 insertions(+)
>  create mode 100644 libavcodec/qsv.c
>  create mode 100644 libavcodec/qsv.h
>  create mode 100644 libavcodec/qsv_h264.c
> 
> +
> +int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
> +                  AVFrame *frame, int *got_frame,
> +                  AVPacket *avpkt)
> +{
> +    mfxFrameSurface1 *insurf;
> +    mfxFrameSurface1 *outsurf;
> +    mfxSyncPoint sync;
> +    int ret, i = 0;
> +    int size = avpkt->size;
> +
> +    *got_frame = 0;
> +
> +    av_packet_list_put(&q->pending, &q->pending_end, avpkt);
> +
> +    if (!q->wait) {
> +        av_packet_list_get(&q->pending, &q->pending_end, avpkt);
> +
> +        if ((ret = put_dts(q, avpkt->pts, avpkt->dts)) < 0)
> +            return ret;
> +
> +        q->bs.TimeStamp = avpkt->pts;
> +
> +        ret = bitstream_enqueue(&q->bs, avpkt->data, avpkt->size);
> +
> +        av_packet_unref(avpkt);
> +
> +        if (ret < 0)
> +            return ret;
> +    }
> +
> +    ret = MFX_ERR_MORE_SURFACE;
> +
> +    while ((insurf = get_surface(q)) && ret == MFX_ERR_MORE_SURFACE) {
> +        ret = MFXVideoDECODE_DecodeFrameAsync(q->session, &q->bs,
> +                                              insurf, &outsurf, &sync);
> +    }
> +
> +    q->wait = 1;
> +
> +    switch (ret) {
> +    case MFX_ERR_MORE_DATA:
> +        q->wait = 0;
> +        ret = 0;
> +        break;
> +    case MFX_WRN_VIDEO_PARAM_CHANGED:
> +    // FIXME handle the param change properly.
> +    //  ret = MFXVideoDECODE_QueryIOSurf(q->session, &q->qsv.param, &req);
> +    //    if (ret < 0)
> +    //        return ff_qsv_error(ret);
> +        ret = 0;
> +    default:
> +        break;
> +    }
> +
> +    if (sync) {
> +        int64_t dts;
> +
> +        MFXVideoCORE_SyncOperation(q->session, sync, 60000);
> +
> +        if ((ret = get_dts(q, outsurf->Data.TimeStamp, &dts)) < 0)
> +            return ret;
> +
> +        if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> +            return ret;
> +        }
> +
> +        *got_frame = 1;
> +
> +        frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
> +        frame->pkt_dts = dts;
> +
> +        frame->repeat_pict =
> +            outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED;
> +        frame->top_field_first =
> +            outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
> +        frame->interlaced_frame =
> +            !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
> +
> +        for (i = 0; i < frame->height; i++) {
> +            memcpy(frame->data[0] + frame->linesize[0] * i,
> +                   outsurf->Data.Y + outsurf->Data.Pitch * i,
> +                   FFMIN(outsurf->Data.Pitch, frame->linesize[0]));
> +        }
> +        for (i = 0; i < frame->height/2; i++) {
> +            memcpy(frame->data[1] + frame->linesize[1] * i,
> +                   outsurf->Data.UV + outsurf->Data.Pitch * i,
> +                   FFMIN(outsurf->Data.Pitch, frame->linesize[1]));
> +        }

This is evil.
Is there no way to avoid to avoid the copy?

> +
> +static av_cold int qsv_dec_init(AVCodecContext *avctx)
> +{
> +    QSVH264Context *q        = avctx->priv_data;
> +    mfxBitstream *bs         = &q->qsv.bs;
> +    int ret;
> +
> +    avctx->pix_fmt = AV_PIX_FMT_NV12;
> +
> +    if (!(q->bsf = av_bitstream_filter_init("h264_mp4toannexb")))
> +        return AVERROR(ENOMEM);
> +
> +    // Data and DataLength passed as dummy pointers
> +    av_bitstream_filter_filter(q->bsf, avctx, NULL,
> +                               &bs->Data, &bs->DataLength,
> +                               NULL, 0, 0);
> +
> +    //FIXME feed it a fake IDR directly
> +    bs->Data = av_malloc(avctx->extradata_size + sizeof(fake_idr));
> +    bs->DataLength = avctx->extradata_size;
> +
> +    memcpy(bs->Data, avctx->extradata, avctx->extradata_size);
> +    memcpy(bs->Data + bs->DataLength, fake_idr, sizeof(fake_idr));
> +
> +    bs->DataLength += sizeof(fake_idr);
> +
> +    bs->MaxLength = bs->DataLength;
> +
> +    ret = ff_qsv_init(avctx, &q->qsv);
> +    if (ret < 0)
> +        av_bitstream_filter_close(q->bsf);

leaking Data?

> +
> +AVCodec ff_h264_qsv_decoder = {
> +    .name           = "h264_qsv",
> +    .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / 
> MPEG-4 part 10 (Intel Quick Sync Video acceleration)"),
> +    .priv_data_size = sizeof(QSVH264Context),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_H264,
> +    .init           = qsv_dec_init,
> +    .decode         = qsv_dec_frame,
> +    .flush          = qsv_dec_flush,
> +    .close          = qsv_dec_close,
> +    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_PKT_TS,

missing DR


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

Reply via email to