Playing AAC RTP stream using ffdshow - directshow

I am trying to play an RTP stream from using a custom network source filter and ffdshow audio decoder (ffdshow-tryout stable).
The mediatype that I set on my source output stream is MEDIASUBTYPE_RAW_AAC1. Here is what I am setting:
pmt->SetType(&MEDIATYPE_Audio);
pmt->SetSubtype(&MEDIASUBTYPE_RAW_AAC1);
pmt->SetFormatType(&FORMAT_WaveFormatEx);
BYTE *AACRAW;
DWORD dwLen = sizeof(WAVEFORMATEX) + 2; //2 bytes of audio config
AACRAW = (BYTE *)::CoTaskMemAlloc(dwLen);
memset(AACRAW, 0, dwLen);
WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_RAW_AAC1;
wfx.nChannels = 1;
wfx.nSamplesPerSec = 16000;
wfx.nAvgBytesPerSec = 8000;
wfx.nBlockAlign = 1;
wfx.wBitsPerSample= 0;
wfx.cbSize = 2;
memcpy(AACRAW, (void *)&wfx, sizeof(WAVEFORMATEX));
vector<unsigned char>extra;
extra.push_back(0x14);
extra.push_back(0x08);
memcpy(AACRAW + sizeof(WAVEFORMATEX), extra.data(), extra.size());
pmt->SetFormat(AACRAW, dwLen);
::CoTaskMemFree(AACRAW);
And then when I receive a rtp packet here is what I forward to the ffdshow filter:
DeliverRTPAAC(pRaw + 12 + 2 + 2, nBufSize - 12 - 2 - 2, pack.timestamp);
where pRaw is the pointer to the rtp packet. Each rtp packet that I receive contains one AU.
The filters connect but does not play audio. No error output from the AAC decoder as well.
The SDP parameters from the Axis camera are:
a=rtpmap:97 mpeg4-generic/16000/1
a=fmtp:97 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=1408; sizeLength=13; indexLength=3; indexDeltaLength=3; profile=1; bitrate=64000;
Can somebody help me out please?

Probably the data you are receiving is wrapped in ADTS headers and you need to strip the ADTS header to supply the decoder with raw AAC.

Related

Play RTP packets payload obtained from the mobile phone in a call service

I have developed a UMTS core network using a home nodeB (HNB) which the mobile phones (or UEs) can register on my network and get the required services such as call service. I have implemented all the required procedures for call service and I can establish a successful call for my connected UEs.
In one of the most important procedure, i.e Call Proceeding, I have identified the coding of speech transferred between UEs and core. Here is my coding options (in wireshark):
GSM A-I/F DTAP - Call Proceeding
Protocol Discriminator: Call Control; call related SS messages (3)
.... 0011 = Protocol discriminator: Call Control; call related SS messages (0x3)
1... .... = TI flag: allocated by receiver
.000 .... = TIO: 0
00.. .... = Sequence number: 0
..00 0010 = DTAP Call Control Message Type: Call Proceeding (0x02)
Bearer Capability 1 - (Spare)
Element ID: 0x04
Length: 6
Octet 3
0... .... = Extension: Extended
.11. .... = Radio channel requirement: Spare
...0 .... = Coding standard: GSM standardized coding
.... 0... = Transfer mode: circuit
.... .000 = Information transfer capability: Speech (0x0)
Octets 3a - Speech Versions
0... .... = Extension: Extended
.0.. .... = Coding: octet used for extension of information transfer capability
..00 .... = Spare bit(s): 0
.... 0010 = Speech version indication: GSM full rate speech version 2(GSM EFR) (0x2)
0... .... = Extension: Extended
.0.. .... = Coding: octet used for extension of information transfer capability
..00 .... = Spare bit(s): 0
.... 1000 = Speech version indication: GSM full rate speech version 5(FR AMR-WB) (0x8)
0... .... = Extension: Extended
.0.. .... = Coding: octet used for extension of information transfer capability
..00 .... = Spare bit(s): 0
.... 0100 = Speech version indication: GSM full rate speech version 3(FR AMR) (0x4)
0... .... = Extension: Extended
.0.. .... = Coding: octet used for extension of information transfer capability
..00 .... = Spare bit(s): 0
.... 0101 = Speech version indication: GSM half rate speech version 3(HR AMR) (0x5)
1... .... = Extension: No Extension
.0.. .... = Coding: octet used for extension of information transfer capability
..00 .... = Spare bit(s): 0
.... 0001 = Speech version indication: GSM half rate speech version 1(GSM HR) (0x1)
So I can see the RTP packets transferred between UE and core. An instance is mentioned here (in wireshark):
Real-Time Transport Protocol
[Stream setup by RANAP (frame 2950)]
10.. .... = Version: RFC 1889 Version (2)
..0. .... = Padding: False
...0 .... = Extension: False
.... 0000 = Contributing source identifiers count: 0
0... .... = Marker: False
Payload type: DynamicRTP-Type-96 (96)
Sequence number: 56611
[Extended sequence number: 56611]
Timestamp: 424448575
Synchronization Source identifier: 0x5c260101 (1545994497)
RFC 2198: Redundant Audio Data
Header 1: PT=ITU-T G.728
0... .... = Follow: Not set
.000 1111 = Payload type: ITU-T G.728 (15)
Payload: 0028ba44776b3eee7a050039cdaa521cc20ac08d2bcf1818…
I have aggregated all RTP packets payload. How can I convert the aggregated bytes to a hearable audio?

