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_codecbase.h"
17 #include "avcodec_errors.h"
18 #include "type_converter.h"
19 #include "hcodec_log.h"
20 #include "hcodec_utils.h"
21 #include "hcodec_api.h"
22
23 namespace OHOS::MediaAVCodec {
24 using namespace std;
25
OnError(AVCodecErrorType errorType,int32_t errorCode)26 void TesterCodecBase::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
27 {
28 TLOGI(">>");
29 }
30
OnOutputFormatChanged(const Format & format)31 void TesterCodecBase::CallBack::OnOutputFormatChanged(const Format &format)
32 {
33 TLOGI(">>");
34 }
35
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)36 void TesterCodecBase::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
37 {
38 lock_guard<mutex> lk(tester_->inputMtx_);
39 tester_->inputList_.emplace_back(index, buffer);
40 tester_->inputCond_.notify_all();
41 }
42
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)43 void TesterCodecBase::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
44 {
45 if (!(buffer->flag_ & AVCODEC_BUFFER_FLAG_EOS)) {
46 auto metaStr = StringifyMeta(buffer->meta_);
47 TLOGI("%s", metaStr.c_str());
48 }
49 tester_->AfterGotOutput(OH_AVCodecBufferAttr {
50 .pts = buffer->pts_,
51 .size = buffer->memory_ ? buffer->memory_->GetSize() : 0,
52 .flags = buffer->flag_,
53 });
54 lock_guard<mutex> lk(tester_->outputMtx_);
55 tester_->outputList_.emplace_back(index, buffer);
56 tester_->outputCond_.notify_all();
57 }
58
Create()59 bool TesterCodecBase::Create()
60 {
61 string mime = GetCodecMime(opt_.protocol);
62 string name = GetCodecName(opt_.isEncoder, mime);
63 auto begin = std::chrono::steady_clock::now();
64 CreateHCodecByName(name, codec_);
65 if (codec_ == nullptr) {
66 TLOGE("Create failed");
67 return false;
68 }
69 Media::Meta meta{};
70 int32_t err = codec_->Init(meta);
71 if (err != AVCS_ERR_OK) {
72 TLOGE("Init failed");
73 return false;
74 }
75 CostRecorder::Instance().Update(begin, "Create");
76 return true;
77 }
78
SetCallback()79 bool TesterCodecBase::SetCallback()
80 {
81 shared_ptr<CallBack> cb = make_shared<CallBack>(this);
82 auto begin = std::chrono::steady_clock::now();
83 int32_t err = codec_->SetCallback(cb);
84 if (err != AVCS_ERR_OK) {
85 TLOGE("SetCallback failed");
86 return false;
87 }
88 CostRecorder::Instance().Update(begin, "SetCallback");
89 return true;
90 }
91
Start()92 bool TesterCodecBase::Start()
93 {
94 auto begin = std::chrono::steady_clock::now();
95 int32_t err = codec_->Start();
96 if (err != AVCS_ERR_OK) {
97 TLOGE("Start failed");
98 return false;
99 }
100 CostRecorder::Instance().Update(begin, "Start");
101 return true;
102 }
103
Stop()104 bool TesterCodecBase::Stop()
105 {
106 auto begin = std::chrono::steady_clock::now();
107 int32_t err = codec_->Stop();
108 if (err != AVCS_ERR_OK) {
109 TLOGE("Stop failed");
110 return false;
111 }
112 CostRecorder::Instance().Update(begin, "Stop");
113 return true;
114 }
115
Release()116 bool TesterCodecBase::Release()
117 {
118 auto begin = std::chrono::steady_clock::now();
119 int32_t err = codec_->Release();
120 if (err != AVCS_ERR_OK) {
121 TLOGE("Release failed");
122 return false;
123 }
124 CostRecorder::Instance().Update(begin, "Release");
125 return true;
126 }
127
Flush()128 bool TesterCodecBase::Flush()
129 {
130 auto begin = std::chrono::steady_clock::now();
131 int32_t err = codec_->Flush();
132 if (err != AVCS_ERR_OK) {
133 TLOGE("Flush failed");
134 return false;
135 }
136 CostRecorder::Instance().Update(begin, "Flush");
137 return true;
138 }
139
ClearAllBuffer()140 void TesterCodecBase::ClearAllBuffer()
141 {
142 {
143 lock_guard<mutex> lk(inputMtx_);
144 inputList_.clear();
145 }
146 {
147 lock_guard<mutex> lk(outputMtx_);
148 outputList_.clear();
149 }
150 }
151
EnableHighPerf(Format & fmt) const152 void TesterCodecBase::EnableHighPerf(Format& fmt) const
153 {
154 if (opt_.isHighPerfMode) {
155 fmt.PutIntValue("frame_rate_adaptive_mode", 1);
156 }
157 }
158
ConfigureEncoder()159 bool TesterCodecBase::ConfigureEncoder()
160 {
161 Format fmt;
162 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, opt_.dispW);
163 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, opt_.dispH);
164 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(opt_.pixFmt));
165 fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, opt_.frameRate);
166 if (opt_.rangeFlag.has_value()) {
167 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, opt_.rangeFlag.value());
168 }
169 if (opt_.primary.has_value()) {
170 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, opt_.primary.value());
171 }
172 if (opt_.transfer.has_value()) {
173 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, opt_.transfer.value());
174 }
175 if (opt_.matrix.has_value()) {
176 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, opt_.matrix.value());
177 }
178 if (opt_.iFrameInterval.has_value()) {
179 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, opt_.iFrameInterval.value());
180 }
181 if (opt_.profile.has_value()) {
182 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PROFILE, opt_.profile.value());
183 }
184 if (opt_.rateMode.has_value()) {
185 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, opt_.rateMode.value());
186 }
187 if (opt_.bitRate.has_value()) {
188 fmt.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, opt_.bitRate.value());
189 }
190 if (opt_.quality.has_value()) {
191 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, opt_.quality.value());
192 }
193 if (opt_.sqrFactor.has_value()) {
194 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, opt_.sqrFactor.value());
195 }
196 if (opt_.maxBitrate.has_value()) {
197 fmt.PutLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, opt_.maxBitrate.value());
198 }
199 if (opt_.targetQp.has_value()) {
200 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TARGET_QP, opt_.targetQp.value());
201 }
202 if (opt_.layerCnt.has_value()) {
203 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, true);
204 int32_t temporalGopSize = 0;
205 switch (opt_.layerCnt.value()) {
206 case 2: // 2: temporal layerCnt
207 temporalGopSize = 2; // 2: temporalGopSize
208 break;
209 case 3: // 3: temporal layerCnt
210 temporalGopSize = 4; // 4: temporalGopSize
211 break;
212 default:
213 break;
214 }
215 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
216 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, 2); // 2: gop mode
217 }
218 EnableHighPerf(fmt);
219 if (opt_.qpRange.has_value()) {
220 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, opt_.qpRange->qpMin);
221 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, opt_.qpRange->qpMax);
222 }
223 if (opt_.repeatAfter.has_value()) {
224 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, opt_.repeatAfter.value());
225 }
226 if (opt_.repeatMaxCnt.has_value()) {
227 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, opt_.repeatMaxCnt.value());
228 }
229 if (!opt_.isBufferMode && !opt_.perFrameParamsMap.empty()) {
230 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, 1);
231 opt_.enableInputCb = true;
232 }
233 if (opt_.ltrFrameCount > 0) {
234 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, opt_.ltrFrameCount);
235 }
236 if (opt_.paramsFeedback == 1) {
237 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_PARAMS_FEEDBACK, opt_.paramsFeedback);
238 }
239 if (opt_.enableQPMap == 1) {
240 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_QP_MAP, opt_.enableQPMap);
241 }
242 if (opt_.gopBMode.has_value()) {
243 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE, opt_.gopBMode.value());
244 }
245 auto begin = std::chrono::steady_clock::now();
246 int32_t err = codec_->Configure(fmt);
247 if (err != AVCS_ERR_OK) {
248 TLOGE("Configure failed");
249 return false;
250 }
251 CostRecorder::Instance().Update(begin, "Configure");
252
253 if (opt_.waterMark.isSet) {
254 shared_ptr<AVBuffer> buffer = CreateWaterMarkBuffer();
255 err = codec_->SetCustomBuffer(buffer);
256 if (err != AVCS_ERR_OK) {
257 TLOGE("SetCustomBuffer failed");
258 return false;
259 }
260 }
261 return true;
262 }
263
SetEncoderParameter(const SetParameterParams & param)264 bool TesterCodecBase::SetEncoderParameter(const SetParameterParams& param)
265 {
266 Format fmt;
267 if (param.bitRate.has_value()) {
268 fmt.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, param.bitRate.value());
269 }
270 if (param.frameRate.has_value()) {
271 fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, param.frameRate.value());
272 }
273 if (param.targetQp.has_value()) {
274 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TARGET_QP, param.targetQp.value());
275 }
276 if (param.operatingRate.has_value()) {
277 fmt.PutDoubleValue(OHOS::Media::Tag::VIDEO_ENCODER_OPERATING_RATE, param.operatingRate.value());
278 }
279 if (param.qpRange.has_value()) {
280 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, static_cast<int32_t>(param.qpRange->qpMin));
281 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, static_cast<int32_t>(param.qpRange->qpMax));
282 }
283 if (opt_.scaleMode.has_value()) {
284 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, static_cast<int32_t>(opt_.scaleMode.value()));
285 }
286 if (param.sqrParam.has_value()) {
287 if (param.sqrParam->bitrate.has_value()) {
288 fmt.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, param.sqrParam->bitrate.value());
289 }
290 if (param.sqrParam->maxBitrate.has_value()) {
291 fmt.PutLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, param.sqrParam->maxBitrate.value());
292 }
293 if (param.sqrParam->sqrFactor.has_value()) {
294 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, param.sqrParam->sqrFactor.value());
295 }
296 }
297 int32_t err = codec_->SetParameter(fmt);
298 if (err != AVCS_ERR_OK) {
299 TLOGE("SetParameter failed");
300 return false;
301 }
302 return true;
303 }
304
SetEncoderPerFrameParam(BufInfo & buf,const PerFrameParams & param)305 bool TesterCodecBase::SetEncoderPerFrameParam(BufInfo& buf, const PerFrameParams& param)
306 {
307 if (buf.avbuf == nullptr) {
308 return false;
309 }
310 shared_ptr<Media::Meta> meta = buf.avbuf->meta_;
311 if (meta == nullptr) {
312 return false;
313 }
314 if (param.requestIdr.has_value()) {
315 meta->SetData(OHOS::Media::Tag::VIDEO_REQUEST_I_FRAME, param.requestIdr.value());
316 }
317 if (param.qpRange.has_value()) {
318 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, static_cast<int32_t>(param.qpRange->qpMin));
319 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, static_cast<int32_t>(param.qpRange->qpMax));
320 }
321 if (param.ltrParam.has_value()) {
322 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_MARK_LTR,
323 static_cast<bool>(param.ltrParam->markAsLTR));
324 if (param.ltrParam->useLTR > 0) {
325 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_USE_LTR,
326 static_cast<int32_t>(param.ltrParam->useLTRPoc));
327 }
328 }
329 if (param.discard.has_value()) {
330 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_DISCARD, param.discard.value());
331 }
332 if (param.ebrParam.has_value()) {
333 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, static_cast<int32_t>(param.ebrParam->minQp));
334 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, static_cast<int32_t>(param.ebrParam->maxQp));
335 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_START, static_cast<int32_t>(param.ebrParam->startQp));
336 meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_SKIP, static_cast<bool>(param.ebrParam->isSkip));
337 }
338 if (param.roiParams.has_value()) {
339 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_ROI_PARAMS, param.roiParams.value());
340 }
341 if (param.absQpMap.has_value() && param.qpMapValue.has_value()) {
342 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_ABS_QP_MAP, param.absQpMap.value());
343
344 size_t widthInBlock = (opt_.dispW - 1) / 16 + 1; // divide by 16x16 block
345 size_t heightInBlock = (opt_.dispH - 1) / 16 + 1; // divide by 16x16 block
346 vector<uint8_t> qpMap (widthInBlock * heightInBlock,
347 static_cast<uint8_t>(param.qpMapValue.value()));
348 meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_QP_MAP, qpMap);
349 }
350 return true;
351 }
352
CreateInputSurface()353 sptr<Surface> TesterCodecBase::CreateInputSurface()
354 {
355 auto begin = std::chrono::steady_clock::now();
356 sptr<Surface> ret = codec_->CreateInputSurface();
357 if (ret == nullptr) {
358 TLOGE("CreateInputSurface failed");
359 return nullptr;
360 }
361 CostRecorder::Instance().Update(begin, "CreateInputSurface");
362 return ret;
363 }
364
NotifyEos()365 bool TesterCodecBase::NotifyEos()
366 {
367 auto begin = std::chrono::steady_clock::now();
368 int32_t err = codec_->NotifyEos();
369 if (err != AVCS_ERR_OK) {
370 TLOGE("NotifyEos failed");
371 return false;
372 }
373 CostRecorder::Instance().Update(begin, "NotifyEos");
374 return true;
375 }
376
RequestIDR()377 bool TesterCodecBase::RequestIDR()
378 {
379 auto begin = std::chrono::steady_clock::now();
380 int32_t err = codec_->SignalRequestIDRFrame();
381 if (err != AVCS_ERR_OK) {
382 TLOGE("RequestIDR failed");
383 return false;
384 }
385 CostRecorder::Instance().Update(begin, "SignalRequestIDRFrame");
386 return true;
387 }
388
GetInputFormat()389 bool TesterCodecBase::GetInputFormat()
390 {
391 auto begin = std::chrono::steady_clock::now();
392 int32_t err = codec_->GetInputFormat(inputFmt_);
393 if (err != AVCS_ERR_OK) {
394 TLOGE("GetInputFormat failed");
395 return false;
396 }
397 CostRecorder::Instance().Update(begin, "GetInputFormat");
398 return true;
399 }
400
GetOutputFormat()401 bool TesterCodecBase::GetOutputFormat()
402 {
403 Format fmt;
404 auto begin = std::chrono::steady_clock::now();
405 int32_t err = codec_->GetOutputFormat(fmt);
406 if (err != AVCS_ERR_OK) {
407 TLOGE("GetOutputFormat failed");
408 return false;
409 }
410 CostRecorder::Instance().Update(begin, "GetOutputFormat");
411 return true;
412 }
413
GetInputStride()414 optional<uint32_t> TesterCodecBase::GetInputStride()
415 {
416 int32_t stride = 0;
417 if (inputFmt_.GetIntValue("stride", stride)) {
418 return stride;
419 } else {
420 return nullopt;
421 }
422 }
423
WaitForInput(BufInfo & buf)424 bool TesterCodecBase::WaitForInput(BufInfo& buf)
425 {
426 {
427 unique_lock<mutex> lk(inputMtx_);
428 if (opt_.timeout == -1) {
429 inputCond_.wait(lk, [this] {
430 return !inputList_.empty();
431 });
432 } else {
433 bool ret = inputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
434 return !inputList_.empty();
435 });
436 if (!ret) {
437 TLOGE("time out");
438 return false;
439 }
440 }
441 std::tie(buf.idx, buf.avbuf) = inputList_.front();
442 inputList_.pop_front();
443 }
444 if (buf.avbuf == nullptr) {
445 TLOGE("null avbuffer");
446 return false;
447 }
448 if (opt_.enableInputCb) {
449 return true;
450 }
451 if (buf.avbuf->memory_ == nullptr) {
452 TLOGE("null memory in avbuffer");
453 return false;
454 }
455 buf.va = buf.avbuf->memory_->GetAddr();
456 buf.capacity = buf.avbuf->memory_->GetCapacity();
457 if (opt_.isEncoder && opt_.isBufferMode) {
458 sptr<SurfaceBuffer> surfaceBuffer = buf.avbuf->memory_->GetSurfaceBuffer();
459 if (!SurfaceBufferToBufferInfo(buf, surfaceBuffer)) {
460 return false;
461 }
462 }
463 return true;
464 }
465
ReturnInput(const BufInfo & buf)466 bool TesterCodecBase::ReturnInput(const BufInfo& buf)
467 {
468 if (!opt_.enableInputCb) {
469 buf.avbuf->pts_ = buf.attr.pts;
470 buf.avbuf->flag_ = buf.attr.flags;
471 buf.avbuf->memory_->SetOffset(buf.attr.offset);
472 buf.avbuf->memory_->SetSize(buf.attr.size);
473 }
474
475 auto begin = std::chrono::steady_clock::now();
476 int32_t err = codec_->QueueInputBuffer(buf.idx);
477 if (err != AVCS_ERR_OK) {
478 TLOGE("QueueInputBuffer failed");
479 return false;
480 }
481 CostRecorder::Instance().Update(begin, "QueueInputBuffer");
482 return true;
483 }
484
WaitForOutput(BufInfo & buf)485 bool TesterCodecBase::WaitForOutput(BufInfo& buf)
486 {
487 {
488 unique_lock<mutex> lk(outputMtx_);
489 if (opt_.timeout == -1) {
490 outputCond_.wait(lk, [this] {
491 return !outputList_.empty();
492 });
493 } else {
494 bool waitRes = outputCond_.wait_for(lk, chrono::milliseconds(opt_.timeout), [this] {
495 return !outputList_.empty();
496 });
497 if (!waitRes) {
498 TLOGE("time out");
499 return false;
500 }
501 }
502 std::tie(buf.idx, buf.avbuf) = outputList_.front();
503 outputList_.pop_front();
504 }
505 if (buf.avbuf == nullptr) {
506 TLOGE("null avbuffer");
507 return false;
508 }
509 if (buf.avbuf->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
510 TLOGI("output eos, quit loop");
511 return false;
512 }
513 buf.attr.pts = buf.avbuf->pts_;
514 if (buf.avbuf->memory_) {
515 buf.va = buf.avbuf->memory_->GetAddr();
516 buf.capacity = static_cast<size_t>(buf.avbuf->memory_->GetCapacity());
517 buf.attr.size = buf.avbuf->memory_->GetSize();
518 }
519 return true;
520 }
521
ReturnOutput(uint32_t idx)522 bool TesterCodecBase::ReturnOutput(uint32_t idx)
523 {
524 int32_t ret;
525 string apiName;
526 auto begin = std::chrono::steady_clock::now();
527 if (opt_.isEncoder || opt_.isBufferMode) {
528 ret = codec_->ReleaseOutputBuffer(idx);
529 apiName = "ReleaseOutputBuffer";
530 } else {
531 ret = codec_->RenderOutputBuffer(idx);
532 apiName = "RenderOutputBuffer";
533 }
534 if (ret != AVCS_ERR_OK) {
535 TLOGE("%s failed", apiName.c_str());
536 return false;
537 }
538 CostRecorder::Instance().Update(begin, apiName);
539 return true;
540 }
541
SetOutputSurface(sptr<Surface> & surface)542 bool TesterCodecBase::SetOutputSurface(sptr<Surface>& surface)
543 {
544 auto begin = std::chrono::steady_clock::now();
545 int32_t err = codec_->SetOutputSurface(surface);
546 if (err != AVCS_ERR_OK) {
547 TLOGE("SetOutputSurface failed");
548 return false;
549 }
550 CostRecorder::Instance().Update(begin, "SetOutputSurface");
551 return true;
552 }
553
ConfigureDecoder()554 bool TesterCodecBase::ConfigureDecoder()
555 {
556 Format fmt;
557 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, opt_.dispW);
558 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, opt_.dispH);
559 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(opt_.pixFmt));
560 fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, opt_.frameRate);
561 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, opt_.rotation);
562 EnableHighPerf(fmt);
563 if (opt_.scaleMode.has_value()) {
564 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, static_cast<int32_t>(opt_.scaleMode.value()));
565 }
566 if (opt_.isVrrEnable.has_value()) {
567 fmt.PutIntValue(OHOS::Media::Tag::VIDEO_DECODER_OUTPUT_ENABLE_VRR, opt_.isVrrEnable.value());
568 }
569 auto begin = std::chrono::steady_clock::now();
570 int32_t err = codec_->Configure(fmt);
571 if (err != AVCS_ERR_OK) {
572 TLOGE("Configure failed");
573 return false;
574 }
575 CostRecorder::Instance().Update(begin, "Configure");
576 return true;
577 }
578 }