Added photo copying during the stream

pull/21/merge
Miroslav Pivovarsky 2024-06-02 10:58:01 +02:00
parent cee7ebc8ae
commit ec7b7eabc7
3 changed files with 84 additions and 3 deletions

View File

@ -29,6 +29,8 @@ Camera::Camera(Configuration* i_conf, Logs* i_log, uint8_t i_FlashPin) {
CameraFlashPin = i_FlashPin;
StreamOnOff = false;
frameBufferSemaphore = xSemaphoreCreateMutex();
FrameBufferDuplicate = (camera_fb_t*)heap_caps_malloc(sizeof(camera_fb_t), MALLOC_CAP_SPIRAM);
StreamSendingPhoto = false;
PhotoExifData.header = NULL;
PhotoExifData.len = 0;
@ -397,6 +399,13 @@ void Camera::CapturePhoto() {
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
}
xSemaphoreGive(frameBufferSemaphore);
} else {
/* Stream is on, set flag for sending photo */
if (xSemaphoreTake(frameBufferSemaphore, portMAX_DELAY)) {
StreamSendingPhoto = true;
xSemaphoreGive(frameBufferSemaphore);
}
}
/* Reinit camera module if photo capture failed */
@ -426,6 +435,40 @@ void Camera::CaptureStream(camera_fb_t* i_buf) {
/* check if photo is correctly saved */
} while (!(FrameBuffer->len > 100));
*i_buf = *FrameBuffer;
/* copy the frame buffer to the duplicate frame buffer. For sending photo to Prusa Connect */
if (false == StreamSendingPhoto) {
/* memory allocation release */
if (FrameBufferDuplicate != NULL) {
if (FrameBufferDuplicate->buf != NULL) {
free(FrameBufferDuplicate->buf);
FrameBufferDuplicate->buf = NULL; /* Set to NULL after freeing */
}
free(FrameBufferDuplicate);
FrameBufferDuplicate = NULL; /* Set to NULL after freeing */
}
/* Allocate memory for the duplicate frame structure */
FrameBufferDuplicate = (camera_fb_t*)heap_caps_malloc(sizeof(camera_fb_t), MALLOC_CAP_SPIRAM);
/* Copy the metadata */
memcpy(FrameBufferDuplicate, FrameBuffer, sizeof(camera_fb_t));
/* Allocate memory for the image data */
FrameBufferDuplicate->buf = (uint8_t*)heap_caps_malloc(FrameBuffer->len, MALLOC_CAP_SPIRAM);
/* Check if memory allocation was successful */
if (!FrameBufferDuplicate->buf) {
/* Handle error */
free(FrameBufferDuplicate);
Serial.println("Failed to allocate memory for the duplicate frame buffer");
} else {
/* Copy the image data */
memcpy(FrameBufferDuplicate->buf, FrameBuffer->buf, FrameBuffer->len);
}
}
xSemaphoreGive(frameBufferSemaphore);
}
}
@ -508,6 +551,15 @@ void Camera::StreamClearFrameData() {
StreamAverageSize = 0;
}
/**
@brief Set Sending Photo for Stream
@param bool - sending photo
@return none
*/
void Camera::StreamSetSendingPhoto(bool i_data) {
StreamSendingPhoto = i_data;
}
/**
@brief Get Photo
@param none
@ -530,6 +582,15 @@ camera_fb_t* Camera::GetPhotoFb() {
return FrameBuffer;
}
/**
@brief Get Photo Frame Buffer Duplicate
@param none
@return camera_fb_t* - photo frame buffer duplicate
*/
camera_fb_t* Camera::GetPhotoFbDuplicate() {
return FrameBufferDuplicate;
}
/**
@brief Get Photo Exif Data
@param none

View File

@ -68,9 +68,11 @@ private:
/* OV2640 camera module pinout and cfg*/
camera_config_t CameraConfig; ///< camera configuration
camera_fb_t *FrameBuffer; ///< frame buffer
camera_fb_t *FrameBufferDuplicate; ///< frame buffer duplicate
sensor_t* sensor; ///< sensor
String Photo; ///< photo in string format
bool StreamOnOff; ///< stream on/off
bool StreamSendingPhoto; ///< sending photo to Prusa Connect during stream
SemaphoreHandle_t frameBufferSemaphore; ///< semaphore for frame buffer
float StreamAverageFps; ///< stream average fps
uint16_t StreamAverageSize; ///< stream average size
@ -104,6 +106,7 @@ public:
uint16_t StreamGetFrameAverageSize();
float StreamGetFrameAverageFps();
void StreamClearFrameData();
void StreamSetSendingPhoto(bool);
void CopyPhoto(camera_fb_t *);
void CopyPhoto(String*);
@ -112,6 +115,7 @@ public:
int GetPhotoSize();
String GetPhoto();
camera_fb_t *GetPhotoFb();
camera_fb_t* GetPhotoFbDuplicate();
PhotoExifData_t * GetPhotoExifData();
framesize_t TransformFrameSizeDataType(uint8_t);
void SetPhotoSending(bool);

View File

@ -126,8 +126,17 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
/* get photo buffer */
bool SendWithExif = false;
uint8_t *fbBuf = camera->GetPhotoFb()->buf;
size_t fbLen = camera->GetPhotoFb()->len;
uint8_t *fbBuf = NULL;
size_t fbLen = 0;
if (camera->GetStreamStatus() == true) {
/* get duplicate photo buffer from camera */
fbBuf = camera->GetPhotoFbDuplicate()->buf;
fbLen = camera->GetPhotoFbDuplicate()->len;
} else {
/* get original photo buffer from camera */
fbBuf = camera->GetPhotoFb()->buf;
fbLen = camera->GetPhotoFb()->len;
}
/* sending exif data */
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
@ -235,8 +244,10 @@ void PrusaConnect::SendPhotoToBackend() {
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
total_len = camera->GetPhotoExifData()->len + camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset;
} else {
} else if (camera->GetStreamStatus() == false) {
total_len = camera->GetPhotoFb()->len;
} else {
total_len = camera->GetPhotoFbDuplicate()->len;
}
SendDataToBackend(&Photo, total_len, F("image/jpg"), F("Photo"), HOST_URL_CAM_PATH, SendPhoto);
camera->SetPhotoSending(false);
@ -302,8 +313,13 @@ void PrusaConnect::TakePictureAndSendToBackend() {
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
}
/* return frame buffer */
if (camera->GetStreamStatus() == false) {
/* return frame buffer when photo is not sent during stream */
camera->CaptureReturnFrameBuffer();
} else {
/* set stream flag for sending photo to false */
camera->StreamSetSendingPhoto(false);
}
}