libcamera  v0.4.0
Supporting cameras in Linux since 2019
fc_queue.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2022, Google Inc.
4  *
5  * IPA Frame context queue
6  */
7 
8 #pragma once
9 
10 #include <stdint.h>
11 #include <vector>
12 
13 #include <libcamera/base/log.h>
14 
15 namespace libcamera {
16 
17 LOG_DECLARE_CATEGORY(FCQueue)
18 
19 namespace ipa {
20 
21 template<typename FrameContext>
22 class FCQueue;
23 
24 struct FrameContext {
25 private:
26  template<typename T> friend class FCQueue;
27  uint32_t frame;
28  bool initialised = false;
29 };
30 
31 template<typename FrameContext>
32 class FCQueue
33 {
34 public:
35  FCQueue(unsigned int size)
36  : contexts_(size)
37  {
38  }
39 
40  void clear()
41  {
42  for (FrameContext &ctx : contexts_) {
43  ctx.initialised = false;
44  ctx.frame = 0;
45  }
46  }
47 
48  FrameContext &alloc(const uint32_t frame)
49  {
50  FrameContext &frameContext = contexts_[frame % contexts_.size()];
51 
52  /*
53  * Do not re-initialise if a get() call has already fetched this
54  * frame context to preseve the context.
55  *
56  * \todo If the the sequence number of the context to initialise
57  * is smaller than the sequence number of the queue slot to use,
58  * it means that we had a serious request underrun and more
59  * frames than the queue size has been produced since the last
60  * time the application has queued a request. Does this deserve
61  * an error condition ?
62  */
63  if (frame != 0 && frame <= frameContext.frame)
64  LOG(FCQueue, Warning)
65  << "Frame " << frame << " already initialised";
66  else
67  init(frameContext, frame);
68 
69  return frameContext;
70  }
71 
72  FrameContext &get(uint32_t frame)
73  {
74  FrameContext &frameContext = contexts_[frame % contexts_.size()];
75 
76  /*
77  * If the IPA algorithms try to access a frame context slot which
78  * has been already overwritten by a newer context, it means the
79  * frame context queue has overflowed and the desired context
80  * has been forever lost. The pipeline handler shall avoid
81  * queueing more requests to the IPA than the frame context
82  * queue size.
83  */
84  if (frame < frameContext.frame)
85  LOG(FCQueue, Fatal) << "Frame context for " << frame
86  << " has been overwritten by "
87  << frameContext.frame;
88 
89  if (frame == 0 && !frameContext.initialised) {
90  /*
91  * If the IPA calls get() at start() time it will get an
92  * un-intialized FrameContext as the below "frame ==
93  * frameContext.frame" check will return success because
94  * FrameContexts are zeroed at creation time.
95  *
96  * Make sure the FrameContext gets initialised if get()
97  * is called before alloc() by the IPA for frame#0.
98  */
99  init(frameContext, frame);
100 
101  return frameContext;
102  }
103 
104  if (frame == frameContext.frame)
105  return frameContext;
106 
107  /*
108  * The frame context has been retrieved before it was
109  * initialised through the initialise() call. This indicates an
110  * algorithm attempted to access a Frame context before it was
111  * queued to the IPA. Controls applied for this request may be
112  * left unhandled.
113  *
114  * \todo Set an error flag for per-frame control errors.
115  */
116  LOG(FCQueue, Warning)
117  << "Obtained an uninitialised FrameContext for " << frame;
118 
119  init(frameContext, frame);
120 
121  return frameContext;
122  }
123 
124 private:
125  void init(FrameContext &frameContext, const uint32_t frame)
126  {
127  frameContext = {};
128  frameContext.frame = frame;
129  frameContext.initialised = true;
130  }
131 
132  std::vector<FrameContext> contexts_;
133 };
134 
135 } /* namespace ipa */
136 
137 } /* namespace libcamera */
#define LOG(category, severity)
Log a message.
Top-level libcamera namespace.
Definition: backtrace.h:17
void clear()
Clear the contexts queue.
Definition: fc_queue.h:40
A support class for managing FrameContext instances in IPA modules.
Definition: fc_queue.h:22
FCQueue(unsigned int size)
Construct a frame contexts queue of a specified size.
Definition: fc_queue.h:35
FrameContext & alloc(const uint32_t frame)
Allocate and return a FrameContext for the frame.
Definition: fc_queue.h:48
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
Context for a frame.
Definition: fc_queue.h:24
Logging infrastructure.