ref: f7455e66cab87a238b6c3ebe79c40c22f0ff384a
parent: 380b5aeb5322914724994d3e059438ff5bf5c41f
author: Ralph Giles <giles@mozilla.com>
date: Wed Oct 3 17:54:43 EDT 2012
Calculate timestamps from packet durations. Previously, everything was hard-coded to 20 ms. Now we increment rtp timestamps and ogg granulepos based on the packet duration as described by the ToC header. This adds a dependency on libopus, but the opus_packet() calls as small and can stand alone, so they could be extracted and supplied separately if necessary. Granulepos values are still ignored when reading from a .opus file. It would probably be better to either warn, or use those as much as possible to set the rtp timestamps to better represent the recorded data.
--- a/Makefile.am
+++ b/Makefile.am
@@ -56,6 +56,6 @@
opusinfo_MANS = man/opusinfo.1
opusrtp_SOURCES = src/opusrtp.c
-opusrtp_LDADD = @LIBPCAP@ $(OGG_LIBS)
+opusrtp_LDADD = @LIBPCAP@ $(OGG_LIBS) $(Opus_LIBS)
#TESTS = FIXME
--- a/Makefile.unix
+++ b/Makefile.unix
@@ -21,7 +21,7 @@
$(CC) $(LDFLAGS) src/opus_header.o src/opusinfo.o src/info_opus.o -o opusinfo -logg
opusrtp: src/opusrtp.o
- $(CC) $(LDFLAGS) src/opusrtp.o -o opusrtp -logg
+ $(CC) $(LDFLAGS) src/opusrtp.o -o opusrtp ../opus/.libs/libopus.a -logg
clean:
rm -f src/*.o $(PROGS) opusrtp
--- a/src/opusrtp.c
+++ b/src/opusrtp.c
@@ -58,6 +58,7 @@
#ifdef HAVE_PCAP
#include <pcap.h>
#endif
+#include <opus.h>
#include <ogg/ogg.h>
#define OPUS_PAYLOAD_TYPE 113
@@ -67,6 +68,7 @@
ogg_stream_state *stream;
FILE *out;
int seq;
+ ogg_int64_t granulepos;
int linktype;
} state;
@@ -215,7 +217,17 @@
return 0;
}
+/* calculate the number of samples in an opus packet */
+int opus_samples(const unsigned char *packet, int size)
+{
+ /* number of samples per frame at 48 kHz */
+ int samples = opus_packet_get_samples_per_frame(packet, 48000);
+ /* number "frames" in this packet */
+ int frames = opus_packet_get_nb_frames(packet, size);
+ return samples*frames;
+}
+
/* helper, write out available ogg pages */
int ogg_write(state *params)
{
@@ -588,6 +600,7 @@
}
/* read and process available packets */
while (ogg_stream_packetout(&os,&op) == 1) {
+ int samples;
/* skip header packets */
if (state == 1 && op.bytes >= 19 && !memcmp(op.packet, "OpusHead", 8)) {
state++;
@@ -597,13 +610,14 @@
state++;
continue;
}
+ /* get packet duration */
+ samples = opus_samples(op.packet, op.bytes);
/* update the rtp header and send */
- rtp.time += 960;
- // TODO: rtp.time += count_samples(op.packet, op.bytes);
rtp.seq++;
+ rtp.time += samples;
rtp.payload_size = op.bytes;
send_rtp_packet(fd, (struct sockaddr *)&sin, &rtp, op.packet);
- usleep(20000);
+ usleep(samples*1000/48);
}
}
}
@@ -733,7 +747,9 @@
/* write the payload to our opus file */
ogg_packet *op = op_from_pkt(packet, size);
- op->granulepos = 960*rtp.seq; // FIXME: get this from the toc byte
+ op->packetno = rtp.seq;
+ params->granulepos += opus_samples(packet, size);
+ op->granulepos = params->granulepos;
ogg_stream_packetin(params->stream, op);
free(op);
ogg_write(params);
@@ -783,6 +799,7 @@
return -2;
}
params->seq = 0;
+ params->granulepos = 0;
/* write stream headers */
op = op_opushead();