• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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