11489
- 收藏
- 点赞
- 分享
- 举报
RTSP_RTP_TCP直播协议,潜入到海思sample_vdec做直播,遇到头疼的花屏问题,求助!...
本帖最后由 转角遇见miss 于 2016-9-13 14:06 编辑
先说说我的代码框架(具体如下,不足再补):
1、建立tcp socket rtsp对接ipc摄像头(已设定SO_RCVBUF=32*1024*5)
2、创建3条线程
//recv()tcp接收数据
pthread_create(&pVdecThread[1], 0, RECV, (HI_VOID *)&my_struct);
//handlestream解析rtp包,保存解析好的数据
pthread_create(&pVdecThread[2], 0, handle, NULL);
//sendstream调用海思mpp接口播放视频流
pthread_create(&pVdecThread, 0, SAMPLE_COMM_VDEC_SendStream, (HI_VOID *)&pstVdecSend);
3、创建了共有环形缓存区fifo + 共有streambuf=32*1024*5
fifo有80个节点,每个节点32*1024*5,用于每次保存线程recv()到得buf;
用信号量来判断,当有缓存区有数据就调用线程handle进行拆包
同样用信号量来判断,当h264_rtp_unpackage()从fifo取数据解析,解析好数据就保存到Video_Stream,当拼好一帧数据就调用SAMPLE_COMM_VDEC_SendStream()
让海思调用hdmi接口播放视频
这里是拆包函数(目测不知有木有问题)
HI_VOID h264_rtp_unpackage(HI_U8 *bufIn, HI_S32 len) //bufin为fifo->buf去掉tcp4个字节的头剩下一个完整的rtp包,当然一个buf可能有多个rtp包
{
unsigned char recvbuf[1500];
//RTPpacket_t *p = NULL;
RTP_FIXED_HEADER * rtp_hdr = NULL;
NALU_HEADER * nalu_hdr = NULL;
FU_INDICATOR *fu_ind = NULL;
FU_HEADER *fu_hdr= NULL;
unsigned int start_code = 0x01000000;
memcpy(recvbuf,bufIn, len); //复制rtp包
//begin rtp_payload and rtp_header
if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)
{
printf("RTP_FIXED_HEADER MEMORY ERROR\n");
}
rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];
if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)
{
printf("NALU_HEADER MEMORY ERROR\n");
}
//网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。
nalu_hdr =(NALU_HEADER*)&recvbuf[12];
//////////////////////////////////////////////////////////////////////////
//开始解包
if ( nalu_hdr->TYPE == 0 || len < 12 )
{
printf("this packet is worse\n");
return;
}
else if ( nalu_hdr->TYPE > 0 && nalu_hdr->TYPE < 24) //单包
{
memcpy(Video_Stream+total_recved, &start_code, 4); //写进起始字节0x00000001
total_recved += 4;
memcpy(Video_Stream+total_recved, &recvbuf[12], len-12);
total_recved += len-12;
}
else if ( nalu_hdr->TYPE == 28) //FU-A分片包,解码顺序和传输顺序相同
{
if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)
{
printf("FU_INDICATOR MEMORY ERROR\n");
}
if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)
{
printf("FU_HEADER MEMORY ERROR\n");
}
fu_ind=(FU_INDICATOR*)&recvbuf[12]; //分片包用的是FU_INDICATOR而不是NALU_HEADER
fu_hdr=(FU_HEADER*)&recvbuf[13]; //FU_HEADER赋值
if (rtp_hdr->marker == 1) //分片包最后一个包
{
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
First++;
if((First+1) % 2 == 0 )//First 用于判断当前为第几帧
{
sem_post(&my_struct.sem_id4);
pthread_mutex_unlock(&my_struct.H_Mutex);
}
}
else if (rtp_hdr->marker == 0) //分片包 但不是最后一个包
{
if (fu_hdr->S == 1) //分片的第一个包
{
if(First == 0 || (First+1)%2 == 0 )
{
sem_wait(&my_struct.sem_id3);
pthread_mutex_lock(&my_struct.H_Mutex);
memset(Video_Stream, 0, sizeof(Video_Stream));
}
unsigned char F;
unsigned char NRI;
unsigned char TYPE;
unsigned char nh;
memcpy(Video_Stream+total_recved, &start_code, 4); //写起始字节码0x00000001
total_recved += 4;
F = fu_ind->F << 7;
NRI = fu_ind->NRI << 5;
TYPE = fu_hdr->TYPE; //应用的是FU_HEADER的TYPE
nh = F | NRI | TYPE;
//写NAL HEADER
memcpy(Video_Stream+total_recved, &nh, 1);
total_recved += 1;
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
}
else //如果不是第一个包
{
//memset(vv->videobuf, 0, 1600);
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
}
}
}
else
{
printf("this packet is worse,30-31 havenot meaning\n");
}
memset(recvbuf,0,1500);
return ;
}
我的问题:视频拨出来出现马赛克或者花屏,而且码率越大,问题越严重(有时是一个屏幕的十分之九都是马赛克,只有上方的一小块正常)。直接封装成h264文件,播放问题就没那么严重(这貌似是海思的问题)
1、框架这样写不知道有没有问题
2、细查生成的264文件,关键帧间隔对得上,没有发现丢帧。(有个奇怪的地方,文件开头的第一次关键帧全为零,或者00000001 06这一帧全为零)
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0001 65b8 0000 0b6d
2027 ffb1 c15e a37d 4639 3ec6 1a6d 358c
3、h264_rtp_unpackage()不知道是不是个bug
4、各位觉得可能的问题点,希望能帮我提出来,大家共同解决。
ps:我只是小菜一个,感谢各位前辈的指教。
先说说我的代码框架(具体如下,不足再补):
1、建立tcp socket rtsp对接ipc摄像头(已设定SO_RCVBUF=32*1024*5)
2、创建3条线程
//recv()tcp接收数据
pthread_create(&pVdecThread[1], 0, RECV, (HI_VOID *)&my_struct);
//handlestream解析rtp包,保存解析好的数据
pthread_create(&pVdecThread[2], 0, handle, NULL);
//sendstream调用海思mpp接口播放视频流
pthread_create(&pVdecThread, 0, SAMPLE_COMM_VDEC_SendStream, (HI_VOID *)&pstVdecSend);
3、创建了共有环形缓存区fifo + 共有streambuf=32*1024*5
fifo有80个节点,每个节点32*1024*5,用于每次保存线程recv()到得buf;
用信号量来判断,当有缓存区有数据就调用线程handle进行拆包
同样用信号量来判断,当h264_rtp_unpackage()从fifo取数据解析,解析好数据就保存到Video_Stream,当拼好一帧数据就调用SAMPLE_COMM_VDEC_SendStream()
让海思调用hdmi接口播放视频
这里是拆包函数(目测不知有木有问题)
HI_VOID h264_rtp_unpackage(HI_U8 *bufIn, HI_S32 len) //bufin为fifo->buf去掉tcp4个字节的头剩下一个完整的rtp包,当然一个buf可能有多个rtp包
{
unsigned char recvbuf[1500];
//RTPpacket_t *p = NULL;
RTP_FIXED_HEADER * rtp_hdr = NULL;
NALU_HEADER * nalu_hdr = NULL;
FU_INDICATOR *fu_ind = NULL;
FU_HEADER *fu_hdr= NULL;
unsigned int start_code = 0x01000000;
memcpy(recvbuf,bufIn, len); //复制rtp包
//begin rtp_payload and rtp_header
if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)
{
printf("RTP_FIXED_HEADER MEMORY ERROR\n");
}
rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];
if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)
{
printf("NALU_HEADER MEMORY ERROR\n");
}
//网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。
nalu_hdr =(NALU_HEADER*)&recvbuf[12];
//////////////////////////////////////////////////////////////////////////
//开始解包
if ( nalu_hdr->TYPE == 0 || len < 12 )
{
printf("this packet is worse\n");
return;
}
else if ( nalu_hdr->TYPE > 0 && nalu_hdr->TYPE < 24) //单包
{
memcpy(Video_Stream+total_recved, &start_code, 4); //写进起始字节0x00000001
total_recved += 4;
memcpy(Video_Stream+total_recved, &recvbuf[12], len-12);
total_recved += len-12;
}
else if ( nalu_hdr->TYPE == 28) //FU-A分片包,解码顺序和传输顺序相同
{
if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)
{
printf("FU_INDICATOR MEMORY ERROR\n");
}
if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)
{
printf("FU_HEADER MEMORY ERROR\n");
}
fu_ind=(FU_INDICATOR*)&recvbuf[12]; //分片包用的是FU_INDICATOR而不是NALU_HEADER
fu_hdr=(FU_HEADER*)&recvbuf[13]; //FU_HEADER赋值
if (rtp_hdr->marker == 1) //分片包最后一个包
{
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
First++;
if((First+1) % 2 == 0 )//First 用于判断当前为第几帧
{
sem_post(&my_struct.sem_id4);
pthread_mutex_unlock(&my_struct.H_Mutex);
}
}
else if (rtp_hdr->marker == 0) //分片包 但不是最后一个包
{
if (fu_hdr->S == 1) //分片的第一个包
{
if(First == 0 || (First+1)%2 == 0 )
{
sem_wait(&my_struct.sem_id3);
pthread_mutex_lock(&my_struct.H_Mutex);
memset(Video_Stream, 0, sizeof(Video_Stream));
}
unsigned char F;
unsigned char NRI;
unsigned char TYPE;
unsigned char nh;
memcpy(Video_Stream+total_recved, &start_code, 4); //写起始字节码0x00000001
total_recved += 4;
F = fu_ind->F << 7;
NRI = fu_ind->NRI << 5;
TYPE = fu_hdr->TYPE; //应用的是FU_HEADER的TYPE
nh = F | NRI | TYPE;
//写NAL HEADER
memcpy(Video_Stream+total_recved, &nh, 1);
total_recved += 1;
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
}
else //如果不是第一个包
{
//memset(vv->videobuf, 0, 1600);
memcpy(Video_Stream+total_recved, &recvbuf[14], len - 14);
total_recved += len - 14;
}
}
}
else
{
printf("this packet is worse,30-31 havenot meaning\n");
}
memset(recvbuf,0,1500);
return ;
}
我的问题:视频拨出来出现马赛克或者花屏,而且码率越大,问题越严重(有时是一个屏幕的十分之九都是马赛克,只有上方的一小块正常)。直接封装成h264文件,播放问题就没那么严重(这貌似是海思的问题)
1、框架这样写不知道有没有问题
2、细查生成的264文件,关键帧间隔对得上,没有发现丢帧。(有个奇怪的地方,文件开头的第一次关键帧全为零,或者00000001 06这一帧全为零)
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0001 65b8 0000 0b6d
2027 ffb1 c15e a37d 4639 3ec6 1a6d 358c
3、h264_rtp_unpackage()不知道是不是个bug
4、各位觉得可能的问题点,希望能帮我提出来,大家共同解决。
ps:我只是小菜一个,感谢各位前辈的指教。
我来回答
回答20个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2014-10-16 20:13:01
-
2013-05-21 18:27:26
-
2016-04-27 10:59:59
-
2017-12-19 13:34:58
-
2013-06-07 10:59:06
-
2019-04-03 17:37:59
-
2019-04-03 10:40:55
-
2013-09-12 11:00:06
-
2020-03-25 15:57:02
-
2016-10-25 10:44:09
-
2018-07-25 11:01:21
-
2017-04-07 15:41:48
-
2019-04-03 10:47:31
-
2015-01-12 11:22:10
-
2018-12-26 21:22:40
-
2015-05-25 21:07:40
-
2015-05-25 21:11:56
-
2016-04-19 21:49:52
-
2014-11-12 16:35:33
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5SS928的emmc有32GB,bootargs设置使用16GB,但是为啥能用的只有rootfs的大小
-
33SS928怎样烧写ubuntu系统
-
10ToolPlatform下载rootfs提示网络失败
-
10谁有GK7205V500的SDK
-
5Hi3516CV610 烧录不进去
-
10Hi3559AV100 芯片硬解码h265编码格式的视频时出现视频播放错误,解码错误信息 s32PackErr:码流有错
-
5海思SS928 / SD3403的sample_venc.c摄像头编码Demo中,采集到的摄像头的YUV数据在哪个相关的函数中?
-
5海鸥派openEuler无法启动网卡,连接WIFI存在问题
-
66有没有ISP相关的巨佬帮忙看看SS928对接IMX347的图像问题
-
50求助hi3559与FPGA通过SLVS-EC接口对接问题
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认