# ESP32-CAM-MJPEG-Stream-Decoder-and-Control-Library

ESP32-CAM is an inexpensive MJPEG stream embedded device.
The library is MJPEG stream decoder based on libcurl and OpenCV, and written in C/C++.

## Firmware

Modify the following code in "CameraWebServer.ino" file, that is MJPEG stream boundary.

```cpp
#define PART_BOUNDARY "WINBONDBOUDARY"
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\n\r\n";
```
## Easy-to-use

### Dependence
- OpenCV 3 or 4
- libcurl 7

- wxWidgets 2.8.12(for wxESP32-CAM example)

### Use
Include "ESP32-CAM MJPEG Library" folder into your project. </br>
- ESP32-CAM Library.h
- ESP32-CAM Library.cpp

```cpp
#include "./ESP32-CAM MJPEG Library/ESP32-CAM Library.h"

typedef enum {
    FRAMESIZE_QQVGA,    // 160x120
    FRAMESIZE_QQVGA2,   // 128x160
    FRAMESIZE_QCIF,     // 176x144
    FRAMESIZE_HQVGA,    // 240x176
    FRAMESIZE_QVGA,     // 320x240
    FRAMESIZE_CIF,      // 400x296
    FRAMESIZE_VGA,      // 640x480
    FRAMESIZE_SVGA,     // 800x600
    FRAMESIZE_XGA,      // 1024x768
    FRAMESIZE_SXGA,     // 1280x1024
    FRAMESIZE_UXGA      // 1600x1200
} framesize_t;

ESP32_CAM *esp32_cam = new ESP32_CAM(std::string( "192.168.1.254" ));   //ESP32-CAM local IP address

esp32_cam->SetResolution(FRAMESIZE_SVGA); // Set mjpeg video stream resolution

esp32_cam->StartVideoStream();   // Start mjpeg video stream thread

cv::Mat frame = esp32_cam->GetFrame(); // Get mjpeg frame
if(!frame.empty()){
   cv::imshow("Example",frame);  //Show mjpeg video stream
}

```
   

### Command POST and ESP32-CAM GET

In cmd_handler, "var" is variable name, "val" is value of variable, curl POST command is:

```cpp
int ESP32_CAM::SendStream(CURL *curl_object)
{
   long return_code;
   CURLcode response;

   curl_easy_setopt(curl_object,CURLOPT_URL,"192.168.1.254/control?var=framesize&val=7");

   response = curl_easy_perform(curl_object);

   response = curl_easy_getinfo(curl_object, CURLINFO_RESPONSE_CODE, &return_code);

   return (int)return_code;
}
```

"192.168.1.254/control?var=framesize&val=8", "192.168.1.254" is ESP32-CAM IP address setting from:

```cpp
// Set your Static IP address
IPAddress local_IP(192, 168, 1, 254);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
WiFi.begin(ssid, password);  
WiFi.config(local_IP, gateway, subnet);
```

In this example, "/control?var=framesize&val=8" POST /control API and set parameter "framesize" value is "7"(FRAMESIZE_SVGA 800x600).

API FlashControl(bool), Flash LED turn on or off "/led?var=flash&val=1", val=1 is on, val=0 is off.

### Receive ESP32-CAM Page Content

Set curl_easy_setopt parameter CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA  for writing received data. 

```cpp
std::string ESP32_CAM::GetRSSI()
{
   std::string buffer;

   curl_easy_setopt(curl_command,CURLOPT_WRITEFUNCTION,WriteCallback);
   curl_easy_setopt(curl_command,CURLOPT_WRITEDATA,&buffer); 

   if(SendStream(curl_command,std::string("/RSSI"))){
   }  

   return buffer;
}
```

### MJPEG Stream Format

In this case MJPEG stream boundary is fixed length, for split into a MJPEG stream of JPEG binary(byte), each frame JPEG binary with cv::imdecode decode to RGB format. </br>

```cpp
const char VIDEO_STREAM_INTERLEAVE[] = "--WINBONDBOUDARY\r\nContent-Type: image/jpeg\r\n\r\n";

const char JPEG_SOI_MARKER_FIRST_BYTE = 0xFF;
const char JPEG_SOI_MARKER_SECOND_BYTE = 0xD8;
```

```cpp
Content-type: multipart/x-mixed-replace;...

Read more »