Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / main / source / generic_encoder.cc
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/engine_configurations.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/media_optimization.h"
15 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
16 #include "webrtc/system_wrappers/interface/logging.h"
17
18 namespace webrtc {
19 namespace {
20 // Map information from info into rtp. If no relevant information is found
21 // in info, rtp is set to NULL.
22 void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) {
23   if (!info) {
24     *rtp = NULL;
25     return;
26   }
27   switch (info->codecType) {
28     case kVideoCodecVP8: {
29       (*rtp)->codec = kRtpVideoVp8;
30       (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8();
31       (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
32       (*rtp)->codecHeader.VP8.nonReference =
33           info->codecSpecific.VP8.nonReference;
34       (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
35       (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
36       (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
37       (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
38       (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
39       return;
40     }
41     case kVideoCodecGeneric:
42       (*rtp)->codec = kRtpVideoGeneric;
43       (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
44       return;
45     default:
46       // No codec specific info. Change RTP header pointer to NULL.
47       *rtp = NULL;
48       return;
49   }
50 }
51 }  // namespace
52
53 //#define DEBUG_ENCODER_BIT_STREAM
54
55 VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
56 :
57 _encoder(encoder),
58 _codecType(kVideoCodecUnknown),
59 _VCMencodedFrameCallback(NULL),
60 _bitRate(0),
61 _frameRate(0),
62 _internalSource(internalSource)
63 {
64 }
65
66
67 VCMGenericEncoder::~VCMGenericEncoder()
68 {
69 }
70
71 int32_t VCMGenericEncoder::Release()
72 {
73     _bitRate = 0;
74     _frameRate = 0;
75     _VCMencodedFrameCallback = NULL;
76     return _encoder.Release();
77 }
78
79 int32_t
80 VCMGenericEncoder::InitEncode(const VideoCodec* settings,
81                               int32_t numberOfCores,
82                               uint32_t maxPayloadSize)
83 {
84     _bitRate = settings->startBitrate * 1000;
85     _frameRate = settings->maxFramerate;
86     _codecType = settings->codecType;
87     if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
88       LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
89                        "payload name: " << settings->plName;
90       return -1;
91     }
92     return 0;
93 }
94
95 int32_t
96 VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame,
97                           const CodecSpecificInfo* codecSpecificInfo,
98                           const std::vector<FrameType>& frameTypes) {
99   std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
100                                                 kDeltaFrame);
101   VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
102   return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
103 }
104
105 int32_t
106 VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int rtt)
107 {
108     return _encoder.SetChannelParameters(packetLoss, rtt);
109 }
110
111 int32_t
112 VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
113 {
114     uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
115     int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
116     if (ret < 0)
117     {
118         return ret;
119     }
120     _bitRate = newBitRate;
121     _frameRate = frameRate;
122     return VCM_OK;
123 }
124
125 int32_t
126 VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
127 {
128     int32_t ret = _encoder.CodecConfigParameters(buffer, size);
129     if (ret < 0)
130     {
131         return ret;
132     }
133     return ret;
134 }
135
136 uint32_t VCMGenericEncoder::BitRate() const
137 {
138     return _bitRate;
139 }
140
141 uint32_t VCMGenericEncoder::FrameRate() const
142 {
143     return _frameRate;
144 }
145
146 int32_t
147 VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
148 {
149     return _encoder.SetPeriodicKeyFrames(enable);
150 }
151
152 int32_t VCMGenericEncoder::RequestFrame(
153     const std::vector<FrameType>& frame_types) {
154   I420VideoFrame image;
155   std::vector<VideoFrameType> video_frame_types(frame_types.size(),
156                                                 kDeltaFrame);
157   VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
158   return _encoder.Encode(image, NULL, &video_frame_types);
159 }
160
161 int32_t
162 VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback)
163 {
164    _VCMencodedFrameCallback = VCMencodedFrameCallback;
165    _VCMencodedFrameCallback->SetInternalSource(_internalSource);
166    return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
167 }
168
169 bool
170 VCMGenericEncoder::InternalSource() const
171 {
172     return _internalSource;
173 }
174
175  /***************************
176   * Callback Implementation
177   ***************************/
178 VCMEncodedFrameCallback::VCMEncodedFrameCallback(
179     EncodedImageCallback* post_encode_callback):
180 _sendCallback(),
181 _mediaOpt(NULL),
182 _payloadType(0),
183 _internalSource(false),
184 post_encode_callback_(post_encode_callback)
185 #ifdef DEBUG_ENCODER_BIT_STREAM
186 , _bitStreamAfterEncoder(NULL)
187 #endif
188 {
189 #ifdef DEBUG_ENCODER_BIT_STREAM
190     _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb");
191 #endif
192 }
193
194 VCMEncodedFrameCallback::~VCMEncodedFrameCallback()
195 {
196 #ifdef DEBUG_ENCODER_BIT_STREAM
197     fclose(_bitStreamAfterEncoder);
198 #endif
199 }
200
201 int32_t
202 VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
203 {
204     _sendCallback = transport;
205     return VCM_OK;
206 }
207
208 int32_t
209 VCMEncodedFrameCallback::Encoded(
210     EncodedImage &encodedImage,
211     const CodecSpecificInfo* codecSpecificInfo,
212     const RTPFragmentationHeader* fragmentationHeader)
213 {
214     post_encode_callback_->Encoded(encodedImage);
215
216     FrameType frameType = VCMEncodedFrame::ConvertFrameType(encodedImage._frameType);
217
218     uint32_t encodedBytes = 0;
219     if (_sendCallback != NULL)
220     {
221         encodedBytes = encodedImage._length;
222
223 #ifdef DEBUG_ENCODER_BIT_STREAM
224         if (_bitStreamAfterEncoder != NULL)
225         {
226             fwrite(encodedImage._buffer, 1, encodedImage._length, _bitStreamAfterEncoder);
227         }
228 #endif
229
230         RTPVideoHeader rtpVideoHeader;
231         RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader;
232         CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);
233
234         int32_t callbackReturn = _sendCallback->SendData(
235             frameType,
236             _payloadType,
237             encodedImage._timeStamp,
238             encodedImage.capture_time_ms_,
239             encodedImage._buffer,
240             encodedBytes,
241             *fragmentationHeader,
242             rtpVideoHeaderPtr);
243        if (callbackReturn < 0)
244        {
245            return callbackReturn;
246        }
247     }
248     else
249     {
250         return VCM_UNINITIALIZED;
251     }
252     if (_mediaOpt != NULL) {
253       _mediaOpt->UpdateWithEncodedData(encodedBytes, encodedImage._timeStamp,
254                                        frameType);
255       if (_internalSource)
256       {
257           return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame
258       }
259     }
260     return VCM_OK;
261 }
262
263 void
264 VCMEncodedFrameCallback::SetMediaOpt(
265     media_optimization::MediaOptimization *mediaOpt)
266 {
267     _mediaOpt = mediaOpt;
268 }
269
270 }  // namespace webrtc