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:
Joshua M. Doe 2011-07-07 14:34:01 -04:00 committed by David Schleef
parent a18180898f
commit 8f08c610ec
3 changed files with 39 additions and 16 deletions

View file

@ -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);
} }

View file

@ -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,

View file

@ -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;