• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "super_resolution_post_processor.h"
17 
18 namespace {
19 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "SuperResolutionPostProcessor" };
20 }
21 
22 namespace OHOS {
23 namespace Media {
24 
25 namespace {
26 constexpr int32_t MAX_WIDTH = 1920;
27 constexpr int32_t MAX_HEIGHT = 1080;
28 }
29 
30 using namespace VideoProcessingEngine;
31 
isSuperResolutionSupported(const std::shared_ptr<Meta> & meta)32 static bool isSuperResolutionSupported(const std::shared_ptr<Meta>& meta)
33 {
34     FALSE_RETURN_V(meta != nullptr, false);
35 
36     int32_t width = 0;
37     int32_t height = 0;
38     bool isDrmProtected = false;
39     bool isHdrVivid = false;
40     meta->GetData(Tag::VIDEO_WIDTH, width);
41     meta->GetData(Tag::VIDEO_HEIGHT, height);
42     meta->GetData(Tag::VIDEO_IS_HDR_VIVID, isHdrVivid);
43     meta->GetData(Tag::AV_PLAYER_IS_DRM_PROTECTED, isDrmProtected);
44     bool isVideoSizeValid = (width > 0 && width <= MAX_WIDTH) &&
45                             (height > 0 && height <= MAX_HEIGHT);
46     bool canCreatePostProcessor = !isDrmProtected && !isHdrVivid && isVideoSizeValid;
47     if (!canCreatePostProcessor) {
48         MEDIA_LOG_E("invalid input stream for super resolution! width: " PUBLIC_LOG_D32
49             ", height: " PUBLIC_LOG_D32 ", isHdrVivid: " PUBLIC_LOG_D32 ", drm: " PUBLIC_LOG_D32,
50             width, height, isHdrVivid, isDrmProtected);
51     }
52     return canCreatePostProcessor;
53 }
54 
55 static AutoRegisterPostProcessor<SuperResolutionPostProcessor> g_registerSuperResolutionPostProcessor(
__anoneb5cbc980302() 56     VideoPostProcessorType::SUPER_RESOLUTION, []() -> std::shared_ptr<BaseVideoPostProcessor> {
57         auto postProcessor = std::make_shared<SuperResolutionPostProcessor>();
58         if (postProcessor == nullptr || !postProcessor->IsValid()) {
59             return nullptr;
60         } else {
61             return postProcessor;
62         }
63     }, &isSuperResolutionSupported);
64 
65 class VPECallback : public VpeVideoCallback {
66 public:
VPECallback(std::shared_ptr<SuperResolutionPostProcessor> postProcessor)67     explicit VPECallback(std::shared_ptr<SuperResolutionPostProcessor> postProcessor)
68         : postProcessor_(postProcessor) {}
69     ~VPECallback() = default;
70 
OnError(VPEAlgoErrCode errorCode)71     void OnError(VPEAlgoErrCode errorCode)
72     {
73         if (auto postProcessor = postProcessor_.lock()) {
74             postProcessor->OnError(errorCode);
75         } else {
76             MEDIA_LOG_I("invalid decoderSurfaceFilter");
77         }
78     }
OnState(VPEAlgoState state)79     void OnState(VPEAlgoState state)
80     {
81     }
OnEffectChange(uint32_t type)82     void OnEffectChange(uint32_t type)
83     {
84         if (auto postProcessor = postProcessor_.lock()) {
85             postProcessor->OnSuperResolutionChanged(type == VIDEO_TYPE_DETAIL_ENHANCER);
86         } else {
87             MEDIA_LOG_I("invalid decoderSurfaceFilter");
88         }
89     }
OnOutputFormatChanged(const Format & format)90     void OnOutputFormatChanged(const Format& format)
91     {
92         size_t addrSize;
93         uint8_t* addr = nullptr;
94         if (!format.GetBuffer(ParameterKey::DETAIL_ENHANCER_TARGET_SIZE, &addr, addrSize)) {
95             MEDIA_LOG_I("can not get target size");
96             return;
97         }
98         FALSE_RETURN_MSG(addr != nullptr && addrSize == sizeof(VpeBufferSize),
99             "Invalid input: addr is null or addrSize=%{public}zu(Expected:%{public}zu)!",
100             addrSize, sizeof(VpeBufferSize));
101         auto size = reinterpret_cast<VpeBufferSize*>(addr);
102 
103         MEDIA_LOG_D("OnOutputFormatChanged nextW=" PUBLIC_LOG_D32 " nextH=" PUBLIC_LOG_D32, size->width, size->height);
104         if (size->width <= 0 || size->height <= 0) {
105             MEDIA_LOG_W("invaild video size");
106             return;
107         }
108     }
OnOutputBufferAvailable(uint32_t index,VpeBufferFlag flag)109     void OnOutputBufferAvailable(uint32_t index, VpeBufferFlag flag)
110     {
111     }
OnOutputBufferAvailable(uint32_t index,const VpeBufferInfo & info)112     void OnOutputBufferAvailable(uint32_t index, const VpeBufferInfo& info)
113     {
114         if (auto postProcessor = postProcessor_.lock()) {
115             postProcessor->OnOutputBufferAvailable(index, info);
116         } else {
117             MEDIA_LOG_I("invalid decoderSurfaceFilter");
118         }
119     }
120 
121 private:
122     std::weak_ptr<SuperResolutionPostProcessor> postProcessor_;
123 };
124 
SuperResolutionPostProcessor()125 SuperResolutionPostProcessor::SuperResolutionPostProcessor()
126 {
127     postProcessor_ = VpeVideo::Create(VIDEO_TYPE_DETAIL_ENHANCER);
128     isPostProcessorOn_ = true;
129 }
130 
~SuperResolutionPostProcessor()131 SuperResolutionPostProcessor::~SuperResolutionPostProcessor()
132 {
133     std::unique_lock<std::shared_mutex> lock(mutex_);
134     postProcessor_ = nullptr;
135 }
136 
IsValid()137 bool SuperResolutionPostProcessor::IsValid()
138 {
139     return postProcessor_ != nullptr;
140 }
141 
Init()142 Status SuperResolutionPostProcessor::Init()
143 {
144     MEDIA_LOG_D("Init in");
145     std::shared_lock<std::shared_mutex> lock(mutex_);
146     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
147 
148     auto ret = SetQualityLevel(DEFAULT_QUALITY_LEVEL);
149     FALSE_RETURN_V(ret == Status::OK, ret);
150     auto callback = std::make_shared<VPECallback>(shared_from_this());
151     return postProcessor_->RegisterCallback(callback) == VPEAlgoErrCode::VPE_ALGO_ERR_OK ?
152         Status::OK : Status::ERROR_INVALID_STATE;
153 }
154 
Flush()155 Status SuperResolutionPostProcessor::Flush()
156 {
157     MEDIA_LOG_D("Flush in");
158     std::shared_lock<std::shared_mutex> lock(mutex_);
159     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
160     auto ret = postProcessor_->Flush();
161     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
162     return Status::OK;
163 }
164 
Stop()165 Status SuperResolutionPostProcessor::Stop()
166 {
167     MEDIA_LOG_D("Stop in");
168     std::shared_lock<std::shared_mutex> lock(mutex_);
169     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
170     auto ret = postProcessor_->Stop();
171     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
172     return Release();
173 }
174 
Start()175 Status SuperResolutionPostProcessor::Start()
176 {
177     MEDIA_LOG_D("Start in");
178     std::shared_lock<std::shared_mutex> lock(mutex_);
179     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
180     auto ret = postProcessor_->Start();
181     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
182     return Status::OK;
183 }
184 
Release()185 Status SuperResolutionPostProcessor::Release()
186 {
187     MEDIA_LOG_D("Release in");
188     std::shared_lock<std::shared_mutex> lock(mutex_);
189     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
190     auto ret = postProcessor_->Release();
191     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
192     return Status::OK;
193 }
194 
NotifyEos(int64_t eosPts)195 Status SuperResolutionPostProcessor::NotifyEos(int64_t eosPts)
196 {
197     MEDIA_LOG_D("Notify eos");
198     std::shared_lock<std::shared_mutex> lock(mutex_);
199     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
200     auto ret = postProcessor_->NotifyEos();
201     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_PARAMETER);
202     return Status::OK;
203 }
204 
GetInputSurface()205 sptr<Surface> SuperResolutionPostProcessor::GetInputSurface()
206 {
207     std::shared_lock<std::shared_mutex> lock(mutex_);
208     FALSE_RETURN_V(postProcessor_ != nullptr, nullptr);
209     return postProcessor_->GetInputSurface();
210 }
211 
SetOutputSurface(sptr<Surface> surface)212 Status SuperResolutionPostProcessor::SetOutputSurface(sptr<Surface> surface)
213 {
214     std::shared_lock<std::shared_mutex> lock(mutex_);
215     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
216     auto ret = postProcessor_->SetOutputSurface(surface);
217     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_PARAMETER);
218     return Status::OK;
219 }
220 
OnOutputBufferAvailable(uint32_t index,VpeBufferFlag flag)221 void SuperResolutionPostProcessor::OnOutputBufferAvailable(uint32_t index, VpeBufferFlag flag)
222 {
223     auto buffer = AVBuffer::CreateAVBuffer();
224     if (buffer == nullptr) {
225         MEDIA_LOG_E("Create buffer failed");
226         ReleaseOutputBuffer(index, false);
227         return;
228     }
229     if (flag & static_cast<uint32_t>(VPE_BUFFER_FLAG_EOS)) {
230         buffer->flag_ |= static_cast<uint32_t>(Plugins::AVBufferFlag::EOS);
231     }
232     FALSE_RETURN_MSG(filterCallback_ != nullptr, "filterCallback_ is nullptr");
233     filterCallback_->OnOutputBufferAvailable(index, buffer);
234 }
235 
OnOutputBufferAvailable(uint32_t index,const VpeBufferInfo & info)236 void SuperResolutionPostProcessor::OnOutputBufferAvailable(uint32_t index, const VpeBufferInfo& info)
237 {
238     auto buffer = AVBuffer::CreateAVBuffer();
239     if (buffer == nullptr) {
240         MEDIA_LOG_E("Create buffer failed");
241         ReleaseOutputBuffer(index, false);
242         return;
243     }
244     if (info.flag & static_cast<uint32_t>(VPE_BUFFER_FLAG_EOS)) {
245         buffer->flag_ |= static_cast<uint32_t>(Plugins::AVBufferFlag::EOS);
246     }
247     buffer->pts_ = info.presentationTimestamp;
248     FALSE_RETURN_MSG(filterCallback_ != nullptr, "filterCallback_ is nullptr");
249     filterCallback_->OnOutputBufferAvailable(index, buffer);
250 }
251 
ReleaseOutputBuffer(uint32_t index,bool render)252 Status SuperResolutionPostProcessor::ReleaseOutputBuffer(uint32_t index, bool render)
253 {
254     std::shared_lock<std::shared_mutex> lock(mutex_);
255     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
256     auto ret = postProcessor_->ReleaseOutputBuffer(index, render);
257     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
258     return Status::OK;
259 }
260 
RenderOutputBufferAtTime(uint32_t index,int64_t renderTimestampNs)261 Status SuperResolutionPostProcessor::RenderOutputBufferAtTime(uint32_t index, int64_t renderTimestampNs)
262 {
263     MEDIA_LOG_D("RenderOutputBufferAtTime timestamp: %{public}" PRId64, renderTimestampNs);
264     std::shared_lock<std::shared_mutex> lock(mutex_);
265     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
266     auto ret = postProcessor_->RenderOutputBufferAtTime(index, renderTimestampNs);
267     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
268     return Status::OK;
269 }
270 
SetCallback(const std::shared_ptr<PostProcessorCallback> callback)271 Status SuperResolutionPostProcessor::SetCallback(const std::shared_ptr<PostProcessorCallback> callback)
272 {
273     filterCallback_ = callback;
274     return Status::OK;
275 }
276 
SetPostProcessorOn(bool isPostProcessorOn)277 Status SuperResolutionPostProcessor::SetPostProcessorOn(bool isPostProcessorOn)
278 {
279     MEDIA_LOG_D("SetPostProcessorOn: %{public}d", isPostProcessorOn);
280     std::shared_lock<std::shared_mutex> lock(mutex_);
281     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
282     VPEAlgoErrCode ret = VPEAlgoErrCode::VPE_ALGO_ERR_OK;
283     if (isPostProcessorOn) {
284         ret = postProcessor_->Enable();
285     } else {
286         ret = postProcessor_->Disable();
287     }
288     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_STATE);
289     return Status::OK;
290 }
291 
SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver> & receiver)292 Status SuperResolutionPostProcessor::SetEventReceiver(const std::shared_ptr<Pipeline::EventReceiver> &receiver)
293 {
294     eventReceiver_ = receiver;
295     return Status::OK;
296 }
297 
SetParameter(const Format & format)298 Status SuperResolutionPostProcessor::SetParameter(const Format &format)
299 {
300     MEDIA_LOG_D("Setparameter in");
301     std::shared_lock<std::shared_mutex> lock(mutex_);
302     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
303     auto ret = postProcessor_->SetParameter(format);
304     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_PARAMETER);
305     return Status::OK;
306 }
307 
SetQualityLevel(DetailEnhancerQualityLevel level)308 Status SuperResolutionPostProcessor::SetQualityLevel(DetailEnhancerQualityLevel level)
309 {
310     MEDIA_LOG_D("SetQualityLevel in");
311     Format parameter;
312     parameter.PutIntValue(ParameterKey::DETAIL_ENHANCER_QUALITY_LEVEL, level);
313     parameter.PutIntValue(ParameterKey::DETAIL_ENHANCER_AUTO_DOWNSHIFT, 0);
314     auto ret = postProcessor_->SetParameter(parameter);
315     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_PARAMETER);
316     return Status::OK;
317 }
318 
SetVideoWindowSize(int32_t width,int32_t height)319 Status SuperResolutionPostProcessor::SetVideoWindowSize(int32_t width, int32_t height)
320 {
321     MEDIA_LOG_D("SetVideoWindowSize in");
322     std::shared_lock<std::shared_mutex> lock(mutex_);
323     FALSE_RETURN_V(postProcessor_ != nullptr, Status::ERROR_INVALID_STATE);
324     Format parameter;
325     VpeBufferSize outputSize = { width, height };
326     parameter.PutBuffer(ParameterKey::DETAIL_ENHANCER_TARGET_SIZE,
327         reinterpret_cast<const uint8_t*>(&outputSize), sizeof(VpeBufferSize));
328     auto ret = postProcessor_->SetParameter(parameter);
329     FALSE_RETURN_V(ret == VPEAlgoErrCode::VPE_ALGO_ERR_OK, Status::ERROR_INVALID_PARAMETER);
330     return Status::OK;
331 }
332 
OnError(VPEAlgoErrCode errorCode)333 void SuperResolutionPostProcessor::OnError(VPEAlgoErrCode errorCode)
334 {
335     std::shared_lock<std::shared_mutex> lock(mutex_);
336     FALSE_RETURN_MSG(filterCallback_ != nullptr, "filterCallback_ is nullptr");
337     MEDIA_LOG_E("SuperResolutionPostProcessor error happened. ErrorCode: %{public}d", errorCode);
338 }
339 
OnOutputFormatChanged(const Format & format)340 void SuperResolutionPostProcessor::OnOutputFormatChanged(const Format &format)
341 {
342     std::shared_lock<std::shared_mutex> lock(mutex_);
343     FALSE_RETURN_MSG(filterCallback_ != nullptr, "filterCallback_ is nullptr");
344     filterCallback_->OnOutputFormatChanged(format);
345 }
346 
OnSuperResolutionChanged(bool enable)347 void SuperResolutionPostProcessor::OnSuperResolutionChanged(bool enable)
348 {
349     MEDIA_LOG_D("OnSuperResolutionChanged: %{public}d", enable);
350     std::shared_lock<std::shared_mutex> lock(mutex_);
351     isPostProcessorOn_ = enable;
352     if (eventReceiver_ != nullptr) {
353         eventReceiver_->OnEvent({"SuperResolutionPostProcessor", EventType::EVENT_SUPER_RESOLUTION_CHANGED, enable});
354     }
355 }
356 
357 } // namespace Media
358 } // namespace OHOS