Skip to content

Commit

Permalink
Added photo copying during the stream
Browse files Browse the repository at this point in the history
  • Loading branch information
Miroslav Pivovarsky committed Jun 2, 2024
1 parent cee7ebc commit ec7b7ea
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
61 changes: 61 additions & 0 deletions ESP32_PrusaConnectCam/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions ESP32_PrusaConnectCam/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ class Camera {
/* 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
Expand Down Expand Up @@ -104,6 +106,7 @@ class Camera {
uint16_t StreamGetFrameAverageSize();
float StreamGetFrameAverageFps();
void StreamClearFrameData();
void StreamSetSendingPhoto(bool);

void CopyPhoto(camera_fb_t *);
void CopyPhoto(String*);
Expand All @@ -112,6 +115,7 @@ class Camera {
int GetPhotoSize();
String GetPhoto();
camera_fb_t *GetPhotoFb();
camera_fb_t* GetPhotoFbDuplicate();
PhotoExifData_t * GetPhotoExifData();
framesize_t TransformFrameSizeDataType(uint8_t);
void SetPhotoSending(bool);
Expand Down
22 changes: 19 additions & 3 deletions ESP32_PrusaConnectCam/connect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down

0 comments on commit ec7b7ea

Please sign in to comment.