Work in progress

This commit is contained in:
Rene Zeldenthuis
2024-02-17 10:12:23 +01:00
parent 152c068f68
commit 6119020e7d
4 changed files with 124 additions and 71 deletions

View File

@@ -2,17 +2,34 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <tuple>
class micro_rtsp_jpeg class micro_rtsp_jpeg
{ {
public: public:
micro_rtsp_jpeg(const uint8_t *jpeg, size_t size); bool decode_jpeg(const uint8_t *jpg, size_t size);
std::tuple<const uint8_t *, size_t> quantization_table_0_; class __attribute__ ((packed)) jpg_section
std::tuple<const uint8_t *, size_t> quantization_table_1_; {
std::tuple<const uint8_t *, size_t> jpeg_data_; public:
protected: uint8_t flag() const { return section_flag; }
bool decode_jpeg(uint8_t *jpg, size_t size); const char *flag_name() const;
std::tuple<const uint8_t *, size_t> find_jpeg_section(uint8_t **ptr, uint8_t *end, uint8_t flag); uint16_t section_length() const { return section_flag == 0xd8 || section_flag == 0xd9 ? 0 : (section_length_msb << 8) + section_length_lsb; }
const uint8_t *data() const { return reinterpret_cast<const uint8_t *>(&section_data[1]); }
uint16_t data_length() const { return section_length() - 3; }
private:
const uint8_t section_flag;
const uint8_t section_length_msb;
const uint8_t section_length_lsb;
const uint8_t section_data[];
};
const jpg_section *quantization_table_0_;
const jpg_section *quantization_table_1_;
const uint8_t *jpeg_data_start;
const uint8_t *jpeg_data_end;
private:
static const jpg_section *find_jpeg_section(const uint8_t **ptr, const uint8_t *end, uint8_t flag);
}; };

View File

