Home | History | Annotate | Download | only in source
      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