|  | /* | 
|  | *  Copyright (c) 2012 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 "webrtc/modules/video_coding/main/interface/video_coding_defines.h" | 
|  | #include "webrtc/modules/video_coding/main/source/encoded_frame.h" | 
|  | #include "webrtc/modules/video_coding/main/source/generic_encoder.h" | 
|  | #include "webrtc/modules/video_coding/main/source/jitter_buffer_common.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._length); | 
|  | memcpy(_buffer, rhs._buffer, rhs._length); | 
|  | _length = rhs._length; | 
|  | } | 
|  | _fragmentation.CopyFrom(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.codecSpecific.VP8.temporalIdx = 0; | 
|  | _codecSpecificInfo.codecSpecific.VP8.layerSync = false; | 
|  | _codecSpecificInfo.codecSpecific.VP8.keyIdx = -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; | 
|  | } | 
|  | if (header->codecHeader.VP8.temporalIdx != kNoTemporalIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP8.temporalIdx = | 
|  | header->codecHeader.VP8.temporalIdx; | 
|  | _codecSpecificInfo.codecSpecific.VP8.layerSync = | 
|  | header->codecHeader.VP8.layerSync; | 
|  | } | 
|  | if (header->codecHeader.VP8.keyIdx != kNoKeyIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP8.keyIdx = | 
|  | header->codecHeader.VP8.keyIdx; | 
|  | } | 
|  | break; | 
|  | } | 
|  | case kRtpVideoH264: { | 
|  | _codecSpecificInfo.codecType = kVideoCodecH264; | 
|  | break; | 
|  | } | 
|  | default: { | 
|  | _codecSpecificInfo.codecType = kVideoCodecUnknown; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | const RTPFragmentationHeader* VCMEncodedFrame::FragmentationHeader() const { | 
|  | return &_fragmentation; | 
|  | } | 
|  |  | 
|  | void VCMEncodedFrame::VerifyAndAllocate(const uint32_t minimumSize) | 
|  | { | 
|  | if(minimumSize > _size) | 
|  | { | 
|  | // create buffer of sufficient size | 
|  | uint8_t* newBuffer = new uint8_t[minimumSize]; | 
|  | if(_buffer) | 
|  | { | 
|  | // copy old data | 
|  | memcpy(newBuffer, _buffer, _size); | 
|  | delete [] _buffer; | 
|  | } | 
|  | _buffer = newBuffer; | 
|  | _size = minimumSize; | 
|  | } | 
|  | } | 
|  |  | 
|  | webrtc::FrameType VCMEncodedFrame::ConvertFrameType(VideoFrameType frameType) | 
|  | { | 
|  | switch(frameType) { | 
|  | case kKeyFrame: | 
|  | return  kVideoFrameKey; | 
|  | case kDeltaFrame: | 
|  | return kVideoFrameDelta; | 
|  | case kSkipFrame: | 
|  | return kFrameEmpty; | 
|  | default: | 
|  | return kVideoFrameDelta; | 
|  | } | 
|  | } | 
|  |  | 
|  | VideoFrameType VCMEncodedFrame::ConvertFrameType(webrtc::FrameType frame_type) { | 
|  | switch (frame_type) { | 
|  | case kVideoFrameKey: | 
|  | return kKeyFrame; | 
|  | case kVideoFrameDelta: | 
|  | return kDeltaFrame; | 
|  | default: | 
|  | assert(false); | 
|  | return kDeltaFrame; | 
|  | } | 
|  | } | 
|  |  | 
|  | void VCMEncodedFrame::ConvertFrameTypes( | 
|  | const std::vector<webrtc::FrameType>& frame_types, | 
|  | std::vector<VideoFrameType>* video_frame_types) { | 
|  | assert(video_frame_types); | 
|  | video_frame_types->reserve(frame_types.size()); | 
|  | for (size_t i = 0; i < frame_types.size(); ++i) { | 
|  | (*video_frame_types)[i] = ConvertFrameType(frame_types[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | } |