1 /*
2  * Copyright (c) 2023 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 
16 #ifndef VCODEC_SIGNAL_H
17 #define VCODEC_SIGNAL_H
18 #include <atomic>
19 #include <memory>
20 #include <mutex>
21 #include <pthread.h>
22 #include <queue>
23 #include <string>
24 #include <thread>
25 #include "native_avbuffer.h"
26 #include "native_avformat.h"
27 #include "native_avmemory.h"
28 
29 namespace OHOS {
30 namespace MediaAVCodec {
31 template <typename T>
32 class VCodecSignal {
33 public:
VCodecSignal(std::shared_ptr<T> codec)34     explicit VCodecSignal(std::shared_ptr<T> codec) : codec_(codec) {}
~VCodecSignal()35     ~VCodecSignal()
36     {
37         if (outFile_ != nullptr && outFile_->is_open()) {
38             outFile_->close();
39         }
40         if (inFile_ != nullptr && inFile_->is_open()) {
41             inFile_->close();
42         }
43     }
44     std::mutex eosMutex_;
45     std::condition_variable eosCond_;
46     std::atomic<bool> isInEos_ = false;
47     std::atomic<bool> isOutEos_ = false;
48 
49     std::mutex inMutex_;
50     std::condition_variable inCond_;
51     std::queue<uint32_t> inQueue_;
52     std::queue<OH_AVMemory *> inMemoryQueue_;
53     std::queue<OH_AVBuffer *> inBufferQueue_;
54 
55     std::mutex outMutex_;
56     std::condition_variable outCond_;
57     std::queue<uint32_t> outQueue_;
58     std::queue<OH_AVCodecBufferAttr> outAttrQueue_;
59     std::queue<OH_AVMemory *> outMemoryQueue_;
60     std::queue<OH_AVBuffer *> outBufferQueue_;
61 
62     std::vector<int32_t> errors_;
63     std::atomic<int32_t> controlNum_ = 0;
64     std::atomic<bool> isRunning_ = false;
65     std::atomic<bool> isFlushing_ = false;
66 
67     std::unique_ptr<std::ifstream> inFile_;
68     std::unique_ptr<std::ofstream> outFile_;
69     std::weak_ptr<T> codec_;
70 
PopInQueue()71     void PopInQueue()
72     {
73         if (!inQueue_.empty()) {
74             inQueue_.pop();
75         }
76         if (!inMemoryQueue_.empty()) {
77             inMemoryQueue_.pop();
78         }
79         if (!inBufferQueue_.empty()) {
80             inBufferQueue_.pop();
81         }
82     }
83 
PopOutQueue()84     void PopOutQueue()
85     {
86         if (!outQueue_.empty()) {
87             outQueue_.pop();
88         }
89         if (!outAttrQueue_.empty()) {
90             outAttrQueue_.pop();
91         }
92         if (!outMemoryQueue_.empty()) {
93             outMemoryQueue_.pop();
94         }
95         if (!outBufferQueue_.empty()) {
96             outBufferQueue_.pop();
97         }
98     }
99 };
100 
101 template <typename T>
102 class FlushGuard {
103 public:
FlushGuard(std::shared_ptr<T> signal)104     explicit FlushGuard(std::shared_ptr<T> signal)
105     {
106         if (signal == nullptr) {
107             return;
108         }
109         signal_ = signal;
110         signal_->isFlushing_ = true;
111         signal_->inCond_.notify_all();
112         signal_->outCond_.notify_all();
113         {
114             std::scoped_lock lock(signal_->inMutex_, signal_->outMutex_);
115             FlushInQueue();
116             FlushOutQueue();
117         }
118     }
119 
~FlushGuard()120     ~FlushGuard()
121     {
122         if (signal_ == nullptr) {
123             return;
124         }
125         signal_->isFlushing_ = false;
126         signal_->inCond_.notify_all();
127         signal_->outCond_.notify_all();
128     }
129 
130 private:
FlushInQueue()131     void FlushInQueue()
132     {
133         std::queue<uint32_t> tempIndex;
134         swap(tempIndex, signal_->inQueue_);
135         std::queue<OH_AVMemory *> tempInMemory;
136         swap(tempInMemory, signal_->inMemoryQueue_);
137         std::queue<OH_AVBuffer *> tempInBuffer;
138         swap(tempInBuffer, signal_->inBufferQueue_);
139     }
140 
FlushOutQueue()141     void FlushOutQueue()
142     {
143         std::queue<uint32_t> tempIndex;
144         swap(tempIndex, signal_->outQueue_);
145         std::queue<OH_AVCodecBufferAttr> tempOutAttr;
146         swap(tempOutAttr, signal_->outAttrQueue_);
147         std::queue<OH_AVMemory *> tempOutMemory;
148         swap(tempOutMemory, signal_->outMemoryQueue_);
149         std::queue<OH_AVBuffer *> tempOutBuffer;
150         swap(tempOutBuffer, signal_->outBufferQueue_);
151     }
152     std::shared_ptr<T> signal_ = nullptr;
153 };
154 } // namespace MediaAVCodec
155 } // namespace OHOS
156 #endif // VCODEC_SIGNAL_H