视频监控平台-GB28181-2016语音对讲功能

很多人在问我,语音对讲是怎么流程, 实现了怎么去测试,语音对讲是在2014版本提出来的,我这里详细写一遍国标28181-2016语音对讲的功能介绍。(如需交流可联系QQ:123011785)
提前先把GB28181检测需要注意的事项说一下:
1、语音对讲其实主要的是音频流的输入输出, 输入设备类型是136,输出设备类型是137
2、目前检测的时候,海康摄像机是定制的检测版本有固定的137类型id,一般海康摄像机是没有配置音频输出通道的,需要自己通过SDK模拟一个音频输出设备或则让海康提供 28181检测的固件版本。
3、检测时候需要用笔记本电脑模拟一个136音频输入的设备,一般和客户端绑定一起(或则后台服务器配置相应的id和客户端绑定一起)
4、音频输入源一般是采用笔记本采集的音频信号,音频采集代码后面的博客提供。
下面看一下语音对讲的流程:
其中, 信令 1 、
2 、 3 、 4 为语音广播通知、 语音广播应答消息流程; 信令 5 、 1 2 、 1 3 、 1 4 、 1 5 、 1 6 为 S I P 服务
器接收到客户端的呼叫请求通过 B 2 B UA 代理方式建立语音流接收者与媒体服务器之间的媒体流信令
过程, 信令 6~1 1 为 S I P 服务器通过三方呼叫控制建立媒体服务器与语音流发送者之间的媒体流信令
过程, 信令 1 7~2 0 为 S I P 服务器断开语音流接收者与媒体服务器之间的媒体流信令过程, 信令 2 1~2 4
6 4
G B / T2 8 1 8 1 — 2 0 1 6
为 S I P 服务器断开媒体服务器与语音流发送者之间的媒体流信令过程。
命令流程描述如下:
a ) 1 : S I P 服务器向语音流接收者发送语音广播通知消息, 消息中通过 T o 头域标明作为目的地址
的语音流接收者 I D , 消息采用 M e s s a g e 方法携带。
b ) 2 : 语音流接收者收到语音广播通知消息后, 向 S I P 服务器发送 2 0 0OK 响应。
c ) 3 : 语音流接收者向 S I P 服务器发送语音广播应答消息, 消息中通过 T o 头域标明作为目的地
址的 S I P 服务器 I D , 消息采用 M e s s a g e 方法携带。
d ) 4 : S I P 服务器收到语音广播应答消息后, 向语音流接收者发送 2 0 0OK 响应。
e ) 5 : 语音流接收者向 S I P 服务器发送 I n v i t e 消息, 消息中通过 T o 头域标明作为目的地址的语音
流发送者 I D , 消息头域中携带 S u b j e c t 字段, 表明请求的语音流发送者 I D 、 发送方媒体流序列
号、 语音流接收者 I D 、 接收方媒体流序列号等参数, S D P 消息体中 s 字段为“ P l a y ” 代表实时点
播, m 字段中媒体参数标识为“
a u d i o ” 表示请求语音媒体流。
f ) 6 : S I P 服务器收到 I n v i t e 请求后, 通过三方呼叫控制建立媒体服务器和语音流发送者之间的
媒体连接。向媒体服务器发送 I n v i t e 消息, 此消息不携带 S D P 消息体。
g ) 7 : 媒体服务器收到 S I P 服务器的 I n v i t e 请求后, 回复 2 0 0OK 响应, 携带 S D P 消息体, 消息体
中描述了媒体服务器接收媒体流的 I P 、 端口、 媒体格式等内容。
h ) 8 : S I P 服务器收到媒体服务器返回的 2 0 0OK 响应后, 向语音流发送者发送 I n v i t e 请求, 消息
中通过 T o 头域标明作为目的地址的语音流发送者 I D , 消息头域中携带 S u b j e c t 字段, 表明请
求的语音流发送者 I D 、 发送方媒体流序列号、 语音流接收者 I D 、 接收方媒体流序列号等参数,
请求中携带消息 7 中媒体服务器回复的 2 0 0OK 响应消息体, s 字段为“ P l a y ” 代表实时点播,
m 字段中媒体参数标识为“ a u d i o ” 表示请求语音媒体流, 增加 y 字段描述 S S R C 值, f 字段描述
媒体参数。
i ) 9 : 语音流发送者收到 S I P 服务器的 I n v i t e 请求后, 回复 2 0 0OK 响应, 携带 S D P 消息体, 消息
体中描述了媒体流发送者发送媒体流的 I P 、 端口、 媒体格式、 S S R C 字段等内容, s 字段为

