/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "serverdec_sample.h" #include #include using namespace OHOS; using namespace OHOS::Media; using namespace OHOS::MediaAVCodec; using namespace OHOS::MediaAVCodec::Codec; using namespace std; namespace { } // namespace void VDecServerSample::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode) { cout << "--OnError--" << endl; tester->isRunning_.store(false); tester->signal_->inCond_.notify_all(); } void VDecServerSample::CallBack::OnOutputFormatChanged(const Format &format) { tester->GetOutputFormat(); } void VDecServerSample::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr buffer) { unique_lock lock(tester->signal_->inMutex_); tester->signal_->inIdxQueue_.push(index); tester->signal_->inBufferQueue_.push(buffer); tester->signal_->inCond_.notify_all(); } void VDecServerSample::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr buffer) { tester->codec_->ReleaseOutputBuffer(index); } VDecServerSample::~VDecServerSample() { if (codec_ != nullptr) { codec_->Stop(); codec_->Release(); } if (signal_ != nullptr) { delete signal_; signal_ = nullptr; } } int32_t VDecServerSample::ConfigServerDecoder() { Format fmt; fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width); fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height); fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, 1); fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate); fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 0); return codec_->Configure(fmt); } int32_t VDecServerSample::SetCallback() { shared_ptr cb = make_shared(this); return codec_->SetCallback(cb); } void VDecServerSample::RunVideoServerDecoder() { codec_ = make_shared("OH.Media.Codec.Decoder.Video.AVC"); if (codec_ == nullptr) { cout << "Create failed" << endl; return; } Media::Meta codecInfo; int32_t instanceid = 0; codecInfo.SetData("av_codec_event_info_instance_id", instanceid); int32_t err = codec_->Init(codecInfo); if (err != AVCS_ERR_OK) { cout << "decoder Init failed!" << endl; return; } err = ConfigServerDecoder(); if (err != AVCS_ERR_OK) { cout << "ConfigServerDecoder failed" << endl; return; } signal_ = new VDecSignal(); if (signal_ == nullptr) { cout << "Failed to new VDecSignal" << endl; return; } err = SetCallback(); if (err != AVCS_ERR_OK) { cout << "SetCallback failed" << endl; return; } err = codec_->Start(); if (err != AVCS_ERR_OK) { cout << "Start failed" << endl; return; } isRunning_.store(true); inputLoop_ = make_unique(&VDecServerSample::InputFunc, this); if (inputLoop_ == nullptr) { cout << "Failed to create input loop" << endl; isRunning_.store(false); } } void VDecServerSample::InputFunc() { int32_t time = 1000; while (sendFrameIndex < frameIndex) { if (!isRunning_.load()) { break; } unique_lock lock(signal_->inMutex_); signal_->inCond_.wait_for(lock, std::chrono::milliseconds(time), [this]() { if (!isRunning_.load()) { cout << "quit signal" << endl; return true; } return signal_->inIdxQueue_.size() > 0; }); if (!isRunning_.load() || signal_->inIdxQueue_.size() == 0) { break; } uint32_t index = signal_->inIdxQueue_.front(); auto buffer = signal_->inBufferQueue_.front(); signal_->inIdxQueue_.pop(); signal_->inBufferQueue_.pop(); lock.unlock(); if (buffer->memory_ == nullptr) { isRunning_.store(false); break; } uint8_t *bufferAddr = buffer->memory_->GetAddr(); if (memcpy_s(bufferAddr, buffer->memory_->GetCapacity(), fuzzData, fuzzSize) != EOK) { break; } int32_t err = codec_->QueueInputBuffer(index); if (err != AVCS_ERR_OK) { cout << "QueueInputBuffer fail" << endl; break; } sendFrameIndex++; } } void VDecServerSample::WaitForEos() { if (inputLoop_ && inputLoop_->joinable()) { inputLoop_->join(); } } void VDecServerSample::GetOutputFormat() { Format fmt; int32_t err = codec_->GetOutputFormat(fmt); if (err != AVCS_ERR_OK) { cout << "GetOutputFormat fail" << endl; isRunning_.store(false); signal_->inCond_.notify_all(); } } void VDecServerSample::Flush() { int32_t err = codec_->Flush(); if (err != AVCS_ERR_OK) { cout << "Flush fail" << endl; isRunning_.store(false); signal_->inCond_.notify_all(); } } void VDecServerSample::Reset() { int32_t err = codec_->Reset(); if (err != AVCS_ERR_OK) { cout << "Reset fail" << endl; isRunning_.store(false); signal_->inCond_.notify_all(); } }