Как я могу отправлять и получать пакеты в сеансе RTP (используя jrtplib) с переменной длиной? - PullRequest
0 голосов
/ 02 декабря 2018

В последнее время я установил jrtplib (C ++), и я пытаюсь понять, как я должен получать данные из пакетов, сохранять их в один буфер и в конце передачи сохранять все эти данные в файл.До сих пор я получил это (в основном из примеров файлов, поставляемых с библиотекой).Это сервер:

using namespace jrtplib;
int main(void)
{
    #ifdef RTP_SOCKETTYPE_WINSOCK
     WSADATA dat;
     WSAStartup(MAKEWORD(2,2),&dat);
    #endif // RTP_SOCKETTYPE_WINSOCK

    RTPSession sess;
    uint16_t portbase = 5000;

    RTPUDPv4TransmissionParams transparams;
    RTPSessionParams sessparams;

    // IMPORTANT: The local timestamp unit MUST be set, otherwise
    // RTCP Sender Report info will be calculated wrong
    // In this case, we'll be sending 10 samples each second, so we'll
    // put the timestamp unit to (1.0/10.0)
    sessparams.SetOwnTimestampUnit(1.0/10.0);

    sessparams.SetAcceptOwnPackets(true);
    transparams.SetPortbase(portbase);
    int status;
    status = sess.Create(sessparams,&transparams);
    checkerror(status);

    bool done = false;
    std::cout << "Waiting for some data...\n";

    RTPTime startTime = RTPTime::CurrentTime();
    std::vector<int8_t> data;

    while(!done)
    {
        std::cout << "Waiting for some data...\n";
        sess.BeginDataAccess();

        // check incoming packets
        if (sess.GotoFirstSourceWithData())
        {
            do
            {
                RTPPacket *pack;

                while ((pack = sess.GetNextPacket()) != NULL)
                {
                    // You can examine the data here
                    data.push_back(*(pack->GetPayloadData()));

                    // we don't longer need the packet, so
                    // we'll delete it
                    sess.DeletePacket(pack);
                }
            } while (sess.GotoNextSourceWithData());
        }

        sess.EndDataAccess();

        #ifndef RTP_SUPPORT_THREAD
         status = sess.Poll();
         checkerror(status);
        #endif // RTP_SUPPORT_THREAD

        RTPTime::Wait(RTPTime(0.020));
        RTPTime t = RTPTime::CurrentTime();
        t -= startTime;
        if ( t > RTPTime(100.0) ) {
            done = true;
        }
    }

    sess.BYEDestroy(RTPTime(10,0),0,0);

    #ifdef RTP_SOCKETTYPE_WINSOCK
     WSACleanup();
    #endif // RTP_SOCKETTYPE_WINSOCK

    FILE *file = fopen("d:/file.png", "w");
    if (file == NULL){
        printf("Could not open file for saving!\n");
        exit(1);
    }

    for (int i  = 0; i < data.size(); i++){
        fwrite(&data[i], sizeof(data[i]), 1, file);
    }

    return 0;
}

А это клиент:

using namespace jrtplib;
int main()
{
    #ifdef RTP_SOCKETTYPE_WINSOCK
     WSADATA dat;
     WSAStartup(MAKEWORD(2,2),&dat); 
    #endif 


    FILE *file = fopen("c:/file.png", "rb");
    if (file == NULL){
        printf("Could not open file!\n");
        exit(1);
    }

    fseek(file, 0L, SEEK_END);
    auto fsize = ftell(file);
    fseek(file, 0L, SEEK_SET);
    printf("File size: %ld\n", fsize);
    auto *buffer = (unsigned char*) malloc(fsize);
    fread(buffer, fsize, 1, file);
    fclose(file);
    file = NULL;

    uint16_t portbase = 5000;
    uint16_t destport = 5000;

    std::string ipstr = "192.168.1.164";
    uint32_t destip = inet_addr(ipstr.c_str());    
    if (destip == INADDR_NONE)
    {
        std::cerr << "Bad IP address specified" << std::endl;
        return -1;
    }

    destip = ntohl(destip);

    /* Parameters for the transmission component */
    RTPUDPv4TransmissionParams transparams;
    transparams.SetPortbase(portbase);

    RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0/10.0);
    sessparams.SetAcceptOwnPackets(true);

    // Give general options for session
    RTPSession sess;
    int status = sess.Create(sessparams,&transparams);
    checkerror(status);

    sess.SetDefaultPayloadType(96);
    sess.SetDefaultMark(false);
    sess.SetDefaultTimestampIncrement(160);

    /* Specify to which destinations rtp and rtcp data should be sent. */
    RTPIPv4Address addr(destip,destport);
    status = sess.AddDestination(addr);
    checkerror(status);

    RTPTime delay(0.020);
    RTPTime starttime = RTPTime::CurrentTime();

    int transmitted = 0;

    auto *p = buffer;
    bool done = false;
    while(!done) {
        // send the packet
        status = sess.SendPacket(p, sizeof(*p));
        checkerror(status);
        transmitted += sizeof(*p);
        p++;

        RTPTime::Wait(delay);
        RTPTime t = RTPTime::CurrentTime();
        t -= starttime;

        if (t > RTPTime(100.0)){
            *buffer = 0;
            status = sess.SendPacket(p, sizeof(*p));
            transmitted += sizeof(*p);
            done = true;
        }
        printf("\nSent %d bytes\n", transmitted);
    }

    sess.BYEDestroy(RTPTime(10,0),0,0);

    #ifdef RTP_SOCKETTYPE_WINSOCK
     WSACleanup();
    #endif 
    return 0;
}   

Мне удалось отправить небольшие текстовые файлы, но только если я знал точный размер файла -Я изменил сервер, чтобы он остановился на точном количестве полученных байтов, чтобы сделать это.Во-вторых, я всегда получаю 1 байт одновременно с 1-байтовым вектором: вектором int8_t.Пока я просто знаю, что посылаю 1 байт за раз.Вопросы:

  • Как остановить передачу, когда я знаю, что она завершена (со стороны клиента и сервера)?

  • Как сделатьЯ отправляю данные разной длины и как их получить, если я не знаю, сколько будет отправлено?Таким образом, я не думаю, что смогу сохранить все данные в векторе, поэтому как мне сохранить их в памяти, если размер буфера постоянно увеличивается?

Я знаю, что используется RTPдля передачи в режиме реального времени (которую я намерен использовать позже), но сейчас я просто хотел понять основные концепции сетей.

...