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,int64_t rtt)49 int32_t TbI420Encoder::SetChannelParameters(uint32_t packetLoss, int64_t rtt) {
50   _functionCalls.SetChannelParameters++;
51   return WEBRTC_VIDEO_CODEC_OK;
52 }
53 
InitEncode(const webrtc::VideoCodec * inst,int32_t,size_t)54 int32_t TbI420Encoder::InitEncode(const webrtc::VideoCodec* inst,
55                                   int32_t /*numberOfCores*/,
56                                   size_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     size_t 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, NULL, NULL);
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 (webrtc::CalcBufferSize(webrtc::kI420,_width,_height) !=
236         inputImage._length) {
237       return WEBRTC_VIDEO_CODEC_ERROR;
238     }
239 
240     int ret =
241         ConvertToI420(webrtc::kI420, inputImage._buffer, 0, 0, _width, _height,
242                       0, webrtc::kVideoRotation_0, &_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