1 /*
2  * Copyright (C) 2022 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 #include "istream_source_stream.h"
17 
18 #include "image_log.h"
19 #include "image_utils.h"
20 
21 #undef LOG_DOMAIN
22 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
23 
24 #undef LOG_TAG
25 #define LOG_TAG "IstreamSourceStream"
26 
27 namespace OHOS {
28 namespace Media {
29 using namespace std;
30 using namespace ImagePlugin;
31 
IstreamSourceStream(unique_ptr<istream> inputStream,size_t size,size_t original,size_t offset)32 IstreamSourceStream::IstreamSourceStream(unique_ptr<istream> inputStream, size_t size, size_t original, size_t offset)
33     : inputStream_(move(inputStream)), streamSize_(size), streamOriginalOffset_(original), streamOffset_(offset)
34 {}
35 
~IstreamSourceStream()36 IstreamSourceStream::~IstreamSourceStream()
37 {
38     ResetReadBuffer();
39 }
40 
CreateSourceStream(unique_ptr<istream> inputStream)41 std::unique_ptr<IstreamSourceStream> IstreamSourceStream::CreateSourceStream(unique_ptr<istream> inputStream)
42 {
43     if ((inputStream == nullptr) || (inputStream->rdbuf() == nullptr) ||
44         inputStream.get() == nullptr) {
45         IMAGE_LOGE("[IstreamSourceStream]input parameter exception.");
46         return nullptr;
47     }
48     size_t streamSize = 0;
49     if (!ImageUtils::GetInputStreamSize(*(inputStream.get()), streamSize)) {
50         IMAGE_LOGE("[IstreamSourceStream]Get the input stream exception.");
51         return nullptr;
52     }
53     if (streamSize == 0) {
54         IMAGE_LOGE("[IstreamSourceStream]input stream size exception.");
55         return nullptr;
56     }
57     size_t original = inputStream->tellg();
58     size_t offset = original;
59     return make_unique<IstreamSourceStream>(move(inputStream), streamSize, original, offset);
60 }
61 
Read(uint32_t desiredSize,DataStreamBuffer & outData)62 bool IstreamSourceStream::Read(uint32_t desiredSize, DataStreamBuffer &outData)
63 {
64     if (desiredSize == 0) {
65         IMAGE_LOGE("[IstreamSourceStream]read stream input parameter exception.");
66         return false;
67     }
68     if (!GetData(desiredSize, outData)) {
69         IMAGE_LOGE("[IstreamSourceStream]read fail.");
70         return false;
71     }
72     streamOffset_ += outData.dataSize;
73     return true;
74 }
75 
Peek(uint32_t desiredSize,DataStreamBuffer & outData)76 bool IstreamSourceStream::Peek(uint32_t desiredSize, DataStreamBuffer &outData)
77 {
78     if (desiredSize == 0) {
79         IMAGE_LOGE("[IstreamSourceStream]peek stream input parameter exception.");
80         return false;
81     }
82     if (!GetData(desiredSize, outData)) {
83         IMAGE_LOGE("[IstreamSourceStream]peek fail.");
84         return false;
85     }
86     inputStream_->seekg(streamOffset_);
87     return true;
88 }
89 
Read(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)90 bool IstreamSourceStream::Read(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
91 {
92     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize) {
93         IMAGE_LOGE("[IstreamSourceStream]input the parameter exception, desiredSize:%{public}u,"
94             "bufferSize:%{public}u.", desiredSize, bufferSize);
95         return false;
96     }
97     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
98         IMAGE_LOGE("[IstreamSourceStream]read fail.");
99         return false;
100     }
101     streamOffset_ += readSize;
102     return true;
103 }
104 
Peek(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)105 bool IstreamSourceStream::Peek(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
106 {
107     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize) {
108         IMAGE_LOGE("[IstreamSourceStream]input the parameter exception, desiredSize:%{public}u,"
109             "bufferSize:%{public}u.", desiredSize, bufferSize);
110         return false;
111     }
112     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
113         IMAGE_LOGE("[IstreamSourceStream]peek fail.");
114         return false;
115     }
116     inputStream_->seekg(streamOffset_);
117     return true;
118 }
119 
Seek(uint32_t position)120 bool IstreamSourceStream::Seek(uint32_t position)
121 {
122     if (position > streamSize_) {
123         IMAGE_LOGE("[IstreamSourceStream]Seek the position error, position:%{public}u,"
124             "streamSize_:%{public}zu.", position, streamSize_);
125         return false;
126     }
127     size_t targetPosition = position + streamOriginalOffset_;
128     streamOffset_ = ((targetPosition < streamSize_) ? targetPosition : streamSize_);
129     inputStream_->seekg(streamOffset_);
130     return true;
131 }
132 
Tell()133 uint32_t IstreamSourceStream::Tell()
134 {
135     return streamOffset_;
136 }
137 
GetData(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)138 bool IstreamSourceStream::GetData(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
139 {
140     if (streamSize_ == 0 || streamOffset_ >= streamSize_) {
141         IMAGE_LOGE("[IstreamSourceStream]get source data fail. streamSize:%{public}zu,"
142             "streamOffset:%{public}zu.", streamSize_, streamOffset_);
143         return false;
144     }
145     if (desiredSize > (streamSize_ - streamOffset_)) {
146         desiredSize = (streamSize_ - streamOffset_);
147     }
148     if (!inputStream_->read(reinterpret_cast<char *>(outBuffer), desiredSize)) {
149         IMAGE_LOGE("[IstreamSourceStream]read the inputstream fail.");
150         return false;
151     }
152     readSize = desiredSize;
153     return true;
154 }
155 
GetData(uint32_t desiredSize,DataStreamBuffer & outData)156 bool IstreamSourceStream::GetData(uint32_t desiredSize, DataStreamBuffer &outData)
157 {
158     if (streamSize_ == 0 || streamOffset_ >= streamSize_) {
159         IMAGE_LOGE("[IstreamSourceStream]get source data fail. streamSize:%{public}zu,"
160             "streamOffset:%{public}zu.", streamSize_, streamOffset_);
161         return false;
162     }
163 
164     if (desiredSize == 0 || desiredSize > MALLOC_MAX_LENTH) {
165         IMAGE_LOGE("IstreamSourceStream]Invalid value, desiredSize out of size.");
166         return false;
167     }
168     ResetReadBuffer();
169     databuffer_ = static_cast<uint8_t *>(malloc(desiredSize));
170     if (databuffer_ == nullptr) {
171         IMAGE_LOGE("[IstreamSourceStream]malloc the output data buffer fail.");
172         return false;
173     }
174     outData.bufferSize = desiredSize;
175     if (desiredSize > (streamSize_ - streamOffset_)) {
176         desiredSize = (streamSize_ - streamOffset_);
177     }
178     inputStream_->seekg(streamOffset_);
179     if (!inputStream_->read(reinterpret_cast<char *>(databuffer_), desiredSize)) {
180         IMAGE_LOGE("[IstreamSourceStream]read the inputstream fail.");
181         free(databuffer_);
182         databuffer_ = nullptr;
183         return false;
184     }
185     outData.inputStreamBuffer = databuffer_;
186     outData.dataSize = desiredSize;
187     return true;
188 }
189 
GetStreamSize()190 size_t IstreamSourceStream::GetStreamSize()
191 {
192     return streamSize_;
193 }
194 
GetDataPtr()195 uint8_t *IstreamSourceStream::GetDataPtr()
196 {
197     return nullptr;
198 }
199 
GetStreamType()200 uint32_t IstreamSourceStream::GetStreamType()
201 {
202     return ImagePlugin::INPUT_STREAM_TYPE;
203 }
204 
ResetReadBuffer()205 void IstreamSourceStream::ResetReadBuffer()
206 {
207     if (databuffer_ != nullptr) {
208         free(databuffer_);
209         databuffer_ = nullptr;
210     }
211 }
212 } // namespace Media
213 } // namespace OHOS
214