• 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 TIME = 12345;
28 constexpr int32_t MAX_SEND_FRAMES = 10;
29 } // namespace
30 
OnError(AVCodecErrorType errorType,int32_t errorCode)31 void VDecServerSample::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
32 {
33     tester->Flush();
34     tester->Reset();
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         HevcDecoder *codec = reinterpret_cast<HevcDecoder*>(codec_.get());
61         codec->DecStrongRef(codec);
62     }
63     if (signal_ != nullptr) {
64         delete signal_;
65         signal_ = nullptr;
66     }
67 }
68 
ConfigServerDecoder()69 int32_t VDecServerSample::ConfigServerDecoder()
70 {
71     Format fmt;
72     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, kWidth);
73     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, kHeight);
74     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, kFormat);
75     fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, kFormatRate);
76     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, kAngle);
77     fmt.PutIntValue(MediaDescriptionKey::MD_KEY_DURATION, kRotation);
78     return codec_->Configure(fmt);
79 }
80 
SetCallback()81 int32_t VDecServerSample::SetCallback()
82 {
83     shared_ptr<CallBack> cb = make_shared<CallBack>(this);
84     return codec_->SetCallback(cb);
85 }
86 
RunVideoServerDecoder()87 void VDecServerSample::RunVideoServerDecoder()
88 {
89     CreateHevcDecoderByName("OH.Media.Codec.Decoder.Video.HEVC", codec_);
90     if (codec_ == nullptr) {
91         cout << "Create failed" << endl;
92         return;
93     }
94     int32_t err = ConfigServerDecoder();
95     if (err != AVCS_ERR_OK) {
96         cout << "ConfigServerDecoder failed" << endl;
97         return;
98     }
99     signal_ = new VDecSignal();
100     if (signal_ == nullptr) {
101         cout << "Failed to new VDecSignal" << endl;
102         return;
103     }
104     err = SetCallback();
105     if (err != AVCS_ERR_OK) {
106         cout << "SetCallback failed" << endl;
107         return;
108     }
109     err = codec_->Start();
110     if (err != AVCS_ERR_OK) {
111         cout << "Start failed" << endl;
112         return;
113     }
114     isRunning_.store(true);
115     inputLoop_ = make_unique<thread>(&VDecServerSample::InputFunc, this);
116     if (inputLoop_ == nullptr) {
117         cout << "Failed to create input loop" << endl;
118         isRunning_.store(false);
119     }
120 }
121 
InputFunc()122 void VDecServerSample::InputFunc()
123 {
124     while (sendFrameIndex < MAX_SEND_FRAMES) {
125         if (!isRunning_.load()) {
126             break;
127         }
128         unique_lock<mutex> lock(signal_->inMutex_);
129         signal_->inCond_.wait(lock, [this]() {
130             if (!isRunning_.load()) {
131                 cout << "quit signal" << endl;
132                 return true;
133             }
134             return signal_->inIdxQueue_.size() > 0;
135         });
136         if (!isRunning_.load()) {
137             break;
138         }
139         uint32_t index = signal_->inIdxQueue_.front();
140         auto buffer = signal_->inBufferQueue_.front();
141         signal_->inIdxQueue_.pop();
142         signal_->inBufferQueue_.pop();
143         lock.unlock();
144         if (buffer->memory_ == nullptr) {
145             isRunning_.store(false);
146             break;
147         }
148         uint8_t *bufferAddr = buffer->memory_->GetAddr();
149         if (memcpy_s(bufferAddr, buffer->memory_->GetCapacity(), fuzzData, fuzzSize) != EOK) {
150             break;
151         }
152         buffer->pts_ = TIME;
153         buffer->flag_ = 0;
154         buffer->memory_->SetOffset(0);
155         buffer->memory_->SetSize(fuzzSize);
156         int32_t err = codec_->QueueInputBuffer(index);
157         if (err != AVCS_ERR_OK) {
158             cout << "QueueInputBuffer fail" << endl;
159             break;
160         }
161         sendFrameIndex++;
162     }
163 }
164 
WaitForEos()165 void VDecServerSample::WaitForEos()
166 {
167     if (inputLoop_ && inputLoop_->joinable()) {
168         inputLoop_->join();
169     }
170 }
171 
GetOutputFormat()172 void VDecServerSample::GetOutputFormat()
173 {
174     Format fmt;
175     int32_t err = codec_->GetOutputFormat(fmt);
176     if (err != AVCS_ERR_OK) {
177         cout << "GetOutputFormat fail" << endl;
178         isRunning_.store(false);
179         signal_->inCond_.notify_all();
180     }
181 }
182 
Flush()183 void VDecServerSample::Flush()
184 {
185     int32_t err = codec_->Flush();
186     if (err != AVCS_ERR_OK) {
187         cout << "Flush fail" << endl;
188         isRunning_.store(false);
189         signal_->inCond_.notify_all();
190     }
191 }
192 
Reset()193 void VDecServerSample::Reset()
194 {
195     int32_t err = codec_->Reset();
196     if (err != AVCS_ERR_OK) {
197         cout << "Reset fail" << endl;
198         isRunning_.store(false);
199         signal_->inCond_.notify_all();
200     }
201 }