Refactor WebRtcOpus_PacketHasFec.

WebRtcOpus_PacketHasFec was written long time ago. see http://webrtc-codereview.appspot.com/7539004.
When revisiting, I notice that adding more comments should help. Code style should be improved a bit too.

Bug: webrtc:10772
Change-Id: If4d60b210e6235b4f787608047e88efc949f6838
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/144056
Commit-Queue: Minyue Li <minyue@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28479}
This commit is contained in:
Minyue Li
2019-07-03 10:14:18 +02:00
committed by Commit Bot
parent 67008dfb36
commit e8fbc5d702

View File

@ -653,48 +653,24 @@ int WebRtcOpus_FecDurationEst(const uint8_t* payload,
return samples;
}
// This method is based on Definition of the Opus Audio Codec
// (https://tools.ietf.org/html/rfc6716). Basically, this method is based on
// parsing the LP layer of an Opus packet, particularly the LBRR flag.
int WebRtcOpus_PacketHasFec(const uint8_t* payload,
size_t payload_length_bytes) {
int frames, channels, payload_length_ms;
int n;
opus_int16 frame_sizes[48];
const unsigned char *frame_data[48];
if (payload == NULL || payload_length_bytes == 0)
return 0;
/* In CELT_ONLY mode, packets should not have FEC. */
// In CELT_ONLY mode, packets should not have FEC.
if (payload[0] & 0x80)
return 0;
// For computing the payload length in ms, the sample rate is not important
// since it cancels out. We use 48 kHz, but any valid sample rate would work.
payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
if (10 > payload_length_ms)
payload_length_ms = 10;
// Max number of frames in an Opus packet is 48.
opus_int16 frame_sizes[48];
const unsigned char *frame_data[48];
channels = opus_packet_get_nb_channels(payload);
switch (payload_length_ms) {
case 10:
case 20: {
frames = 1;
break;
}
case 40: {
frames = 2;
break;
}
case 60: {
frames = 3;
break;
}
default: {
return 0; // It is actually even an invalid packet.
}
}
/* The following is to parse the LBRR flags. */
// Parse packet to get the frames. But we only care about the first frame,
// since we can only decode the FEC from the first one.
if (opus_packet_parse(payload, (opus_int32)payload_length_bytes, NULL,
frame_data, frame_sizes, NULL) < 0) {
return 0;
@ -704,8 +680,44 @@ int WebRtcOpus_PacketHasFec(const uint8_t* payload,
return 0;
}
for (n = 0; n < channels; n++) {
if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
// For computing the payload length in ms, the sample rate is not important
// since it cancels out. We use 48 kHz, but any valid sample rate would work.
int payload_length_ms =
opus_packet_get_samples_per_frame(payload, 48000) / 48;
if (payload_length_ms < 10)
payload_length_ms = 10;
int silk_frames;
switch (payload_length_ms) {
case 10:
case 20:
silk_frames = 1;
break;
case 40:
silk_frames = 2;
break;
case 60:
silk_frames = 3;
break;
default:
return 0; // It is actually even an invalid packet.
}
const int channels = opus_packet_get_nb_channels(payload);
RTC_DCHECK(channels == 1 || channels == 2);
// A frame starts with the LP layer. The LP layer begins with two to eight
// header bits.These consist of one VAD bit per SILK frame (up to 3),
// followed by a single flag indicating the presence of LBRR frames.
// For a stereo packet, these first flags correspond to the mid channel, and
// a second set of flags is included for the side channel. Because these are
// the first symbols decoded by the range coder and because they are coded
// as binary values with uniform probability, they can be extracted directly
// from the most significant bits of the first byte of compressed data.
for (int n = 0; n < channels; n++) {
// The LBRR bit for channel 1 is on the (|silk_frames| + 1)-th bit, and
// that of channel 2 is on the |(|silk_frames| + 1) * 2 + 1|-th bit.
if (frame_data[0][0] & (0x80 >> ((n + 1) * (silk_frames + 1) - 1)))
return 1;
}