I have pcap file that contains RTP data which in turn is audio for G.729 codec. Is there a way to decode this stream by pushing it into FFMPEG? This would probably mean I have to extract the RTP payload data from the PCAP file and then somehow pass it to FFMPEG.
Any guidelines and pointers are highly appreciated!
This answer doesn't require ffmpeg
, but I assume you dont really care how the audio is extracted... check out How to Decode G729 on the wireshark wiki...
In Wireshark, use menu "Statistics -> RTP -> Show All Streams". Select the desired stream and press "Analyze".
In the next dialog screen, press "Save Payload...". Save options are Format = .raw
and Channel = forward
. Name file my_input.raw
.
Convert the .raw
file to .pcm
format using the Open G.729
decoder. Syntax: va_g729_decoder.exe my_input.raw my_output.pcm
. Or for Linux: wine va_g729_decoder.exe my_input.raw my_output.pcm
.
The .pcm
file contains 16-bit linear PCM samples at 8000 Hz. Note that each sample is in Little-Endian format. To convert to .au
format, all you need to do is prepend the 24-byte au header, and convert each PCM sample to network byte order (or Big-Endian). The following perl
script will do the trick.
USAGE: perl pcm2au.pl [my_inputFile] [my_outputFile]
$usage = "Usage: 'perl $0 [Source PCM File] [Destination AU File]' ";
$my_inputFile = shift or die $usage;
$my_outputFile = shift or die $usage;
open(INPUTFILE, "$my_inputFile") or die "Unable to open file: $!\n";
binmode INPUTFILE;
open(OUTPUTFILE, "> $my_outputFile") or die "Unable to open file: $!\n";
binmode OUTPUTFILE;
###################################
# Write the AU header
###################################
print OUTPUTFILE ".snd";
$foo = pack("CCCC", 0,0,0,24);
print OUTPUTFILE $foo;
$foo = pack("CCCC", 0xff,0xff,0xff,0xff);
print OUTPUTFILE $foo;
$foo = pack("CCCC", 0,0,0,3);
print OUTPUTFILE $foo;
$foo = pack("CCCC", 0,0,0x1f,0x40);
print OUTPUTFILE $foo;
$foo = pack("CCCC", 0,0,0,1);
print OUTPUTFILE $foo;
#############################
# swap the PCM samples
#############################
while (read(INPUTFILE, $inWord, 2) == 2) {
@bytes = unpack('CC', $inWord);
$outWord = pack('CC', $bytes[1], $bytes[0]);
print OUTPUTFILE $outWord;
}
close(OUTPUTFILE);
close(INPUTFILE);