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