mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 19:42:26 +00:00
decklink: improve frame handling
Send NEWSEGMENT on start. Send warning instead of error on dropped frames. Signed-off-by: David Schleef <ds@schleef.org>
This commit is contained in:
parent
a18180898f
commit
8f08c610ec
3 changed files with 39 additions and 16 deletions
|
@ -45,7 +45,7 @@ IDeckLink *deckLink;
|
||||||
IDeckLinkInput *deckLinkInput;
|
IDeckLinkInput *deckLinkInput;
|
||||||
IDeckLinkDisplayModeIterator *displayModeIterator;
|
IDeckLinkDisplayModeIterator *displayModeIterator;
|
||||||
|
|
||||||
static BMDTimecodeFormat g_timecodeFormat = 0;
|
static BMDTimecodeFormat g_timecodeFormat = (BMDTimecodeFormat)0;
|
||||||
|
|
||||||
DeckLinkCaptureDelegate::DeckLinkCaptureDelegate ():m_refCount (0)
|
DeckLinkCaptureDelegate::DeckLinkCaptureDelegate ():m_refCount (0)
|
||||||
{
|
{
|
||||||
|
@ -124,6 +124,10 @@ HRESULT
|
||||||
decklinksrc->audio_frame = audioFrame;
|
decklinksrc->audio_frame = audioFrame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* increment regardless whether frame was dropped or not */
|
||||||
|
decklinksrc->frame_num++;
|
||||||
|
|
||||||
g_cond_signal (decklinksrc->cond);
|
g_cond_signal (decklinksrc->cond);
|
||||||
g_mutex_unlock (decklinksrc->mutex);
|
g_mutex_unlock (decklinksrc->mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,6 +277,10 @@ gst_decklink_src_init (GstDecklinkSrc * decklinksrc,
|
||||||
decklinksrc->connection = GST_DECKLINK_CONNECTION_SDI;
|
decklinksrc->connection = GST_DECKLINK_CONNECTION_SDI;
|
||||||
decklinksrc->audio_connection = GST_DECKLINK_AUDIO_CONNECTION_AUTO;
|
decklinksrc->audio_connection = GST_DECKLINK_AUDIO_CONNECTION_AUTO;
|
||||||
|
|
||||||
|
decklinksrc->stop = FALSE;
|
||||||
|
decklinksrc->dropped_frames = 0;
|
||||||
|
decklinksrc->dropped_frames_old = 0;
|
||||||
|
decklinksrc->frame_num = -1; /* -1 so will be 0 after incrementing */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -389,7 +393,7 @@ gst_decklink_src_start (GstElement * element)
|
||||||
DeckLinkCaptureDelegate *delegate;
|
DeckLinkCaptureDelegate *delegate;
|
||||||
//IDeckLinkDisplayModeIterator *mode_iterator;
|
//IDeckLinkDisplayModeIterator *mode_iterator;
|
||||||
//IDeckLinkDisplayMode *mode;
|
//IDeckLinkDisplayMode *mode;
|
||||||
int sample_depth;
|
BMDAudioSampleType sample_depth;
|
||||||
int channels;
|
int channels;
|
||||||
HRESULT ret;
|
HRESULT ret;
|
||||||
const GstDecklinkMode *mode;
|
const GstDecklinkMode *mode;
|
||||||
|
@ -520,7 +524,7 @@ gst_decklink_src_start (GstElement * element)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample_depth = 16;
|
sample_depth = bmdAudioSampleType16bitInteger;
|
||||||
channels = 2;
|
channels = 2;
|
||||||
ret = decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz,
|
ret = decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz,
|
||||||
sample_depth, channels);
|
sample_depth, channels);
|
||||||
|
@ -1056,7 +1060,6 @@ gst_decklink_src_task (void *priv)
|
||||||
GstBuffer *audio_buffer;
|
GstBuffer *audio_buffer;
|
||||||
IDeckLinkVideoInputFrame *video_frame;
|
IDeckLinkVideoInputFrame *video_frame;
|
||||||
IDeckLinkAudioInputPacket *audio_frame;
|
IDeckLinkAudioInputPacket *audio_frame;
|
||||||
int dropped_frames;
|
|
||||||
void *data;
|
void *data;
|
||||||
int n_samples;
|
int n_samples;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
@ -1070,7 +1073,6 @@ gst_decklink_src_task (void *priv)
|
||||||
}
|
}
|
||||||
video_frame = decklinksrc->video_frame;
|
video_frame = decklinksrc->video_frame;
|
||||||
audio_frame = decklinksrc->audio_frame;
|
audio_frame = decklinksrc->audio_frame;
|
||||||
dropped_frames = decklinksrc->dropped_frames;
|
|
||||||
decklinksrc->video_frame = NULL;
|
decklinksrc->video_frame = NULL;
|
||||||
decklinksrc->audio_frame = NULL;
|
decklinksrc->audio_frame = NULL;
|
||||||
g_mutex_unlock (decklinksrc->mutex);
|
g_mutex_unlock (decklinksrc->mutex);
|
||||||
|
@ -1080,10 +1082,14 @@ gst_decklink_src_task (void *priv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dropped_frames > 0) {
|
/* warning on dropped frames */
|
||||||
GST_ELEMENT_ERROR (decklinksrc, RESOURCE, READ, (NULL), (NULL));
|
if (decklinksrc->dropped_frames - decklinksrc->dropped_frames_old > 0) {
|
||||||
/* ERROR */
|
GST_ELEMENT_WARNING (decklinksrc, RESOURCE, READ,
|
||||||
return;
|
("Dropped %d frame(s), for a total of %d frame(s)",
|
||||||
|
decklinksrc->dropped_frames - decklinksrc->dropped_frames_old,
|
||||||
|
decklinksrc->dropped_frames),
|
||||||
|
(NULL));
|
||||||
|
decklinksrc->dropped_frames_old = decklinksrc->dropped_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = gst_decklink_get_mode (decklinksrc->mode);
|
mode = gst_decklink_get_mode (decklinksrc->mode);
|
||||||
|
@ -1106,16 +1112,28 @@ gst_decklink_src_task (void *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buffer) =
|
GST_BUFFER_TIMESTAMP (buffer) =
|
||||||
gst_util_uint64_scale_int (decklinksrc->num_frames * GST_SECOND,
|
gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
|
||||||
mode->fps_d, mode->fps_n);
|
mode->fps_d, mode->fps_n);
|
||||||
GST_BUFFER_DURATION (buffer) =
|
GST_BUFFER_DURATION (buffer) =
|
||||||
gst_util_uint64_scale_int ((decklinksrc->num_frames + 1) * GST_SECOND,
|
gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
|
||||||
mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
|
mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
|
||||||
GST_BUFFER_OFFSET (buffer) = decklinksrc->num_frames;
|
GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
|
||||||
if (decklinksrc->num_frames == 0) {
|
GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num;
|
||||||
|
if (decklinksrc->frame_num == 0) {
|
||||||
|
GstEvent *event;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
|
||||||
|
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
|
||||||
|
GST_CLOCK_TIME_NONE, 0);
|
||||||
|
|
||||||
|
ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
|
||||||
|
if (!ret) {
|
||||||
|
GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
decklinksrc->num_frames++;
|
|
||||||
|
|
||||||
if (decklinksrc->video_caps == NULL) {
|
if (decklinksrc->video_caps == NULL) {
|
||||||
decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
|
decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
|
||||||
|
@ -1144,7 +1162,7 @@ gst_decklink_src_task (void *priv)
|
||||||
|
|
||||||
if (decklinksrc->audio_caps == NULL) {
|
if (decklinksrc->audio_caps == NULL) {
|
||||||
decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
|
decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||||
"endianness", G_TYPE_INT, LITTLE_ENDIAN,
|
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
|
||||||
"signed", G_TYPE_BOOLEAN, TRUE,
|
"signed", G_TYPE_BOOLEAN, TRUE,
|
||||||
"depth", G_TYPE_INT, 16,
|
"depth", G_TYPE_INT, 16,
|
||||||
"width", G_TYPE_INT, 16,
|
"width", G_TYPE_INT, 16,
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct _GstDecklinkSrc
|
||||||
GMutex *mutex;
|
GMutex *mutex;
|
||||||
GCond *cond;
|
GCond *cond;
|
||||||
int dropped_frames;
|
int dropped_frames;
|
||||||
|
int dropped_frames_old;
|
||||||
gboolean stop;
|
gboolean stop;
|
||||||
IDeckLinkVideoInputFrame *video_frame;
|
IDeckLinkVideoInputFrame *video_frame;
|
||||||
IDeckLinkAudioInputPacket * audio_frame;
|
IDeckLinkAudioInputPacket * audio_frame;
|
||||||
|
@ -60,7 +61,7 @@ struct _GstDecklinkSrc
|
||||||
guint64 num_audio_samples;
|
guint64 num_audio_samples;
|
||||||
|
|
||||||
GstCaps *video_caps;
|
GstCaps *video_caps;
|
||||||
guint64 num_frames;
|
guint64 frame_num;
|
||||||
int fps_n;
|
int fps_n;
|
||||||
int fps_d;
|
int fps_d;
|
||||||
int width;
|
int width;
|
||||||
|
|
Loading…
Reference in a new issue