From patchwork Wed Nov 8 08:20:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jun Zhao X-Patchwork-Id: 5987 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.90 with SMTP id m26csp448901jah; Wed, 8 Nov 2017 00:20:54 -0800 (PST) X-Google-Smtp-Source: ABhQp+SZMsmVatEdu4rALjB8/t7Rc8MxhhJfM2+ZQX/qwRKWs338GWlX6O0apxdtd657g71NPAAh X-Received: by 10.223.147.39 with SMTP id 36mr1121369wro.175.1510129254400; Wed, 08 Nov 2017 00:20:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510129254; cv=none; d=google.com; s=arc-20160816; b=rTSMgfvVsTcRf4Dc8G2RRwLIRH5oUKc4Zp+IuX2DTw6PkLiVXxZbqUsDVyBmnuDpxV 9HVAejpn/Ugqmszr1bYqV8TrnZBODRbT1/ZbMk+XVqCtX1Puz6aeqn+15wvwUCuXOCWt hzguD/azZgnNsBYwi3kh2TVHnyKhY+zC3I09wzDYXDZoSAhfgIPmYLfnj5Dl3JCjR41L KjaSLmCU0wPrN+ojqN45d7RyPsIJ3SjqeSJRFZxBh2t1nV8uF8Xl2BKL8wt3rVylb3CQ JkT1L8vIv6p84PgOLPXQ0YqMaSrC3DVmWrPgXqCLolX+QXaGkLlFikGzR/B68AfUXwNr CAUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :content-language:mime-version:user-agent:date:message-id:from:to :dkim-signature:delivered-to:arc-authentication-results; bh=QBDxvoUrmH4z5lxjCQ62q4bJHNLEe0T7VpOkrF6jSoI=; b=gihZqTsNPboTrvQJIwGNUJgxEEVtD3NKCqbiKlUBYOa3SYhq8jsXOXwcbjBnJEqwi0 yyB8GA68xthw6fihdhZyhatkt4XtgjdZN09AEqDgpm0U1TCfuwCb5/IgQ9ZaZcroxY9F wTgWMT2ZS7DUvDbWQUbG809OQeP3EGKJwIo1OwBJii6JRptS650F/pOoHOg+lqaHCkwU DILlnJnbl0D3B3IBiF6IozIMTEPsrZS8nKeQ7cwPZstNFQquk1pzaYux1IcIoJgsnjQG bJiuhrLMG1+Vf9nJm+lLcXx1zMAPMZhvzGE7+YjnKw9xmnUslwEn4JAJ092RXra0JDBi 8QSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=YpNeb+a6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g9si2775956wmf.55.2017.11.08.00.20.53; Wed, 08 Nov 2017 00:20:54 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=YpNeb+a6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AA7AF689C32; Wed, 8 Nov 2017 10:20:35 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pl0-f44.google.com (mail-pl0-f44.google.com [209.85.160.44]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 60A9D689C15 for ; Wed, 8 Nov 2017 10:20:34 +0200 (EET) Received: by mail-pl0-f44.google.com with SMTP id g15so828278plk.10 for ; Wed, 08 Nov 2017 00:20:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=ER+AHdyMoZVlsQiyi5wyWTEgrhMM9yO14WF7ugjNS00=; b=YpNeb+a6YSMNrNf9QqAZZcP/gDoXOMd63kSlXSvRx6vE9siITmZAER6RCQonY0rJR9 wnWmG4Tcsrhj5Jv/HMZkcr3zD2kEmDrO2zJd8fAxkNAHn49gUiPtdMtKoTttdEWpAhgi NNSRFJb7rAEJtc6OPBgTWWgRtPJwpBpYZ/CH4uP1R3RBhuKGCMOIs749t63PTa4+yw4b yXx32wp9VhawQw1aSuXjGpZWVWrk8CBnfOkRNMaqWNC235D8iZNSd780l7RhgNogRiil 7GDW3KXA6dedAV3oS5ReQF0uhFi7QZDyUTWVfHJaCVFqqx5Kg/BHpXpuMM4Rf8qxWQBa sNRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=ER+AHdyMoZVlsQiyi5wyWTEgrhMM9yO14WF7ugjNS00=; b=oAMeDc64tcRqHUVA1oNNqrmEFQNucTw67HaShYHoSFiBDJpo8OnzYWfFe8esWE68s2 ISnufVYEGYC41Ot5PuPy3StsHblVSTsthvx47corZU8prhhwHAyjxiOG8p9Mjm/AuzKK n9r49VJi5+BfZEm0+RIplCMZauFcTuH5EUN6L+78Ym2+MLI2r7+GrizYZNK8XZ0p8QB6 rTfdQcI5EXMHWEGd2EtwxHwuVe6I283Tg0++F1Fz5lBKM+8btZjg1OltXKHZeYun2LIy 5W/6eJr7l13BOI5dJ6zqpPlgY4gKcqENMrKBQHg/qEb+vl61cj6VwXA2qGpjL1cG9kS1 xCjQ== X-Gm-Message-State: AJaThX7Sw9157OfFEm6lM93f3TCqmJBLEFwUoLpALd2WMw35SKsqwyHe UssiACggnUYFl9L53hNL3HE= X-Received: by 10.84.160.204 with SMTP id v12mr1492899plg.206.1510129245628; Wed, 08 Nov 2017 00:20:45 -0800 (PST) Received: from [10.67.68.23] ([192.55.54.41]) by smtp.gmail.com with ESMTPSA id x4sm5722792pge.23.2017.11.08.00.20.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 08 Nov 2017 00:20:45 -0800 (PST) To: FFmpeg development discussions and patches , Mark Thompson From: Jun Zhao Message-ID: <4b6c8abe-e2f1-af03-a136-1a4a6236b0e6@gmail.com> Date: Wed, 8 Nov 2017 16:20:40 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 Content-Language: en-US Subject: [FFmpeg-devel] [PATCH 2/3] lavc/vaapi_encode_h264: enable mutil-reference frames. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From ed976e6cde34521ffd59269100d49526e68a301e Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 7 Nov 2017 14:32:42 +0800 Subject: [PATCH 2/3] lavc/vaapi_encode_h264: enable mutil-reference frames. Add mutil-reference frames support and respect "refs" option in h264_vaapi encoder. Signed-off-by: Jun Zhao Signed-off-by: Wang, Yi A --- libavcodec/vaapi_encode_h264.c | 435 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 421 insertions(+), 14 deletions(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 1d43e934ef..479783bdf4 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -40,6 +40,8 @@ enum { SEI_RECOVERY_POINT = 0x04, }; +static const char *picture_type_name[] = { "IDR", "I", "P", "B" }; + // Random (version 4) ISO 11578 UUID. static const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = { 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf, @@ -82,6 +84,11 @@ typedef struct VAAPIEncodeH264Context { CodedBitstreamFragment current_access_unit; int aud_needed; int sei_needed; + + // reference frames param + struct VAAPIEncodePicture *references[MAX_PICTURE_REFERENCES]; + int ref_nr; + int max_ref_nr; } VAAPIEncodeH264Context; typedef struct VAAPIEncodeH264Options { @@ -302,9 +309,7 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) sps->log2_max_pic_order_cnt_lsb_minus4 = av_clip(av_log2(ctx->b_per_p + 1) - 2, 0, 12); - sps->max_num_ref_frames = - (avctx->profile & FF_PROFILE_H264_INTRA) ? 0 : - 1 + (ctx->b_per_p > 0); + sps->max_num_ref_frames = (avctx->profile & FF_PROFILE_H264_INTRA) ? 0 : priv->max_ref_nr; sps->pic_width_in_mbs_minus1 = priv->mb_width - 1; sps->pic_height_in_map_units_minus1 = priv->mb_height - 1; @@ -737,19 +742,23 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, vslice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID; } - av_assert0(pic->nb_refs <= 2); - if (pic->nb_refs >= 1) { - // Backward reference for P- or B-frame. - av_assert0(pic->type == PICTURE_TYPE_P || - pic->type == PICTURE_TYPE_B); - vslice->RefPicList0[0] = vpic->ReferenceFrames[0]; + sh->num_ref_idx_active_override_flag = 1; + + if (pic->type == PICTURE_TYPE_P) { + for (i = 0; i < pic->nb_refs; i++) + vslice->RefPicList0[i] = vpic->ReferenceFrames[pic->nb_refs - 1 - i]; + sh->num_ref_idx_l0_active_minus1 = pic->nb_refs - 1; } - if (pic->nb_refs >= 2) { - // Forward reference for B-frame. - av_assert0(pic->type == PICTURE_TYPE_B); - vslice->RefPicList1[0] = vpic->ReferenceFrames[1]; + + if (pic->type == PICTURE_TYPE_B) { + for (i = 0; i < pic->nb_refs - 1; i++) + vslice->RefPicList0[i] = vpic->ReferenceFrames[pic->nb_refs - 2 - i]; + vslice->RefPicList1[0] = vpic->ReferenceFrames[pic->nb_refs - 1]; + sh->num_ref_idx_l0_active_minus1 = pic->nb_refs - 2; } + vslice->num_ref_idx_active_override_flag = sh->num_ref_idx_active_override_flag; + vslice->num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1; vslice->slice_qp_delta = sh->slice_qp_delta; return 0; @@ -834,6 +843,34 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx) } } + priv->max_ref_nr = avctx->refs; + + if (priv->max_ref_nr > ctx->max_ref_l0 + ctx->max_ref_l1) { + av_log(avctx, AV_LOG_WARNING, "Warning: " \ + "reference frame number exceeds %d" \ + "correct to %d\n", \ + ctx->max_ref_l0 + ctx->max_ref_l1, + ctx->max_ref_l0 + ctx->max_ref_l1); + priv->max_ref_nr = ctx->max_ref_l0 + ctx->max_ref_l1; + } + if (avctx->max_b_frames && priv->max_ref_nr < 2) { + av_log(avctx, AV_LOG_WARNING, "Warning: " \ + "reference frame number is 1 but b frame encoding is setted," \ + "correct to 2\n"); + priv->max_ref_nr = 2; + } + if (!avctx->max_b_frames && priv->max_ref_nr > ctx->max_ref_l0) { + av_log(avctx, AV_LOG_WARNING, "Warning: " \ + "no b frame, but ref_nr > max_ref_l0" \ + "correct to %d\n", ctx->max_ref_l0); + priv->max_ref_nr = ctx->max_ref_l0; + } + if (priv->max_ref_nr < 1 && avctx->gop_size) { + av_log(avctx, AV_LOG_WARNING, "Warning: " \ + "reference frame number is %d but gop_size > 0," \ + "correct to 1\n", priv->max_ref_nr); + priv->max_ref_nr = 1; + } return 0; } @@ -958,6 +995,376 @@ static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx) return ff_vaapi_encode_close(avctx); } +static void vaapi_encode_h264_add_reference (AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + int i; + + av_assert0 (pic->type != PICTURE_TYPE_B); + + if (pic->type == PICTURE_TYPE_IDR) { + // clear the reference frame list + for (i = 0 ; i < priv->ref_nr; i++) { + priv->references[i]->ref_count --; + priv->references[i] = NULL; + } + priv->ref_nr = 0; + } + + if (priv->ref_nr == priv->max_ref_nr) { + // remove the oldest reference frame + for (i = 0 ; i < priv->ref_nr - 1; i++) { + priv->references[i]->ref_count --; + priv->references[i] = priv->references[i+1]; + priv->references[i]->ref_count ++; + } + priv->references[priv->ref_nr-1]->ref_count--; + priv->ref_nr --; + } + + priv->references[priv->ref_nr] = pic; + priv->references[priv->ref_nr]->ref_count ++; + priv->ref_nr++; +} + + +static int vaapi_encode_h264_get_next(AVCodecContext *avctx, + VAAPIEncodePicture **pic_out) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodePicture *start, *end, *pic; + int i,j; + + for (pic = ctx->pic_start; pic; pic = pic->next) { + if (pic->next) + av_assert0(pic->display_order < pic->next->display_order); + if (pic->display_order == ctx->input_order) { + *pic_out = pic; + return 0; + } + } + + pic = vaapi_encode_alloc(); + if (!pic) + return AVERROR(ENOMEM); + + if (ctx->input_order == 0 || ctx->force_idr || + ctx->gop_counter >= avctx->gop_size) { + pic->type = PICTURE_TYPE_IDR; + ctx->force_idr = 0; + ctx->gop_counter = 1; + ctx->p_counter = 0; + } else if (ctx->p_counter >= ctx->p_per_i) { + pic->type = PICTURE_TYPE_I; + ++ctx->gop_counter; + ctx->p_counter = 0; + } else { + pic->type = PICTURE_TYPE_P; + for (i = 0 ; i < priv->ref_nr; i++) { + pic->refs[i] = priv->references[i]; + pic->refs[i]->ref_count++; + } + pic->nb_refs = priv->ref_nr; + ++ctx->gop_counter; + ++ctx->p_counter; + } + start = end = pic; + vaapi_encode_h264_add_reference(avctx, pic); + + if (pic->type != PICTURE_TYPE_IDR) { + // If that was not an IDR frame, add B-frames display-before and + // encode-after it, but not exceeding the GOP size. + + for (i = 0; i < ctx->b_per_p && + ctx->gop_counter < avctx->gop_size; i++) { + pic = vaapi_encode_alloc(); + if (!pic) + goto fail; + + pic->type = PICTURE_TYPE_B; + for (j = 0 ; j < priv->ref_nr; j++) { + pic->refs[j] = priv->references[j]; + pic->refs[j]->ref_count++; + } + pic->nb_refs = priv->ref_nr; + pic->next = start; + pic->display_order = ctx->input_order + ctx->b_per_p - i - 1; + pic->encode_order = pic->display_order + 1; + start = pic; + + ++ctx->gop_counter; + } + } + + if (ctx->input_order == 0) { + pic->display_order = 0; + pic->encode_order = 0; + + ctx->pic_start = ctx->pic_end = pic; + + } else { + for (i = 0, pic = start; pic; i++, pic = pic->next) { + pic->display_order = ctx->input_order + i; + if (end->type == PICTURE_TYPE_IDR) + pic->encode_order = ctx->input_order + i; + else if (pic == end) + pic->encode_order = ctx->input_order; + else + pic->encode_order = ctx->input_order + i + 1; + } + + av_assert0(ctx->pic_end); + ctx->pic_end->next = start; + ctx->pic_end = end; + } + *pic_out = start; + + av_log(avctx, AV_LOG_DEBUG, "Pictures:"); + for (pic = ctx->pic_start; pic; pic = pic->next) { + av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", + picture_type_name[pic->type], + pic->display_order, pic->encode_order); + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + + return 0; + +fail: + while (start) { + pic = start->next; + vaapi_encode_free(avctx, start); + start = pic; + } + return AVERROR(ENOMEM); +} + +static int vaapi_encode_h264_clear_old(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic, *next; + pic = ctx->pic_start; + while (pic && pic->next) { + if (pic->encode_order > ctx->output_order) + break; + + if (pic->ref_count == 0 && pic == ctx->pic_start) { + ctx->pic_start = pic->next; + vaapi_encode_free(avctx, pic); + pic = ctx->pic_start; + continue; + } + next = pic->next; + + if (next->encode_order > ctx->output_order) + break; + if (next->ref_count == 0) { + pic->next = next->next; + vaapi_encode_free(avctx, next); + } + pic = pic->next; + } + return 0; +} + +static int vaapi_encode_h264_truncate_gop(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH264Context *priv = ctx->priv_data; + VAAPIEncodePicture *pic, *last_pic, *next; + + // Find the last picture we actually have input for. + for (pic = ctx->pic_start; pic; pic = pic->next) { + if (!pic->input_available) + break; + last_pic = pic; + } + + if (pic) { + av_assert0(last_pic); + + if (last_pic->type == PICTURE_TYPE_B) { + // Some fixing up is required. Change the type of this + // picture to P, then modify preceding B references which + // point beyond it to point at it instead. + int last_ref = last_pic->nb_refs - 1; + + last_pic->type = PICTURE_TYPE_P; + last_pic->encode_order = last_pic->refs[last_ref]->encode_order; + + for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) { + if (pic->type == PICTURE_TYPE_B && + pic->refs[last_ref] == last_pic->refs[last_ref]) { + if (last_pic->refs[last_ref]) + pic->refs[last_ref]->ref_count --; + pic->refs[last_ref] = last_pic; + pic->refs[last_ref]->ref_count ++; + } + } + + last_pic->nb_refs = last_pic->refs[last_ref] ? last_pic->nb_refs - 1 : last_pic->nb_refs; + + if (last_pic->refs[last_ref]) + last_pic->refs[last_ref]->ref_count--; + last_pic->refs[last_ref] = NULL; + } else { + // We can use the current structure (no references point + // beyond the end), but there are unused pics to discard. + } + + // Discard all following pics, they will never be used. + for (pic = last_pic->next; pic; pic = next) { + int i; + int ref_nr = priv->ref_nr; + next = pic->next; + + for (i = 0; i < pic->nb_refs; i++) { + pic->refs[i]->ref_count--; + } + for (i = 0 ; i < ref_nr; i++) { + if (priv->references[i] == pic) { + priv->references[i]->ref_count--; + priv->references[i] = NULL; + priv->ref_nr --; + } + } + vaapi_encode_free(avctx, pic); + } + + last_pic->next = NULL; + ctx->pic_end = last_pic; + + } else { + // Input is available for all pictures, so we don't need to + // mangle anything. + } + + av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:"); + for (pic = ctx->pic_start; pic; pic = pic->next) { + av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", + picture_type_name[pic->type], + pic->display_order, pic->encode_order); + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + + return 0; +} + +static av_cold int vaapi_encode_h264_encode(AVCodecContext *avctx, + AVPacket *pkt, + const AVFrame *input_image, + int *got_packet) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *pic; + int err; + + if (input_image) { + av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n", + input_image->width, input_image->height, input_image->pts); + + if (input_image->pict_type == AV_PICTURE_TYPE_I) { + err = vaapi_encode_h264_truncate_gop(avctx); + if (err < 0) + goto fail; + ctx->force_idr = 1; + } + + err = vaapi_encode_h264_get_next(avctx, &pic); + if (err) { + av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err); + return err; + } + + pic->input_image = av_frame_alloc(); + if (!pic->input_image) { + err = AVERROR(ENOMEM); + goto fail; + } + err = av_frame_ref(pic->input_image, input_image); + if (err < 0) + goto fail; + pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3]; + pic->pts = input_image->pts; + + if (ctx->input_order == 0) + ctx->first_pts = pic->pts; + if (ctx->input_order == ctx->decode_delay) + ctx->dts_pts_diff = pic->pts - ctx->first_pts; + if (ctx->output_delay > 0) + ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts; + + pic->input_available = 1; + + } else { + if (!ctx->end_of_stream) { + err = vaapi_encode_h264_truncate_gop(avctx); + if (err < 0) + goto fail; + ctx->end_of_stream = 1; + } + } + + ++ctx->input_order; + ++ctx->output_order; + av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order); + + for (pic = ctx->pic_start; pic; pic = pic->next) + if (pic->encode_order == ctx->output_order) + break; + + // pic can be null here if we don't have a specific target in this + // iteration. We might still issue encodes if things can be overlapped, + // even though we don't intend to output anything. + + err = vaapi_encode_step(avctx, pic); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); + goto fail; + } + + if (!pic) { + *got_packet = 0; + } else { + err = vaapi_encode_output(avctx, pic, pkt); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); + goto fail; + } + + if (ctx->output_delay == 0) { + pkt->dts = pkt->pts; + } else if (ctx->output_order < ctx->decode_delay) { + if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff) + pkt->dts = INT64_MIN; + else + pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff; + } else { + pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) % + (3 * ctx->output_delay)]; + } + + *got_packet = 1; + } + + err = vaapi_encode_h264_clear_old(avctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err); + goto fail; + } + + return 0; + +fail: + // Unclear what to clean up on failure. There are probably some things we + // could do usefully clean up here, but for now just leave them for uninit() + // to do instead. + return err; +} + + #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ offsetof(VAAPIEncodeH264Options, x)) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) @@ -1024,7 +1431,7 @@ AVCodec ff_h264_vaapi_encoder = { .priv_data_size = (sizeof(VAAPIEncodeContext) + sizeof(VAAPIEncodeH264Options)), .init = &vaapi_encode_h264_init, - .encode2 = &ff_vaapi_encode2, + .encode2 = &vaapi_encode_h264_encode, .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, .capabilities = AV_CODEC_CAP_DELAY,