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:
int64_t m_num;
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
{
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)

View file

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

View file

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

View file

@ -39,6 +39,18 @@
#include "VCamUtils/src/ipcbridge.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
{
using RegisterServerFunc = HRESULT (WINAPI *)();
@ -82,6 +94,9 @@ namespace AkVCam
MessageServer m_mainServer;
SharedMemory m_sharedMemory;
Mutex m_globalMutex;
SC_HANDLE m_scManager {nullptr};
SC_HANDLE m_assistantService {nullptr};
SERVICE_NOTIFY m_notifyBuffer;
explicit IpcBridgePrivate(IpcBridge *self);
~IpcBridgePrivate();
@ -91,8 +106,10 @@ namespace AkVCam
void updateDeviceSharedProperties();
void updateDeviceSharedProperties(const std::string &deviceId,
const std::string &owner);
static void pipeStateChanged(void *userData,
MessageServer::PipeState state);
bool isServiceRunning() const;
void startServiceStatusCheck();
void stopServiceStatusCheck();
static void CALLBACK notifyCallback(void *parameter);
// Message handling methods
void isAlive(Message *message);
@ -135,14 +152,12 @@ AkVCam::IpcBridge::IpcBridge()
this->d->m_mainServer.start();
this->registerPeer();
this->d->updateDeviceSharedProperties();
this->d->m_mainServer.connectPipeStateChanged(this,
&IpcBridgePrivate::pipeStateChanged);
this->d->startServiceStatusCheck();
}
AkVCam::IpcBridge::~IpcBridge()
{
this->d->m_mainServer.disconnectPipeStateChanged(this,
&IpcBridgePrivate::pipeStateChanged);
this->d->stopServiceStatusCheck();
this->unregisterPeer();
this->d->m_mainServer.stop();
delete this->d;
@ -1022,14 +1037,86 @@ void AkVCam::IpcBridgePrivate::updateDeviceSharedProperties(const std::string &d
}
}
void AkVCam::IpcBridgePrivate::pipeStateChanged(void *userData,
MessageServer::PipeState state)
bool AkVCam::IpcBridgePrivate::isServiceRunning() const
{
AkLogFunction();
auto self = reinterpret_cast<IpcBridgePrivate *>(userData);
bool isRunning = false;
auto manager = OpenSCManager(nullptr, nullptr, GENERIC_READ);
switch (state) {
case MessageServer::PipeStateAvailable:
if (manager) {
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;
if (self->self->registerPeer()) {
@ -1037,17 +1124,12 @@ void AkVCam::IpcBridgePrivate::pipeStateChanged(void *userData,
ServerStateChanged,
IpcBridge::ServerStateAvailable)
}
break;
case MessageServer::PipeStateGone:
} else {
AkLogWarning() << "Server Gone" << std::endl;
AKVCAM_EMIT(self->self,
ServerStateChanged,
IpcBridge::ServerStateGone)
self->self->unregisterPeer();
break;
}
}

View file

@ -63,6 +63,7 @@ namespace AkVCam
std::string m_filterName;
IFilterGraph *m_filterGraph {nullptr};
IpcBridge m_ipcBridge;
IpcBridge::ServerState m_serverState {IpcBridge::ServerStateGone};
BaseFilterPrivate(BaseFilter *self,
const std::string &filterName,
@ -457,6 +458,16 @@ void AkVCam::BaseFilterPrivate::serverStateChanged(void *userData,
{
AkLogFunction();
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;
self->self->EnumPins(&pins);
@ -467,6 +478,8 @@ void AkVCam::BaseFilterPrivate::serverStateChanged(void *userData,
if (state == IpcBridge::ServerStateAvailable)
self->updatePins();
self->m_serverState = state;
}
void AkVCam::BaseFilterPrivate::frameReady(void *userData,