2013-01-04 33 views
1

对不起,我的英语说得不好。如何发送/接收RTP音频流(C++)?

我做了两个项目(QT,C++,mingw32)。

它是使用RTP发送/接收音频流(ortp-0.20.0)。

但是,收到的声音是失真的。 (输出声音很渺茫)

任何人都可以帮忙吗?

RTPSend.cpp

#include <ortp/ortp.h> // ortp-0.20.0 

RtpSession *session; 
unsigned char buffer[160]; 

#include <windows.h> 
#include <stdio.h> 
#include <iostream> 
using namespace std; 

#define BS 8000 
int sampleRate = 8000; // 8000, 11025, 16000, 22050, 24000, 32000, 44100 
int NUMPTS = sampleRate * 10; // 10 seconds 
short int waveIn[BS]; 
HWAVEIN hWaveIn; 
WAVEHDR WaveInHdr; 
MMRESULT result; 
WAVEFORMATEX pFormat; 

uint32_t user_ts = 0; 


void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) 
{ 
    WAVEHDR *pHdr=NULL; 
    WAVEHDR pHdr2; 
    switch(uMsg) 
    { 
     case WIM_CLOSE: 
      cout << "waveInProc()... WIM_CLOSE" << endl; 
      break; 

     case WIM_DATA: 
      { 
       pHdr = (WAVEHDR *)dwParam1; 
       pHdr2.lpData = (LPSTR)pHdr->lpData; 
       pHdr2.dwBufferLength = pHdr->dwBufferLength; 
       pHdr2.dwBytesRecorded = pHdr->dwBytesRecorded; 
       pHdr2.dwUser = 0; 
       pHdr2.dwFlags = 0; 
       pHdr2.dwLoops = 0; 

       cout << "waveInProc()... WIM_DATA : " << "pHdr->dwBufferLength:" << pHdr->dwBufferLength << " pHdr->dwBytesRecorded:" << pHdr->dwBytesRecorded<< endl; 

       int len = pHdr->dwBytesRecorded; 
       for(int i=0; i<len;) { 
        int length = 160; 
        if(len-i < 160) length=len-i; 
        memcpy(buffer, pHdr->lpData+i, length); 
        rtp_session_send_with_ts(session, buffer, length, user_ts); 
        user_ts+=160; 
        i+=length; 
       } 

       waveInPrepareHeader(hwi, pHdr, sizeof(WAVEHDR)); 
       waveInAddBuffer(hwi, pHdr, sizeof(WAVEHDR)); 

      } 
      break; 

     case WIM_OPEN: 
      cout << "waveInProc()... WIM_OPEN" << endl; 
      break; 

     default: 
      break; 
    } 
} 

int main(int argv, char **args) 
{ 
    ortp_init(); 
    ortp_scheduler_init(); 
    ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR); 
    session=rtp_session_new(RTP_SESSION_SENDONLY); 

    rtp_session_set_scheduling_mode(session,1); 
    rtp_session_set_blocking_mode(session,1); 
    rtp_session_set_connected_mode(session,TRUE); 
    rtp_session_set_remote_addr(session,"192.168.0.181",61610); 
    rtp_session_set_payload_type(session,0); 


    pFormat.wFormatTag = WAVE_FORMAT_PCM; 
    pFormat.nChannels = 1; 
    pFormat.nSamplesPerSec = sampleRate; 
    pFormat.nAvgBytesPerSec = 2 * sampleRate; 
    pFormat.nBlockAlign = 2; 
    pFormat.wBitsPerSample = 16; 
    pFormat.cbSize = 0; 

    result = waveInOpen(&hWaveIn, WAVE_MAPPER, &pFormat, (DWORD_PTR)waveInProc, NULL, CALLBACK_FUNCTION); 

    if(result) { 
     cout << "Failed to open waveform input device." << endl; 
     return -1; 
    } 

    WaveInHdr.lpData = (LPSTR)waveIn; 
    WaveInHdr.dwBufferLength = BS; 
    WaveInHdr.dwBytesRecorded = 0; 
    WaveInHdr.dwUser = 0; 
    WaveInHdr.dwFlags = 0; 
    WaveInHdr.dwLoops = 0; 
    waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); 

    result = waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); 
    if(result) { 
     cout << "Failed to read block from device" << endl; 
     return -1; 
    } 

    result = waveInStart(hWaveIn); 
    if(result) { 
     cout << "Failed to start recording" << endl; 
     return -1; 
    } 

    cout << "Recording..." << endl; 

    Sleep((NUMPTS/sampleRate) * 1000); 

    waveInUnprepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); 
