On 20/02/17 06:27, wm4 wrote:
> On Sun, 19 Feb 2017 18:46:36 +0000
> Mark Thompson <[email protected]> wrote:
>
>> ---
>> libavutil/hwcontext_qsv.c | 100
>> ++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 100 insertions(+)
>>
>> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
>> index 4e393e630..9fcf8fab7 100644
>> --- a/libavutil/hwcontext_qsv.c
>> +++ b/libavutil/hwcontext_qsv.c
>> @@ -723,6 +723,104 @@ static int qsv_transfer_data_to(AVHWFramesContext
>> *ctx, AVFrame *dst,
>> return 0;
>> }
>>
>> +static void qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
>> +{
>> + surf->Info.BitDepthLuma = 8;
>> + surf->Info.BitDepthChroma = 8;
>> + surf->Info.Shift = 0;
>> + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
>> + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
>
> Is that line repeated?
Yeah, oops. (This has a bit of hard-coding for specific cases. I'm going to
clean it up when I make the DXVA2 work. P010 should be here too, for example.)
>> + surf->Info.FourCC = MFX_FOURCC_NV12;
>> + surf->Info.Width = ctx->width;
>> + surf->Info.CropW = ctx->width;
>> + surf->Info.Height = ctx->height;
>> + surf->Info.CropH = ctx->height;
>> + surf->Info.FrameRateExtN = 25;
>> + surf->Info.FrameRateExtD = 1;
>> +}
>> +
>> +static int qsv_map_frames_to(AVHWFramesContext *dst_ctx,
>> + AVHWFramesContext *src_ctx, int flags)
>> +{
>> + QSVFramesContext *s = dst_ctx->internal->priv;
>> + AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
>> + int i;
>> +
>> + switch (src_ctx->device_ctx->type) {
>> +#if CONFIG_VAAPI
>> + case AV_HWDEVICE_TYPE_VAAPI:
>> + {
>> + AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
>> + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
>> +
>> sizeof(*s->surfaces_internal));
>> + if (!s->surfaces_internal)
>> + return AVERROR(ENOMEM);
>> + for (i = 0; i < src_hwctx->nb_surfaces; i++) {
>> + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
>> + s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids
>> + i;
>> + }
>> + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
>> + dst_hwctx->frame_type =
>> MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
>> + }
>> + break;
>> +#endif
>> +#if CONFIG_DXVA2
>> + {
>> + AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx;
>> + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
>> +
>> sizeof(*s->surfaces_internal));
>> + if (!s->surfaces_internal)
>> + return AVERROR(ENOMEM);
>> + for (i = 0; i < src_hwctx->nb_surfaces; i++) {
>> + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
>> + s->surfaces_internal[i].Data.MemId =
>> (mfxMemId)src_hwctx->surfaces[i];
>> + }
>> + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
>> + if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
>> + dst_hwctx->frame_type =
>> MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
>> + else
>> + dst_hwctx->frame_type =
>> MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
>> + }
>> + break;
>> +#endif
>> + default:
>> + return AVERROR(ENOSYS);
>> + }
>> +
>> + dst_hwctx->surfaces = s->surfaces_internal;
>> +
>> + return 0;
>> +}
>> +
>> +static int qsv_map_to(AVHWFramesContext *dst_ctx,
>> + AVFrame *dst, const AVFrame *src, int flags)
>> +{
>> + AVQSVFramesContext *hwctx = dst_ctx->hwctx;
>> + int i, err;
>> +
>> + for (i = 0; i < hwctx->nb_surfaces; i++) {
>> + if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
>> + (VASurfaceID)(uintptr_t)src->data[3])
>> + break;
>
> Why does it deal with VASurfaceIDs, which don't exist on Windows/DXVA?
Probably because I still haven't tested on Windows. I want to add a cleaner
way to deal with the Data.MemId things when doing that, but I'm not yet sure
exactly what it looks like (the different indirection levels are a pain).
>> + }
>> + if (i >= hwctx->nb_surfaces) {
>> + av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which "
>> + "is not in the mapped frames context.\n");
>> + return AVERROR(EINVAL);
>> + }
>> +
>> + err = ff_hwframe_map_create(dst->hw_frames_ctx,
>> + dst, src, NULL, NULL);
>> + if (err)
>> + return err;
>> +
>> + dst->width = src->width;
>> + dst->height = src->height;
>> + dst->data[3] = (uint8_t*)&hwctx->surfaces[i];
>> +
>> + return 0;
>> +}
>> +
>> static int qsv_frames_get_constraints(AVHWDeviceContext *ctx,
>> const void *hwconfig,
>> AVHWFramesConstraints *constraints)
>> @@ -937,7 +1035,9 @@ const HWContextType ff_hwcontext_type_qsv = {
>> .transfer_get_formats = qsv_transfer_get_formats,
>> .transfer_data_to = qsv_transfer_data_to,
>> .transfer_data_from = qsv_transfer_data_from,
>> + .map_to = qsv_map_to,
>> .map_from = qsv_map_from,
>> + .map_frames_to = qsv_map_frames_to,
>>
>> .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV,
>> AV_PIX_FMT_NONE },
>> };
>
> Can't quite wrap my head around why both map_to and map_frames_to
> exist, why they can't share code, and why map_from exists, but I guess
> it all has its reasons.
map_frames_to: Map a the platform frames context to a QSV frames context;
really this is just filling the hwctx member so that the context is usable.
map_to: Map a single platform frame to QSV, inside a context-pair which was
previous mapped with map_frames_to.
map_from: Map a QSV frame either directly to a platform frame (which can be
used without any specific frames context data for VAAPI at least, hence no
map_frames_from), or to normal memory via the platform frame.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel