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
This commit is contained in:
parent
e8dbcb8f08
commit
c2d86f0639
4 changed files with 104 additions and 48 deletions
|
@ -246,10 +246,14 @@ OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp);
|
|||
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -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 @@ OpusRepacketizer *opus_repacketizer_create(void)
|
|||
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 @@ int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, int l
|
|||
{
|
||||
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 @@ int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, int l
|
|||
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 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign
|
|||
}
|
||||
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 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign
|
|||
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 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign
|
|||
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 @@ int opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsign
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -104,13 +104,11 @@ int main(int argc, char *argv[])
|
|||
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 @@ int main(int argc, char *argv[])
|
|||
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,14 +338,13 @@ int main(int argc, char *argv[])
|
|||
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++)
|
||||
for (i=curr_read*channels;i<frame_size*channels;i++)
|
||||
in[i] = 0;
|
||||
stop = 1;
|
||||
}
|
||||
|
@ -386,22 +384,16 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "opus.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_PACKETOUT 32000
|
||||
|
||||
|
@ -26,27 +28,43 @@ static opus_uint32 char_to_int(unsigned char ch[4])
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int eof=0;
|
||||
int i, eof=0;
|
||||
FILE *fin, *fout;
|
||||
unsigned char packets[48][1500];
|
||||
int len[48];
|
||||
int rng[48];
|
||||
OpusRepacketizer *rp;
|
||||
unsigned char output_packet[MAX_PACKETOUT];
|
||||
int merge = 1, split=0;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
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");
|
||||
|
||||
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,6 +99,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (eof)
|
||||
break;
|
||||
|
||||
if (!split)
|
||||
{
|
||||
err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
|
||||
if (err>0) {
|
||||
unsigned char int_field[4];
|
||||
|
@ -93,6 +114,28 @@ int main(int argc, char *argv[])
|
|||
} else {
|
||||
fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
|
||||
}
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue