| /* |
| * Copyright (c) 2011 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 "typedefs.h" |
| #include "critical_section_wrapper.h" |
| #include "decoding_state.h" |
| #include "module_common_types.h" |
| #include "video_coding_defines.h" |
| #include "inter_frame_delay.h" |
| #include "event.h" |
| #include "frame_list.h" |
| #include "jitter_buffer_common.h" |
| #include "jitter_estimator.h" |
| |
| namespace webrtc |
| { |
| |
| enum VCMNackMode |
| { |
| kNackInfinite, |
| kNackHybrid, |
| kNoNack |
| }; |
| |
| // forward declarations |
| class TickTimeBase; |
| class VCMFrameBuffer; |
| class VCMPacket; |
| class VCMEncodedFrame; |
| |
| class VCMJitterSample |
| { |
| public: |
| VCMJitterSample() : timestamp(0), frameSize(0), latestPacketTime(-1) {} |
| WebRtc_UWord32 timestamp; |
| WebRtc_UWord32 frameSize; |
| WebRtc_Word64 latestPacketTime; |
| }; |
| |
| class VCMJitterBuffer |
| { |
| public: |
| VCMJitterBuffer(TickTimeBase* clock, |
| WebRtc_Word32 vcmId = -1, |
| WebRtc_Word32 receiverId = -1, |
| bool master = true); |
| virtual ~VCMJitterBuffer(); |
| |
| void CopyFrom(const VCMJitterBuffer& rhs); |
| |
| // We need a start and stop to break out of the wait event |
| // used in GetCompleteFrameForDecoding |
| void Start(); |
| void Stop(); |
| bool Running() const; |
| |
| // Empty the Jitter buffer of all its data |
| void Flush(); |
| |
| // Statistics, Get received key and delta frames |
| WebRtc_Word32 GetFrameStatistics(WebRtc_UWord32& receivedDeltaFrames, |
| WebRtc_UWord32& receivedKeyFrames) const; |
| |
| // The number of packets discarded by the jitter buffer because the decoder |
| // won't be able to decode them. |
| WebRtc_UWord32 NumNotDecodablePackets() const; |
| // Get number of packets discarded by the jitter buffer |
| WebRtc_UWord32 DiscardedPackets() const; |
| |
| // Statistics, Calculate frame and bit rates |
| WebRtc_Word32 GetUpdate(WebRtc_UWord32& frameRate, WebRtc_UWord32& bitRate); |
| |
| // Wait for the first packet in the next frame to arrive, blocks |
| // for <= maxWaitTimeMS ms |
| WebRtc_Word64 GetNextTimeStamp(WebRtc_UWord32 maxWaitTimeMS, |
| FrameType& incomingFrameType, |
| WebRtc_Word64& renderTimeMs); |
| |
| // Will the packet sequence be complete if the next frame is grabbed |
| // for decoding right now? That is, have we lost a frame between the |
| // last decoded frame and the next, or is the next frame missing one |
| // or more packets? |
| bool CompleteSequenceWithNextFrame(); |
| |
| // TODO (mikhal/stefan): Merge all GetFrameForDecoding into one. |
| // Wait maxWaitTimeMS for a complete frame to arrive. After timeout NULL |
| // is returned. |
| VCMEncodedFrame* GetCompleteFrameForDecoding(WebRtc_UWord32 maxWaitTimeMS); |
| |
| // Get a frame for decoding (even an incomplete) without delay. |
| VCMEncodedFrame* GetFrameForDecoding(); |
| |
| VCMEncodedFrame* GetFrameForDecodingNACK(); |
| |
| // Release frame (when done with decoding) |
| void ReleaseFrame(VCMEncodedFrame* frame); |
| |
| // Get frame to use for this timestamp |
| WebRtc_Word32 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. |
| WebRtc_Word64 LastPacketTime(VCMEncodedFrame* frame, |
| bool& retransmitted) const; |
| |
| // Insert a packet into a frame |
| VCMFrameBufferEnum InsertPacket(VCMEncodedFrame* frame, |
| const VCMPacket& packet); |
| |
| // Sync |
| WebRtc_UWord32 GetEstimatedJitterMS(); |
| void UpdateRtt(WebRtc_UWord32 rttMs); |
| |
| // NACK |
| // 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 lowRttNackThresholdMs, |
| int highRttNackThresholdMs); |
| VCMNackMode GetNackMode() const; // Get nack mode |
| // Get list of missing sequence numbers (size in number of elements) |
| WebRtc_UWord16* GetNackList(WebRtc_UWord16& nackSize, |
| bool& listExtended); |
| |
| WebRtc_Word64 LastDecodedTimestamp() const; |
| |
| private: |
| // Misc help functions |
| // Recycle (release) frame, used if we didn't receive whole frame |
| void RecycleFrame(VCMFrameBuffer* frame); |
| void ReleaseFrameInternal(VCMFrameBuffer* frame); |
| // Flush and reset the jitter buffer. Call under critical section. |
| void FlushInternal(); |
| |
| // Help functions for insert packet |
| // Get empty frame, creates new (i.e. increases JB size) if necessary |
| VCMFrameBuffer* GetEmptyFrame(); |
| // Recycle oldest frames up to a key frame, used if JB is completely full |
| bool RecycleFramesUntilKeyFrame(); |
| // Update frame state |
| // (set as complete or reconstructable if conditions are met) |
| VCMFrameBufferEnum UpdateFrameState(VCMFrameBuffer* frameListItem); |
| |
| // Help functions for getting a frame |
| // Find oldest complete frame, used for getting next frame to decode |
| // When enabled, will return a decodable frame |
| VCMFrameListItem* FindOldestCompleteContinuousFrame(bool enableDecodable); |
| |
| void CleanUpOldFrames(); |
| |
| void VerifyAndSetPreviousFrameLost(VCMFrameBuffer& frame); |
| bool IsPacketRetransmitted(const VCMPacket& packet) const; |
| |
| void UpdateJitterAndDelayEstimates(VCMJitterSample& sample, |
| bool incompleteFrame); |
| void UpdateJitterAndDelayEstimates(VCMFrameBuffer& frame, |
| bool incompleteFrame); |
| void UpdateJitterAndDelayEstimates(WebRtc_Word64 latestPacketTimeMs, |
| WebRtc_UWord32 timestamp, |
| WebRtc_UWord32 frameSize, |
| bool incompleteFrame); |
| void UpdateOldJitterSample(const VCMPacket& packet); |
| WebRtc_UWord32 GetEstimatedJitterMsInternal(); |
| |
| // NACK help |
| WebRtc_UWord16* CreateNackList(WebRtc_UWord16& nackSize, |
| bool& listExtended); |
| WebRtc_Word32 GetLowHighSequenceNumbers(WebRtc_Word32& lowSeqNum, |
| WebRtc_Word32& highSeqNum) const; |
| |
| static bool FrameEqualTimestamp(VCMFrameBuffer* frame, |
| const void* timestamp); |
| static bool CompleteDecodableKeyFrameCriteria(VCMFrameBuffer* frame, |
| const void* notUsed); |
| // Decide whether should wait for NACK (mainly relevant for hybrid mode) |
| bool WaitForNack(); |
| |
| WebRtc_Word32 _vcmId; |
| WebRtc_Word32 _receiverId; |
| TickTimeBase* _clock; |
| // If we are running (have started) or not |
| bool _running; |
| CriticalSectionWrapper* _critSect; |
| bool _master; |
| // Event to signal when we have a frame ready for decoder |
| VCMEvent _frameEvent; |
| // Event to signal when we have received a packet |
| VCMEvent _packetEvent; |
| // Number of allocated frames |
| WebRtc_Word32 _maxNumberOfFrames; |
| // Array of pointers to the frames in JB |
| VCMFrameBuffer* _frameBuffers[kMaxNumberOfFrames]; |
| VCMFrameListTimestampOrderAsc _frameBuffersTSOrder; |
| |
| // timing |
| VCMDecodingState _lastDecodedState; |
| WebRtc_UWord32 _packetsNotDecodable; |
| |
| // Statistics |
| // Frame counter for each type (key, delta, golden, key-delta) |
| WebRtc_UWord8 _receiveStatistics[4]; |
| // Latest calculated frame rates of incoming stream |
| WebRtc_UWord8 _incomingFrameRate; |
| // Frame counter, reset in GetUpdate |
| WebRtc_UWord32 _incomingFrameCount; |
| // Real time for last _frameCount reset |
| WebRtc_Word64 _timeLastIncomingFrameCount; |
| // Received bits counter, reset in GetUpdate |
| WebRtc_UWord32 _incomingBitCount; |
| WebRtc_UWord32 _incomingBitRate; |
| WebRtc_UWord32 _dropCount; // Frame drop counter |
| // Number of frames in a row that have been too old |
| WebRtc_UWord32 _numConsecutiveOldFrames; |
| // Number of packets in a row that have been too old |
| WebRtc_UWord32 _numConsecutiveOldPackets; |
| // Number of packets discarded by the jitter buffer |
| WebRtc_UWord32 _discardedPackets; |
| |
| // Filters for estimating jitter |
| VCMJitterEstimator _jitterEstimate; |
| // Calculates network delays used for jitter calculations |
| VCMInterFrameDelay _delayEstimate; |
| VCMJitterSample _waitingForCompletion; |
| WebRtc_UWord32 _rttMs; |
| |
| // NACK |
| VCMNackMode _nackMode; |
| int _lowRttNackThresholdMs; |
| int _highRttNackThresholdMs; |
| // Holds the internal nack list (the missing sequence numbers) |
| WebRtc_Word32 _NACKSeqNumInternal[kNackHistoryLength]; |
| WebRtc_UWord16 _NACKSeqNum[kNackHistoryLength]; |
| WebRtc_UWord32 _NACKSeqNumLength; |
| bool _waitingForKeyFrame; |
| |
| bool _firstPacket; |
| |
| DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer); |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // WEBRTC_MODULES_VIDEO_CODING_JITTER_BUFFER_H_ |