Added photo copying during the stream
parent
cee7ebc8ae
commit
ec7b7eabc7
|
|
@ -29,6 +29,8 @@ Camera::Camera(Configuration* i_conf, Logs* i_log, uint8_t i_FlashPin) {
|
||||||
CameraFlashPin = i_FlashPin;
|
CameraFlashPin = i_FlashPin;
|
||||||
StreamOnOff = false;
|
StreamOnOff = false;
|
||||||
frameBufferSemaphore = xSemaphoreCreateMutex();
|
frameBufferSemaphore = xSemaphoreCreateMutex();
|
||||||
|
FrameBufferDuplicate = (camera_fb_t*)heap_caps_malloc(sizeof(camera_fb_t), MALLOC_CAP_SPIRAM);
|
||||||
|
StreamSendingPhoto = false;
|
||||||
|
|
||||||
PhotoExifData.header = NULL;
|
PhotoExifData.header = NULL;
|
||||||
PhotoExifData.len = 0;
|
PhotoExifData.len = 0;
|
||||||
|
|
@ -397,6 +399,13 @@ void Camera::CapturePhoto() {
|
||||||
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
|
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
|
||||||
}
|
}
|
||||||
xSemaphoreGive(frameBufferSemaphore);
|
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 */
|
/* 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 */
|
/* check if photo is correctly saved */
|
||||||
} while (!(FrameBuffer->len > 100));
|
} while (!(FrameBuffer->len > 100));
|
||||||
*i_buf = *FrameBuffer;
|
*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);
|
xSemaphoreGive(frameBufferSemaphore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,6 +551,15 @@ void Camera::StreamClearFrameData() {
|
||||||
StreamAverageSize = 0;
|
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
|
@brief Get Photo
|
||||||
@param none
|
@param none
|
||||||
|
|
@ -530,6 +582,15 @@ camera_fb_t* Camera::GetPhotoFb() {
|
||||||
return FrameBuffer;
|
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
|
@brief Get Photo Exif Data
|
||||||
@param none
|
@param none
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,11 @@ private:
|
||||||
/* OV2640 camera module pinout and cfg*/
|
/* OV2640 camera module pinout and cfg*/
|
||||||
camera_config_t CameraConfig; ///< camera configuration
|
camera_config_t CameraConfig; ///< camera configuration
|
||||||
camera_fb_t *FrameBuffer; ///< frame buffer
|
camera_fb_t *FrameBuffer; ///< frame buffer
|
||||||
|
camera_fb_t *FrameBufferDuplicate; ///< frame buffer duplicate
|
||||||
sensor_t* sensor; ///< sensor
|
sensor_t* sensor; ///< sensor
|
||||||
String Photo; ///< photo in string format
|
String Photo; ///< photo in string format
|
||||||
bool StreamOnOff; ///< stream on/off
|
bool StreamOnOff; ///< stream on/off
|
||||||
|
bool StreamSendingPhoto; ///< sending photo to Prusa Connect during stream
|
||||||
SemaphoreHandle_t frameBufferSemaphore; ///< semaphore for frame buffer
|
SemaphoreHandle_t frameBufferSemaphore; ///< semaphore for frame buffer
|
||||||
float StreamAverageFps; ///< stream average fps
|
float StreamAverageFps; ///< stream average fps
|
||||||
uint16_t StreamAverageSize; ///< stream average size
|
uint16_t StreamAverageSize; ///< stream average size
|
||||||
|
|
@ -104,6 +106,7 @@ public:
|
||||||
uint16_t StreamGetFrameAverageSize();
|
uint16_t StreamGetFrameAverageSize();
|
||||||
float StreamGetFrameAverageFps();
|
float StreamGetFrameAverageFps();
|
||||||
void StreamClearFrameData();
|
void StreamClearFrameData();
|
||||||
|
void StreamSetSendingPhoto(bool);
|
||||||
|
|
||||||
void CopyPhoto(camera_fb_t *);
|
void CopyPhoto(camera_fb_t *);
|
||||||
void CopyPhoto(String*);
|
void CopyPhoto(String*);
|
||||||
|
|
@ -112,6 +115,7 @@ public:
|
||||||
int GetPhotoSize();
|
int GetPhotoSize();
|
||||||
String GetPhoto();
|
String GetPhoto();
|
||||||
camera_fb_t *GetPhotoFb();
|
camera_fb_t *GetPhotoFb();
|
||||||
|
camera_fb_t* GetPhotoFbDuplicate();
|
||||||
PhotoExifData_t * GetPhotoExifData();
|
PhotoExifData_t * GetPhotoExifData();
|
||||||
framesize_t TransformFrameSizeDataType(uint8_t);
|
framesize_t TransformFrameSizeDataType(uint8_t);
|
||||||
void SetPhotoSending(bool);
|
void SetPhotoSending(bool);
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,17 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
||||||
|
|
||||||
/* get photo buffer */
|
/* get photo buffer */
|
||||||
bool SendWithExif = false;
|
bool SendWithExif = false;
|
||||||
uint8_t *fbBuf = camera->GetPhotoFb()->buf;
|
uint8_t *fbBuf = NULL;
|
||||||
size_t fbLen = camera->GetPhotoFb()->len;
|
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 */
|
/* sending exif data */
|
||||||
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
|
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
|
||||||
|
|
@ -235,8 +244,10 @@ void PrusaConnect::SendPhotoToBackend() {
|
||||||
|
|
||||||
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
|
if ((camera->GetPhotoExifData()->header != NULL) && (camera->GetStreamStatus() == false)) {
|
||||||
total_len = camera->GetPhotoExifData()->len + camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset;
|
total_len = camera->GetPhotoExifData()->len + camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset;
|
||||||
} else {
|
} else if (camera->GetStreamStatus() == false) {
|
||||||
total_len = camera->GetPhotoFb()->len;
|
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);
|
SendDataToBackend(&Photo, total_len, F("image/jpg"), F("Photo"), HOST_URL_CAM_PATH, SendPhoto);
|
||||||
camera->SetPhotoSending(false);
|
camera->SetPhotoSending(false);
|
||||||
|
|
@ -302,8 +313,13 @@ void PrusaConnect::TakePictureAndSendToBackend() {
|
||||||
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
|
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return frame buffer */
|
||||||
if (camera->GetStreamStatus() == false) {
|
if (camera->GetStreamStatus() == false) {
|
||||||
|
/* return frame buffer when photo is not sent during stream */
|
||||||
camera->CaptureReturnFrameBuffer();
|
camera->CaptureReturnFrameBuffer();
|
||||||
|
} else {
|
||||||
|
/* set stream flag for sending photo to false */
|
||||||
|
camera->StreamSetSendingPhoto(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue