static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src) { QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 in = {{ 0 }}; mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; mfxSyncPoint sync = NULL; mfxStatus err; int ret; while (!s->session_upload_init && !s->session_upload && !ret) { #if HAVE_PTHREADS if (pthread_mutex_trylock(&s->session_lock) == 0) { #endif if (!s->session_upload_init) { ret = qsv_init_internal_session(ctx, &s->session_upload, 1); if (s->session_upload) s->session_upload_init = 1; } #if HAVE_PTHREADS pthread_mutex_unlock(&s->session_lock); pthread_cond_signal(&s->session_cond); } else { pthread_mutex_lock(&s->session_lock); while (!s->session_upload_init && !s->session_upload) { pthread_cond_wait(&s->session_cond, &s->session_lock); } pthread_mutex_unlock(&s->session_lock); } #endif } if (ret < 0) return ret; if (!s->session_upload) { if (s->child_frames_ref) return qsv_transfer_data_child(ctx, dst, src); av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n"); return AVERROR(ENOSYS); } in.Info = out->Info; in.Data.PitchLow = src->linesize[0]; in.Data.Y = src->data[0]; in.Data.U = src->data[1]; in.Data.V = src->data[2]; in.Data.A = src->data[3]; do { err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync); if (err == MFX_WRN_DEVICE_BUSY) av_usleep(1); } while (err == MFX_WRN_DEVICE_BUSY); if (err < 0 || !sync) { av_log(ctx, AV_LOG_ERROR, "Error uploading the surface\n"); return AVERROR_UNKNOWN; } do { err = MFXVideoCORE_SyncOperation(s->session_upload, sync, 1000); } while (err == MFX_WRN_IN_EXECUTION); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation\n"); return AVERROR_UNKNOWN; } return 0; }
static int qsv_frames_init(AVHWFramesContext *ctx) { QSVFramesContext *s = ctx->internal->priv; AVQSVFramesContext *frames_hwctx = ctx->hwctx; int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); uint32_t fourcc = 0; int i, ret; for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) { fourcc = supported_pixel_formats[i].fourcc; break; } } if (!fourcc) { av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n"); return AVERROR(ENOSYS); } if (!ctx->pool) { ret = qsv_init_pool(ctx, fourcc); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n"); return ret; } } if (opaque) { s->surface_ptrs = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->surface_ptrs)); if (!s->surface_ptrs) return AVERROR(ENOMEM); for (i = 0; i < frames_hwctx->nb_surfaces; i++) s->surface_ptrs[i] = frames_hwctx->surfaces + i; s->opaque_alloc.In.Surfaces = s->surface_ptrs; s->opaque_alloc.In.NumSurface = frames_hwctx->nb_surfaces; s->opaque_alloc.In.Type = frames_hwctx->frame_type; s->opaque_alloc.Out = s->opaque_alloc.In; s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; } else { s->mem_ids = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids)); if (!s->mem_ids) return AVERROR(ENOMEM); for (i = 0; i < frames_hwctx->nb_surfaces; i++) s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId; } ret = qsv_init_internal_session(ctx, &s->session_download, 0); if (ret < 0) return ret; ret = qsv_init_internal_session(ctx, &s->session_upload, 1); if (ret < 0) return ret; return 0; }