From 93d216c23faaa509b798dc8f2d2b58b30714cd1e Mon Sep 17 00:00:00 2001 From: "stefan@webrtc.org" Date: Tue, 4 Oct 2011 06:48:11 +0000 Subject: [PATCH] Fixed bug in jitter buffer which caused the missingFrames bit to never be set. Also updated the VP8 wrapper to return fully concealed frames (for rendering). BUG= TEST= Review URL: http://webrtc-codereview.appspot.com/190003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@687 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../codecs/vp8/main/interface/vp8.h | 2 + .../codecs/vp8/main/source/vp8.cc | 114 ++++++++++-------- .../video_coding/main/source/jitter_buffer.cc | 4 +- 3 files changed, 68 insertions(+), 52 deletions(-) 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 f8b13b4848..1a869931c0 100644 --- a/src/modules/video_coding/codecs/vp8/main/interface/vp8.h +++ b/src/modules/video_coding/codecs/vp8/main/interface/vp8.h @@ -255,6 +255,8 @@ private: WebRtc_Word32 DecodePartitions(const EncodedImage& input_image, const RTPFragmentationHeader* fragmentation); + WebRtc_Word32 ReturnFrame(const vpx_image_t* img, WebRtc_UWord32 timeStamp); + RawImage _decodedImage; DecodedImageCallback* _decodeCompleteCallback; bool _inited; 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 ac17a6b135..06fc7e5746 100644 --- a/src/modules/video_coding/codecs/vp8/main/source/vp8.cc +++ b/src/modules/video_coding/codecs/vp8/main/source/vp8.cc @@ -822,8 +822,9 @@ VP8Decoder::Decode(const EncodedImage& inputImage, } #endif - vpx_dec_iter_t _iter = NULL; + vpx_dec_iter_t iter = NULL; vpx_image_t* img; + WebRtc_Word32 ret; // check for missing frames if (missingFrames) @@ -833,6 +834,11 @@ VP8Decoder::Decode(const EncodedImage& inputImage, { return WEBRTC_VIDEO_CODEC_ERROR; } + img = vpx_codec_get_frame(_decoder, &iter); + ret = ReturnFrame(img, inputImage._timeStamp); + if (ret != 0) + return ret; + iter = NULL; } #ifdef INDEPENDENT_PARTITIONS @@ -892,56 +898,10 @@ VP8Decoder::Decode(const EncodedImage& inputImage, } #endif - img = vpx_codec_get_frame(_decoder, &_iter); - - if (img == NULL) - { - // Decoder OK and NULL image => No show frame - return WEBRTC_VIDEO_CODEC_OK; - } - - // Allocate memory for decoded image - WebRtc_UWord32 requiredSize = (3 * img->h * img->w) >> 1; - if (_decodedImage._buffer != NULL) - { - delete [] _decodedImage._buffer; - _decodedImage._buffer = NULL; - } - if (_decodedImage._buffer == NULL) - { - _decodedImage._size = requiredSize; - _decodedImage._buffer = new WebRtc_UWord8[_decodedImage._size]; - if (_decodedImage._buffer == NULL) - { - return WEBRTC_VIDEO_CODEC_MEMORY; - } - } - - WebRtc_UWord8* buf; - WebRtc_UWord32 locCnt = 0; - WebRtc_UWord32 plane, y; - - for (plane = 0; plane < 3; plane++) - { - buf = img->planes[plane]; - WebRtc_UWord32 shiftFactor = plane ? 1 : 0; - for(y = 0; y < img->d_h >> shiftFactor; y++) - { - memcpy(&_decodedImage._buffer[locCnt], buf, img->d_w >> shiftFactor); - locCnt += img->d_w >> shiftFactor; - buf += img->stride[plane]; - } - } - - // Set image parameters - _decodedImage._height = img->d_h; - _decodedImage._width = img->d_w; - _decodedImage._length = (3 * img->d_h * img->d_w) >> 1; - _decodedImage._timeStamp = inputImage._timeStamp; - _decodeCompleteCallback->Decoded(_decodedImage); - - // Remember image format for later - _imageFormat = img->fmt; + img = vpx_codec_get_frame(_decoder, &iter); + ret = ReturnFrame(img, inputImage._timeStamp); + if (ret != 0) + return ret; // we need to communicate that we should send a RPSI with a specific picture ID @@ -1000,6 +960,58 @@ VP8Decoder::DecodePartitions(const EncodedImage& input_image, return WEBRTC_VIDEO_CODEC_OK; } +WebRtc_Word32 +VP8Decoder::ReturnFrame(const vpx_image_t* img, WebRtc_UWord32 timeStamp) +{ + if (img == NULL) + { + // Decoder OK and NULL image => No show frame + return WEBRTC_VIDEO_CODEC_OK; + } + + // Allocate memory for decoded image + WebRtc_UWord32 requiredSize = (3 * img->h * img->w) >> 1; + if (_decodedImage._buffer != NULL) + { + delete [] _decodedImage._buffer; + _decodedImage._buffer = NULL; + } + if (_decodedImage._buffer == NULL) + { + _decodedImage._size = requiredSize; + _decodedImage._buffer = new WebRtc_UWord8[_decodedImage._size]; + } + + WebRtc_UWord8* buf; + WebRtc_UWord32 locCnt = 0; + WebRtc_UWord32 plane, y; + + for (plane = 0; plane < 3; plane++) + { + buf = img->planes[plane]; + WebRtc_UWord32 shiftFactor = plane ? 1 : 0; + for(y = 0; y < img->d_h >> shiftFactor; y++) + { + memcpy(&_decodedImage._buffer[locCnt], buf, img->d_w >> shiftFactor); + locCnt += img->d_w >> shiftFactor; + buf += img->stride[plane]; + } + } + + // Set image parameters + _decodedImage._height = img->d_h; + _decodedImage._width = img->d_w; + _decodedImage._length = (3 * img->d_h * img->d_w) >> 1; + _decodedImage._timeStamp = timeStamp; + WebRtc_Word32 ret = _decodeCompleteCallback->Decoded(_decodedImage); + if (ret != 0) + return ret; + + // Remember image format for later + _imageFormat = img->fmt; + return WEBRTC_VIDEO_CODEC_OK; +} + WebRtc_Word32 VP8Decoder::RegisterDecodeCompleteCallback(DecodedImageCallback* callback) { diff --git a/src/modules/video_coding/main/source/jitter_buffer.cc b/src/modules/video_coding/main/source/jitter_buffer.cc index 9642ccb475..0399f0f8fa 100644 --- a/src/modules/video_coding/main/source/jitter_buffer.cc +++ b/src/modules/video_coding/main/source/jitter_buffer.cc @@ -1115,7 +1115,6 @@ VCMJitterBuffer::GetFrameForDecoding() _waitingForCompletion.latestPacketTime = oldestFrame->LatestPacketTimeMs(); _waitingForCompletion.timestamp = oldestFrame->TimeStamp(); - oldestFrame->SetState(kStateDecoding); } _frameBuffersTSOrder.Erase(oldestFrameListItem); oldestFrameListItem = NULL; @@ -1123,7 +1122,10 @@ VCMJitterBuffer::GetFrameForDecoding() CleanUpOldFrames(); CleanUpSizeZeroFrames(); + // Look for previous frame loss VerifyAndSetPreviousFrameLost(*oldestFrame); + // Set as decoding. Propagates the missingFrame bit. + oldestFrame->SetState(kStateDecoding); // Store current seqnum & time _lastDecodedSeqNum = oldestFrame->GetHighSeqNum();