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