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