aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/video_coding/jitter_buffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/video_coding/jitter_buffer.h')
-rw-r--r--webrtc/modules/video_coding/jitter_buffer.h389
1 files changed, 389 insertions, 0 deletions
diff --git a/webrtc/modules/video_coding/jitter_buffer.h b/webrtc/modules/video_coding/jitter_buffer.h
new file mode 100644
index 0000000000..01e27752d2
--- /dev/null
+++ b/webrtc/modules/video_coding/jitter_buffer.h
@@ -0,0 +1,389 @@
+/*
+ * 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_JITTER_BUFFER_H_
+#define WEBRTC_MODULES_VIDEO_CODING_JITTER_BUFFER_H_
+
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/thread_annotations.h"
+#include "webrtc/modules/include/module_common_types.h"
+#include "webrtc/modules/video_coding/include/video_coding.h"
+#include "webrtc/modules/video_coding/include/video_coding_defines.h"
+#include "webrtc/modules/video_coding/decoding_state.h"
+#include "webrtc/modules/video_coding/inter_frame_delay.h"
+#include "webrtc/modules/video_coding/jitter_buffer_common.h"
+#include "webrtc/modules/video_coding/jitter_estimator.h"
+#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+enum VCMNackMode { kNack, kNoNack };
+
+// forward declarations
+class Clock;
+class EventFactory;
+class EventWrapper;
+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 Vp9SsMap {
+ public:
+ typedef std::map<uint32_t, GofInfoVP9, TimestampLessThan> SsMap;
+ bool Insert(const VCMPacket& packet);
+ void Reset();
+
+ // Removes SS data that are older than |timestamp|.
+ // The |timestamp| should be an old timestamp, i.e. packets with older
+ // timestamps should no longer be inserted.
+ void RemoveOld(uint32_t timestamp);
+
+ bool UpdatePacket(VCMPacket* packet);
+ void UpdateFrames(FrameList* frames);
+
+ // Public for testing.
+ // Returns an iterator to the corresponding SS data for the input |timestamp|.
+ bool Find(uint32_t timestamp, SsMap::iterator* it);
+
+ private:
+ // These two functions are called by RemoveOld.
+ // Checks if it is time to do a clean up (done each kSsCleanupIntervalSec).
+ bool TimeForCleanup(uint32_t timestamp) const;
+
+ // Advances the oldest SS data to handle timestamp wrap in cases where SS data
+ // are received very seldom (e.g. only once in beginning, second when
+ // IsNewerTimestamp is not true).
+ void AdvanceFront(uint32_t timestamp);
+
+ SsMap ss_map_;
+};
+
+class VCMJitterBuffer {
+ public:
+ VCMJitterBuffer(Clock* clock, rtc::scoped_ptr<EventWrapper> event);
+
+ ~VCMJitterBuffer();
+
+ // 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 frames, by type, since the jitter buffer
+ // was started.
+ FrameCounts FrameStatistics() 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 received.
+ int num_packets() const;
+
+ // Gets number of duplicated packets received.
+ int num_duplicated_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);
+
+ // 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();
+
+ // Wait |max_wait_time_ms| for a complete frame to arrive.
+ // The function returns true once such a frame is found, its corresponding
+ // timestamp is returned. Otherwise, returns false.
+ bool NextCompleteTimestamp(uint32_t max_wait_time_ms, uint32_t* timestamp);
+
+ // Locates a frame for decoding (even an incomplete) without delay.
+ // The function returns true once such a frame is found, its corresponding
+ // timestamp is returned. Otherwise, returns false.
+ bool NextMaybeIncompleteTimestamp(uint32_t* timestamp);
+
+ // 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();
+
+ // Updates the round-trip time estimate.
+ void UpdateRtt(int64_t rtt_ms);
+
+ // Set the NACK mode. |high_rtt_nack_threshold_ms| is an RTT threshold in ms
+ // above which NACK will be disabled if the NACK mode is |kNack|, -1 meaning
+ // that NACK is always enabled in the |kNack| mode.
+ // |low_rtt_nack_threshold_ms| 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,
+ int64_t low_rtt_nack_threshold_ms,
+ int64_t high_rtt_nack_threshold_ms);
+
+ void SetNackSettings(size_t max_nack_list_size,
+ int max_packet_age_to_nack,
+ int max_incomplete_time_ms);
+
+ // Returns the current NACK mode.
+ VCMNackMode nack_mode() const;
+
+ // Returns a list of the sequence numbers currently missing.
+ std::vector<uint16_t> GetNackList(bool* request_key_frame);
+
+ // Set decode error mode - Should not be changed in the middle of the
+ // session. Changes will not influence frames already in the buffer.
+ void SetDecodeErrorMode(VCMDecodeErrorMode error_mode);
+ int64_t LastDecodedTimestamp() const;
+ VCMDecodeErrorMode decode_error_mode() const { return decode_error_mode_; }
+
+ // Used to compute time of complete continuous frames. Returns the timestamps
+ // corresponding to the start and end of the continuous complete buffer.
+ void RenderBufferSize(uint32_t* timestamp_start, uint32_t* timestamp_end);
+
+ void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
+
+ 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)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // 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
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // Returns true if |frame| is continuous in the |last_decoded_state_|, taking
+ // all decodable frames into account.
+ bool IsContinuous(const VCMFrameBuffer& frame) const
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // Looks for frames in |incomplete_frames_| which are continuous in the
+ // provided |decoded_state|. Starts the search from the timestamp of
+ // |decoded_state|.
+ void FindAndInsertContinuousFramesWithState(
+ const VCMDecodingState& decoded_state)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // 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)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ VCMFrameBuffer* NextFrame() const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // 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)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ 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() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ bool MissingTooOldPacket(uint16_t latest_sequence_number) const
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // 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)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+ // Drops all packets in the NACK list up until |last_decoded_sequence_number|.
+ void DropPacketsFromNackList(uint16_t last_decoded_sequence_number);
+
+ void ReleaseFrameIfNotDecoding(VCMFrameBuffer* frame);
+
+ // Gets an empty frame, creating a new frame if necessary (i.e. increases
+ // jitter buffer size).
+ VCMFrameBuffer* GetEmptyFrame() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // Attempts to increase the size of the jitter buffer. Returns true on
+ // success, false otherwise.
+ bool TryToIncreaseJitterBufferSize() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // 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() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // Updates the frame statistics.
+ // Counts only complete frames, so decodable incomplete frames will not be
+ // counted.
+ void CountFrame(const VCMFrameBuffer& frame)
+ EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // 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() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ // 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 true if we should wait for retransmissions, false otherwise.
+ bool WaitForRetransmissions();
+
+ int NonContinuousOrIncompleteDuration() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ uint16_t EstimatedLowSequenceNumber(const VCMFrameBuffer& frame) const;
+
+ void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
+ Clock* clock_;
+ // If we are running (have started) or not.
+ bool running_;
+ CriticalSectionWrapper* crit_sect_;
+ // Event to signal when we have a frame ready for decoder.
+ rtc::scoped_ptr<EventWrapper> frame_event_;
+ // Number of allocated frames.
+ int max_number_of_frames_;
+ UnorderedFrameList free_frames_ GUARDED_BY(crit_sect_);
+ FrameList decodable_frames_ GUARDED_BY(crit_sect_);
+ FrameList incomplete_frames_ GUARDED_BY(crit_sect_);
+ VCMDecodingState last_decoded_state_ GUARDED_BY(crit_sect_);
+ bool first_packet_since_reset_;
+
+ // Statistics.
+ VCMReceiveStatisticsCallback* stats_callback_ GUARDED_BY(crit_sect_);
+ // Frame counts for each type (key, delta, ...)
+ FrameCounts receive_statistics_;
+ // 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_;
+ // 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 received.
+ int num_packets_ GUARDED_BY(crit_sect_);
+ // Number of duplicated packets received.
+ int num_duplicated_packets_ GUARDED_BY(crit_sect_);
+ // Number of packets discarded by the jitter buffer.
+ int num_discarded_packets_ GUARDED_BY(crit_sect_);
+ // Time when first packet is received.
+ int64_t time_first_packet_ms_ GUARDED_BY(crit_sect_);
+
+ // Jitter estimation.
+ // Filter for estimating jitter.
+ VCMJitterEstimator jitter_estimate_;
+ // Calculates network delays used for jitter calculations.
+ VCMInterFrameDelay inter_frame_delay_;
+ VCMJitterSample waiting_for_completion_;
+ int64_t rtt_ms_;
+
+ // NACK and retransmissions.
+ VCMNackMode nack_mode_;
+ int64_t low_rtt_nack_threshold_ms_;
+ int64_t high_rtt_nack_threshold_ms_;
+ // 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_;
+
+ VCMDecodeErrorMode decode_error_mode_;
+ // 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_;
+ RTC_DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer);
+};
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_VIDEO_CODING_JITTER_BUFFER_H_