#include <cstdio>
|
#include <string>
|
#include <cstring>
|
#include <deque>
|
#include <pthread.h>
|
|
#include "librtsp.h"
|
#include <sys/time.h>
|
|
|
using namespace std;
|
|
template<typename T>
|
class MyQueue {
|
public:
|
MyQueue():mtx(PTHREAD_MUTEX_INITIALIZER), cond(PTHREAD_COND_INITIALIZER){
|
t.tv_sec = 0;
|
t.tv_nsec = 0;
|
}
|
|
~MyQueue() {
|
|
}
|
|
public:
|
void push(T v) {
|
pthread_mutex_lock(&mtx);
|
q.push_back(v);
|
pthread_cond_signal(&cond);
|
pthread_mutex_unlock(&mtx);
|
}
|
|
//向队列的前面插入元素
|
void push_front_one(T v) {
|
pthread_mutex_lock(&mtx);
|
q.push_front(v);
|
pthread_cond_signal(&cond);
|
pthread_mutex_unlock(&mtx);
|
}
|
|
T pop() {
|
pthread_mutex_lock(&mtx);
|
if (q.empty()) {
|
gettimeofday(&now, NULL);
|
t.tv_sec = now.tv_sec + 5;
|
t.tv_nsec = now.tv_usec * 1000;
|
// pthread_cond_wait(&cond, &mtx);
|
pthread_cond_timedwait(&cond, &mtx, &t);
|
}
|
if (q.empty()) {
|
pthread_mutex_unlock(&mtx);
|
return 0;
|
}
|
T value = q.front();
|
q.pop_front();
|
pthread_mutex_unlock(&mtx);
|
return value;
|
}
|
|
T popNotWait() {
|
pthread_mutex_lock(&mtx);
|
T value = q.front();
|
q.pop_front();
|
pthread_mutex_unlock(&mtx);
|
return value;
|
|
}
|
|
int count_queue() {
|
return q.size();
|
}
|
|
T clearAll(){
|
pthread_mutex_lock(&mtx);
|
while (!q.empty()) q.pop_front();
|
pthread_mutex_unlock(&mtx);
|
}
|
|
void clearAll(std::function<void(T)> fn){
|
pthread_mutex_lock(&mtx);
|
while (!q.empty()){
|
T value = q.front();
|
fn(value);
|
q.pop_front();
|
}
|
pthread_mutex_unlock(&mtx);
|
}
|
private:
|
deque<T> q;
|
pthread_mutex_t mtx;
|
pthread_cond_t cond;
|
timespec t;
|
struct timeval now;
|
};
|
|
typedef struct _buffInfo {
|
unsigned char *buff;
|
int buffLen;
|
} frameBuffInfo;
|
|
class GB28181API{
|
public:
|
GB28181API(/*string rtspUrl*/){
|
// handle = addCamera(rtspUrl);
|
}
|
|
~GB28181API(){
|
printf("GB28181API end!\n");
|
// m_rtpQueue.clearAll();
|
m_rtpQueue.clearAll([](frameBuffInfo *info){
|
delete[] info->buff;
|
delete info;
|
});
|
deleteCamera();
|
}
|
|
bool pushInfo(unsigned char *data, int datalen) {
|
|
frameBuffInfo *info = new frameBuffInfo();
|
info->buff = new unsigned char[datalen];
|
info->buffLen = datalen;
|
memcpy(info->buff, data, datalen);
|
|
//printf(" m_rtpQueue.push befores ");
|
m_rtpQueue.push(info);
|
//printf(" m_rtpQueue.push after ");
|
|
return true;
|
}
|
|
static int readData(void *opaque, unsigned char *buf, int bufsize) {
|
|
GB28181API *_this = (GB28181API *)opaque;
|
int len = bufsize;
|
int diff = 0;
|
do {
|
// printf(" m_rtpQueue.pop before \n");
|
//从缓存中获取buffinfo
|
frameBuffInfo *buffinfo = _this->m_rtpQueue.pop();
|
// printf(" m_rtpQueue.pop after \n");
|
if(buffinfo != nullptr){
|
diff = len - buffinfo->buffLen;
|
}else{
|
return 0;
|
}
|
|
//帧长大于bufsize
|
if (diff < 0) {
|
// printf("/帧长大于bufsize:%d\n", diff);
|
memcpy(buf + bufsize - len, buffinfo->buff, len);
|
|
frameBuffInfo *info = new frameBuffInfo();
|
info->buffLen = buffinfo->buffLen - len;
|
info->buff = new unsigned char[buffinfo->buffLen - len]{};
|
memcpy(info->buff, buffinfo->buff + len, buffinfo->buffLen - len);
|
|
// printf("/帧长大于info->buffLen:%d\n", info->buffLen);
|
_this->m_rtpQueue.push_front_one(info);
|
// printf("/帧长大于info->buffLen\n");
|
} else if (diff == 0) {
|
// printf("/帧长等于bufsize:%d\n", diff);
|
memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
|
} else if (diff > 0) {
|
// printf("/帧长小于bufsize:%d\n", diff);
|
memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
|
len = len - buffinfo->buffLen; //还需要填充的大小
|
memset(buf + bufsize - len, 0, len);
|
//不等待填充,直接进行解码
|
diff = 0;
|
}
|
delete[] buffinfo->buff;
|
delete buffinfo;
|
// printf("/帧长大于info->buffLen1\n");
|
} while (diff > 0);
|
|
return bufsize;
|
}
|
|
static void streamCallBack(int datatype, int frametype, unsigned char *data, unsigned int datalen, long userdata)
|
{
|
GB28181API *_this = (GB28181API *)userdata;
|
//printf("userdata:%ld,datatype:%d, frametype:%d, datalen:%d\n", userdata, datatype, frametype, datalen);
|
|
/*static FILE* fp_write = NULL;
|
if (!fp_write)
|
|
{
|
|
fp_write = fopen("stream_callback.mp4", "wb+");
|
|
}
|
|
fwrite(data, sizeof(char), datalen, fp_write); */
|
|
static bool startFlag = false;
|
if(frametype == GB_VIDEO_FRAME_I){
|
startFlag = true;
|
}
|
if((data != NULL) && (startFlag == true)){
|
_this->pushInfo(data, datalen);
|
}
|
}
|
|
long addCamera(string &rtsp){
|
// long userdata = 1001;//
|
handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, (long)this);
|
printf("RTSPSTREAM_Open, handle:%ld \n", handle);
|
return handle;
|
}
|
|
void deleteCamera(){
|
printf("RTSPSTREAM_Close\n");
|
if(handle != -1){
|
RTSPSTREAM_Close(handle);
|
}
|
|
handle = -1;
|
}
|
private:
|
MyQueue<frameBuffInfo *> m_rtpQueue;
|
long handle = -1;
|
};
|