Check service status instead of service pipe status. Replaced signbit() with sign(). Don't modify filter pins when the filter is running.

This commit is contained in:
Gonzalo Exequiel Pedone 2021-06-05 17:34:58 -03:00
parent 1744482e9d
commit b7f1ff83b6
No known key found for this signature in database
GPG key ID: B8B09E63E9B85BAF
5 changed files with 125 additions and 18 deletions

View file

@ -32,6 +32,11 @@ namespace AkVCam
public: public:
int64_t m_num; int64_t m_num;
int64_t m_den; int64_t m_den;
template<typename T> inline static int sign(T value)
{
return value < 0? -1: 1;
}
}; };
} }
@ -151,7 +156,7 @@ bool AkVCam::Fraction::isInfinity() const
int AkVCam::Fraction::sign() const int AkVCam::Fraction::sign() const
{ {
return std::signbit(this->d->m_num) == std::signbit(this->d->m_den)? 1: -1; return FractionPrivate::sign(this->d->m_num) == FractionPrivate::sign(this->d->m_den)? 1: -1;
} }
bool AkVCam::Fraction::isFraction(const std::string &str) bool AkVCam::Fraction::isFraction(const std::string &str)

View file

@ -24,6 +24,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "logger.h"
#ifndef UNUSED #ifndef UNUSED
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
#endif #endif
@ -131,11 +133,15 @@
std::vector<CallbackName##Callback> m_##CallbackName##Callback; std::vector<CallbackName##Callback> m_##CallbackName##Callback;
#define AKVCAM_EMIT(owner, CallbackName, ...) \ #define AKVCAM_EMIT(owner, CallbackName, ...) \
AkLogDebug() << "Emiting: " << #CallbackName << std::endl; \
\
for (auto &callback: owner->m_##CallbackName##Callback) \ for (auto &callback: owner->m_##CallbackName##Callback) \
if (callback.second) \ if (callback.second) \
callback.second(callback.first, __VA_ARGS__); \ callback.second(callback.first, __VA_ARGS__); \
#define AKVCAM_EMIT_NOARGS(owner, CallbackName) \ #define AKVCAM_EMIT_NOARGS(owner, CallbackName) \
AkLogDebug() << "Emiting: " << #CallbackName << std::endl; \
\
for (auto &callback: owner->m_##CallbackName##Callback) \ for (auto &callback: owner->m_##CallbackName##Callback) \
if (callback.second) \ if (callback.second) \
callback.second(callback.first); \ callback.second(callback.first); \

View file

@ -227,6 +227,7 @@ AkVCam::MessageServerPrivate::MessageServerPrivate(MessageServer *self):
bool AkVCam::MessageServerPrivate::startReceive(bool wait) bool AkVCam::MessageServerPrivate::startReceive(bool wait)
{ {
AkLogFunction(); AkLogFunction();
AkLogDebug() << "Wait: " << wait << std::endl;
AKVCAM_EMIT(this->self, StateChanged, MessageServer::StateAboutToStart) AKVCAM_EMIT(this->self, StateChanged, MessageServer::StateAboutToStart)
this->m_running = true; this->m_running = true;

View file

@ -39,6 +39,18 @@
#include "VCamUtils/src/ipcbridge.h" #include "VCamUtils/src/ipcbridge.h"
#include "VCamUtils/src/logger.h" #include "VCamUtils/src/logger.h"
#ifndef SERVICE_NOTIFY_STOPPED
#define SERVICE_NOTIFY_STOPPED 0x1
#endif
#ifndef SERVICE_NOTIFY_RUNNING
#define SERVICE_NOTIFY_RUNNING 0x8
#endif
#ifndef SERVICE_NOTIFY_STATUS_CHANGE
#define SERVICE_NOTIFY_STATUS_CHANGE 2
#endif
namespace AkVCam namespace AkVCam
{ {
using RegisterServerFunc = HRESULT (WINAPI *)(); using RegisterServerFunc = HRESULT (WINAPI *)();
@ -82,6 +94,9 @@ namespace AkVCam
MessageServer m_mainServer; MessageServer m_mainServer;
SharedMemory m_sharedMemory; SharedMemory m_sharedMemory;
Mutex m_globalMutex; Mutex m_globalMutex;
SC_HANDLE m_scManager {nullptr};
SC_HANDLE m_assistantService {nullptr};
SERVICE_NOTIFY m_notifyBuffer;
explicit IpcBridgePrivate(IpcBridge *self); explicit IpcBridgePrivate(IpcBridge *self);
~IpcBridgePrivate(); ~IpcBridgePrivate();
@ -91,8 +106,10 @@ namespace AkVCam
void updateDeviceSharedProperties(); void updateDeviceSharedProperties();
void updateDeviceSharedProperties(const std::string &deviceId, void updateDeviceSharedProperties(const std::string &deviceId,
const std::string &owner); const std::string &owner);
static void pipeStateChanged(void *userData, bool isServiceRunning() const;
MessageServer::PipeState state); void startServiceStatusCheck();
void stopServiceStatusCheck();
static void CALLBACK notifyCallback(void *parameter);
// Message handling methods // Message handling methods
void isAlive(Message *message); void isAlive(Message *message);
@ -135,14 +152,12 @@ AkVCam::IpcBridge::IpcBridge()
this->d->m_mainServer.start(); this->d->m_mainServer.start();
this->registerPeer(); this->registerPeer();
this->d->updateDeviceSharedProperties(); this->d->updateDeviceSharedProperties();
this->d->m_mainServer.connectPipeStateChanged(this, this->d->startServiceStatusCheck();
&IpcBridgePrivate::pipeStateChanged);
} }
AkVCam::IpcBridge::~IpcBridge() AkVCam::IpcBridge::~IpcBridge()
{ {
this->d->m_mainServer.disconnectPipeStateChanged(this, this->d->stopServiceStatusCheck();
&IpcBridgePrivate::pipeStateChanged);
this->unregisterPeer(); this->unregisterPeer();
this->d->m_mainServer.stop(); this->d->m_mainServer.stop();
delete this->d; delete this->d;
@ -1022,14 +1037,86 @@ void AkVCam::IpcBridgePrivate::updateDeviceSharedProperties(const std::string &d
} }
} }
void AkVCam::IpcBridgePrivate::pipeStateChanged(void *userData, bool AkVCam::IpcBridgePrivate::isServiceRunning() const
MessageServer::PipeState state)
{ {
AkLogFunction(); AkLogFunction();
auto self = reinterpret_cast<IpcBridgePrivate *>(userData); bool isRunning = false;
auto manager = OpenSCManager(nullptr, nullptr, GENERIC_READ);
switch (state) { if (manager) {
case MessageServer::PipeStateAvailable: auto service = OpenService(manager,
TEXT(DSHOW_PLUGIN_ASSISTANT_NAME),
SERVICE_QUERY_STATUS);
if (service) {
SERVICE_STATUS status;
memset(&status, 0, sizeof(SERVICE_STATUS));
QueryServiceStatus(service, &status);
isRunning = status.dwCurrentState == SERVICE_RUNNING;
CloseServiceHandle(service);
}
CloseServiceHandle(manager);
}
return isRunning;
}
void AkVCam::IpcBridgePrivate::startServiceStatusCheck()
{
AkLogFunction();
this->m_scManager = OpenSCManager(nullptr,
nullptr,
SC_MANAGER_CONNECT);
if (!this->m_scManager)
return;
this->m_assistantService =
OpenService(this->m_scManager,
TEXT(DSHOW_PLUGIN_ASSISTANT_NAME),
SERVICE_QUERY_STATUS);
if (!this->m_assistantService) {
CloseServiceHandle(this->m_scManager);
this->m_scManager = nullptr;
return;
}
memset(&this->m_notifyBuffer, 0, sizeof(SERVICE_NOTIFY));
this->m_notifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
this->m_notifyBuffer.pfnNotifyCallback =
PFN_SC_NOTIFY_CALLBACK(notifyCallback);
this->m_notifyBuffer.pContext = this;
NotifyServiceStatusChange(this->m_assistantService,
SERVICE_NOTIFY_RUNNING | SERVICE_NOTIFY_STOPPED,
&this->m_notifyBuffer);
}
void AkVCam::IpcBridgePrivate::stopServiceStatusCheck()
{
if (this->m_assistantService) {
CloseServiceHandle(this->m_assistantService);
this->m_assistantService = nullptr;
}
if (this->m_scManager) {
CloseServiceHandle(this->m_scManager);
this->m_scManager = nullptr;
}
}
void AkVCam::IpcBridgePrivate::notifyCallback(void *parameter)
{
AkLogFunction();
auto serviceNotify = PSERVICE_NOTIFY(parameter);
auto self = reinterpret_cast<IpcBridgePrivate *>(serviceNotify->pContext);
if (!self)
return;
if (serviceNotify->ServiceStatus.dwCurrentState == SERVICE_RUNNING) {
AkLogInfo() << "Server Available" << std::endl; AkLogInfo() << "Server Available" << std::endl;
if (self->self->registerPeer()) { if (self->self->registerPeer()) {
@ -1037,17 +1124,12 @@ void AkVCam::IpcBridgePrivate::pipeStateChanged(void *userData,
ServerStateChanged, ServerStateChanged,
IpcBridge::ServerStateAvailable) IpcBridge::ServerStateAvailable)
} }
} else {
break;
case MessageServer::PipeStateGone:
AkLogWarning() << "Server Gone" << std::endl; AkLogWarning() << "Server Gone" << std::endl;
AKVCAM_EMIT(self->self, AKVCAM_EMIT(self->self,
ServerStateChanged, ServerStateChanged,
IpcBridge::ServerStateGone) IpcBridge::ServerStateGone)
self->self->unregisterPeer(); self->self->unregisterPeer();
break;
} }
} }

View file

@ -63,6 +63,7 @@ namespace AkVCam
std::string m_filterName; std::string m_filterName;
IFilterGraph *m_filterGraph {nullptr}; IFilterGraph *m_filterGraph {nullptr};
IpcBridge m_ipcBridge; IpcBridge m_ipcBridge;
IpcBridge::ServerState m_serverState {IpcBridge::ServerStateGone};
BaseFilterPrivate(BaseFilter *self, BaseFilterPrivate(BaseFilter *self,
const std::string &filterName, const std::string &filterName,
@ -457,6 +458,16 @@ void AkVCam::BaseFilterPrivate::serverStateChanged(void *userData,
{ {
AkLogFunction(); AkLogFunction();
auto self = reinterpret_cast<BaseFilterPrivate *>(userData); auto self = reinterpret_cast<BaseFilterPrivate *>(userData);
if (self->m_serverState == state)
return;
FILTER_STATE filterState = State_Stopped;
self->self->GetState(0, &filterState);
if (filterState != State_Stopped)
return;
IEnumPins *pins = nullptr; IEnumPins *pins = nullptr;
self->self->EnumPins(&pins); self->self->EnumPins(&pins);
@ -467,6 +478,8 @@ void AkVCam::BaseFilterPrivate::serverStateChanged(void *userData,
if (state == IpcBridge::ServerStateAvailable) if (state == IpcBridge::ServerStateAvailable)
self->updatePins(); self->updatePins();
self->m_serverState = state;
} }
void AkVCam::BaseFilterPrivate::frameReady(void *userData, void AkVCam::BaseFilterPrivate::frameReady(void *userData,