2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_coding/main/source/frame_buffer.h"
16 #include "webrtc/modules/video_coding/main/source/packet.h"
17 #include "webrtc/system_wrappers/interface/logging.h"
21 VCMFrameBuffer::VCMFrameBuffer()
26 _latestPacketTimeMs(-1) {
29 VCMFrameBuffer::~VCMFrameBuffer() {
32 VCMFrameBuffer::VCMFrameBuffer(const VCMFrameBuffer& rhs)
36 _frameCounted(rhs._frameCounted),
38 _nackCount(rhs._nackCount),
39 _latestPacketTimeMs(rhs._latestPacketTimeMs) {
40 _sessionInfo = rhs._sessionInfo;
41 _sessionInfo.UpdateDataPointers(rhs._buffer, _buffer);
45 VCMFrameBuffer::FrameType() const {
46 return _sessionInfo.FrameType();
50 VCMFrameBuffer::GetLowSeqNum() const {
51 return _sessionInfo.LowSequenceNumber();
55 VCMFrameBuffer::GetHighSeqNum() const {
56 return _sessionInfo.HighSequenceNumber();
59 int VCMFrameBuffer::PictureId() const {
60 return _sessionInfo.PictureId();
63 int VCMFrameBuffer::TemporalId() const {
64 return _sessionInfo.TemporalId();
67 bool VCMFrameBuffer::LayerSync() const {
68 return _sessionInfo.LayerSync();
71 int VCMFrameBuffer::Tl0PicId() const {
72 return _sessionInfo.Tl0PicId();
75 bool VCMFrameBuffer::NonReference() const {
76 return _sessionInfo.NonReference();
80 VCMFrameBuffer::IsSessionComplete() const {
81 return _sessionInfo.complete();
86 VCMFrameBuffer::InsertPacket(const VCMPacket& packet,
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;
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);
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 +
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 "
123 VerifyAndAllocate(newSize);
124 _sessionInfo.UpdateDataPointers(prevBuffer, _buffer);
127 if (packet.width > 0 && packet.height > 0) {
128 _encodedWidth = packet.width;
129 _encodedHeight = packet.height;
132 CopyCodecSpecific(&packet.codecSpecificHeader);
134 int retVal = _sessionInfo.InsertPacket(packet, _buffer,
139 } else if (retVal == -2) {
140 return kDuplicatePacket;
141 } else if (retVal == -3) {
142 return kOutOfBoundsPacket;
145 _length = Length() + static_cast<uint32_t>(retVal);
147 _latestPacketTimeMs = timeInMs;
149 if (_sessionInfo.complete()) {
150 SetState(kStateComplete);
151 return kCompleteSession;
152 } else if (_sessionInfo.decodable()) {
153 SetState(kStateDecodable);
154 return kDecodableSession;
160 VCMFrameBuffer::LatestPacketTimeMs() const {
161 return _latestPacketTimeMs;
165 VCMFrameBuffer::IncrementNackCount() {
170 VCMFrameBuffer::GetNackCount() const {
175 VCMFrameBuffer::HaveFirstPacket() const {
176 return _sessionInfo.HaveFirstPacket();
180 VCMFrameBuffer::HaveLastPacket() const {
181 return _sessionInfo.HaveLastPacket();
185 VCMFrameBuffer::NumPackets() const {
186 return _sessionInfo.NumPackets();
190 VCMFrameBuffer::Reset() {
193 _sessionInfo.Reset();
194 _frameCounted = false;
197 _latestPacketTimeMs = -1;
198 _state = kStateEmpty;
199 VCMEncodedFrame::Reset();
202 // Set state of frame
204 VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) {
205 if (_state == state) {
209 case kStateIncomplete:
210 // we can go to this state from state kStateEmpty
211 assert(_state == kStateEmpty);
213 // Do nothing, we received a packet
217 assert(_state == kStateEmpty ||
218 _state == kStateIncomplete ||
219 _state == kStateDecodable);
224 // Should only be set to empty through Reset().
228 case kStateDecodable:
229 assert(_state == kStateEmpty ||
230 _state == kStateIncomplete);
236 // Set counted status (as counted by JB or not)
237 void VCMFrameBuffer::SetCountedFrame(bool frameCounted) {
238 _frameCounted = frameCounted;
241 bool VCMFrameBuffer::GetCountedFrame() const {
242 return _frameCounted;
245 // Get current state of frame
246 VCMFrameBufferStateEnum
247 VCMFrameBuffer::GetState() const {
251 // Get current state of frame
252 VCMFrameBufferStateEnum
253 VCMFrameBuffer::GetState(uint32_t& timeStamp) const {
254 timeStamp = TimeStamp();
259 VCMFrameBuffer::IsRetransmitted() const {
260 return _sessionInfo.session_nack();
264 VCMFrameBuffer::PrepareForDecode(bool continuous) {
265 #ifdef INDEPENDENT_PARTITIONS
266 if (_codec == kVideoCodecVP8) {
268 _sessionInfo.BuildVP8FragmentationHeader(_buffer, _length,
271 int bytes_removed = _sessionInfo.MakeDecodable();
272 _length -= bytes_removed;
275 int bytes_removed = _sessionInfo.MakeDecodable();
276 _length -= bytes_removed;
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;
285 } // namespace webrtc