DPDK TX checksum offload for TCP has fixed offset from correct checksum

I try to compute checksum for IP and TCP via DPDK checksum offload. The code does the following:
ipv4_hdr->hdr_checksum = 0;
mb->l2_len = eth_hdr_len;
mb->l3_len = ipv4_hdr_len;
mb->ol_flags = PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM;
tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr, mb->ol_flags);
rte_eth_conf has been set:
port_conf.txmode.offloads = DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM;
the IP checksum is right, TCP checksum has fixed offset from the correct checksum (under my environment, it is 4)
Any ideas?
Please refer to the answer DPDK HW and SW checksum. For enabling HW checksum one has to set the current checksum value to 0.
/* HW check sum */
ip_hdr->hdr_checksum = 0;
tcp_hdr = (struct tcp_hdr *)((char *)ip_hdr + info->l3_len);
tcp_hdr->cksum = 0;

libnetfilter_queue: Why can't I see the TCP payload of packets from nfq_get_payload?

I have a fairly basic user space firewall application. It receives data from libnetfilter_queue properly, we can see all the IP and TCP header information including source and destination IPs, ports, protocols, etc, but we don't get ANY of the TCP payload information...
The setup is pretty standard, I won't include it all but here are the highlights:
#define MAX_BUFFER_SIZE 65535
nfq_set_mode(qh, NFQNL_COPY_PACKET, MAX_BUFFER_SIZE)
So we are asking for the FULL PACKET back...
In the main thread we have:
rv = recv(fd, nfq_buffer, sizeof(nfq_buffer), 0);
printf("\nGot packet len: %d", rv);
if (rv > 0)
nfq_handle_packet(nfq_h, (char*)nfq_buffer, rv);
Here, on a standard HTTP call I will get a packet length of 140. But, in the callback handler the PACKET length is ALWAYS 64:
static int handle_packet(struct nfq_q_handle* qh, struct nfgenmsg* nfmsg, struct nfq_data* dat, void* data)
{
struct nfqnl_msg_packet_hdr* nfq_hdr = nfq_get_msg_packet_hdr(dat);
unsigned char* nf_packet;
int len = nfq_get_payload(dat,&nf_packet);
struct iphdr *iph = ((struct iphdr *) nf_packet);
iphdr_size = iph->ihl << 2;
if (iph->protocol == 6){
struct tcphdr *tcp = ((struct tcphdr *) (nf_packet + iphdr_size));
unsigned short tcphdr_size = (tcp->doff << 2);
printf("\nGot a packet!! len: %d iphdr: %d tcphdr: %d", len, iphdr_size, tcphdr_size);
}
}
In TCP, len is ALWAYS 64 (iphdr is 20, tcphdr is 44)... ALWAYS. I never get the TCP payload. What am I doing wrong???
Thanks to Joel for pointing out that problem was not in the C code, but in the iptables rules. There was a -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT rule prior to the NFQUEUE rule, so I was only getting the connection setup packets... whoops.

libpcap read packet size

