henrik.lundin@webrtc.org baf6db5ead Making dual decoder work again in VCM
Changing the assignment operator in VCMJitterBuffer to a named
function (CopyFrom) instead, since it is not a straight
assignment. Also fixing two bugs in the jitter copy function.

Bug fix in VCMEncodedFrame: The copy constructor did not
copy _length.

In VCM codec database, make sure that the callback object is
preserved when copying back from secondary to primary decoder.

In VP8 wrapper, adding code to copy the _decodedImage to the
Copy() method.

Bugfix in video_coding_test rtp_player:
The retransmissions where made in reverse order. Now new items are
appended to the end of the LostPackets list, which makes the order
correct when retransmitting.

Handling the case when cloning an unused decoder state:
When the decoder has not successfully decoded a frame yet,
it cannot be cloned. A NULL pointer will be returned all
the way out to VideoCodingModuleImpl::Decode(). When this
happens, the VCM will call Reset() for the dual receiver,
in order to reset the state to kPassive.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@873 4adac7df-926f-26a2-2b94-8c16560cd09d
2011-11-02 18:58:39 +00:00

239 lines
5.7 KiB
C++

/*
* 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.
*/
#include "encoded_frame.h"
#include "generic_encoder.h"
#include "jitter_buffer_common.h"
#include "video_coding_defines.h"
namespace webrtc {
VCMEncodedFrame::VCMEncodedFrame()
:
webrtc::EncodedImage(),
_renderTimeMs(-1),
_payloadType(0),
_missingFrame(false),
_codec(kVideoCodecUnknown),
_fragmentation()
{
_codecSpecificInfo.codecType = kVideoCodecUnknown;
}
VCMEncodedFrame::VCMEncodedFrame(const webrtc::EncodedImage& rhs)
:
webrtc::EncodedImage(rhs),
_renderTimeMs(-1),
_payloadType(0),
_missingFrame(false),
_codec(kVideoCodecUnknown),
_fragmentation()
{
_codecSpecificInfo.codecType = kVideoCodecUnknown;
_buffer = NULL;
_size = 0;
_length = 0;
if (rhs._buffer != NULL)
{
VerifyAndAllocate(rhs._length);
memcpy(_buffer, rhs._buffer, rhs._length);
}
}
VCMEncodedFrame::VCMEncodedFrame(const VCMEncodedFrame& rhs)
:
webrtc::EncodedImage(rhs),
_renderTimeMs(rhs._renderTimeMs),
_payloadType(rhs._payloadType),
_missingFrame(rhs._missingFrame),
_codecSpecificInfo(rhs._codecSpecificInfo),
_codec(rhs._codec),
_fragmentation() {
_buffer = NULL;
_size = 0;
_length = 0;
if (rhs._buffer != NULL)
{
VerifyAndAllocate(rhs._size);
memcpy(_buffer, rhs._buffer, rhs._length);
_length = rhs._length;
}
// Deep operator=
_fragmentation = rhs._fragmentation;
}
VCMEncodedFrame::~VCMEncodedFrame()
{
Free();
}
void VCMEncodedFrame::Free()
{
Reset();
if (_buffer != NULL)
{
delete [] _buffer;
_buffer = NULL;
}
}
void VCMEncodedFrame::Reset()
{
_renderTimeMs = -1;
_timeStamp = 0;
_payloadType = 0;
_frameType = kDeltaFrame;
_encodedWidth = 0;
_encodedHeight = 0;
_completeFrame = false;
_missingFrame = false;
_length = 0;
_codecSpecificInfo.codecType = kVideoCodecUnknown;
_codec = kVideoCodecUnknown;
}
void VCMEncodedFrame::CopyCodecSpecific(const RTPVideoHeader* header)
{
if (header)
{
switch (header->codec)
{
case kRTPVideoVP8:
{
if (_codecSpecificInfo.codecType != kVideoCodecVP8)
{
// This is the first packet for this frame.
_codecSpecificInfo.codecSpecific.VP8.pictureId = -1;
_codecSpecificInfo.codecType = kVideoCodecVP8;
}
_codecSpecificInfo.codecSpecific.VP8.nonReference =
header->codecHeader.VP8.nonReference;
if (header->codecHeader.VP8.pictureId != kNoPictureId)
{
_codecSpecificInfo.codecSpecific.VP8.pictureId =
header->codecHeader.VP8.pictureId;
}
break;
}
default:
{
_codecSpecificInfo.codecType = kVideoCodecUnknown;
break;
}
}
}
}
const RTPFragmentationHeader* VCMEncodedFrame::FragmentationHeader() const {
return &_fragmentation;
}
WebRtc_Word32
VCMEncodedFrame::Store(VCMFrameStorageCallback& storeCallback) const
{
EncodedVideoData frameToStore;
frameToStore.codec = _codec;
if (_buffer != NULL)
{
frameToStore.VerifyAndAllocate(_length);
memcpy(frameToStore.payloadData, _buffer, _length);
frameToStore.payloadSize = _length;
}
frameToStore.completeFrame = _completeFrame;
frameToStore.encodedWidth = _encodedWidth;
frameToStore.encodedHeight = _encodedHeight;
frameToStore.frameType = ConvertFrameType(_frameType);
frameToStore.missingFrame = _missingFrame;
frameToStore.payloadType = _payloadType;
frameToStore.renderTimeMs = _renderTimeMs;
frameToStore.timeStamp = _timeStamp;
storeCallback.StoreReceivedFrame(frameToStore);
return VCM_OK;
}
WebRtc_Word32
VCMEncodedFrame::VerifyAndAllocate(const WebRtc_UWord32 minimumSize)
{
if(minimumSize > _size)
{
// create buffer of sufficient size
WebRtc_UWord8* newBuffer = new WebRtc_UWord8[minimumSize];
if (newBuffer == NULL)
{
return -1;
}
if(_buffer)
{
// copy old data
memcpy(newBuffer, _buffer, _size);
delete [] _buffer;
}
_buffer = newBuffer;
_size = minimumSize;
}
return 0;
}
webrtc::FrameType VCMEncodedFrame::ConvertFrameType(VideoFrameType frameType)
{
switch(frameType)
{
case kKeyFrame:
{
return kVideoFrameKey;
}
case kDeltaFrame:
{
return kVideoFrameDelta;
}
case kGoldenFrame:
{
return kVideoFrameGolden;
}
case kAltRefFrame:
{
return kVideoFrameAltRef;
}
default:
{
return kVideoFrameDelta;
}
}
}
VideoFrameType VCMEncodedFrame::ConvertFrameType(webrtc::FrameType frameType)
{
switch (frameType)
{
case kVideoFrameKey:
{
return kKeyFrame;
}
case kVideoFrameDelta:
{
return kDeltaFrame;
}
case kVideoFrameGolden:
{
return kGoldenFrame;
}
case kVideoFrameAltRef:
{
return kAltRefFrame;
}
default:
{
return kDeltaFrame;
}
}
}
}