Macros used in gstreamer (e.g. G_DEFINE_TYPE) are functions. The end semicolons with the macros are unnecessary. Signed-off-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
199 lines
4.3 KiB
C++
199 lines
4.3 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2019, Collabora Ltd.
|
|
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
|
*
|
|
* gstlibcamerapad.cpp - GStreamer Capture Pad
|
|
*/
|
|
|
|
#include "gstlibcamerapad.h"
|
|
|
|
#include <libcamera/stream.h>
|
|
|
|
#include "gstlibcamera-utils.h"
|
|
|
|
using namespace libcamera;
|
|
|
|
struct _GstLibcameraPad {
|
|
GstPad parent;
|
|
StreamRole role;
|
|
GstLibcameraPool *pool;
|
|
GQueue pending_buffers;
|
|
GstClockTime latency;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_STREAM_ROLE
|
|
};
|
|
|
|
G_DEFINE_TYPE(GstLibcameraPad, gst_libcamera_pad, GST_TYPE_PAD)
|
|
|
|
static void
|
|
gst_libcamera_pad_set_property(GObject *object, guint prop_id,
|
|
const GValue *value, GParamSpec *pspec)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(object);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
|
|
switch (prop_id) {
|
|
case PROP_STREAM_ROLE:
|
|
self->role = (StreamRole)g_value_get_enum(value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_libcamera_pad_get_property(GObject *object, guint prop_id, GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(object);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
|
|
switch (prop_id) {
|
|
case PROP_STREAM_ROLE:
|
|
g_value_set_enum(value, self->role);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_libcamera_pad_query(GstPad *pad, GstObject *parent, GstQuery *query)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
|
|
if (query->type != GST_QUERY_LATENCY)
|
|
return gst_pad_query_default(pad, parent, query);
|
|
|
|
/* TRUE here means live, we assumes that max latency is the same as min
|
|
* as we have no idea that duration of frames. */
|
|
gst_query_set_latency(query, TRUE, self->latency, self->latency);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gst_libcamera_pad_init(GstLibcameraPad *self)
|
|
{
|
|
GST_PAD_QUERYFUNC(self) = gst_libcamera_pad_query;
|
|
}
|
|
|
|
static GType
|
|
gst_libcamera_stream_role_get_type()
|
|
{
|
|
static GType type = 0;
|
|
static const GEnumValue values[] = {
|
|
{ StillCapture, "libcamera::StillCapture", "still-capture" },
|
|
{ VideoRecording, "libcamera::VideoRecording", "video-recording" },
|
|
{ Viewfinder, "libcamera::Viewfinder", "view-finder" },
|
|
{ 0, NULL, NULL }
|
|
};
|
|
|
|
if (!type)
|
|
type = g_enum_register_static("GstLibcameraStreamRole", values);
|
|
|
|
return type;
|
|
}
|
|
|
|
static void
|
|
gst_libcamera_pad_class_init(GstLibcameraPadClass *klass)
|
|
{
|
|
auto *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->set_property = gst_libcamera_pad_set_property;
|
|
object_class->get_property = gst_libcamera_pad_get_property;
|
|
|
|
auto *spec = g_param_spec_enum("stream-role", "Stream Role",
|
|
"The selected stream role",
|
|
gst_libcamera_stream_role_get_type(),
|
|
VideoRecording,
|
|
(GParamFlags)(GST_PARAM_MUTABLE_READY
|
|
| G_PARAM_CONSTRUCT
|
|
| G_PARAM_READWRITE
|
|
| G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property(object_class, PROP_STREAM_ROLE, spec);
|
|
}
|
|
|
|
StreamRole
|
|
gst_libcamera_pad_get_role(GstPad *pad)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
return self->role;
|
|
}
|
|
|
|
GstLibcameraPool *
|
|
gst_libcamera_pad_get_pool(GstPad *pad)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
return self->pool;
|
|
}
|
|
|
|
void
|
|
gst_libcamera_pad_set_pool(GstPad *pad, GstLibcameraPool *pool)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
|
|
if (self->pool)
|
|
g_object_unref(self->pool);
|
|
self->pool = pool;
|
|
}
|
|
|
|
Stream *
|
|
gst_libcamera_pad_get_stream(GstPad *pad)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
|
|
if (self->pool)
|
|
return gst_libcamera_pool_get_stream(self->pool);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
gst_libcamera_pad_queue_buffer(GstPad *pad, GstBuffer *buffer)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
|
|
g_queue_push_head(&self->pending_buffers, buffer);
|
|
}
|
|
|
|
GstFlowReturn
|
|
gst_libcamera_pad_push_pending(GstPad *pad)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
GstBuffer *buffer;
|
|
|
|
{
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
buffer = GST_BUFFER(g_queue_pop_tail(&self->pending_buffers));
|
|
}
|
|
|
|
if (!buffer)
|
|
return GST_FLOW_OK;
|
|
|
|
return gst_pad_push(pad, buffer);
|
|
}
|
|
|
|
bool
|
|
gst_libcamera_pad_has_pending(GstPad *pad)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
return self->pending_buffers.length > 0;
|
|
}
|
|
|
|
void
|
|
gst_libcamera_pad_set_latency(GstPad *pad, GstClockTime latency)
|
|
{
|
|
auto *self = GST_LIBCAMERA_PAD(pad);
|
|
GLibLocker lock(GST_OBJECT(self));
|
|
self->latency = latency;
|
|
}
|