diff --git a/avaota_app_demo/build_main.sh b/avaota_app_demo/build_main.sh index fe90c68..66582ee 100644 --- a/avaota_app_demo/build_main.sh +++ b/avaota_app_demo/build_main.sh @@ -46,8 +46,8 @@ check_lib() { } all_libs_ok=true -check_lib "libssl.so" || all_libs_ok=false -check_lib "libcrypto.so" || all_libs_ok=false +# check_lib "libssl.so" || all_libs_ok=false (Removed in optimization) +# check_lib "libcrypto.so" || all_libs_ok=false (Removed in optimization) check_lib "libcurl.so" || all_libs_ok=false check_lib "libasound.so" || all_libs_ok=false diff --git a/avaota_app_demo/src/Makefile b/avaota_app_demo/src/Makefile index fcaee5c..c910fb7 100644 --- a/avaota_app_demo/src/Makefile +++ b/avaota_app_demo/src/Makefile @@ -132,8 +132,8 @@ LDFLAGS += -lcedarxrender -lhwdisplay # ALSA 音频库(静态库不存在,且音频播放已禁用) # LDFLAGS += -lasound -# OpenSSL (用于 WebSocket 握手) -LDFLAGS += -lssl -lcrypto +# OpenSSL (Removed in Day 26 optimization) +# LDFLAGS += -lssl -lcrypto # 结束静态库组 LDFLAGS += -Wl,--end-group diff --git a/avaota_app_demo/src/camera/camera.cpp b/avaota_app_demo/src/camera/camera.cpp index e15bc0b..13ab31d 100644 --- a/avaota_app_demo/src/camera/camera.cpp +++ b/avaota_app_demo/src/camera/camera.cpp @@ -52,7 +52,11 @@ Camera::Camera() , m_fps(0.0f) , m_frame_count(0) , m_last_time(0) + , m_current_buf_idx(0) { + // Initialize buffer pointers to nullptr + m_frame_buffers[0] = nullptr; + m_frame_buffers[1] = nullptr; LOGD("Camera constructor"); } @@ -102,6 +106,14 @@ void Camera::deinit() // 退出系统 AW_MPI_SYS_Exit(); + // Day 26: Free memory pool + for (int i = 0; i < 2; i++) { + if (m_frame_buffers[i]) { + delete[] m_frame_buffers[i]; + m_frame_buffers[i] = nullptr; + } + } + // 重置统计 m_fps = 0.0f; m_frame_count = 0; @@ -113,6 +125,18 @@ void Camera::deinit() bool Camera::init() { LOGI("Initializing camera: %dx%d @%dfps", m_width, m_height, DEFAULT_FPS); + + // Day 26: Pre-allocate memory pool + for (int i = 0; i < 2; i++) { + if (!m_frame_buffers[i]) { + m_frame_buffers[i] = new uint8_t[MAX_FRAME_SIZE]; + if (!m_frame_buffers[i]) { + LOGE("Failed to allocate frame buffer %d", i); + return false; + } + LOGD("Allocated frame buffer %d (%zu bytes)", i, MAX_FRAME_SIZE); + } + } // 1. 初始化 MPP 系统 MPP_SYS_CONF_S sys_conf; @@ -332,16 +356,25 @@ bool Camera::capture_frame(uint8_t** jpeg_data, size_t* jpeg_size) return false; } - // 计算总大小 + // Day 26: Use Memory Pool instead of dynamic allocation size_t total_size = stream.mpPack[0].mLen0 + stream.mpPack[0].mLen1 + stream.mpPack[0].mLen2; if (total_size == 0) { LOGE("Empty JPEG frame"); AW_MPI_VENC_ReleaseStream(m_venc_chn, &stream); return false; } + + // Safety check for buffer overflow + if (total_size > MAX_FRAME_SIZE) { + LOGE("Frame size (%zu) exceeds MAX_FRAME_SIZE (%zu), dropping frame", total_size, MAX_FRAME_SIZE); + AW_MPI_VENC_ReleaseStream(m_venc_chn, &stream); + return false; + } - // 分配内存并拷贝数据 - uint8_t* buffer = new uint8_t[total_size]; + // Get current buffer + uint8_t* buffer = m_frame_buffers[m_current_buf_idx]; + + // Copy data size_t offset = 0; if (stream.mpPack[0].mLen0 > 0 && stream.mpPack[0].mpAddr0) { @@ -360,6 +393,9 @@ bool Camera::capture_frame(uint8_t** jpeg_data, size_t* jpeg_size) // 释放流 AW_MPI_VENC_ReleaseStream(m_venc_chn, &stream); + // Switch buffer index for next frame + m_current_buf_idx = (m_current_buf_idx + 1) % 2; + // 更新 FPS 统计 update_fps_stats(); @@ -373,9 +409,8 @@ bool Camera::capture_frame(uint8_t** jpeg_data, size_t* jpeg_size) void Camera::release_frame(uint8_t* jpeg_data) { - if (jpeg_data) { - delete[] jpeg_data; - } + // No-op for memory pool + // Buffer will be overwritten when it's turn comes again } bool Camera::set_framesize(const std::string& size) diff --git a/avaota_app_demo/src/camera/camera.h b/avaota_app_demo/src/camera/camera.h index 57dbe40..b687222 100644 --- a/avaota_app_demo/src/camera/camera.h +++ b/avaota_app_demo/src/camera/camera.h @@ -95,6 +95,11 @@ private: bool init_venc(); // Video Encoder void update_fps_stats(); + + // Day 26 Optimization: Fixed Memory Pool (Double Buffering) + static const size_t MAX_FRAME_SIZE = 512 * 1024; // 512KB (Sufficient for 720p MJPEG) + uint8_t* m_frame_buffers[2]; + int m_current_buf_idx; }; #endif // CAMERA_H diff --git a/avaota_app_demo/src/network/ws_client.cpp b/avaota_app_demo/src/network/ws_client.cpp index 6dd8dc6..f2ba285 100644 --- a/avaota_app_demo/src/network/ws_client.cpp +++ b/avaota_app_demo/src/network/ws_client.cpp @@ -12,10 +12,61 @@ #include #include #include -#include -#include -#include -#include +#include +#include + +// Day 26: Remove OpenSSL dependency +// #include +// #include +// #include +// #include + +// Custom Base64 Encoding Table +static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +// Custom helper: base64 encode +static std::string base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + } + + return ret; +} // WebSocket 魔术字符串(用于握手验证,当前未使用) // static const char* WS_MAGIC_STRING = "258EAFAA-5914-47DA-95CA-C5AB0DC85B11"; @@ -178,21 +229,11 @@ bool WSClient::perform_handshake() { random_bytes[i] = rand() % 256; } - // Base64 编码 - BIO *bio, *b64; - BUF_MEM *bufferPtr; + // Day 26: Use custom Base64 implementation instead of OpenSSL + std::string ws_key = base64_encode(random_bytes, 16); - b64 = BIO_new(BIO_f_base64()); - bio = BIO_new(BIO_s_mem()); - bio = BIO_push(b64, bio); - - BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - BIO_write(bio, random_bytes, 16); - BIO_flush(bio); - BIO_get_mem_ptr(bio, &bufferPtr); - - std::string ws_key(bufferPtr->data, bufferPtr->length); - BIO_free_all(bio); + // Debug log key (optional) + // LOG_DEBUG("[WS] Generated Sec-WebSocket-Key: %s", ws_key.c_str()); // 构造 HTTP 升级请求 char request[1024];