History

hwcontext_qsv: Implement mapping frames from the child device type

Factorises out existing surface initialisation code to reuse. (cherry picked from commit eaa5e0710496db50fc164806e5f49eaaccc83bb5)

Mark Thompson committed 9 years ago

Commit f82ace71 parent ec3dbea1 file · +142 −32Browse files

Unified · Split

libavutil/hwcontext_qsv.c+142−32
@@ -94,6 +94,16 @@ static const struct { · 93 unmodified lines
9494 { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 },
9595 };
9696
97+static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
98+{
99+ int i;
100+ for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
101+ if (supported_pixel_formats[i].pix_fmt == pix_fmt)
102+ return supported_pixel_formats[i].fourcc;
103+ }
104+ return 0;
105+}
106+
97107 static int qsv_device_init(AVHWDeviceContext *ctx)
98108 {
99109 AVQSVDeviceContext *hwctx = ctx->hwctx;
@@ -272,18 +282,48 @@ fail: · 172 unmodified lines
272282 return ret;
273283 }
274284
285+static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
286+{
287+ const AVPixFmtDescriptor *desc;
288+ uint32_t fourcc;
289+
290+ desc = av_pix_fmt_desc_get(ctx->sw_format);
291+ if (!desc)
292+ return AVERROR(EINVAL);
293+
294+ fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
295+ if (!fourcc)
296+ return AVERROR(EINVAL);
297+
298+ surf->Info.BitDepthLuma = desc->comp[0].depth;
299+ surf->Info.BitDepthChroma = desc->comp[0].depth;
300+ surf->Info.Shift = desc->comp[0].depth > 8;
301+
302+ if (desc->log2_chroma_w && desc->log2_chroma_h)
303+ surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
304+ else if (desc->log2_chroma_w)
305+ surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
306+ else
307+ surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
308+
309+ surf->Info.FourCC = fourcc;
310+ surf->Info.Width = ctx->width;
311+ surf->Info.CropW = ctx->width;
312+ surf->Info.Height = ctx->height;
313+ surf->Info.CropH = ctx->height;
314+ surf->Info.FrameRateExtN = 25;
315+ surf->Info.FrameRateExtD = 1;
316+
317+ return 0;
318+}
319+
275320 static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
276321 {
277322 QSVFramesContext *s = ctx->internal->priv;
278323 AVQSVFramesContext *frames_hwctx = ctx->hwctx;
279− const AVPixFmtDescriptor *desc;
280324
281325 int i, ret = 0;
282326
283− desc = av_pix_fmt_desc_get(ctx->sw_format);
284− if (!desc)
285− return AVERROR_BUG;
286−
287327 if (ctx->initial_pool_size <= 0) {
288328 av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n");
289329 return AVERROR(EINVAL);
@@ -295,26 +335,9 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) · 5 unmodified lines
295335 return AVERROR(ENOMEM);
296336
297337 for (i = 0; i < ctx->initial_pool_size; i++) {
298− mfxFrameSurface1 *surf = &s->surfaces_internal[i];
299−
300− surf->Info.BitDepthLuma = desc->comp[0].depth;
301− surf->Info.BitDepthChroma = desc->comp[0].depth;
302− surf->Info.Shift = desc->comp[0].depth > 8;
303−
304− if (desc->log2_chroma_w && desc->log2_chroma_h)
305− surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
306− else if (desc->log2_chroma_w)
307− surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
308− else
309− surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
310−
311− surf->Info.FourCC = fourcc;
312− surf->Info.Width = ctx->width;
313− surf->Info.CropW = ctx->width;
314− surf->Info.Height = ctx->height;
315− surf->Info.CropH = ctx->height;
316− surf->Info.FrameRateExtN = 25;
317− surf->Info.FrameRateExtD = 1;
338+ ret = qsv_init_surface(ctx, &s->surfaces_internal[i]);
339+ if (ret < 0)
340+ return ret;
318341 }
319342
320343 if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
@@ -466,15 +489,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx) · 145 unmodified lines
466489
467490 int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
468491
469− uint32_t fourcc = 0;
492+ uint32_t fourcc;
470493 int i, ret;
471494
472− for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
473− if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) {
474− fourcc = supported_pixel_formats[i].fourcc;
475− break;
476− }
477− }
495+ fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
478496 if (!fourcc) {
479497 av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n");
480498 return AVERROR(ENOSYS);
@@ -723,6 +741,96 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, · 242 unmodified lines
723741 return 0;
724742 }
725743
744+static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx,
745+ AVHWFramesContext *src_ctx, int flags)
746+{
747+ QSVFramesContext *s = dst_ctx->internal->priv;
748+ AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
749+ int i;
750+
751+ switch (src_ctx->device_ctx->type) {
752+#if CONFIG_VAAPI
753+ case AV_HWDEVICE_TYPE_VAAPI:
754+ {
755+ AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
756+ s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
757+ sizeof(*s->surfaces_internal));
758+ if (!s->surfaces_internal)
759+ return AVERROR(ENOMEM);
760+ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
761+ qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
762+ s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids + i;
763+ }
764+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
765+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
766+ }
767+ break;
768+#endif
769+#if CONFIG_DXVA2
770+ case AV_HWDEVICE_TYPE_DXVA2:
771+ {
772+ AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx;
773+ s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
774+ sizeof(*s->surfaces_internal));
775+ if (!s->surfaces_internal)
776+ return AVERROR(ENOMEM);
777+ for (i = 0; i < src_hwctx->nb_surfaces; i++) {
778+ qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
779+ s->surfaces_internal[i].Data.MemId = (mfxMemId)src_hwctx->surfaces[i];
780+ }
781+ dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
782+ if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
783+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
784+ else
785+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
786+ }
787+ break;
788+#endif
789+ default:
790+ return AVERROR(ENOSYS);
791+ }
792+
793+ dst_hwctx->surfaces = s->surfaces_internal;
794+
795+ return 0;
796+}
797+
798+static int qsv_map_to(AVHWFramesContext *dst_ctx,
799+ AVFrame *dst, const AVFrame *src, int flags)
800+{
801+ AVQSVFramesContext *hwctx = dst_ctx->hwctx;
802+ int i, err;
803+
804+ for (i = 0; i < hwctx->nb_surfaces; i++) {
805+#if CONFIG_VAAPI
806+ if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
807+ (VASurfaceID)(uintptr_t)src->data[3])
808+ break;
809+#endif
810+#if CONFIG_DXVA2
811+ if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId ==
812+ (IDirect3DSurface9*)(uintptr_t)src->data[3])
813+ break;
814+#endif
815+ }
816+ if (i >= hwctx->nb_surfaces) {
817+ av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which "
818+ "is not in the mapped frames context.\n");
819+ return AVERROR(EINVAL);
820+ }
821+
822+ err = ff_hwframe_map_create(dst->hw_frames_ctx,
823+ dst, src, NULL, NULL);
824+ if (err)
825+ return err;
826+
827+ dst->width = src->width;
828+ dst->height = src->height;
829+ dst->data[3] = (uint8_t*)&hwctx->surfaces[i];
830+
831+ return 0;
832+}
833+
726834 static int qsv_frames_get_constraints(AVHWDeviceContext *ctx,
727835 const void *hwconfig,
728836 AVHWFramesConstraints *constraints)
@@ -931,7 +1039,9 @@ const HWContextType ff_hwcontext_type_qsv = { · 202 unmodified lines
9311039 .transfer_get_formats = qsv_transfer_get_formats,
9321040 .transfer_data_to = qsv_transfer_data_to,
9331041 .transfer_data_from = qsv_transfer_data_from,
1042+ .map_to = qsv_map_to,
9341043 .map_from = qsv_map_from,
1044+ .frames_derive_to = qsv_frames_derive_to,
9351045
9361046 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE },
9371047 };

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t