On 09/05/17 06:07, wm4 wrote:
> On Mon, 8 May 2017 22:59:11 +0100
> Mark Thompson <[email protected]> wrote:
>> On 04/05/17 07:44, wm4 wrote:
>>> To be used with the new d3d11 hwaccel decode API.
>>>
>>> With the new hwaccel API, we don't want surfaces to depend on the
>>> decoder (other than the required dimension and format). The old D3D11VA
>>> pixfmt uses ID3D11VideoDecoderOutputView pointers, which include the
>>> decoder configuration, and thus is incompatible with the new hwaccel
>>> API. This patch introduces AV_PIX_FMT_D3D11, which uses ID3D11Texture2D
>>> and an index. It's simpler and compatible with the new hwaccel API.
>>>
>>> The introduced hwcontext supports only the new pixfmt.
>>>
>>> Significantly based on work by Steve Lhomme <[email protected]>, but with
>>> heavy changes/rewrites.
> 
> 
>>> ---
>>> Somewhat sketchy: if initial_pool_size is set, the pool is assumed to
>>> be static.
>>> ---
> 
> Any comments on that?

It's how all of the other implementations with fixed pools work, so fine?

>>> +static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst,
>>> +                                 const AVFrame *src)
>>> +{
>>> +    AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
>>> +    D3D11VAFramesContext              *s = ctx->internal->priv;
>>> +    int download = !!src->hw_frames_ctx;  
>>
>> This isn't correct - src could have hw_frames_ctx set as a mapped frame 
>> while we are really uploading to dst.  I don't think you can write this with 
>> only one function.
>>
>> (Not sure there is any case where you would ever want to do that, though.)
> 
> OK I guess.
> 
>>> +    const AVFrame *frame = download ? src : dst;
>>> +    // (The interface types are compatible.)
>>> +    ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D 
>>> *)frame->data[0];
>>> +    int index = (intptr_t)frame->data[1];
>>> +    ID3D11Resource *staging = (ID3D11Resource *)s->staging_texture;
>>> +    int w = FFMIN(dst->width,  src->width);
>>> +    int h = FFMIN(dst->height, src->height);
>>> +    uint8_t *map_data[4];
>>> +    int map_linesize[4];
>>> +    D3D11_TEXTURE2D_DESC desc;
>>> +    D3D11_MAPPED_SUBRESOURCE map;
>>> +    HRESULT hr;
>>> +
>>> +    device_hwctx->lock(device_hwctx->lock_ctx);
>>> +
>>> +    ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
>>> +
>>> +    if (download) {
>>> +        
>>> ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
>>> +                                                  staging, 0, 0, 0, 0,
>>> +                                                  texture, index, NULL);
>>> +
>>> +        hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
>>> +                                     staging, 0, D3D11_MAP_READ, 0, &map);
>>> +        if (FAILED(hr))
>>> +            goto map_failed;
>>> +
>>> +        fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
>>> +
>>> +        av_image_copy(dst->data, dst->linesize, map_data, map_linesize,
>>> +                      ctx->sw_format, w, h);  
>>
>> Is the staging texture somehow magic such that it isn't going to be uncached 
>> memory or anything tricky like that?
> 
> Yes, I'm fairly sure it simply lives in CPU memory, and
> CopySubresourceRegion() will access the actual video memory.
> 
> This is also why d3d11 with copy back is slower than dxva2, apparently.

Well, at least it's probably faster on Braswell :P

>>> +
>>> +        ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 
>>> 0);
>>> +    } else {
>>> +        hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
>>> +                                     staging, 0, D3D11_MAP_WRITE, 0, &map);
>>> +        if (FAILED(hr))
>>> +            goto map_failed;
>>> +
>>> +        fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
>>> +
>>> +        av_image_copy(map_data, map_linesize, src->data, src->linesize,
>>> +                      ctx->sw_format, w, h);
>>> +
>>> +        ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 
>>> 0);
>>> +
>>> +        
>>> ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
>>> +                                                  texture, index, 0, 0, 0,
>>> +                                                  staging, 0, NULL);
>>> +    }
>>> +
>>> +    device_hwctx->unlock(device_hwctx->lock_ctx);
>>> +    return 0;
>>> +
>>> +map_failed:
>>> +    av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", 
>>> (long)hr);
>>> +    device_hwctx->unlock(device_hwctx->lock_ctx);
>>> +    return AVERROR_UNKNOWN;
>>> +}  
>>
>> Seems like it would be nicer to implement map and use it rather than putting 
>> it multiple times inside this function.
> 
> Maybe. I'm unsure about the mapping semantics. Will look at it again.
> 
>>> +    AV_PIX_FMT_D3D11,     ///< HW decoding through Direct3D11 via new API, 
>>> Picture.data[0] contains a ID3D11Texture2D pointer, and data[1] contains 
>>> the texture array index of the frame as intptr_t if the ID3D11Texture2D is 
>>> an array texture (or 0 if it's a normal texture)  
>>
>> The old format was specifically for decoding, but the new one is more 
>> general than that.
> 
> OK. Well, someone new to the API who's trying to figure out which
> format to use is going to be confused, so mentioning the new decode API
> might help.

Yeah, fair.  Mention decoding but not as the only thing, then.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to