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

标签 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;
}

最佳答案

您可以在客户端创建一个大缓冲区。例如:一个缓冲区持有 10 秒。尝试从 waveOutGetPosition() 开始接收小缓冲区并将其添加到大缓冲区并不断释放主缓冲区,然后在 WOM_DONE 之后使用 waveOutWrite()消息。

关于c++ - 如何发送/接收 RTP 音频流(C++)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14150365/

相关文章:

python - QSortFilterProxyModel 获取过滤后的数据

linux - 使用 Mingw 在 Windows 上安装 Linux 库

linux - CMake:使用 MinGW 交叉编译 linux-to-windows 没有找到一些系统头文件

c++ - 如何检查是否在运行时定义了 C++ 抽象方法

c++ - qt 将数据库 sql 添加到从 cmake 导入的项目中

c++ - 在 C++ 中实现和包装函数组合以进行惰性求值

c++ - 基于 downloadmanager 示例,Qt 下载超过 15 个文件不起作用

c++ - 如何使用 MinGW 在 Linux 上构建 Crypto++ 库?

c++ - GCC C++14/17 成员函数指针模板参数的区别

c++ - char c = 255 的值转换为 int