• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }