bool CheckQSVHardwareSupport(bool log=true) { safe_handle helper_process, helper_thread; IPCWaiter waiter; String event_prefix; if(!spawn_helper(event_prefix, helper_process, helper_thread, waiter)) return false; ipc_init_request req((event_prefix + INIT_REQUEST).Array()); req->mode = req->MODE_QUERY; req.signal(); if(!waiter.wait(INFINITE)) return false; DWORD code = 0; if(!GetExitCodeProcess(helper_process.h, &code)) return false; if(code == 0) { if(log) Log(TEXT("Found QSV hardware support")); return true; } if(log) Log(TEXT("Failed to initialize QSV hardware session")); return false; }
static int run_test(void) { uv_process_t process; uv_buf_t buf; int r; spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); buf = uv_buf_init(".", 1); r = uv_write2(&ctx.write_req, (uv_stream_t*)&ctx.channel, &buf, 1, &ctx.send.stream, NULL); ASSERT(r == 0); r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(num_recv_handles == 1); return 0; }
static int run_test(int inprocess) { uv_process_t process; uv_thread_t tid; int r; if (inprocess) { r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42); ASSERT(r == 0); uv_sleep(1000); r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1); ASSERT(r == 0); uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb); } else { spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); connect_cb(&ctx.connect_req, 0); } r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(recv_cb_count == 2); if (inprocess) { r = uv_thread_join(&tid); ASSERT(r == 0); } return 0; }
static int spawn_core_worker(void) { char *argvec[] = {nagios_binary_path, "--worker", qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET, NULL}; int ret; if ((ret = spawn_helper(argvec)) < 0) logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to launch core worker: %s\n", strerror(errno)); else wproc_num_workers_spawned++; return ret; }
static int run_ipc_test(const char* helper, uv_read_cb read_cb) { uv_process_t process; int r; spawn_helper(&channel, &process, helper); uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
bool CheckQSVHardwareSupport(bool log=true, bool *configurationWarning = nullptr) { safe_handle helper_process, helper_thread; IPCWaiter waiter; String event_prefix; if(!spawn_helper(event_prefix, helper_process, helper_thread, waiter)) return false; ipc_init_request req((event_prefix + INIT_REQUEST).Array()); req->mode = req->MODE_QUERY; req.signal(); if(!waiter.wait(INFINITE)) return false; DWORD code = 0; if(!GetExitCodeProcess(helper_process.h, &code)) return false; if(code == 0) { if(log) Log(TEXT("Found QSV hardware support")); return true; } static bool warning_logged = false; if (code == EXIT_NO_INTEL_GRAPHICS && (!warning_logged || log)) { Log(L"No Intel graphics adapter visible in QSVHelper.exe, Optimus problem?"); warning_logged = true; } if (configurationWarning) *configurationWarning = code == EXIT_NO_INTEL_GRAPHICS && qsv_get_cpu_platform() != QSV_CPU_PLATFORM_UNKNOWN; if(log) Log(TEXT("Failed to initialize QSV hardware session")); return false; }
QSVEncoder(int fps_, int width, int height, int quality, CTSTR preset, bool bUse444, ColorDescription &colorDesc, int maxBitrate, int bufferSize, bool bUseCFR_) : bFirstFrameProcessed(false), width(width), height(height), max_bitrate(maxBitrate) { fps = fps_; bUseCBR = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCBR")) != 0; bUseCFR = bUseCFR_; UINT keyframeInterval = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("KeyframeInterval"), 6); int keyint = fps*keyframeInterval; int bframes = 7; bool bHaveCustomImpl = false; impl_parameters custom = { 0 }; BOOL bUseCustomParams = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCustomSettings")) && AppConfig->GetInt(TEXT("Video Encoding"), TEXT("QSVUseVideoEncoderSettings")); if(bUseCustomParams) { StringList paramList; String strCustomParams = AppConfig->GetString(TEXT("Video Encoding"), TEXT("CustomSettings")); strCustomParams.KillSpaces(); if(strCustomParams.IsValid()) { Log(TEXT("Using custom encoder settings: \"%s\""), strCustomParams.Array()); strCustomParams.GetTokenList(paramList, ' ', FALSE); for(UINT i=0; i<paramList.Num(); i++) { String &strParam = paramList[i]; if(!schr(strParam, '=')) continue; String strParamName = strParam.GetToken(0, '='); String strParamVal = strParam.GetTokenOffset(1, '='); if(strParamName == "keyint") { int keyint_ = strParamVal.ToInt(); if(keyint_ < 0) continue; keyint = keyint_; } else if(strParamName == "bframes") { int bframes_ = strParamVal.ToInt(); if(bframes_ < 0) continue; bframes = bframes_; } else if(strParamName == "qsvimpl") { StringList bits; strParamVal.GetTokenList(bits, ',', true); if(bits.Num() < 3) continue; StringList version; bits[2].GetTokenList(version, '.', false); if(version.Num() != 2) continue; custom.type = bits[0].ToInt(); if(custom.type == 0) custom.type = MFX_IMPL_HARDWARE_ANY; auto &intf = bits[1].MakeLower(); custom.intf = intf == "d3d11" ? MFX_IMPL_VIA_D3D11 : (intf == "d3d9" ? MFX_IMPL_VIA_D3D9 : MFX_IMPL_VIA_ANY); custom.version.Major = version[0].ToInt(); custom.version.Minor = version[1].ToInt(); bHaveCustomImpl = true; } } } } if(!spawn_helper(event_prefix, qsvhelper_process, qsvhelper_thread, process_waiter)) CrashError(TEXT("Couldn't launch QSVHelper: %u"), GetLastError()); ipc_init_request request((event_prefix + INIT_REQUEST).Array()); request->mode = request->MODE_ENCODE; request->obs_process_id = GetCurrentProcessId(); request->fps = fps_; request->keyint = keyint; request->bframes = bframes; request->width = width; request->height = height; request->max_bitrate = maxBitrate; request->buffer_size = bufferSize; request->use_cbr = bUseCBR; request->full_range = colorDesc.fullRange; request->matrix = colorDesc.matrix; request->primaries = colorDesc.primaries; request->transfer = colorDesc.transfer; request->use_custom_impl = bHaveCustomImpl; request->custom_impl = custom.type; request->custom_intf = custom.intf; request->custom_version = custom.version; request.signal(); ipc_init_response response((event_prefix + INIT_RESPONSE).Array()); IPCWaiter response_waiter = process_waiter; response_waiter.push_back(response.signal_); if(response_waiter.wait_for_two(0, 1, INFINITE)) { DWORD code = 0; if(!GetExitCodeProcess(qsvhelper_process.h, &code)) CrashError(TEXT("Failed to initialize QSV session.")); switch(code) { case EXIT_INCOMPATIBLE_CONFIGURATION: CrashError(TEXT("QSVHelper.exe has exited because of an incompatible qsvimpl custom parameter (before response)")); case EXIT_NO_VALID_CONFIGURATION: if(OSGetVersion() < 8) CrashError(TEXT("QSVHelper.exe could not find a valid configuration. Make sure you have a (virtual) display connected to your iGPU")); CrashError(TEXT("QSVHelper.exe could not find a valid configuration")); default: CrashError(TEXT("QSVHelper.exe has exited with code %i (before response)"), code); } } Log(TEXT("------------------------------------------")); if(bHaveCustomImpl && !response->using_custom_impl) AppWarning(TEXT("Could not initialize QSV session using custom settings")); ver = response->version; auto intf_str = qsv_intf_str(response->requested_impl), actual_intf_str = qsv_intf_str(response->actual_impl); auto length = std::distance(std::begin(implStr), std::end(implStr)); auto impl = response->requested_impl & (MFX_IMPL_VIA_ANY - 1); if(impl > length) impl = static_cast<mfxIMPL>(length-1); Log(TEXT("QSV version %u.%u using %s%s (actual: %s%s)"), ver.Major, ver.Minor, implStr[impl], intf_str, implStr[response->actual_impl & (MFX_IMPL_VIA_ANY - 1)], actual_intf_str); target_usage = response->target_usage; encode_tasks.SetSize(response->bitstream_num); bs_buff = ipc_bitstream_buff((event_prefix + BITSTREAM_BUFF).Array(), response->bitstream_size*response->bitstream_num); if(!bs_buff) CrashError(TEXT("Failed to initialize QSV bitstream buffer (%u)"), GetLastError()); mfxU8 *bs_start = (mfxU8*)(((size_t)&bs_buff + 31)/32*32); for(unsigned i = 0; i < encode_tasks.Num(); i++) { zero(encode_tasks[i].surf); mfxBitstream &bs = encode_tasks[i].bs; zero(bs); bs.Data = bs_start + i*response->bitstream_size; bs.MaxLength = response->bitstream_size; idle_tasks << i; } frames.SetSize(response->frame_num); frame_buff = ipc_frame_buff((event_prefix + FRAME_BUFF).Array(), response->frame_size*response->frame_num); if(!frame_buff) CrashError(TEXT("Failed to initialize QSV frame buffer (%u)"), GetLastError()); mfxU8 *frame_start = (mfxU8*)(((size_t)&frame_buff + 15)/16*16); for(unsigned i = 0; i < frames.Num(); i++) { mfxFrameData& frame = frames[i]; zero(frame); frame.Y = frame_start + i * response->frame_size; frame.UV = frame_start + i * response->frame_size + response->UV_offset; frame.V = frame_start + i * response->frame_size + response->V_offset; frame.Pitch = response->frame_pitch; } Log(TEXT("Using %u bitstreams and %u frame buffers"), encode_tasks.Num(), frames.Num()); Log(TEXT("------------------------------------------")); Log(GetInfoString()); Log(TEXT("------------------------------------------")); DataPacket packet; GetHeaders(packet); frame_queue = ipc_frame_queue((event_prefix + FRAME_QUEUE).Array(), frames.Num()); if(!frame_queue) CrashError(TEXT("Failed to initialize frame queue (%u)"), GetLastError()); frame_buff_status = ipc_frame_buff_status((event_prefix + FRAME_BUFF_STATUS).Array(), frames.Num()); if(!frame_buff_status) CrashError(TEXT("Failed to initialize QSV frame buffer status (%u)"), GetLastError()); bs_info = ipc_bitstream_info((event_prefix + BITSTREAM_INFO).Array(), response->bitstream_num); if(!bs_info) CrashError(TEXT("Failed to initialize QSV bitstream info (%u)"), GetLastError()); filled_bitstream = ipc_filled_bitstream((event_prefix + FILLED_BITSTREAM).Array()); if(!filled_bitstream) CrashError(TEXT("Failed to initialize bitstream signal (%u)"), GetLastError()); stop = ipc_stop((event_prefix + STOP_REQUEST).Array()); if(!stop) CrashError(TEXT("Failed to initialize QSV stop signal (%u)"), GetLastError()); filled_bitstream_waiter = process_waiter; filled_bitstream_waiter.push_back(filled_bitstream.signal_); }