#include <cstdio>
|
#include <string>
|
#include <cstring>
|
#include <deque>
|
#include <pthread.h>
|
|
#include "librtsp.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 = 20000000;
|
}
|
|
~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);
|
while (q.empty()) {
|
pthread_cond_wait(&cond, &mtx);
|
pthread_cond_timedwait(&cond, &mtx, &t);
|
}
|
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);
|
}
|
|
private:
|
deque<T> q;
|
pthread_mutex_t mtx;
|
pthread_cond_t cond;
|
timespec t;
|
};
|
|
typedef struct _buffInfo {
|
unsigned char *buff;
|
int buffLen;
|
} frameBuffInfo;
|
|
MyQueue<frameBuffInfo *> m_rtpQueue;
|
long Handle;
|
|
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;
|
}
|
|
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 ");
|
//从缓存中获取buffinfo
|
frameBuffInfo *buffinfo = m_rtpQueue.pop();
|
// DBG(" m_rtpQueue.pop after ");
|
diff = len - buffinfo->buffLen;
|
|
//帧长大于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);
|
|
m_rtpQueue.push_front_one(info);
|
} 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;
|
} while (diff > 0);
|
|
return bufsize;
|
}
|
|
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);
|
|
// //debug===============
|
// static int count = 0;
|
// static FILE *fp_write = NULL;
|
// if(count < 100) {
|
// count++;
|
//
|
// if (!fp_write) {
|
// fp_write = fopen("stream_callback.mp4", "wb+");
|
// }
|
//
|
// fwrite(data, sizeof(char), datalen, fp_write);
|
// }
|
// if(count >= 100){
|
// if (!fp_write) {
|
// fclose(fp_write);
|
// }
|
// }
|
// //debug===============
|
|
static bool startFlag = false;
|
if(frametype == GB_VIDEO_FRAME_I){
|
startFlag = true;
|
}
|
if((data != NULL) && (startFlag == true)){
|
pushInfo(data, datalen);
|
}
|
|
}
|
|
long addCamera(string &rtsp){
|
printf("RTSPSTREAM_Open\n");
|
long userdata = 1001;
|
Handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, userdata);
|
return Handle;
|
}
|
|
void deleteCamera(void){
|
m_rtpQueue.clearAll();
|
RTSPSTREAM_Close(Handle);
|
Handle = 0;
|
}
|