mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
Implement auto mode detection in ajasrc
This also allows switching modes while running.
This commit is contained in:
parent
02519523df
commit
d03f733bba
3 changed files with 696 additions and 647 deletions
|
@ -789,7 +789,7 @@ GType gst_aja_sdi_mode_get_type(void) {
|
|||
GType gst_aja_video_format_get_type(void) {
|
||||
static gsize id = 0;
|
||||
static const GEnumValue modes[] = {
|
||||
// TODO: Implement: {GST_AJA_VIDEO_FORMAT_AUTO, "auto", "Autodetect"},
|
||||
{GST_AJA_VIDEO_FORMAT_AUTO, "auto", "Auto detect format"},
|
||||
{GST_AJA_VIDEO_FORMAT_1080i_5000, "1080i-5000", "1080i 5000"},
|
||||
{GST_AJA_VIDEO_FORMAT_1080i_5994, "1080i-5994", "1080i 5994"},
|
||||
{GST_AJA_VIDEO_FORMAT_1080i_6000, "1080i-6000", "1080i 6000"},
|
||||
|
|
|
@ -182,7 +182,7 @@ GType gst_aja_sdi_mode_get_type(void);
|
|||
|
||||
typedef enum {
|
||||
GST_AJA_VIDEO_FORMAT_INVALID = -1,
|
||||
// TODO: Implement: GST_AJA_VIDEO_FORMAT_AUTO,
|
||||
GST_AJA_VIDEO_FORMAT_AUTO,
|
||||
GST_AJA_VIDEO_FORMAT_1080i_5000,
|
||||
GST_AJA_VIDEO_FORMAT_1080i_5994,
|
||||
GST_AJA_VIDEO_FORMAT_1080i_6000,
|
||||
|
|
445
gstajasrc.cpp
445
gstajasrc.cpp
|
@ -34,7 +34,6 @@ GST_DEBUG_CATEGORY_STATIC(gst_aja_src_debug);
|
|||
|
||||
#define DEFAULT_DEVICE_IDENTIFIER ("0")
|
||||
#define DEFAULT_CHANNEL (::NTV2_CHANNEL1)
|
||||
// TODO: GST_AJA_VIDEO_FORMAT_AUTO
|
||||
#define DEFAULT_VIDEO_FORMAT (GST_AJA_VIDEO_FORMAT_1080i_5000)
|
||||
#define DEFAULT_AUDIO_SYSTEM (GST_AJA_AUDIO_SYSTEM_AUTO)
|
||||
#define DEFAULT_INPUT_SOURCE (GST_AJA_INPUT_SOURCE_AUTO)
|
||||
|
@ -93,7 +92,6 @@ static GstFlowReturn gst_aja_src_create(GstPushSrc *psrc, GstBuffer **buffer);
|
|||
|
||||
static gboolean gst_aja_src_open(GstAjaSrc *src);
|
||||
static gboolean gst_aja_src_close(GstAjaSrc *src);
|
||||
static gboolean gst_aja_src_start(GstAjaSrc *src);
|
||||
static gboolean gst_aja_src_stop(GstAjaSrc *src);
|
||||
|
||||
static GstStateChangeReturn gst_aja_src_change_state(GstElement *element,
|
||||
|
@ -250,6 +248,8 @@ static void gst_aja_src_init(GstAjaSrc *self) {
|
|||
gst_queue_array_new_for_struct(sizeof(QueueItem), self->queue_size);
|
||||
gst_base_src_set_live(GST_BASE_SRC_CAST(self), TRUE);
|
||||
gst_base_src_set_format(GST_BASE_SRC_CAST(self), GST_FORMAT_TIME);
|
||||
|
||||
self->video_format = NTV2_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
void gst_aja_src_set_property(GObject *object, guint property_id,
|
||||
|
@ -412,14 +412,10 @@ static gboolean gst_aja_src_close(GstAjaSrc *self) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
||||
// Must be called with ShmMutexLocker
|
||||
static gboolean gst_aja_src_configure(GstAjaSrc *self) {
|
||||
GST_DEBUG_OBJECT(self, "Starting");
|
||||
|
||||
{
|
||||
// Make sure to globally lock here as the routing settings and others are
|
||||
// global shared state
|
||||
ShmMutexLocker locker;
|
||||
|
||||
#define NEEDS_QUAD_MODE(self) \
|
||||
(self->sdi_mode == GST_AJA_SDI_MODE_QUAD_LINK_SQD || \
|
||||
self->sdi_mode == GST_AJA_SDI_MODE_QUAD_LINK_TSI || \
|
||||
|
@ -427,126 +423,30 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
self->input_source <= GST_AJA_INPUT_SOURCE_HDMI4))
|
||||
|
||||
self->quad_mode = NEEDS_QUAD_MODE(self);
|
||||
self->video_format = gst_ntv2_video_format_from_aja_format(
|
||||
self->video_format_setting, self->quad_mode);
|
||||
|
||||
#undef NEEDS_QUAD_MODE
|
||||
|
||||
if (self->video_format == NTV2_FORMAT_UNKNOWN) {
|
||||
GST_ERROR_OBJECT(self, "Unsupported mode");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!::NTV2DeviceCanDoVideoFormat(self->device_id, self->video_format)) {
|
||||
GST_ERROR_OBJECT(self, "Device does not support mode %d",
|
||||
(int)self->video_format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->device->device->AutoCirculateStop(self->channel);
|
||||
if (self->quad_mode) {
|
||||
if (self->channel != ::NTV2_CHANNEL1 &&
|
||||
self->channel != ::NTV2_CHANNEL5) {
|
||||
GST_ERROR_OBJECT(self, "Quad modes require channels 1 or 5");
|
||||
return FALSE;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
self->device->device->AutoCirculateStop((NTV2Channel)(self->channel + i));
|
||||
}
|
||||
}
|
||||
|
||||
gst_video_info_from_ntv2_video_format(&self->configured_info,
|
||||
self->video_format);
|
||||
|
||||
if (self->quad_mode) {
|
||||
if (self->input_source >= GST_AJA_INPUT_SOURCE_HDMI1 &&
|
||||
self->input_source <= GST_AJA_INPUT_SOURCE_HDMI4) {
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false, self->channel);
|
||||
self->device->device->Set4kSquaresEnable(true, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(true, self->channel);
|
||||
} else {
|
||||
switch (self->sdi_mode) {
|
||||
case GST_AJA_SDI_MODE_SINGLE_LINK:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
case GST_AJA_SDI_MODE_QUAD_LINK_SQD:
|
||||
if (self->configured_info.height > 2160) {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(true, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(true,
|
||||
self->channel);
|
||||
} else {
|
||||
self->device->device->SetQuadQuadFrameEnable(false,
|
||||
self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
self->device->device->Set4kSquaresEnable(true, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
}
|
||||
break;
|
||||
case GST_AJA_SDI_MODE_QUAD_LINK_TSI:
|
||||
if (self->configured_info.height > 2160) {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(true, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
} else {
|
||||
self->device->device->SetQuadQuadFrameEnable(false,
|
||||
self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(true, self->channel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false, self->channel);
|
||||
if (self->buffer_pool) {
|
||||
gst_buffer_pool_set_active(self->buffer_pool, FALSE);
|
||||
gst_clear_object(&self->buffer_pool);
|
||||
}
|
||||
|
||||
self->device->device->SetMode(self->channel, NTV2_MODE_CAPTURE, false);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetMode((NTV2Channel)(self->channel + i),
|
||||
NTV2_MODE_CAPTURE, false);
|
||||
if (self->audio_buffer_pool) {
|
||||
gst_buffer_pool_set_active(self->audio_buffer_pool, FALSE);
|
||||
gst_clear_object(&self->audio_buffer_pool);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT(self, "Configuring video format %d on channel %d",
|
||||
(int)self->video_format, (int)self->channel);
|
||||
self->device->device->SetVideoFormat(self->video_format, false, false,
|
||||
self->channel);
|
||||
|
||||
if (!::NTV2DeviceCanDoFrameBufferFormat(self->device_id,
|
||||
::NTV2_FBF_10BIT_YCBCR)) {
|
||||
GST_ERROR_OBJECT(self, "Device does not support frame buffer format %d",
|
||||
(int)::NTV2_FBF_10BIT_YCBCR);
|
||||
return FALSE;
|
||||
if (self->anc_buffer_pool) {
|
||||
gst_buffer_pool_set_active(self->anc_buffer_pool, FALSE);
|
||||
gst_clear_object(&self->anc_buffer_pool);
|
||||
}
|
||||
self->device->device->SetFrameBufferFormat(self->channel,
|
||||
::NTV2_FBF_10BIT_YCBCR);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetFrameBufferFormat(
|
||||
(NTV2Channel)(self->channel + i), ::NTV2_FBF_10BIT_YCBCR);
|
||||
}
|
||||
|
||||
self->device->device->DMABufferAutoLock(false, true, 0);
|
||||
|
||||
if (::NTV2DeviceHasBiDirectionalSDI(self->device_id)) {
|
||||
self->device->device->SetSDITransmitEnable(self->channel, false);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetSDITransmitEnable(
|
||||
(NTV2Channel)(self->channel + i), false);
|
||||
}
|
||||
}
|
||||
|
||||
// Always use the framebuffer associated with the channel
|
||||
NTV2InputCrosspointID framebuffer_id =
|
||||
::GetFrameBufferInputXptFromChannel(self->channel, false);
|
||||
|
||||
NTV2VANCMode vanc_mode;
|
||||
NTV2InputSource input_source;
|
||||
|
@ -554,8 +454,7 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
switch (self->input_source) {
|
||||
case GST_AJA_INPUT_SOURCE_AUTO:
|
||||
input_source = ::NTV2ChannelToInputSource(self->channel);
|
||||
input_source_id =
|
||||
::GetSDIInputOutputXptFromChannel(self->channel, false);
|
||||
input_source_id = ::GetSDIInputOutputXptFromChannel(self->channel, false);
|
||||
vanc_mode = ::NTV2DeviceCanDoCustomAnc(self->device_id)
|
||||
? ::NTV2_VANCMODE_OFF
|
||||
: ::NTV2_VANCMODE_TALL;
|
||||
|
@ -634,6 +533,154 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
|
||||
self->vanc_mode = vanc_mode;
|
||||
|
||||
if (!self->device->device->EnableChannel(self->channel)) {
|
||||
GST_ERROR_OBJECT(self, "Failed to enable channel");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (!self->device->device->EnableChannel(
|
||||
(NTV2Channel)(self->channel + i))) {
|
||||
GST_ERROR_OBJECT(self, "Failed to enable channel");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->device->device->EnableInputInterrupt(self->channel);
|
||||
self->device->device->SubscribeInputVerticalEvent(self->channel);
|
||||
|
||||
if (self->video_format_setting == GST_AJA_VIDEO_FORMAT_AUTO) {
|
||||
self->device->device->WaitForInputVerticalInterrupt(self->channel, 10);
|
||||
self->video_format = self->device->device->GetInputVideoFormat(
|
||||
self->configured_input_source);
|
||||
if (self->video_format == NTV2_FORMAT_UNKNOWN) {
|
||||
GST_ERROR_OBJECT(self, "Input video format not detected");
|
||||
return TRUE;
|
||||
}
|
||||
std::string configured_string = NTV2VideoFormatToString(self->video_format);
|
||||
GST_DEBUG_OBJECT(self, "Detected input video format %s (%d)",
|
||||
configured_string.c_str(), (int)self->video_format);
|
||||
} else {
|
||||
self->video_format = gst_ntv2_video_format_from_aja_format(
|
||||
self->video_format_setting, self->quad_mode);
|
||||
}
|
||||
|
||||
if (self->video_format == NTV2_FORMAT_UNKNOWN) {
|
||||
GST_ERROR_OBJECT(self, "Unsupported mode");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!::NTV2DeviceCanDoVideoFormat(self->device_id, self->video_format)) {
|
||||
GST_ERROR_OBJECT(self, "Device does not support mode %d",
|
||||
(int)self->video_format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->quad_mode) {
|
||||
if (self->channel != ::NTV2_CHANNEL1 && self->channel != ::NTV2_CHANNEL5) {
|
||||
GST_ERROR_OBJECT(self, "Quad modes require channels 1 or 5");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_video_info_from_ntv2_video_format(&self->configured_info,
|
||||
self->video_format);
|
||||
|
||||
if (self->quad_mode) {
|
||||
if (self->input_source >= GST_AJA_INPUT_SOURCE_HDMI1 &&
|
||||
self->input_source <= GST_AJA_INPUT_SOURCE_HDMI4) {
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false, self->channel);
|
||||
self->device->device->Set4kSquaresEnable(true, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(true, self->channel);
|
||||
} else {
|
||||
switch (self->sdi_mode) {
|
||||
case GST_AJA_SDI_MODE_SINGLE_LINK:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
case GST_AJA_SDI_MODE_QUAD_LINK_SQD:
|
||||
if (self->configured_info.height > 2160) {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(true, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(true, self->channel);
|
||||
} else {
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
self->device->device->Set4kSquaresEnable(true, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
}
|
||||
break;
|
||||
case GST_AJA_SDI_MODE_QUAD_LINK_TSI:
|
||||
if (self->configured_info.height > 2160) {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(true, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
} else {
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false,
|
||||
self->channel);
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(true, self->channel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self->device->device->Set4kSquaresEnable(false, self->channel);
|
||||
self->device->device->SetTsiFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadFrameEnable(false, self->channel);
|
||||
self->device->device->SetQuadQuadSquaresEnable(false, self->channel);
|
||||
}
|
||||
|
||||
self->device->device->SetMode(self->channel, NTV2_MODE_CAPTURE, false);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetMode((NTV2Channel)(self->channel + i),
|
||||
NTV2_MODE_CAPTURE, false);
|
||||
}
|
||||
|
||||
std::string configured_string = NTV2VideoFormatToString(self->video_format);
|
||||
GST_DEBUG_OBJECT(self, "Configuring video format %s (%d) on channel %d",
|
||||
configured_string.c_str(), (int)self->video_format,
|
||||
(int)self->channel);
|
||||
self->device->device->SetVideoFormat(self->video_format, false, false,
|
||||
self->channel);
|
||||
|
||||
if (!::NTV2DeviceCanDoFrameBufferFormat(self->device_id,
|
||||
::NTV2_FBF_10BIT_YCBCR)) {
|
||||
GST_ERROR_OBJECT(self, "Device does not support frame buffer format %d",
|
||||
(int)::NTV2_FBF_10BIT_YCBCR);
|
||||
return FALSE;
|
||||
}
|
||||
self->device->device->SetFrameBufferFormat(self->channel,
|
||||
::NTV2_FBF_10BIT_YCBCR);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetFrameBufferFormat(
|
||||
(NTV2Channel)(self->channel + i), ::NTV2_FBF_10BIT_YCBCR);
|
||||
}
|
||||
|
||||
self->device->device->DMABufferAutoLock(false, true, 0);
|
||||
|
||||
if (::NTV2DeviceHasBiDirectionalSDI(self->device_id)) {
|
||||
self->device->device->SetSDITransmitEnable(self->channel, false);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++)
|
||||
self->device->device->SetSDITransmitEnable(
|
||||
(NTV2Channel)(self->channel + i), false);
|
||||
}
|
||||
}
|
||||
|
||||
// Always use the framebuffer associated with the channel
|
||||
NTV2InputCrosspointID framebuffer_id =
|
||||
::GetFrameBufferInputXptFromChannel(self->channel, false);
|
||||
|
||||
const NTV2Standard standard(
|
||||
::GetNTV2StandardFromVideoFormat(self->video_format));
|
||||
self->device->device->SetStandard(standard, self->channel);
|
||||
|
@ -664,8 +711,7 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
const NTV2FrameGeometry vanc_geometry =
|
||||
::GetVANCFrameGeometry(geometry, self->vanc_mode);
|
||||
|
||||
self->device->device->SetFrameGeometry(vanc_geometry, false,
|
||||
self->channel);
|
||||
self->device->device->SetFrameGeometry(vanc_geometry, false, self->channel);
|
||||
self->device->device->SetVANCMode(self->vanc_mode, self->channel);
|
||||
|
||||
if (self->quad_mode) {
|
||||
|
@ -691,8 +737,7 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
self->input_source <= GST_AJA_INPUT_SOURCE_HDMI4) {
|
||||
// Need to disconnect the 4 inputs corresponding to this channel from
|
||||
// their framebuffers/muxers, and muxers from their framebuffers
|
||||
for (auto iter = connections.begin(); iter != connections.end();
|
||||
iter++) {
|
||||
for (auto iter = connections.begin(); iter != connections.end(); iter++) {
|
||||
if (iter->first == NTV2_XptFrameBuffer1Input ||
|
||||
iter->first == NTV2_XptFrameBuffer1BInput ||
|
||||
iter->first == NTV2_XptFrameBuffer2Input ||
|
||||
|
@ -712,8 +757,7 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
router.RemoveConnection(iter->first, iter->second);
|
||||
}
|
||||
} else if (self->channel == NTV2_CHANNEL1) {
|
||||
for (auto iter = connections.begin(); iter != connections.end();
|
||||
iter++) {
|
||||
for (auto iter = connections.begin(); iter != connections.end(); iter++) {
|
||||
if (iter->first == NTV2_XptFrameBuffer1Input ||
|
||||
iter->first == NTV2_XptFrameBuffer1BInput ||
|
||||
iter->first == NTV2_XptFrameBuffer1DS2Input ||
|
||||
|
@ -728,10 +772,8 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
iter->first == NTV2_Xpt425Mux1BInput ||
|
||||
iter->first == NTV2_Xpt425Mux2AInput ||
|
||||
iter->first == NTV2_Xpt425Mux2BInput ||
|
||||
iter->second == NTV2_XptSDIIn1 ||
|
||||
iter->second == NTV2_XptSDIIn2 ||
|
||||
iter->second == NTV2_XptSDIIn3 ||
|
||||
iter->second == NTV2_XptSDIIn4 ||
|
||||
iter->second == NTV2_XptSDIIn1 || iter->second == NTV2_XptSDIIn2 ||
|
||||
iter->second == NTV2_XptSDIIn3 || iter->second == NTV2_XptSDIIn4 ||
|
||||
iter->second == NTV2_XptSDIIn1DS2 ||
|
||||
iter->second == NTV2_XptSDIIn2DS2 ||
|
||||
iter->first == NTV2_XptFrameBuffer1Input ||
|
||||
|
@ -741,8 +783,7 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
router.RemoveConnection(iter->first, iter->second);
|
||||
}
|
||||
} else if (self->channel == NTV2_CHANNEL5) {
|
||||
for (auto iter = connections.begin(); iter != connections.end();
|
||||
iter++) {
|
||||
for (auto iter = connections.begin(); iter != connections.end(); iter++) {
|
||||
if (iter->first == NTV2_XptFrameBuffer5Input ||
|
||||
iter->first == NTV2_XptFrameBuffer5BInput ||
|
||||
iter->first == NTV2_XptFrameBuffer5DS2Input ||
|
||||
|
@ -757,10 +798,8 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
iter->first == NTV2_Xpt425Mux3BInput ||
|
||||
iter->first == NTV2_Xpt425Mux4AInput ||
|
||||
iter->first == NTV2_Xpt425Mux4BInput ||
|
||||
iter->second == NTV2_XptSDIIn5 ||
|
||||
iter->second == NTV2_XptSDIIn6 ||
|
||||
iter->second == NTV2_XptSDIIn7 ||
|
||||
iter->second == NTV2_XptSDIIn8 ||
|
||||
iter->second == NTV2_XptSDIIn5 || iter->second == NTV2_XptSDIIn6 ||
|
||||
iter->second == NTV2_XptSDIIn7 || iter->second == NTV2_XptSDIIn8 ||
|
||||
iter->second == NTV2_XptSDIIn5DS2 ||
|
||||
iter->second == NTV2_XptSDIIn6DS2 ||
|
||||
iter->first == NTV2_XptFrameBuffer5Input ||
|
||||
|
@ -828,17 +867,13 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
if (self->sdi_mode == GST_AJA_SDI_MODE_QUAD_LINK_TSI) {
|
||||
if (NTV2_IS_QUAD_QUAD_HFR_VIDEO_FORMAT(self->video_format)) {
|
||||
if (self->channel == NTV2_CHANNEL1) {
|
||||
router.AddConnection(NTV2_XptFrameBuffer1DS2Input,
|
||||
NTV2_XptSDIIn2);
|
||||
router.AddConnection(NTV2_XptFrameBuffer1DS2Input, NTV2_XptSDIIn2);
|
||||
router.AddConnection(NTV2_XptFrameBuffer2Input, NTV2_XptSDIIn3);
|
||||
router.AddConnection(NTV2_XptFrameBuffer2DS2Input,
|
||||
NTV2_XptSDIIn4);
|
||||
router.AddConnection(NTV2_XptFrameBuffer2DS2Input, NTV2_XptSDIIn4);
|
||||
} else if (self->channel == NTV2_CHANNEL5) {
|
||||
router.AddConnection(NTV2_XptFrameBuffer5DS2Input,
|
||||
NTV2_XptSDIIn6);
|
||||
router.AddConnection(NTV2_XptFrameBuffer5DS2Input, NTV2_XptSDIIn6);
|
||||
router.AddConnection(NTV2_XptFrameBuffer5Input, NTV2_XptSDIIn7);
|
||||
router.AddConnection(NTV2_XptFrameBuffer6DS2Input,
|
||||
NTV2_XptSDIIn8);
|
||||
router.AddConnection(NTV2_XptFrameBuffer6DS2Input, NTV2_XptSDIIn8);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -987,8 +1022,8 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
::NTV2InputSourceToEmbeddedAudioInput(input_source));
|
||||
self->configured_audio_channels =
|
||||
::NTV2DeviceGetMaxAudioChannels(self->device_id);
|
||||
self->device->device->SetNumberAudioChannels(
|
||||
self->configured_audio_channels, self->audio_system);
|
||||
self->device->device->SetNumberAudioChannels(self->configured_audio_channels,
|
||||
self->audio_system);
|
||||
self->device->device->SetAudioRate(::NTV2_AUDIO_48K, self->audio_system);
|
||||
self->device->device->SetAudioBufferSize(::NTV2_AUDIO_BUFFER_BIG,
|
||||
self->audio_system);
|
||||
|
@ -1058,7 +1093,6 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
guint video_buffer_size = ::GetVideoActiveSize(
|
||||
self->video_format, ::NTV2_FBF_10BIT_YCBCR, self->vanc_mode);
|
||||
|
@ -1100,6 +1134,17 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
gst_buffer_pool_set_active(self->anc_buffer_pool, TRUE);
|
||||
}
|
||||
|
||||
gst_element_post_message(GST_ELEMENT_CAST(self),
|
||||
gst_message_new_latency(GST_OBJECT_CAST(self)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
||||
GST_DEBUG_OBJECT(self, "Starting");
|
||||
|
||||
self->video_format = NTV2_FORMAT_UNKNOWN;
|
||||
|
||||
self->capture_thread = new AJAThread();
|
||||
self->capture_thread->Attach(capture_thread_func, self);
|
||||
self->capture_thread->SetPriority(AJA_ThreadPriority_High);
|
||||
|
@ -1111,9 +1156,6 @@ static gboolean gst_aja_src_start(GstAjaSrc *self) {
|
|||
g_cond_signal(&self->queue_cond);
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
|
||||
gst_element_post_message(GST_ELEMENT_CAST(self),
|
||||
gst_message_new_latency(GST_OBJECT_CAST(self)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1165,6 +1207,8 @@ static gboolean gst_aja_src_stop(GstAjaSrc *self) {
|
|||
gst_clear_object(&self->anc_buffer_pool);
|
||||
}
|
||||
|
||||
self->video_format = NTV2_FORMAT_UNKNOWN;
|
||||
|
||||
GST_DEBUG_OBJECT(self, "Stopped");
|
||||
|
||||
return TRUE;
|
||||
|
@ -1597,53 +1641,6 @@ restart:
|
|||
GST_DEBUG_OBJECT(self, "Starting capture");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
|
||||
// TODO: Wait for stable input signal
|
||||
|
||||
if (!self->device->device->EnableChannel(self->channel)) {
|
||||
GST_ELEMENT_ERROR(self, STREAM, FAILED, (NULL),
|
||||
("Failed to enable channel"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (!self->device->device->EnableChannel(
|
||||
(NTV2Channel)(self->channel + i))) {
|
||||
GST_ELEMENT_ERROR(self, STREAM, FAILED, (NULL),
|
||||
("Failed to enable channel"));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure to globally lock here as the routing settings and others are
|
||||
// global shared state
|
||||
ShmMutexLocker locker;
|
||||
|
||||
self->device->device->AutoCirculateStop(self->channel);
|
||||
if (self->quad_mode) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
self->device->device->AutoCirculateStop(
|
||||
(NTV2Channel)(self->channel + i));
|
||||
}
|
||||
}
|
||||
|
||||
self->device->device->EnableInputInterrupt(self->channel);
|
||||
self->device->device->SubscribeInputVerticalEvent(self->channel);
|
||||
if (!self->device->device->AutoCirculateInitForInput(
|
||||
self->channel, self->queue_size / 2, self->audio_system,
|
||||
AUTOCIRCULATE_WITH_RP188 |
|
||||
(self->vanc_mode == ::NTV2_VANCMODE_OFF ? AUTOCIRCULATE_WITH_ANC
|
||||
: 0),
|
||||
1)) {
|
||||
GST_ELEMENT_ERROR(self, STREAM, FAILED, (NULL),
|
||||
("Failed to initialize autocirculate"));
|
||||
goto out;
|
||||
}
|
||||
self->device->device->AutoCirculateStart(self->channel);
|
||||
}
|
||||
|
||||
gst_clear_object(&clock);
|
||||
clock = gst_element_get_clock(GST_ELEMENT_CAST(self));
|
||||
|
||||
|
@ -1652,6 +1649,51 @@ restart:
|
|||
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
while (self->playing && !self->shutdown) {
|
||||
// If we don't have a video format configured, configure the device now
|
||||
// and potentially auto-detect the video format
|
||||
if (self->video_format == NTV2_FORMAT_UNKNOWN) {
|
||||
// Make sure to globally lock here as the routing settings and others are
|
||||
// global shared state
|
||||
ShmMutexLocker locker;
|
||||
|
||||
// Don't keep queue locked while configuring as this might take a while
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
|
||||
if (!gst_aja_src_configure(self)) {
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
GST_ELEMENT_ERROR(self, STREAM, FAILED, (NULL),
|
||||
("Failed to configure device"));
|
||||
goto out;
|
||||
}
|
||||
g_mutex_lock(&self->queue_lock);
|
||||
|
||||
if (self->video_format == ::NTV2_FORMAT_UNKNOWN) {
|
||||
GST_DEBUG_OBJECT(self, "No signal, waiting");
|
||||
frames_dropped_last = G_MAXUINT64;
|
||||
if (have_signal) {
|
||||
GST_ELEMENT_WARNING(GST_ELEMENT(self), RESOURCE, READ,
|
||||
("Signal lost"),
|
||||
("No input source was detected"));
|
||||
have_signal = FALSE;
|
||||
}
|
||||
self->device->device->WaitForInputVerticalInterrupt(self->channel);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!self->device->device->AutoCirculateInitForInput(
|
||||
self->channel, self->queue_size / 2, self->audio_system,
|
||||
AUTOCIRCULATE_WITH_RP188 | (self->vanc_mode == ::NTV2_VANCMODE_OFF
|
||||
? AUTOCIRCULATE_WITH_ANC
|
||||
: 0),
|
||||
1)) {
|
||||
GST_ELEMENT_ERROR(self, STREAM, FAILED, (NULL),
|
||||
("Failed to initialize autocirculate"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->device->device->AutoCirculateStart(self->channel);
|
||||
}
|
||||
|
||||
// Check for valid signal first
|
||||
NTV2VideoFormat current_video_format =
|
||||
self->device->device->GetInputVideoFormat(
|
||||
|
@ -1673,6 +1715,9 @@ restart:
|
|||
}
|
||||
|
||||
if (current_video_format == ::NTV2_FORMAT_UNKNOWN) {
|
||||
if (self->video_format_setting == GST_AJA_VIDEO_FORMAT_AUTO)
|
||||
self->video_format = NTV2_FORMAT_UNKNOWN;
|
||||
|
||||
GST_DEBUG_OBJECT(self, "No signal, waiting");
|
||||
g_mutex_unlock(&self->queue_lock);
|
||||
frames_dropped_last = G_MAXUINT64;
|
||||
|
@ -1686,7 +1731,11 @@ restart:
|
|||
continue;
|
||||
} else if (current_video_format != effective_video_format &&
|
||||
current_video_format != self->video_format) {
|
||||
// TODO: Handle GST_AJA_VIDEO_FORMAT_AUTO here
|
||||
// Try reconfiguring with the newly detected video format
|
||||
if (self->video_format_setting == GST_AJA_VIDEO_FORMAT_AUTO) {
|
||||
self->video_format = NTV2_FORMAT_UNKNOWN;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string current_string =
|
||||
NTV2VideoFormatToString(current_video_format);
|
||||
|
@ -1766,8 +1815,8 @@ restart:
|
|||
AUTOCIRCULATE_TRANSFER transfer;
|
||||
|
||||
if (!have_signal) {
|
||||
GST_ELEMENT_INFO(GST_ELEMENT(self), RESOURCE, READ, ("Signal recovered"),
|
||||
("Input source detected"));
|
||||
GST_ELEMENT_INFO(GST_ELEMENT(self), RESOURCE, READ,
|
||||
("Signal recovered"), ("Input source detected"));
|
||||
have_signal = TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue