• 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 "raw_maker.h"
17 
18 #include <cerrno>
19 #include <string>
20 
21 #include <gslogger.h>
22 #include <securec.h>
23 #include <zlib.h>
24 
25 namespace OHOS {
26 namespace {
27 DEFINE_HILOG_LABEL("RawMaker");
28 } // namespace
29 
SetFilename(const std::string & filename)30 void RawMaker::SetFilename(const std::string &filename)
31 {
32     if (firstFrame) {
33         this->filename = filename;
34     }
35     if (this->filename != filename) {
36         GSLOG2HI(ERROR) << "RawMaker::SetFilename now filename is different to first frame filename";
37     }
38 }
39 
SetWidth(uint32_t width)40 void RawMaker::SetWidth(uint32_t width)
41 {
42     if (firstFrame) {
43         this->width = width;
44     }
45     if (this->width != width) {
46         GSLOG2HI(ERROR) << "RawMaker::SetWidth now width is different to first frame width";
47     }
48     size = static_cast<int32_t>(width * height * 0x4);
49 }
50 
SetHeight(uint32_t height)51 void RawMaker::SetHeight(uint32_t height)
52 {
53     if (firstFrame) {
54         this->height = height;
55     }
56     if (this->height != height) {
57         GSLOG2HI(ERROR) << "RawMaker::SetHeight now height is different to first frame height";
58     }
59     size = static_cast<int32_t>(width * height * 0x4);
60 }
61 
SetHeaderType(RawHeaderType type)62 void RawMaker::SetHeaderType(RawHeaderType type)
63 {
64     this->type = type;
65     if (type != RAW_HEADER_TYPE_NONE) {
66         GSLOG2HI(ERROR) << "RawMaker::SetHeaderType now type is not RAW_HEADER_TYPE_NONE";
67     }
68 }
69 
WriteNextData(const uint8_t * addr)70 int32_t RawMaker::WriteNextData(const uint8_t *addr)
71 {
72     int32_t ret = 0;
73     if (firstFrame) {
74         ret = DoFirstFrame();
75         writing.offset = 0;
76         writing.length = size;
77     } else {
78         CompareWithLastFrame(addr);
79     }
80 
81     ofs.open(filename, std::ofstream::app | std::ofstream::binary | std::ofstream::out);
82     if (errno) {
83         GSLOG2HI(ERROR) << "open " << filename << ", because " << strerror(errno);
84         return errno;
85     }
86 
87     if (writing.length == 0) {
88         ret = PrepareInNone();
89     } else if (type == RAW_HEADER_TYPE_RAW) {
90         ret = PrepareInRaw(addr);
91     } else if (type == RAW_HEADER_TYPE_COMPRESSED) {
92         ret = PrepareInCompress(addr);
93     }
94 
95     if (ret) {
96         GSLOG2SO(ERROR) << "failed at prepare";
97         ofs.close();
98         return ret;
99     }
100 
101     WriteData();
102     ofs.close();
103     return 0;
104 }
105 
PrepareInNone()106 int32_t RawMaker::PrepareInNone()
107 {
108     writing.type = RAW_HEADER_TYPE_NONE;
109     writing.offset = 0;
110     writing.length = 0;
111     writing.compressedLength = 0;
112     writing.data = nullptr;
113     return 0;
114 }
115 
PrepareInRaw(const uint8_t * addr)116 int32_t RawMaker::PrepareInRaw(const uint8_t *addr)
117 {
118     writing.type = RAW_HEADER_TYPE_RAW;
119     writing.compressedLength = writing.length;
120     writing.data = addr + writing.offset;
121     return UpdateLastFrame(addr);
122 }
123 
PrepareInCompress(const uint8_t * addr)124 int32_t RawMaker::PrepareInCompress(const uint8_t *addr)
125 {
126     writing.type = RAW_HEADER_TYPE_COMPRESSED;
127 
128     uLongf clen = compressBound(writing.length);
129     compressed = std::make_unique<uint8_t[]>(clen);
130     auto ret = compress(compressed.get(), &clen, addr + writing.offset, writing.length);
131     if (ret != Z_OK) {
132         GSLOG2HI(ERROR) << "compress failed with " << ret;
133         return ret;
134     }
135 
136     writing.compressedLength = static_cast<int32_t>(clen);
137     writing.data = compressed.get();
138     return UpdateLastFrame(addr);
139 }
140 
UpdateLastFrame(const uint8_t * addr)141 int32_t RawMaker::UpdateLastFrame(const uint8_t *addr)
142 {
143     auto dst = lastFrame.get() + writing.offset;
144     auto dstlen = size - writing.offset;
145     auto src = writing.data;
146     auto srclen = writing.length;
147     auto ret = memcpy_s(dst, dstlen, src, srclen);
148     if (ret) {
149         GSLOG2HI(ERROR) << "memcpy_s failed with <" << strerror(errno) << ">"
150             << ", params: " << "dstlen(" << dstlen << "), srclen(" << srclen << ")";
151         return ret;
152     }
153     return 0;
154 }
155 
WriteData()156 int32_t RawMaker::WriteData()
157 {
158     WriteInt32(writing.type);
159     WriteInt32(writing.offset);
160     WriteInt32(writing.length);
161     WriteInt32(writing.compressedLength);
162     ofs.write(reinterpret_cast<const char *>(writing.data), writing.compressedLength);
163 
164     int32_t align = writing.compressedLength % 0x4;
165     while (align) {
166         align = (align + 1) % 0x4;
167         ofs.write("\0", 1);
168     }
169     return 0;
170 }
171 
WriteInt32(int32_t integer)172 void RawMaker::WriteInt32(int32_t integer)
173 {
174     ofs.write(reinterpret_cast<const char *>(&integer), sizeof(integer));
175 }
176 
CompareWithLastFrame(const uint8_t * addr)177 void RawMaker::CompareWithLastFrame(const uint8_t *addr)
178 {
179     writing.length = 0;
180     writing.offset = size;
181     for (int32_t i = 0; i < size; i++) {
182         if (addr[i] != lastFrame[i]) {
183             writing.offset = i;
184             break;
185         }
186     }
187 
188     for (int32_t i = size - 1; i >= writing.offset; i++) {
189         if (addr[i] != lastFrame[i]) {
190             writing.length = i - writing.offset + 1;
191             break;
192         }
193     }
194 }
195 
DoFirstFrame()196 int32_t RawMaker::DoFirstFrame()
197 {
198     firstFrame = false;
199     ofs.open(filename, std::ofstream::trunc | std::ofstream::binary | std::ofstream::out);
200     if (errno) {
201         GSLOG2HI(ERROR) << "open " << filename << ", because " << strerror(errno);
202         return errno;
203     }
204 
205     lastFrame = std::make_unique<uint8_t[]>(static_cast<uint32_t>(size));
206     ofs.write("RAW.dif2", 0x8);
207     WriteInt32(static_cast<int32_t>(width));
208     WriteInt32(height);
209     ofs.close();
210     return 0;
211 }
212 } // namespace OHOS
213