static GstFlowReturn
gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
- GstV4l2MemoryGroup * group)
+ GstV4l2MemoryGroup * group, guint32 * frame_number)
{
const GstV4l2Object *obj = pool->obj;
- GstClockTime timestamp;
gint index;
index = group->buffer.index;
group->buffer.field = field;
}
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- timestamp = GST_BUFFER_TIMESTAMP (buf);
- GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
+ if (frame_number) {
+ group->buffer.timestamp.tv_sec = *frame_number;
+ group->buffer.timestamp.tv_usec = 0;
+ } else {
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buf);
+ GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
+ } else {
+ group->buffer.timestamp.tv_sec = -1;
+ group->buffer.timestamp.tv_usec = -1;
+ }
}
GST_OBJECT_LOCK (pool);
if (pool->other_pool)
ret = gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
if (ret != GST_FLOW_OK ||
- gst_v4l2_buffer_pool_qbuf (pool, buffer, group) != GST_FLOW_OK)
+ gst_v4l2_buffer_pool_qbuf (pool, buffer, group,
+ NULL) != GST_FLOW_OK)
pclass->release_buffer (bpool, buffer);
} else {
/* Simply release invalid/modified buffer, the allocator will
* gst_v4l2_buffer_pool_process:
* @bpool: a #GstBufferPool
* @buf: a #GstBuffer, maybe be replaced
+ * @frame_number: 32 bit frame number or %NULL
*
* Process @buf in @bpool. For capture devices, this functions fills @buf with
* data from the device. For output devices, this functions send the contents of
* @buf to the device for playback.
*
+ * If non-%NULL and an output device, @frame_number is stored inside the timestamp for output devices and read
+ * back from the timestamp for capture devices.
+ *
* Returns: %GST_FLOW_OK on success.
*/
GstFlowReturn
-gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
+gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf,
+ guint32 * frame_number)
{
GstFlowReturn ret = GST_FLOW_OK;
GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
gst_v4l2_is_buffer_valid (to_queue, &group);
}
- if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue, group))
+ if ((ret =
+ gst_v4l2_buffer_pool_qbuf (pool, to_queue, group,
+ frame_number))
!= GST_FLOW_OK)
goto queue_failed;
GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj, GstCaps *caps);
-GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer ** buf);
+GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer ** buf, guint32 * frame_number);
void gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
GstBufferPool * other_pool);
gst_buffer_ref (buf);
again:
ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool),
- &buf);
+ &buf, NULL);
if (ret == GST_FLOW_FLUSHING) {
ret = gst_base_sink_wait_preroll (GST_BASE_SINK (vsink));
if (ret == GST_FLOW_OK)
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto alloc_failed;
- ret = gst_v4l2_buffer_pool_process (pool, buf);
+ ret = gst_v4l2_buffer_pool_process (pool, buf, NULL);
} while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER);
}
GST_DEBUG_OBJECT (self, "Queue input buffer");
- ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), &inbuf);
+ ret =
+ gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), &inbuf, NULL);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto beach;
goto alloc_failed;
pool = self->v4l2capture->pool;
- ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), outbuf);
+ ret =
+ gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), outbuf,
+ NULL);
} while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER);
buffer = gst_buffer_new ();
ret =
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
- v4l2output->pool), &buffer);
+ v4l2output->pool), &buffer, NULL);
gst_buffer_unref (buffer);
}
}
return GST_FLOW_OK;
}
-static GstVideoCodecFrame *
-gst_v4l2_video_dec_get_oldest_frame (GstVideoDecoder * decoder)
-{
- GstVideoCodecFrame *frame = NULL;
- GList *frames, *l;
- gint count = 0;
-
- frames = gst_video_decoder_get_frames (decoder);
-
- for (l = frames; l != NULL; l = l->next) {
- GstVideoCodecFrame *f = l->data;
-
- if (!frame || frame->pts > f->pts)
- frame = f;
-
- count++;
- }
-
- if (frame) {
- GST_LOG_OBJECT (decoder,
- "Oldest frame is %d %" GST_TIME_FORMAT " and %d frames left",
- frame->system_frame_number, GST_TIME_ARGS (frame->pts), count - 1);
- gst_video_codec_frame_ref (frame);
- }
-
- g_list_free_full (frames, (GDestroyNotify) gst_video_codec_frame_unref);
-
- return frame;
-}
-
static void
gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
{
goto beach;
GST_LOG_OBJECT (decoder, "Process output buffer");
- ret = gst_v4l2_buffer_pool_process (v4l2_pool, &buffer);
-
+ ret = gst_v4l2_buffer_pool_process (v4l2_pool, &buffer, NULL);
} while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER);
if (ret != GST_FLOW_OK)
goto beach;
- frame = gst_v4l2_video_dec_get_oldest_frame (decoder);
+ if (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND != 0)
+ GST_ERROR_OBJECT (decoder,
+ "Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git");
+ GST_LOG_OBJECT (decoder, "Got buffer for frame number %u",
+ (guint32) (GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND));
+ /* FIXME: Add garbage collection for the frames */
+ frame =
+ gst_video_decoder_get_frame (decoder,
+ GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND);
if (frame) {
frame->output_buffer = buffer;
buffer = NULL;
GstBuffer *codec_data;
GstCaps *acquired_caps, *available_caps, *caps, *filter;
GstStructure *st;
+ guint32 dummy_frame_number = 0;
GST_DEBUG_OBJECT (self, "Sending header");
}
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
+ processed ? frame->system_frame_number : 0);
ret =
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
- v4l2output->pool), &codec_data);
+ v4l2output->pool), &codec_data,
+ processed ? &frame->system_frame_number : &dummy_frame_number);
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
gst_buffer_unref (codec_data);
if (!processed) {
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
+ frame->system_frame_number);
ret =
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
- pool), &frame->input_buffer);
+ pool), &frame->input_buffer, &frame->system_frame_number);
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
if (ret == GST_FLOW_FLUSHING) {
return FALSE;
}
-static GstVideoCodecFrame *
-gst_v4l2_video_enc_get_oldest_frame (GstVideoEncoder * encoder)
-{
- GstVideoCodecFrame *frame = NULL;
- GList *frames, *l;
- gint count = 0;
-
- frames = gst_video_encoder_get_frames (encoder);
-
- for (l = frames; l != NULL; l = l->next) {
- GstVideoCodecFrame *f = l->data;
-
- if (!frame || frame->pts > f->pts)
- frame = f;
-
- count++;
- }
-
- if (frame) {
- GST_LOG_OBJECT (encoder,
- "Oldest frame is %d %" GST_TIME_FORMAT
- " and %d frames left",
- frame->system_frame_number, GST_TIME_ARGS (frame->pts), count - 1);
- gst_video_codec_frame_ref (frame);
- }
-
- g_list_free_full (frames, (GDestroyNotify) gst_video_codec_frame_unref);
-
- return frame;
-}
-
static void
gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
{
goto beach;
}
-
/* FIXME Check if buffer isn't the last one here */
GST_LOG_OBJECT (encoder, "Process output buffer");
ret =
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL
- (self->v4l2capture->pool), &buffer);
+ (self->v4l2capture->pool), &buffer, NULL);
if (ret != GST_FLOW_OK)
goto beach;
- frame = gst_v4l2_video_enc_get_oldest_frame (encoder);
+ if (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND != 0)
+ GST_ERROR_OBJECT (encoder,
+ "Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git");
+ GST_LOG_OBJECT (encoder, "Got buffer for frame number %u",
+ (guint32) (GST_BUFFER_PTS (buffer) / GST_SECOND));
+ frame =
+ gst_video_encoder_get_frame (encoder,
+ GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND);
if (frame) {
/* At this point, the delta unit buffer flag is already correctly set by
if (frame->input_buffer) {
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
+ GST_LOG_OBJECT (encoder, "Passing buffer with frame number %u",
+ frame->system_frame_number);
ret =
- gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL
- (self->v4l2output->pool), &frame->input_buffer);
+ gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
+ v4l2output->pool), &frame->input_buffer,
+ &frame->system_frame_number);
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
if (ret == GST_FLOW_FLUSHING) {