Returning correct duration estimate on Opus DTX packets.

Bug 4985 revealed two flaws
1. Opus duration estimate did not return correct length for DTX packets,

2. NetEq DoCodecInternalCng did not assign enough buffer.

P.S.
Generalizing problem 1, current NetEq decode function checks memory size by calling the duration estimate function. This is not ideal. A better way is to let codec's decode function to receive buffer size and return failure if it is not enough. This can be made in a separate CL.

BUG=webrtc:4985
R=henrik.lundin@webrtc.org

Review URL: https://codereview.webrtc.org/1334303005 .

Cr-Commit-Position: refs/heads/master@{#10031}
This commit is contained in:
minyuel
2015-09-23 15:20:39 +02:00
parent c14f5ff60f
commit 6d92bf59f3
7 changed files with 343 additions and 30 deletions

View File

@ -61,7 +61,8 @@ class AudioDecoder {
virtual bool HasDecodePlc() const;
// Calls the packet-loss concealment of the decoder to update the state after
// one or several lost packets.
// one or several lost packets. The caller has to make sure that the
// memory allocated in |decoded| should accommodate |num_frames| frames.
virtual size_t DecodePlc(size_t num_frames, int16_t* decoded);
// Resets the decoder state (empty buffers etc.).

View File

@ -294,6 +294,20 @@ int WebRtcOpus_DurationEst(OpusDecInst* inst,
const uint8_t* payload,
size_t payload_length_bytes);
/****************************************************************************
* WebRtcOpus_PlcDuration(...)
*
* This function calculates the duration of a frame returned by packet loss
* concealment (PLC).
*
* Input:
* - inst : Decoder context
*
* Return value : The duration of a frame returned by PLC, in
* samples per channel.
*/
int WebRtcOpus_PlcDuration(OpusDecInst* inst);
/* TODO(minyue): Check whether it is needed to add a decoder context to the
* arguments, like WebRtcOpus_DurationEst(...). In fact, the packet itself tells
* the duration. The decoder context in WebRtcOpus_DurationEst(...) is not used.

View File

@ -359,6 +359,12 @@ int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
int WebRtcOpus_DurationEst(OpusDecInst* inst,
const uint8_t* payload,
size_t payload_length_bytes) {
if (payload_length_bytes == 0) {
// WebRtcOpus_Decode calls PLC when payload length is zero. So we return
// PLC duration correspondingly.
return WebRtcOpus_PlcDuration(inst);
}
int frames, samples;
frames = opus_packet_get_nb_frames(payload, (opus_int32)payload_length_bytes);
if (frames < 0) {
@ -373,6 +379,15 @@ int WebRtcOpus_DurationEst(OpusDecInst* inst,
return samples;
}
int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
/* The number of samples we ask for is |number_of_lost_frames| times
* |prev_decoded_samples_|. Limit the number of samples to maximum
* |kWebRtcOpusMaxFrameSizePerChannel|. */
const int plc_samples = inst->prev_decoded_samples;
return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
}
int WebRtcOpus_FecDurationEst(const uint8_t* payload,
size_t payload_length_bytes) {
int samples;

View File

@ -105,9 +105,12 @@ int OpusTest::EncodeDecode(WebRtcOpusEncInst* encoder,
kMaxBytes, bitstream_);
EXPECT_GE(encoded_bytes_int, 0);
encoded_bytes_ = static_cast<size_t>(encoded_bytes_int);
return WebRtcOpus_Decode(decoder, bitstream_,
encoded_bytes_, output_audio,
audio_type);
int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_);
int act_len = WebRtcOpus_Decode(decoder, bitstream_,
encoded_bytes_, output_audio,
audio_type);
EXPECT_EQ(est_len, act_len);
return act_len;
}
// Test if encoder/decoder can enter DTX mode properly and do not enter DTX when