1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/video_coding/main/source/frame_buffer.h" 12 13 #include <assert.h> 14 #include <string.h> 15 16 #include "webrtc/modules/video_coding/main/source/packet.h" 17 #include "webrtc/system_wrappers/interface/logging.h" 18 19 namespace webrtc { 20 21 VCMFrameBuffer::VCMFrameBuffer() 22 : 23 _state(kStateEmpty), 24 _frameCounted(false), 25 _nackCount(0), 26 _latestPacketTimeMs(-1) { 27 } 28 29 VCMFrameBuffer::~VCMFrameBuffer() { 30 } 31 32 VCMFrameBuffer::VCMFrameBuffer(const VCMFrameBuffer& rhs) 33 : 34 VCMEncodedFrame(rhs), 35 _state(rhs._state), 36 _frameCounted(rhs._frameCounted), 37 _sessionInfo(), 38 _nackCount(rhs._nackCount), 39 _latestPacketTimeMs(rhs._latestPacketTimeMs) { 40 _sessionInfo = rhs._sessionInfo; 41 _sessionInfo.UpdateDataPointers(rhs._buffer, _buffer); 42 } 43 44 webrtc::FrameType 45 VCMFrameBuffer::FrameType() const { 46 return _sessionInfo.FrameType(); 47 } 48 49 int32_t 50 VCMFrameBuffer::GetLowSeqNum() const { 51 return _sessionInfo.LowSequenceNumber(); 52 } 53 54 int32_t 55 VCMFrameBuffer::GetHighSeqNum() const { 56 return _sessionInfo.HighSequenceNumber(); 57 } 58 59 int VCMFrameBuffer::PictureId() const { 60 return _sessionInfo.PictureId(); 61 } 62 63 int VCMFrameBuffer::TemporalId() const { 64 return _sessionInfo.TemporalId(); 65 } 66 67 bool VCMFrameBuffer::LayerSync() const { 68 return _sessionInfo.LayerSync(); 69 } 70 71 int VCMFrameBuffer::Tl0PicId() const { 72 return _sessionInfo.Tl0PicId(); 73 } 74 75 bool VCMFrameBuffer::NonReference() const { 76 return _sessionInfo.NonReference(); 77 } 78 79 bool 80 VCMFrameBuffer::IsSessionComplete() const { 81 return _sessionInfo.complete(); 82 } 83 84 // Insert packet 85 VCMFrameBufferEnum 86 VCMFrameBuffer::InsertPacket(const VCMPacket& packet, 87 int64_t timeInMs, 88 VCMDecodeErrorMode decode_error_mode, 89 const FrameData& frame_data) { 90 assert(!(NULL == packet.dataPtr && packet.sizeBytes > 0)); 91 if (packet.dataPtr != NULL) { 92 _payloadType = packet.payloadType; 93 } 94 95 if (kStateEmpty == _state) { 96 // First packet (empty and/or media) inserted into this frame. 97 // store some info and set some initial values. 98 _timeStamp = packet.timestamp; 99 // We only take the ntp timestamp of the first packet of a frame. 100 ntp_time_ms_ = packet.ntp_time_ms_; 101 _codec = packet.codec; 102 if (packet.frameType != kFrameEmpty) { 103 // first media packet 104 SetState(kStateIncomplete); 105 } 106 } 107 108 uint32_t requiredSizeBytes = Length() + packet.sizeBytes + 109 (packet.insertStartCode ? kH264StartCodeLengthBytes : 0); 110 if (requiredSizeBytes >= _size) { 111 const uint8_t* prevBuffer = _buffer; 112 const uint32_t increments = requiredSizeBytes / 113 kBufferIncStepSizeBytes + 114 (requiredSizeBytes % 115 kBufferIncStepSizeBytes > 0); 116 const uint32_t newSize = _size + 117 increments * kBufferIncStepSizeBytes; 118 if (newSize > kMaxJBFrameSizeBytes) { 119 LOG(LS_ERROR) << "Failed to insert packet due to frame being too " 120 "big."; 121 return kSizeError; 122 } 123 VerifyAndAllocate(newSize); 124 _sessionInfo.UpdateDataPointers(prevBuffer, _buffer); 125 } 126 127 if (packet.width > 0 && packet.height > 0) { 128 _encodedWidth = packet.width; 129 _encodedHeight = packet.height; 130 } 131 132 CopyCodecSpecific(&packet.codecSpecificHeader); 133 134 int retVal = _sessionInfo.InsertPacket(packet, _buffer, 135 decode_error_mode, 136 frame_data); 137 if (retVal == -1) { 138 return kSizeError; 139 } else if (retVal == -2) { 140 return kDuplicatePacket; 141 } else if (retVal == -3) { 142 return kOutOfBoundsPacket; 143 } 144 // update length 145 _length = Length() + static_cast<uint32_t>(retVal); 146 147 _latestPacketTimeMs = timeInMs; 148 149 if (_sessionInfo.complete()) { 150 SetState(kStateComplete); 151 return kCompleteSession; 152 } else if (_sessionInfo.decodable()) { 153 SetState(kStateDecodable); 154 return kDecodableSession; 155 } 156 return kIncomplete; 157 } 158 159 int64_t 160 VCMFrameBuffer::LatestPacketTimeMs() const { 161 return _latestPacketTimeMs; 162 } 163 164 void 165 VCMFrameBuffer::IncrementNackCount() { 166 _nackCount++; 167 } 168 169 int16_t 170 VCMFrameBuffer::GetNackCount() const { 171 return _nackCount; 172 } 173 174 bool 175 VCMFrameBuffer::HaveFirstPacket() const { 176 return _sessionInfo.HaveFirstPacket(); 177 } 178 179 bool 180 VCMFrameBuffer::HaveLastPacket() const { 181 return _sessionInfo.HaveLastPacket(); 182 } 183 184 int 185 VCMFrameBuffer::NumPackets() const { 186 return _sessionInfo.NumPackets(); 187 } 188 189 void 190 VCMFrameBuffer::Reset() { 191 _length = 0; 192 _timeStamp = 0; 193 _sessionInfo.Reset(); 194 _frameCounted = false; 195 _payloadType = 0; 196 _nackCount = 0; 197 _latestPacketTimeMs = -1; 198 _state = kStateEmpty; 199 VCMEncodedFrame::Reset(); 200 } 201 202 // Set state of frame 203 void 204 VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) { 205 if (_state == state) { 206 return; 207 } 208 switch (state) { 209 case kStateIncomplete: 210 // we can go to this state from state kStateEmpty 211 assert(_state == kStateEmpty); 212 213 // Do nothing, we received a packet 214 break; 215 216 case kStateComplete: 217 assert(_state == kStateEmpty || 218 _state == kStateIncomplete || 219 _state == kStateDecodable); 220 221 break; 222 223 case kStateEmpty: 224 // Should only be set to empty through Reset(). 225 assert(false); 226 break; 227 228 case kStateDecodable: 229 assert(_state == kStateEmpty || 230 _state == kStateIncomplete); 231 break; 232 } 233 _state = state; 234 } 235 236 // Set counted status (as counted by JB or not) 237 void VCMFrameBuffer::SetCountedFrame(bool frameCounted) { 238 _frameCounted = frameCounted; 239 } 240 241 bool VCMFrameBuffer::GetCountedFrame() const { 242 return _frameCounted; 243 } 244 245 // Get current state of frame 246 VCMFrameBufferStateEnum 247 VCMFrameBuffer::GetState() const { 248 return _state; 249 } 250 251 // Get current state of frame 252 VCMFrameBufferStateEnum 253 VCMFrameBuffer::GetState(uint32_t& timeStamp) const { 254 timeStamp = TimeStamp(); 255 return GetState(); 256 } 257 258 bool 259 VCMFrameBuffer::IsRetransmitted() const { 260 return _sessionInfo.session_nack(); 261 } 262 263 void 264 VCMFrameBuffer::PrepareForDecode(bool continuous) { 265 #ifdef INDEPENDENT_PARTITIONS 266 if (_codec == kVideoCodecVP8) { 267 _length = 268 _sessionInfo.BuildVP8FragmentationHeader(_buffer, _length, 269 &_fragmentation); 270 } else { 271 int bytes_removed = _sessionInfo.MakeDecodable(); 272 _length -= bytes_removed; 273 } 274 #else 275 int bytes_removed = _sessionInfo.MakeDecodable(); 276 _length -= bytes_removed; 277 #endif 278 // Transfer frame information to EncodedFrame and create any codec 279 // specific information. 280 _frameType = ConvertFrameType(_sessionInfo.FrameType()); 281 _completeFrame = _sessionInfo.complete(); 282 _missingFrame = !continuous; 283 } 284 285 } // namespace webrtc 286