webrtc_m130/modules/video_coding/jitter_buffer.h

273 lines
11 KiB
C
Raw Normal View History

/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_VIDEO_CODING_JITTER_BUFFER_H_
#define MODULES_VIDEO_CODING_JITTER_BUFFER_H_
#include <list>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "modules/include/module_common_types.h"
#include "modules/include/module_common_types_public.h"
#include "modules/video_coding/decoding_state.h"
#include "modules/video_coding/event_wrapper.h"
#include "modules/video_coding/include/video_coding.h"
#include "modules/video_coding/include/video_coding_defines.h"
#include "modules/video_coding/inter_frame_delay.h"
#include "modules/video_coding/jitter_buffer_common.h"
#include "modules/video_coding/jitter_estimator.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
// forward declarations
class Clock;
class VCMFrameBuffer;
class VCMPacket;
class VCMEncodedFrame;
typedef std::list<VCMFrameBuffer*> UnorderedFrameList;
struct VCMJitterSample {
VCMJitterSample() : timestamp(0), frame_size(0), latest_packet_time(-1) {}
uint32_t timestamp;
uint32_t frame_size;
int64_t latest_packet_time;
};
class TimestampLessThan {
public:
bool operator()(uint32_t timestamp1, uint32_t timestamp2) const {
return IsNewerTimestamp(timestamp2, timestamp1);
}
};
class FrameList
: public std::map<uint32_t, VCMFrameBuffer*, TimestampLessThan> {
public:
void InsertFrame(VCMFrameBuffer* frame);
VCMFrameBuffer* PopFrame(uint32_t timestamp);
VCMFrameBuffer* Front() const;
VCMFrameBuffer* Back() const;
int RecycleFramesUntilKeyFrame(FrameList::iterator* key_frame_it,
UnorderedFrameList* free_frames);
void CleanUpOldOrEmptyFrames(VCMDecodingState* decoding_state,
UnorderedFrameList* free_frames);
void Reset(UnorderedFrameList* free_frames);
};
class VCMJitterBuffer {
public:
VCMJitterBuffer(Clock* clock, std::unique_ptr<EventWrapper> event);
~VCMJitterBuffer();
VCMJitterBuffer(const VCMJitterBuffer&) = delete;
VCMJitterBuffer& operator=(const VCMJitterBuffer&) = delete;
// Initializes and starts jitter buffer.
void Start();
// Signals all internal events and stops the jitter buffer.
void Stop();
// Returns true if the jitter buffer is running.
bool Running() const;
// Empty the jitter buffer of all its data.
void Flush();
// Gets number of packets received.
int num_packets() const;
// Gets number of duplicated packets received.
int num_duplicated_packets() const;
// Wait `max_wait_time_ms` for a complete frame to arrive.
// If found, a pointer to the frame is returned. Returns nullptr otherwise.
VCMEncodedFrame* NextCompleteFrame(uint32_t max_wait_time_ms);
// Extract frame corresponding to input timestamp.
// Frame will be set to a decoding state.
VCMEncodedFrame* ExtractAndSetDecode(uint32_t timestamp);
// Releases a frame returned from the jitter buffer, should be called when
// done with decoding.
void ReleaseFrame(VCMEncodedFrame* frame);
// Returns the time in ms when the latest packet was inserted into the frame.
// Retransmitted is set to true if any of the packets belonging to the frame
// has been retransmitted.
int64_t LastPacketTime(const VCMEncodedFrame* frame,
bool* retransmitted) const;
// Inserts a packet into a frame returned from GetFrame().
// If the return value is <= 0, `frame` is invalidated and the pointer must
// be dropped after this function returns.
VCMFrameBufferEnum InsertPacket(const VCMPacket& packet, bool* retransmitted);
// Returns the estimated jitter in milliseconds.
uint32_t EstimatedJitterMs();
void SetNackSettings(size_t max_nack_list_size,
int max_packet_age_to_nack,
int max_incomplete_time_ms);
// Returns a list of the sequence numbers currently missing.
std::vector<uint16_t> GetNackList(bool* request_key_frame);
private:
class SequenceNumberLessThan {
public:
bool operator()(const uint16_t& sequence_number1,
const uint16_t& sequence_number2) const {
return IsNewerSequenceNumber(sequence_number2, sequence_number1);
}
};
typedef std::set<uint16_t, SequenceNumberLessThan> SequenceNumberSet;
// Gets the frame assigned to the timestamp of the packet. May recycle
// existing frames if no free frames are available. Returns an error code if
// failing, or kNoError on success. `frame_list` contains which list the
// packet was in, or NULL if it was not in a FrameList (a new frame).
VCMFrameBufferEnum GetFrame(const VCMPacket& packet,
VCMFrameBuffer** frame,
FrameList** frame_list)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Returns true if `frame` is continuous in `decoding_state`, not taking
// decodable frames into account.
bool IsContinuousInState(const VCMFrameBuffer& frame,
const VCMDecodingState& decoding_state) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Returns true if `frame` is continuous in the `last_decoded_state_`, taking
// all decodable frames into account.
bool IsContinuous(const VCMFrameBuffer& frame) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Looks for frames in `incomplete_frames_` which are continuous in the
// provided `decoded_state`. Starts the search from the timestamp of
// `decoded_state`.
Fix jitter buffer bug around out-of-order packets and non-RTX padding. tl;dr - non-continuous frames (due to padding) would get stuck as incomplete if the previous complete frame arrived and was decoded before the padding arrived.This fix re-checks the incomplete frame list for continuous frames after old packets arrive. When padding is enabled and RTX is not, padding is sent as empty RTP packets tacked onto the end of completed frames (meaning: same timestamp, but after a packet with the marker bit set). Given the following set of circumstances, codified in the new unit test method, a frame can get permanently stuck in the incomplete frames list: - Frame A decoded (packets 94-95). Next expected sequence number is 96. - Frame C arrives (packets 100-101) and is marked complete. It isn't continuous, since it starts at 100, so it's placed in the incomplete frame list. - Frame B arrives (packets 96-97) and is complete, since 97 has a marker bit. Turns out that packets 98-99 are padding, but the receiver doesn't know that. - Frame B is decoded, removed from the decodable frames list, and last decoded state is updated. - Packets 98-99 arrive. They hit the IsOldPacket check and update the last decoded state, but they don't trigger FindAndInsertContinuousFrames. - Further packets/frames arrive and complete, but FindAndInsertContinuousFrames only runs on frames that are newer than the newly completed frame. In this state, Frame C is permanently stuck as incomplete, so the jitter buffer overall is stuck until max NACK age (default: 450 packets), the max NACK list size (default: 200 packets), or a keyframe arrives and IsContinuous returns true for the keyframe. (Before the November refactoring, Frame B wouldn't have to have been decoded for the bug to trigger; just having a complete continuous frame at any time before the padding arrived would cause this state, as FindAndInsertContinuousFrames was only called when the frame originally became continuous and was inserted into the decodable frames list. Post refactoring, the frame is removed/re-added to the decodable list on every padding packet that arrives) BUG= R=stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/50959004 Cr-Commit-Position: refs/heads/master@{#9264}
2015-05-22 14:03:00 -07:00
void FindAndInsertContinuousFramesWithState(
const VCMDecodingState& decoded_state)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Looks for frames in `incomplete_frames_` which are continuous in
// `last_decoded_state_` taking all decodable frames into account. Starts
// the search from `new_frame`.
void FindAndInsertContinuousFrames(const VCMFrameBuffer& new_frame)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
VCMFrameBuffer* NextFrame() const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Returns true if the NACK list was updated to cover sequence numbers up to
// `sequence_number`. If false a key frame is needed to get into a state where
// we can continue decoding.
bool UpdateNackList(uint16_t sequence_number)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool TooLargeNackList() const;
// Returns true if the NACK list was reduced without problem. If false a key
// frame is needed to get into a state where we can continue decoding.
bool HandleTooLargeNackList() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool MissingTooOldPacket(uint16_t latest_sequence_number) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Returns true if the too old packets was successfully removed from the NACK
// list. If false, a key frame is needed to get into a state where we can
// continue decoding.
bool HandleTooOldPackets(uint16_t latest_sequence_number)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Drops all packets in the NACK list up until `last_decoded_sequence_number`.
void DropPacketsFromNackList(uint16_t last_decoded_sequence_number);
// Gets an empty frame, creating a new frame if necessary (i.e. increases
// jitter buffer size).
VCMFrameBuffer* GetEmptyFrame() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Attempts to increase the size of the jitter buffer. Returns true on
// success, false otherwise.
bool TryToIncreaseJitterBufferSize() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Recycles oldest frames until a key frame is found. Used if jitter buffer is
// completely full. Returns true if a key frame was found.
bool RecycleFramesUntilKeyFrame() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Update rolling average of packets per frame.
void UpdateAveragePacketsPerFrame(int current_number_packets_);
// Cleans the frame list in the JB from old/empty frames.
// Should only be called prior to actual use.
void CleanUpOldOrEmptyFrames() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Returns true if `packet` is likely to have been retransmitted.
bool IsPacketRetransmitted(const VCMPacket& packet) const;
// The following three functions update the jitter estimate with the
// payload size, receive time and RTP timestamp of a frame.
void UpdateJitterEstimate(const VCMJitterSample& sample,
bool incomplete_frame);
void UpdateJitterEstimate(const VCMFrameBuffer& frame, bool incomplete_frame);
void UpdateJitterEstimate(int64_t latest_packet_time_ms,
uint32_t timestamp,
unsigned int frame_size,
bool incomplete_frame);
int NonContinuousOrIncompleteDuration() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
uint16_t EstimatedLowSequenceNumber(const VCMFrameBuffer& frame) const;
// Reset frame buffer and return it to free_frames_.
void RecycleFrameBuffer(VCMFrameBuffer* frame)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Clock* clock_;
// If we are running (have started) or not.
bool running_;
mutable Mutex mutex_;
// Event to signal when we have a frame ready for decoder.
std::unique_ptr<EventWrapper> frame_event_;
// Number of allocated frames.
int max_number_of_frames_;
UnorderedFrameList free_frames_ RTC_GUARDED_BY(mutex_);
FrameList decodable_frames_ RTC_GUARDED_BY(mutex_);
FrameList incomplete_frames_ RTC_GUARDED_BY(mutex_);
VCMDecodingState last_decoded_state_ RTC_GUARDED_BY(mutex_);
bool first_packet_since_reset_;
// Number of packets in a row that have been too old.
int num_consecutive_old_packets_;
// Number of packets received.
int num_packets_ RTC_GUARDED_BY(mutex_);
// Number of duplicated packets received.
int num_duplicated_packets_ RTC_GUARDED_BY(mutex_);
// Jitter estimation.
// Filter for estimating jitter.
VCMJitterEstimator jitter_estimate_;
// Calculates network delays used for jitter calculations.
VCMInterFrameDelay inter_frame_delay_;
VCMJitterSample waiting_for_completion_;
// Holds the internal NACK list (the missing sequence numbers).
SequenceNumberSet missing_sequence_numbers_;
uint16_t latest_received_sequence_number_;
size_t max_nack_list_size_;
int max_packet_age_to_nack_; // Measured in sequence numbers.
int max_incomplete_time_ms_;
// Estimated rolling average of packets per frame
float average_packets_per_frame_;
// average_packets_per_frame converges fast if we have fewer than this many
// frames.
int frame_counter_;
};
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_JITTER_BUFFER_H_