• 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 "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