• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 #include "video_source_encoder.h"
17 #include "avsharedmemory.h"
18 #include "common/common_macro.h"
19 #include "media_errors.h"
20 #include "protocol/frame/h264_frame.h"
21 #include "sharing_log.h"
22 
23 namespace OHOS {
24 namespace Sharing {
25 
OnError(Media::AVCodecErrorType errorType,int32_t errorCode)26 void VideoSourceEncoder::VideoEncodeCallback::OnError(Media::AVCodecErrorType errorType, int32_t errorCode)
27 {
28     SHARING_LOGD("trace.");
29     if (auto parent = parent_.lock()) {
30         parent->OnError(errorType, errorCode);
31     }
32 }
33 
OnOutputFormatChanged(const Media::Format & format)34 void VideoSourceEncoder::VideoEncodeCallback::OnOutputFormatChanged(const Media::Format &format)
35 {
36     SHARING_LOGD("trace.");
37     if (auto parent = parent_.lock()) {
38         parent->OnOutputFormatChanged(format);
39     }
40 }
41 
OnInputBufferAvailable(uint32_t index)42 void VideoSourceEncoder::VideoEncodeCallback::OnInputBufferAvailable(uint32_t index)
43 {
44     SHARING_LOGD("trace.");
45     if (auto parent = parent_.lock()) {
46         parent->OnInputBufferAvailable(index);
47     }
48 }
49 
OnOutputBufferAvailable(uint32_t index,Media::AVCodecBufferInfo info,Media::AVCodecBufferFlag flag)50 void VideoSourceEncoder::VideoEncodeCallback::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info,
51                                                                       Media::AVCodecBufferFlag flag)
52 {
53     SHARING_LOGD("trace.");
54     if (auto parent = parent_.lock()) {
55         parent->OnOutputBufferAvailable(index, info, flag);
56     }
57 }
58 
~VideoSourceEncoder()59 VideoSourceEncoder::~VideoSourceEncoder()
60 {
61     SHARING_LOGD("trace.");
62     StopEncoder();
63     ReleaseEncoder();
64     encoderCb_ = nullptr;
65 }
66 
InitEncoder(const VideoSourceConfigure & configure)67 bool VideoSourceEncoder::InitEncoder(const VideoSourceConfigure &configure)
68 {
69     SHARING_LOGD("trace.");
70     if (!CreateEncoder(configure)) {
71         SHARING_LOGE("Create encoder failed!");
72         return false;
73     }
74 
75     if (!ConfigEncoder(configure)) {
76         SHARING_LOGE("Config encoder failed!");
77         ReleaseEncoder();
78         return false;
79     }
80 
81     videoEncoderSurface_ = videoEncoder_->CreateInputSurface();
82     if (videoEncoderSurface_ == nullptr) {
83         SHARING_LOGE("Create encoder surface failed!");
84         ReleaseEncoder();
85         return false;
86     }
87 
88     return true;
89 }
90 
CreateEncoder(const VideoSourceConfigure & configure)91 bool VideoSourceEncoder::CreateEncoder(const VideoSourceConfigure &configure)
92 {
93     SHARING_LOGD("trace.");
94     switch (configure.codecType_) {
95         case CodecId::CODEC_H264:
96             videoEncoder_ = OHOS::Media::VideoEncoderFactory::CreateByMime("video/avc");
97             break;
98         case CodecId::CODEC_H265:
99             videoEncoder_ = OHOS::Media::VideoEncoderFactory::CreateByMime("video/hevc");
100             break;
101         default:
102             SHARING_LOGE("Encoder codecType is invalid!");
103             videoEncoder_ = nullptr;
104     }
105     if (videoEncoder_ == nullptr) {
106         SHARING_LOGE("Create Video Source Encoder failed!");
107         return false;
108     }
109     encoderCb_ = std::make_shared<VideoEncodeCallback>(shared_from_this());
110     int32_t ret = videoEncoder_->SetCallback(encoderCb_);
111     if (ret != Media::MSERR_OK) {
112         SHARING_LOGE("Set encoder callback failed!");
113         ReleaseEncoder();
114         return false;
115     }
116 
117     return true;
118 }
119 
ConfigEncoder(const VideoSourceConfigure & configure)120 bool VideoSourceEncoder::ConfigEncoder(const VideoSourceConfigure &configure)
121 {
122     SHARING_LOGD("trace.");
123     if (videoEncoder_ == nullptr) {
124         SHARING_LOGE("Encoder is null!");
125         return false;
126     }
127     Media::Format videoFormat;
128     switch (configure.codecType_) {
129         case CodecId::CODEC_H264:
130             videoFormat.PutStringValue("codec_mime", "video/avc");
131             break;
132         case CodecId::CODEC_H265:
133             videoFormat.PutStringValue("codec_mime", "video/hevc");
134             break;
135         default:
136             SHARING_LOGE("Encoder codecType is invalid!");
137             return false;
138     }
139     videoFormat.PutIntValue("pixel_format", configure.pixleFormat_);
140     videoFormat.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
141     videoFormat.PutIntValue("width", configure.videoWidth_);
142     videoFormat.PutIntValue("height", configure.videoHeight_);
143     videoFormat.PutIntValue("frame_rate", configure.frameRate_);
144     videoFormat.PutIntValue("bitrate", SCREEN_CAPTURE_ENCODE_BITRATE);
145     int32_t ret = videoEncoder_->Configure(videoFormat);
146     if (ret != Media::MSERR_OK) {
147         SHARING_LOGE("Configure encoder failed!");
148         return false;
149     }
150 
151     return true;
152 }
153 
GetEncoderSurface()154 sptr<Surface> &VideoSourceEncoder::GetEncoderSurface()
155 {
156     SHARING_LOGD("trace.");
157     return videoEncoderSurface_;
158 }
159 
StartEncoder()160 bool VideoSourceEncoder::StartEncoder()
161 {
162     SHARING_LOGD("trace.");
163     if (videoEncoder_ == nullptr) {
164         SHARING_LOGE("Encoder is null!");
165         return false;
166     }
167 
168     int32_t ret = videoEncoder_->Prepare();
169     if (ret != Media::MSERR_OK) {
170         SHARING_LOGE("Prepare encoder failed!");
171         return false;
172     }
173 
174     ret = videoEncoder_->Start();
175     if (ret != Media::MSERR_OK) {
176         SHARING_LOGE("Start encoder failed!");
177         return false;
178     }
179 
180     return true;
181 }
182 
StopEncoder()183 bool VideoSourceEncoder::StopEncoder()
184 {
185     SHARING_LOGD("trace.");
186     if (videoEncoder_ == nullptr) {
187         SHARING_LOGE("Encoder is null!");
188         return false;
189     }
190 
191     int32_t ret = videoEncoder_->Flush();
192     if (ret != Media::MSERR_OK) {
193         SHARING_LOGE("Flush encoder failed!");
194     }
195 
196     ret = videoEncoder_->Stop();
197     if (ret != Media::MSERR_OK) {
198         SHARING_LOGE("Stop encoder failed!");
199         return false;
200     }
201 
202     return true;
203 }
204 
ReleaseEncoder()205 bool VideoSourceEncoder::ReleaseEncoder()
206 {
207     SHARING_LOGD("trace.");
208     if (videoEncoder_ == nullptr) {
209         SHARING_LOGE("encoder is null!");
210         return false;
211     }
212     int32_t ret = videoEncoder_->Release();
213     if (ret != Media::MSERR_OK) {
214         SHARING_LOGE("Release encoder failed.");
215         return false;
216     }
217     videoEncoder_ = nullptr;
218 
219     return true;
220 }
221 
OnOutputBufferAvailable(uint32_t index,Media::AVCodecBufferInfo info,Media::AVCodecBufferFlag flag)222 void VideoSourceEncoder::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info,
223                                                  Media::AVCodecBufferFlag flag)
224 {
225     SHARING_LOGI("index: %{public}u, size:%{public}u, pts: %{public}" PRIi64 ".", index, info.size,
226                  info.presentationTimeUs);
227     if (!videoEncoder_) {
228         SHARING_LOGE("encoder is null!");
229         return;
230     }
231 
232     auto videoSharedMemory = videoEncoder_->GetOutputBuffer(index);
233     if (videoSharedMemory == nullptr || videoSharedMemory->GetBase() == nullptr) {
234         SHARING_LOGE("Get output buffer null!");
235         return;
236     }
237     size_t dataSize = static_cast<size_t>(info.size);
238     if (dataSize == 0) {
239         SHARING_LOGE("params invalid, size: %{public}zu.", dataSize);
240         return;
241     }
242 
243     const char *data = reinterpret_cast<const char *>(videoSharedMemory->GetBase());
244     if (auto listener = listener_.lock()) {
245         SplitH264(data, dataSize, 0, [&](const char *buf, size_t len, size_t prefix) {
246             if ((*(buf + prefix) & 0x1f) == 0x07) {
247                 SHARING_LOGD("get sps, size:%{public}zu.", len);
248                 Frame::Ptr videoFrame = FrameImpl::Create();
249                 videoFrame->Assign(buf, len);
250                 listener->OnFrame(videoFrame, SPS_FRAME, false);
251                 videoFrame = nullptr;
252                 return;
253             }
254             if ((*(buf + prefix) & 0x1f) == 0x08) {
255                 SHARING_LOGD("get pps, size:%{public}zu.", len);
256                 Frame::Ptr videoFrame = FrameImpl::Create();
257                 videoFrame->Assign(buf, len);
258                 listener->OnFrame(videoFrame, PPS_FRAME, false);
259                 videoFrame = nullptr;
260                 return;
261             }
262             SHARING_LOGD("get frame , size:%{public}zu.", len);
263             bool keyFrame = (*(buf + prefix) & 0x1f) == 0x05 ? true : false;
264             Frame::Ptr videoFrame = FrameImpl::Create();
265             videoFrame->Assign(buf, len);
266             listener->OnFrame(videoFrame, IDR_FRAME, keyFrame);
267             videoFrame = nullptr;
268         });
269     } else {
270         SHARING_LOGE("listener_ is null, call OnFrame failed!");
271     }
272 
273     if (videoEncoder_->ReleaseOutputBuffer(index) != Media::MSERR_OK) {
274         SHARING_LOGW("release output buffer failed!");
275     }
276 }
277 
OnInputBufferAvailable(uint32_t index)278 void VideoSourceEncoder::OnInputBufferAvailable(uint32_t index)
279 {
280     SHARING_LOGI("index:%{public}u.", index);
281     if (auto listener = listener_.lock()) {
282         listener->OnFrameBufferUsed();
283     }
284 }
285 
OnOutputFormatChanged(const Media::Format & format)286 void VideoSourceEncoder::OnOutputFormatChanged(const Media::Format &format)
287 {
288     SHARING_LOGD("trace.");
289     (void)format;
290 }
291 
OnError(Media::AVCodecErrorType errorType,int32_t errorCode)292 void VideoSourceEncoder::OnError(Media::AVCodecErrorType errorType, int32_t errorCode)
293 {
294     SHARING_LOGD("Encoder error, errorType(%{public}d), errorCode(%{public}d)!", errorType, errorCode);
295 }
296 } // namespace Sharing
297 } // namespace OHOS
298