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 
16 #ifndef FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_H
17 #define FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <fstream>
22 #include <vector>
23 
24 #include "metadata_stream.h"
25 
26 namespace OHOS {
27 namespace Media {
28 #if defined(FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_TESTS_PRIVATE)
29 #define FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_PRIVATE_UNLESS_TESTED public
30 #else
31 #define FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_PRIVATE_UNLESS_TESTED private
32 #endif
33 
34 /**
35  * @class BufferMetadataStream
36  * @brief A class for handling image streams in memory.
37  *
38  * This class provides methods for reading from and seeking within an image
39  * stream in memory.
40  */
41 class BufferMetadataStream : public MetadataStream {
42 public:
43     enum MemoryMode {
44         Fix,    // Memory is fixed at construction and cannot be changed
45         Dynamic // Memory can be changed
46     };
47 
48     /* *
49      * @brief Constructs a new BufferMetadataStream object.
50      */
51     BufferMetadataStream();
52 
53     /* *
54      * @brief Constructs a new BufferMetadataStream object with specified data, size and memory mode.
55      * @param originData The original data to be used for the BufferMetadataStream.
56      * @param size The size of the original data.
57      * @param mode The memory mode to be used for the BufferMetadataStream.
58      * @param originalFd The original file fd of buffer data.
59      * @param originalPath The original file path of buffer data.
60      */
61     BufferMetadataStream(byte *originData, size_t size, MemoryMode mode,
62                          int originalFd = METADATA_STREAM_INVALID_FD,
63                          const std::string &originalPath = METADATA_STREAM_INVALID_PATH);
64 
65     /* *
66      * @brief Destructs the BufferMetadataStream object.
67      */
68     virtual ~BufferMetadataStream();
69 
70     /* *
71      * @brief Writes data to the BufferMetadataStream.
72      * @param data The data to be written.
73      * @param size The size of the data. On a 32-bit system, the maximum size
74      * that can be written at once is 2GB or 4GB.
75      * @return The number of bytes written. Returns -1 if an error occurred
76      * during writing.
77      */
78     virtual ssize_t Write(uint8_t *data, ssize_t size) override;
79 
80     /* *
81      * @brief Reads data from the BufferMetadataStream.
82      * @param buf The buffer to store the data.
83      * @param size The size of the data.
84      * @return The number of bytes read. Returns -1 if the buffer pointer is null.
85      */
86     virtual ssize_t Read(uint8_t *buf, ssize_t size) override;
87 
88     /* *
89      * @brief Reads a byte from the BufferMetadataStream.
90      * @return The byte read.
91      */
92     virtual int ReadByte() override;
93 
94     /* *
95      * @brief Seeks to a specific position in the image stream.
96      * @param offset The offset to seek to. This can be positive or negative.
97      * @param pos The position to seek from. This can be the beginning, current position, or end of the stream.
98      * @return The new position in the stream. Returns -1 if an invalid seek position is provided.
99      */
100     virtual long Seek(long offset, SeekPos pos) override;
101 
102     /* *
103      * @brief Gets the current position in the BufferMetadataStream.
104      * @return The current position.
105      */
106     virtual long Tell() override;
107 
108     /* *
109      * @brief Checks if the end of the BufferMetadataStream has been reached.
110      * @return true if the end has been reached, false otherwise.
111      */
112     virtual bool IsEof() override;
113 
114     /* *
115      * @brief Checks if the BufferMetadataStream is open.
116      * @return true if it is open, false otherwise.
117      */
118     virtual bool IsOpen() override;
119 
120     /* *
121      * For BufferMetadataStream, the Open function with a mode is not applicable,
122      * as the data for BufferMetadataStream is already in memory and there are no
123      * read-only scenarios.
124      *
125      * @param mode This parameter is ignored, as there are no read-only
126      * scenarios for BufferMetadataStream.
127      * @return Returns false, as this function is not applicable for
128      * BufferMetadataStream.
129      */
130     virtual bool Open(OpenMode mode = OpenMode::ReadWrite) override;
131 
132     /* *
133      * For BufferMetadataStream, the Flush function is not applicable,
134      * as the data for BufferMetadataStream is already in memory and there are no
135      * write operations that need to be flushed.
136      *
137      * @return Returns true, as this function is not applicable for
138      * BufferMetadataStream, but it is assumed that the data is always "flushed" in
139      * memory.
140      */
141     virtual bool Flush() override;
142 
143     /* *
144      * @param isWriteable This parameter is ignored, the data of
145      * BufferMetadataStream is always writable.
146      * @return Returns a pointer to the data of BufferMetadataStream.
147      * The read/write characteristics of the memory pointed to by the
148      * returned addr pointer depend on whether it comes from managed
149      * memory or is allocated by itself. If it is self-allocated, it
150      * can be both read and written. If it is managed, it depends on
151      * the read/write properties of the managed memory.
152      */
153     virtual byte *GetAddr(bool isWriteable = false) override;
154 
155     /* *
156      * Transfer the content of the source MetadataStream to the current
157      * BufferMetadataStream. This function first clears the current buffer and sets
158      * the current offset to 0. Then, this function reads data from the source
159      * MetadataStream and appends the read data to the current buffer. If an error
160      * occurs during the reading process, this function will return immediately
161      * and log the error information.
162      *
163      * @param src The source MetadataStream, this function will read data from this
164      * MetadataStream.
165      */
166     virtual bool CopyFrom(MetadataStream &src) override;
167 
168     /* *
169      * Get the size of the BufferMetadataStream.
170      *
171      * @return Returns the size of the BufferMetadataStream.
172      */
173     virtual ssize_t GetSize() override;
174 
175     /* *
176      * Release the managed memory to the external.
177      *
178      * @return Returns the pointer to the released memory.
179      */
180     byte *Release();
181 
182 private:
183     /*
184      * These constants are used in conjunction with CalculateNewCapacity to quickly approximate potential image sizes.
185      * Based on the value of expandCount_, an appropriate capacity level is selected to optimize memory management and
186      * reduce memory copy operations, thereby enhancing the efficiency of image processing.
187      */
188     static constexpr long METADATA_STREAM_INITIAL_CAPACITY = METADATA_STREAM_PAGE_SIZE;
189     static constexpr long METADATA_STREAM_CAPACITY_512KB = 512 * 1024;
190     static constexpr long METADATA_STREAM_CAPACITY_2MB = 2 * 1024 * 1024;
191     static constexpr long METADATA_STREAM_CAPACITY_5MB = 5 * 1024 * 1024;
192     static constexpr long METADATA_STREAM_CAPACITY_15MB = 15 * 1024 * 1024;
193     static constexpr long METADATA_STREAM_CAPACITY_30MB = 30 * 1024 * 1024;
194 
195     static constexpr int INITIAL_EXPANSION = 0;
196     static constexpr int SECOND_EXPANSION = 1;
197     static constexpr int THIRD_EXPANSION = 2;
198     static constexpr int FOURTH_EXPANSION = 3;
199     static constexpr int FIFTH_EXPANSION = 4;
200 
201     static constexpr int METADATA_STREAM_MAX_CAPACITY = 1024 * 1024 * 1024;
202 
203     /* *
204      * @brief Closes the BufferImageStream.
205      */
206     virtual void Close() override;
207     bool ReadAndWriteData(MetadataStream &src);
208     void HandleWriteFailure();
209 
210     /* *
211      * @brief To handle memory read/write operations where the image size is often unknown, a fixed incremental
212      * growth approach would result in numerous memory copy operations. Considering that the current scenario
213      * involves processing images, a leapfrogging approach is used to quickly approximate potential image sizes,
214      * thereby reducing the number of memory copies.
215      * @param currentOffset The current offset in the BufferImageStream.
216      * @param size The size to be added to the BufferImageStream.
217      * @return The new capacity of the BufferImageStream.
218      */
219     long CalculateNewCapacity(long currentOffset, ssize_t size);
220 
221     /* *
222      * @brief Tracks the number of capacity expansions to facilitate the leapfrogging approach in capacity calculation.
223      * This count helps in selecting the appropriate predefined capacity level during memory allocation for image
224      * processing, optimizing the approach to quickly approximate potential image sizes and reduce memory copy
225      * operations.
226      */
227     int expandCount_ = 0;
228 
229     /* *
230      * @brief The memory buffer of the BufferImageStream.
231      */
232     byte *buffer_;
233 
234     /* *
235      * @brief The original pointer saved when constructed with originData.
236      * It is needed when closing to determine whether to release the buffer.
237      */
238     byte *originData_;
239 
240     /* *
241      * @brief The pre-allocated memory capacity of the buffer.
242      */
243     long capacity_;
244 
245     /* *
246      * @brief The data size of the buffer.
247      * Since it is in memory, bufferSize will not exceed the maximum length of
248      * memory, so size_t is not used here.
249      */
250     long bufferSize_;
251 
252     /* *
253      * @brief The current offset in the BufferImageStream.
254      */
255     long currentOffset_;
256 
257     /* *
258      * @brief The memory mode, which can be fixed memory or dynamic memory.
259      * See MemoryMode for details.
260      */
261     MemoryMode memoryMode_;
262 };
263 } // namespace Media
264 } // namespace OHOS
265 #endif // FRAMEWORKS_INNERKITSIMPL_ACCESSOR_INCLUDE_BUFFER_METADATA_STREAM_H
266