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 16 #ifndef CODEC_BUFFER_CIRCULAR_H 17 #define CODEC_BUFFER_CIRCULAR_H 18 19 #include <queue> 20 #include <shared_mutex> 21 #include <string> 22 #include "avcodec_common.h" 23 #include "avcodec_dfx_component.h" 24 25 namespace OHOS { 26 namespace MediaAVCodec { 27 class BufferConverter; 28 class CodecBufferCircular : public AVCodecDfxComponent { 29 public: 30 CodecBufferCircular() = default; 31 ~CodecBufferCircular(); 32 33 // Configure circular 34 void SetConverter(std::shared_ptr<BufferConverter> &converter); 35 int32_t SetCallback(const std::shared_ptr<AVCodecCallback> &callback); 36 int32_t SetCallback(const std::shared_ptr<MediaCodecCallback> &callback); 37 int32_t SetCallback(const std::shared_ptr<MediaCodecParameterCallback> &callback); 38 int32_t SetCallback(const std::shared_ptr<MediaCodecParameterWithAttrCallback> &callback); 39 40 void SetIsRunning(bool isRunning); 41 bool CanEnableSyncMode(); 42 bool CanEnableAsyncMode(); 43 void EnableSyncMode(); 44 void EnableAsyncMode(); 45 bool IsSyncMode(); 46 void ResetFlag(); 47 48 // Caches 49 void ClearCaches(); 50 void FlushCaches(); 51 52 // Sycn mode interface 53 int32_t QueryInputBuffer(uint32_t &index, int64_t timeoutUs); 54 int32_t QueryOutputBuffer(uint32_t &index, int64_t timeoutUs); 55 std::shared_ptr<AVBuffer> GetInputBuffer(uint32_t index); 56 std::shared_ptr<AVBuffer> GetOutputBuffer(uint32_t index); 57 58 // Handle buffer before send to proxy 59 int32_t HandleInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag); 60 int32_t HandleInputBuffer(uint32_t index); 61 int32_t HandleOutputBuffer(uint32_t index); 62 void QueueInputBufferDone(uint32_t index); 63 void ReleaseOutputBufferDone(uint32_t index); 64 void NotifyEos(); 65 66 // Callback 67 void OnError(AVCodecErrorType errorType, int32_t errorCode); 68 void OnOutputFormatChanged(const Format &format); 69 void OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer); 70 void OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer); 71 void OnOutputBufferBinded(std::map<uint32_t, sptr<SurfaceBuffer>> &bufferMap); 72 void OnOutputBufferUnbinded(); 73 74 private: 75 typedef enum : uint8_t { 76 FLAG_NONE = 0, 77 FLAG_IS_RUNNING = 1 << 0, 78 FLAG_IS_SYNC = 1 << 1, 79 FLAG_SYNC_ASYNC_CONFIGURED = 1 << 2, 80 FLAG_ERROR = 1 << 3, 81 FLAG_INPUT_EOS = 1 << 4, 82 FLAG_OUTPUT_EOS = 1 << 5, 83 } CodecCircularFlag; 84 typedef enum : uint8_t { 85 OWNED_BY_SERVER = 0, 86 OWNED_BY_CLIENT = 1, 87 OWNED_BY_USER = 2, 88 } BufferOwner; 89 90 typedef enum : uint8_t { 91 MODE_ASYNC, 92 MODE_SYNC, 93 } ModeType; 94 95 typedef struct BufferItem { 96 std::shared_ptr<AVBuffer> buffer = nullptr; 97 std::shared_ptr<AVSharedMemory> memory = nullptr; 98 std::shared_ptr<Format> parameter = nullptr; 99 std::shared_ptr<Format> attribute = nullptr; 100 BufferOwner owner = OWNED_BY_SERVER; 101 102 // Used in QueueInputBuffer/ReleaseOutputBuffer 103 uint32_t flag = 0; 104 int32_t size = 0; 105 int64_t pts = 0; 106 } BufferItem; 107 using BufferCache = std::unordered_map<uint32_t, BufferItem>; 108 using BufferCacheIter = BufferCache::iterator; 109 110 // Common 111 static std::shared_ptr<Format> GetParameter(BufferCacheIter &iter); 112 static std::shared_ptr<Format> GetAttribute(BufferCacheIter &iter); 113 static const std::string &OwnerToString(BufferOwner owner); 114 void PrintCaches(bool isOutput); 115 void ClearOutputBufferOwnedByCodec(); 116 bool HasFlag(const CodecCircularFlag flag); 117 void AddFlag(const CodecCircularFlag flag); 118 void RemoveFlag(const CodecCircularFlag flag); 119 120 template <ModeType mode> CanEnableMode()121 inline bool CanEnableMode() 122 { 123 bool isUnconfigured = !(flags_ & FLAG_SYNC_ASYNC_CONFIGURED); 124 bool modeMatched = !(flags_ & FLAG_IS_SYNC); 125 if constexpr (mode == MODE_SYNC) { 126 modeMatched = (flags_ & FLAG_IS_SYNC); 127 } 128 return isUnconfigured || modeMatched; 129 } 130 131 template <ModeType mode> EnableMode()132 inline void EnableMode() 133 { 134 if constexpr (mode == MODE_SYNC) { 135 flags_ |= FLAG_IS_SYNC; 136 } 137 flags_ |= FLAG_SYNC_ASYNC_CONFIGURED; 138 } 139 140 BufferCache inCache_; 141 BufferCache outCache_; 142 std::mutex inMutex_; 143 std::mutex outMutex_; 144 std::atomic<uint8_t> flags_ = FLAG_NONE; 145 146 // Async mode 147 void AsyncOnError(AVCodecErrorType errorType, int32_t errorCode); 148 void AsyncOnOutputFormatChanged(const Format &format); 149 void AsyncOnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> &buffer); 150 void AsyncOnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> &buffer); 151 void ConvertToSharedMemory(const std::shared_ptr<AVBuffer> &buffer, std::shared_ptr<AVSharedMemory> &memory); 152 153 std::shared_ptr<AVCodecCallback> callback_ = nullptr; 154 std::shared_ptr<MediaCodecCallback> mediaCb_ = nullptr; 155 std::shared_ptr<MediaCodecParameterCallback> paramCb_ = nullptr; 156 std::shared_ptr<MediaCodecParameterWithAttrCallback> attrCb_ = nullptr; 157 std::shared_ptr<BufferConverter> converter_ = nullptr; 158 159 // Sync mode 160 typedef enum : uint8_t { 161 EVENT_UNKNOWN, 162 EVENT_OUTPUT_BUFFER, 163 EVENT_INPUT_BUFFER, 164 EVENT_STREAM_CHANGED, 165 } EventType; 166 typedef struct Event { 167 EventType type = EVENT_UNKNOWN; 168 uint32_t index = 0; 169 } Event; 170 using EventQueue = std::queue<Event>; 171 172 void SyncOnError(AVCodecErrorType errorType, int32_t errorCode); 173 void SyncOnOutputFormatChanged(const Format &format); 174 void SyncOnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> &buffer); 175 void SyncOnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> &buffer); 176 int32_t QueryInputIndex(uint32_t &index, int64_t timeoutUs); 177 int32_t QueryOutputIndex(uint32_t &index, int64_t timeoutUs); 178 bool WaitForInputBuffer(std::unique_lock<std::mutex> &lock, int64_t timeoutUs); 179 bool WaitForOutputBuffer(std::unique_lock<std::mutex> &lock, int64_t timeoutUs); 180 181 std::condition_variable inCond_; 182 std::condition_variable outCond_; 183 EventQueue inQueue_; 184 EventQueue outQueue_; 185 int32_t lastError_ = 0; 186 }; 187 } // namespace MediaAVCodec 188 } // namespace OHOS 189 #endif