diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8.cc index e94f41026..6de1dafbf 100644 --- a/src/modules/rtp_rtcp/source/rtp_format_vp8.cc +++ b/src/modules/rtp_rtcp/source/rtp_format_vp8.cc @@ -318,11 +318,7 @@ int RtpFormatVp8::WriteTIDFields(WebRtc_UWord8* x_field, int RtpFormatVp8::PayloadDescriptorExtraLength() const { - int length_bytes = 0; - if (beginning_) - { - length_bytes = PictureIdLength(); - } + int length_bytes = PictureIdLength(); if (TL0PicIdxFieldPresent()) ++length_bytes; if (TIDFieldPresent()) ++length_bytes; if (length_bytes > 0) ++length_bytes; // Include the extension field. @@ -331,7 +327,7 @@ int RtpFormatVp8::PayloadDescriptorExtraLength() const int RtpFormatVp8::PictureIdLength() const { - if (!beginning_ || hdr_info_.pictureId == kNoPictureId) + if (hdr_info_.pictureId == kNoPictureId) { return 0; } diff --git a/src/modules/video_coding/codecs/vp8/main/interface/vp8.h b/src/modules/video_coding/codecs/vp8/main/interface/vp8.h index d1086a9c0..47ada1911 100644 --- a/src/modules/video_coding/codecs/vp8/main/interface/vp8.h +++ b/src/modules/video_coding/codecs/vp8/main/interface/vp8.h @@ -268,6 +268,7 @@ private: EncodedImage _lastKeyFrame; int _imageFormat; vpx_ref_frame_t* _refFrame; + int _propagationCnt; };// end of VP8Decoder class diff --git a/src/modules/video_coding/codecs/vp8/main/source/vp8.cc b/src/modules/video_coding/codecs/vp8/main/source/vp8.cc index 005515b41..bfe121337 100644 --- a/src/modules/video_coding/codecs/vp8/main/source/vp8.cc +++ b/src/modules/video_coding/codecs/vp8/main/source/vp8.cc @@ -28,7 +28,7 @@ #include "module_common_types.h" -#define VP8_FREQ_HZ 90000 +enum { kVp8ErrorPropagationTh = 60 }; //#define DEV_PIC_LOSS namespace webrtc @@ -725,7 +725,8 @@ VP8Decoder::VP8Decoder(): _numCores(1), _lastKeyFrame(), _imageFormat(VPX_IMG_FMT_NONE), - _refFrame(NULL) + _refFrame(NULL), + _propagationCnt(-1) { } @@ -752,6 +753,7 @@ VP8Decoder::Reset() { InitDecode(NULL, _numCores); } + _propagationCnt = -1; return WEBRTC_VIDEO_CODEC_OK; } @@ -811,6 +813,7 @@ VP8Decoder::InitDecode(const VideoCodec* inst, *_inst = *inst; } _numCores = numberOfCores; + _propagationCnt = -1; _inited = true; return WEBRTC_VIDEO_CODEC_OK; @@ -822,7 +825,7 @@ VP8Decoder::Decode(const EncodedImage& inputImage, const RTPFragmentationHeader* fragmentation, const CodecSpecificInfo* codecSpecificInfo, WebRtc_Word64 /*renderTimeMs*/) - { +{ if (!_inited) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; @@ -853,6 +856,17 @@ VP8Decoder::Decode(const EncodedImage& inputImage, } #endif + // Restrict error propagation + // Reset on a key frame refresh + if (inputImage._frameType == kKeyFrame && inputImage._completeFrame) + _propagationCnt = -1; + // Start count on first loss + else if ((!inputImage._completeFrame || missingFrames) && + _propagationCnt == -1) + _propagationCnt = 0; + if (_propagationCnt >= 0) + _propagationCnt++; + vpx_dec_iter_t iter = NULL; vpx_image_t* img; WebRtc_Word32 ret; @@ -863,6 +877,9 @@ VP8Decoder::Decode(const EncodedImage& inputImage, // call decoder with zero data length to signal missing frames if (vpx_codec_decode(_decoder, NULL, 0, 0, VPX_DL_REALTIME)) { + // Reset to avoid requesting key frames too often. + if (_propagationCnt > 0) + _propagationCnt = 0; return WEBRTC_VIDEO_CODEC_ERROR; } img = vpx_codec_get_frame(_decoder, &iter); @@ -872,6 +889,9 @@ VP8Decoder::Decode(const EncodedImage& inputImage, #ifdef INDEPENDENT_PARTITIONS if (DecodePartitions(inputImage, fragmentation)) { + // Reset to avoid requesting key frames too often. + if (_propagationCnt > 0) + _propagationCnt = 0; return WEBRTC_VIDEO_CODEC_ERROR; } #else @@ -886,6 +906,9 @@ VP8Decoder::Decode(const EncodedImage& inputImage, 0, VPX_DL_REALTIME)) { + // Reset to avoid requesting key frames too often. + if (_propagationCnt > 0) + _propagationCnt = 0; return WEBRTC_VIDEO_CODEC_ERROR; } #endif @@ -922,11 +945,17 @@ VP8Decoder::Decode(const EncodedImage& inputImage, #ifdef DEV_PIC_LOSS if (vpx_codec_control(_decoder, VP8D_GET_LAST_REF_UPDATES, &lastRefUpdates)) { + // Reset to avoid requesting key frames too often. + if (_propagationCnt > 0) + _propagationCnt = 0; return WEBRTC_VIDEO_CODEC_ERROR; } int corrupted = 0; if (vpx_codec_control(_decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { + // Reset to avoid requesting key frames too often. + if (_propagationCnt > 0) + _propagationCnt = 0; return WEBRTC_VIDEO_CODEC_ERROR; } #endif @@ -934,7 +963,12 @@ VP8Decoder::Decode(const EncodedImage& inputImage, img = vpx_codec_get_frame(_decoder, &iter); ret = ReturnFrame(img, inputImage._timeStamp); if (ret != 0) + { + // Reset to avoid requesting key frames too often. + if (ret < 0 && _propagationCnt > 0) + _propagationCnt = 0; return ret; + } // we need to communicate that we should send a RPSI with a specific picture ID @@ -967,6 +1001,14 @@ VP8Decoder::Decode(const EncodedImage& inputImage, return WEBRTC_VIDEO_CODEC_REQUEST_SLI; } #endif + + // Check Vs. threshold + if (_propagationCnt > kVp8ErrorPropagationTh) + { + // Reset to avoid requesting key frames too often. + _propagationCnt = 0; + return WEBRTC_VIDEO_CODEC_ERROR; + } return WEBRTC_VIDEO_CODEC_OK; } diff --git a/src/modules/video_coding/main/source/frame_buffer.cc b/src/modules/video_coding/main/source/frame_buffer.cc index bb4ec87f1..f143044c2 100644 --- a/src/modules/video_coding/main/source/frame_buffer.cc +++ b/src/modules/video_coding/main/source/frame_buffer.cc @@ -69,6 +69,10 @@ VCMFrameBuffer::GetHighSeqNum() const return _sessionInfo.GetHighSeqNum(); } +int VCMFrameBuffer::PictureId() const { + return _sessionInfo.PictureId(); +} + bool VCMFrameBuffer::IsSessionComplete() const { @@ -234,13 +238,6 @@ VCMFrameBuffer::HaveLastPacket() const return _sessionInfo.HaveLastPacket(); } -bool -VCMFrameBuffer::ForceSetHaveLastPacket() -{ - _sessionInfo.ForceSetHaveLastPacket(); - return _sessionInfo.IsSessionComplete(); -} - void VCMFrameBuffer::Reset() { @@ -346,10 +343,7 @@ VCMFrameBuffer::RestructureFrameInformation() PrepareForDecode(); _frameType = ConvertFrameType(_sessionInfo.FrameType()); _completeFrame = _sessionInfo.IsSessionComplete(); - // TODO(holmer): This bit is disabled for now since we can't tell whether - // we have had a full frame loss or if we've just lost an FEC/empty packet. - // _missingFrame = _sessionInfo.PreviousFrameLoss(); - _missingFrame = false; + _missingFrame = _sessionInfo.PreviousFrameLoss(); } WebRtc_Word32 diff --git a/src/modules/video_coding/main/source/frame_buffer.h b/src/modules/video_coding/main/source/frame_buffer.h index 619834fce..b55440865 100644 --- a/src/modules/video_coding/main/source/frame_buffer.h +++ b/src/modules/video_coding/main/source/frame_buffer.h @@ -45,7 +45,6 @@ public: bool IsRetransmitted() const; bool IsSessionComplete() const; bool HaveLastPacket() const; - bool ForceSetHaveLastPacket(); // Makes sure the session contain a decodable stream. void MakeSessionDecodable(); @@ -55,6 +54,8 @@ public: // Get highest packet sequence number in frame WebRtc_Word32 GetHighSeqNum() const; + int PictureId() const; + // Set counted status (as counted by JB or not) void SetCountedFrame(bool frameCounted); bool GetCountedFrame() const; diff --git a/src/modules/video_coding/main/source/jitter_buffer.cc b/src/modules/video_coding/main/source/jitter_buffer.cc index 1dd5745c3..5557dd651 100644 --- a/src/modules/video_coding/main/source/jitter_buffer.cc +++ b/src/modules/video_coding/main/source/jitter_buffer.cc @@ -73,6 +73,7 @@ VCMJitterBuffer::VCMJitterBuffer(WebRtc_Word32 vcmId, WebRtc_Word32 receiverId, _frameBuffersTSOrder(), _lastDecodedSeqNum(-1), _lastDecodedTimeStamp(-1), + _lastDecodedPictureId(-1), _packetsNotDecodable(0), _receiveStatistics(), _incomingFrameRate(0), @@ -88,7 +89,6 @@ VCMJitterBuffer::VCMJitterBuffer(WebRtc_Word32 vcmId, WebRtc_Word32 receiverId, _nackMode(kNoNack), _NACKSeqNum(), _NACKSeqNumLength(0), - _missingMarkerBits(false), _firstPacket(true) { memset(_frameBuffers, 0, sizeof(_frameBuffers)); @@ -141,10 +141,10 @@ VCMJitterBuffer::operator=(const VCMJitterBuffer& rhs) _nackMode = rhs._nackMode; _rttMs = rhs._rttMs; _NACKSeqNumLength = rhs._NACKSeqNumLength; - _missingMarkerBits = rhs._missingMarkerBits; _firstPacket = rhs._firstPacket; _lastDecodedSeqNum = rhs._lastDecodedSeqNum; _lastDecodedTimeStamp = rhs._lastDecodedTimeStamp; + _lastDecodedPictureId = rhs._lastDecodedPictureId; _packetsNotDecodable = rhs._packetsNotDecodable; memcpy(_receiveStatistics, rhs._receiveStatistics, sizeof(_receiveStatistics)); @@ -196,7 +196,6 @@ VCMJitterBuffer::Start() _waitingForCompletion.frameSize = 0; _waitingForCompletion.timestamp = 0; _waitingForCompletion.latestPacketTime = -1; - _missingMarkerBits = false; _firstPacket = true; _NACKSeqNumLength = 0; _rttMs = 0; @@ -215,6 +214,7 @@ VCMJitterBuffer::Stop() _running = false; _lastDecodedTimeStamp = -1; _lastDecodedSeqNum = -1; + _lastDecodedPictureId = -1; _frameBuffersTSOrder.Flush(); for (int i = 0; i < kMaxNumberOfFrames; i++) { @@ -258,6 +258,7 @@ VCMJitterBuffer::FlushInternal() } _lastDecodedSeqNum = -1; _lastDecodedTimeStamp = -1; + _lastDecodedPictureId = -1; _packetsNotDecodable = 0; _frameEvent.Reset(); @@ -274,7 +275,6 @@ VCMJitterBuffer::FlushInternal() _waitingForCompletion.timestamp = 0; _waitingForCompletion.latestPacketTime = -1; - _missingMarkerBits = false; _firstPacket = true; _NACKSeqNumLength = 0; @@ -602,22 +602,9 @@ VCMJitterBuffer::FindOldestCompleteContinuousFrame() oldestFrame = oldestFrameItem->GetItem(); } // is the frame complete? - if (oldestFrame != NULL) + if (oldestFrame != NULL && kStateComplete != oldestFrame->GetState()) { - if (kStateComplete != oldestFrame->GetState()) - { - // Try to see if the frame is complete even though the state is not - // complete. Can happen if markerbit is not set. - if (!CheckForCompleteFrame(oldestFrameItem)) - { - oldestFrame = NULL; - } - } - else - { - // we have a complete frame - currentLow = oldestFrame->GetLowSeqNum(); - } + oldestFrame = NULL; } if (oldestFrame == NULL) { @@ -647,52 +634,6 @@ VCMJitterBuffer::FindOldestCompleteContinuousFrame() return oldestFrameItem; } -// Check if the oldest frame is complete even though it isn't complete. -// This can happen when makerbit is not set -// Must be called under the critical section _critSect. -// Return false for lost packets -bool -VCMJitterBuffer::CheckForCompleteFrame(VCMFrameListItem* oldestFrameItem) -{ - const VCMFrameListItem* - nextFrameItem = _frameBuffersTSOrder.Next(oldestFrameItem); - VCMFrameBuffer* oldestFrame = NULL; - if (oldestFrameItem != NULL) - { - oldestFrame = oldestFrameItem->GetItem(); - } - if (nextFrameItem != NULL) - { - // We have received at least one packet from a later frame. - if(!oldestFrame->HaveLastPacket()) // If we don't have the markerbit - { - VCMFrameBuffer* nextFrame = nextFrameItem->GetItem(); - // Verify that we have received the first packet of the next frame, - // so we're not missing the last packet. - if (nextFrame != NULL && nextFrame->GetLowSeqNum() == - static_cast(oldestFrame->GetHighSeqNum() + 1)) - { - _missingMarkerBits = true; - bool completeSession = oldestFrame->ForceSetHaveLastPacket(); - if (completeSession) - { - UpdateFrameState(oldestFrame); - } - const VCMFrameBufferStateEnum state = oldestFrame->GetState(); - if (state == kStateComplete) - { - if (oldestFrame->Length() > 0) - { - UpdateJitterAndDelayEstimates(*oldestFrame, false); - } - return true; - } - } - } - } - return false; -} - // Call from inside the critical section _critSect void VCMJitterBuffer::RecycleFrame(VCMFrameBuffer* frame) @@ -710,7 +651,6 @@ VCMJitterBuffer::RecycleFrame(VCMFrameBuffer* frame) ReleaseFrameInternal(frame); } - // Calculate frame and bit rates WebRtc_Word32 VCMJitterBuffer::GetUpdate(WebRtc_UWord32& frameRate, WebRtc_UWord32& bitRate) @@ -878,13 +818,11 @@ VCMJitterBuffer::GetCompleteFrameForDecoding(WebRtc_UWord32 maxWaitTimeMS) // Ignore retransmitted and empty frames. UpdateJitterAndDelayEstimates(*oldestFrame, false); } - - // This needs to be done before we clean up old frames, - // otherwise we'll remove ourselves... - oldestFrame->SetState(kStateDecoding); _frameBuffersTSOrder.Erase(oldestFrameListItem); oldestFrameListItem = NULL; + oldestFrame->SetState(kStateDecoding); + CleanUpOldFrames(); CleanUpSizeZeroFrames(); @@ -893,6 +831,7 @@ VCMJitterBuffer::GetCompleteFrameForDecoding(WebRtc_UWord32 maxWaitTimeMS) // We have a frame - store seqnum & timestamp _lastDecodedSeqNum = oldestFrame->GetHighSeqNum(); _lastDecodedTimeStamp = oldestFrame->TimeStamp(); + _lastDecodedPictureId = oldestFrame->PictureId(); return oldestFrame; } @@ -918,17 +857,6 @@ VCMJitterBuffer::GetEstimatedJitterMsInternal() } estimate += static_cast (_jitterEstimate.GetJitterEstimate(rttMult) + 0.5); - if (_missingMarkerBits) - { - // Since the incoming packets are all missing marker bits we have to - // wait until the first packet of the next frame arrives, before we can - // safely say that the frame is complete. Therefore we have to - // compensate the jitter buffer level with one frame period. - // TODO(holmer): The timestamp diff should probably be filtered - // (max filter) since the diff can alternate between e.g. 3000 and 6000 - // if we have a frame rate between 15 and 30 frames per seconds. - estimate += _delayEstimate.CurrentTimeStampDiffMs(); - } return estimate; } @@ -1045,8 +973,18 @@ VCMJitterBuffer::CompleteSequenceWithNextFrame() { return false; } - else if (oldestFrame->GetLowSeqNum() != (_lastDecodedSeqNum + 1) - % 0x00010000) + // We can't use sequence numbers to detect frame loss when FEC is enabled. + // Assume FEC is only enabled for VP8 with picture ids, and use picture ids + // to detect frame loss in that situation. + else if (oldestFrame->PictureId() == kNoPictureId) + { + if (oldestFrame->GetLowSeqNum() != + (_lastDecodedSeqNum + 1) % 0x00010000) + { + return false; + } + } + else if (!ContinuousPictureId(oldestFrame->PictureId())) { return false; } @@ -1111,19 +1049,24 @@ VCMJitterBuffer::GetFrameForDecoding() _frameBuffersTSOrder.Erase(oldestFrameListItem); oldestFrameListItem = NULL; - CleanUpOldFrames(); - CleanUpSizeZeroFrames(); - // Look for previous frame loss VerifyAndSetPreviousFrameLost(*oldestFrame); + + // The state must be changed to decoding before cleaning up zero sized + // frames to avoid empty frames being cleaned up and then given to the + // decoder. // Set as decoding. Propagates the missingFrame bit. oldestFrame->SetState(kStateDecoding); + CleanUpOldFrames(); + CleanUpSizeZeroFrames(); + _packetsNotDecodable += oldestFrame->NotDecodablePackets(); // Store current seqnum & time _lastDecodedSeqNum = oldestFrame->GetHighSeqNum(); _lastDecodedTimeStamp = oldestFrame->TimeStamp(); + _lastDecodedPictureId = oldestFrame->PictureId(); return oldestFrame; } @@ -1171,11 +1114,16 @@ VCMJitterBuffer::GetFrameForDecodingNACK() // Ignore retransmitted and empty frames. UpdateJitterAndDelayEstimates(*oldestFrame, false); } - - // This needs to be done before we clean up old frames, - // otherwise we might release the frame we want to decode right now. - oldestFrame->SetState(kStateDecoding); _frameBuffersTSOrder.Erase(oldestFrameListItem); + oldestFrameListItem = NULL; + + // Look for previous frame loss + VerifyAndSetPreviousFrameLost(*oldestFrame); + + // The state must be changed to decoding before cleaning up zero sized + // frames to avoid empty frames being cleaned up and then given to the + // decoder. + oldestFrame->SetState(kStateDecoding); // Clean up old frames and empty frames CleanUpOldFrames(); @@ -1185,6 +1133,7 @@ VCMJitterBuffer::GetFrameForDecodingNACK() // Store seqnum & timestamp _lastDecodedSeqNum = oldestFrame->GetHighSeqNum(); _lastDecodedTimeStamp = oldestFrame->TimeStamp(); + _lastDecodedPictureId = oldestFrame->PictureId(); return oldestFrame; } @@ -1903,7 +1852,8 @@ VCMJitterBuffer::CleanUpSizeZeroFrames() VCMFrameBuffer* ptrTempBuffer = frameListItem->GetItem(); // pop frame if its size zero but store seqnum - if (ptrTempBuffer->Length() == 0) + if (ptrTempBuffer->Length() == 0 && + ptrTempBuffer->GetState() != kStateDecoding) { WebRtc_Word32 frameHighSeqNum = ptrTempBuffer->GetHighSeqNum(); if (frameHighSeqNum == -1) @@ -1983,21 +1933,47 @@ VCMJitterBuffer::VerifyAndSetPreviousFrameLost(VCMFrameBuffer& frame) frame.MakeSessionDecodable(); // make sure the session can be decoded. if (frame.FrameType() == kVideoFrameKey) return; - WebRtc_UWord16 nextExpectedSeqNum = - static_cast(_lastDecodedSeqNum + 1); + if (_lastDecodedSeqNum == -1) { - // First frame + // First frame is not a key frame frame.SetPreviousFrameLoss(); + return; } - else if (static_cast(frame.GetLowSeqNum()) != - nextExpectedSeqNum) + // We can't use sequence numbers to detect frame loss when FEC is enabled. + // Assume FEC is only enabled for VP8 with picture ids, and use picture ids + // to detect frame loss in that situation. + if (frame.PictureId() == kNoPictureId) + { + WebRtc_UWord16 nextExpectedSeqNum = + static_cast(_lastDecodedSeqNum + 1); + if (static_cast(frame.GetLowSeqNum()) != + nextExpectedSeqNum) + { + frame.SetPreviousFrameLoss(); + } + } + else if (!ContinuousPictureId(frame.PictureId())) { - // Frame loss frame.SetPreviousFrameLoss(); } } +bool VCMJitterBuffer::ContinuousPictureId(int pictureId) const { + if (pictureId < _lastDecodedPictureId) { + // Wrap + if (_lastDecodedPictureId >= (1<<8)) { + // 15 bits used for picture id + return (((_lastDecodedPictureId + 1) % 0x7FFF) == pictureId); + } else { + // 7 bits used for picture id + return (((_lastDecodedPictureId + 1) % 0x7F) == pictureId); + } + } + // No wrap + return (_lastDecodedPictureId + 1 == pictureId); +} + bool VCMJitterBuffer::WaitForNack() { diff --git a/src/modules/video_coding/main/source/jitter_buffer.h b/src/modules/video_coding/main/source/jitter_buffer.h index fc027e164..8ac8cd63b 100644 --- a/src/modules/video_coding/main/source/jitter_buffer.h +++ b/src/modules/video_coding/main/source/jitter_buffer.h @@ -150,10 +150,6 @@ private: // Find oldest complete frame, used for getting next frame to decode VCMFrameListItem* FindOldestCompleteContinuousFrame(); - // Check if a frame is missing the markerbit but is complete - bool CheckForCompleteFrame(VCMFrameListItem* oldestFrameItem); - - void CleanUpOldFrames(); void CleanUpSizeZeroFrames(); @@ -181,6 +177,7 @@ private: const void* timestamp); static bool CompleteDecodableKeyFrameCriteria(VCMFrameBuffer* frame, const void* notUsed); + bool ContinuousPictureId(int pictureId) const; // Decide whether should wait for NACK (mainly relevant for hybrid mode) bool WaitForNack(); @@ -205,6 +202,7 @@ private: WebRtc_Word32 _lastDecodedSeqNum; // Timestamp of last frame that was given to decoder WebRtc_Word64 _lastDecodedTimeStamp; + int _lastDecodedPictureId; WebRtc_UWord32 _packetsNotDecodable; // Statistics @@ -241,7 +239,6 @@ private: WebRtc_UWord16 _NACKSeqNum[kNackHistoryLength]; WebRtc_UWord32 _NACKSeqNumLength; - bool _missingMarkerBits; bool _firstPacket; }; diff --git a/src/modules/video_coding/main/source/session_info.cc b/src/modules/video_coding/main/source/session_info.cc index 58d95dc6e..cbfcf2273 100644 --- a/src/modules/video_coding/main/source/session_info.cc +++ b/src/modules/video_coding/main/source/session_info.cc @@ -26,7 +26,8 @@ VCMSessionInfo::VCMSessionInfo(): _emptySeqNumLow(-1), _emptySeqNumHigh(-1), _markerSeqNum(-1), - _packetsNotDecodable(0) + _packetsNotDecodable(0), + _pictureId(-1) { } @@ -55,6 +56,10 @@ VCMSessionInfo::GetHighSeqNum() const return LatestSequenceNumber(_emptySeqNumHigh, _highSeqNum, NULL); } +int VCMSessionInfo::PictureId() const { + return _pictureId; +} + void VCMSessionInfo::Reset() { for (int i = 0; i <= _highestPacketIndex; ++i) @@ -71,6 +76,7 @@ VCMSessionInfo::Reset() { _highestPacketIndex = 0; _markerSeqNum = -1; _packetsNotDecodable = 0; + _pictureId = -1; } WebRtc_UWord32 @@ -169,6 +175,11 @@ VCMSessionInfo::InsertBuffer(WebRtc_UWord8* ptrStartOfLayer, } returnLength = packetSize; + if (packet.codecSpecificHeader.codec == kRTPVideoVP8) + { + _pictureId = packet.codecSpecificHeader.codecHeader.VP8.pictureId; + } + if (packet.markerBit) { _markerBit = true; @@ -645,13 +656,6 @@ VCMSessionInfo::HaveLastPacket() const return _markerBit; } -void -VCMSessionInfo::ForceSetHaveLastPacket() -{ - _markerBit = true; - UpdateCompleteSession(); -} - bool VCMSessionInfo::IsRetransmitted() const { diff --git a/src/modules/video_coding/main/source/session_info.h b/src/modules/video_coding/main/source/session_info.h index 64878a5ae..942c85de2 100644 --- a/src/modules/video_coding/main/source/session_info.h +++ b/src/modules/video_coding/main/source/session_info.h @@ -61,7 +61,6 @@ public: WebRtc_UWord32 GetSessionLength(); bool HaveLastPacket() const; - void ForceSetHaveLastPacket(); bool IsRetransmitted() const; webrtc::FrameType FrameType() const { return _frameType; } @@ -74,6 +73,7 @@ public: WebRtc_Word32 GetLowSeqNum() const; // returns highest seqNum, media or empty WebRtc_Word32 GetHighSeqNum() const; + int PictureId() const; WebRtc_UWord32 PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer, VideoCodecType codec); @@ -130,6 +130,7 @@ private: WebRtc_Word32 _markerSeqNum; // Number of packets discarded because the decoder can't use them. int _packetsNotDecodable; + int _pictureId; }; } // namespace webrtc