summaryrefslogtreecommitdiff
path: root/src/android/camera_hal_manager.h
blob: 94d8f005444d16b42ebba28c8fb812c97d8931b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * camera_hal_manager.h - libcamera Android Camera Manager
 */
#ifndef __ANDROID_CAMERA_MANAGER_H__
#define __ANDROID_CAMERA_MANAGER_H__

#include <stddef.h>
#include <vector>

#include <hardware/hardware.h>
#include <system/camera_metadata.h>

#include <libcamera/camera_manager.h>

class CameraDevice;

class CameraHalManager
{
public:
	CameraHalManager();
	~CameraHalManager();

	int init();

	CameraDevice *open(unsigned int id, const hw_module_t *module);

	unsigned int numCameras() const;
	int getCameraInfo(unsigned int id, struct camera_info *info);

private:
	camera_metadata_t *getStaticMetadata(unsigned int id);

	libcamera::CameraManager *cameraManager_;

	std::vector<std::unique_ptr<CameraDevice>> cameras_;
};

#endif /* __ANDROID_CAMERA_MANAGER_H__ */
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
/* 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;
}