1 /*
2 * Copyright (c) 2024 Huawei Device 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 "media_codec_encoder_adapter_impl.h"
17 #include "ohos_buffer_adapter_impl.h"
18 #include "buffer_info_adapter_impl.h"
19 #include "capability_data_adapter_impl.h"
20 #include "codec_format_adapter_impl.h"
21
22 #include <unordered_map>
23
24 #include "nweb_log.h"
25
26 namespace OHOS::NWeb {
27 namespace {
28 const std::unordered_map<OHOS::MediaAVCodec::AVCodecErrorType, ErrorType> ERROR_TYPE_MAP = {
29 { OHOS::MediaAVCodec::AVCodecErrorType::AVCODEC_ERROR_INTERNAL, ErrorType::CODEC_ERROR_INTERNAL },
30 { OHOS::MediaAVCodec::AVCodecErrorType::AVCODEC_ERROR_EXTEND_START, ErrorType::CODEC_ERROR_EXTEND_START }
31 };
32
33 const std::unordered_map<OHOS::MediaAVCodec::AVCodecBufferFlag, BufferFlag> BUFFER_FLAG_MAP = {
34 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE, BufferFlag::CODEC_BUFFER_FLAG_NONE },
35 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_EOS, BufferFlag::CODEC_BUFFER_FLAG_EOS },
36 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_SYNC_FRAME, BufferFlag::CODEC_BUFFER_FLAG_SYNC_FRAME },
37 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_PARTIAL_FRAME,
38 BufferFlag::CODEC_BUFFER_FLAG_PARTIAL_FRAME },
39 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_CODEC_DATA, BufferFlag::CODEC_BUFFER_FLAG_CODEC_DATA }
40 };
41
42 const std::unordered_map<BufferFlag, OHOS::MediaAVCodec::AVCodecBufferFlag> AV_BUFFER_FLAG_MAP = {
43 { BufferFlag::CODEC_BUFFER_FLAG_NONE, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE },
44 { BufferFlag::CODEC_BUFFER_FLAG_EOS, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_EOS },
45 { BufferFlag::CODEC_BUFFER_FLAG_SYNC_FRAME, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_SYNC_FRAME },
46 { BufferFlag::CODEC_BUFFER_FLAG_PARTIAL_FRAME,
47 OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_PARTIAL_FRAME },
48 { BufferFlag::CODEC_BUFFER_FLAG_CODEC_DATA, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_CODEC_DATA }
49 };
50 } // namespace
51
CreateVideoCodecByMime(const std::string mimetype)52 CodecCodeAdapter MediaCodecEncoderAdapterImpl::CreateVideoCodecByMime(const std::string mimetype)
53 {
54 encoder_ = VideoEncoderFactory::CreateByMime(mimetype);
55 if (encoder_ == nullptr) {
56 WVLOG_E("MediaCodecEncoder create by mime failed.");
57 return CodecCodeAdapter::ERROR;
58 }
59
60 return CodecCodeAdapter::OK;
61 }
62
CreateVideoCodecByName(const std::string name)63 CodecCodeAdapter MediaCodecEncoderAdapterImpl::CreateVideoCodecByName(const std::string name)
64 {
65 encoder_ = VideoEncoderFactory::CreateByName(name);
66 if (encoder_ == nullptr) {
67 WVLOG_E("MediaCodecEncoder create by name failed.");
68 return CodecCodeAdapter::ERROR;
69 }
70
71 return CodecCodeAdapter::OK;
72 }
73
SetCodecCallback(const std::shared_ptr<CodecCallbackAdapter> callback)74 CodecCodeAdapter MediaCodecEncoderAdapterImpl::SetCodecCallback(const std::shared_ptr<CodecCallbackAdapter> callback)
75 {
76 if (callback == nullptr) {
77 WVLOG_E("Media Callback is NULL.");
78 return CodecCodeAdapter::ERROR;
79 }
80
81 callback_ = std::make_shared<EncoderCallbackImpl>(callback);
82 if (callback_ == nullptr) {
83 WVLOG_E("create Callback failed.");
84 return CodecCodeAdapter::ERROR;
85 }
86
87 if (encoder_ == nullptr) {
88 WVLOG_E("MediaCodecEncoder is nullptr.");
89 return CodecCodeAdapter::ERROR;
90 }
91
92 int32_t ret = encoder_->SetCallback(callback_);
93 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
94 WVLOG_E("MediaCodecEncoder set callback failed.");
95 return CodecCodeAdapter::ERROR;
96 }
97 return CodecCodeAdapter::OK;
98 }
99
Configure(const std::shared_ptr<CodecConfigParaAdapter> config)100 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Configure(const std::shared_ptr<CodecConfigParaAdapter> config)
101 {
102 if (encoder_ == nullptr) {
103 WVLOG_E("MediaCodecEncoder is nullptr when ConfigureEncoder.");
104 return CodecCodeAdapter::ERROR;
105 }
106
107 if (config == nullptr) {
108 WVLOG_E("config is nullptr when ConfigureEncoder.");
109 return CodecCodeAdapter::ERROR;
110 }
111
112 OHOS::MediaAVCodec::Format avCodecFormat;
113
114 avCodecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, config->GetWidth());
115 avCodecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, config->GetHeight());
116 avCodecFormat.PutDoubleValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_FRAME_RATE, config->GetFrameRate());
117 avCodecFormat.PutLongValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_BITRATE, config->GetBitRate());
118 avCodecFormat.PutIntValue(
119 OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, VideoEncodeBitrateMode::CBR);
120 avCodecFormat.PutIntValue(
121 OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, (int32_t)VideoPixelFormat::YUVI420);
122 WVLOG_I("Configure width: %{public}d, height: %{public}d, bitRate: %{public}d, framerate: %{public}lf,",
123 config->GetWidth(), config->GetHeight(), (int32_t)config->GetBitRate(), config->GetFrameRate());
124 int32_t ret = encoder_->Configure(avCodecFormat);
125 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
126 WVLOG_E("encoder config error.");
127 return CodecCodeAdapter::ERROR;
128 }
129 return CodecCodeAdapter::OK;
130 }
131
Prepare()132 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Prepare()
133 {
134 if (encoder_ == nullptr) {
135 WVLOG_E("MediaCodecEncoder is nullptr when PrepareEncoder.");
136 return CodecCodeAdapter::ERROR;
137 }
138
139 int32_t ret = encoder_->Prepare();
140 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
141 WVLOG_E("encoder PrepareEncoder error.");
142 return CodecCodeAdapter::ERROR;
143 }
144 return CodecCodeAdapter::OK;
145 }
146
Start()147 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Start()
148 {
149 if (encoder_ == nullptr) {
150 WVLOG_E("MediaCodecEncoder is nullptr when StartEncoder.");
151 return CodecCodeAdapter::ERROR;
152 }
153
154 int32_t ret = encoder_->Start();
155 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
156 WVLOG_E("encoder Start error.");
157 return CodecCodeAdapter::ERROR;
158 }
159 return CodecCodeAdapter::OK;
160 }
161
Stop()162 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Stop()
163 {
164 if (encoder_ == nullptr) {
165 WVLOG_E("MediaCodecEncoder is nullptr when StopEncoder.");
166 return CodecCodeAdapter::ERROR;
167 }
168
169 int32_t ret = encoder_->Stop();
170 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
171 WVLOG_E("encoder Stop error.");
172 return CodecCodeAdapter::ERROR;
173 }
174 return CodecCodeAdapter::OK;
175 }
176
Reset()177 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Reset()
178 {
179 if (encoder_ == nullptr) {
180 WVLOG_E("MediaCodecEncoder is nullptr when ResetEncoder.");
181 return CodecCodeAdapter::ERROR;
182 }
183
184 int32_t ret = encoder_->Reset();
185 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
186 WVLOG_E("encoder Reset error.");
187 return CodecCodeAdapter::ERROR;
188 }
189 return CodecCodeAdapter::OK;
190 }
191
Release()192 CodecCodeAdapter MediaCodecEncoderAdapterImpl::Release()
193 {
194 if (encoder_ == nullptr) {
195 WVLOG_E("MediaCodecEncoder is nullptr when ReleaseEncoder.");
196 return CodecCodeAdapter::ERROR;
197 }
198
199 int32_t ret = encoder_->Release();
200 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
201 WVLOG_E("encoder Release error.");
202 return CodecCodeAdapter::ERROR;
203 }
204 return CodecCodeAdapter::OK;
205 }
206
CreateInputSurface()207 std::shared_ptr<ProducerSurfaceAdapter> MediaCodecEncoderAdapterImpl::CreateInputSurface()
208 {
209 if (encoder_ == nullptr) {
210 WVLOG_E("MediaCodecEncoder is nullptr when CreateInputSurface.");
211 return nullptr;
212 }
213
214 auto avCodecEncoderSurface = encoder_->CreateInputSurface();
215 if (avCodecEncoderSurface == nullptr) {
216 WVLOG_E("encoder create input surface error.");
217 return nullptr;
218 }
219
220 return std::make_shared<ProducerSurfaceAdapterImpl>(avCodecEncoderSurface);
221 }
222
ReleaseOutputBuffer(uint32_t index,bool isRender)223 CodecCodeAdapter MediaCodecEncoderAdapterImpl::ReleaseOutputBuffer(uint32_t index, bool isRender)
224 {
225 if (encoder_ == nullptr) {
226 WVLOG_E("MediaCodecEncoder is nullptr.");
227 return CodecCodeAdapter::ERROR;
228 }
229
230 int32_t ret = encoder_->ReleaseOutputBuffer(index);
231 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
232 WVLOG_E("release buffer failed.");
233 return CodecCodeAdapter::ERROR;
234 }
235 return CodecCodeAdapter::OK;
236 }
237
RequestKeyFrameSoon()238 CodecCodeAdapter MediaCodecEncoderAdapterImpl::RequestKeyFrameSoon()
239 {
240 if (encoder_ == nullptr) {
241 WVLOG_E("MediaCodecEncoder is nullptr when RequestKeyFrameSoon.");
242 return CodecCodeAdapter::ERROR;
243 }
244
245 OHOS::MediaAVCodec::Format avCodecFormat;
246 avCodecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, true);
247
248 int32_t ret = encoder_->SetParameter(avCodecFormat);
249 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
250 WVLOG_E("encoder SetParameter error.");
251 return CodecCodeAdapter::ERROR;
252 }
253 return CodecCodeAdapter::OK;
254 }
255
GetErrorType(AVCodecErrorType codecErrorType)256 ErrorType MediaCodecEncoderAdapterImpl::GetErrorType(AVCodecErrorType codecErrorType)
257 {
258 auto type = ERROR_TYPE_MAP.find(codecErrorType);
259 if (type == ERROR_TYPE_MAP.end()) {
260 WVLOG_E("error type not found.");
261 return ErrorType::CODEC_ERROR_INTERNAL;
262 }
263 return type->second;
264 }
265
GetBufferFlag(AVCodecBufferFlag codecBufferFlag)266 BufferFlag MediaCodecEncoderAdapterImpl::GetBufferFlag(AVCodecBufferFlag codecBufferFlag)
267 {
268 auto flag = BUFFER_FLAG_MAP.find(codecBufferFlag);
269 if (flag == BUFFER_FLAG_MAP.end()) {
270 WVLOG_E("buffer flag not found.");
271 return BufferFlag::CODEC_BUFFER_FLAG_NONE;
272 }
273 return flag->second;
274 }
275
EncoderCallbackImpl(std::shared_ptr<CodecCallbackAdapter> cb)276 EncoderCallbackImpl::EncoderCallbackImpl(std::shared_ptr<CodecCallbackAdapter> cb) : cb_(cb) {};
277
OnError(AVCodecErrorType errorType,int32_t errorCode)278 void EncoderCallbackImpl::OnError(AVCodecErrorType errorType, int32_t errorCode)
279 {
280 if (!cb_) {
281 WVLOG_E("callback is null.");
282 return;
283 }
284
285 ErrorType errType = MediaCodecEncoderAdapterImpl::GetErrorType(errorType);
286
287 cb_->OnError(errType, errorCode);
288 }
289
OnOutputFormatChanged(const Format & format)290 void EncoderCallbackImpl::OnOutputFormatChanged(const Format& format)
291 {
292 if (!cb_) {
293 WVLOG_E("callback is null.");
294 return;
295 }
296
297 std::shared_ptr<CodecFormatAdapterImpl> formatAdapter = std::make_shared<CodecFormatAdapterImpl>();
298 if (!formatAdapter) {
299 WVLOG_E("formatAdapter is null");
300 return;
301 }
302
303 int32_t width = 0;
304 int32_t height = 0;
305 format.GetIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, width);
306 format.GetIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, height);
307 formatAdapter->SetWidth(width);
308 formatAdapter->SetHeight(height);
309 cb_->OnStreamChanged(formatAdapter);
310 }
311
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)312 void EncoderCallbackImpl::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
313 {
314 if (!cb_) {
315 WVLOG_E("callback is null.");
316 return;
317 }
318
319 if (buffer == nullptr || buffer->GetBase() == nullptr) {
320 WVLOG_E("callback input buffer is null");
321 return;
322 }
323
324 std::shared_ptr<OhosBufferAdapterImpl> ohosBuffer = std::make_shared<OhosBufferAdapterImpl>();
325 if (!ohosBuffer) {
326 WVLOG_E("new OhosBufferAdapterImpl failed");
327 return;
328 }
329
330 ohosBuffer->SetAddr(buffer->GetBase());
331 ohosBuffer->SetBufferSize(buffer->GetSize());
332 cb_->OnNeedInputData(index, ohosBuffer);
333 }
334
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)335 void EncoderCallbackImpl::OnOutputBufferAvailable(
336 uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
337 {
338 if (!cb_) {
339 WVLOG_E("callback is null.");
340 return;
341 }
342
343 if (buffer == nullptr || buffer->GetBase() == nullptr) {
344 WVLOG_E("callback output buffer is null");
345 return;
346 }
347
348 std::shared_ptr<BufferInfoAdapterImpl> bufferInfo = std::make_shared<BufferInfoAdapterImpl>();
349 if (bufferInfo == nullptr) {
350 WVLOG_E("new bufferInfoAdapterImpl failed");
351 return;
352 }
353
354 std::shared_ptr<OhosBufferAdapterImpl> ohosBuffer = std::make_shared<OhosBufferAdapterImpl>();
355 if (ohosBuffer == nullptr) {
356 WVLOG_E("new OhosBufferAdapterImpl failed");
357 return;
358 }
359
360 bufferInfo->SetPresentationTimeUs(info.presentationTimeUs);
361 bufferInfo->SetSize(info.size);
362 bufferInfo->SetOffset(info.offset);
363
364 BufferFlag flagAdapter = MediaCodecEncoderAdapterImpl::GetBufferFlag(flag);
365
366 ohosBuffer->SetAddr(buffer->GetBase());
367 ohosBuffer->SetBufferSize(info.size);
368 cb_->OnNeedOutputData(index, bufferInfo, flagAdapter, ohosBuffer);
369 }
370 } // namespace OHOS::NWeb
371