@@ -2,100 +2,100 @@
#include "micro_rtsp_jpeg.h" #include "micro_rtsp_jpeg.h"
micro_rtsp_jpeg::micro_rtsp_jpeg(const uint8_t *jpeg, size_t size) const char *micro_rtsp_jpeg::jpg_section::flag_name() const
{ {
switch (section_flag)
{
case 0xd8:
return "SOI"; // start of image
case 0xd9:
return "EOI"; // end of image
case 0xe0:
return "APP0";
case 0xdb:
return "DQT"; // define quantization table
case 0xc4:
return "DHT"; // define Huffman table
case 0xc0:
return "SOF"; // start of frame
case 0xda:
return "SOS"; // start of scan
}
return "Unknown";
} }
std::tuple<const uint8_t *, size_t> micro_rtsp_jpeg::find_jpeg_section(uint8_t **ptr, uint8_t *end, uint8_t flag) const micro_rtsp_jpeg::jpg_section *micro_rtsp_jpeg::find_jpeg_section(const uint8_t **ptr, const uint8_t *end, uint8_t flag)
{ {
size_t len; log_d("find_jpeg_section 0x%02x", flag);
while (*ptr < end) while (*ptr < end)
{ {
auto framing = *(*ptr++); auto framing = *((*ptr)++);
if (framing != 0xff) if (framing != 0xff)
{ {
log_e("Malformed jpeg. Expected framing 0xff but found: 0x%02x", framing); log_e("Expected framing 0xff but found: 0x%02x", framing);
break; break;
} }
// framing = 0xff, flag, len MSB, len LSB // framing = 0xff, flag, len MSB, len LSB
auto flag_code = *(*ptr++); auto section = reinterpret_cast<const jpg_section *>((*ptr)++);
// Length of section // Advance pointer section has a length, so not SOI (0xd8) and EOI (0xd9)
len = *(*ptr++) * 256 + *(*ptr++); *ptr += section->section_length();
if (flag_code == flag) if (section->flag() == flag)
return std::tuple<const uint8_t *, size_t>(*ptr, len); {
log_d("Found section 0x%02x (%s), %d bytes", flag, section->flag_name(), section->section_length());
return section;
}
// Skip the section log_d("Skipping section: 0x%02x (%s), %d bytes", section->flag(), section->flag_name(), section->section_length());
switch (flag_code)
{
case 0xe0: // APP00
case 0xdb: // DQT (define quantization table)
case 0xc4: // DHT (define Huffman table)
case 0xc0: // SOF0 (start of frame)
case 0xda: // SOS (start of scan)
{
log_d("Skipping jpeg section flag: 0x%02x, %d bytes", flag_code, len);
ptr += len;
break;
}
default:
log_e("Unexpected jpeg flag: 0x%02x", flag_code);
}
} }
// Not found // Not found
return std::tuple<const uint8_t *, size_t>(nullptr, 0); return nullptr;
} }
// See https://create.stephan-brumme.com/toojpeg/ // See https://create.stephan-brumme.com/toojpeg/
bool micro_rtsp_jpeg::decode_jpeg(uint8_t *data, size_t size) bool micro_rtsp_jpeg::decode_jpeg(const uint8_t *data, size_t size)
{ {
log_d("decode_jpeg");
// Look for start jpeg file (0xd8) // Look for start jpeg file (0xd8)
auto ptr = data; auto ptr = data;
auto end = ptr + size; auto end = ptr + size;
// Check for SOI (start of image) 0xff, 0xd8 // Check for SOI (start of image) 0xff, 0xd8
if (*(ptr++) != 0xff || *(ptr++) != 0xd8) if (!find_jpeg_section(&ptr, end, 0xd8))
{ {
log_e("No valid start of image marker found"); log_e("No valid start of image marker found");
return false; return false;
} }
// First quantization table // First quantization table
quantization_table_0_ = find_jpeg_section(&ptr, end, 0xdb); if (!(quantization_table_0_ = find_jpeg_section(&ptr, end, 0xdb)))
if (std::get<0>(quantization_table_0_) == nullptr)
{
log_e("No quantization table 0 section found"); log_e("No quantization table 0 section found");
}
// Second quantization table (for color images) // Second quantization table (for color images)
quantization_table_1_ = find_jpeg_section(&ptr, end, 0xdb); if (!(quantization_table_1_ = find_jpeg_section(&ptr, end, 0xdb)))
if (std::get<0>(quantization_table_1_) == nullptr)
{
log_w("No quantization table 1 section found"); log_w("No quantization table 1 section found");
}
// Start of scan // Start of scan
auto sos = find_jpeg_section(&ptr, end, 0xda); if (!find_jpeg_section(&ptr, end, 0xda))
if (std::get<0>(sos) == nullptr)
{
log_e("No start of scan section found"); log_e("No start of scan section found");
}
// Start of the data sections // Start of the data sections
auto start = ptr; jpeg_data_start = ptr;
// Scan over all the sections. 0xff followed by not zero, is a new section // Scan over all the sections. 0xff followed by not zero, is a new section
while (ptr < end - 1 && (*ptr != 0xff || ptr[1] == 0)) while (ptr < end - 1 && (ptr[0] != 0xff || ptr[1] == 0))
ptr++; ptr++;
// Go back tgo start of section
ptr--;
// Check if marker is an end of image marker // Check if marker is an end of image marker
if (*(ptr++) != 0xff || *(ptr++) != 0xd9) if (!find_jpeg_section(&ptr, end, 0xd9))
{ {
log_e("No end of image marker found"); log_e("No end of image marker found");
return false;
} }
jpeg_data_ = std::tuple<const uint8_t *, size_t>(start, size - (ptr - start - 2)); jpeg_data_end = ptr;
log_d("Total jpeg data = %d bytes", jpeg_data_end - jpeg_data_start);
return true; return true;
} }

View File

@@ -31,6 +31,7 @@ default_envs = esp32cam_ai_thinker
[env] [env]
platform = espressif32 platform = espressif32
framework = arduino framework = arduino
test_framework = unity
#upload_protocol = espota #upload_protocol = espota
#upload_port = 192.168.178.223 #upload_port = 192.168.178.223
@@ -42,7 +43,8 @@ framework = arduino
monitor_speed = 115200 monitor_speed = 115200
monitor_rts = 0 monitor_rts = 0
monitor_dtr = 0 monitor_dtr = 0
monitor_filters = log2file, time, default, esp32_exception_decoder #monitor_filters = log2file, time, default, esp32_exception_decoder
monitor_filters = esp32_exception_decoder
build_flags = build_flags =
-Ofast -Ofast

File diff suppressed because one or more lines are too long