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