P l a y ” 代表实时点播,
m 字段中媒体参数标识为“ a u d i o ” 表示请求语音媒体流。
j ) 1 0 : S I P 服务器收到语音流发送者返回的 2 0 0OK 响应后, 向媒体服务器发送 A C K 请求, 请求
中携带消息 9 中语音流发送者回复的 2 0 0OK 响应消息体, 完成与媒体服务器的 I n v i t e 会话
建立过程。
k ) 1 1 : S I P 服务器收到语音流发送者返回的 2 0 0OK 响应后, 向语音流发送者发送 A C K 请求, 请
求中不携带消息体, 完成与语音流发送者的 I n v i t e 会话建立过程。
l ) 1 2 : 完成三方呼叫控制后, S I P 服务器通过 B 2 B UA 代理方式建立语音流接收者和媒体服务器
之间的媒体连接。在消息 5 中增加 S S R C 值, 转发给媒体服务器。
m ) 1 3 : 媒体服务器收到 I n v i t e 请求, 回复 2 0 0OK 响应, 携带 S D P 消息体, 消息体中描述了媒体服
务器发送媒体流的 I P 、 端口、 媒体格式、 S S R C 值等内容,
s 字段为“ P l a y ” 代表实时点播, m 字段
中媒体参数标识为“
a u d i o ” 表示请求语音媒体流。
n ) 1 4 : S I P 服务器将消息 1 3 转发给语音流接收者。
o ) 1 5 : 语音流接收者收到 2 0 0OK 响应后, 回复 A C K 消息, 完成与 S I P 服务器的 I n v i t e 会话建立
过程。
p ) 1 6 : S I P 服务器将消息 1 5 转发给媒体服务器, 完成与媒体服务器的 I n v i t e 会话建立过程。
q ) 1 7 : S I P 服务器向语音流接收者发送 B Y E 消息, 断开消息 5 、 1 4 、 1 5 建立的 I n v i t e 会话。
r ) 1 8 : 语音流接收者收到 B Y E 消息后回复 2 0 0OK 响应, 会话断开。
s ) 1 9 : S I P 服务器向媒体服务器发送 B Y E 消息, 断开消息 1 2 、 1 3 、 1 6 建立的同媒体服务器的
I n v i t e 会话。
上面是28181协议里面规定的流程,直接照搬过来,不管怎么实现语音对讲也要根据流程走。
下面我把抓包详情粘贴下:
MESSAGE sip:34020000001370000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-1047e076-A8X5JYC1
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=CN2Ei3Vu
To: <sip:34020000001370000001@192.168.1.81:5060>
Call-ID: 5c0d74ae-4352-df11-aa52-56a46c795625@192.168.1.93
CSeq: 55 MESSAGE
Contact: <sip:192.168.1.93:5060>
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: iVMS 1.0
Content-Length:   173<?xml version="1.0"?>
<Notify>
<CmdType>Broadcast</CmdType>
<SN>20</SN>
<SourceID>64000000001360000001</SourceID>
<TargetID>34020000001370000001</TargetID>
</Notify>
SIP/2.0 200 OK
To: <sip:34020000001370000001@192.168.1.81:5060>;tag=75600014_53173353_c376baa4-b5f9-4f2a-a739-653dc3299ae1
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-1047e076-A8X5JYC1;received=192.168.1.93
CSeq: 55 MESSAGE
Call-ID: 5c0d74ae-4352-df11-aa52-56a46c795625@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=CN2Ei3Vu
Content-Length: 0MESSAGE sip:64000000002000000001@6400000000 SIP/2.0
Call-ID: 2cf6a25ea9b4f63ca255f60faefb584d@0.0.0.0
CSeq: 1 MESSAGE
From: <sip:34020000002000000001@3402000000>;tag=78679367_53173353_5e822bd3-744e-4d50-a7ae-3dcb31308ad5
To: <sip:64000000002000000001@6400000000>
Max-Forwards: 70
Content-Encoding: GB2312
Content-Type: Application/MANSCDP+xml
Route: <sip:64000000002000000001@192.168.1.93:5060;lr>
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK5e822bd3-744e-4d50-a7ae-3dcb31308ad5_53173353_28675579067886
Content-Length: 147<?xml version="1.0"?>
<Response>
<CmdType>Broadcast</CmdType>
<SN>20</SN>
<DeviceID>34020000001370000001</DeviceID>
<Result>OK</Result>
</Response>SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK5e822bd3-744e-4d50-a7ae-3dcb31308ad5_53173353_28675579067886
From: <sip:34020000002000000001@3402000000>;tag=78679367_53173353_5e822bd3-744e-4d50-a7ae-3dcb31308ad5
To: <sip:64000000002000000001@6400000000>;tag=nVa5oJ2n
Call-ID: 2cf6a25ea9b4f63ca255f60faefb584d@0.0.0.0
CSeq: 1 MESSAGE
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Content-Length: 0INVITE sip:64000000001360000001@6400000000 SIP/2.0
Call-ID: a0ce1d2417f6cb64571120b90c2243c1@0.0.0.0
CSeq: 1 INVITE
From: <sip:34020000002000000001@3402000000>;tag=84133916_53173353_4063c926-989f-4a9a-af9c-867f8219c6ab
To: <sip:64000000001360000001@6400000000>
Max-Forwards: 70
Contact: "34020000002000000001" <sip:192.168.1.81:5060>
Subject: 64000000001360000001:0-4-0,34020000002000000001:1
Content-Type: application/sdp
Route: <sip:64000000001360000001@192.168.1.93:5060;lr>
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK4063c926-989f-4a9a-af9c-867f8219c6ab_53173353_28675585450209
Content-Length: 171v=0
o=64010000002020000001 0 0 IN IP4 192.168.1.81
s=Play
c=IN IP4 192.168.1.81
t=0 0
m=audio 8000 RTP/AVP 96
a=recvonly
a=rtpmap:96 PS/90000
y=0100000001
f=v/a/1/8/1
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK4063c926-989f-4a9a-af9c-867f8219c6ab_53173353_28675585450209
From: <sip:34020000002000000001@3402000000>;tag=84133916_53173353_4063c926-989f-4a9a-af9c-867f8219c6ab
To: <sip:64000000001360000001@6400000000>
Call-ID: a0ce1d2417f6cb64571120b90c2243c1@0.0.0.0
CSeq: 1 INVITE
Content-Length: 0SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK4063c926-989f-4a9a-af9c-867f8219c6ab_53173353_28675585450209
Record-Route: <sip:64000000002000000001@192.168.1.93:5060;lr>
From: <sip:34020000002000000001@3402000000>;tag=84133916_53173353_4063c926-989f-4a9a-af9c-867f8219c6ab
To: <sip:64000000001360000001@6400000000>;tag=Wn1J54GK
Call-ID: a0ce1d2417f6cb64571120b90c2243c1@0.0.0.0
CSeq: 1 INVITE
Contact: <sip:64000000001360000001@192.168.1.93:5060>
Content-Type: application/sdp
Content-Length:   180v=0
o=64000000001360000001 0 0 IN IP4 192.168.1.93
s=Play
c=IN IP4 192.168.1.93
t=0 0
m=audio 20104 RTP/AVP 8
a=sendonly
a=rtpmap:8 PS/90000
y=0100000001
f=v/a/1/8/1
ACK sip:64000000001360000001@192.168.1.93:5060 SIP/2.0
Call-ID: a0ce1d2417f6cb64571120b90c2243c1@0.0.0.0
CSeq: 1 ACK
From: <sip:34020000002000000001@3402000000>;tag=84133916_53173353_4063c926-989f-4a9a-af9c-867f8219c6ab
To: <sip:64000000001360000001@6400000000>;tag=Wn1J54GK
Max-Forwards: 70
Route: <sip:64000000002000000001@192.168.1.93:5060;lr>
Via: SIP/2.0/UDP 192.168.1.81:5060;branch=z9hG4bK4063c926-989f-4a9a-af9c-867f8219c6ab_53173353_28675725931057
Content-Length: 0

