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