Skip to content

Commit 2515ef7

Browse files
committed
asyncweb: CaptureTask doc and logging
1 parent 908381e commit 2515ef7

File tree

2 files changed

+55
-20
lines changed

2 files changed

+55
-20
lines changed

src/esp32cam/asyncweb.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,30 @@
55
#include <freertos/FreeRTOS.h>
66
#include <freertos/idf_additions.h>
77

8+
#define CAPTURE_LOG(fmt, ...) ESP32CAM_LOG("CaptureTask(%p) " fmt, this, ##__VA_ARGS__)
89
#define STILL_LOG(fmt, ...) ESP32CAM_LOG("StillResponse(%p) " fmt, this, ##__VA_ARGS__)
910
#define MJPEG_LOG(fmt, ...) ESP32CAM_LOG("MjpegResponse(%p) " fmt, this, ##__VA_ARGS__)
1011

1112
namespace esp32cam {
1213
namespace detail {
1314

14-
CaptureTask::CaptureTask(uint32_t queueLength, uint32_t priority) {
15+
CaptureTask::CaptureTask(uint32_t queueLength, uint32_t priority, bool continuous)
16+
: m_continuous(continuous) {
1517
m_queue = xQueueCreate(queueLength, sizeof(Frame*));
1618
if (m_queue == nullptr) {
19+
CAPTURE_LOG("queue create fail");
1720
return;
1821
}
1922

2023
TaskHandle_t task = nullptr;
21-
if (xTaskCreatePinnedToCore(run, "esp32cam-capture", 2048, this, priority, &task,
22-
xPortGetCoreID()) == pdPASS) {
23-
m_task = task;
24-
};
24+
if (xTaskCreatePinnedToCore(run0, "esp32cam-capture", 2048, this, priority, &task,
25+
xPortGetCoreID()) != pdPASS) {
26+
CAPTURE_LOG("task create fail");
27+
return;
28+
}
29+
30+
m_task = task;
31+
CAPTURE_LOG("created");
2532
}
2633

2734
CaptureTask::~CaptureTask() {
@@ -33,20 +40,25 @@ CaptureTask::~CaptureTask() {
3340
if (m_queue != nullptr) {
3441
Frame* frame = nullptr;
3542
while (xQueueReceive(reinterpret_cast<QueueHandle_t>(m_queue), &frame, 0) == pdTRUE) {
36-
delete frame;
43+
if (frame != nullptr) {
44+
CAPTURE_LOG("dequeued and deleted frame=%p", frame->data());
45+
delete frame;
46+
}
3747
}
3848
vQueueDelete(reinterpret_cast<QueueHandle_t>(m_queue));
3949
m_queue = nullptr;
4050
}
51+
52+
CAPTURE_LOG("deleted");
4153
}
4254

4355
void
44-
CaptureTask::request(bool continuous) {
56+
CaptureTask::request() {
4557
if (m_task == nullptr || m_continuous) {
4658
return;
4759
}
48-
m_continuous = continuous;
49-
xTaskNotify(reinterpret_cast<TaskHandle_t>(m_task), 1, eSetValueWithOverwrite);
60+
auto res = xTaskNotify(reinterpret_cast<TaskHandle_t>(m_task), 1, eSetValueWithoutOverwrite);
61+
CAPTURE_LOG("requested res=%d", static_cast<int>(res));
5062
}
5163

5264
std::unique_ptr<Frame>
@@ -56,14 +68,21 @@ CaptureTask::retrieve() {
5668
xQueueReceive(reinterpret_cast<QueueHandle_t>(m_queue), &frame, 0) != pdTRUE) {
5769
return nullptr;
5870
}
71+
CAPTURE_LOG("dequeued frame=%p", frame->data());
5972
return std::unique_ptr<Frame>(frame);
6073
}
6174

6275
void
63-
CaptureTask::run(void* ctx) {
76+
CaptureTask::run0(void* ctx) {
6477
auto self = reinterpret_cast<CaptureTask*>(ctx);
78+
self->run();
79+
}
80+
81+
void
82+
CaptureTask::run() {
83+
auto queue = reinterpret_cast<QueueHandle_t>(m_queue);
6584
while (true) {
66-
if (!self->m_continuous) {
85+
if (!m_continuous) {
6786
uint32_t value = 0;
6887
xTaskNotifyWait(0, UINT32_MAX, &value, pdMS_TO_TICKS(10000));
6988
if (value == 0) {
@@ -72,10 +91,11 @@ CaptureTask::run(void* ctx) {
7291
}
7392

7493
auto frame = Camera.capture().release();
75-
while (xQueueSend(reinterpret_cast<QueueHandle_t>(self->m_queue), &frame,
76-
pdMS_TO_TICKS(10000)) != pdTRUE) {
77-
;
94+
CAPTURE_LOG("captured frame=%p", frame == nullptr ? nullptr : frame->data());
95+
while (xQueueSend(queue, &frame, pdMS_TO_TICKS(10000)) != pdTRUE) {
96+
CAPTURE_LOG("enqueue fail room=%d", static_cast<int>(uxQueueSpacesAvailable(queue)));
7897
}
98+
CAPTURE_LOG("enqueued frame=%p", frame == nullptr ? nullptr : frame->data());
7999
}
80100
}
81101

@@ -121,7 +141,7 @@ StillResponse::_fillBuffer(uint8_t* buf, size_t buflen) {
121141
}
122142

123143
MjpegResponse::MjpegResponse(const MjpegConfig& cfg)
124-
: m_task(2)
144+
: m_task(2, 1, cfg.minInterval < 0)
125145
, m_ctrl(cfg) {
126146
MJPEG_LOG("created");
127147
if (!m_task) {
@@ -176,7 +196,7 @@ MjpegResponse::_fillBuffer(uint8_t* buf, size_t buflen) {
176196
// fallthrough
177197
}
178198
case Ctrl::CAPTURE: {
179-
m_task.request(m_ctrl.cfg.minInterval < 0);
199+
m_task.request();
180200
m_ctrl.notifyCapture();
181201
return RESPONSE_TRY_AGAIN;
182202
}

src/esp32cam/asyncweb.hpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,42 @@
88
namespace esp32cam {
99
namespace detail {
1010

11+
/**
12+
* @brief FreeRTOS task for capturing image(s) from camera.
13+
*
14+
* If `continuous` is false, the task receives a request via FreeRTOS notification value.
15+
* Upon receiving the request, the task captures one image.
16+
* The image `Frame*` is sent to the main task via a FreeRTOS queue.
17+
*
18+
* If `continuous` is true, the task continuously captures images.
19+
* It would then wait until the image is accepted by the queue.
20+
*
21+
* The task is started in the same CPU core as calling code.
22+
* When the calling code is done with the `Frame*`, it can directly delete it.
23+
*/
1124
class CaptureTask {
1225
public:
13-
explicit CaptureTask(uint32_t queueLength, uint32_t priority = 1);
26+
explicit CaptureTask(uint32_t queueLength, uint32_t priority = 1, bool continuous = false);
1427

1528
~CaptureTask();
1629

1730
explicit operator bool() const {
1831
return m_queue != nullptr && m_task != nullptr;
1932
}
2033

21-
void request(bool continuous = false);
34+
void request();
2235

2336
std::unique_ptr<Frame> retrieve();
2437

2538
private:
26-
static void run(void* ctx);
39+
static void run0(void* ctx);
40+
41+
void run();
2742

2843
private:
2944
void* m_queue = nullptr;
3045
void* m_task = nullptr;
31-
bool m_continuous = false;
46+
bool m_continuous;
3247
};
3348

3449
} // namespace detail

0 commit comments

Comments
 (0)