From patchwork Fri Nov 18 14:11:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hendrik Leppkes X-Patchwork-Id: 1472 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.90.1 with SMTP id o1csp92421vsb; Fri, 18 Nov 2016 06:12:02 -0800 (PST) X-Received: by 10.194.222.169 with SMTP id qn9mr5841907wjc.62.1479478322235; Fri, 18 Nov 2016 06:12:02 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m186si2599527wmm.130.2016.11.18.06.12.01; Fri, 18 Nov 2016 06:12:02 -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; 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 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 22463689D0A; Fri, 18 Nov 2016 16:11:49 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f66.google.com (mail-wm0-f66.google.com [74.125.82.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A29AE689C56 for ; Fri, 18 Nov 2016 16:11:41 +0200 (EET) Received: by mail-wm0-f66.google.com with SMTP id g23so6625392wme.1 for ; Fri, 18 Nov 2016 06:11:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=1JePKjb3NtUjxHATXlHSSIF+mBkLjJbVBGFdy/I3C2M=; b=kJdmPeGrK/nKK6Na9TrXcEEoDM5O3OZRPY4/O4TD9W1/xKRoZgXmfpuN2109+CtSwi MqsFrDb41swgfh8HTFDnIYTeqLA6fVfhF92ZlMNE5r2PUufOT/a/Vu5DmHpV89ZP49JQ pAoCySRs6UkQvCA4CKixpZQ0zaiHe5VNyjjMVeBjTd+Q6R5HqvtkZNIxFBMDA15FDxHo a7X+FvDXngPWKfv23pD9D8HLGI42b9a5uHLx2LCKVoEfRHtJ2mew0I6OxwVsGIHFpGRE 6jgPQ8V5v/i6EXamqmHueyPRsOASxBhcl0mac/5/6MtRosRMtlD1JHkAQ5fUTenXuGqH qxEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=1JePKjb3NtUjxHATXlHSSIF+mBkLjJbVBGFdy/I3C2M=; b=MA4JiFyoIED83Ia3b52EIHgJi0UwT6b2yKhsf/Lk4uoteoav8cM//1M/IMyoBMG7ky SdGORqUu5g7x2vK7xHW8xCPa8wL4luSwg3YqxtQRB2FwiK6KCTvXLgdF25e8e/7XMsCY kzT42zxETy2HOQ9xW3zDVYFd7E6XI8pMh8Vu+TSpbDoDCDTxOLLaqOkRDQpRIvIKL2Vw JjXtCBpQ1QnUtGic7ipHXjvCn6JmOudv4lrzc9Avx7Zn8Ks5CA5JTaBQj0GYvVl04Xjc lfjdw7bgQqm4ZrlkELghcXqfDWOmUX31G/MVLDev3srdS8j7smaFvcjVdmcdXQzEe3GW W9nQ== X-Gm-Message-State: AKaTC02AHQ7zX24mqde484lHAj0TrISo6eKMqYc4k6gp27b8X6FfObeb6azz0dD7muBeYQ== X-Received: by 10.28.158.148 with SMTP id h142mr327448wme.59.1479478302609; Fri, 18 Nov 2016 06:11:42 -0800 (PST) Received: from localhost (p5DC18C25.dip0.t-ipconnect.de. [93.193.140.37]) by smtp.gmail.com with ESMTPSA id d184sm3620738wmd.8.2016.11.18.06.11.41 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Nov 2016 06:11:41 -0800 (PST) From: Hendrik Leppkes To: ffmpeg-devel@ffmpeg.org Date: Fri, 18 Nov 2016 15:11:37 +0100 Message-Id: <20161118141137.1888-2-h.leppkes@gmail.com> X-Mailer: git-send-email 2.10.2.windows.1 In-Reply-To: <20161118141137.1888-1-h.leppkes@gmail.com> References: <20161118141137.1888-1-h.leppkes@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/2] dxva2_vc1: support multiple slices 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" --- libavcodec/dxva2_vc1.c | 106 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index 7cbbc7e..36bf1ba 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -29,9 +29,11 @@ // potentially newer version. #include "dxva2_internal.h" +#define MAX_SLICES 1024 struct dxva2_picture_context { DXVA_PictureParameters pp; - DXVA_SliceInfo si; + unsigned slice_count; + DXVA_SliceInfo slice[MAX_SLICES]; const uint8_t *bitstream; unsigned bitstream_size; @@ -174,7 +176,8 @@ static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, slice->bStartCodeBitOffset = 0; slice->bReservedBits = (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) ? v->bfraction_lut_index + 9 : 0; slice->wMBbitOffset = v->p_frame_skipped ? 0xffff : get_bits_count(&s->gb) + (avctx->codec_id == AV_CODEC_ID_VC1 ? 32 : 0); - slice->wNumberMBsInSlice = s->mb_width * s->mb_height; /* XXX We assume 1 slice */ + /* XXX We store the index of the first MB and it will be fixed later */ + slice->wNumberMBsInSlice = (s->mb_y >> v->field_mode) * s->mb_width + s->mb_x; slice->wQuantizerScaleCode = v->pq; slice->wBadSliceChopping = 0; } @@ -188,18 +191,15 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, const MpegEncContext *s = &v->s; struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; - DXVA_SliceInfo *slice = &ctx_pic->si; - static const uint8_t start_code[] = { 0, 0, 1, 0x0d }; const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ? sizeof(start_code) : 0; - const unsigned slice_size = slice->dwSliceBitsInBuffer / 8; - const unsigned padding = 128 - ((start_code_size + slice_size) & 127); - const unsigned data_size = start_code_size + slice_size + padding; - + const unsigned mb_count = s->mb_width * (s->mb_height >> v->field_mode); + DXVA_SliceInfo *slice = NULL; void *dxva_data_ptr; - uint8_t *dxva_data; + uint8_t *dxva_data, *current, *end; unsigned dxva_size; - int result; + unsigned padding; + unsigned i; unsigned type; #if CONFIG_D3D11VA @@ -223,19 +223,49 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, #endif dxva_data = dxva_data_ptr; - result = data_size <= dxva_size ? 0 : -1; - if (!result) { - if (start_code_size > 0) { - memcpy(dxva_data, start_code, start_code_size); - if (v->second_field) - dxva_data[3] = 0x0c; + current = dxva_data; + end = dxva_data + dxva_size; + + for (i = 0; i < ctx_pic->slice_count; i++) { + unsigned position, size; + slice = &ctx_pic->slice[i]; + position = slice->dwSliceDataLocation; + size = slice->dwSliceBitsInBuffer / 8; + if (start_code_size + size > end - current) { + av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); + break; } - memcpy(dxva_data + start_code_size, - ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size); - if (padding > 0) - memset(dxva_data + start_code_size + slice_size, 0, padding); - slice->dwSliceBitsInBuffer = 8 * data_size; + slice->dwSliceDataLocation = current - dxva_data; + + if (i < ctx_pic->slice_count - 1) + slice->wNumberMBsInSlice = + slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; + else + slice->wNumberMBsInSlice = + mb_count - slice[0].wNumberMBsInSlice; + + /* write the appropriate frame, field or slice start code */ + if (start_code_size) { + memcpy(current, start_code, start_code_size); + if (i == 0 && v->second_field) + current[3] = 0x0c; + else if (i > 0) + current[3] = 0x0b; + + current += start_code_size; + slice->dwSliceBitsInBuffer += start_code_size * 8; + } + + memcpy(current, &ctx_pic->bitstream[position], size); + current += size; } + padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); + if (slice && padding > 0) { + memset(current, 0, padding); + current += padding; + slice->dwSliceBitsInBuffer += padding * 8; + } + #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) @@ -246,16 +276,16 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) return -1; #endif - if (result) - return result; + if (i < ctx_pic->slice_count) + return -1; #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; - dsc11->DataSize = data_size; - dsc11->NumMBsInBuffer = s->mb_width * s->mb_height; + dsc11->DataSize = current - dxva_data; + dsc11->NumMBsInBuffer = mb_count; type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; } @@ -265,17 +295,18 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DXVA2_DecodeBufferDesc *dsc2 = bs; memset(dsc2, 0, sizeof(*dsc2)); dsc2->CompressedBufferType = type; - dsc2->DataSize = data_size; - dsc2->NumMBsInBuffer = s->mb_width * s->mb_height; + dsc2->DataSize = current - dxva_data; + dsc2->NumMBsInBuffer = mb_count; type = DXVA2_SliceControlBufferType; } #endif - assert((data_size & 127) == 0); return ff_dxva2_commit_buffer(avctx, ctx, sc, type, - slice, sizeof(*slice), s->mb_width * s->mb_height); + ctx_pic->slice, + ctx_pic->slice_count * sizeof(*ctx_pic->slice), + mb_count); } static int dxva2_vc1_start_frame(AVCodecContext *avctx, @@ -294,6 +325,7 @@ static int dxva2_vc1_start_frame(AVCodecContext *avctx, fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp); + ctx_pic->slice_count = 0; ctx_pic->bitstream_size = 0; ctx_pic->bitstream = NULL; return 0; @@ -306,9 +338,13 @@ static int dxva2_vc1_decode_slice(AVCodecContext *avctx, const VC1Context *v = avctx->priv_data; const Picture *current_picture = v->s.current_picture_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + unsigned position; - if (ctx_pic->bitstream_size > 0) + if (ctx_pic->slice_count >= MAX_SLICES) { + avpriv_request_sample(avctx, "%d slices in dxva2", + ctx_pic->slice_count); return -1; + } if (avctx->codec_id == AV_CODEC_ID_VC1 && size >= 4 && IS_MARKER(AV_RB32(buffer))) { @@ -316,10 +352,12 @@ static int dxva2_vc1_decode_slice(AVCodecContext *avctx, size -= 4; } - ctx_pic->bitstream_size = size; - ctx_pic->bitstream = buffer; + if (!ctx_pic->bitstream) + ctx_pic->bitstream = buffer; + ctx_pic->bitstream_size += size; - fill_slice(avctx, &ctx_pic->si, 0, size); + position = buffer - ctx_pic->bitstream; + fill_slice(avctx, &ctx_pic->slice[ctx_pic->slice_count++], position, size); return 0; } @@ -329,7 +367,7 @@ static int dxva2_vc1_end_frame(AVCodecContext *avctx) struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; int ret; - if (ctx_pic->bitstream_size <= 0) + if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f,