I started to write an application which will read RTP/H.264 video packets from an existing .pcap file, I need to read the packet size.
I tried to use packet->len or header->len, but it never displays the right number of bytes for packets (I'm using wireshark to verify packet size - under Length column). How to do it?
This is part of my code:
while (packet = pcap_next(handle,&header)) {
u_char *pkt_ptr = (u_char *)packet;
struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure
struct pcap_pkthdr *pkt_hdr =(struct pcap_pkthdr *)packet;
unsigned int packet_length = pkt_hdr->len;
unsigned int ip_length = ntohs(ip_hdr->ip_len);
printf("Packet # %i IP Header length: %d bytes, Packet length: %d bytes\n",pkt_counter,ip_length,packet_length);
Packet # 0 IP Header length: 180 bytes, Packet length: 104857664 bytes
Packet # 1 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 2 IP Header length: 100 bytes, Packet length: 104857600 bytes
Packet # 3 IP Header length: 100 bytes, Packet length: 104857664 bytes
Packet # 4 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 5 IP Header length: 100 bytes, Packet length: 104857600 bytes
Another option I tried is to use:
pkt_ptr-> I get:
read_pcapfile.c:67:43: error: request for member ‘len’ in something not a structure or union
while (packet = pcap_next(handle,&header)) {
u_char *pkt_ptr = (u_char *)packet;
Don't do that; you're throwing away the const, and you really should NOT be modifying what the return value of pcap_next() points to.
struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure
That will point to an IP header structure ONLY if pcap_datalink(handle) returns DLT_RAW, which it probably will NOT do on most devices.
If, for example, pcap_datalink(handle) returns DLT_EN10MB, packet will point to an Ethernet header (the 10MB is historical - it's used for all Ethernet speeds other than the ancient historical 3MB experimental Ethernet at Xerox, which had a different header type).
See the list of link-layer header type values for a list of the possible DLT_ types.
struct pcap_pkthdr *pkt_hdr =(struct pcap_pkthdr *)packet;
That won't work, either. The struct pcap_pkthdr for the packet is in header.
unsigned int packet_length = pkt_hdr->len;
As per my earlier comment, that won't work. Use header.len instead.
(And bear in mind that, if a "snapshot length" shorter than the maximum packet size was specified in the pcap_open_live() call, or specified in a pcap_set_snaplen() call between the pcap_create() and pcap_activate() calls, header.caplen could be less than header.len, and only header.caplen bytes of the packet data will actually be available.)
unsigned int ip_length = ntohs(ip_hdr->ip_len);
And, as per my earlier comment, that probably won't work, either.
You should be using header.len.
unsigned int packet_length = header.len;

iOS UDP broadcast vs. PHP UDP broadcast

I'm trying to send data via UDP to the network. I've got some PHP code running on my local machine which works:
#!/usr/bin/php -q
<?php
$socket = stream_socket_client('udp://225.0.0.0:50000');
for($i=0;$i<strlen($argv[1]);$i++) $b.="\0\0\0".$argv[1][$i];
fwrite($socket,$b,strlen($argv[1])*4);
fclose($socket);
?>
Gives me the output in tcpdump:
18:53:24.504447 IP 10.0.1.2.52919 > 225.0.0.0.50000: UDP, length 36
I'm trying to get to the same result on a remote iOS with the following code:
- (void)broadcast:(NSString *)dx {
NSData* data=[dx dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"Broadcasting data: %#", dx);
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr4client;
memset(&addr4client, 0, sizeof(addr4client));
addr4client.sin_len = sizeof(addr4client);
addr4client.sin_family = AF_INET;
addr4client.sin_port = htons(PORT);
addr4client.sin_addr.s_addr = htonl(INADDR_BROADCAST);
int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void *)&yes, sizeof(yes)) == -1) {
NSLog([NSString stringWithFormat:#"Failure to set broadcast! : %d", errno]);
}
char *toSend = (char *)[data bytes];
if (sendto(fd, toSend, [data length], 0, (struct sockaddr *)&addr4client, sizeof(addr4client)) == -1) {
NSLog([NSString stringWithFormat:#"Failure to send! : %d", errno]);
}
close(fd);
}
Which gives me the following output in tcpdump:
19:01:22.776192 IP 10.0.1.4.60643 > broadcasthost.50000: UDP, length 9
Looks basically OK, but doesn't arrive in Quartz Composer for some reason, I guess there should be the IP address or something instead of 'broadcasthost'.
Any idea?
The problem was not in the implementation of the broadcaster, but the format of the string. To work with Quartz Composer, every character needs to be preceded by a backslash-zero combination: "\0\0\0", so "abc" has to be formatted and sent as "\0\0\0a\0\0\0b\0\0\0c".
See also Celso Martinho's blog article: Leopard’s Quartz Composer and Network events.
I suggest using AsyncSocket ( google it, its on googlecode ), very well tested objective-c code that runs on iOS.
That way you can send data really easy using a NSData object. AsyncSocket manages the hard part for you.
If that isn't an option for you you should use CFSocket. What you are doing is implementing code that has been written for you already, CFSocket.

Resources