основы VoIP - информация заголовка для пакета? - PullRequest
3 голосов
/ 01 февраля 2012

Я изучаю использование voip over udp в небольшой сети.Я знаю, что есть несколько библиотек, готовых сделать и перестараться со всем, что мне когда-либо нужно, с помощью нескольких вызовов методов, но, как я уже сказал, я учусь, поэтому мне нужно заново изобрести колесо, чтобы увидеть, как оно работает.

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

Небольшой код для отражениясреда:

byte[] block;
DatagramPacket packet; // UDP packet                

/* x Bytes per block , y blocks per second,
   z ms time block playback duration */

block = recorder.getBlock(); // assume I have class that handles audio
                              // recording and returns speech in a
                              // uncompressed form of bytes

packet = new DatagramPacket(block, block.length, clientIP, PORT);

Во-первых, я предполагаю, что, поскольку это UDP, отправителю на самом деле все равно, кроме простого факта, что он куда-то перебрасывает пакеты.Вот почему внутри такого метода нет.

Во-вторых, я предполагаю, что мне нужно сделать это самому - добавить дополнительные байты в блок байтов, который будет отправлен, который будет содержать порядковый номер пакета?Однако я также обеспокоен тем, что если я это сделаю, то как мне распознать, что байты являются байтами заголовка, а не байтами аудио?Я могу предположить, что первый байт представляет число, однако мы знаем, что байт может представлять только 258 чисел.Я никогда раньше не работал на байтовом уровне.Или, может быть, есть другие методы?

Коротко говоря, для чередования мне нужно знать, как настроить порядковый номер пакета , поскольку я не могу заказать неупорядоченные пакеты :-)

Спасибо,

1 Ответ

6 голосов
/ 01 февраля 2012

Вам нужно будет сериализовать / десериализовать типы данных, которые ваша программа использует, в байтовый массив.

Предположим, вы говорите о RTP , и вы хотите отправитьПакет с этими полями - смотрите главу 5 в спецификации RTP:

Версия = 2 дополнения = 0 расширение = 0 Подсчет CSRC = 1 маркер = 0 тип полезной нагрузки = 8 (G711 alaw) порядковый номер = 1234 отметка времени =1 one CSRC = 4321

Позволяет поместить их в некоторые переменные, используя целые числа для простоты или длинные, когда нам нужно иметь дело с 32-битным значением без знака:

int version = 2;
int padding = 0;
int extension = 0;
int csrcCount = 1;
int marker = 0;
int payloadType = 8;
int sequenceNumber = 1234;
long timestamp = 1;
long ourCsrc = 4321;

byte buf[] = ...; //allocate this big enough to hold the RTP header + audio data

//assemble the first bytes according to the RTP spec (note, the spec marks version as bit 0 and 1, but
//this is really the high bits of the first byte ...
buf[0] = (byte) ((version & 0x3) << 6 | (padding & 0x1) << 5 | (extension & 0x1) << 4 | (csrcCount & 0xf));

//2.byte
buf[1] = (byte)((marker & 0x1) << 7 | payloadType & 0x7f);

//squence number, 2 bytes, in big endian format. So the MSB first, then the LSB.
buf[2] = (byte)((sequenceNumber & 0xff00) >> 8);
buf[3] = (byte)(sequenceNumber  & 0x00ff);

//packet timestamp , 4 bytes in big endian format
buf[4] = (byte)((timestamp & 0xff000000) >> 24);
buf[5] = (byte)((timestamp & 0x00ff0000) >> 16);
buf[6] = (byte)((timestamp & 0x0000ff00) >> 8);
buf[7] = (byte) (timestamp & 0x000000ff);
//our CSRC , 4 bytes in big endian format
buf[ 8] = (byte)((sequenceNumber & 0xff000000) >> 24);
buf[ 9] = (byte)((sequenceNumber & 0x00ff0000) >> 16);
buf[10] = (byte)((sequenceNumber & 0x0000ff00) >> 8);
buf[11] = (byte) (sequenceNumber & 0x000000ff);

Это заголовок,теперь вы можете скопировать аудио байты в buf, начиная с buf[12] и отправить buf как один пакет.

Теперь вышеприведенное, конечно, просто для демонстрации принципов, фактического сериализатора для RTPпакет должен иметь дело с гораздо большим, в соответствии со спецификацией RTP (например, вам могут потребоваться некоторые заголовки расширения, вам может потребоваться более одного CSRC, вам нужен правильный тип полезной нагрузки в соответствии с форматом аудиоданных yВы должны правильно упаковать и запланировать эти аудиоданные - например, для G.711Alaw вы должны заполнить каждый пакет RTP 160-ю байтами аудиоданных и отправлять один пакет каждые 20 миллисекунд.

...