// waveInClose(hWaveIn); 

    rtp_session_destroy(session); 
    ortp_exit(); 
    ortp_global_stats_display(); 

    return 0; 
} 

RTPRecv.cpp

#include <ortp/ortp.h> // ortp-0.20.0 

#include <windows.h> 
#include <stdio.h> 
#include <iostream> 
using namespace std; 

int sampleRate = 8000; // 8000, 11025, 16000, 22050, 24000, 32000, 44100 
WAVEHDR WaveOutHdr; 
MMRESULT result; 
HWAVEOUT hWaveOut; 
WAVEFORMATEX pFormat; 

int main(int argv, char **args) 
{ 
    pFormat.wFormatTag = WAVE_FORMAT_PCM; 
    pFormat.nChannels = 1; 
    pFormat.nSamplesPerSec = sampleRate; 
    pFormat.nAvgBytesPerSec = 2 * sampleRate; 
    pFormat.nBlockAlign = 2; 
    pFormat.wBitsPerSample = 16; 
    pFormat.cbSize = 0; 

    if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT)) 
    { 
     MessageBoxA(NULL, "Failed to replay", NULL, MB_OK | MB_ICONEXCLAMATION); 
    } 

    RtpSession *session; 

    int jittcomp=40; 
    bool_t adapt=TRUE; 

    ortp_init(); 
    ortp_scheduler_init(); 
    ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR); 
    session=rtp_session_new(RTP_SESSION_RECVONLY); 
    rtp_session_set_scheduling_mode(session,1); 
    rtp_session_set_blocking_mode(session,1); 
    rtp_session_set_local_addr(session,"0.0.0.0",61610); 
    rtp_session_set_connected_mode(session,TRUE); 
    rtp_session_set_symmetric_rtp(session,TRUE); 
    rtp_session_enable_adaptive_jitter_compensation(session,adapt); 
    rtp_session_set_jitter_compensation(session,jittcomp); 

    rtp_session_set_payload_type(session,0); 

    rtp_session_signal_connect(session,"ssrc_changed",(RtpCallback)rtp_session_reset,0); 

    unsigned char buffer[160]; 
    int have_more; 
    int err; 
    uint32_t ts=0; 
    int stream_received=0; 

    while(1) { 
     have_more=1; 
     while (have_more){ 
      err=rtp_session_recv_with_ts(session, buffer, 160, ts, &have_more); 
      if (err>0) stream_received=1; 
      if ((stream_received) && (err>0)) { 
       WaveOutHdr.lpData = (LPSTR)buffer; 
       WaveOutHdr.dwBufferLength = 160; 
       WaveOutHdr.dwBytesRecorded = 160; 
       WaveOutHdr.dwUser = 0; 
       WaveOutHdr.dwFlags = 0; 
       WaveOutHdr.dwLoops = 0; 
       waveOutPrepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); 
       waveOutWrite(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); 
      } 
     } 
     ts+=160; 
    } 

    waveOutUnprepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); 
    waveOutClose(hWaveOut); 

    rtp_session_destroy(session); 
    ortp_exit(); 
    ortp_global_stats_display(); 

    return 0; 
} 
+0

你看过输入/输出的二进制文件,特别是在Audacity这样的能够理解WAV格式的程序中? –

+0

与你的问题没有关系,但是......你在哪里使用Qt?我没有找到它... –

回答

0

您可以在客户端有很大的缓冲区。例如:一个持有10秒的缓冲区。尝试接收小缓冲区,并将其添加到大的一个,因为waveOutGetPosition()不断释放主缓冲区,然后waveOutWrite()WOM_DONE消息。

相关问题