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/video_engine/test/libvietest/include/tb_I420_codec.h"
12
13 #include <assert.h>
14 #include <stdio.h>
15
16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
17
TbI420Encoder()18 TbI420Encoder::TbI420Encoder() :
19 _inited(false), _encodedImage(), _encodedCompleteCallback(NULL)
20 {
21 //
22 memset(&_functionCalls, 0, sizeof(_functionCalls));
23 }
24
~TbI420Encoder()25 TbI420Encoder::~TbI420Encoder()
26 {
27 _inited = false;
28 if (_encodedImage._buffer != NULL)
29 {
30 delete[] _encodedImage._buffer;
31 _encodedImage._buffer = NULL;
32 }
33 }
34
Release()35 int32_t TbI420Encoder::Release()
36 {
37 _functionCalls.Release++;
38 // should allocate an encoded frame and then release it here, for that we
39 // actaully need an init flag
40 if (_encodedImage._buffer != NULL)
41 {
42 delete[] _encodedImage._buffer;
43 _encodedImage._buffer = NULL;
44 }
45 _inited = false;
46 return WEBRTC_VIDEO_CODEC_OK;
47 }
48
SetChannelParameters(uint32_t packetLoss,int rtt)49 int32_t TbI420Encoder::SetChannelParameters(uint32_t packetLoss, int rtt) {
50 _functionCalls.SetChannelParameters++;
51 return WEBRTC_VIDEO_CODEC_OK;
52 }
53
InitEncode(const webrtc::VideoCodec * inst,int32_t,uint32_t)54 int32_t TbI420Encoder::InitEncode(const webrtc::VideoCodec* inst,
55 int32_t /*numberOfCores*/,
56 uint32_t /*maxPayloadSize */)
57 {
58 _functionCalls.InitEncode++;
59 if (inst == NULL)
60 {
61 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
62 }
63 if (inst->width < 1 || inst->height < 1)
64 {
65 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
66 }
67
68 // allocating encoded memory
69 if (_encodedImage._buffer != NULL)
70 {
71 delete[] _encodedImage._buffer;
72 _encodedImage._buffer = NULL;
73 _encodedImage._size = 0;
74 }
75 const uint32_t newSize = (3 * inst->width * inst->height) >> 1;
76 uint8_t* newBuffer = new uint8_t[newSize];
77 if (newBuffer == NULL)
78 {
79 return WEBRTC_VIDEO_CODEC_MEMORY;
80 }
81 _encodedImage._size = newSize;
82 _encodedImage._buffer = newBuffer;
83
84 // if no memeory allocation, no point to init
85 _inited = true;
86 return WEBRTC_VIDEO_CODEC_OK;
87 }
88
Encode(const webrtc::I420VideoFrame & inputImage,const webrtc::CodecSpecificInfo *,const std::vector<webrtc::VideoFrameType> *)89 int32_t TbI420Encoder::Encode(
90 const webrtc::I420VideoFrame& inputImage,
91 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/,
92 const std::vector<webrtc::VideoFrameType>* /*frameTypes*/)
93 {
94 _functionCalls.Encode++;
95 if (!_inited)
96 {
97 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
98 }
99 if (_encodedCompleteCallback == NULL)
100 {
101 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
102 }
103
104 _encodedImage._frameType = webrtc::kKeyFrame; // no coding
105 _encodedImage._timeStamp = inputImage.timestamp();
106 _encodedImage._encodedHeight = inputImage.height();
107 _encodedImage._encodedWidth = inputImage.width();
108 unsigned int reqSize = webrtc::CalcBufferSize(webrtc::kI420,
109 _encodedImage._encodedWidth,
110 _encodedImage._encodedHeight);
111 if (reqSize > _encodedImage._size)
112 {
113
114 // allocating encoded memory
115 if (_encodedImage._buffer != NULL)
116 {
117 delete[] _encodedImage._buffer;
118 _encodedImage._buffer = NULL;
119 _encodedImage._size = 0;
120 }
121 uint8_t* newBuffer = new uint8_t[reqSize];
122 if (newBuffer == NULL)
123 {
124 return WEBRTC_VIDEO_CODEC_MEMORY;
125 }
126 _encodedImage._size = reqSize;
127 _encodedImage._buffer = newBuffer;
128 }
129 if (ExtractBuffer(inputImage, _encodedImage._size,
130 _encodedImage._buffer) < 0) {
131 return -1;
132 }
133
134 _encodedImage._length = reqSize;
135 _encodedCompleteCallback->Encoded(_encodedImage);
136 return WEBRTC_VIDEO_CODEC_OK;
137 }
138
RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback * callback)139 int32_t TbI420Encoder::RegisterEncodeCompleteCallback(
140 webrtc::EncodedImageCallback* callback)
141 {
142 _functionCalls.RegisterEncodeCompleteCallback++;
143 _encodedCompleteCallback = callback;
144 return WEBRTC_VIDEO_CODEC_OK;
145 }
146
SetRates(uint32_t newBitRate,uint32_t frameRate)147 int32_t TbI420Encoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
148 {
149 _functionCalls.SetRates++;
150 return WEBRTC_VIDEO_CODEC_OK;
151 }
152
SetPeriodicKeyFrames(bool enable)153 int32_t TbI420Encoder::SetPeriodicKeyFrames(bool enable)
154 {
155 _functionCalls.SetPeriodicKeyFrames++;
156 return WEBRTC_VIDEO_CODEC_ERROR;
157 }
158
CodecConfigParameters(uint8_t *,int32_t)159 int32_t TbI420Encoder::CodecConfigParameters(uint8_t* /*buffer*/,
160 int32_t /*size*/)
161 {
162 _functionCalls.CodecConfigParameters++;
163 return WEBRTC_VIDEO_CODEC_ERROR;
164 }
GetFunctionCalls()165 TbI420Encoder::FunctionCalls TbI420Encoder::GetFunctionCalls()
166 {
167 return _functionCalls;
168 }
169
TbI420Decoder()170 TbI420Decoder::TbI420Decoder():
171 _decodedImage(), _width(0), _height(0), _inited(false),
172 _decodeCompleteCallback(NULL)
173 {
174 memset(&_functionCalls, 0, sizeof(_functionCalls));
175 }
176
~TbI420Decoder()177 TbI420Decoder::~TbI420Decoder()
178 {
179 Release();
180 }
181
Reset()182 int32_t TbI420Decoder::Reset()
183 {
184 _functionCalls.Reset++;
185 return WEBRTC_VIDEO_CODEC_OK;
186 }
187
InitDecode(const webrtc::VideoCodec * inst,int32_t)188 int32_t TbI420Decoder::InitDecode(const webrtc::VideoCodec* inst,
189 int32_t /*numberOfCores */)
190 {
191 _functionCalls.InitDecode++;
192 if (inst == NULL)
193 {
194 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
195 }
196 else if (inst->width < 1 || inst->height < 1)
197 {
198 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
199 }
200 _width = inst->width;
201 _height = inst->height;
202 int half_width = (_width + 1 ) / 2 ;
203 _decodedImage.CreateEmptyFrame(_width, _height,
204 _width, half_width, half_width);
205 _inited = true;
206 return WEBRTC_VIDEO_CODEC_OK;
207 }
208
Decode(const webrtc::EncodedImage & inputImage,bool,const webrtc::RTPFragmentationHeader *,const webrtc::CodecSpecificInfo *,int64_t)209 int32_t TbI420Decoder::Decode(
210 const webrtc::EncodedImage& inputImage,
211 bool /*missingFrames*/,
212 const webrtc::RTPFragmentationHeader* /*fragmentation*/,
213 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/,
214 int64_t /*renderTimeMs*/)
215 {
216 _functionCalls.Decode++;
217 if (inputImage._buffer == NULL)
218 {
219 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
220 }
221 if (_decodeCompleteCallback == NULL)
222 {
223 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
224 }
225 if (inputImage._length <= 0)
226 {
227 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
228 }
229 if (!_inited)
230 {
231 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
232 }
233
234 // Only send complete frames.
235 if (static_cast<int>(inputImage._length) !=
236 webrtc::CalcBufferSize(webrtc::kI420,_width,_height)) {
237 return WEBRTC_VIDEO_CODEC_ERROR;
238 }
239
240 int ret = ConvertToI420(webrtc::kI420, inputImage._buffer, 0, 0,
241 _width, _height,
242 0, webrtc::kRotateNone, &_decodedImage);
243
244 if (ret < 0)
245 return WEBRTC_VIDEO_CODEC_ERROR;
246
247 _decodedImage.set_timestamp(inputImage._timeStamp);
248
249 _decodeCompleteCallback->Decoded(_decodedImage);
250 return WEBRTC_VIDEO_CODEC_OK;
251 }
252
RegisterDecodeCompleteCallback(webrtc::DecodedImageCallback * callback)253 int32_t TbI420Decoder::RegisterDecodeCompleteCallback(
254 webrtc::DecodedImageCallback* callback)
255 {
256 _functionCalls.RegisterDecodeCompleteCallback++;
257 _decodeCompleteCallback = callback;
258 return WEBRTC_VIDEO_CODEC_OK;
259 }
260
Release()261 int32_t TbI420Decoder::Release()
262 {
263 _functionCalls.Release++;
264 _inited = false;
265 return WEBRTC_VIDEO_CODEC_OK;
266 }
267
GetFunctionCalls()268 TbI420Decoder::FunctionCalls TbI420Decoder::GetFunctionCalls()
269 {
270 return _functionCalls;
271 }
272