
This is a second version of http://review.webrtc.org/1065006/ which passes the parameters via methods instead of via constructors. BUG=1289 Review URL: https://webrtc-codereview.appspot.com/1065007 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3456 4adac7df-926f-26a2-2b94-8c16560cd09d
280 lines
11 KiB
C++
280 lines
11 KiB
C++
/*
|
|
* 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 WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_JITTER_BUFFER_H_
|
|
#define WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_JITTER_BUFFER_H_
|
|
|
|
#include <list>
|
|
#include <vector>
|
|
|
|
#include "webrtc/modules/interface/module_common_types.h"
|
|
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
|
|
#include "webrtc/modules/video_coding/main/source/decoding_state.h"
|
|
#include "webrtc/modules/video_coding/main/source/event.h"
|
|
#include "webrtc/modules/video_coding/main/source/inter_frame_delay.h"
|
|
#include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h"
|
|
#include "webrtc/modules/video_coding/main/source/jitter_estimator.h"
|
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
|
#include "webrtc/typedefs.h"
|
|
|
|
namespace webrtc {
|
|
|
|
enum VCMNackMode {
|
|
kNackInfinite,
|
|
kNackHybrid,
|
|
kNoNack
|
|
};
|
|
|
|
typedef std::list<VCMFrameBuffer*> FrameList;
|
|
|
|
// forward declarations
|
|
class Clock;
|
|
class VCMFrameBuffer;
|
|
class VCMPacket;
|
|
class VCMEncodedFrame;
|
|
|
|
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 VCMJitterBuffer {
|
|
public:
|
|
VCMJitterBuffer(Clock* clock,
|
|
int vcm_id,
|
|
int receiver_id,
|
|
bool master);
|
|
virtual ~VCMJitterBuffer();
|
|
|
|
// Makes |this| a deep copy of |rhs|.
|
|
void CopyFrom(const VCMJitterBuffer& rhs);
|
|
|
|
// 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();
|
|
|
|
// Get the number of received key and delta frames since the jitter buffer
|
|
// was started.
|
|
void FrameStatistics(uint32_t* received_delta_frames,
|
|
uint32_t* received_key_frames) const;
|
|
|
|
// The number of packets discarded by the jitter buffer because the decoder
|
|
// won't be able to decode them.
|
|
int num_not_decodable_packets() const;
|
|
|
|
// Gets number of packets discarded by the jitter buffer.
|
|
int num_discarded_packets() const;
|
|
|
|
// Statistics, Calculate frame and bit rates.
|
|
void IncomingRateStatistics(unsigned int* framerate,
|
|
unsigned int* bitrate);
|
|
|
|
// Waits for the first packet in the next frame to arrive and then returns
|
|
// the timestamp of that frame. |incoming_frame_type| and |render_time_ms| are
|
|
// set to the frame type and render time of the next frame.
|
|
// Blocks for up to |max_wait_time_ms| ms. Returns -1 if no packet has arrived
|
|
// after |max_wait_time_ms| ms.
|
|
int64_t NextTimestamp(uint32_t max_wait_time_ms,
|
|
FrameType* incoming_frame_type,
|
|
int64_t* render_time_ms);
|
|
|
|
// Checks if the packet sequence will be complete if the next frame would be
|
|
// grabbed for decoding. That is, if a frame has been lost between the
|
|
// last decoded frame and the next, or if the next frame is missing one
|
|
// or more packets.
|
|
bool CompleteSequenceWithNextFrame();
|
|
|
|
// TODO(mikhal/stefan): Merge all GetFrameForDecoding into one.
|
|
// Wait |max_wait_time_ms| for a complete frame to arrive. After timeout NULL
|
|
// is returned.
|
|
VCMEncodedFrame* GetCompleteFrameForDecoding(uint32_t max_wait_time_ms);
|
|
|
|
// Get a frame for decoding (even an incomplete) without delay.
|
|
VCMEncodedFrame* GetFrameForDecoding();
|
|
|
|
// Releases a frame returned from the jitter buffer, should be called when
|
|
// done with decoding.
|
|
void ReleaseFrame(VCMEncodedFrame* frame);
|
|
|
|
// Returns the frame assigned to this timestamp.
|
|
int GetFrame(const VCMPacket& packet, VCMEncodedFrame*&);
|
|
VCMEncodedFrame* GetFrame(const VCMPacket& packet); // Deprecated.
|
|
|
|
// 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(VCMEncodedFrame* frame, bool* retransmitted) const;
|
|
|
|
// Inserts a packet into a frame returned from GetFrame().
|
|
VCMFrameBufferEnum InsertPacket(VCMEncodedFrame* frame,
|
|
const VCMPacket& packet);
|
|
|
|
// Enable a max filter on the jitter estimate, and setting of the initial
|
|
// delay (only when in max mode). When disabled (default), the last jitter
|
|
// estimate will be used.
|
|
void EnableMaxJitterEstimate(bool enable, uint32_t initial_delay_ms);
|
|
|
|
// Returns the estimated jitter in milliseconds.
|
|
uint32_t EstimatedJitterMs();
|
|
|
|
// Updates the round-trip time estimate.
|
|
void UpdateRtt(uint32_t rtt_ms);
|
|
|
|
// Set the NACK mode. |highRttNackThreshold| is an RTT threshold in ms above
|
|
// which NACK will be disabled if the NACK mode is |kNackHybrid|, -1 meaning
|
|
// that NACK is always enabled in the hybrid mode.
|
|
// |lowRttNackThreshold| is an RTT threshold in ms below which we expect to
|
|
// rely on NACK only, and therefore are using larger buffers to have time to
|
|
// wait for retransmissions.
|
|
void SetNackMode(VCMNackMode mode, int low_rtt_nack_threshold_ms,
|
|
int high_rtt_nack_threshold_ms);
|
|
|
|
void SetNackSettings(size_t max_nack_list_size,
|
|
int max_packet_age_to_nack);
|
|
|
|
// Returns the current NACK mode.
|
|
VCMNackMode nack_mode() const;
|
|
|
|
// Creates a list of missing sequence numbers.
|
|
uint16_t* CreateNackList(uint16_t* nack_list_size, bool* list_extended);
|
|
|
|
int64_t LastDecodedTimestamp() const;
|
|
|
|
private:
|
|
// In NACK-only mode this function doesn't return or release non-complete
|
|
// frames unless we have a complete key frame. In hybrid mode, we may release
|
|
// "decodable", incomplete frames.
|
|
VCMEncodedFrame* GetFrameForDecodingNACK();
|
|
|
|
void ReleaseFrameIfNotDecoding(VCMFrameBuffer* frame);
|
|
|
|
// Gets an empty frame, creating a new frame if necessary (i.e. increases
|
|
// jitter buffer size).
|
|
VCMFrameBuffer* GetEmptyFrame();
|
|
|
|
// 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();
|
|
|
|
// Sets the state of |frame| to complete if it's not too old to be decoded.
|
|
// Also updates the frame statistics. Signals the |frame_event| if this is
|
|
// the next frame to be decoded.
|
|
VCMFrameBufferEnum UpdateFrameState(VCMFrameBuffer* frame);
|
|
|
|
// Finds the oldest complete frame, used for getting next frame to decode.
|
|
// Can return a decodable, incomplete frame if |enable_decodable| is true.
|
|
FrameList::iterator FindOldestCompleteContinuousFrame(bool enable_decodable);
|
|
|
|
void CleanUpOldFrames();
|
|
|
|
// Sets the "decodable" and "frame loss" flags of a frame depending on which
|
|
// packets have been received and which are missing.
|
|
// A frame is "decodable" if enough packets of that frame has been received
|
|
// for it to be usable by the decoder.
|
|
// A frame has the "frame loss" flag set if packets are missing after the
|
|
// last decoded frame and before |frame|.
|
|
void VerifyAndSetPreviousFrameLost(VCMFrameBuffer* frame);
|
|
|
|
// 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);
|
|
|
|
// Returns the lowest and highest known sequence numbers, where the lowest is
|
|
// the last decoded sequence number if a frame has been decoded.
|
|
// -1 is returned if a sequence number cannot be determined.
|
|
void GetLowHighSequenceNumbers(int32_t* low_seq_num,
|
|
int32_t* high_seq_num) const;
|
|
|
|
// Returns true if we should wait for retransmissions, false otherwise.
|
|
bool WaitForRetransmissions();
|
|
|
|
int vcm_id_;
|
|
int receiver_id_;
|
|
Clock* clock_;
|
|
// If we are running (have started) or not.
|
|
bool running_;
|
|
CriticalSectionWrapper* crit_sect_;
|
|
bool master_;
|
|
// Event to signal when we have a frame ready for decoder.
|
|
VCMEvent frame_event_;
|
|
// Event to signal when we have received a packet.
|
|
VCMEvent packet_event_;
|
|
// Number of allocated frames.
|
|
int max_number_of_frames_;
|
|
// Array of pointers to the frames in jitter buffer.
|
|
VCMFrameBuffer* frame_buffers_[kMaxNumberOfFrames];
|
|
FrameList frame_list_;
|
|
VCMDecodingState last_decoded_state_;
|
|
bool first_packet_;
|
|
|
|
// Statistics.
|
|
int num_not_decodable_packets_;
|
|
// Frame counter for each type (key, delta, golden, key-delta).
|
|
unsigned int receive_statistics_[4];
|
|
// Latest calculated frame rates of incoming stream.
|
|
unsigned int incoming_frame_rate_;
|
|
unsigned int incoming_frame_count_;
|
|
int64_t time_last_incoming_frame_count_;
|
|
unsigned int incoming_bit_count_;
|
|
unsigned int incoming_bit_rate_;
|
|
unsigned int drop_count_; // Frame drop counter.
|
|
// Number of frames in a row that have been too old.
|
|
int num_consecutive_old_frames_;
|
|
// Number of packets in a row that have been too old.
|
|
int num_consecutive_old_packets_;
|
|
// Number of packets discarded by the jitter buffer.
|
|
int num_discarded_packets_;
|
|
|
|
// Jitter estimation.
|
|
// Filter for estimating jitter.
|
|
VCMJitterEstimator jitter_estimate_;
|
|
// Calculates network delays used for jitter calculations.
|
|
VCMInterFrameDelay inter_frame_delay_;
|
|
VCMJitterSample waiting_for_completion_;
|
|
WebRtc_UWord32 rtt_ms_;
|
|
|
|
// NACK and retransmissions.
|
|
VCMNackMode nack_mode_;
|
|
int low_rtt_nack_threshold_ms_;
|
|
int high_rtt_nack_threshold_ms_;
|
|
// Holds the internal NACK list (the missing sequence numbers).
|
|
std::vector<int> nack_seq_nums_internal_;
|
|
std::vector<uint16_t> nack_seq_nums_;
|
|
unsigned int nack_seq_nums_length_;
|
|
size_t max_nack_list_size_;
|
|
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
|
bool waiting_for_key_frame_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer);
|
|
};
|
|
} // namespace webrtc
|
|
|
|
#endif // WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_JITTER_BUFFER_H_
|