Основы voip - информация заголовка для пакета?

Я немного учусь использовать voip поверх 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 чисел. Я никогда раньше не работал на уровне байтов. Или может есть другие техники?

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

Спасибо,


person Aubergine    schedule 01.02.2012    source источник


Ответы (1)


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

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

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

Давайте поместим их в некоторые переменные, используя целые числа для простоты или long, когда нам нужно иметь дело с 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, вам нужен правильный тип полезной нагрузки в соответствии с форматом аудиоданных, которые у вас есть, вам нужно правильно пакетировать и планировать эти аудиоданные - например, для G.711Alaw вы должны заполнить каждый пакет RTP 160 байтами аудиоданных и отправить один пакет каждые 20 миллисекунд.

person nos    schedule 01.02.2012
comment
о, это именно то, что я искал. Так много нужно узнать и проанализировать, однако теперь у меня есть направление, и это важно! Спасибо - person Aubergine; 01.02.2012
comment
Я спрашивал phd парней о смещении битов, показывающем ваш код, они сказали, что одного приведения достаточно. Так что мне строго нужно использовать предоставленный вами сдвиг, если я могу просто позвонить: buf[4] = (byte) sequenceNumber ? Спасибо. - person Aubergine; 06.02.2012
comment
@Aubergine Вам нужно поместить старший байт 4-байтового целого числа в buf[4], и вы не можете сделать это, приведя целое число к байту. Однако для младшего значащего байта было бы достаточно buf[7] = (byte) timestamp; вместо buf[7] = (byte) (timestamp & 0x000000ff); - person nos; 07.02.2012
comment
@Nos Во-первых, спасибо, я нашел ваш ответ здесь полезным и у меня есть вопрос. Почему И значения перед сдвигом битов. Например, почему version & 0x3 или timestamp & 0xff000000? Кажется, вы применяете битовую маску с 1. Разве это не лишнее или я что-то упускаю? - person strwils; 12.01.2015
comment
@strwils Многие из них предназначены только для удобства чтения и ясности. version&0x3 дает понять, что поле версии состоит всего из 2 бит. timestamp & 0xff000000 дает понять, что вы извлекаете верхние 8 бит, и просто (timestamp >> 24) не будет делать то, что вы хотите, из-за расширения знака при сдвиге вправо. Если вам нужно, вы можете очень хорошо оптимизировать код, если это необходимо, но чаще всего JIT все равно заботится о таких оптимизациях, и это не стоит того, если вы потеряете читабельность кода. - person nos; 12.01.2015
comment
@nos О, хорошо. Понятно. Спасибо за объяснение. - person strwils; 12.01.2015