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; 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 GstFlowReturn gst_msdkvpp_transform (GstBaseTransform * trans, GstBuffer * inbuf, GstBuffer * outbuf) { GstMsdkVPP *thiz = GST_MSDKVPP (trans); GstClockTime timestamp; GstFlowReturn ret = GST_FLOW_OK; mfxSession session; mfxSyncPoint sync_point = NULL; mfxStatus status; MsdkSurface *in_surface = NULL; MsdkSurface *out_surface = NULL; timestamp = GST_BUFFER_TIMESTAMP (inbuf); in_surface = get_msdk_surface_from_input_buffer (thiz, inbuf); if (!in_surface) return GST_FLOW_ERROR; if (gst_msdk_is_msdk_buffer (outbuf)) { out_surface = g_slice_new0 (MsdkSurface); out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf); } else { GST_ERROR ("Failed to get msdk outsurface!"); return GST_FLOW_ERROR; } session = gst_msdk_context_get_session (thiz->context); /* outer loop is for handling FrameRate Control and deinterlace use cases */ do { for (;;) { status = MFXVideoVPP_RunFrameVPPAsync (session, in_surface->surface, out_surface->surface, NULL, &sync_point); if (status != MFX_WRN_DEVICE_BUSY) break; /* If device is busy, wait 1ms and retry, as per MSDK's recommendation */ g_usleep (1000); }; if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA && status != MFX_ERR_MORE_SURFACE) goto vpp_error; /* No output generated */ if (status == MFX_ERR_MORE_DATA) goto error_more_data; if (sync_point) MFXVideoCORE_SyncOperation (session, sync_point, 10000); /* More than one output buffers are generated */ if (status == MFX_ERR_MORE_SURFACE) { GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration; timestamp += thiz->buffer_duration; ret = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (trans), outbuf); if (ret != GST_FLOW_OK) goto error_push_buffer; outbuf = create_output_buffer (thiz); } else { GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration; } } while (status == MFX_ERR_MORE_SURFACE); free_msdk_surface (in_surface); return ret; vpp_error: GST_ERROR_OBJECT (thiz, "MSDK Failed to do VPP"); free_msdk_surface (in_surface); free_msdk_surface (out_surface); return GST_FLOW_ERROR; error_more_data: GST_WARNING_OBJECT (thiz, "MSDK Requries additional input for processing, " "Retruning FLOW_DROPPED since no output buffer was generated"); free_msdk_surface (in_surface); return GST_BASE_TRANSFORM_FLOW_DROPPED; error_push_buffer: { free_msdk_surface (in_surface); free_msdk_surface (out_surface); GST_DEBUG_OBJECT (thiz, "failed to push output buffer: %s", gst_flow_get_name (ret)); return ret; } }
static int qsvscale_filter_frame(AVFilterLink *link, AVFrame *in) { AVFilterContext *ctx = link->dst; QSVScaleContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; mfxSyncPoint sync = NULL; mfxStatus err; AVFrame *out = NULL; int ret = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { ret = AVERROR(ENOMEM); goto fail; } do { err = MFXVideoVPP_RunFrameVPPAsync(s->session, (mfxFrameSurface1*)in->data[3], (mfxFrameSurface1*)out->data[3], 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 during scaling\n"); ret = AVERROR_UNKNOWN; goto fail; } do { err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); } while (err == MFX_WRN_IN_EXECUTION); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); ret = AVERROR_UNKNOWN; goto fail; } ret = av_frame_copy_props(out, in); if (ret < 0) goto fail; out->width = outlink->w; out->height = outlink->h; av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, INT_MAX); av_frame_free(&in); return ff_filter_frame(outlink, out); fail: av_frame_free(&in); av_frame_free(&out); return ret; }
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; }
GstMfxFilterStatus gst_mfx_filter_process (GstMfxFilter * filter, GstMfxSurface * surface, GstMfxSurface ** out_surface) { mfxFrameSurface1 *insurf, *outsurf = NULL; mfxSyncPoint syncp; mfxStatus sts = MFX_ERR_NONE; GstMfxFilterStatus ret = GST_MFX_FILTER_STATUS_SUCCESS; gboolean more_surface = FALSE; /* Delayed VPP initialization to enable surface pool sharing with * encoder plugin */ if (G_UNLIKELY (!filter->inited)) { ret = gst_mfx_filter_start (filter); if (ret != GST_MFX_FILTER_STATUS_SUCCESS) return ret; filter->inited = TRUE; } insurf = gst_mfx_surface_get_frame_surface (surface); do { *out_surface = gst_mfx_surface_new_from_pool (filter->vpp_pool[1]); if (!*out_surface) return GST_MFX_FILTER_STATUS_ERROR_ALLOCATION_FAILED; outsurf = gst_mfx_surface_get_frame_surface (*out_surface); sts = MFXVideoVPP_RunFrameVPPAsync (filter->session, insurf, outsurf, NULL, &syncp); if (MFX_WRN_INCOMPATIBLE_VIDEO_PARAM == sts) sts = MFX_ERR_NONE; if (MFX_WRN_DEVICE_BUSY == sts) g_usleep (500); } while (MFX_WRN_DEVICE_BUSY == sts); if (MFX_ERR_MORE_DATA == sts) return GST_MFX_FILTER_STATUS_ERROR_MORE_DATA; /* The current frame is ready. Hence treat it * as MFX_ERR_NONE and request for more surface */ if (MFX_ERR_MORE_SURFACE == sts) { sts = MFX_ERR_NONE; more_surface = TRUE; } if (MFX_ERR_NONE != sts) { GST_ERROR ("Error during MFX filter process."); return GST_MFX_FILTER_STATUS_ERROR_OPERATION_FAILED; } if (syncp) { if (!gst_mfx_task_has_type (filter->vpp[1], GST_MFX_TASK_ENCODER)) do { sts = MFXVideoCORE_SyncOperation (filter->session, syncp, 1000); } while (MFX_WRN_IN_EXECUTION == sts); *out_surface = gst_mfx_surface_pool_find_surface (filter->vpp_pool[1], outsurf); } if (more_surface) return GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE; return GST_MFX_FILTER_STATUS_SUCCESS; }