• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include <arpa/inet.h>
16 #include <sys/time.h>
17 #include <utility>
18 #include "serverdec_sample.h"
19 #include <iostream>
20 #include <chrono>
21 using namespace OHOS;
22 using namespace OHOS::Media;
23 using namespace OHOS::MediaAVCodec;
24 using namespace OHOS::MediaAVCodec::Codec;
25 using namespace std;
26 namespace {
27 
28 } // namespace
29 
OnError(AVCodecErrorType errorType,int32_t errorCode)30 void VDecServerSample::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
31 {
32     cout << "--OnError--" << endl;
33     tester->isRunning_.store(false);
34     tester->signal_->inCond_.notify_all();
35 }
36 
OnOutputFormatChanged(const Format & format)37 void VDecServerSample::CallBack::OnOutputFormatChanged(const Format &format)
38 {
39     tester->GetOutputFormat();
40 }
41 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)42 void VDecServerSample::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
43 {
44     unique_lock<mutex> lock(tester->signal_->inMutex_);
45     tester->signal_->inIdxQueue_.push(index);
46     tester->signal_->inBufferQueue_.push(buffer);
47     tester->signal_->inCond_.notify_all();
48 }
49 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)50 void VDecServerSample::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
51 {
52     tester->codec_->ReleaseOutputBuffer(index);
53 }
54 
~VDecServerSample()55 VDecServerSample::~VDecServerSample()
56 {
57     if (codec_ != nullptr) {
58         codec_->Stop();
59         codec_->Release();
60     }
61     if (signal_ != nullptr) {
62         delete signal_;
63         signal_ = nullptr;
64     }
65 }
66 
ConfigServerDecoder()67 int32_t VDecServerSample::ConfigServerDecoder()
68 {
69     Format fmt;
70     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width);
71     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height);
72     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, 1);
73     fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
74     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 0);
75     return codec_->Configure(fmt);
76 }
77 
SetCallback()78 int32_t VDecServerSample::SetCallback()
79 {
80     shared_ptr<CallBack> cb = make_shared<CallBack>(this);
81     return codec_->SetCallback(cb);
82 }
83 
RunVideoServerDecoder()84 void VDecServerSample::RunVideoServerDecoder()
85 {
86     codec_ = make_shared<FCodec>("OH.Media.Codec.Decoder.Video.MPEG2");
87     if (codec_ == nullptr) {
88         cout << "Create failed" << endl;
89         return;
90     }
91     Media::Meta codecInfo;
92     int32_t instanceid = 0;
93     codecInfo.SetData("av_codec_event_info_instance_id", instanceid);
94     int32_t err = codec_->Init(codecInfo);
95     if (err != AVCS_ERR_OK) {
96         cout << "decoder Init failed!" << endl;
97         return;
98     }
99     err = ConfigServerDecoder();
100     if (err != AVCS_ERR_OK) {
101         cout << "ConfigServerDecoder failed" << endl;
102         return;
103     }
104     signal_ = new VDecSignal();
105     if (signal_ == nullptr) {
106         cout << "Failed to new VDecSignal" << endl;
107         return;
108     }
109     err = SetCallback();
110     if (err != AVCS_ERR_OK) {
111         cout << "SetCallback failed" << endl;
112         return;
113     }
114     err = codec_->Start();
115     if (err != AVCS_ERR_OK) {
116         cout << "Start failed" << endl;
117         return;
118     }
119     isRunning_.store(true);
120     inputLoop_ = make_unique<thread>(&VDecServerSample::InputFunc, this);
121     if (inputLoop_ == nullptr) {
122         cout << "Failed to create input loop" << endl;
123         isRunning_.store(false);
124     }
125 }
126 
InputFunc()127 void VDecServerSample::InputFunc()
128 {
129     int32_t time = 1000;
130     while (sendFrameIndex < frameIndex) {
131         if (!isRunning_.load()) {
132             break;
133         }
134         unique_lock<mutex> lock(signal_->inMutex_);
135         signal_->inCond_.wait_for(lock, std::chrono::milliseconds(time), [this]() {
136             if (!isRunning_.load()) {
137                 cout << "quit signal" << endl;
138                 return true;
139             }
140             return signal_->inIdxQueue_.size() > 0;
141         });
142         if (!isRunning_.load() || signal_->inIdxQueue_.size() == 0) {
143             break;
144         }
145         uint32_t index = signal_->inIdxQueue_.front();
146         auto buffer = signal_->inBufferQueue_.front();
147         signal_->inIdxQueue_.pop();
148         signal_->inBufferQueue_.pop();
149         lock.unlock();
150         if (buffer->memory_ == nullptr) {
151             isRunning_.store(false);
152             break;
153         }
154         uint8_t *bufferAddr = buffer->memory_->GetAddr();
155         if (memcpy_s(bufferAddr, buffer->memory_->GetCapacity(), fuzzData, fuzzSize) != EOK) {
156             break;
157         }
158         int32_t err = codec_->QueueInputBuffer(index);
159         if (err != AVCS_ERR_OK) {
160             cout << "QueueInputBuffer fail" << endl;
161             break;
162         }
163         sendFrameIndex++;
164     }
165 }
166 
WaitForEos()167 void VDecServerSample::WaitForEos()
168 {
169     if (inputLoop_ && inputLoop_->joinable()) {
170         inputLoop_->join();
171     }
172 }
173 
GetOutputFormat()174 void VDecServerSample::GetOutputFormat()
175 {
176     Format fmt;
177     int32_t err = codec_->GetOutputFormat(fmt);
178     if (err != AVCS_ERR_OK) {
179         cout << "GetOutputFormat fail" << endl;
180         isRunning_.store(false);
181         signal_->inCond_.notify_all();
182     }
183 }
184 
Flush()185 void VDecServerSample::Flush()
186 {
187     int32_t err = codec_->Flush();
188     if (err != AVCS_ERR_OK) {
189         cout << "Flush fail" << endl;
190         isRunning_.store(false);
191         signal_->inCond_.notify_all();
192     }
193 }
194 
Reset()195 void VDecServerSample::Reset()
196 {
197     int32_t err = codec_->Reset();
198     if (err != AVCS_ERR_OK) {
199         cout << "Reset fail" << endl;
200         isRunning_.store(false);
201         signal_->inCond_.notify_all();
202     }
203 }