227 lines
5.4 KiB
C++
227 lines
5.4 KiB
C++
#include "OV2640.h"
|
|
#include <WiFi.h>
|
|
#include <WebServer.h>
|
|
#include <WiFiClient.h>
|
|
|
|
#include "SimStreamer.h"
|
|
#include "OV2640Streamer.h"
|
|
#include "CRtspSession.h"
|
|
|
|
#define ENABLE_OLED //if want use oled ,turn on thi macro
|
|
// #define SOFTAP_MODE // If you want to run our own softap turn this on
|
|
#define ENABLE_WEBSERVER
|
|
#define ENABLE_RTSPSERVER
|
|
|
|
#ifdef ENABLE_OLED
|
|
#include "SSD1306.h"
|
|
#define OLED_ADDRESS 0x3c
|
|
#define I2C_SDA 14
|
|
#define I2C_SCL 13
|
|
SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_32);
|
|
bool hasDisplay; // we probe for the device at runtime
|
|
#endif
|
|
|
|
OV2640 cam;
|
|
|
|
#ifdef ENABLE_WEBSERVER
|
|
WebServer server(80);
|
|
#endif
|
|
|
|
#ifdef ENABLE_RTSPSERVER
|
|
WiFiServer rtspServer(8554);
|
|
#endif
|
|
|
|
|
|
#ifdef SOFTAP_MODE
|
|
IPAddress apIP = IPAddress(192, 168, 1, 1);
|
|
#else
|
|
#include "wifikeys.h"
|
|
#endif
|
|
|
|
#ifdef ENABLE_WEBSERVER
|
|
void handle_jpg_stream(void)
|
|
{
|
|
WiFiClient client = server.client();
|
|
String response = "HTTP/1.1 200 OK\r\n";
|
|
response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
|
|
server.sendContent(response);
|
|
|
|
while (1)
|
|
{
|
|
cam.run();
|
|
if (!client.connected())
|
|
break;
|
|
response = "--frame\r\n";
|
|
response += "Content-Type: image/jpeg\r\n\r\n";
|
|
server.sendContent(response);
|
|
|
|
client.write((char *)cam.getfb(), cam.getSize());
|
|
server.sendContent("\r\n");
|
|
if (!client.connected())
|
|
break;
|
|
}
|
|
}
|
|
|
|
void handle_jpg(void)
|
|
{
|
|
WiFiClient client = server.client();
|
|
|
|
cam.run();
|
|
if (!client.connected())
|
|
{
|
|
return;
|
|
}
|
|
String response = "HTTP/1.1 200 OK\r\n";
|
|
response += "Content-disposition: inline; filename=capture.jpg\r\n";
|
|
response += "Content-type: image/jpeg\r\n\r\n";
|
|
server.sendContent(response);
|
|
client.write((char *)cam.getfb(), cam.getSize());
|
|
}
|
|
|
|
void handleNotFound()
|
|
{
|
|
String message = "Server is running!\n\n";
|
|
message += "URI: ";
|
|
message += server.uri();
|
|
message += "\nMethod: ";
|
|
message += (server.method() == HTTP_GET) ? "GET" : "POST";
|
|
message += "\nArguments: ";
|
|
message += server.args();
|
|
message += "\n";
|
|
server.send(200, "text/plain", message);
|
|
}
|
|
#endif
|
|
|
|
void lcdMessage(String msg)
|
|
{
|
|
#ifdef ENABLE_OLED
|
|
if(hasDisplay) {
|
|
display.clear();
|
|
display.drawString(128 / 2, 32 / 2, msg);
|
|
display.display();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void setup()
|
|
{
|
|
#ifdef ENABLE_OLED
|
|
hasDisplay = display.init();
|
|
if(hasDisplay) {
|
|
display.flipScreenVertically();
|
|
display.setFont(ArialMT_Plain_16);
|
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
|
}
|
|
#endif
|
|
lcdMessage("booting");
|
|
|
|
Serial.begin(115200);
|
|
while (!Serial)
|
|
{
|
|
;
|
|
}
|
|
cam.init(esp32cam_config);
|
|
|
|
IPAddress ip;
|
|
|
|
|
|
#ifdef SOFTAP_MODE
|
|
const char *hostname = "devcam";
|
|
// WiFi.hostname(hostname); // FIXME - find out why undefined
|
|
lcdMessage("starting softAP");
|
|
WiFi.mode(WIFI_AP);
|
|
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
|
bool result = WiFi.softAP(hostname, "12345678", 1, 0);
|
|
if (!result)
|
|
{
|
|
Serial.println("AP Config failed.");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
Serial.println("AP Config Success.");
|
|
Serial.print("AP MAC: ");
|
|
Serial.println(WiFi.softAPmacAddress());
|
|
|
|
ip = WiFi.softAPIP();
|
|
}
|
|
#else
|
|
lcdMessage(String("join ") + ssid);
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.begin(ssid, password);
|
|
while (WiFi.status() != WL_CONNECTED)
|
|
{
|
|
delay(500);
|
|
Serial.print(F("."));
|
|
}
|
|
ip = WiFi.localIP();
|
|
Serial.println(F("WiFi connected"));
|
|
Serial.println("");
|
|
Serial.println(ip);
|
|
#endif
|
|
|
|
lcdMessage(ip.toString());
|
|
|
|
#ifdef ENABLE_WEBSERVER
|
|
server.on("/", HTTP_GET, handle_jpg_stream);
|
|
server.on("/jpg", HTTP_GET, handle_jpg);
|
|
server.onNotFound(handleNotFound);
|
|
server.begin();
|
|
#endif
|
|
|
|
#ifdef ENABLE_RTSPSERVER
|
|
rtspServer.begin();
|
|
#endif
|
|
}
|
|
|
|
CStreamer *streamer;
|
|
CRtspSession *session;
|
|
WiFiClient client; // FIXME, support multiple clients
|
|
|
|
void loop()
|
|
{
|
|
#ifdef ENABLE_WEBSERVER
|
|
server.handleClient();
|
|
#endif
|
|
|
|
#ifdef ENABLE_RTSPSERVER
|
|
uint32_t msecPerFrame = 100;
|
|
static uint32_t lastimage = millis();
|
|
|
|
// If we have an active client connection, just service that until gone
|
|
// (FIXME - support multiple simultaneous clients)
|
|
if(session) {
|
|
session->handleRequests(0); // we don't use a timeout here,
|
|
// instead we send only if we have new enough frames
|
|
|
|
uint32_t now = millis();
|
|
if(now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
|
|
session->broadcastCurrentFrame(now);
|
|
lastimage = now;
|
|
|
|
// check if we are overrunning our max frame rate
|
|
now = millis();
|
|
if(now > lastimage + msecPerFrame)
|
|
printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
|
|
}
|
|
|
|
if(session->m_stopped) {
|
|
delete session;
|
|
delete streamer;
|
|
session = NULL;
|
|
streamer = NULL;
|
|
}
|
|
}
|
|
else {
|
|
client = rtspServer.accept();
|
|
|
|
if(client) {
|
|
//streamer = new SimStreamer(&client, true); // our streamer for UDP/TCP based RTP transport
|
|
streamer = new OV2640Streamer(&client, cam); // our streamer for UDP/TCP based RTP transport
|
|
|
|
session = new CRtspSession(&client, streamer); // our threads RTSP session and state
|
|
}
|
|
}
|
|
#endif
|
|
}
|