1 /*
2  * Copyright (c) 2021-2021 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 HISTREAMER_DATA_PACKER_H
17 #define HISTREAMER_DATA_PACKER_H
18 
19 #include <atomic>
20 #include <deque>
21 #include <vector>
22 
23 #include "foundation/osal/thread/mutex.h"
24 #include "foundation/osal/thread/scoped_lock.h"
25 #include "pipeline/core/type_define.h"
26 
27 namespace OHOS {
28 namespace Media {
29 class DataPacker {
30 public:
31     DataPacker();
32 
33     ~DataPacker();
34 
35     DataPacker(const DataPacker& other) = delete;
36 
37     DataPacker& operator=(const DataPacker& other) = delete;
38 
39     void PushData(AVBufferPtr bufferPtr, uint64_t offset);
40 
41     bool IsDataAvailable(uint64_t offset, uint32_t size, uint64_t &curOffset);
42 
43     bool PeekRange(uint64_t offset, uint32_t size, AVBufferPtr &bufferPtr);
44 
45     bool GetRange(uint64_t offset, uint32_t size, AVBufferPtr &bufferPtr);
46 
47     bool GetRange(uint32_t size, AVBufferPtr &bufferPtr); // For live play
48 
49     void Flush();
50 
51     void SetEos();
52 
53     bool IsEmpty();
54 
55     void Start();
56 
57     void Stop();
58 
59     // Record the position that GerRange copy start or end.
60     struct Position {
61         int32_t index; // Buffer index, -1 means this Position is invalid
62         uint32_t bufferOffset; // Offset in the buffer
63         uint64_t mediaOffset;  // Offset in the media file
64 
PositionPosition65         Position(int32_t index, uint32_t bufferOffset, uint64_t mediaOffset) noexcept
66         {
67             this->index = index;
68             this->bufferOffset = bufferOffset;
69             this->mediaOffset = mediaOffset;
70         }
71 
72         bool operator < (const Position& other) const
73         {
74             if (index < 0 || other.index < 0) { // Position invalid
75                 return false;
76             }
77             if (index != other.index) {
78                 return index < other.index;
79             }
80             return bufferOffset < other.bufferOffset; // use bufferOffset, maybe live play mediaOffset is invalid
81         }
82 
ToStringPosition83         std::string ToString() const
84         {
85             return "Position (index " + std::to_string(index) + ", bufferOffset " + std::to_string(bufferOffset) +
86                 ", mediaOffset " + std::to_string(mediaOffset);
87         }
88     };
89 
90 private:
91     void RemoveBufferContent(std::shared_ptr<AVBuffer> &buffer, size_t removeSize);
92 
93     bool PeekRangeInternal(uint64_t offset, uint32_t size, AVBufferPtr &bufferPtr, bool isGet);
94 
95     void FlushInternal();
96 
97     bool FindFirstBufferToCopy(uint64_t offset, int32_t &startIndex, uint64_t &prevOffset);
98 
99     size_t CopyFirstBuffer(size_t size, int32_t index, uint8_t *dstPtr, AVBufferPtr &dstBufferPtr,
100                            int32_t bufferOffset);
101 
102     int32_t CopyFromSuccessiveBuffer(uint64_t prevOffset, uint64_t offsetEnd, int32_t startIndex, uint8_t *dstPtr,
103                                      uint32_t &needCopySize);
104 
105     void RemoveOldData(const Position& position);
106 
107     bool RemoveTo(const Position& position);
108 
109     bool UpdateWhenFrontDataRemoved(size_t removeSize);
110 
111     std::string ToString() const;
112 
113     OSAL::Mutex mutex_;
114     std::deque<AVBufferPtr> que_;
115     std::atomic<uint32_t> size_;
116     uint64_t mediaOffset_; // The media file offset of the first byte in data packer
117     uint64_t pts_;
118     uint64_t dts_;
119     bool isEos_ {false};
120 
121     // The position in prev GetRange / current GetRange
122     Position prevGet_ ;
123     Position currentGet_ ;
124 
125     OSAL::ConditionVariable cvFull_;
126     OSAL::ConditionVariable cvEmpty_;
127     const size_t capacity_;
128     std::atomic<bool> stopped_ {false};
129 };
130 } // namespace Media
131 } // namespace OHOS
132 #endif // HISTREAMER_DATA_PACKER_H
133