Skip to content
Snippets Groups Projects
Verified Commit 885d7038 authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

Make FEC handling in opus_demo more general

Now only running the decoder on "received" packets
parent d1b48b71
No related branches found
No related tags found
No related merge requests found
......@@ -216,10 +216,10 @@ int main(int argc, char *argv[])
OpusEncoder *enc=NULL;
OpusDecoder *dec=NULL;
int args;
int len[2];
int len;
int frame_size, channels;
opus_int32 bitrate_bps=0;
unsigned char *data[2] = {NULL, NULL};
unsigned char *data = NULL;
unsigned char *fbytes=NULL;
opus_int32 sampling_rate;
int use_vbr;
......@@ -243,8 +243,7 @@ int main(int argc, char *argv[])
int bandwidth=OPUS_AUTO;
const char *bandwidth_string;
int lost = 0, lost_prev = 1;
int toggle = 0;
opus_uint32 enc_final_range[2];
opus_uint32 enc_final_range;
opus_uint32 dec_final_range;
int encode_only=0, decode_only=0;
int max_frame_size = 48000*2;
......@@ -264,6 +263,7 @@ int main(int argc, char *argv[])
int variable_duration=OPUS_FRAMESIZE_ARG;
int delayed_decision=0;
int ret = EXIT_FAILURE;
int lost_count=0;
if (argc < 5 )
{
......@@ -587,10 +587,7 @@ int main(int argc, char *argv[])
out = (short*)malloc(max_frame_size*channels*sizeof(short));
/* We need to allocate for 16-bit PCM data, but we store it as unsigned char. */
fbytes = (unsigned char*)malloc(max_frame_size*channels*sizeof(short));
data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
if ( use_inbandfec ) {
data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
}
data = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
if(delayed_decision)
{
if (frame_size==sampling_rate/400)
......@@ -652,22 +649,22 @@ int main(int argc, char *argv[])
num_read = fread(ch, 1, 4, fin);
if (num_read!=4)
break;
len[toggle] = char_to_int(ch);
if (len[toggle]>max_payload_bytes || len[toggle]<0)
len = char_to_int(ch);
if (len>max_payload_bytes || len<0)
{
fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
fprintf(stderr, "Invalid payload length: %d\n",len);
break;
}
num_read = fread(ch, 1, 4, fin);
if (num_read!=4)
break;
enc_final_range[toggle] = char_to_int(ch);
num_read = fread(data[toggle], 1, len[toggle], fin);
if (num_read!=(size_t)len[toggle])
enc_final_range = char_to_int(ch);
num_read = fread(data, 1, len, fin);
if (num_read!=(size_t)len)
{
fprintf(stderr, "Ran out of input, "
"expecting %d bytes got %d\n",
len[toggle],(int)num_read);
len,(int)num_read);
break;
}
} else {
......@@ -696,8 +693,8 @@ int main(int argc, char *argv[])
if (encode_only || decode_only)
stop = 1;
}
len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
nb_encoded = opus_packet_get_samples_per_frame(data[toggle], sampling_rate)*opus_packet_get_nb_frames(data[toggle], len[toggle]);
len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
nb_encoded = opus_packet_get_samples_per_frame(data, sampling_rate)*opus_packet_get_nb_frames(data, len);
remaining = frame_size-nb_encoded;
for(i=0;i<remaining*channels;i++)
in[i] = in[nb_encoded*channels+i];
......@@ -716,10 +713,10 @@ int main(int argc, char *argv[])
bitrate_bps = 1000;
opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
}
opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
if (len[toggle] < 0)
opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range));
if (len < 0)
{
fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
fprintf (stderr, "opus_encode() returned %d\n", len);
goto failure;
}
curr_mode_count += frame_size;
......@@ -731,56 +728,60 @@ int main(int argc, char *argv[])
}
#if 0 /* This is for testing the padding code, do not enable by default */
if (len[toggle]<1275)
if (len<1275)
{
int new_len = len[toggle]+rand()%(max_payload_bytes-len[toggle]);
if ((err = opus_packet_pad(data[toggle], len[toggle], new_len)) != OPUS_OK)
int new_len = len+rand()%(max_payload_bytes-len);
if ((err = opus_packet_pad(data, len, new_len)) != OPUS_OK)
{
fprintf(stderr, "padding failed: %s\n", opus_strerror(err));
goto failure;
}
len[toggle] = new_len;
len = new_len;
}
#endif
if (encode_only)
{
unsigned char int_field[4];
int_to_char(len[toggle], int_field);
int_to_char(len, int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
int_to_char(enc_final_range[toggle], int_field);
int_to_char(enc_final_range, int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
if (fwrite(data[toggle], 1, len[toggle], fout) != (unsigned)len[toggle]) {
if (fwrite(data, 1, len, fout) != (unsigned)len) {
fprintf(stderr, "Error writing.\n");
goto failure;
}
tot_samples += nb_encoded;
} else {
opus_int32 output_samples;
lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
int fr;
int run_decoder;
lost = len==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
if (lost)
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
else
output_samples = max_frame_size;
if( count >= use_inbandfec ) {
/* delay by one packet when using in-band FEC */
if( use_inbandfec ) {
if( lost_prev ) {
/* attempt to decode with in-band FEC from next packet */
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 1);
} else {
/* regular decode */
output_samples = max_frame_size;
output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, output_samples, 0);
}
{
lost_count++;
run_decoder = 0;
} else {
run_decoder= 1;
}
if (run_decoder)
run_decoder += lost_count;
/* FIXME: Figure out how to trigger the decoder when the last packet of the file is lost. */
for (fr=0;fr<run_decoder;fr++) {
opus_int32 output_samples=0;
if (fr < lost_count-1) {
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
output_samples = opus_decode(dec, NULL, 0, out, output_samples, 1);
} else if (fr == lost_count-1) {
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
output_samples = opus_decode(dec, data, len, out, output_samples, 1);
} else {
output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 0);
output_samples = max_frame_size;
output_samples = opus_decode(dec, data, len, out, output_samples, 0);
}
if (output_samples>0)
{
......@@ -817,24 +818,26 @@ int main(int argc, char *argv[])
if (!encode_only)
opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
/* compare final range encoder rng values of encoder and decoder */
if( enc_final_range[toggle^use_inbandfec]!=0 && !encode_only
if( enc_final_range!=0 && !encode_only
&& !lost && !lost_prev
&& dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
&& dec_final_range != enc_final_range ) {
fprintf (stderr, "Error: Range coder state mismatch "
"between encoder and decoder "
"in frame %ld: 0x%8lx vs 0x%8lx\n",
(long)count,
(unsigned long)enc_final_range[toggle^use_inbandfec],
(unsigned long)enc_final_range,
(unsigned long)dec_final_range);
goto failure;
}
lost_prev = lost;
if (!lost)
lost_count = 0;
if( count >= use_inbandfec ) {
/* count bits */
bits += len[toggle]*8;
bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
bits2 += len[toggle]*len[toggle]*64;
bits += len*8;
bits_max = ( len*8 > bits_max ) ? len*8 : bits_max;
bits2 += len*len*64;
if (!decode_only)
{
nrg = 0.0;
......@@ -843,13 +846,12 @@ int main(int argc, char *argv[])
}
nrg /= frame_size * channels;
if( nrg > 1e5 ) {
bits_act += len[toggle]*8;
bits_act += len*8;
count_act++;
}
}
}
count++;
toggle = (toggle + use_inbandfec) & 1;
}
if(decode_only && count > 0)
......@@ -879,8 +881,7 @@ int main(int argc, char *argv[])
failure:
opus_encoder_destroy(enc);
opus_decoder_destroy(dec);
free(data[0]);
free(data[1]);
free(data);
if (fin)
fclose(fin);
if (fout)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment