1 /*
2 * Copyright (c) 2023 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, Hardware
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 <algorithm>
17 #include <cstdio>
18 #include <ctime>
19 #include <iostream>
20 #include <string>
21 #include <securec.h>
22 #include <sys/time.h>
23
24 #include "png.h"
25 #include "feature/capture/rs_surface_capture_task.h"
26 #include "transaction/rs_interfaces.h"
27
28 using namespace OHOS::Rosen;
29 using namespace OHOS::Media;
30 using namespace std;
31
32 class SurfaceCaptureFuture : public SurfaceCaptureCallback {
33 public:
34 SurfaceCaptureFuture() = default;
~SurfaceCaptureFuture()35 ~SurfaceCaptureFuture() {};
OnSurfaceCapture(shared_ptr<PixelMap> pixelmap)36 void OnSurfaceCapture(shared_ptr<PixelMap> pixelmap) override
37 {
38 pixelMap_ = pixelmap;
39 }
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> pixelMapHDR)40 void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
41 std::shared_ptr<Media::PixelMap> pixelMapHDR) override {}
GetPixelMap()42 shared_ptr<PixelMap> GetPixelMap()
43 {
44 return pixelMap_;
45 }
46 private:
47 shared_ptr<PixelMap> pixelMap_ = nullptr;
48 };
49
50 const char *SNAPSHOT_PATH = "/data/surface_";
51 const char *SNAPSHOT_SUFFIX = ".png";
52 constexpr int MAX_TIME_STR_LEN = 40;
53 constexpr int YEAR_SINCE = 1900;
54 constexpr int BITMAP_DEPTH = 8;
55
GenerateFileName()56 string GenerateFileName()
57 {
58 timeval tv;
59 string fileName = SNAPSHOT_PATH;
60
61 if (gettimeofday(&tv, nullptr) == 0) {
62 struct tm *tmVal = localtime(&tv.tv_sec);
63 if (tmVal != nullptr) {
64 char timeStr[MAX_TIME_STR_LEN] = { 0 };
65 snprintf_s(timeStr, sizeof(timeStr), sizeof(timeStr) - 1,
66 "%04d-%02d-%02d_%02d-%02d-%02d",
67 tmVal->tm_year + YEAR_SINCE, tmVal->tm_mon + 1, tmVal->tm_mday,
68 tmVal->tm_hour, tmVal->tm_min, tmVal->tm_sec);
69 fileName += timeStr;
70 }
71 }
72 fileName += SNAPSHOT_SUFFIX;
73 return fileName;
74 }
75
WriteToPng(const std::string & filename,const WriteToPngParam & param)76 bool WriteToPng(const std::string &filename, const WriteToPngParam ¶m)
77 {
78 if (filename.empty()) {
79 RS_LOGI("WriteToPng filename is empty");
80 return false;
81 }
82 RS_LOGI("WriteToPng filename = %{public}s", filename.c_str());
83 png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
84 if (pngStruct == nullptr) {
85 return false;
86 }
87 png_infop pngInfo = png_create_info_struct(pngStruct);
88 if (pngInfo == nullptr) {
89 png_destroy_write_struct(&pngStruct, nullptr);
90 return false;
91 }
92
93 FILE *fp = fopen(filename.c_str(), "wb");
94 if (fp == nullptr) {
95 png_destroy_write_struct(&pngStruct, &pngInfo);
96 return false;
97 }
98 png_init_io(pngStruct, fp);
99
100 // set png header
101 png_set_IHDR(pngStruct, pngInfo,
102 param.width, param.height,
103 param.bitDepth,
104 PNG_COLOR_TYPE_RGBA,
105 PNG_INTERLACE_NONE,
106 PNG_COMPRESSION_TYPE_BASE,
107 PNG_FILTER_TYPE_BASE);
108 png_set_packing(pngStruct); // set packing info
109 png_write_info(pngStruct, pngInfo); // write to header
110
111 for (uint32_t i = 0; i < param.height; i++) {
112 png_write_row(pngStruct, param.data + (i * param.stride));
113 }
114 png_write_end(pngStruct, pngInfo);
115
116 // free
117 png_destroy_write_struct(&pngStruct, &pngInfo);
118 int ret = fclose(fp);
119 return ret == 0;
120 }
121
WritePixelMapToPng(PixelMap & pixelMap,std::string filename)122 bool WritePixelMapToPng(PixelMap& pixelMap, std::string filename)
123 {
124 struct timeval now;
125 int64_t nowVal = 0;
126 if (gettimeofday(&now, nullptr) == 0) {
127 constexpr int secToUsec = 1000 * 1000;
128 nowVal = static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
129 }
130 if (filename.size() == 0) {
131 filename = "/data/PixelMap_" + std::to_string(nowVal) + ".png";
132 }
133
134 WriteToPngParam param;
135 param.width = static_cast<uint32_t>(pixelMap.GetWidth());
136 param.height = static_cast<uint32_t>(pixelMap.GetHeight());
137 param.data = pixelMap.GetPixels();
138 param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
139 param.bitDepth = BITMAP_DEPTH;
140
141 return WriteToPng(filename, param);
142 }
143
main()144 int main()
145 {
146 cout << "Please input surfacenode id: ";
147 uint64_t input;
148 cin >> input;
149 shared_ptr<SurfaceCaptureFuture> callback = make_shared<SurfaceCaptureFuture>();
150 RSSurfaceCaptureConfig captureConfig;
151 RSInterfaces::GetInstance().TakeSurfaceCapture(input, callback, captureConfig);
152 sleep(2);
153 shared_ptr<PixelMap> pixelmap = callback->GetPixelMap();
154 if (pixelmap == nullptr) {
155 cout << "pixelmap is nullptr" << endl;
156 return 0;
157 }
158 string filename = GenerateFileName();
159 bool ret = WritePixelMapToPng(*pixelmap, filename);
160 if (ret) {
161 cout << "success: snapshot surface " << input << " , write to " << filename.c_str() << endl;
162 } else {
163 cout << "error: snapshot surface " << input << endl;
164 }
165 return 0;
166 }