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/interface/video_coding_defines.h"
12#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
13#include "webrtc/modules/video_coding/main/source/generic_encoder.h"
14#include "webrtc/modules/video_coding/main/source/jitter_buffer_common.h"
15
16namespace webrtc {
17
18VCMEncodedFrame::VCMEncodedFrame()
19:
20webrtc::EncodedImage(),
21_renderTimeMs(-1),
22_payloadType(0),
23_missingFrame(false),
24_codec(kVideoCodecUnknown),
25_fragmentation()
26{
27    _codecSpecificInfo.codecType = kVideoCodecUnknown;
28}
29
30VCMEncodedFrame::VCMEncodedFrame(const webrtc::EncodedImage& rhs)
31:
32webrtc::EncodedImage(rhs),
33_renderTimeMs(-1),
34_payloadType(0),
35_missingFrame(false),
36_codec(kVideoCodecUnknown),
37_fragmentation()
38{
39    _codecSpecificInfo.codecType = kVideoCodecUnknown;
40    _buffer = NULL;
41    _size = 0;
42    _length = 0;
43    if (rhs._buffer != NULL)
44    {
45        VerifyAndAllocate(rhs._length);
46        memcpy(_buffer, rhs._buffer, rhs._length);
47    }
48}
49
50VCMEncodedFrame::VCMEncodedFrame(const VCMEncodedFrame& rhs)
51  :
52    webrtc::EncodedImage(rhs),
53    _renderTimeMs(rhs._renderTimeMs),
54    _payloadType(rhs._payloadType),
55    _missingFrame(rhs._missingFrame),
56    _codecSpecificInfo(rhs._codecSpecificInfo),
57    _codec(rhs._codec),
58    _fragmentation() {
59  _buffer = NULL;
60  _size = 0;
61  _length = 0;
62  if (rhs._buffer != NULL)
63  {
64      VerifyAndAllocate(rhs._length);
65      memcpy(_buffer, rhs._buffer, rhs._length);
66      _length = rhs._length;
67  }
68  _fragmentation.CopyFrom(rhs._fragmentation);
69}
70
71VCMEncodedFrame::~VCMEncodedFrame()
72{
73    Free();
74}
75
76void VCMEncodedFrame::Free()
77{
78    Reset();
79    if (_buffer != NULL)
80    {
81        delete [] _buffer;
82        _buffer = NULL;
83    }
84}
85
86void VCMEncodedFrame::Reset()
87{
88    _renderTimeMs = -1;
89    _timeStamp = 0;
90    _payloadType = 0;
91    _frameType = kDeltaFrame;
92    _encodedWidth = 0;
93    _encodedHeight = 0;
94    _completeFrame = false;
95    _missingFrame = false;
96    _length = 0;
97    _codecSpecificInfo.codecType = kVideoCodecUnknown;
98    _codec = kVideoCodecUnknown;
99}
100
101void VCMEncodedFrame::CopyCodecSpecific(const RTPVideoHeader* header)
102{
103  if (header) {
104    switch (header->codec) {
105      case kRtpVideoVp8: {
106        if (_codecSpecificInfo.codecType != kVideoCodecVP8) {
107          // This is the first packet for this frame.
108          _codecSpecificInfo.codecSpecific.VP8.pictureId = -1;
109          _codecSpecificInfo.codecSpecific.VP8.temporalIdx = 0;
110          _codecSpecificInfo.codecSpecific.VP8.layerSync = false;
111          _codecSpecificInfo.codecSpecific.VP8.keyIdx = -1;
112          _codecSpecificInfo.codecType = kVideoCodecVP8;
113        }
114        _codecSpecificInfo.codecSpecific.VP8.nonReference =
115            header->codecHeader.VP8.nonReference;
116        if (header->codecHeader.VP8.pictureId != kNoPictureId) {
117          _codecSpecificInfo.codecSpecific.VP8.pictureId =
118              header->codecHeader.VP8.pictureId;
119        }
120        if (header->codecHeader.VP8.temporalIdx != kNoTemporalIdx) {
121          _codecSpecificInfo.codecSpecific.VP8.temporalIdx =
122              header->codecHeader.VP8.temporalIdx;
123          _codecSpecificInfo.codecSpecific.VP8.layerSync =
124              header->codecHeader.VP8.layerSync;
125        }
126        if (header->codecHeader.VP8.keyIdx != kNoKeyIdx) {
127          _codecSpecificInfo.codecSpecific.VP8.keyIdx =
128              header->codecHeader.VP8.keyIdx;
129        }
130        break;
131      }
132      case kRtpVideoH264: {
133        _codecSpecificInfo.codecType = kVideoCodecH264;
134        break;
135      }
136      default: {
137        _codecSpecificInfo.codecType = kVideoCodecUnknown;
138        break;
139      }
140    }
141  }
142}
143
144const RTPFragmentationHeader* VCMEncodedFrame::FragmentationHeader() const {
145  return &_fragmentation;
146}
147
148void VCMEncodedFrame::VerifyAndAllocate(const uint32_t minimumSize)
149{
150    if(minimumSize > _size)
151    {
152        // create buffer of sufficient size
153        uint8_t* newBuffer = new uint8_t[minimumSize];
154        if(_buffer)
155        {
156            // copy old data
157            memcpy(newBuffer, _buffer, _size);
158            delete [] _buffer;
159        }
160        _buffer = newBuffer;
161        _size = minimumSize;
162    }
163}
164
165webrtc::FrameType VCMEncodedFrame::ConvertFrameType(VideoFrameType frameType)
166{
167  switch(frameType) {
168    case kKeyFrame:
169      return  kVideoFrameKey;
170    case kDeltaFrame:
171      return kVideoFrameDelta;
172    case kSkipFrame:
173      return kFrameEmpty;
174    default:
175      return kVideoFrameDelta;
176  }
177}
178
179VideoFrameType VCMEncodedFrame::ConvertFrameType(webrtc::FrameType frame_type) {
180  switch (frame_type) {
181    case kVideoFrameKey:
182      return kKeyFrame;
183    case kVideoFrameDelta:
184      return kDeltaFrame;
185    default:
186      assert(false);
187      return kDeltaFrame;
188  }
189}
190
191void VCMEncodedFrame::ConvertFrameTypes(
192    const std::vector<webrtc::FrameType>& frame_types,
193    std::vector<VideoFrameType>* video_frame_types) {
194  assert(video_frame_types);
195  video_frame_types->reserve(frame_types.size());
196  for (size_t i = 0; i < frame_types.size(); ++i) {
197    (*video_frame_types)[i] = ConvertFrameType(frame_types[i]);
198  }
199}
200
201}
202