|  | /* | 
|  | *  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/include/video_coding_defines.h" | 
|  | #include "webrtc/modules/video_coding/encoded_frame.h" | 
|  | #include "webrtc/modules/video_coding/generic_encoder.h" | 
|  | #include "webrtc/modules/video_coding/jitter_buffer_common.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | VCMEncodedFrame::VCMEncodedFrame() | 
|  | : webrtc::EncodedImage(), | 
|  | _renderTimeMs(-1), | 
|  | _payloadType(0), | 
|  | _missingFrame(false), | 
|  | _codec(kVideoCodecUnknown), | 
|  | _fragmentation(), | 
|  | _rotation(kVideoRotation_0), | 
|  | _rotation_set(false) { | 
|  | _codecSpecificInfo.codecType = kVideoCodecUnknown; | 
|  | } | 
|  |  | 
|  | VCMEncodedFrame::VCMEncodedFrame(const webrtc::EncodedImage& rhs) | 
|  | : webrtc::EncodedImage(rhs), | 
|  | _renderTimeMs(-1), | 
|  | _payloadType(0), | 
|  | _missingFrame(false), | 
|  | _codec(kVideoCodecUnknown), | 
|  | _fragmentation(), | 
|  | _rotation(kVideoRotation_0), | 
|  | _rotation_set(false) { | 
|  | _codecSpecificInfo.codecType = kVideoCodecUnknown; | 
|  | _buffer = NULL; | 
|  | _size = 0; | 
|  | _length = 0; | 
|  | if (rhs._buffer != NULL) { | 
|  | VerifyAndAllocate(rhs._length + | 
|  | EncodedImage::GetBufferPaddingBytes(_codec)); | 
|  | 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(), | 
|  | _rotation(rhs._rotation), | 
|  | _rotation_set(rhs._rotation_set) { | 
|  | _buffer = NULL; | 
|  | _size = 0; | 
|  | _length = 0; | 
|  | if (rhs._buffer != NULL) { | 
|  | VerifyAndAllocate(rhs._length + | 
|  | EncodedImage::GetBufferPaddingBytes(_codec)); | 
|  | 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 = kVideoFrameDelta; | 
|  | _encodedWidth = 0; | 
|  | _encodedHeight = 0; | 
|  | _completeFrame = false; | 
|  | _missingFrame = false; | 
|  | _length = 0; | 
|  | _codecSpecificInfo.codecType = kVideoCodecUnknown; | 
|  | _codec = kVideoCodecUnknown; | 
|  | _rotation = kVideoRotation_0; | 
|  | _rotation_set = false; | 
|  | } | 
|  |  | 
|  | 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 kRtpVideoVp9: { | 
|  | if (_codecSpecificInfo.codecType != kVideoCodecVP9) { | 
|  | // This is the first packet for this frame. | 
|  | _codecSpecificInfo.codecSpecific.VP9.picture_id = -1; | 
|  | _codecSpecificInfo.codecSpecific.VP9.temporal_idx = 0; | 
|  | _codecSpecificInfo.codecSpecific.VP9.spatial_idx = 0; | 
|  | _codecSpecificInfo.codecSpecific.VP9.gof_idx = 0; | 
|  | _codecSpecificInfo.codecSpecific.VP9.inter_layer_predicted = false; | 
|  | _codecSpecificInfo.codecSpecific.VP9.tl0_pic_idx = -1; | 
|  | _codecSpecificInfo.codecType = kVideoCodecVP9; | 
|  | } | 
|  | _codecSpecificInfo.codecSpecific.VP9.inter_pic_predicted = | 
|  | header->codecHeader.VP9.inter_pic_predicted; | 
|  | _codecSpecificInfo.codecSpecific.VP9.flexible_mode = | 
|  | header->codecHeader.VP9.flexible_mode; | 
|  | _codecSpecificInfo.codecSpecific.VP9.num_ref_pics = | 
|  | header->codecHeader.VP9.num_ref_pics; | 
|  | for (uint8_t r = 0; r < header->codecHeader.VP9.num_ref_pics; ++r) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.p_diff[r] = | 
|  | header->codecHeader.VP9.pid_diff[r]; | 
|  | } | 
|  | _codecSpecificInfo.codecSpecific.VP9.ss_data_available = | 
|  | header->codecHeader.VP9.ss_data_available; | 
|  | if (header->codecHeader.VP9.picture_id != kNoPictureId) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.picture_id = | 
|  | header->codecHeader.VP9.picture_id; | 
|  | } | 
|  | if (header->codecHeader.VP9.tl0_pic_idx != kNoTl0PicIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.tl0_pic_idx = | 
|  | header->codecHeader.VP9.tl0_pic_idx; | 
|  | } | 
|  | if (header->codecHeader.VP9.temporal_idx != kNoTemporalIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.temporal_idx = | 
|  | header->codecHeader.VP9.temporal_idx; | 
|  | _codecSpecificInfo.codecSpecific.VP9.temporal_up_switch = | 
|  | header->codecHeader.VP9.temporal_up_switch; | 
|  | } | 
|  | if (header->codecHeader.VP9.spatial_idx != kNoSpatialIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.spatial_idx = | 
|  | header->codecHeader.VP9.spatial_idx; | 
|  | _codecSpecificInfo.codecSpecific.VP9.inter_layer_predicted = | 
|  | header->codecHeader.VP9.inter_layer_predicted; | 
|  | } | 
|  | if (header->codecHeader.VP9.gof_idx != kNoGofIdx) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.gof_idx = | 
|  | header->codecHeader.VP9.gof_idx; | 
|  | } | 
|  | if (header->codecHeader.VP9.ss_data_available) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.num_spatial_layers = | 
|  | header->codecHeader.VP9.num_spatial_layers; | 
|  | _codecSpecificInfo.codecSpecific.VP9 | 
|  | .spatial_layer_resolution_present = | 
|  | header->codecHeader.VP9.spatial_layer_resolution_present; | 
|  | if (header->codecHeader.VP9.spatial_layer_resolution_present) { | 
|  | for (size_t i = 0; i < header->codecHeader.VP9.num_spatial_layers; | 
|  | ++i) { | 
|  | _codecSpecificInfo.codecSpecific.VP9.width[i] = | 
|  | header->codecHeader.VP9.width[i]; | 
|  | _codecSpecificInfo.codecSpecific.VP9.height[i] = | 
|  | header->codecHeader.VP9.height[i]; | 
|  | } | 
|  | } | 
|  | _codecSpecificInfo.codecSpecific.VP9.gof.CopyGofInfoVP9( | 
|  | header->codecHeader.VP9.gof); | 
|  | } | 
|  | break; | 
|  | } | 
|  | case kRtpVideoH264: { | 
|  | _codecSpecificInfo.codecType = kVideoCodecH264; | 
|  | break; | 
|  | } | 
|  | default: { | 
|  | _codecSpecificInfo.codecType = kVideoCodecUnknown; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | const RTPFragmentationHeader* VCMEncodedFrame::FragmentationHeader() const { | 
|  | return &_fragmentation; | 
|  | } | 
|  |  | 
|  | void VCMEncodedFrame::VerifyAndAllocate(size_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; | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace webrtc |