2013-01-04 1 views
1

죄송합니다. 영어를 잘 못합니다.RTP 오디오 스트림 (C++)을 송수신하는 방법은 무엇입니까?

2 개의 프로젝트 (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

특히 WAV 형식을 이해하는 Audacity와 같은 프로그램에서 입출력의 바이너리를 살펴 보셨습니까? –

+0

질문과 관련이 없지만 ... Qt를 어디에서 사용하고 있습니까? 나는 그것을 발견하지 못했다 ... –

답변

0

당신은 클라이언트에서 큰 버퍼를 만들 수 있습니다. 예 : 10 초를 유지하는 버퍼. 작은 버퍼를 받아서 waveOutGetPosition() 이후에 큰 버퍼에 추가하고 계속해서 메인 버퍼를 해제 한 다음 WOM_DONE 메시지 이후에 waveOutWrite()을 수신합니다.

관련 문제