I am working on getting image form ip camera. Here i am trying to get raw data only. I need to implement RTSP client library to handle all request and data from ip camera. I connected microcontroller and ip camera with same wifi. I created TCP socket and connected it with ip camera.
std::string genmsg_DESCRIBE(const std::string& url, int seq, const std::string& userAgent, const std::string& authSeq) {
std::string msgRet = "DESCRIBE " + url + " RTSP/1.0\r\n";
msgRet += "CSeq: " + std::to_string(seq) + "\r\n";
msgRet += "Authorization: " + authSeq + "\r\n";
msgRet += "User-Agent: " + userAgent + "\r\n";
msgRet += "Accept: application/sdp\r\n";
msgRet += "\r\n";
return msgRet;
}
std::string genmsg_SETUP(const std::string& url, int seq, const std::string& userAgent, const std::string& authSeq) {
std::string msgRet = "SETUP " + url + " RTSP/1.0\r\n";
msgRet += "CSeq: " + std::to_string(seq) + "\r\n";
msgRet += "Authorization: " + authSeq + "\r\n";
msgRet += "User-Agent: " + userAgent + "\r\n";
msgRet += "Blocksize: 65535\r\n";
msgRet += "Transport: RTP/AVP/TCP;unicast\r\n";
msgRet += "\r\n";
return msgRet;
}
std::string genmsg_OPTIONS(const std::string& url, int seq, const std::string& userAgent, const std::string& sessionId, const std::string& authSeq) {
std::string msgRet = "OPTIONS " + url + " RTSP/1.0\r\n";
msgRet += "CSeq: " + std::to_string(seq) + "\r\n";
msgRet += "User-Agent: " + userAgent + "\r\n";
msgRet += "Session: " + sessionId + "\r\n";
msgRet += "\r\n";
return msgRet;
}
std::string genmsg_PLAY(const std::string& url, int seq, const std::string& userAgent, const std::string& sessionId, const std::string& authSeq) {
std::string msgRet = "PLAY " + url + " RTSP/1.0\r\n";
msgRet += "CSeq: " + std::to_string(seq) + "\r\n";
msgRet += "User-Agent: " + userAgent + "\r\n";
msgRet += "Session: " + sessionId + "\r\n";
msgRet += "Range: npt=0.000-\r\n";
msgRet += "\r\n";
return msgRet;
}
std::string genmsg_TEARDOWN(const std::string& url, int seq, const std::string& userAgent, const std::string& sessionId, const std::string& authSeq) {
std::string msgRet = "TEARDOWN " + url + " RTSP/1.0\r\n";
msgRet += "CSeq: " + std::to_string(seq) + "\r\n";
msgRet += "User-Agent: " + userAgent + "\r\n";
msgRet += "Session: " + sessionId + "\r\n";
msgRet += "\r\n";
return msgRet;
}
Is there anything wrong with this request ?
and i am using md5 hash
std::string generateAuthString(const std::string& username, const std::string& password, const std::string& realm,
const std::string& method, const std::string& uri, const std::string& nonce) {
std::string combined_str1 = username + ":" + realm + ":" + password;
std::string combined_str2 = method + ":" + uri;
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, reinterpret_cast<unsigned char*>(const_cast<char*>(combined_str1.c_str())), combined_str1.length());
unsigned char m1[MD5_DIGEST_LENGTH];
MD5Final(&context, m1);
MD5Init(&context);
MD5Update(&context, reinterpret_cast<unsigned char*>(const_cast<char*>(combined_str2.c_str())), combined_str2.length());
unsigned char m2[MD5_DIGEST_LENGTH];
MD5Final(&context, m2);
std::string combined_str3 = bin2hex(m1, MD5_DIGEST_LENGTH) + ":" + nonce + ":" + bin2hex(m2, MD5_DIGEST_LENGTH);
MD5Init(&context);
MD5Update(&context, reinterpret_cast<unsigned char*>(const_cast<char*>(combined_str3.c_str())), combined_str3.length());
unsigned char response[MD5_DIGEST_LENGTH];
MD5Final(&context, response);
std::stringstream mapRetInf;
mapRetInf << "Digest ";
mapRetInf << "username=\"" << defaultUsername << "\", ";
mapRetInf << "realm=\"" << realm << "\", ";
mapRetInf << "algorithm=\"MD5\", ";
mapRetInf << "nonce=\"" << nonce << "\", ";
mapRetInf << "uri=\"" << uri << "\", ";
mapRetInf << "response=\"" << bin2hex(response, MD5_DIGEST_LENGTH) << "\"";
return mapRetInf.str();
}
Since microcontroller don't have enough space and ram to handle high ram rom function so i have tried to creat simple request.
void setup() {
const char *ssid = "Embedded"; // Put your SSID here
const char *password = "embedded@123"; // Put your PASSWORD here
Serial.begin(115200);
// Connect the WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
// Print information how to contact the camera server
IPAddress ip = WiFi.localIP();
Serial.print("\nWiFi connected with (ESP)IP:");
Serial.println(ip);
int seq = 1;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serverAddress;
// Configure server address structure
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(defaultServerPort);
inet_pton(AF_INET, defaultServerIp.c_str(), &serverAddress.sin_addr);
if (connect(sockfd, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == 0) {
Serial.println("sync connect success");
} else if (errno == EINPROGRESS){
Serial.println("async connecting...");
}
else {
Serial.println("invalid connect");
return;
}
std::string url = "rtsp://" + defaultServerIp + defaultTestUri;
char buffer[BUF_LEN];
bool isDigest = false;
std::string authSeq = "Basic " + std::string("YWRtaW46RW1iZWRkZWRA");
std::string mesg=genmsg_DESCRIBE(url, seq, defaultUserAgent, authSeq);
send(sockfd, mesg.c_str(), mesg.length(), 0);
char buffer1[BUF_LEN];
ssize_t bytesRead1=recv(sockfd, buffer1, BUF_LEN, 0);
buffer1[bytesRead1] = '\0';
Serial.printf("%s",buffer1);
seq++;
mesg="";
char* unauthorizedCheck = strstr(buffer, "Unauthorized");
if (unauthorizedCheck) {
isDigest = true;
// New DESCRIBE with digest authentication
char* start = strstr(buffer, "realm");
char* begin = strchr(start, '\"');
char* end = strchr(begin + 1, '\"');
std::string realm(begin + 1, end);
start = strstr(buffer, "nonce");
begin = strchr(start, '\"');
end = strchr(begin + 1, '\"');
std::string nonce(begin + 1, end);
authSeq = generateAuthString(defaultUsername, defaultPassword, realm, "DESCRIBE", defaultTestUri, nonce);
mesg=genmsg_DESCRIBE(url, seq, defaultUserAgent, authSeq);
send(sockfd, mesg.c_str(), mesg.length(), 0);
char buffer2[BUF_LEN];
ssize_t bytesRead2=recv(sockfd, buffer2, BUF_LEN, 0);
buffer2[bytesRead2] = '\0';
Serial.printf("%s",buffer2);
seq++;
mesg="";
}
control = decodeControl(buffer);
if (isDigest) {
authSeq = generateAuthString(defaultUsername, defaultPassword, realm, "SETUP", defaultTestUri, nonce);
}
mesg=genmsg_SETUP(control, seq, defaultUserAgent, authSeq);
send(sockfd, mesg.c_str(), mesg.length(), 0);
char sessionIdBuffer[BUF_LEN];
ssize_t bytesRead3=recv(sockfd, sessionIdBuffer, BUF_LEN, 0);
sessionIdBuffer[bytesRead3] = '\0';
Serial.printf("%s",sessionIdBuffer);
sessionId = decodeSession(sessionIdBuffer);
seq++;
mesg="";
mesg=genmsg_OPTIONS(url, seq, defaultUserAgent, sessionId, authSeq);
send(sockfd, mesg.c_str(), mesg.length(), 0);
char optionsBuffer[BUF_LEN];
ssize_t bytesRead4=recv(sockfd, optionsBuffer, BUF_LEN, 0);
optionsBuffer[bytesRead4] = '\0';
Serial.printf("%s",optionsBuffer);
mesg="";
seq++;
mesg=genmsg_PLAY(url + "/", seq, defaultUserAgent, sessionId, authSeq);
send(sockfd, mesg.c_str(), mesg.length(), 0);
char playBuffer[BUF_LEN];
ssize_t bytesRead5=recv(sockfd, playBuffer, BUF_LEN, 0);
playBuffer[bytesRead5] = '\0';
Serial.printf("%s",playBuffer);
mesg="";
seq++;
starttime = time(nullptr);
while (true) {
// Send a new RTSP OPTION command to keep the stream alive
time_t now = time(nullptr);
if (difftime(now, starttime) > 50) {
sendAndReceive(genmsg_OPTIONS(url, seq, defaultUserAgent, sessionId, authSeq), seq, sockfd);
starttime = time(nullptr);
}
char msgRcvBuffer[BUF_LEN];
//recv(sockfd, msgRcvBuffer, BUF_LEN, 0);
Serial.printf("%s",buffer);
}
seq++;
sendAndReceive(genmsg_TEARDOWN(url, seq, defaultUserAgent, sessionId, authSeq), seq, sockfd);
char teardownBuffer[BUF_LEN];
close(sockfd);
}
void loop() {
}
I am not getting data from ip camera, can you help me to understand it?
Basical everything is working and i sent play request to ip camera and got response too but i want raw data from ip camera like h264 data.