frame_buffer.cc (8783B)
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 "modules/video_coding/deprecated/frame_buffer.h" 12 13 #include <cstdint> 14 #include <cstring> 15 #include <vector> 16 17 #include "api/video/encoded_image.h" 18 #include "api/video/video_frame_type.h" 19 #include "api/video/video_timing.h" 20 #include "modules/video_coding/codecs/h264/include/h264_globals.h" 21 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" 22 #include "modules/video_coding/deprecated/jitter_buffer_common.h" 23 #include "modules/video_coding/deprecated/packet.h" 24 #include "modules/video_coding/deprecated/session_info.h" 25 #include "modules/video_coding/encoded_frame.h" 26 #include "rtc_base/checks.h" 27 #include "rtc_base/logging.h" 28 #include "rtc_base/trace_event.h" 29 30 namespace webrtc { 31 32 VCMFrameBuffer::VCMFrameBuffer() 33 : _state(kStateEmpty), _nackCount(0), _latestPacketTimeMs(-1) {} 34 35 VCMFrameBuffer::~VCMFrameBuffer() {} 36 37 VideoFrameType VCMFrameBuffer::FrameType() const { 38 return _sessionInfo.FrameType(); 39 } 40 41 int32_t VCMFrameBuffer::GetLowSeqNum() const { 42 return _sessionInfo.LowSequenceNumber(); 43 } 44 45 int32_t VCMFrameBuffer::GetHighSeqNum() const { 46 return _sessionInfo.HighSequenceNumber(); 47 } 48 49 int VCMFrameBuffer::PictureId() const { 50 return _sessionInfo.PictureId(); 51 } 52 53 int VCMFrameBuffer::TemporalId() const { 54 return _sessionInfo.TemporalId(); 55 } 56 57 bool VCMFrameBuffer::LayerSync() const { 58 return _sessionInfo.LayerSync(); 59 } 60 61 int VCMFrameBuffer::Tl0PicId() const { 62 return _sessionInfo.Tl0PicId(); 63 } 64 65 std::vector<NaluInfo> VCMFrameBuffer::GetNaluInfos() const { 66 return _sessionInfo.GetNaluInfos(); 67 } 68 69 void VCMFrameBuffer::SetGofInfo(const GofInfoVP9& gof_info, size_t idx) { 70 TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetGofInfo"); 71 _sessionInfo.SetGofInfo(gof_info, idx); 72 // TODO(asapersson): Consider adding hdr->VP9.ref_picture_id for testing. 73 _codecSpecificInfo.codecSpecific.VP9.temporal_idx = 74 gof_info.temporal_idx[idx]; 75 _codecSpecificInfo.codecSpecific.VP9.temporal_up_switch = 76 gof_info.temporal_up_switch[idx]; 77 } 78 79 // Insert packet 80 VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(const VCMPacket& packet, 81 int64_t timeInMs, 82 const FrameData& frame_data) { 83 TRACE_EVENT0("webrtc", "VCMFrameBuffer::InsertPacket"); 84 RTC_DCHECK(!(nullptr == packet.dataPtr && packet.sizeBytes > 0)); 85 if (packet.dataPtr != nullptr) { 86 _payloadType = packet.payloadType; 87 } 88 89 if (kStateEmpty == _state) { 90 // First packet (empty and/or media) inserted into this frame. 91 // store some info and set some initial values. 92 SetRtpTimestamp(packet.timestamp); 93 // We only take the ntp timestamp of the first packet of a frame. 94 ntp_time_ms_ = packet.ntp_time_ms_; 95 _codec = packet.codec(); 96 if (packet.video_header.frame_type != VideoFrameType::kEmptyFrame) { 97 // first media packet 98 SetState(kStateIncomplete); 99 } 100 } 101 102 size_t oldSize = encoded_image_buffer_ ? encoded_image_buffer_->size() : 0; 103 uint32_t requiredSizeBytes = 104 size() + packet.sizeBytes + 105 (packet.insertStartCode ? kH264StartCodeLengthBytes : 0); 106 if (requiredSizeBytes > oldSize) { 107 const uint8_t* prevBuffer = data(); 108 const uint32_t increments = 109 requiredSizeBytes / kBufferIncStepSizeBytes + 110 (requiredSizeBytes % kBufferIncStepSizeBytes > 0); 111 const uint32_t newSize = oldSize + increments * kBufferIncStepSizeBytes; 112 if (newSize > kMaxJBFrameSizeBytes) { 113 RTC_LOG(LS_ERROR) << "Failed to insert packet due to frame being too " 114 "big."; 115 return kSizeError; 116 } 117 if (data() == nullptr) { 118 encoded_image_buffer_ = EncodedImageBuffer::Create(newSize); 119 SetEncodedData(encoded_image_buffer_); 120 set_size(0); 121 } else { 122 RTC_CHECK(encoded_image_buffer_ != nullptr); 123 RTC_DCHECK_EQ(encoded_image_buffer_->data(), data()); 124 encoded_image_buffer_->Realloc(newSize); 125 } 126 _sessionInfo.UpdateDataPointers(prevBuffer, data()); 127 } 128 129 if (packet.width() > 0 && packet.height() > 0) { 130 _encodedWidth = packet.width(); 131 _encodedHeight = packet.height(); 132 } 133 134 // Don't copy payload specific data for empty packets (e.g padding packets). 135 if (packet.sizeBytes > 0) 136 CopyCodecSpecific(&packet.video_header); 137 138 int retVal = _sessionInfo.InsertPacket( 139 packet, encoded_image_buffer_ ? encoded_image_buffer_->data() : nullptr, 140 frame_data); 141 if (retVal == -1) { 142 return kSizeError; 143 } else if (retVal == -2) { 144 return kDuplicatePacket; 145 } else if (retVal == -3) { 146 return kOutOfBoundsPacket; 147 } 148 // update size 149 set_size(size() + static_cast<uint32_t>(retVal)); 150 151 _latestPacketTimeMs = timeInMs; 152 153 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ 154 // ts_126114v120700p.pdf Section 7.4.5. 155 // The MTSI client shall add the payload bytes as defined in this clause 156 // onto the last RTP packet in each group of packets which make up a key 157 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 158 // (HEVC)). 159 if (packet.markerBit) { 160 rotation_ = packet.video_header.rotation; 161 content_type_ = packet.video_header.content_type; 162 if (packet.video_header.video_timing.flags != VideoSendTiming::kInvalid) { 163 timing_.encode_start_ms = 164 ntp_time_ms_ + packet.video_header.video_timing.encode_start_delta_ms; 165 timing_.encode_finish_ms = 166 ntp_time_ms_ + 167 packet.video_header.video_timing.encode_finish_delta_ms; 168 timing_.packetization_finish_ms = 169 ntp_time_ms_ + 170 packet.video_header.video_timing.packetization_finish_delta_ms; 171 timing_.pacer_exit_ms = 172 ntp_time_ms_ + packet.video_header.video_timing.pacer_exit_delta_ms; 173 timing_.network_timestamp_ms = 174 ntp_time_ms_ + 175 packet.video_header.video_timing.network_timestamp_delta_ms; 176 timing_.network2_timestamp_ms = 177 ntp_time_ms_ + 178 packet.video_header.video_timing.network2_timestamp_delta_ms; 179 } 180 timing_.flags = packet.video_header.video_timing.flags; 181 } 182 183 if (packet.is_first_packet_in_frame()) { 184 SetPlayoutDelay(packet.video_header.playout_delay); 185 } 186 187 if (_sessionInfo.complete()) { 188 SetState(kStateComplete); 189 return kCompleteSession; 190 } 191 return kIncomplete; 192 } 193 194 int64_t VCMFrameBuffer::LatestPacketTimeMs() const { 195 TRACE_EVENT0("webrtc", "VCMFrameBuffer::LatestPacketTimeMs"); 196 return _latestPacketTimeMs; 197 } 198 199 void VCMFrameBuffer::IncrementNackCount() { 200 TRACE_EVENT0("webrtc", "VCMFrameBuffer::IncrementNackCount"); 201 _nackCount++; 202 } 203 204 int16_t VCMFrameBuffer::GetNackCount() const { 205 TRACE_EVENT0("webrtc", "VCMFrameBuffer::GetNackCount"); 206 return _nackCount; 207 } 208 209 bool VCMFrameBuffer::HaveFirstPacket() const { 210 TRACE_EVENT0("webrtc", "VCMFrameBuffer::HaveFirstPacket"); 211 return _sessionInfo.HaveFirstPacket(); 212 } 213 214 int VCMFrameBuffer::NumPackets() const { 215 TRACE_EVENT0("webrtc", "VCMFrameBuffer::NumPackets"); 216 return _sessionInfo.NumPackets(); 217 } 218 219 void VCMFrameBuffer::Reset() { 220 TRACE_EVENT0("webrtc", "VCMFrameBuffer::Reset"); 221 set_size(0); 222 _sessionInfo.Reset(); 223 _payloadType = 0; 224 _nackCount = 0; 225 _latestPacketTimeMs = -1; 226 _state = kStateEmpty; 227 VCMEncodedFrame::Reset(); 228 } 229 230 // Set state of frame 231 void VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) { 232 TRACE_EVENT0("webrtc", "VCMFrameBuffer::SetState"); 233 if (_state == state) { 234 return; 235 } 236 switch (state) { 237 case kStateIncomplete: 238 // we can go to this state from state kStateEmpty 239 RTC_DCHECK_EQ(_state, kStateEmpty); 240 241 // Do nothing, we received a packet 242 break; 243 244 case kStateComplete: 245 RTC_DCHECK(_state == kStateEmpty || _state == kStateIncomplete); 246 247 break; 248 249 case kStateEmpty: 250 // Should only be set to empty through Reset(). 251 RTC_DCHECK_NOTREACHED(); 252 break; 253 } 254 _state = state; 255 } 256 257 // Get current state of frame 258 VCMFrameBufferStateEnum VCMFrameBuffer::GetState() const { 259 return _state; 260 } 261 262 void VCMFrameBuffer::PrepareForDecode(bool continuous) { 263 TRACE_EVENT0("webrtc", "VCMFrameBuffer::PrepareForDecode"); 264 size_t bytes_removed = _sessionInfo.MakeDecodable(); 265 set_size(size() - bytes_removed); 266 // Transfer frame information to EncodedFrame and create any codec 267 // specific information. 268 _frameType = _sessionInfo.FrameType(); 269 _missingFrame = !continuous; 270 } 271 272 } // namespace webrtc