summaryrefslogtreecommitdiff
path: root/src/libcamera/request.cpp
blob: d76db24de0e279e592faf275deae6d48528d9cc2 (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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * request.cpp - Capture request handling
 */

#include <map>

#include <libcamera/buffer.h>
#include <libcamera/camera.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>

#include "log.h"

/**
 * \file request.h
 * \brief Describes a frame capture request to be processed by a camera
 */

namespace libcamera {

LOG_DEFINE_CATEGORY(Request)

/**
 * \class Request
 * \brief A frame capture request
 *
 * A Request allows an application to associate buffers and controls on a
 * per-frame basis to be queued to the camera device for processing.
 */

/**
 * \brief Create a capture request for a camera
 * \param[in] camera The camera that creates the request
 */
Request::Request(Camera *camera)
	: camera_(camera)
{
}

/**
 * \brief Set the streams to capture with associated buffers
 * \param[in] streamMap The map of streams to buffers
 * \return 0 on success or a negative error code otherwise
 * \retval -EBUSY Buffers have already been set
 */
int Request::setBuffers(const std::map<Stream *, Buffer *> &streamMap)
{
	if (!bufferMap_.empty()) {
		LOG(Request, Error) << "Buffers already set";
		return -EBUSY;
	}

	bufferMap_ = streamMap;
	return 0;
}

/**
 * \var Request::bufferMap_
 * \brief Mapping of streams to buffers for this request
 *
 * The bufferMap_ tracks the buffers associated with each stream. If a stream is
 * not utilised in this request there will be no buffer for that stream in the
 * map.
 */

/**
 * \brief Return the buffer associated with a stream
 * \param[in] stream The stream the buffer is associated to
 *
 * \return The buffer associated with the stream, or nullptr if the stream is
 * not part of this request
 */
Buffer *Request::findBuffer(Stream *stream) const
{
	auto it = bufferMap_.find(stream);
	if (it == bufferMap_.end())
		return nullptr;

	return it->second;
}

/**
 * \brief Prepare the resources for the completion handler
 */
int Request::prepare()
{
	for (auto const &pair : bufferMap_) {
		Buffer *buffer = pair.second;
		buffer->completed.connect(this, &Request::bufferCompleted);
		pending_.insert(buffer);
	}

	return 0;
}

/**
 * \brief Slot for the buffer completed signal
 *
 * The bufferCompleted method serves as slot where to connect the
 * Buffer::completed signal that is emitted when a buffer has available
 * data.
 *
 * The request completes when all the buffers it contains are ready to be
 * presented to the application. It then emits the Camera::requestCompleted
 * signal and is automatically deleted.
 */
void Request::bufferCompleted(Buffer *buffer)
{
	buffer->completed.disconnect(this, &Request::bufferCompleted);

	int ret = pending_.erase(buffer);
	ASSERT(ret == 1);

	if (!pending_.empty())
		return;

	std::map<Stream *, Buffer *> buffers(std::move(bufferMap_));
	camera_->requestCompleted.emit(this, buffers);
	delete this;
}

} /* namespace libcamera */