1e9297d28Sopenharmony_ci/*
2e9297d28Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3e9297d28Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e9297d28Sopenharmony_ci * you may not use this file except in compliance with the License.
5e9297d28Sopenharmony_ci * You may obtain a copy of the License at
6e9297d28Sopenharmony_ci *
7e9297d28Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e9297d28Sopenharmony_ci *
9e9297d28Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e9297d28Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e9297d28Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e9297d28Sopenharmony_ci * See the License for the specific language governing permissions and
13e9297d28Sopenharmony_ci * limitations under the License.
14e9297d28Sopenharmony_ci */
15e9297d28Sopenharmony_ci
16e9297d28Sopenharmony_ci#include "output.h"
17e9297d28Sopenharmony_ci#include <GLES3/gl32.h>
18e9297d28Sopenharmony_ci#include <cmath>
19e9297d28Sopenharmony_ci#include <memory>
20e9297d28Sopenharmony_ci
21e9297d28Sopenharmony_cinamespace OHOS {
22e9297d28Sopenharmony_cinamespace Rosen {
23e9297d28Sopenharmony_ciOutput::Output()
24e9297d28Sopenharmony_ci{
25e9297d28Sopenharmony_ci    CreateProgram(GetVertexShader(), GetFragmentShader());
26e9297d28Sopenharmony_ci}
27e9297d28Sopenharmony_ci
28e9297d28Sopenharmony_ciFILTER_TYPE Output::GetFilterType()
29e9297d28Sopenharmony_ci{
30e9297d28Sopenharmony_ci    return FILTER_TYPE::OUTPUT;
31e9297d28Sopenharmony_ci}
32e9297d28Sopenharmony_ci
33e9297d28Sopenharmony_cistd::unique_ptr<OHOS::Media::PixelMap> Output::GetPixelMap()
34e9297d28Sopenharmony_ci{
35e9297d28Sopenharmony_ci    return std::move(pixelMap_);
36e9297d28Sopenharmony_ci}
37e9297d28Sopenharmony_ci
38e9297d28Sopenharmony_ciconst std::vector<uint8_t>& Output::GetColorBuffer()
39e9297d28Sopenharmony_ci{
40e9297d28Sopenharmony_ci    return colorBuffer_;
41e9297d28Sopenharmony_ci}
42e9297d28Sopenharmony_ci
43e9297d28Sopenharmony_civoid Output::DoProcess(ProcessData& data)
44e9297d28Sopenharmony_ci{
45e9297d28Sopenharmony_ci    if (format_ == "image/jpeg" || format_ == "image/png") {
46e9297d28Sopenharmony_ci        EncodeToFile(data);
47e9297d28Sopenharmony_ci    } else if (format_ == "pixelMap") {
48e9297d28Sopenharmony_ci        EncodeToPixelMap(data);
49e9297d28Sopenharmony_ci    } else if (format_ == "buffer") {
50e9297d28Sopenharmony_ci        WriteToBuffer(data);
51e9297d28Sopenharmony_ci    } else {
52e9297d28Sopenharmony_ci        LOGE("The format of Output is incorrect!!!");
53e9297d28Sopenharmony_ci    }
54e9297d28Sopenharmony_ci}
55e9297d28Sopenharmony_ci
56e9297d28Sopenharmony_civoid Output::EncodeToFile(ProcessData& data)
57e9297d28Sopenharmony_ci{
58e9297d28Sopenharmony_ci    EncodeToPixelMap(data);
59e9297d28Sopenharmony_ci    OHOS::Media::ImagePacker imagePacker;
60e9297d28Sopenharmony_ci    OHOS::Media::PackOption option;
61e9297d28Sopenharmony_ci    option.format = format_;
62e9297d28Sopenharmony_ci    std::set<std::string> formats;
63e9297d28Sopenharmony_ci    uint32_t ret = imagePacker.GetSupportedFormats(formats);
64e9297d28Sopenharmony_ci    if (ret != 0) {
65e9297d28Sopenharmony_ci        return;
66e9297d28Sopenharmony_ci    }
67e9297d28Sopenharmony_ci    imagePacker.StartPacking(dstImagePath_, option);
68e9297d28Sopenharmony_ci    if (pixelMap_ == nullptr) {
69e9297d28Sopenharmony_ci        LOGE("The pixelMap is null.");
70e9297d28Sopenharmony_ci        return;
71e9297d28Sopenharmony_ci    }
72e9297d28Sopenharmony_ci    imagePacker.AddImage(*pixelMap_);
73e9297d28Sopenharmony_ci    int64_t packedSize = 0;
74e9297d28Sopenharmony_ci    imagePacker.FinalizePacking(packedSize);
75e9297d28Sopenharmony_ci}
76e9297d28Sopenharmony_ci
77e9297d28Sopenharmony_civoid Output::EncodeToPixelMap(ProcessData& data)
78e9297d28Sopenharmony_ci{
79e9297d28Sopenharmony_ci    WriteToBuffer(data);
80e9297d28Sopenharmony_ci    WriteToBuffer(data);
81e9297d28Sopenharmony_ci    Media::InitializationOptions opts;
82e9297d28Sopenharmony_ci    opts.size.width = std::ceil(data.textureWidth);
83e9297d28Sopenharmony_ci    opts.size.height = std::ceil(data.textureHeight);
84e9297d28Sopenharmony_ci    opts.editable = true;
85e9297d28Sopenharmony_ci    pixelMap_ = Media::PixelMap::Create(opts);
86e9297d28Sopenharmony_ci    if (pixelMap_ == nullptr) {
87e9297d28Sopenharmony_ci        LOGE("The pixelMap create failed.");
88e9297d28Sopenharmony_ci        return;
89e9297d28Sopenharmony_ci    }
90e9297d28Sopenharmony_ci    pixelMap_->WritePixels(colorBuffer_.data(), pixelMap_->GetByteCount());
91e9297d28Sopenharmony_ci}
92e9297d28Sopenharmony_ci
93e9297d28Sopenharmony_civoid Output::WriteToBuffer(ProcessData& data)
94e9297d28Sopenharmony_ci{
95e9297d28Sopenharmony_ci    uint32_t bufferSize = static_cast<uint32_t>(data.textureWidth * data.textureHeight * COLOR_CHANNEL);
96e9297d28Sopenharmony_ci    colorBuffer_.resize(bufferSize);
97e9297d28Sopenharmony_ci    glBindFramebuffer(GL_FRAMEBUFFER, data.frameBufferID);
98e9297d28Sopenharmony_ci    glBindTexture(GL_TEXTURE_2D, data.dstTextureID);
99e9297d28Sopenharmony_ci    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.textureWidth, data.textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
100e9297d28Sopenharmony_ci    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, data.dstTextureID, 0);
101e9297d28Sopenharmony_ci    Use();
102e9297d28Sopenharmony_ci    glViewport(0, 0, data.textureWidth, data.textureHeight);
103e9297d28Sopenharmony_ci    glBindVertexArray(mesh_->VAO_);
104e9297d28Sopenharmony_ci    glBindTexture(GL_TEXTURE_2D, data.srcTextureID);
105e9297d28Sopenharmony_ci    glDrawElements(GL_TRIANGLES, AlgoFilter::DRAW_ELEMENTS_NUMBER, GL_UNSIGNED_INT, 0);
106e9297d28Sopenharmony_ci    glPixelStorei(GL_PACK_ALIGNMENT, 1);
107e9297d28Sopenharmony_ci    glReadPixels(0, 0, data.textureWidth, data.textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorBuffer_.data());
108e9297d28Sopenharmony_ci}
109e9297d28Sopenharmony_ci
110e9297d28Sopenharmony_civoid Output::SetValue(const std::string& key, std::shared_ptr<void> value, int size)
111e9297d28Sopenharmony_ci{
112e9297d28Sopenharmony_ci    if (key == "format" && size > 0) {
113e9297d28Sopenharmony_ci        std::shared_ptr<std::string> format = std::static_pointer_cast<std::string>(value);
114e9297d28Sopenharmony_ci        format_ = *(format.get());
115e9297d28Sopenharmony_ci        if (format_ == "jpg" || format_ == "jpeg") {
116e9297d28Sopenharmony_ci            format_ = "image/jpeg";
117e9297d28Sopenharmony_ci        } else if (format_ == "png") {
118e9297d28Sopenharmony_ci            format_ = "image/png";
119e9297d28Sopenharmony_ci        }
120e9297d28Sopenharmony_ci        LOGD("The output format is %{public}s.", format_.c_str());
121e9297d28Sopenharmony_ci    } else if (key == "dst" && size > 0) {
122e9297d28Sopenharmony_ci        if (format_ == "image/jpeg" || format_ == "image/png") {
123e9297d28Sopenharmony_ci            std::shared_ptr<std::string> dstImagePath = std::static_pointer_cast<std::string>(value);
124e9297d28Sopenharmony_ci            dstImagePath_ = *(dstImagePath.get());
125e9297d28Sopenharmony_ci            LOGD("The ouput source image path is %{public}s.", dstImagePath_.c_str());
126e9297d28Sopenharmony_ci        }
127e9297d28Sopenharmony_ci    }
128e9297d28Sopenharmony_ci}
129e9297d28Sopenharmony_ci
130e9297d28Sopenharmony_cistd::string Output::GetVertexShader()
131e9297d28Sopenharmony_ci{
132e9297d28Sopenharmony_ci    return R"SHADER(#version 320 es
133e9297d28Sopenharmony_ci        precision mediump float;
134e9297d28Sopenharmony_ci        layout (location = 0) in vec3 vertexCoord;
135e9297d28Sopenharmony_ci        layout (location = 1) in vec2 inputTexCoord;
136e9297d28Sopenharmony_ci        out vec2 texCoord;
137e9297d28Sopenharmony_ci
138e9297d28Sopenharmony_ci        void main()
139e9297d28Sopenharmony_ci        {
140e9297d28Sopenharmony_ci            gl_Position = vec4(vertexCoord, 1.0);
141e9297d28Sopenharmony_ci            texCoord = inputTexCoord;
142e9297d28Sopenharmony_ci        }
143e9297d28Sopenharmony_ci    )SHADER";
144e9297d28Sopenharmony_ci}
145e9297d28Sopenharmony_ci
146e9297d28Sopenharmony_cistd::string Output::GetFragmentShader()
147e9297d28Sopenharmony_ci{
148e9297d28Sopenharmony_ci    return R"SHADER(#version 320 es
149e9297d28Sopenharmony_ci        precision mediump float;
150e9297d28Sopenharmony_ci        in vec2 texCoord;
151e9297d28Sopenharmony_ci        out vec4 fragColor;
152e9297d28Sopenharmony_ci        uniform sampler2D uTexture;
153e9297d28Sopenharmony_ci        void main()
154e9297d28Sopenharmony_ci        {
155e9297d28Sopenharmony_ci            fragColor = texture(uTexture, texCoord);
156e9297d28Sopenharmony_ci        }
157e9297d28Sopenharmony_ci    )SHADER";
158e9297d28Sopenharmony_ci}
159e9297d28Sopenharmony_ci} // namespcae Rosen
160e9297d28Sopenharmony_ci} // namespace OHOS