Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / main / source / frame_buffer.cc
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