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