流程抓包截图:

音频流采用的G711格式:
下面粘贴音频采集代码的片段:
#pragma once
#include <mmsystem.h>
#include <dsound.h>
#include <memory.h>
#include <list>
#include <process.h>
#include "WaveHeader.h"
#include <math.h>
#include "SoundRecord.h"
#include "g711.h"class CDSRecord : public CSoundRecord
{
public:CDSRecord(ISoundNotify* pNotify);~CDSRecord(void);LPDIRECTSOUNDCAPTURE       m_pDSCapture;LPDIRECTSOUNDCAPTUREBUFFER m_pDSBCapture;LPDIRECTSOUNDNOTIFY        m_pDSNotify;HINSTANCE                  m_hInst;bool                       m_bRecording;WAVEFORMATEX               m_wfxInput;DSBPOSITIONNOTIFY          m_aPosNotify[4];  HANDLE                     m_hNotificationEvent; HANDLE                     m_hStopThreadEvent;BOOL                       m_abInputFormatSupported[20];DWORD                      m_dwCaptureBufferSize;DWORD                      m_dwNextCaptureOffset;DWORD                      m_dwNotifySize;HANDLE                     m_hThread;WAVEFORMATEX WaveFormat;float bSampleReal[1024];float bSampleImg[1024];bool InitDS(void);bool SaveDataToFile(LPCTSTR m_pathname);bool ReadCaptureBuffer(void);bool StarRecord(void);bool StopRecord(void);std::list<DWORD> SizeList;std::list<void*> BufList;CWaveHeader WaveHeader;bool Sampling(void);void FFT(float xreal [], float ximag [], int n);//通知接口ISoundNotify* m_pISoundNotify;// 销毁void Destroy(void);// 开始bool Start(void);// 结束bool Stop(void);protected:void bitrp(float xreal [], float ximag [], int n);void IFFT (float xreal [], float ximag [], int n);
};
#include "StdAfx.h"
#include "DSRecord.h"UINT ReceiveDataThread(void* pParam);CDSRecord::CDSRecord(ISoundNotify* pNotify)
:m_pDSCapture(0)
,m_pDSBCapture(0)
,m_pDSNotify(0)
,m_bRecording(false)
{ZeroMemory(&bSampleReal,1024);ZeroMemory(&bSampleImg,1024);m_pISoundNotify = pNotify;}CDSRecord::~CDSRecord(void)
{while(!BufList.empty()){free(BufList.front());BufList.pop_front();}
}bool CDSRecord::InitDS(void)
{HRESULT hr;// 创建DSC对象if( FAILED( hr = DirectSoundCaptureCreate(NULL, &m_pDSCapture, NULL ) ) ){_WRITE_LOG( LOG_LEVEL_WARNING, "创建DSC对象失败");return false;}//初始化录音格式----------------------------------------------WaveFormat.wFormatTag = WAVE_FORMAT_PCM;WaveFormat.nSamplesPerSec = 8000;//G.711采样频率WaveFormat.wBitsPerSample = 16; //16位WaveFormat.nChannels = 2;WaveFormat.nBlockAlign =  WaveFormat.nChannels * (  WaveFormat.wBitsPerSample / 8 );WaveFormat.nAvgBytesPerSec =  WaveFormat.nBlockAlign *  WaveFormat.nSamplesPerSec;//初始化buffer// Create the capture bufferm_dwCaptureBufferSize = WaveFormat.nAvgBytesPerSec / 20*8;   //设定8秒的缓冲区;m_dwNextCaptureOffset=0;DSCBUFFERDESC dscbd;ZeroMemory( &dscbd, sizeof(dscbd) );dscbd.dwSize        = sizeof(dscbd);dscbd.dwBufferBytes = m_dwCaptureBufferSize;dscbd.lpwfxFormat   = &WaveFormat; // Set the format during creatationif( FAILED( hr = m_pDSCapture->CreateCaptureBuffer(&dscbd, &m_pDSBCapture, NULL ) ) ){_WRITE_LOG(LOG_LEVEL_WARNING,"创建缓冲区失败");return false;}//初始化消息// Create a notification event, for when the sound stops playingif( FAILED( hr = m_pDSBCapture->QueryInterface( IID_IDirectSoundNotify,(VOID**)&m_pDSNotify ) ) ){_WRITE_LOG(LOG_LEVEL_WARNING,"创建消息界面失败");return false;}// Set the notification sizem_dwNotifySize =m_dwCaptureBufferSize/4;   //到文件尾时m_dwNotifySize -=m_dwNotifySize %WaveFormat.nBlockAlign; // Setup the notification positionsm_hNotificationEvent = CreateEvent( NULL, FALSE, FALSE, NULL );m_hStopThreadEvent   = CreateEvent(NULL,FALSE,FALSE, NULL);ZeroMemory( &m_aPosNotify, sizeof(DSBPOSITIONNOTIFY) * 4 );for(int i=0;i<4;i++){m_aPosNotify[i].dwOffset =  m_dwNotifySize*i%m_dwCaptureBufferSize;m_aPosNotify[i].hEventNotify = m_hNotificationEvent; }// Tell DirectSound when to notify us. the notification will come in the from // of signaled events that are handled in WinMain()if( FAILED( hr =m_pDSNotify->SetNotificationPositions(2, m_aPosNotify) ) ){_WRITE_LOG(LOG_LEVEL_WARNING,"设置消息位置失败");return false;}return true;
}bool CDSRecord::ReadCaptureBuffer(void)
{if(!m_pDSBCapture|!m_bRecording)return false;HRESULT hr;VOID*   pbCaptureData    = NULL;DWORD   dwCaptureLength=0;VOID*   pbCaptureData2   = NULL;DWORD   dwCaptureLength2=0;DWORD   dwReadPos;DWORD   dwCapturePos;LONG    lLockSize;if( FAILED( hr = m_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) ){this->m_bRecording=false;_WRITE_LOG(LOG_LEVEL_WARNING,"读取当前指针位置错误");}lLockSize = dwReadPos - m_dwNextCaptureOffset;if( lLockSize < 0 )lLockSize += m_dwCaptureBufferSize;if( lLockSize == 0 )return false;// Lock the capture buffer downif( FAILED( hr = m_pDSBCapture->Lock( m_dwNextCaptureOffset, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L ) ) )return false;if(dwCaptureLength+dwCaptureLength2!=lLockSize)_WRITE_LOG(LOG_LEVEL_WARNING,"error");// Write the data into listWaveHeader.dwRIFFLen+=lLockSize;WaveHeader.dwdataLen+=lLockSize;void* TmpBuf=malloc(lLockSize);//BufList.push_back(TmpBuf);//SizeList.push_back(lLockSize);memcpy(TmpBuf,pbCaptureData,dwCaptureLength);if( pbCaptureData2){memcpy((BYTE*)TmpBuf+dwCaptureLength,pbCaptureData2,dwCaptureLength2);}int G711Size = 0;unsigned char* G711Buf = (unsigned char*)malloc(lLockSize/2);for(int i = 0;i < lLockSize/2;i++){int  out_size = 1;//8位G711unsigned char g711_val = 0;g711_val = linear2alaw(*((short*)TmpBuf + i));memcpy(G711Buf + G711Size,&g711_val,out_size);G711Size += out_size;}
#if 0static FILE* m_myfVideo = NULL;if (m_myfVideo == NULL){m_myfVideo = fopen("c:\\audio.pcm",  "ab+");}fwrite(G711Buf,1,G711Size,m_myfVideo);
#endif  m_pISoundNotify->OnGetAudioData(G711Buf,G711Size);// Unlock the capture bufferm_pDSBCapture->Unlock( pbCaptureData,  dwCaptureLength, pbCaptureData2, dwCaptureLength2 );//让m_dwNextCaptureOffset向前移动到读指针处m_dwNextCaptureOffset+=lLockSize;m_dwNextCaptureOffset=m_dwNextCaptureOffset% m_dwCaptureBufferSize;free(TmpBuf);free(G711Buf);return true;
}bool CDSRecord::Sampling(void)
{if(!m_pDSBCapture|!m_bRecording )return false;HRESULT hr;VOID*   pbCaptureData    = NULL;DWORD   dwCaptureLength=0;VOID*   pbCaptureData2   = NULL;DWORD   dwCaptureLength2=0;DWORD   dwReadPos;DWORD   dwCapturePos;LONG    lLockSize;DWORD dwStartPos;if( FAILED( hr = m_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) ){this->m_bRecording=false;_WRITE_LOG(LOG_LEVEL_WARNING,"读取当前指针位置错误");}lLockSize = 1024;dwStartPos=dwReadPos-lLockSize;if(dwStartPos<0)dwStartPos+=lLockSize;// Lock the capture buffer downif( FAILED( hr = m_pDSBCapture->Lock( dwStartPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L ) ) )return false;for(DWORD i=0;i<dwCaptureLength;i++){float pPos=*((BYTE*)pbCaptureData+i);this->bSampleReal[i]=pPos/255;this->bSampleImg[i]=0;}if( pbCaptureData2){for(DWORD i=0;i<dwCaptureLength2;i++){BYTE* pPos=(BYTE*)pbCaptureData2+i;this->bSampleReal[dwCaptureLength+i]=(float)*pPos/255;this->bSampleImg[i]=0;}}// Unlock the capture bufferm_pDSBCapture->Unlock( pbCaptureData,  dwCaptureLength, pbCaptureData2, dwCaptureLength2 );return true;
}UINT ReceiveDataThread(void* pParam)
{CDSRecord *pApp=(CDSRecord*)pParam;HANDLE hArray[2]={pApp->m_hNotificationEvent,pApp->m_hStopThreadEvent};DWORD EventResult;DWORD HandleNumber=sizeof(hArray)/sizeof(HANDLE);while(pApp->m_bRecording){EventResult = WaitForMultipleObjects(HandleNumber,hArray,FALSE,INFINITE);if(WAIT_OBJECT_0+1 == EventResult)break;if(WAIT_OBJECT_0 == EventResult){pApp->ReadCaptureBuffer();ResetEvent(pApp->m_hNotificationEvent);}}return 0;
}bool CDSRecord::StarRecord(void)
{if(!InitDS())return false;if( FAILED(m_pDSBCapture->Start( DSCBSTART_LOOPING ) ) ){_WRITE_LOG(LOG_LEVEL_WARNING,"开始录音失败");return false;}unsigned int ThrdAddr;m_hThread  = (HANDLE) _beginthreadex(NULL, 0, (unsigned int (__stdcall *)(void *))ReceiveDataThread,(void *)(this),//NULL, 0, &ThrdAddr);this->m_bRecording=true;return true;
}bool CDSRecord::StopRecord(void)
{if(m_pDSBCapture == 0){return false;}if( FAILED(m_pDSBCapture->Stop() ) ){_WRITE_LOG(LOG_LEVEL_WARNING,"停止录音失败");return false;}SetEvent(m_hStopThreadEvent);this->m_bRecording=false;return true;
}bool CDSRecord::SaveDataToFile(LPCTSTR m_pathname)
{//m_pDSBCapture->GetFormat(&WaveHeader.WaveFormat, sizeof(WAVEFORMATEX),NULL);//if(m_pathname)//{// CFile file(m_pathname,CFile::modeWrite|CFile::modeCreate);//    file.Write(&WaveHeader,46);//   for(;!BufList.empty();)//   {//     void* pBuf=BufList.front();//      file.Write(pBuf,SizeList.front());//        BufList.pop_front();//      SizeList.pop_front();//     free(pBuf);//   }// file.Flush();// file.Close();//}//else//{// _WRITE_LOG(LOG_LEVEL_WARNING,"请选择保存路径");//}return true;
}inline void swap (float &a, float &b)
{float t;t = a;a = b;b = t;
}void CDSRecord::bitrp(float xreal [], float ximag [], int n)
{// 位反转置换 Bit-reversal Permutationint i, j, a, b, p;for (i = 1, p = 0; i < n; i *= 2){p ++;}for (i = 0; i < n; i ++){a = i;b = 0;for (j = 0; j < p; j ++){b = (b << 1) + (a & 1);    // b = b * 2 + a % 2;a >>= 1;        // a = a / 2;}if ( b > i){swap (xreal [i], xreal [b]);swap (ximag [i], ximag [b]);}}
}void  CDSRecord::FFT(float xreal [], float ximag [], int n)
{const int N = 1024;const float PI = 3.1416;// 快速傅立叶变换,将复数 x 变换后仍保存在 x 中,xreal, ximag 分别是 x 的实部和虚部float* wreal=new float  [n / 2];float* wimag=new float [n / 2];float treal, timag, ureal, uimag, arg;int m, k, j, t, index1, index2;bitrp (xreal, ximag, n);// 计算 1 的前 n / 2 个 n 次方根的共轭复数 W'j = wreal [j] + i * wimag [j] , j = 0, 1,  , n / 2 - 1arg = - 2 * PI / n;treal = cos (arg);timag = sin (arg);wreal [0] = 1.0;wimag [0] = 0.0;for (j = 1; j < n / 2; j ++){wreal [j] = wreal [j - 1] * treal - wimag [j - 1] * timag;wimag [j] = wreal [j - 1] * timag + wimag [j - 1] * treal;}for (m = 2; m <= n; m *= 2){for (k = 0; k < n; k += m){for (j = 0; j < m / 2; j ++){index1 = k + j;index2 = index1 + m / 2;t = n * j / m;    // 旋转因子 w 的实部在 wreal [] 中的下标为 ttreal = wreal [t] * xreal [index2] - wimag [t] * ximag [index2];timag = wreal [t] * ximag [index2] + wimag [t] * xreal [index2];ureal = xreal [index1];uimag = ximag [index1];xreal [index1] = ureal + treal;ximag [index1] = uimag + timag;xreal [index2] = ureal - treal;ximag [index2] = uimag - timag;}}}delete  []wreal;delete []wimag;
}void  CDSRecord::IFFT (float xreal [], float ximag [], int n)
{const float PI = 3.1416;// 快速傅立叶逆变换float * wreal=new float [n / 2];float * wimag=new float  [n / 2];float treal, timag, ureal, uimag, arg;int m, k, j, t, index1, index2;bitrp (xreal, ximag, n);// 计算 1 的前 n / 2 个 n 次方根 Wj = wreal [j] + i * wimag [j] , j = 0, 1,  , n / 2 - 1arg = 2 * PI / n;treal = cos (arg);timag = sin (arg);wreal [0] = 1.0;wimag [0] = 0.0;for (j = 1; j < n / 2; j ++){wreal [j] = wreal [j - 1] * treal - wimag [j - 1] * timag;wimag [j] = wreal [j - 1] * timag + wimag [j - 1] * treal;}for (m = 2; m <= n; m *= 2){for (k = 0; k < n; k += m){for (j = 0; j < m / 2; j ++){index1 = k + j;index2 = index1 + m / 2;t = n * j / m;    // 旋转因子 w 的实部在 wreal [] 中的下标为 ttreal = wreal [t] * xreal [index2] - wimag [t] * ximag [index2];timag = wreal [t] * ximag [index2] + wimag [t] * xreal [index2];ureal = xreal [index1];uimag = ximag [index1];xreal [index1] = ureal + treal;ximag [index1] = uimag + timag;xreal [index2] = ureal - treal;ximag [index2] = uimag - timag;}}}for (j=0; j < n; j ++){xreal [j] /= n;ximag [j] /= n;}delete []wreal;
delete []wimag;
}bool CDSRecord::Start(void)
{return StarRecord();
}bool CDSRecord::Stop(void)
{return StopRecord();
}void CDSRecord::Destroy(void)
{Stop();delete this;return;
}

视频监控平台-GB28181-语音对讲功能相关推荐

  1. 视频监控平台GB28181:媒体流保活机制

    前言 目前实际项目对接遇见很多平台级联过程中,视频流有类似rtsp一样的rtcp保活机制,随翻看国标GB28181-2016协议文档,查阅相关说明,现分享如下. 协议原文 平台.设备媒体流保活机制 贴 ...

  2. 视频监控平台GB28181:实时视音频点播

    实时视音频点播基本要求 -实时视音频点播的SIP消息应通过本域或其它域的SIP服务器进行路由.转发,目标设备的实时视音频流宜通过本域内的媒体服务器进行转发. -实时视音频点播采用SIP协议(RFC 3 ...

  3. 语音对讲功能在车载监控系统中的应用意义

    随着近年来智能交通运输行业精细化管理需求的加剧,政府监管部门对商用车的安全监管也逐渐升级,车载监控系统/平台作为可实现智能化.集中化监管车辆营运的有效手段,也成为当前市场的香饽饽. 车载监控系统/平台 ...

  4. 浅析语音对讲功能在车载监控系统中的应用意义

    随着近年来智能交通运输行业精细化管理需求的加剧,政府监管部门对商用车的安全监管也逐渐升级,车载监控系统/平台作为可实现智能化.集中化监管车辆营运的有效手段,也成为当前市场的香饽饽. 车载监控系统/平台 ...

  5. 国标GB28181协议网络摄像头直播视频平台EasyGBS如何实现语音对讲功能?

    在当下这个智能大热的时代,人工智能技术在持续升温,越来越多电子产品开始融入AI技术,为这些产品提供了新的发展方向.而作为安防摄像头无插件直播应用,智能摄像机自然也不会错过与人工智能技术结合的机会,比如 ...

  6. 使用视频监控摄像头的语音对讲功能,在视频平台,配置符合GB28181协议国标视频对讲

    使用视频监控摄像头的语音对讲功能,在视频平台,配置符合GB28181协议国标视频对讲的设置注意事项: (1)打开伴音和混音设置: (2)音频传输设置要与视频平台对接一样,在选择GB28181协议下,音 ...

  7. 语音对讲功能在GB28181协议国标视频云服务EasyGBS中的项目应用

    在监控行业的语音对讲,指的是监控设备与电脑.手机APP.平台软件之间进行语音交流.例如在手机上预览监控画面时,可以同步跟画面中的人物进行语音对话.目前语音对讲功能已经广泛应用于我们日常监控环境中.需要 ...

  8. GB28181系列笔记-语音对讲功能

    GB28181系列笔记-注册与保活 GB28181系列笔记-设备目录查询 GB28181系列笔记-实时流请求 GB28181系列笔记-历史流查询与请求 GB28181系列笔记-语音对讲功能 GB281 ...

  9. RTSP/RTMP/GB28181协议视频监控平台搭建之国网B接口协议介绍

    我们知道TSINGSEE青犀视频全线产品对应了不同的视频协议,比如EasyNVR就是支持RTSP协议的视频平台,EasyDSS是支持RTMP协议的视频平台,EasyGBS是支持GB28181协议的视频 ...

最新文章

  1. Docker基本原理概述
  2. java 最小化 api_Java的API设计实践
  3. 被忽视的Web安全漏洞:如何识别和解决?
  4. GLUT库与GLAUX库
  5. linux端口对外开放
  6. ABAP和Go语言的初始化操作, Kubernetes的Init Container
  7. 一个长方体玻璃容器从里面量长宽_泰来包装分享:如何设计钢边箱里面中型木包装箱...
  8. azure linux 多磁盘 lvm,EVE-NG扩展磁盘空间(扩展LVM卷)
  9. Codeforces Round #207 (Div. 1) B. Xenia and Hamming(gcd的运用)
  10. 编程之美-程序理解和时间分析
  11. win10服务器显示图标,Win10专业版桌面图标消失的三种情况及相应解决方法
  12. c语言 界面编程 毕业设计,基于c语言的毕业设计.docx
  13. 2021-2027全球与中国陶瓷基板市场现状及未来发展趋势
  14. java毕业设计——基于java+AngularJS+jsp的配件营销系统设计与实现(毕业论文+程序源码)——配件营销系统
  15. 深圳小汽车车牌竞拍价格预测
  16. Thinking in Java---从哲学家就餐问题看死锁现象
  17. 基于原生JS项目使用Vue3 + Surely Vue Table组件
  18. Unity 3D PC平台发布|| Unity 3D Web 平台发布||Unity 3D Android平台发布
  19. 西门子S7-200 PLC下载
  20. 11_FreeRTOS时间片调度实验

热门文章

  1. Mac答疑「7」超详细mac新手教程-Mac界面篇
  2. macos系统升级到big sur以后safari浏览器崩溃怎么办?
  3. 京东11.11:商品搜索系统架构设计解密
  4. 物联网卡零售应用的真实案例
  5. ps如何把自己的图与样机结合_如何利用PS制作贴图样机那
  6. 运行 dist 打包文件:简单得很!!!
  7. 基于Patachmatch的stereo matching笔记(三):《PatchmatchNet》
  8. Node.js 在微医的应用场景及实践
  9. 最新年龄估计综述(Deep learning approach for facial age classification: a survey of the state of the art)
  10. 2021年计算机类考研人数,2021年考研79所院校报考人数汇总