From patchwork Wed Feb 20 10:33:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing SUN X-Patchwork-Id: 12110 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 9E6D7447776 for ; Wed, 20 Feb 2019 11:36:56 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5EC9D68ABB5; Wed, 20 Feb 2019 11:36:56 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 00C2268ABA7 for ; Wed, 20 Feb 2019 11:36:48 +0200 (EET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Feb 2019 01:36:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,390,1544515200"; d="scan'208";a="116336093" Received: from unknown (HELO localhost.localdomain.bj.intel.com) ([172.16.181.151]) by orsmga007.jf.intel.com with ESMTP; 20 Feb 2019 01:36:45 -0800 From: Jing SUN To: ffmpeg-devel@ffmpeg.org Date: Wed, 20 Feb 2019 18:33:15 +0800 Message-Id: <1550658795-25142-1-git-send-email-jing.a.sun@intel.com> X-Mailer: git-send-email 1.8.3.1 Subject: [FFmpeg-devel] [PATCH v2 1/1] avcodec/vaapi_encode: add frame-skip func 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 Cc: Jing SUN MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This implements app controlled frame skipping in vaapi encoding. To make a frame skipped, allocate its frame side data of the newly added AV_FRAME_DATA_SKIP_FRAME type and set its value to 1. Signed-off-by: Jing SUN --- libavcodec/vaapi_encode.c | 112 ++++++++++++++++++++++++++++++++++++++++++++-- libavcodec/vaapi_encode.h | 5 +++ libavutil/frame.c | 1 + libavutil/frame.h | 5 +++ 4 files changed, 119 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index b4e9fad..debcfa6 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" +#include "libavutil/intreadwrite.h" #include "vaapi_encode.h" #include "avcodec.h" @@ -103,6 +104,41 @@ static int vaapi_encode_make_param_buffer(AVCodecContext *avctx, return 0; } +static int vaapi_encode_check_if_skip(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + AVFrameSideData *fside = NULL; + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodePicture *cur = NULL; + int i = 0; + if (!pic || !pic->input_image) + return AVERROR(EINVAL); + fside = av_frame_get_side_data(pic->input_image, AV_FRAME_DATA_SKIP_FRAME); + if (fside) + pic->skipped_flag = AV_RL8(fside->data); + else + pic->skipped_flag = 0; + if (0 == pic->skipped_flag) + return 0; + if ((pic->type == PICTURE_TYPE_IDR) || (pic->type == PICTURE_TYPE_I)) { + av_log(avctx, AV_LOG_INFO, "Can't skip IDR/I pic %"PRId64"/%"PRId64".\n", + pic->display_order, pic->encode_order); + pic->skipped_flag = 0; + return 0; + } + for (cur = ctx->pic_start; cur; cur = cur->next) { + for (i=0; i < cur->nb_refs; ++i) { + if (cur->refs[i] == pic) { + av_log(avctx, AV_LOG_INFO, "Can't skip ref pic %"PRId64"/%"PRId64".\n", + pic->display_order, pic->encode_order); + pic->skipped_flag = 0; + return 0; + } + } + } + return 0; +} + static int vaapi_encode_wait(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -412,6 +448,50 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } } + err = vaapi_encode_check_if_skip(avctx, pic); + if (err != 0) + av_log(avctx, AV_LOG_ERROR, "Fail to check if skip.\n"); + +#if VA_CHECK_VERSION(0,38,1) + if (pic->skipped_flag) { + av_log(avctx, AV_LOG_INFO, "Skip pic %"PRId64"/%"PRId64" as requested.\n", + pic->display_order, pic->encode_order); + ++ctx->skipped_pic_count; + pic->encode_issued = 1; + return 0; + } else if (ctx->skipped_pic_count > 0) { + VAEncMiscParameterBuffer *misc_param = NULL; + VAEncMiscParameterSkipFrame *skip_param = NULL; + + misc_param = av_malloc(sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterSkipFrame)); + misc_param->type = (VAEncMiscParameterType)VAEncMiscParameterTypeSkipFrame; + skip_param = (VAEncMiscParameterSkipFrame *)misc_param->data; + + skip_param->skip_frame_flag = 1; + skip_param->num_skip_frames = ctx->skipped_pic_count; + skip_param->size_skip_frames = 0; + + err = vaapi_encode_make_param_buffer(avctx, pic, + VAEncMiscParameterBufferType, (void *)misc_param, + (sizeof(VAEncMiscParameterBuffer) + + sizeof(VAEncMiscParameterSkipFrame))); + + free(misc_param); + + if (err < 0) + goto fail; + + ctx->skipped_pic_count = 0; + } +#else + if (pic->skipped_flag) { + av_log(avctx, AV_LOG_INFO, "Skip-frame isn't supported and pic %"PRId64"/%"PRId64" isn't skipped.\n", + pic->display_order, pic->encode_order); + pic->skipped_flag = 0; + ctx->skipped_pic_count = 0; + } +#endif + vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, pic->input_surface); if (vas != VA_STATUS_SUCCESS) { @@ -491,9 +571,23 @@ static int vaapi_encode_output(AVCodecContext *avctx, VAStatus vas; int err; - err = vaapi_encode_wait(avctx, pic); - if (err < 0) - return err; + if (!pic->skipped_flag) { + err = vaapi_encode_wait(avctx, pic); + if (err < 0) + return err; + } else { + av_frame_free(&pic->input_image); + pic->encode_complete = 1; + err = av_new_packet(pkt, 0); + if (err < 0) + goto fail; + pkt->pts = pic->pts; + av_buffer_unref(&pic->output_buffer_ref); + pic->output_buffer = VA_INVALID_ID; + av_log(avctx, AV_LOG_DEBUG, "Output 0 byte for pic %"PRId64"/%"PRId64".\n", + pic->display_order, pic->encode_order); + return 0; + } buf_list = NULL; vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer, @@ -514,6 +608,9 @@ static int vaapi_encode_output(AVCodecContext *avctx, goto fail_mapped; memcpy(pkt->data, buf->buf, buf->size); + + memset(buf->buf, 0, buf->size); + buf->size = 0; } if (pic->type == PICTURE_TYPE_IDR) @@ -547,7 +644,12 @@ fail: static int vaapi_encode_discard(AVCodecContext *avctx, VAAPIEncodePicture *pic) { - vaapi_encode_wait(avctx, pic); + if (!pic->skipped_flag) { + vaapi_encode_wait(avctx, pic); + } else { + av_frame_free(&pic->input_image); + pic->encode_complete = 1; + } if (pic->output_buffer_ref) { av_log(avctx, AV_LOG_DEBUG, "Discard output for pic " @@ -2034,6 +2136,8 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) } } + ctx->skipped_pic_count = 0; + return 0; fail: diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index a420686..bcbbd1a 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -112,6 +112,8 @@ typedef struct VAAPIEncodePicture { int nb_slices; VAAPIEncodeSlice *slices; + + uint8_t skipped_flag; } VAAPIEncodePicture; typedef struct VAAPIEncodeProfile { @@ -270,6 +272,9 @@ typedef struct VAAPIEncodeContext { int idr_counter; int gop_counter; int end_of_stream; + + // Skipped frame info + unsigned int skipped_pic_count; } VAAPIEncodeContext; enum { diff --git a/libavutil/frame.c b/libavutil/frame.c index dcf1fc3..1c38ebe 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -842,6 +842,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) #endif case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)"; case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest"; + case AV_FRAME_DATA_SKIP_FRAME: return "Skip frame"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index 8aa3e88..9022aba 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -179,6 +179,11 @@ enum AVFrameSideDataType { * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. */ AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * VAAPI Encode skip-frame indicator. + */ + AV_FRAME_DATA_SKIP_FRAME, }; enum AVActiveFormatDescription {