xref: /aosp_15_r20/frameworks/native/libs/renderengine/benchmark/Codec.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include <RenderEngineBench.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <android/bitmap.h>
19*38e8c45fSAndroid Build Coastguard Worker #include <android/data_space.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <android/imagedecoder.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <renderengine/ExternalTexture.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <renderengine/RenderEngine.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker using namespace android;
27*38e8c45fSAndroid Build Coastguard Worker using namespace android::renderengine;
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker namespace {
30*38e8c45fSAndroid Build Coastguard Worker struct DecoderDeleter {
operator ()__anon795bede20111::DecoderDeleter31*38e8c45fSAndroid Build Coastguard Worker     void operator()(AImageDecoder* decoder) { AImageDecoder_delete(decoder); }
32*38e8c45fSAndroid Build Coastguard Worker };
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker using AutoDecoderDeleter = std::unique_ptr<AImageDecoder, DecoderDeleter>;
35*38e8c45fSAndroid Build Coastguard Worker 
ok(int aImageDecoderResult,const char * path,const char * method)36*38e8c45fSAndroid Build Coastguard Worker bool ok(int aImageDecoderResult, const char* path, const char* method) {
37*38e8c45fSAndroid Build Coastguard Worker     if (aImageDecoderResult == ANDROID_IMAGE_DECODER_SUCCESS) {
38*38e8c45fSAndroid Build Coastguard Worker         return true;
39*38e8c45fSAndroid Build Coastguard Worker     }
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker     ALOGE("Failed AImageDecoder_%s on '%s' with error '%s'", method, path,
42*38e8c45fSAndroid Build Coastguard Worker           AImageDecoder_resultToString(aImageDecoderResult));
43*38e8c45fSAndroid Build Coastguard Worker     return false;
44*38e8c45fSAndroid Build Coastguard Worker }
45*38e8c45fSAndroid Build Coastguard Worker } // namespace
46*38e8c45fSAndroid Build Coastguard Worker 
47*38e8c45fSAndroid Build Coastguard Worker namespace renderenginebench {
48*38e8c45fSAndroid Build Coastguard Worker 
decode(const char * path,const sp<GraphicBuffer> & buffer)49*38e8c45fSAndroid Build Coastguard Worker void decode(const char* path, const sp<GraphicBuffer>& buffer) {
50*38e8c45fSAndroid Build Coastguard Worker     base::unique_fd fd{open(path, O_RDONLY)};
51*38e8c45fSAndroid Build Coastguard Worker     if (fd.get() < 0) {
52*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to open %s", path);
53*38e8c45fSAndroid Build Coastguard Worker         return;
54*38e8c45fSAndroid Build Coastguard Worker     }
55*38e8c45fSAndroid Build Coastguard Worker 
56*38e8c45fSAndroid Build Coastguard Worker     AImageDecoder* decoder{nullptr};
57*38e8c45fSAndroid Build Coastguard Worker     auto result = AImageDecoder_createFromFd(fd.get(), &decoder);
58*38e8c45fSAndroid Build Coastguard Worker     if (!ok(result, path, "createFromFd")) {
59*38e8c45fSAndroid Build Coastguard Worker         return;
60*38e8c45fSAndroid Build Coastguard Worker     }
61*38e8c45fSAndroid Build Coastguard Worker 
62*38e8c45fSAndroid Build Coastguard Worker     AutoDecoderDeleter deleter(decoder);
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(buffer->getWidth() <= 0 || buffer->getHeight() <= 0,
65*38e8c45fSAndroid Build Coastguard Worker                         "Impossible buffer size!");
66*38e8c45fSAndroid Build Coastguard Worker     auto width = static_cast<int32_t>(buffer->getWidth());
67*38e8c45fSAndroid Build Coastguard Worker     auto height = static_cast<int32_t>(buffer->getHeight());
68*38e8c45fSAndroid Build Coastguard Worker     result = AImageDecoder_setTargetSize(decoder, width, height);
69*38e8c45fSAndroid Build Coastguard Worker     if (!ok(result, path, "setTargetSize")) {
70*38e8c45fSAndroid Build Coastguard Worker         return;
71*38e8c45fSAndroid Build Coastguard Worker     }
72*38e8c45fSAndroid Build Coastguard Worker 
73*38e8c45fSAndroid Build Coastguard Worker     void* pixels{nullptr};
74*38e8c45fSAndroid Build Coastguard Worker     int32_t stride{0};
75*38e8c45fSAndroid Build Coastguard Worker     if (auto status = buffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &pixels,
76*38e8c45fSAndroid Build Coastguard Worker                                    nullptr /*outBytesPerPixel*/, &stride);
77*38e8c45fSAndroid Build Coastguard Worker         status < 0) {
78*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to lock pixels!");
79*38e8c45fSAndroid Build Coastguard Worker         return;
80*38e8c45fSAndroid Build Coastguard Worker     }
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker     result = AImageDecoder_decodeImage(decoder, pixels, static_cast<size_t>(stride),
83*38e8c45fSAndroid Build Coastguard Worker                                        static_cast<size_t>(stride * height));
84*38e8c45fSAndroid Build Coastguard Worker     if (auto status = buffer->unlock(); status < 0) {
85*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to unlock pixels!");
86*38e8c45fSAndroid Build Coastguard Worker     }
87*38e8c45fSAndroid Build Coastguard Worker 
88*38e8c45fSAndroid Build Coastguard Worker     // For the side effect of logging.
89*38e8c45fSAndroid Build Coastguard Worker     (void)ok(result, path, "decodeImage");
90*38e8c45fSAndroid Build Coastguard Worker }
91*38e8c45fSAndroid Build Coastguard Worker 
encodeToJpeg(const char * path,const sp<GraphicBuffer> & buffer)92*38e8c45fSAndroid Build Coastguard Worker void encodeToJpeg(const char* path, const sp<GraphicBuffer>& buffer) {
93*38e8c45fSAndroid Build Coastguard Worker     base::unique_fd fd{open(path, O_WRONLY | O_CREAT, S_IWUSR)};
94*38e8c45fSAndroid Build Coastguard Worker     if (fd.get() < 0) {
95*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to open %s", path);
96*38e8c45fSAndroid Build Coastguard Worker         return;
97*38e8c45fSAndroid Build Coastguard Worker     }
98*38e8c45fSAndroid Build Coastguard Worker 
99*38e8c45fSAndroid Build Coastguard Worker     void* pixels{nullptr};
100*38e8c45fSAndroid Build Coastguard Worker     int32_t stride{0};
101*38e8c45fSAndroid Build Coastguard Worker     if (auto status = buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &pixels,
102*38e8c45fSAndroid Build Coastguard Worker                                    nullptr /*outBytesPerPixel*/, &stride);
103*38e8c45fSAndroid Build Coastguard Worker         status < 0) {
104*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to lock pixels!");
105*38e8c45fSAndroid Build Coastguard Worker         return;
106*38e8c45fSAndroid Build Coastguard Worker     }
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker     AndroidBitmapInfo info{
109*38e8c45fSAndroid Build Coastguard Worker             .width = buffer->getWidth(),
110*38e8c45fSAndroid Build Coastguard Worker             .height = buffer->getHeight(),
111*38e8c45fSAndroid Build Coastguard Worker             .stride = static_cast<uint32_t>(stride),
112*38e8c45fSAndroid Build Coastguard Worker             .format = ANDROID_BITMAP_FORMAT_RGBA_8888,
113*38e8c45fSAndroid Build Coastguard Worker             .flags = ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE,
114*38e8c45fSAndroid Build Coastguard Worker     };
115*38e8c45fSAndroid Build Coastguard Worker     int result = AndroidBitmap_compress(&info, ADATASPACE_SRGB, pixels,
116*38e8c45fSAndroid Build Coastguard Worker                                         ANDROID_BITMAP_COMPRESS_FORMAT_JPEG, 80, &fd,
117*38e8c45fSAndroid Build Coastguard Worker                                         [](void* fdPtr, const void* data, size_t size) -> bool {
118*38e8c45fSAndroid Build Coastguard Worker                                             const ssize_t bytesWritten =
119*38e8c45fSAndroid Build Coastguard Worker                                                     write(reinterpret_cast<base::unique_fd*>(fdPtr)
120*38e8c45fSAndroid Build Coastguard Worker                                                                   ->get(),
121*38e8c45fSAndroid Build Coastguard Worker                                                           data, size);
122*38e8c45fSAndroid Build Coastguard Worker                                             return bytesWritten > 0 &&
123*38e8c45fSAndroid Build Coastguard Worker                                                     static_cast<size_t>(bytesWritten) == size;
124*38e8c45fSAndroid Build Coastguard Worker                                         });
125*38e8c45fSAndroid Build Coastguard Worker     if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
126*38e8c45fSAndroid Build Coastguard Worker         ALOGD("Successfully encoded to '%s'", path);
127*38e8c45fSAndroid Build Coastguard Worker     } else {
128*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to encode to %s with error %d", path, result);
129*38e8c45fSAndroid Build Coastguard Worker     }
130*38e8c45fSAndroid Build Coastguard Worker 
131*38e8c45fSAndroid Build Coastguard Worker     if (auto status = buffer->unlock(); status < 0) {
132*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to unlock pixels!");
133*38e8c45fSAndroid Build Coastguard Worker     }
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker 
136*38e8c45fSAndroid Build Coastguard Worker } // namespace renderenginebench
137