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