Sorry if you receive multiple copies.

Dear Jean-Marc,

I've got some problems with the FEC of Opus using the current stable release (1.02) from the repository. According to my understanding of FEC, the FEC information of the next packet is used to restore the former lost packet. But if I use the "packet_size of the lost packet" to invoke FEC for it, as recomended in the API documentation, the function opus_decode_native uses PLC because of line 748 in file opus_decoder.c:

"if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY){"

If I use "max_frame_size", like in the opus_demo invokation of opus_decode (file opus_demo.c, line 714), FEC is used for the last packet. But the recursive call inserts PLC for the other packets until "max_frame_size" is reached.
This behaviour leads to a fragmented output-file.

If I use twice the "packet_size of the lost packet" to invoke opus_decode, PLC and FEC still seem to be called for only 1 lost packet and the outputfile is fragmented again.

So I changed file opus_decoder.c line 748

if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)

to

if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)

But then

/* Otherwise, run the PLC on everything except the size for which we might have FEC */
duration_copy = st->last_packet_duration;
ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL);

is called anyway, and Opus never reaches the FEC part.

I then changed the code to the following and it worked, but I'm not sure if I missed sth.:

opus_decoder.c:738-764

    if (decode_fec)
   {
      int duration_copy;
      int ret;
      /* If no FEC can be present, run the PLC (recursive call) */
if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY){ return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL);
      }
if(frame_size == packet_frame_size && packet_mode != MODE_CELT_ONLY && st->mode != MODE_CELT_ONLY){
            /* Complete with FEC */
            st->mode = packet_mode;
            st->bandwidth = packet_bandwidth;
            st->frame_size = packet_frame_size;
            st->stream_channels = packet_stream_channels;
ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
                  packet_frame_size, 1);
            if (ret<0)
               return ret;
      }else{
/* Otherwise, run the PLC on everything except the size for which we might have FEC */
          duration_copy = st->last_packet_duration;
ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL);
          if (ret<0)
          {
             st->last_packet_duration = duration_copy;
             return ret;
          }
      }
      st->last_packet_duration = frame_size;
      return frame_size;
   }

What's your opinion on this?

Regards,
Alfons

--
Symonics GmbH

Sand 13

72076 Tübingen

Tel +49 7071 2970573

Fax +49 7071 5681309

Email: alfons.mar...@symonics.com


Geschäftsführer/Presidents: Michael Haun, Dr. Christian Hoene, Patrick Schreiner

Sitz der Gesellschaft/Place of Business: Tübingen

Registereintrag/Commercial Register: Amtsgericht Stuttgart, HRB 739918

_______________________________________________
codec mailing list
codec@ietf.org
https://www.ietf.org/mailman/listinfo/codec

Reply via email to