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:
parent
ed081a99a9
commit
06887aebae
@ -16,6 +16,7 @@
|
|||||||
// Define return values
|
// Define return values
|
||||||
|
|
||||||
#define WEBRTC_VIDEO_CODEC_REQUEST_SLI 2
|
#define WEBRTC_VIDEO_CODEC_REQUEST_SLI 2
|
||||||
|
#define WEBRTC_VIDEO_CODEC_NO_OUTPUT 1
|
||||||
#define WEBRTC_VIDEO_CODEC_OK 0
|
#define WEBRTC_VIDEO_CODEC_OK 0
|
||||||
#define WEBRTC_VIDEO_CODEC_ERROR -1
|
#define WEBRTC_VIDEO_CODEC_ERROR -1
|
||||||
#define WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED -2
|
#define WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED -2
|
||||||
|
@ -835,9 +835,6 @@ VP8Decoder::Decode(const EncodedImage& inputImage,
|
|||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
}
|
}
|
||||||
img = vpx_codec_get_frame(_decoder, &iter);
|
img = vpx_codec_get_frame(_decoder, &iter);
|
||||||
ret = ReturnFrame(img, inputImage._timeStamp);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
iter = NULL;
|
iter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,7 +963,7 @@ VP8Decoder::ReturnFrame(const vpx_image_t* img, WebRtc_UWord32 timeStamp)
|
|||||||
if (img == NULL)
|
if (img == NULL)
|
||||||
{
|
{
|
||||||
// Decoder OK and NULL image => No show frame
|
// Decoder OK and NULL image => No show frame
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for decoded image
|
// Allocate memory for decoded image
|
||||||
|
@ -343,7 +343,10 @@ VCMFrameBuffer::RestructureFrameInformation()
|
|||||||
PrepareForDecode();
|
PrepareForDecode();
|
||||||
_frameType = ConvertFrameType(_sessionInfo.FrameType());
|
_frameType = ConvertFrameType(_sessionInfo.FrameType());
|
||||||
_completeFrame = _sessionInfo.IsSessionComplete();
|
_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
|
WebRtc_Word32
|
||||||
|
@ -30,7 +30,8 @@ VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
|
|||||||
delete &_critSect;
|
delete &_critSect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCMDecodedFrameCallback::SetUserReceiveCallback(VCMReceiveCallback* receiveCallback)
|
void VCMDecodedFrameCallback::SetUserReceiveCallback(
|
||||||
|
VCMReceiveCallback* receiveCallback)
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(_critSect);
|
CriticalSectionScoped cs(_critSect);
|
||||||
_receiveCallback = receiveCallback;
|
_receiveCallback = receiveCallback;
|
||||||
@ -38,18 +39,27 @@ void VCMDecodedFrameCallback::SetUserReceiveCallback(VCMReceiveCallback* receive
|
|||||||
|
|
||||||
WebRtc_Word32 VCMDecodedFrameCallback::Decoded(RawImage& decodedImage)
|
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);
|
CriticalSectionScoped cs(_critSect);
|
||||||
VCMFrameInformation* frameInfo = static_cast<VCMFrameInformation*>(_timestampMap.Pop(decodedImage._timeStamp));
|
VCMFrameInformation* frameInfo = static_cast<VCMFrameInformation*>(
|
||||||
|
_timestampMap.Pop(decodedImage._timeStamp));
|
||||||
if (frameInfo == NULL)
|
if (frameInfo == NULL)
|
||||||
{
|
{
|
||||||
|
// The map should never be empty or full if this callback is called.
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
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)
|
if (_receiveCallback != NULL)
|
||||||
{
|
{
|
||||||
_frame.Swap(decodedImage._buffer, decodedImage._length, decodedImage._size);
|
_frame.Swap(decodedImage._buffer,
|
||||||
|
decodedImage._length,
|
||||||
|
decodedImage._size);
|
||||||
_frame.SetWidth(decodedImage._width);
|
_frame.SetWidth(decodedImage._width);
|
||||||
_frame.SetHeight(decodedImage._height);
|
_frame.SetHeight(decodedImage._height);
|
||||||
_frame.SetTimeStamp(decodedImage._timeStamp);
|
_frame.SetTimeStamp(decodedImage._timeStamp);
|
||||||
@ -58,18 +68,18 @@ WebRtc_Word32 VCMDecodedFrameCallback::Decoded(RawImage& decodedImage)
|
|||||||
WebRtc_Word32 callbackReturn = _receiveCallback->FrameToRender(_frame);
|
WebRtc_Word32 callbackReturn = _receiveCallback->FrameToRender(_frame);
|
||||||
if (callbackReturn < 0)
|
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;
|
return WEBRTC_VIDEO_CODEC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(const WebRtc_UWord64 pictureId)
|
VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
|
||||||
|
const WebRtc_UWord64 pictureId)
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(_critSect);
|
CriticalSectionScoped cs(_critSect);
|
||||||
if (_receiveCallback != NULL)
|
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;
|
_requireKeyFrame = requireKeyFrame;
|
||||||
_keyFrameDecoded = false;
|
_keyFrameDecoded = false;
|
||||||
@ -149,9 +161,10 @@ WebRtc_Word32 VCMGenericDecoder::Decode(const VCMEncodedFrame& frame)
|
|||||||
_frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
|
_frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs();
|
||||||
_callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
|
_callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]);
|
||||||
|
|
||||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_id),
|
WEBRTC_TRACE(webrtc::kTraceDebug,
|
||||||
"Decoding timestamp %u",
|
webrtc::kTraceVideoCoding,
|
||||||
frame.TimeStamp());
|
VCMId(_id),
|
||||||
|
"Decoding timestamp %u", frame.TimeStamp());
|
||||||
|
|
||||||
_nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
|
_nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength;
|
||||||
|
|
||||||
@ -167,6 +180,12 @@ WebRtc_Word32 VCMGenericDecoder::Decode(const VCMEncodedFrame& frame)
|
|||||||
_callback->Pop(frame.TimeStamp());
|
_callback->Pop(frame.TimeStamp());
|
||||||
return ret;
|
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.
|
// 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);
|
_keyFrameDecoded = (frame.FrameType() == kVideoFrameKey || frame.FrameType() == kVideoFrameGolden);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -199,7 +199,7 @@ VCMTiming::StopDecodeTimer(WebRtc_UWord32 timeStamp,
|
|||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_vcmId, _timingId),
|
||||||
"Codec timer error: %d", timeDiffMs);
|
"Codec timer error: %d", timeDiffMs);
|
||||||
return timeDiffMs;
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_master)
|
if (_master)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user