如何发送/接收RTP音频流(C ++)?

时间:2013-01-04 02:41:20

标签: c++ qt mingw rtp

抱歉,我说英语不好。

我做了两个项目(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;
}

1 个答案:

答案 0 :(得分:0)

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