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