1 /*
2  * Copyright (c) 2022-2022 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 #ifdef VIDEO_SUPPORT
17 
18 #define HST_LOG_TAG "VideoDecoderFilter"
19 
20 #include "pipeline/filters/codec/video_decoder/video_decoder_filter.h"
21 #include "foundation/cpp_ext/memory_ext.h"
22 #include "foundation/log.h"
23 #include "foundation/osal/utils/util.h"
24 #include "foundation/utils/constants.h"
25 #include "foundation/utils/steady_clock.h"
26 #include "pipeline/factory/filter_factory.h"
27 #include "pipeline/filters/codec/codec_filter_factory.h"
28 #include "plugin/common/plugin_buffer.h"
29 #include "plugin/common/plugin_video_tags.h"
30 #include "plugin/common/surface_allocator.h"
31 
32 namespace {
33 const uint32_t DEFAULT_IN_BUFFER_POOL_SIZE = 8;
34 const uint32_t DEFAULT_OUT_BUFFER_POOL_SIZE = 8;
35 const float VIDEO_PIX_DEPTH = 1.5;
36 const uint32_t VIDEO_ALIGN_SIZE = 16;
37 }
38 
39 namespace OHOS {
40 namespace Media {
41 namespace Pipeline {
42 #ifdef OHOS_LITE
43 static AutoRegisterFilter<VideoDecoderFilter> g_registerVideoDecoderFilter("builtin.player.videodecoder",
__anon589c82e20202(const std::string& name) 44     [](const std::string& name) { return CreateCodecFilter(name, FilterCodecMode::VIDEO_ASYNC_DECODER); });
45 #else
46 static AutoRegisterFilter<VideoDecoderFilter> g_registerVideoDecoderFilter("builtin.player.videodecoder",
47     [](const std::string& name) { return CreateCodecFilter(name, FilterCodecMode::VIDEO_ASYNC_DECODER); });
48 #endif
VideoDecoderFilter(const std::string & name,std::shared_ptr<CodecMode> codecMode)49 VideoDecoderFilter::VideoDecoderFilter(const std::string& name, std::shared_ptr<CodecMode> codecMode)
50     : CodecFilterBase(name)
51 {
52     MEDIA_LOG_I("video decoder ctor called");
53     filterType_ = FilterType::VIDEO_DECODER;
54     bufferMetaType_ = Plugin::BufferMetaType::VIDEO;
55     pluginType_ = Plugin::PluginType::VIDEO_DECODER;
56     codecMode_ = std::move(codecMode);
57 }
58 
~VideoDecoderFilter()59 VideoDecoderFilter::~VideoDecoderFilter()
60 {
61     MEDIA_LOG_D("video decoder dtor called");
62     if (plugin_) {
63         plugin_->Stop();
64         plugin_->Deinit();
65     }
66     (void)codecMode_->Release();
67 }
68 
Prepare()69 ErrorCode VideoDecoderFilter::Prepare()
70 {
71     MEDIA_LOG_I("video decoder prepare called.");
72     codecMode_->SetBufferPoolSize(static_cast<uint32_t>(DEFAULT_IN_BUFFER_POOL_SIZE),
73                                   static_cast<uint32_t>(DEFAULT_OUT_BUFFER_POOL_SIZE));
74     (void)codecMode_->Prepare();
75     return CodecFilterBase::Prepare();
76 }
77 
Start()78 ErrorCode VideoDecoderFilter::Start()
79 {
80     return CodecFilterBase::Start();
81 }
82 
Stop()83 ErrorCode VideoDecoderFilter::Stop()
84 {
85     MEDIA_LOG_D("video decoder stop start.");
86     FAIL_RETURN(CodecFilterBase::Stop());
87     MEDIA_LOG_D("video decoder stop end.");
88     return ErrorCode::SUCCESS;
89 }
90 
FlushStart()91 void VideoDecoderFilter::FlushStart()
92 {
93     MEDIA_LOG_I("Video decoder FlushStart entered.");
94     codecMode_->FlushStart();
95     CodecFilterBase::FlushStart();
96 }
97 
FlushEnd()98 void VideoDecoderFilter::FlushEnd()
99 {
100     MEDIA_LOG_I("Video decoder FlushEnd entered.");
101     codecMode_->FlushEnd();
102     CodecFilterBase::FlushEnd();
103 }
104 
Configure(const std::string & inPort,const std::shared_ptr<const Plugin::Meta> & upstreamMeta,Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)105 bool VideoDecoderFilter::Configure(const std::string& inPort, const std::shared_ptr<const Plugin::Meta>& upstreamMeta,
106                                    Plugin::Meta& upstreamParams, Plugin::Meta& downstreamParams)
107 {
108     PROFILE_BEGIN("video decoder configure begin");
109     FALSE_RETURN_V(CodecFilterBase::Configure(inPort, upstreamMeta, upstreamParams, downstreamParams), false);
110     PROFILE_END("video decoder configure end");
111     return true;
112 }
113 
Negotiate(const std::string & inPort,const std::shared_ptr<const Plugin::Capability> & upstreamCap,Plugin::Capability & negotiatedCap,const Plugin::Meta & upstreamParams,Plugin::Meta & downstreamParams)114 bool VideoDecoderFilter::Negotiate(const std::string& inPort,
115                                    const std::shared_ptr<const Plugin::Capability>& upstreamCap,
116                                    Plugin::Capability& negotiatedCap,
117                                    const Plugin::Meta& upstreamParams,
118                                    Plugin::Meta& downstreamParams)
119 {
120     FALSE_RETURN_V(CodecFilterBase::Negotiate(inPort, upstreamCap, negotiatedCap, upstreamParams, downstreamParams),
121                    false);
122     MEDIA_LOG_D("video decoder negotiate end");
123     return true;
124 }
125 
GetOutBufferPoolSize()126 uint32_t VideoDecoderFilter::GetOutBufferPoolSize()
127 {
128     return DEFAULT_OUT_BUFFER_POOL_SIZE;
129 }
130 
CalculateBufferSize(const std::shared_ptr<const Plugin::Meta> & meta)131 uint32_t VideoDecoderFilter::CalculateBufferSize(const std::shared_ptr<const Plugin::Meta>& meta)
132 {
133     uint32_t bufferSize = 0;
134     uint32_t vdecWidth;
135     uint32_t vdecHeight;
136     Plugin::VideoPixelFormat vdecFormat;
137 
138     FALSE_RETURN_V(meta->Get<Plugin::Tag::VIDEO_WIDTH>(vdecWidth), 0);
139     FALSE_RETURN_V(meta->Get<Plugin::Tag::VIDEO_HEIGHT>(vdecHeight), 0);
140     FALSE_RETURN_V(meta->Get<Plugin::Tag::VIDEO_PIXEL_FORMAT>(vdecFormat), 0);
141 
142     // YUV420: size = stride * height * 1.5
143     uint32_t stride = Plugin::AlignUp(vdecWidth, VIDEO_ALIGN_SIZE);
144     if (vdecFormat == Plugin::VideoPixelFormat::YUV420P ||
145         vdecFormat == Plugin::VideoPixelFormat::NV21 ||
146         vdecFormat == Plugin::VideoPixelFormat::NV12) {
147         bufferSize = static_cast<uint32_t>(Plugin::AlignUp(stride, VIDEO_ALIGN_SIZE) *
148                                            Plugin::AlignUp(vdecHeight, VIDEO_ALIGN_SIZE) * VIDEO_PIX_DEPTH);
149         MEDIA_LOG_D("YUV output buffer size: " PUBLIC_LOG_U32, bufferSize);
150     } else if (vdecFormat == Plugin::VideoPixelFormat::RGBA ||
151                vdecFormat == Plugin::VideoPixelFormat::ARGB ||
152                vdecFormat == Plugin::VideoPixelFormat::ABGR ||
153                vdecFormat == Plugin::VideoPixelFormat::BGRA) {
154         bufferSize = static_cast<uint32_t>(Plugin::AlignUp(stride, VIDEO_ALIGN_SIZE) *
155                                             Plugin::AlignUp(vdecHeight, VIDEO_ALIGN_SIZE) * 4); // 4: 32bit
156         MEDIA_LOG_D("RGBA output buffer size: " PUBLIC_LOG_U32, bufferSize);
157     } else {
158         // need to check video sink support and calc buffer size
159         MEDIA_LOG_E("Unsupported video pixel format: " PUBLIC_LOG_U32, vdecFormat);
160     }
161     return bufferSize;
162 }
163 
GetNegotiateParams(const Plugin::Meta & upstreamParams)164 Plugin::Meta VideoDecoderFilter::GetNegotiateParams(const Plugin::Meta& upstreamParams)
165 {
166     // video, need to get the max buffer num from plugin capability when use hdi as codec plugin interfaces
167     Plugin::Meta proposeParams = upstreamParams;
168     proposeParams.Set<Plugin::Tag::VIDEO_MAX_SURFACE_NUM>(DEFAULT_OUT_BUFFER_POOL_SIZE);
169     return proposeParams;
170 }
171 
GetAllocator()172 std::shared_ptr<Allocator> VideoDecoderFilter::GetAllocator()
173 {
174 #ifndef OHOS_LITE
175     // Use sink allocator first, zero copy while passing data
176     Plugin::Tag tag = Plugin::Tag::BUFFER_ALLOCATOR;
177     auto ite = sinkParams_.Find(tag);
178     if (ite != std::end(sinkParams_)) {
179         if (Plugin::Any::IsSameTypeWith<std::shared_ptr<Plugin::SurfaceAllocator>>(ite->second)) {
180             MEDIA_LOG_D("Get SurfaceAllocator from sink");
181             return Plugin::AnyCast<std::shared_ptr<Plugin::SurfaceAllocator>>(ite->second);
182         }
183     }
184 #endif
185     return plugin_->GetAllocator();
186 }
187 
UpdateParams(const std::shared_ptr<const Plugin::Meta> & upMeta,std::shared_ptr<Plugin::Meta> & meta)188 void VideoDecoderFilter::UpdateParams(const std::shared_ptr<const Plugin::Meta>& upMeta,
189                                       std::shared_ptr<Plugin::Meta>& meta)
190 {
191     MEDIA_LOG_D("UpdateParams begin");
192 }
193 
OnInputBufferDone(const std::shared_ptr<Plugin::Buffer> & input)194 void VideoDecoderFilter::OnInputBufferDone(const std::shared_ptr<Plugin::Buffer>& input)
195 {
196     MEDIA_LOG_DD("VideoDecoderFilter::OnInputBufferDone");
197 }
198 
OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer> & output)199 void VideoDecoderFilter::OnOutputBufferDone(const std::shared_ptr<Plugin::Buffer>& output)
200 {
201     codecMode_->OnOutputBufferDone(output);
202 }
203 } // namespace Pipeline
204 } // namespace Media
205 } // namespace OHOS
206 #endif
207