• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include <unistd.h>
17 #include "image_log.h"
18 #include "image_utils.h"
19 #include "media_errors.h"
20 #include "directory_ex.h"
21 #include "file_source_stream.h"
22 
23 namespace OHOS {
24 namespace Media {
25 using namespace OHOS::HiviewDFX;
26 using namespace std;
27 using namespace ImagePlugin;
28 
FileSourceStream(std::FILE * file,size_t size,size_t offset,size_t original)29 FileSourceStream::FileSourceStream(std::FILE *file, size_t size, size_t offset, size_t original)
30     : filePtr_(file), fileSize_(size), fileOffset_(offset), fileOriginalOffset_(original)
31 {}
32 
~FileSourceStream()33 FileSourceStream::~FileSourceStream()
34 {
35     fclose(filePtr_);
36     ResetReadBuffer();
37 }
38 
CreateSourceStream(const string & pathName)39 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const string &pathName)
40 {
41     string realPath;
42     if (!PathToRealPath(pathName, realPath)) {
43         IMAGE_LOGE("[FileSourceStream]input the file path exception.");
44         return nullptr;
45     }
46     size_t size = 0;
47     if (!ImageUtils::GetFileSize(realPath, size)) {
48         IMAGE_LOGE("[FileSourceStream]get the file size fail.");
49         return nullptr;
50     }
51     FILE *filePtr = fopen(realPath.c_str(), "rb");
52     if (filePtr == nullptr) {
53         IMAGE_LOGE("[FileSourceStream]open file fail.");
54         return nullptr;
55     }
56     int64_t offset = ftell(filePtr);
57     if (offset < 0) {
58         IMAGE_LOGE("[FileSourceStream]get the position fail.");
59         fclose(filePtr);
60         return nullptr;
61     }
62     return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
63 }
64 
CreateSourceStream(const int fd)65 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const int fd)
66 {
67     size_t size = 0;
68 
69     int dupFd = dup(fd);
70     if (dupFd < 0) {
71         IMAGE_LOGE("[FileSourceStream]Fail to dup fd.");
72         return nullptr;
73     }
74 
75     if (!ImageUtils::GetFileSize(dupFd, size)) {
76         IMAGE_LOGE("[FileSourceStream]get the file size fail.");
77         return nullptr;
78     }
79     FILE *filePtr = fdopen(dupFd, "rb");
80     if (filePtr == nullptr) {
81         IMAGE_LOGE("[FileSourceStream]open file fail.");
82         return nullptr;
83     }
84 
85     int ret = fseek(filePtr, 0, SEEK_SET);
86     if (ret != 0) {
87         IMAGE_LOGE("[FileSourceStream]Go to 0 position fail, ret:%{public}d.", ret);
88     }
89 
90     int64_t offset = ftell(filePtr);
91     if (offset < 0) {
92         IMAGE_LOGE("[FileSourceStream]get the position fail.");
93         fclose(filePtr);
94         return nullptr;
95     }
96     return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
97 }
98 
Read(uint32_t desiredSize,DataStreamBuffer & outData)99 bool FileSourceStream::Read(uint32_t desiredSize, DataStreamBuffer &outData)
100 {
101     if (desiredSize == 0 || filePtr_ == nullptr) {
102         IMAGE_LOGE("[FileSourceStream]read stream input parameter exception.");
103         return false;
104     }
105     if (!GetData(desiredSize, outData)) {
106         IMAGE_LOGE("[FileSourceStream]read fail.");
107         return false;
108     }
109     fileOffset_ += outData.dataSize;
110     return true;
111 }
112 
Peek(uint32_t desiredSize,DataStreamBuffer & outData)113 bool FileSourceStream::Peek(uint32_t desiredSize, DataStreamBuffer &outData)
114 {
115     if (desiredSize == 0 || filePtr_ == nullptr) {
116         IMAGE_LOGE("[FileSourceStream]peek stream input parameter exception.");
117         return false;
118     }
119     if (!GetData(desiredSize, outData)) {
120         IMAGE_LOGE("[FileSourceStream]peek fail.");
121         return false;
122     }
123     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
124     if (ret != 0) {
125         IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
126         return false;
127     }
128     return true;
129 }
130 
Read(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)131 bool FileSourceStream::Read(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
132 {
133     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
134         IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
135                    fileSize_:%{public}zu.",
136                    desiredSize, bufferSize, fileSize_);
137         return false;
138     }
139     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
140         IMAGE_LOGE("[FileSourceStream]read fail.");
141         return false;
142     }
143     fileOffset_ += readSize;
144     return true;
145 }
146 
Peek(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)147 bool FileSourceStream::Peek(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
148 {
149     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
150         IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
151                    fileSize_:%{public}zu.",
152                    desiredSize, bufferSize, fileSize_);
153         return false;
154     }
155     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
156         IMAGE_LOGE("[FileSourceStream]peek fail.");
157         return false;
158     }
159     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
160     if (ret != 0) {
161         IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
162         return false;
163     }
164     return true;
165 }
166 
Seek(uint32_t position)167 bool FileSourceStream::Seek(uint32_t position)
168 {
169     if (position > fileSize_) {
170         IMAGE_LOGE("[FileSourceStream]Seek the position greater than the file size, position:%{public}u.", position);
171         return false;
172     }
173     size_t targetPosition = position + fileOriginalOffset_;
174     fileOffset_ = ((targetPosition < fileSize_) ? targetPosition : fileSize_);
175     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
176     if (ret != 0) {
177         IMAGE_LOGE("[FileSourceStream]go to offset position fail, ret:%{public}d.", ret);
178         return false;
179     }
180     return true;
181 }
182 
Tell()183 uint32_t FileSourceStream::Tell()
184 {
185     return fileOffset_;
186 }
187 
GetData(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)188 bool FileSourceStream::GetData(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
189 {
190     if (fileSize_ == fileOffset_) {
191         IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
192         return false;
193     }
194     if (desiredSize > (fileSize_ - fileOffset_)) {
195         desiredSize = fileSize_ - fileOffset_;
196     }
197     size_t bytesRead = fread(outBuffer, sizeof(outBuffer[0]), desiredSize, filePtr_);
198     if (bytesRead < desiredSize) {
199         IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
200         return false;
201     }
202     readSize = desiredSize;
203     return true;
204 }
205 
GetData(uint32_t desiredSize,DataStreamBuffer & outData)206 bool FileSourceStream::GetData(uint32_t desiredSize, DataStreamBuffer &outData)
207 {
208     if (fileSize_ == fileOffset_) {
209         IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
210         return false;
211     }
212 
213     if (desiredSize == 0 || desiredSize > MALLOC_MAX_LENTH) {
214         IMAGE_LOGE("[FileSourceStream]Invalid value, desiredSize out of size.");
215         return false;
216     }
217 
218     ResetReadBuffer();
219     readBuffer_ = static_cast<uint8_t *>(malloc(desiredSize));
220     if (readBuffer_ == nullptr) {
221         IMAGE_LOGE("[FileSourceStream]malloc the desiredSize fail.");
222         return false;
223     }
224     outData.bufferSize = desiredSize;
225     if (desiredSize > (fileSize_ - fileOffset_)) {
226         desiredSize = fileSize_ - fileOffset_;
227     }
228     size_t bytesRead = fread(readBuffer_, sizeof(uint8_t), desiredSize, filePtr_);
229     if (bytesRead < desiredSize) {
230         IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
231         free(readBuffer_);
232         readBuffer_ = nullptr;
233         return false;
234     }
235     outData.inputStreamBuffer = static_cast<uint8_t *>(readBuffer_);
236     outData.dataSize = desiredSize;
237     return true;
238 }
239 
GetStreamSize()240 size_t FileSourceStream::GetStreamSize()
241 {
242     return fileSize_;
243 }
244 
GetDataPtr()245 uint8_t *FileSourceStream::GetDataPtr()
246 {
247     return nullptr;
248 }
249 
GetStreamType()250 uint32_t FileSourceStream::GetStreamType()
251 {
252     return ImagePlugin::FILE_STREAM_TYPE;
253 }
254 
ResetReadBuffer()255 void FileSourceStream::ResetReadBuffer()
256 {
257     if (readBuffer_ != nullptr) {
258         free(readBuffer_);
259         readBuffer_ = nullptr;
260     }
261 }
262 } // namespace Media
263 } // namespace OHOS
264