Skip to content

Commit

Permalink
LinuxCapture: Add mutex around AVC calls
Browse files Browse the repository at this point in the history
Signed-off-by: Maxime Gervais <[email protected]>
  • Loading branch information
g-maxime committed Apr 26, 2024
1 parent c599274 commit 673cdbc
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
47 changes: 44 additions & 3 deletions Source/Common/LinuxWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <vector>
#include <cstring>
#include <sstream>
#include <iostream>
#include <sys/poll.h>
#include <libavc1394/rom1394.h>
#include <libavc1394/avc1394.h>
Expand Down Expand Up @@ -133,6 +134,8 @@ LinuxWrapper::LinuxWrapper(size_t DeviceIndex)
throw error("Unable to connect to device.");
}

raw1394_set_bus_reset_handler(CtlHandle, LinuxWrapper::Raw1394ControlBusResetHandler);

iec61883_cmp_normalize_output(CtlHandle, 0xffc0 | Node);
}

Expand Down Expand Up @@ -189,7 +192,11 @@ LinuxWrapper::~LinuxWrapper()
StopCaptureSession();

if (CtlHandle)
{
CtlHandleMutex.lock();
raw1394_destroy_handle(CtlHandle);
CtlHandleMutex.unlock();
}
}

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -264,7 +271,9 @@ size_t LinuxWrapper::GetDeviceIndex(const string& DeviceID)
//---------------------------------------------------------------------------
playback_mode LinuxWrapper::GetMode()
{
CtlHandleMutex.lock();
quadlet_t Status = avc1394_vcr_status(CtlHandle, Node);
CtlHandleMutex.unlock();
if (AVC1394_MASK_OPCODE(Status) == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY)
{
if (AVC1394_MASK_OPERAND0(Status) >= AVC1394_VCR_OPERAND_PLAY_SLOWEST_FORWARD &&
Expand All @@ -281,7 +290,9 @@ std::string LinuxWrapper::GetStatus()
if (!CtlHandle || Node == (nodeid_t)-1)
return "invalid";

CtlHandleMutex.lock();
quadlet_t Status = avc1394_vcr_status(CtlHandle, Node);
CtlHandleMutex.unlock();

if (AVC1394_MASK_OPCODE(Status) == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY)
{
Expand Down Expand Up @@ -328,7 +339,9 @@ float LinuxWrapper::GetSpeed()
if (!CtlHandle || Node == (nodeid_t)-1)
return 0.0f;

CtlHandleMutex.lock();
quadlet_t Status = avc1394_vcr_status(CtlHandle, Node);
CtlHandleMutex.unlock();
if (AVC1394_MASK_OPCODE(Status) == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY)
{
if (AVC1394_MASK_OPERAND0(Status) == AVC1394_VCR_OPERAND_PLAY_REVERSE_PAUSE ||
Expand Down Expand Up @@ -373,6 +386,8 @@ void LinuxWrapper::CreateCaptureSession(FileWrapper* Wrapper_)
CaptureHandle = raw1394_new_handle_on_port(Port);
if (CaptureHandle)
{
raw1394_set_bus_reset_handler(CaptureHandle, LinuxWrapper::Raw1394CaptureBusResetHandler);

Channel = iec61883_cmp_connect(CaptureHandle, Node, &OutPlug, raw1394_get_local_id(CaptureHandle), &InPlug, &Bandwidth);
if (Channel < 0) // try broadcast channel if connect failed
Channel = 63;
Expand Down Expand Up @@ -504,9 +519,28 @@ bool LinuxWrapper::WaitForSessionEnd(uint64_t Timeout)
return false;
}

//---------------------------------------------------------------------------
int LinuxWrapper::Raw1394CaptureBusResetHandler(raw1394handle_t, unsigned int)
{
cerr << "Error: Capture bus was reset." << endl;
StopCaptureSession();
return 0;
}

//---------------------------------------------------------------------------
int LinuxWrapper::Raw1394ControlBusResetHandler(raw1394handle_t Handle, unsigned int Generation)
{
cerr << "Error: Capture bus was reset." << endl;
StopCaptureSession();
return 0;
}

//---------------------------------------------------------------------------
void LinuxWrapper::SetPlaybackMode(playback_mode Mode, float Speed)
{
if (!CtlHandle || Node == (nodeid_t)-1)
return;

switch (Mode)
{
case Playback_Mode_Playing:
Expand All @@ -531,17 +565,24 @@ void LinuxWrapper::SetPlaybackMode(playback_mode Mode, float Speed)
else if (Speed <= -2.0f) // fastest reverse play mode
Code=AVC1394_VCR_OPERAND_PLAY_FASTEST_REVERSE;

CtlHandleMutex.lock();
avc1394_send_command(CtlHandle, Node, CTLVCR0 | AVC1394_VCR_COMMAND_PLAY | Code);
CtlHandleMutex.unlock();
break;
}
case Playback_Mode_NotPlaying:
{
uint8_t Code;
if (Speed == 0.0f) // stop
avc1394_send_command(CtlHandle, Node, CTLVCR0 | AVC1394_VCR_COMMAND_WIND | AVC1394_VCR_OPERAND_WIND_STOP);
Code=AVC1394_VCR_OPERAND_WIND_STOP;
else if (Speed > 0.0f) // fast-forward
avc1394_send_command(CtlHandle, Node, CTLVCR0 | AVC1394_VCR_COMMAND_WIND | AVC1394_VCR_OPERAND_WIND_FAST_FORWARD);
Code=AVC1394_VCR_OPERAND_WIND_FAST_FORWARD;
else if (Speed < 0.0f) // rewind
avc1394_send_command(CtlHandle, Node, CTLVCR0 | AVC1394_VCR_COMMAND_WIND | AVC1394_VCR_OPERAND_WIND_REWIND);
Code=AVC1394_VCR_OPERAND_WIND_REWIND;

CtlHandleMutex.lock();
avc1394_send_command(CtlHandle, Node, CTLVCR0 | AVC1394_VCR_COMMAND_WIND | Code);
CtlHandleMutex.unlock();
break;
}
}
Expand Down
5 changes: 5 additions & 0 deletions Source/Common/LinuxWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,18 @@ class LinuxWrapper : public BaseWrapper {
static const std::string Interface;

private:
// Functions
static int Raw1394CaptureBusResetHandler(raw1394handle_t Handle, unsigned int Generation);
static int Raw1394ControlBusResetHandler(raw1394handle_t Handle, unsigned int Generation);

// global
int Port = -1;
nodeid_t Node = (nodeid_t)-1;
octlet_t UUID = (octlet_t)-1;

// avc1394
raw1394handle_t CtlHandle = nullptr;
std::mutex CtlHandleMutex;

// mi
FileWrapper* Wrapper = nullptr;
Expand Down

0 comments on commit 673cdbc

Please sign in to comment.