Skip to content
Snippets Groups Projects
vaapi_encode.c 35.2 KiB
Newer Older
  • Learn to ignore specific revisions
  •     ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data;
    
        ctx->recon_frames->format    = AV_PIX_FMT_VAAPI;
        ctx->recon_frames->sw_format = recon_format;
        ctx->recon_frames->width     = ctx->aligned_width;
        ctx->recon_frames->height    = ctx->aligned_height;
        ctx->recon_frames->initial_pool_size = ctx->nb_recon_frames;
    
        err = av_hwframe_ctx_init(ctx->recon_frames_ref);
        if (err < 0) {
            av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
                   "frame context: %d.\n", err);
            goto fail;
        }
        recon_hwctx = ctx->recon_frames->hwctx;
    
        vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
                              ctx->aligned_width, ctx->aligned_height,
                              VA_PROGRESSIVE,
                              recon_hwctx->surface_ids,
                              recon_hwctx->nb_surfaces,
                              &ctx->va_context);
        if (vas != VA_STATUS_SUCCESS) {
            av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
                   "context: %d (%s).\n", vas, vaErrorStr(vas));
            err = AVERROR(EIO);
            goto fail;
        }
    
        ctx->input_order  = 0;
        ctx->output_delay = avctx->max_b_frames;
        ctx->decode_delay = 1;
        ctx->output_order = - ctx->output_delay - 1;
    
        if (ctx->codec->sequence_params_size > 0) {
            ctx->codec_sequence_params =
                av_mallocz(ctx->codec->sequence_params_size);
            if (!ctx->codec_sequence_params) {
                err = AVERROR(ENOMEM);
                goto fail;
            }
        }
        if (ctx->codec->picture_params_size > 0) {
            ctx->codec_picture_params =
                av_mallocz(ctx->codec->picture_params_size);
            if (!ctx->codec_picture_params) {
                err = AVERROR(ENOMEM);
                goto fail;
            }
        }
    
        if (ctx->codec->init_sequence_params) {
            err = ctx->codec->init_sequence_params(avctx);
            if (err < 0) {
                av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
                       "failed: %d.\n", err);
                goto fail;
            }
        }
    
        // All I are IDR for now.
        ctx->i_per_idr = 0;
        ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) /
                        (avctx->max_b_frames + 1));
        ctx->b_per_p = avctx->max_b_frames;
    
        // This should be configurable somehow.  (Needs testing on a machine
        // where it actually overlaps properly, though.)
        ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT;
    
        return 0;
    
    fail:
        av_freep(&hwconfig);
        av_hwframe_constraints_free(&constraints);
        ff_vaapi_encode_close(avctx);
        return err;
    }
    
    av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
    {
        VAAPIEncodeContext *ctx = avctx->priv_data;
        VAAPIEncodePicture *pic, *next;
    
        for (pic = ctx->pic_start; pic; pic = next) {
            next = pic->next;
            vaapi_encode_free(avctx, pic);
        }
    
        if (ctx->va_context != VA_INVALID_ID)
            vaDestroyContext(ctx->hwctx->display, ctx->va_context);
    
        if (ctx->va_config != VA_INVALID_ID)
            vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
    
        if (ctx->codec->close)
            ctx->codec->close(avctx);
    
        av_freep(&ctx->codec_sequence_params);
        av_freep(&ctx->codec_picture_params);
    
        av_buffer_unref(&ctx->recon_frames_ref);
        av_buffer_unref(&ctx->input_frames_ref);
        av_buffer_unref(&ctx->device_ref);
    
        av_freep(&ctx->priv_data);
    
        return 0;
    }