summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline/ipu3/frames.cpp
blob: a4c3477cd9ef623cf9429e827d551187b35c82af (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2020, Google Inc.
 *
 * frames.cpp - Intel IPU3 Frames helper
 */

#include "frames.h"

#include <libcamera/framebuffer.h>
#include <libcamera/request.h>

#include "libcamera/internal/framebuffer.h"
#include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/v4l2_videodevice.h"

namespace libcamera {

LOG_DECLARE_CATEGORY(IPU3)

IPU3Frames::IPU3Frames()
{
}

void IPU3Frames::init(const std::vector<std::unique_ptr<FrameBuffer>> &paramBuffers,
		      const std::vector<std::unique_ptr<FrameBuffer>> &statBuffers)
{
	for (const std::unique_ptr<FrameBuffer> &buffer : paramBuffers)
		availableParamBuffers_.push(buffer.get());

	for (const std::unique_ptr<FrameBuffer> &buffer : statBuffers)
		availableStatBuffers_.push(buffer.get());

	frameInfo_.clear();
}

void IPU3Frames::clear()
{
	availableParamBuffers_ = {};
	availableStatBuffers_ = {};
}

IPU3Frames::Info *IPU3Frames::create(Request *request)
{
	unsigned int id = request->sequence();

	if (availableParamBuffers_.empty()) {
		LOG(IPU3, Debug) << "Parameters buffer underrun";
		return nullptr;
	}

	if (availableStatBuffers_.empty()) {
		LOG(IPU3, Debug) << "Statistics buffer underrun";
		return nullptr;
	}

	FrameBuffer *paramBuffer = availableParamBuffers_.front();
	FrameBuffer *statBuffer = availableStatBuffers_.front();

	paramBuffer->_d()->setRequest(request);
	statBuffer->_d()->setRequest(request);

	availableParamBuffers_.pop();
	availableStatBuffers_.pop();

	/* \todo Remove the dynamic allocation of Info */
	std::unique_ptr<Info> info = std::make_unique<Info>();

	info->id = id;
	info->request = request;
	info->rawBuffer = nullptr;
	info->paramBuffer = paramBuffer;
	info->statBuffer = statBuffer;
	info->paramDequeued = false;
	info->metadataProcessed = false;

	frameInfo_[id] = std::move(info);

	return frameInfo_[id].get();
}

void IPU3Frames::remove(IPU3Frames::Info *info)
{
	/* Return params and stat buffer for reuse. */
	availableParamBuffers_.push(info->paramBuffer);
	availableStatBuffers_.push(info->statBuffer);

	/* Delete the extended frame information. */
	frameInfo_.erase(info->id);
}

bool IPU3Frames::tryComplete(IPU3Frames::Info *info)
{
	Request *request = info->request;

	if (request->hasPendingBuffers())
		return false;

	if (!info->metadataProcessed)
		return false;

	if (!info->paramDequeued)
		return false;

	remove(info);

	bufferAvailable.emit();

	return true;
}

IPU3Frames::Info *IPU3Frames::find(unsigned int id)
{
	const auto &itInfo = frameInfo_.find(id);

	if (itInfo != frameInfo_.end())
		return itInfo->second.get();

	LOG(IPU3, Fatal) << "Can't find tracking information for frame " << id;

	return nullptr;
}

IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer)
{
	for (auto const &itInfo : frameInfo_) {
		Info *info = itInfo.second.get();

		for (auto const itBuffers : info->request->buffers())
			if (itBuffers.second == buffer)
				return info;

		if (info->rawBuffer == buffer || info->paramBuffer == buffer ||
		    info->statBuffer == buffer)
			return info;
	}

	LOG(IPU3, Fatal) << "Can't find tracking information from buffer";

	return nullptr;
}

} /* namespace libcamera */