Skip to content

Commit

Permalink
add support for AJA capture cards
Browse files Browse the repository at this point in the history
  • Loading branch information
lukegb committed Dec 22, 2024
1 parent 1c88dbb commit cfc43d3
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 2 deletions.
4 changes: 2 additions & 2 deletions vocto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
os.environ['GST_DEBUG_DUMP_DOT_DIR'] = os.getcwd()

def kind_has_audio(source):
return source in ["decklink", "tcp", "test", "pa", "alsa"]
return source in ["aja", "decklink", "tcp", "test", "pa", "alsa"]

def kind_has_video(source):
return source in ["decklink", "tcp", "test", "v4l2", "img", "file", "background", "RPICam"]
return source in ["aja", "decklink", "tcp", "test", "v4l2", "img", "file", "background", "RPICam"]
12 changes: 12 additions & 0 deletions vocto/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ def getDeckLinkVideoMode(self, source):

def getDeckLinkVideoFormat(self, source):
return self.get('source.{}'.format(source), 'video_format', fallback='auto')

def getAJADeviceIdentifier(self, source):
return self.get(f'source.{source}', 'device', fallback='')

def getAJAInputChannel(self, source):
return self.getint(f'source.{source}', 'channel', fallback=0)

def getAJAVideoMode(self, source):
return self.get(f'source.{source}', 'video_mode', fallback='auto')

def getAJAAudioSource(self, source):
return self.get(f'source.{source}', 'audio_source', fallback='embedded')

def getPulseAudioDevice(self, source):
return self.get('source.{}'.format(source), 'device', fallback='auto')
Expand Down
3 changes: 3 additions & 0 deletions voctocore/lib/sources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
def spawn_source(name, port, has_audio=True, has_video=True):

from lib.config import Config
from lib.sources.ajaavsource import AJAAVSource
from lib.sources.decklinkavsource import DeckLinkAVSource
from lib.sources.imgvsource import ImgVSource
from lib.sources.tcpavsource import TCPAVSource
Expand All @@ -24,6 +25,8 @@ def spawn_source(name, port, has_audio=True, has_video=True):
sources[name] = ImgVSource(name)
elif kind == 'decklink':
sources[name] = DeckLinkAVSource(name, has_audio, has_video)
elif kind == 'aja':
sources[name] = AJAAVSource(name, has_audio, has_video)
elif kind == 'file':
sources[name] = FileSource(name, has_audio, has_video)
elif kind == 'tcp':
Expand Down
99 changes: 99 additions & 0 deletions voctocore/lib/sources/ajaavsource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
import logging
import re

from lib.config import Config
from lib.sources.avsource import AVSource


class AJAAVSource(AVSource):

timer_resolution = 0.5

def __init__(self, name, has_audio=True, has_video=True):
super().__init__('AJAAVSource', name, has_audio, has_video, show_no_signal=True)

self.device = Config.getAJADeviceIdentifier(name)
self.input_channel = Config.getAJAInputChannel(name)
self.vmode = Config.getAJAVideoMode(name)
self.asrc = Config.getAJAAudioSource(name)
self.name = name

self.signalPad = None
self.build_pipeline()

def port(self):
return "AJA #{}".format(self.device)

def attach(self, pipeline):
super().attach(pipeline)
self.signalPad = pipeline.get_by_name(
f'ajasrc-{self.name}')

def num_connections(self):
return 1 if self.signalPad and self.signalPad.get_property('signal') else 0

def get_valid_channel_numbers(self):
return (2, 8, 16)

def __str__(self):
return f'AJAAVSource[{self.name}] reading card #{self.device}'

def build_source(self):
pipe = f"""
ajasrc
name=ajasrc-{self.name}
device-identifier={self.device}
channel={self.input_channel}
video-format={self.vmode}
! ajasrcdemux
name=ajasrcdemux-{self.name}
"""

# add rest of the video pipeline
if self.has_video:
pipe += f"""\
ajasrcdemux-{self.name}.video
"""

# maybe add deinterlacer
if deinterlacer := self.build_deinterlacer():
pipe += f"""\
! {deinterlacer}
"""

pipe += f"""\
! videoconvert
! videoscale
! videorate
name=vout-{self.name}
"""

if chans := self.internal_audio_channels():
pipe += f"""\
ajasrcdemux-{self.name}.audio
! audioconvert
"""

if chans < 16:
# Take the first {chans} channels.
pipe += f"""\
! audiomixmatrix
in-channels=16
out-channels={chans}
mode=first-channels
"""
pipe += f"""\
name=aout-{self.name}
"""

return pipe

def build_audioport(self):
return f'aout-{self.name}.'

def build_videoport(self):
return f'vout-{self.name}.'

def get_nosignal_text(self):
return f"{super().get_nosignal_text()}/AJA{self.device}"

0 comments on commit cfc43d3

Please sign in to comment.