ref: c2d86f06399780830d04239038265626f94a8d0f
parent: e8dbcb8f087c8e5568fb3942a86d09c35749ad95
author: Jean-Marc Valin <[email protected]>
date: Wed Aug 10 10:17:55 EDT 2011
Fixed multiple bugs in the repacketizer Repacketizer now seems to work, though it doesn't yet handle unmergeable packets. Also, test_opis no longer attempt to do proper gapless at the end of the file, which was causing problems for repacketization, but also with 32 bit overflows
--- a/src/opus.h
+++ b/src/opus.h
@@ -246,9 +246,13 @@
OPUS_EXPORT OpusRepacketizer *opus_repacketizer_create(void);
+OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
+
OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, int len);
OPUS_EXPORT int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen);
+
+OPUS_EXPORT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp);
OPUS_EXPORT int opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, int maxlen);
--- a/src/repacketizer.c
+++ b/src/repacketizer.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include "string.h"
#include "opus.h"
+#include "stdlib.h"
struct OpusRepacketizer {
unsigned char toc;
@@ -70,6 +71,11 @@
return opus_repacketizer_init(malloc(opus_repacketizer_get_size()));
}
+void opus_repacketizer_destroy(OpusRepacketizer *rp)
+{
+ free(rp);
+}
+
int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, int len)
{
unsigned char tmp_toc;
@@ -79,7 +85,7 @@
{
rp->toc = data[0];
rp->framesize = opus_packet_get_samples_per_frame(data, 48000);
- } else if (rp->toc != data[0])
+ } else if (rp->toc&0xFC != data[0]&0xFC)
{
/*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
return OPUS_CORRUPTED_DATA;
@@ -98,9 +104,16 @@
return OPUS_OK;
}
+int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
+{
+ return rp->nb_frames;
+}
+
int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, int maxlen)
{
int i, count, tot_size;
+ short *len;
+ const unsigned char **frames;
if (begin<0 || begin>=end || end>rp->nb_frames)
{
@@ -109,12 +122,14 @@
}
count = end-begin;
+ len = rp->len+begin;
+ frames = rp->frames+begin;
switch (count)
{
case 1:
{
/* Code 0 */
- tot_size = rp->len[0]+1;
+ tot_size = len[0]+1;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*data++ = rp->toc&0xFC;
@@ -122,20 +137,20 @@
break;
case 2:
{
- if (rp->len[1] == rp->len[0])
+ if (len[1] == len[0])
{
/* Code 1 */
- tot_size = 2*rp->len[0]+1;
+ tot_size = 2*len[0]+1;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*data++ = (rp->toc&0xFC) | 0x1;
} else {
/* Code 2 */
- tot_size = rp->len[0]+rp->len[0]+2+(rp->len[0]>=252);
+ tot_size = len[0]+len[1]+2+(len[0]>=252);
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*data++ = (rp->toc&0xFC) | 0x2;
- data += encode_size(rp->len[0], data);
+ data += encode_size(len[0], data);
}
}
break;
@@ -145,9 +160,9 @@
int vbr;
vbr = 0;
- for (i=1;i<rp->nb_frames;i++)
+ for (i=1;i<count;i++)
{
- if (rp->len[i] != rp->len[0])
+ if (len[i] != len[0])
{
vbr=1;
break;
@@ -156,28 +171,30 @@
if (vbr)
{
tot_size = 2;
- for (i=0;i<rp->nb_frames;i++)
- tot_size += 1 + (rp->len[i]>=252) + rp->len[i];
+ for (i=0;i<count-1;i++)
+ tot_size += 1 + (len[i]>=252) + len[i];
+ tot_size += len[count-1];
+
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*data++ = (rp->toc&0xFC) | 0x3;
- *data++ = rp->nb_frames | 0x80;
- for (i=0;i<rp->nb_frames-1;i++)
- data += encode_size(rp->len[i], data);
+ *data++ = count | 0x80;
+ for (i=0;i<count-1;i++)
+ data += encode_size(len[i], data);
} else {
- tot_size = rp->nb_frames*rp->len[0]+2;
+ tot_size = count*len[0]+2;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*data++ = (rp->toc&0xFC) | 0x3;
- *data++ = rp->nb_frames;
+ *data++ = count;
}
}
}
/* Copy the actual data */
- for (i=0;i<rp->nb_frames;i++)
+ for (i=0;i<count;i++)
{
- memcpy(data, rp->frames[i], rp->len[i]);
- data += rp->len[i];
+ memcpy(data, frames[i], len[i]);
+ data += len[i];
}
return tot_size;
}
--- a/src/test_opus.c
+++ b/src/test_opus.c
@@ -104,13 +104,11 @@
int count=0, count_act=0, k;
int skip;
int stop=0;
- int tot_read=0, tot_written=0;
short *in, *out;
int application;
double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
int bandwidth=-1;
const char *bandwidth_string;
- int write_samples;
int lost = 0, lost_prev = 1;
int toggle = 0;
int enc_final_range[2];
@@ -158,7 +156,8 @@
forcemono = 0;
use_dtx = 0;
packet_loss_perc = 0;
- int max_frame_size = 960*3;
+ int max_frame_size = 960*6;
+ int curr_read=0;
args = 5;
while( args < argc - 2 ) {
@@ -339,15 +338,14 @@
err = fread(data[toggle], 1, len[toggle], fin);
if (feof(fin))
break;
- tot_read += frame_size*channels;
} else {
err = fread(in, sizeof(short), frame_size*channels, fin);
- tot_read += err;
- if (err < frame_size*channels)
+ curr_read = err;
+ if (curr_read < frame_size*channels)
{
int i;
- for (i=err;i<frame_size*channels;i++)
- in[i] = 0;
+ for (i=curr_read*channels;i<frame_size*channels;i++)
+ in[i] = 0;
stop = 1;
}
@@ -386,13 +384,7 @@
}
if (output_samples>0)
{
- write_samples = output_samples-skip;
- tot_written += write_samples*channels;
- if (tot_written > tot_read)
- {
- write_samples -= (tot_written-tot_read)/channels;
- }
- fwrite(out+skip, sizeof(short), write_samples*channels, fout);
+ fwrite(out+skip, sizeof(short), output_samples-skip*channels, fout);
skip = 0;
}
}
@@ -399,9 +391,9 @@
}
/* compare final range encoder rng values of encoder and decoder */
- if( !encode_only && !lost && !lost_prev &&
+ if( enc_final_range[toggle^use_inbandfec]!=0 && !encode_only && !lost && !lost_prev &&
opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
- fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
+ fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d: 0x%8x vs 0x%8x\n", count, enc_final_range[toggle^use_inbandfec], opus_decoder_get_final_range( dec ));
return 0;
}
--- a/src/test_repacketizer.c
+++ b/src/test_repacketizer.c
@@ -2,6 +2,8 @@
#include "opus.h"
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#define MAX_PACKETOUT 32000
@@ -26,7 +28,7 @@
int main(int argc, char *argv[])
{
- int eof=0;
+ int i, eof=0;
FILE *fin, *fout;
unsigned char packets[48][1500];
int len[48];
@@ -33,6 +35,7 @@
int rng[48];
OpusRepacketizer *rp;
unsigned char output_packet[MAX_PACKETOUT];
+ int merge = 1, split=0;
if (argc < 3)
{
@@ -39,6 +42,21 @@
usage(argv[0]);
return 1;
}
+ for (i=1;i<argc-2;i++)
+ {
+ if (strcmp(argv[i], "-merge")==0)
+ {
+ merge = atoi(argv[i+1]);
+ i++;
+ } else if (strcmp(argv[i], "-split")==0)
+ split = 1;
+ else
+ {
+ fprintf(stderr, "Unknown option: %s\n", argv[i]);
+ usage(argv[0]);
+ return 1;
+ }
+ }
fin = fopen(argv[argc-2], "r");
fout = fopen(argv[argc-1], "w");
@@ -45,8 +63,8 @@
rp = opus_repacketizer_create();
while (!eof)
{
- int i, err;
- int nb_packets=2;
+ int err;
+ int nb_packets=merge;
opus_repacketizer_init(rp);
for (i=0;i<nb_packets;i++)
{
@@ -81,17 +99,42 @@
if (eof)
break;
- err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
- if (err>0) {
- unsigned char int_field[4];
- int_to_char(err, int_field);
- fwrite(int_field, 1, 4, fout);
- int_to_char(rng[nb_packets-1], int_field);
- fwrite(int_field, 1, 4, fout);
- fwrite(output_packet, 1, err, fout);
- /*fprintf(stderr, "out len = %d\n", err);*/
+
+ if (!split)
+ {
+ err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
+ if (err>0) {
+ unsigned char int_field[4];
+ int_to_char(err, int_field);
+ fwrite(int_field, 1, 4, fout);
+ int_to_char(rng[nb_packets-1], int_field);
+ fwrite(int_field, 1, 4, fout);
+ fwrite(output_packet, 1, err, fout);
+ /*fprintf(stderr, "out len = %d\n", err);*/
+ } else {
+ fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
+ }
} else {
- fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
+ int nb_frames = opus_repacketizer_get_nb_frames(rp);
+ for (i=0;i<nb_frames;i++)
+ {
+ err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT);
+ if (err>0) {
+ unsigned char int_field[4];
+ int_to_char(err, int_field);
+ fwrite(int_field, 1, 4, fout);
+ if (i==nb_frames-1)
+ int_to_char(rng[nb_packets-1], int_field);
+ else
+ int_to_char(0, int_field);
+ fwrite(int_field, 1, 4, fout);
+ fwrite(output_packet, 1, err, fout);
+ /*fprintf(stderr, "out len = %d\n", err);*/
+ } else {
+ fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
+ }
+
+ }
}
}