Fixes two bugs when decoding with packet losses.

Disable _missingFrame bit since we can't set it correctly with FEC.

No longer return more than one decoded frame per Decode() call.
This is a work-around for a bug where the frame info map was popped more often than items were added to the map.

BUG=
TEST=

Review URL: http://webrtc-codereview.appspot.com/215001

git-svn-id: http://webrtc.googlecode.com/svn/trunk@722 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2011-10-10 14:17:46 +00:00
parent ed081a99a9
commit 06887aebae
5 changed files with 40 additions and 20 deletions

View File

@ -16,6 +16,7 @@
// Define return values
#define WEBRTC_VIDEO_CODEC_REQUEST_SLI 2
#define WEBRTC_VIDEO_CODEC_NO_OUTPUT 1
#define WEBRTC_VIDEO_CODEC_OK 0
#define WEBRTC_VIDEO_CODEC_ERROR -1
#define WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED -2

View File

@ -835,9 +835,6 @@ 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;
}
@ -966,7 +963,7 @@ 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;
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}
// Allocate memory for decoded image

View File

@ -343,7 +343,10 @@ VCMFrameBuffer::RestructureFrameInformation()
PrepareForDecode();
_frameType = ConvertFrameType(_sessionInfo.FrameType());
_completeFrame = _sessionInfo.IsSessionComplete();
_missingFrame = _sessionInfo.PreviousFrameLoss();
// 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;
}
WebRtc_Word32

View File

@ -30,7 +30,8 @@ VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
delete &_critSect;
}
void VCMDecodedFrameCallback::SetUserReceiveCallback(VCMReceiveCallback* receiveCallback)
void VCMDecodedFrameCallback::SetUserReceiveCallback(
VCMReceiveCallback* receiveCallback)
{
CriticalSectionScoped cs(_critSect);
_receiveCallback = receiveCallback;
@ -38,18 +39,27 @@ void VCMDecodedFrameCallback::SetUserReceiveCallback(VCMReceiveCallback* receive
WebRtc_Word32 VCMDecodedFrameCallback::Decoded(RawImage& decodedImage)
{
// TODO(holmer): We should improve this so that we can handle multiple
// callbacks from one call to Decode().
CriticalSectionScoped cs(_critSect);
VCMFrameInformation* frameInfo = static_cast<VCMFrameInformation*>(_timestampMap.Pop(decodedImage._timeStamp));
VCMFrameInformation* frameInfo = static_cast<VCMFrameInformation*>(
_timestampMap.Pop(decodedImage._timeStamp));
if (frameInfo == NULL)
{
// The map should never be empty or full if this callback is called.
return WEBRTC_VIDEO_CODEC_ERROR;
}
WebRtc_Word32 ret = _timing.StopDecodeTimer(decodedImage._timeStamp, frameInfo->decodeStartTimeMs, VCMTickTime::MillisecondTimestamp());
_timing.StopDecodeTimer(
decodedImage._timeStamp,
frameInfo->decodeStartTimeMs,
VCMTickTime::MillisecondTimestamp());
if (_receiveCallback != NULL)
{
_frame.Swap(decodedImage._buffer, decodedImage._length, decodedImage._size);
_frame.Swap(decodedImage._buffer,
decodedImage._length,
decodedImage._size);
_frame.SetWidth(decodedImage._width);
_frame.SetHeight(decodedImage._height);
_frame.SetTimeStamp(decodedImage._timeStamp);
@ -58,18 +68,18 @@ WebRtc_Word32 VCMDecodedFrameCallback::Decoded(RawImage& decodedImage)
WebRtc_Word32 callbackReturn = _receiveCallback->FrameToRender(_frame);
if (callbackReturn < 0)
{
return callbackReturn;
WEBRTC_TRACE(webrtc::kTraceDebug,
webrtc::kTraceVideoCoding,
-1,
"Render callback returned error: %d", callbackReturn);
}
}
if (ret < 0)
{
return ret;
}
return WEBRTC_VIDEO_CODEC_OK;
}
WebRtc_Word32
VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(const WebRtc_UWord64 pictureId)
VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
const WebRtc_UWord64 pictureId)
{
CriticalSectionScoped cs(_critSect);
if (_receiveCallback != NULL)
@ -125,7 +135,9 @@ VCMGenericDecoder::~VCMGenericDecoder()
{
}
WebRtc_Word32 VCMGenericDecoder::InitDecode(const VideoCodec* settings, WebRtc_Word32 numberOfCores, bool requireKeyFrame)
WebRtc_Word32 VCMGenericDecoder::InitDecode(const VideoCodec* settings,
WebRtc_Word32 numberOfCores,
bool requireKeyFrame)
{
_requireKeyFrame = requireKeyFrame;
_keyFrameDecoded = false;
@ -149,9 +161,10 @@ WebRtc_Word32 VCMGenericDecoder::Decode(const VCMEncodedFrame& frame)
_frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
_callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_id),
"Decoding timestamp %u",
frame.TimeStamp());
WEBRTC_TRACE(webrtc::kTraceDebug,
webrtc::kTraceVideoCoding,
VCMId(_id),
"Decoding timestamp %u", frame.TimeStamp());
_nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
@ -167,6 +180,12 @@ WebRtc_Word32 VCMGenericDecoder::Decode(const VCMEncodedFrame& frame)
_callback->Pop(frame.TimeStamp());
return ret;
}
else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT ||
ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
{
// No output
_callback->Pop(frame.TimeStamp());
}
// Update the key frame decoded variable so that we know whether or not we've decoded a key frame since reset.
_keyFrameDecoded = (frame.FrameType() == kVideoFrameKey || frame.FrameType() == kVideoFrameGolden);
return ret;

View File

@ -199,7 +199,7 @@ VCMTiming::StopDecodeTimer(WebRtc_UWord32 timeStamp,
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
"Codec timer error: %d", timeDiffMs);
return timeDiffMs;
assert(false);
}
if (_master)