1、怎么实现最小的RTSP服务器
亲 很高兴为你解答 以下答案有道友提供
//////rtsp.c//////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <errno.h>
#include <netdb.h>
#include <time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h> //close()
#include "h264.h"
//#define DEST_PORT 8888
typedef struct
{
int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
unsigned max_size; //! Nal Unit Buffer size
int forbidden_bit; //! should be always FALSE
int nal_reference_idc; //! NALU_PRIORITY_xxxx
int nal_unit_type; //! NALU_TYPE_xxxx
char *buf; //! contains the first byte followed by the EBSP
unsigned short lost_packets; //! true, if packet loss is detected
} NALU_t;
FILE *bits = NULL; //!< the bit stream file
static int FindStartCode2 (unsigned char *Buf);//查找开始字符0x000001
static int FindStartCode3 (unsigned char *Buf);//查找开始字符0x00000001
//static bool flag = true;
static int info2=0, info3=0;
RTP_FIXED_HEADER *rtp_hdr;
NALU_HEADER *nalu_hdr;
FU_INDICATOR *fu_ind;
FU_HEADER *fu_hdr;
/**
int sock_init(int sockfd,struct sockaddr_in addr,int SERVER_PORT)
{
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Socket Error:%s\n",strerror(errno));
exit(1);
}
printf("sockfd is %d\n",sockfd);
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(SERVER_PORT);
if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0)
{
fprintf(stderr,"Bind Error:%s\n",strerror(errno));
exit(1);
}
printf("init successfel!!\nport is %dsockfd is %d\n",SERVER_PORT,sockfd);
return 0;
}
*/
char* sock_recv(int sockfd,struct sockaddr *addr_client,int *addrlen)
{
//int *tem_len = &addrlen;
socklen_t len;
printf("sock_recv sockfd is %d\n",sockfd);
char *recv_buffer = malloc (sizeof (char));
//printf("sock_recv sockfd is88888888888888 %d\n",sockfd);
int n;
n=recvfrom(sockfd,recv_buffer,256,0,addr_client,&len);
//printf("recv number is %d\n",n);
if(0)
{
printf("recvfrom error!\n");
exit (1);
}
if(-1==n)
{
perror("recv error:");
}
else
{
addrlen=(int *)len;
printf("sock recv success!!\n");
/** char IPdotdec[20]; //存放点分十进制IP地址
struct in_addr s =
inet_ntop(AF_INET, (void *)&s, IPdotdec, 16);
printf("addr_client.data=%s\n",IPdotdec);
*/ printf("addr_len=%ld\n",addrlen);
}
return recv_buffer;
}
//为NALU_t结构体分配内存空间
NALU_t *AllocNALU(int buffersize)
{
NALU_t *n;
if ((n = (NALU_t*)calloc (1, sizeof (NALU_t))) == NULL)
{
printf("AllocNALU: n");
exit(0);
}
n->max_size=buffersize;
if ((n->buf = (char*)calloc (buffersize, sizeof (char))) == NULL)
{
free (n);
printf ("AllocNALU: n->buf");
exit(0);
}
return n;
}
//释放
void FreeNALU(NALU_t *n)
{
if (n)
{
if (n->buf)
{
free(n->buf);
n->buf=NULL;
}
free (n);
}
}
void OpenBitstreamFile (char *fn)
{
if (NULL == (bits=fopen(fn, "rb")))
{
printf("open file error\n");
exit(0);
}
printf("test264 open successful!\n");
}
//这个函数输入为一个NAL结构体,主要功能为得到一个完整的NALU并保存在NALU_t的buf中,获取他的长度,填充F,IDC,TYPE位。
//并且返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
int GetAnnexbNALU (NALU_t *nalu)
{
int pos = 0;
int StartCodeFound, rewind;
unsigned char *Buf;
if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL)
printf ("GetAnnexbNALU: Could not allocate Buf memory\n");
nalu->startcodeprefix_len=3;//初始化码流序列的开始字符为3个字节
if (3 != fread (Buf, 1, 3, bits))//从码流中读3个字节
{
free(Buf);
return 0;
}
info2 = FindStartCode2 (Buf);//判断是否为0x000001
if(info2 != 1)
{
//如果不是,再读一个字节
if(1 != fread(Buf+3, 1, 1, bits))//读一个字节
{
free(Buf);
return 0;
}
info3 = FindStartCode3 (Buf);//判断是否为0x00000001
if (info3 != 1)//如果不是,返回-1
{
free(Buf);
return -1;
}
else
{
//如果是0x00000001,得到开始前缀为4个字节
pos = 4;
nalu->startcodeprefix_len = 4;
}
}
else
{
//如果是0x000001,得到开始前缀为3个字节
nalu->startcodeprefix_len = 3;
pos = 3;
}
//查找下一个开始字符的标志位
StartCodeFound = 0;
info2 = 0;
info3 = 0;
while (!StartCodeFound)
{
if (feof (bits))//判断是否到了文件尾
{
nalu->len = (pos-1)-nalu->startcodeprefix_len;
memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);
nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
free(Buf);
return pos-1;
}
Buf[pos++] = fgetc (bits);//读一个字节到BUF中
info3 = FindStartCode3(&Buf[pos-4]);//判断是否为0x00000001
if(info3 != 1)
info2 = FindStartCode2(&Buf[pos-3]);//判断是否为0x000001
StartCodeFound = (info2 == 1 || info3 == 1);
}
// Here, we have found another start code (and read length of startcode bytes more than we should
// have. Hence, go back in the file
rewind = (info3 == 1)? -4 : -3;
if (0 != fseek (bits, rewind, SEEK_CUR))//把文件指针指向前一个NALU的末尾
{
free(Buf);
printf("GetAnnexbNALU: Cannot fseek in the bit stream file");
}
// Here the Start code, the complete NALU, and the next start code is in the Buf.
// The size of Buf is pos, pos+rewind are the number of bytes excluding the next
// start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start code
// 不管有没有再次读到 头 ,其主要 关心的还是 nalu->len
nalu->len = (pos+rewind)-nalu->startcodeprefix_len;
memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);//拷贝一个完整NALU,不拷贝起始前缀0x000001或0x00000001
nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
free(Buf);
return (pos+rewind);//返回两个开始字符之间间隔的字节数,即包含有前缀的NALU的长度
}
//输出NALU长度和TYPE
void mp(NALU_t *n)
{
if (!n)return;
//printf("a new nal:");
printf(" len: %d ", n->len);
printf("nal_unit_type: %x\n", n->nal_unit_type);
}
希望能帮助你
2、有支持3种码流的网络摄像机吗?
我知道网视无忧这个品牌的网络摄像机可以支持3种码流,可以满足本地,互联网,跨平台访问的要求,有兴趣可以找他们厂家详细了解。
3、这个算25MB的高清码流吗?
D1格式一般一张图片是220K,
定码率下一个小时一个通道录像文件大小的计算公式如下:
码流(kbit/s) ÷ 8 × 3600 ÷ 1024 (单位:MB)
意思是1秒钟8张图片的情况下,3600秒是1小时,得出来的数是多少Kb,除以1024,得出1个通道用D1格式记录的文件大小。
一般D1(4cif)录像1小时是100M,你调成2帧每秒除以4,最后就是1小时25MB了
12小时300MB
120G=120*1024MB=12880MB
12880MB/25(MB/小时)=4900小时
算上光照不够的情况下每小时文件会增大5M,估计你可以保存4500小时
你可以选择覆盖
问题2:
普通摄像机达到 D1没问题,这个码率主要是对硬盘录像机或者是视频服务器来说的
问题三
白平衡你需要设置AUTO,这样白天夜间色温差别会小点
柜台不算太长,但我还是建议你选择一个较小的空间进行监控,不过一般来说在看清人脸的前提下,普通摄像机能看清楚4米左右的范围
给你个公式,我经常用的
正确选用镜头焦距的理论计算
摄取景物的镜头视场角是极为重要的参数,镜头视场角随镜头焦距及摄像机规格大小而变化(其变化关系如前所述),覆盖景物镜头的焦距可用下述公式计算:
(1)f=u·D/U
(2)f=h·D/H
f:镜头焦距、U:景物实际高度、H:景物实际宽度、D:镜头至景物实测距离、u:图像高度、h:图像宽度
举例说明:
当选用1/2〃镜头时,图像尺寸为u=4.8mm,h=6.4mm。镜头至景物距离D=3500mm,景物的实际高度为U=2500mm(景物的实际宽度可由下式算出H=1.333·U,这种关系由摄像机取景器CCD片决定)。
将以上参数代入公式(1)中,可得f=4.8·3500/2500=6.72mm,故选用6mm定焦镜头即可。
强烈建议你选用摄像机的时候不要贪图便宜去选择国产的、有各种功能的摄像机,因为你如果买来,用3个月之后你会后悔的,因为原材料就不是一个等级的。
三星或者sony是最好的选择,你有钱可以选福特
4、我的视频使用300Kbps的码流,我的服务器带宽是10M,请问我的服务器能承受同时多少人的视频访问。
应该是273个,带宽10m/s=10*1024KB/S
而300Kbps=37.5KB/S
所以10240除以37.5等于273.06666不尽
故可以承受约273人的访问 不过这是全速版理论值
考虑到服权务器工作状态(不满载,不超载)和网络状况
应该在220人左右吧
自己算的 看着给吧
5、如何将服务器上采集的海康H.264码流进行后期传送及处理?
1
2的话重新编解码费时
6、如何通过python把一段码流发到服务器
建议看看socket通信那部分, 很简单的,码流你确定可以处理ok?我觉得你会处理码流,一个socket通信算个p!
7、视频监控系统中,分辨率与码流的关系?
D1格式一般一张图片是220K,
定码率下一个小时一个通道录像文件大小的计算公式如下:
码流(kbit/s) ÷ 8 × 3600 ÷ 1024 (单位:MB)
意思是1秒钟8张图片的情况下,3600秒是1小时,得出来的数是多少Kb,除以1024,得出1个通道用D1格式记录的文件大小。
一般D1(4cif)录像1小时是100M,你调成2帧每秒除以4,最后就是1小时25MB了
12小时300MB
120G=120*1024MB=12880MB
12880MB/25(MB/小时)=4900小时
算上光照不够的情况下每小时文件会增大5M,估计你可以保存4500小时
你可以选择覆盖
问题2:
普通摄像机达到 D1没问题,这个码率主要是对硬盘录像机或者是视频服务器来说的
问题三
白平衡你需要设置AUTO,这样白天夜间色温差别会小点
柜台不算太长,但我还是建议你选择一个较小的空间进行监控,不过一般来说在看清人脸的前提下,普通摄像机能看清楚4米左右的范围
给你个公式,我经常用的
正确选用镜头焦距的理论计算
摄取景物的镜头视场角是极为重要的参数,镜头视场角随镜头焦距及摄像机规格大小而变化(其变化关系如前所述),覆盖景物镜头的焦距可用下述公式计算:
(1)f=u·D/U
(2)f=h·D/H
f:镜头焦距、U:景物实际高度、H:景物实际宽度、D:镜头至景物实测距离、u:图像高度、h:图像宽度
举例说明:
当选用1/2〃镜头时,图像尺寸为u=4.8mm,h=6.4mm。镜头至景物距离D=3500mm,景物的实际高度为U=2500mm(景物的实际宽度可由下式算出H=1.333·U,这种关系由摄像机取景器CCD片决定)。
将以上参数代入公式(1)中,可得f=4.8·3500/2500=6.72mm,故选用6mm定焦镜头即可。
强烈建议你选用摄像机的时候不要贪图便宜去选择国产的、有各种功能的摄像机,因为你如果买来,用3个月之后你会后悔的,因为原材料就不是一个等级的。
三星或者sony是最好的选择,你有钱可以选福特
8、网络摄像机一般占用网络带宽是多少?
那要看你网络摄像机的分辨率了。
一般CIF在500Kbps左右;D1在1.5Mbps左右 100W占用3Mbps左右;200W占用5Mbps左右。(注意是Mbps不是MBps),图像流畅,动态画面基本不会出现马赛克现象。