1 /*
2 * Copyright (C) 2023 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 "tester_capi.h"
17 #include "common/native_mfmagic.h"
18 #include "hcodec_log.h"
19 #include "native_avcodec_videodecoder.h"
20 #include "native_avcodec_videoencoder.h"
21 #include "native_window.h"
22
23 namespace OHOS::MediaAVCodec {
24 using namespace std;
25
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)26 void TesterCapi::OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
27 {
28 TLOGI(">>");
29 }
30
OnStreamChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)31 void TesterCapi::OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
32 {
33 TLOGI(">>");
34 }
35
OnNeedInputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)36 void TesterCapiOld::OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
37 {
38 TesterCapiOld* tester = static_cast<TesterCapiOld*>(userData);
39 if (tester == nullptr) {
40 return;
41 }
42 lock_guard<mutex> lk(tester->inputMtx_);
43 tester->inputList_.emplace_back(index, data);
44 tester->inputCond_.notify_all();
45 }
46
OnNewOutputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)47 void TesterCapiOld::OnNewOutputData(
48 OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr, void *userData)
49 {
50 TesterCapiOld* tester = static_cast<TesterCapiOld*>(userData);
51 if (tester == nullptr || attr == nullptr) {
52 return;
53 }
54 tester->AfterGotOutput(*attr);
55 lock_guard<mutex> lk(tester->outputMtx_);
56 tester->outputList_.emplace_back(index, data, *attr);
57 tester->outputCond_.notify_all();
58 }
59
OnNeedInputBuffer(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)60 void TesterCapiNew::OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
61 {
62 TesterCapiNew* tester = static_cast<TesterCapiNew*>(userData);
63 if (tester == nullptr) {
64 return;
65 }
66 lock_guard<mutex> lk(tester->inputMtx_);
67 tester->inputList_.emplace_back(index, buffer);
68 tester->inputCond_.notify_all();
69 }
70
OnNewOutputBuffer(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)71 void TesterCapiNew::OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
72 {
73 TesterCapiNew* tester = static_cast<TesterCapiNew*>(userData);
74 if (tester == nullptr) {
75 return;
76 }
77 OH_AVCodecBufferAttr attr;
78 OH_AVBuffer_GetBufferAttr(buffer, &attr);
79 tester->AfterGotOutput(attr);
80 lock_guard<mutex> lk(tester->outputMtx_);
81 tester->outputList_.emplace_back(index, buffer);
82 tester->outputCond_.notify_all();
83 }
84
Create()85 bool TesterCapi::Create()
86 {
87 string mime = GetCodecMime(opt_.protocol);
88 auto begin = std::chrono::steady_clock::now();
89 codec_ = opt_.isEncoder ? OH_VideoEncoder_CreateByMime(mime.c_str()) : OH_VideoDecoder_CreateByMime(mime.c_str());
90 if (codec_ == nullptr) {
91 TLOGE("Create failed");
92 return false;
93 }
94 CostRecorder::Instance().Update(begin,
95 opt_.isEncoder ? "OH_VideoEncoder_CreateByMime" : "OH_VideoDecoder_CreateByMime");
96 return true;
97 }
98
SetCallback()99 bool TesterCapiOld::SetCallback()
100 {
101 OH_AVCodecAsyncCallback cb {
102 &TesterCapi::OnError,
103 &TesterCapi::OnStreamChanged,
104 &TesterCapiOld::OnNeedInputData,
105 &TesterCapiOld::OnNewOutputData,
106 };
107 auto begin = std::chrono::steady_clock::now();
108 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_SetCallback(codec_, cb, this) :
109 OH_VideoDecoder_SetCallback(codec_, cb, this);
110 if (ret != AV_ERR_OK) {
111 TLOGE("SetCallback failed");
112 return false;
113 }
114 CostRecorder::Instance().Update(begin,
115 opt_.isEncoder ? "OH_VideoEncoder_SetCallback" : "OH_VideoDecoder_SetCallback");
116 return true;
117 }
118
SetCallback()119 bool TesterCapiNew::SetCallback()
120 {
121 auto begin = std::chrono::steady_clock::now();
122 OH_AVCodecCallback cb {
123 &TesterCapi::OnError,
124 &TesterCapi::OnStreamChanged,
125 &TesterCapiNew::OnNeedInputBuffer,
126 &TesterCapiNew::OnNewOutputBuffer,
127 };
128 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_RegisterCallback(codec_, cb, this) :
129 OH_VideoDecoder_RegisterCallback(codec_, cb, this);
130 if (ret != AV_ERR_OK) {
131 TLOGE("RegisterCallback failed");
132 return false;
133 }
134 CostRecorder::Instance().Update(begin,
135 opt_.isEncoder ? "OH_VideoEncoder_RegisterCallback" : "OH_VideoDecoder_RegisterCallback");
136 return true;
137 }
138
Start()139 bool TesterCapi::Start()
140 {
141 auto begin = std::chrono::steady_clock::now();
142 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_Start(codec_) :
143 OH_VideoDecoder_Start(codec_);
144 if (ret != AV_ERR_OK) {
145 TLOGE("Start failed");
146 return false;
147 }
148 CostRecorder::Instance().Update(begin,
149 opt_.isEncoder ? "OH_VideoEncoder_Start" : "OH_VideoDecoder_Start");
150 return true;
151 }
152
Stop()153 bool TesterCapi::Stop()
154 {
155 auto begin = std::chrono::steady_clock::now();
156 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_Stop(codec_) :
157 OH_VideoDecoder_Stop(codec_);
158 if (ret != AV_ERR_OK) {
159 TLOGE("Stop failed");
160 return false;
161 }
162 CostRecorder::Instance().Update(begin,
163 opt_.isEncoder ? "OH_VideoEncoder_Stop" : "OH_VideoDecoder_Stop");
164 return true;
165 }
166
Release()167 bool TesterCapi::Release()
168 {
169 auto begin = std::chrono::steady_clock::now();
170 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_Destroy(codec_) :
171 OH_VideoDecoder_Destroy(codec_);
172 if (ret != AV_ERR_OK) {
173 TLOGE("Destroy failed");
174 return false;
175 }
176 CostRecorder::Instance().Update(begin,
177 opt_.isEncoder ? "OH_VideoEncoder_Destroy" : "OH_VideoDecoder_Destroy");
178 return true;
179 }
180
Flush()181 bool TesterCapi::Flush()
182 {
183 auto begin = std::chrono::steady_clock::now();
184 OH_AVErrCode ret = opt_.isEncoder ? OH_VideoEncoder_Flush(codec_) :
185 OH_VideoDecoder_Flush(codec_);
186 if (ret != AV_ERR_OK) {
187 TLOGE("Flush failed");
188 return false;
189 }
190 CostRecorder::Instance().Update(begin,
191 opt_.isEncoder ? "OH_VideoEncoder_Flush" : "OH_VideoDecoder_Flush");
192 return true;
193 }
194
ClearAllBuffer()195 void TesterCapiOld::ClearAllBuffer()
196 {
197 {
198 lock_guard<mutex> lk(inputMtx_);
199 inputList_.clear();
200 }
201 {
202 lock_guard<mutex> lk(outputMtx_);
203 outputList_.clear();
204 }
205 }
206
ClearAllBuffer()207 void TesterCapiNew::ClearAllBuffer()
208 {
209 {
210 lock_guard<mutex> lk(inputMtx_);
211 inputList_.clear();
212 }
213 {
214 lock_guard<mutex> lk(outputMtx_);
215 outputList_.clear();
216 }
217 }
218
ConfigureEncoder()219 bool TesterCapi::ConfigureEncoder()
220 {
221 auto fmt = shared_ptr<OH_AVFormat>(OH_AVFormat_Create(), OH_AVFormat_Destroy);
222 IF_TRUE_RETURN_VAL_WITH_MSG(fmt == nullptr, false, "OH_AVFormat_Create failed");
223 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_WIDTH, opt_.dispW);
224 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_HEIGHT, opt_.dispH);
225 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(opt_.pixFmt));
226 OH_AVFormat_SetDoubleValue(fmt.get(), OH_MD_KEY_FRAME_RATE, opt_.frameRate);
227 if (opt_.rangeFlag.has_value()) {
228 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_RANGE_FLAG, opt_.rangeFlag.value());
229 }
230 if (opt_.primary.has_value()) {
231 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_COLOR_PRIMARIES, opt_.primary.value());
232 }
233 if (opt_.transfer.has_value()) {
234 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_TRANSFER_CHARACTERISTICS, opt_.transfer.value());
235 }
236 if (opt_.matrix.has_value()) {
237 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_MATRIX_COEFFICIENTS, opt_.matrix.value());
238 }
239 if (opt_.iFrameInterval.has_value()) {
240 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_I_FRAME_INTERVAL, opt_.iFrameInterval.value());
241 }
242 if (opt_.profile.has_value()) {
243 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_PROFILE, opt_.profile.value());
244 }
245 if (opt_.rateMode.has_value()) {
246 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, opt_.rateMode.value());
247 }
248 if (opt_.bitRate.has_value()) {
249 OH_AVFormat_SetLongValue(fmt.get(), OH_MD_KEY_BITRATE, opt_.bitRate.value());
250 }
251 if (opt_.quality.has_value()) {
252 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_QUALITY, opt_.quality.value());
253 }
254
255 auto begin = std::chrono::steady_clock::now();
256 OH_AVErrCode ret = OH_VideoEncoder_Configure(codec_, fmt.get());
257 if (ret != AV_ERR_OK) {
258 TLOGE("ConfigureEncoder failed");
259 return false;
260 }
261 CostRecorder::Instance().Update(begin, "OH_VideoEncoder_Configure");
262 return true;
263 }
264
CreateInputSurface()265 sptr<Surface> TesterCapi::CreateInputSurface()
266 {
267 OHNativeWindow *window = nullptr;
268 auto begin = std::chrono::steady_clock::now();
269 OH_AVErrCode ret = OH_VideoEncoder_GetSurface(codec_, &window);
270 if (ret != AV_ERR_OK || window == nullptr) {
271 TLOGE("CreateInputSurface failed");
272 return nullptr;
273 }
274 sptr<Surface> surface = window->surface;
275 if (surface == nullptr) {
276 TLOGE("surface in OHNativeWindow is null");
277 return nullptr;
278 }
279 CostRecorder::Instance().Update(begin, "OH_VideoEncoder_GetSurface");
280 // if we dont decrease here, the OHNativeWindow will never be destroyed
281 OH_NativeWindow_DestroyNativeWindow(window);
282 return surface;
283 }
284
NotifyEos()285 bool TesterCapi::NotifyEos()
286 {
287 auto begin = std::chrono::steady_clock::now();
288 OH_AVErrCode ret = OH_VideoEncoder_NotifyEndOfStream(codec_);
289 if (ret != AV_ERR_OK) {
290 TLOGE("NotifyEos failed");
291 return false;
292 }
293 CostRecorder::Instance().Update(begin, "OH_VideoEncoder_NotifyEndOfStream");
294 return true;
295 }
296
RequestIDR()297 bool TesterCapi::RequestIDR()
298 {
299 auto fmt = shared_ptr<OH_AVFormat>(OH_AVFormat_Create(), OH_AVFormat_Destroy);
300 IF_TRUE_RETURN_VAL_WITH_MSG(fmt == nullptr, false, "OH_AVFormat_Create failed");
301 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_REQUEST_I_FRAME, true);
302
303 auto begin = std::chrono::steady_clock::now();
304 OH_AVErrCode ret = OH_VideoEncoder_SetParameter(codec_, fmt.get());
305 if (ret != AV_ERR_OK) {
306 TLOGE("RequestIDR failed");
307 return false;
308 }
309 CostRecorder::Instance().Update(begin, "OH_VideoEncoder_SetParameter");
310 return true;
311 }
312
GetInputFormat()313 bool TesterCapi::GetInputFormat()
314 {
315 if (!opt_.isEncoder) {
316 return true;
317 }
318 auto begin = std::chrono::steady_clock::now();
319 OH_AVFormat *fmt = OH_VideoEncoder_GetInputDescription(codec_);
320 if (fmt == nullptr) {
321 TLOGE("GetInputFormat failed");
322 return false;
323 }
324 CostRecorder::Instance().Update(begin, "OH_VideoEncoder_GetInputDescription");
325 inputFmt_ = shared_ptr<OH_AVFormat>(fmt, OH_AVFormat_Destroy);
326 OH_AVFormat_GetIntValue(inputFmt_.get(), "stride", &inputStride_);
327 return true;
328 }
329
GetOutputFormat()330 bool TesterCapi::GetOutputFormat()
331 {
332 auto begin = std::chrono::steady_clock::now();
333 OH_AVFormat *fmt = opt_.isEncoder ? OH_VideoEncoder_GetOutputDescription(codec_) :
334 OH_VideoDecoder_GetOutputDescription(codec_);
335 if (fmt == nullptr) {
336 TLOGE("GetOutputFormat failed");
337 return false;
338 }
339 CostRecorder::Instance().Update(begin,
340 opt_.isEncoder ? "OH_VideoEncoder_GetOutputDescription" : "OH_VideoDecoder_GetOutputDescription");
341 OH_AVFormat_Destroy(fmt);
342 return true;
343 }
344
GetInputStride()345 optional<uint32_t> TesterCapi::GetInputStride()
346 {
347 int32_t stride = 0;
348 if (OH_AVFormat_GetIntValue(inputFmt_.get(), "stride", &stride)) {
349 return stride;
350 } else {
351 return nullopt;
352 }
353 }
354
WaitForInput(BufInfo & buf)355 bool TesterCapiOld::WaitForInput(BufInfo& buf)
356 {
357 {
358 unique_lock<mutex> lk(inputMtx_);
359 if (opt_.timeout == -1) {
360 inputCond_.wait(lk, [this] {
361 return !inputList_.empty();
362 });
363 } else {
364 bool ret = inputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
365 return !inputList_.empty();
366 });
367 if (!ret) {
368 TLOGE("time out");
369 return false;
370 }
371 }
372 std::tie(buf.idx, buf.mem) = inputList_.front();
373 inputList_.pop_front();
374 }
375 if (buf.mem == nullptr) {
376 TLOGE("null OH_AVMemory");
377 return false;
378 }
379 buf.va = OH_AVMemory_GetAddr(buf.mem);
380 buf.capacity = OH_AVMemory_GetSize(buf.mem);
381 if (opt_.isEncoder && opt_.isBufferMode) {
382 buf.dispW = opt_.dispW;
383 buf.dispH = opt_.dispH;
384 buf.fmt = displayFmt_;
385 if (inputStride_ < static_cast<int32_t>(opt_.dispW)) {
386 TLOGE("pixelStride %d < dispW %u", inputStride_, opt_.dispW);
387 return false;
388 }
389 buf.byteStride = inputStride_;
390 }
391 return true;
392 }
393
WaitForInput(BufInfo & buf)394 bool TesterCapiNew::WaitForInput(BufInfo& buf)
395 {
396 {
397 unique_lock<mutex> lk(inputMtx_);
398 if (opt_.timeout == -1) {
399 inputCond_.wait(lk, [this] {
400 return !inputList_.empty();
401 });
402 } else {
403 bool ret = inputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
404 return !inputList_.empty();
405 });
406 if (!ret) {
407 TLOGE("time out");
408 return false;
409 }
410 }
411 std::tie(buf.idx, buf.cavbuf) = inputList_.front();
412 inputList_.pop_front();
413 }
414 if (buf.cavbuf == nullptr) {
415 TLOGE("null OH_AVBuffer");
416 return false;
417 }
418 buf.va = OH_AVBuffer_GetAddr(buf.cavbuf);
419 buf.capacity = OH_AVBuffer_GetCapacity(buf.cavbuf);
420 if (opt_.isEncoder && opt_.isBufferMode) {
421 OH_NativeBuffer* nativeBuffer = OH_AVBuffer_GetNativeBuffer(buf.cavbuf);
422 if (!NativeBufferToBufferInfo(buf, nativeBuffer)) {
423 return false;
424 }
425 }
426 return true;
427 }
428
WaitForOutput(BufInfo & buf)429 bool TesterCapiOld::WaitForOutput(BufInfo& buf)
430 {
431 {
432 unique_lock<mutex> lk(outputMtx_);
433 if (opt_.timeout == -1) {
434 outputCond_.wait(lk, [this] {
435 return !outputList_.empty();
436 });
437 } else {
438 bool waitRes = outputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
439 return !outputList_.empty();
440 });
441 if (!waitRes) {
442 TLOGE("time out");
443 return false;
444 }
445 }
446 std::tie(buf.idx, buf.mem, buf.attr) = outputList_.front();
447 outputList_.pop_front();
448 }
449 if (buf.attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
450 TLOGI("output eos, quit loop");
451 return false;
452 }
453 if (buf.mem != nullptr) {
454 buf.va = OH_AVMemory_GetAddr(buf.mem);
455 buf.capacity = OH_AVMemory_GetSize(buf.mem);
456 }
457 return true;
458 }
459
WaitForOutput(BufInfo & buf)460 bool TesterCapiNew::WaitForOutput(BufInfo& buf)
461 {
462 {
463 unique_lock<mutex> lk(outputMtx_);
464 if (opt_.timeout == -1) {
465 outputCond_.wait(lk, [this] {
466 return !outputList_.empty();
467 });
468 } else {
469 bool waitRes = outputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
470 return !outputList_.empty();
471 });
472 if (!waitRes) {
473 TLOGE("time out");
474 return false;
475 }
476 }
477 std::tie(buf.idx, buf.cavbuf) = outputList_.front();
478 outputList_.pop_front();
479 }
480 OH_AVCodecBufferAttr attr;
481 OH_AVBuffer_GetBufferAttr(buf.cavbuf, &attr);
482 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
483 TLOGI("output eos, quit loop");
484 return false;
485 }
486 buf.attr = attr;
487 buf.va = OH_AVBuffer_GetAddr(buf.cavbuf);
488 buf.capacity = OH_AVBuffer_GetCapacity(buf.cavbuf);
489 return true;
490 }
491
ReturnInput(const BufInfo & buf)492 bool TesterCapiOld::ReturnInput(const BufInfo& buf)
493 {
494 auto begin = std::chrono::steady_clock::now();
495 OH_AVErrCode err = opt_.isEncoder ? OH_VideoEncoder_PushInputData(codec_, buf.idx, buf.attr) :
496 OH_VideoDecoder_PushInputData(codec_, buf.idx, buf.attr);
497 if (err != AV_ERR_OK) {
498 TLOGE("QueueInputBuffer failed");
499 return false;
500 }
501 CostRecorder::Instance().Update(begin,
502 opt_.isEncoder ? "OH_VideoEncoder_PushInputData" : "OH_VideoDecoder_PushInputData");
503 return true;
504 }
505
ReturnInput(const BufInfo & buf)506 bool TesterCapiNew::ReturnInput(const BufInfo& buf)
507 {
508 OH_AVBuffer_SetBufferAttr(buf.cavbuf, &buf.attr);
509 auto begin = std::chrono::steady_clock::now();
510 OH_AVErrCode err = opt_.isEncoder ? OH_VideoEncoder_PushInputBuffer(codec_, buf.idx) :
511 OH_VideoDecoder_PushInputBuffer(codec_, buf.idx);
512 if (err != AV_ERR_OK) {
513 TLOGE("PushInputBuffer failed");
514 return false;
515 }
516 CostRecorder::Instance().Update(begin,
517 opt_.isEncoder ? "OH_VideoEncoder_PushInputBuffer" : "OH_VideoDecoder_PushInputBuffer");
518 return true;
519 }
520
ReturnOutput(uint32_t idx)521 bool TesterCapiOld::ReturnOutput(uint32_t idx)
522 {
523 OH_AVErrCode err;
524 string apiName;
525 auto begin = std::chrono::steady_clock::now();
526 if (opt_.isEncoder) {
527 err = OH_VideoEncoder_FreeOutputData(codec_, idx);
528 apiName = "OH_VideoEncoder_FreeOutputData";
529 } else {
530 if (opt_.isBufferMode) {
531 err = OH_VideoDecoder_FreeOutputData(codec_, idx);
532 apiName = "OH_VideoDecoder_FreeOutputData";
533 } else {
534 err = OH_VideoDecoder_RenderOutputData(codec_, idx);
535 apiName = "OH_VideoDecoder_RenderOutputData";
536 }
537 }
538 if (err != AV_ERR_OK) {
539 TLOGE("%s failed", apiName.c_str());
540 return false;
541 }
542 CostRecorder::Instance().Update(begin, apiName);
543 return true;
544 }
545
ReturnOutput(uint32_t idx)546 bool TesterCapiNew::ReturnOutput(uint32_t idx)
547 {
548 OH_AVErrCode err;
549 string apiName;
550 auto begin = std::chrono::steady_clock::now();
551 if (opt_.isEncoder) {
552 err = OH_VideoEncoder_FreeOutputBuffer(codec_, idx);
553 apiName = "OH_VideoEncoder_FreeOutputBuffer";
554 } else {
555 if (opt_.isBufferMode) {
556 err = OH_VideoDecoder_FreeOutputBuffer(codec_, idx);
557 apiName = "OH_VideoDecoder_FreeOutputBuffer";
558 } else {
559 err = OH_VideoDecoder_RenderOutputBuffer(codec_, idx);
560 apiName = "OH_VideoDecoder_RenderOutputBuffer";
561 }
562 }
563 if (err != AV_ERR_OK) {
564 TLOGE("%s failed", apiName.c_str());
565 return false;
566 }
567 CostRecorder::Instance().Update(begin, apiName);
568 return true;
569 }
570
SetOutputSurface(sptr<Surface> & surface)571 bool TesterCapi::SetOutputSurface(sptr<Surface>& surface)
572 {
573 OHNativeWindow *window = CreateNativeWindowFromSurface(&surface);
574 if (window == nullptr) {
575 TLOGE("CreateNativeWindowFromSurface failed");
576 return false;
577 }
578 auto begin = std::chrono::steady_clock::now();
579 OH_AVErrCode err = OH_VideoDecoder_SetSurface(codec_, window);
580 if (err != AV_ERR_OK) {
581 TLOGE("OH_VideoDecoder_SetSurface failed");
582 return false;
583 }
584 CostRecorder::Instance().Update(begin, "OH_VideoDecoder_SetSurface");
585 return true;
586 }
587
ConfigureDecoder()588 bool TesterCapi::ConfigureDecoder()
589 {
590 auto fmt = shared_ptr<OH_AVFormat>(OH_AVFormat_Create(), OH_AVFormat_Destroy);
591 IF_TRUE_RETURN_VAL_WITH_MSG(fmt == nullptr, false, "OH_AVFormat_Create failed");
592 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_WIDTH, opt_.dispW);
593 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_HEIGHT, opt_.dispH);
594 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(opt_.pixFmt));
595 OH_AVFormat_SetDoubleValue(fmt.get(), OH_MD_KEY_FRAME_RATE, opt_.frameRate);
596 OH_AVFormat_SetIntValue(fmt.get(), OH_MD_KEY_ROTATION, opt_.rotation);
597
598 auto begin = std::chrono::steady_clock::now();
599 OH_AVErrCode ret = OH_VideoDecoder_Configure(codec_, fmt.get());
600 if (ret != AV_ERR_OK) {
601 TLOGE("OH_VideoDecoder_Configure failed");
602 return false;
603 }
604 CostRecorder::Instance().Update(begin, "OH_VideoDecoder_Configure");
605 return true;
606 }
607 }