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 "avcodec_errors.h"
18 #include "buffer/avsharedmemory.h"
19 #include "common/common_macro.h"
20 #include "protocol/frame/h264_frame.h"
21 #include "sharing_log.h"
22
23 namespace OHOS {
24 namespace Sharing {
25
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)26 void VideoSourceEncoder::VideoEncodeCallback::OnError(MediaAVCodec::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 MediaAVCodec::Format & format)34 void VideoSourceEncoder::VideoEncodeCallback::OnOutputFormatChanged(const MediaAVCodec::Format &format)
35 {
36 SHARING_LOGD("trace.");
37 if (auto parent = parent_.lock()) {
38 parent->OnOutputFormatChanged(format);
39 }
40 }
41
OnInputBufferAvailable(uint32_t index,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)42 void VideoSourceEncoder::VideoEncodeCallback::OnInputBufferAvailable(
43 uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
44 {
45 SHARING_LOGD("trace.");
46 if (auto parent = parent_.lock()) {
47 parent->OnInputBufferAvailable(index, buffer);
48 }
49 }
50
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)51 void VideoSourceEncoder::VideoEncodeCallback::OnOutputBufferAvailable(
52 uint32_t index, MediaAVCodec::AVCodecBufferInfo info, MediaAVCodec::AVCodecBufferFlag flag,
53 std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
54 {
55 SHARING_LOGD("trace.");
56 if (auto parent = parent_.lock()) {
57 parent->OnOutputBufferAvailable(index, info, flag, buffer);
58 }
59 }
60
~VideoSourceEncoder()61 VideoSourceEncoder::~VideoSourceEncoder()
62 {
63 SHARING_LOGD("trace.");
64 StopEncoder();
65 ReleaseEncoder();
66 encoderCb_ = nullptr;
67 }
68
InitEncoder(const VideoSourceConfigure & configure)69 bool VideoSourceEncoder::InitEncoder(const VideoSourceConfigure &configure)
70 {
71 SHARING_LOGD("trace.");
72 if (!CreateEncoder(configure)) {
73 SHARING_LOGE("Create encoder failed!");
74 return false;
75 }
76
77 if (!ConfigEncoder(configure)) {
78 SHARING_LOGE("Config encoder failed!");
79 ReleaseEncoder();
80 return false;
81 }
82
83 videoEncoderSurface_ = videoEncoder_->CreateInputSurface();
84 if (videoEncoderSurface_ == nullptr) {
85 SHARING_LOGE("Create encoder surface failed!");
86 ReleaseEncoder();
87 return false;
88 }
89
90 return true;
91 }
92
CreateEncoder(const VideoSourceConfigure & configure)93 bool VideoSourceEncoder::CreateEncoder(const VideoSourceConfigure &configure)
94 {
95 SHARING_LOGD("trace.");
96 switch (configure.codecType_) {
97 case CodecId::CODEC_H264:
98 videoEncoder_ = OHOS::MediaAVCodec::VideoEncoderFactory::CreateByMime("video/avc");
99 break;
100 case CodecId::CODEC_H265:
101 videoEncoder_ = OHOS::MediaAVCodec::VideoEncoderFactory::CreateByMime("video/hevc");
102 break;
103 default:
104 SHARING_LOGE("Encoder codecType is invalid!");
105 videoEncoder_ = nullptr;
106 }
107 if (videoEncoder_ == nullptr) {
108 SHARING_LOGE("Create Video Source Encoder failed!");
109 return false;
110 }
111 encoderCb_ = std::make_shared<VideoEncodeCallback>(shared_from_this());
112 int32_t ret = videoEncoder_->SetCallback(encoderCb_);
113 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
114 SHARING_LOGE("Set encoder callback failed!");
115 ReleaseEncoder();
116 return false;
117 }
118
119 return true;
120 }
121
ConfigEncoder(const VideoSourceConfigure & configure)122 bool VideoSourceEncoder::ConfigEncoder(const VideoSourceConfigure &configure)
123 {
124 SHARING_LOGD("trace.");
125 if (videoEncoder_ == nullptr) {
126 SHARING_LOGE("Encoder is null!");
127 return false;
128 }
129 MediaAVCodec::Format videoFormat;
130 switch (configure.codecType_) {
131 case CodecId::CODEC_H264:
132 videoFormat.PutStringValue("codec_mime", "video/avc");
133 break;
134 case CodecId::CODEC_H265:
135 videoFormat.PutStringValue("codec_mime", "video/hevc");
136 break;
137 default:
138 SHARING_LOGE("Encoder codecType is invalid!");
139 return false;
140 }
141 videoFormat.PutIntValue("pixel_format", configure.pixleFormat_);
142 videoFormat.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
143 videoFormat.PutIntValue("width", configure.videoWidth_);
144 videoFormat.PutIntValue("height", configure.videoHeight_);
145 videoFormat.PutIntValue("frame_rate", configure.frameRate_);
146 videoFormat.PutIntValue("bitrate", SCREEN_CAPTURE_ENCODE_BITRATE);
147 int32_t ret = videoEncoder_->Configure(videoFormat);
148 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
149 SHARING_LOGE("Configure encoder failed!");
150 return false;
151 }
152
153 return true;
154 }
155
GetEncoderSurface()156 sptr<Surface> &VideoSourceEncoder::GetEncoderSurface()
157 {
158 SHARING_LOGD("trace.");
159 return videoEncoderSurface_;
160 }
161
StartEncoder()162 bool VideoSourceEncoder::StartEncoder()
163 {
164 SHARING_LOGD("trace.");
165 if (videoEncoder_ == nullptr) {
166 SHARING_LOGE("Encoder is null!");
167 return false;
168 }
169
170 int32_t ret = videoEncoder_->Prepare();
171 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
172 SHARING_LOGE("Prepare encoder failed!");
173 return false;
174 }
175
176 ret = videoEncoder_->Start();
177 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
178 SHARING_LOGE("Start encoder failed!");
179 return false;
180 }
181
182 return true;
183 }
184
StopEncoder()185 bool VideoSourceEncoder::StopEncoder()
186 {
187 SHARING_LOGD("trace.");
188 if (videoEncoder_ == nullptr) {
189 SHARING_LOGE("Encoder is null!");
190 return false;
191 }
192
193 int32_t ret = videoEncoder_->Flush();
194 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
195 SHARING_LOGE("Flush encoder failed!");
196 }
197
198 ret = videoEncoder_->Stop();
199 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
200 SHARING_LOGE("Stop encoder failed!");
201 return false;
202 }
203
204 return true;
205 }
206
ReleaseEncoder()207 bool VideoSourceEncoder::ReleaseEncoder()
208 {
209 SHARING_LOGD("trace.");
210 if (videoEncoder_ == nullptr) {
211 SHARING_LOGE("encoder is null!");
212 return false;
213 }
214 int32_t ret = videoEncoder_->Release();
215 if (ret != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
216 SHARING_LOGE("Release encoder failed.");
217 return false;
218 }
219 videoEncoder_ = nullptr;
220
221 return true;
222 }
223
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)224 void VideoSourceEncoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
225 MediaAVCodec::AVCodecBufferFlag flag,
226 std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
227 {
228 SHARING_LOGI("index: %{public}u, size:%{public}u, pts: %{public}" PRIi64 ".", index, info.size,
229 info.presentationTimeUs);
230 if (!videoEncoder_) {
231 SHARING_LOGE("encoder is null!");
232 return;
233 }
234
235 if (buffer == nullptr || buffer->GetBase() == nullptr) {
236 SHARING_LOGE("Get output buffer null!");
237 return;
238 }
239 size_t dataSize = static_cast<size_t>(info.size);
240 if (dataSize == 0) {
241 SHARING_LOGE("params invalid, size: %{public}zu.", dataSize);
242 return;
243 }
244
245 const char *data = reinterpret_cast<const char *>(buffer->GetBase());
246 RETURN_IF_NULL(data);
247 if (auto listener = listener_.lock()) {
248 SplitH264(data, dataSize, 0, [&](const char *buf, size_t len, size_t prefix) {
249 if ((*(buf + prefix) & 0x1f) == 0x07) {
250 SHARING_LOGD("get sps, size:%{public}zu.", len);
251 Frame::Ptr videoFrame = FrameImpl::Create();
252 RETURN_IF_NULL(videoFrame);
253 videoFrame->Assign(buf, len);
254 listener->OnFrame(videoFrame, SPS_FRAME, false);
255 videoFrame = nullptr;
256 return;
257 }
258 if ((*(buf + prefix) & 0x1f) == 0x08) {
259 SHARING_LOGD("get pps, size:%{public}zu.", len);
260 Frame::Ptr videoFrame = FrameImpl::Create();
261 RETURN_IF_NULL(videoFrame);
262 videoFrame->Assign(buf, len);
263 listener->OnFrame(videoFrame, PPS_FRAME, false);
264 videoFrame = nullptr;
265 return;
266 }
267 SHARING_LOGD("get frame , size:%{public}zu.", len);
268 bool keyFrame = (*(buf + prefix) & 0x1f) == 0x05 ? true : false;
269 Frame::Ptr videoFrame = FrameImpl::Create();
270 RETURN_IF_NULL(videoFrame);
271 videoFrame->Assign(buf, len);
272 listener->OnFrame(videoFrame, IDR_FRAME, keyFrame);
273 videoFrame = nullptr;
274 });
275 } else {
276 SHARING_LOGE("listener_ is null, call OnFrame failed!");
277 }
278
279 if (videoEncoder_->ReleaseOutputBuffer(index) != MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
280 SHARING_LOGW("release output buffer failed!");
281 }
282 }
283
OnInputBufferAvailable(uint32_t index,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)284 void VideoSourceEncoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
285 {
286 SHARING_LOGI("index:%{public}u.", index);
287 if (auto listener = listener_.lock()) {
288 listener->OnFrameBufferUsed();
289 }
290 }
291
OnOutputFormatChanged(const MediaAVCodec::Format & format)292 void VideoSourceEncoder::OnOutputFormatChanged(const MediaAVCodec::Format &format)
293 {
294 SHARING_LOGD("trace.");
295 (void)format;
296 }
297
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)298 void VideoSourceEncoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
299 {
300 SHARING_LOGD("Encoder error, errorType(%{public}d), errorCode(%{public}d)!", errorType, errorCode);
301 }
302 } // namespace Sharing
303 } // namespace OHOS
304