• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 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 #if !defined(OHOS_LITE) && defined(RECORDER_SUPPORT) && defined(VIDEO_SUPPORT)
17 
18 #define HST_LOG_TAG "VideoCapturePlugin"
19 
20 #include "video_capture_plugin.h"
21 #include <algorithm>
22 #include <cmath>
23 #include "foundation/log.h"
24 #include "plugin/common/plugin_time.h"
25 #include "utils/utils.h"
26 #include "utils/constants.h"
27 
28 namespace {
29 // register plugins
30 using namespace OHOS::Media::Plugin;
31 using namespace VideoCapture;
VideoCapturePluginCreater(const std::string & name)32 std::shared_ptr<SourcePlugin> VideoCapturePluginCreater(const std::string &name)
33 {
34     return std::make_shared<VideoCapturePlugin>(name);
35 }
36 
VideoCaptureRegister(const std::shared_ptr<Register> & reg)37 Status VideoCaptureRegister(const std::shared_ptr<Register> &reg)
38 {
39     SourcePluginDef definition;
40     definition.name = "AudioCapture";
41     definition.description = "Video capture from audio service";
42     definition.rank = 100; // 100: max rank
43     definition.inputType = SrcInputType::VID_SURFACE_YUV;
44     definition.creator = VideoCapturePluginCreater;
45     Capability outCaps(OHOS::Media::MEDIA_MIME_VIDEO_RAW);
46     definition.outCaps.push_back(outCaps);
47     // add es outCaps later
48     return reg->AddPlugin(definition);
49 }
__anon4a561c470202null50 PLUGIN_DEFINITION(StdVideoCapture, LicenseType::APACHE_V2, VideoCaptureRegister, [] {});
51 }
52 
53 namespace OHOS {
54 namespace Media {
55 namespace Plugin {
56 using namespace OHOS::Media::Plugin;
57 
58 constexpr int32_t DEFAULT_SURFACE_QUEUE_SIZE = 6;
59 constexpr int32_t DEFAULT_SURFACE_SIZE = 1024 * 1024;
60 constexpr int32_t DEFAULT_VIDEO_WIDTH = 1920;
61 constexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080;
62 
Alloc(size_t size)63 void* VideoCaptureAllocator::Alloc(size_t size)
64 {
65     if (size == 0) {
66         return nullptr;
67     }
68     return reinterpret_cast<void*>(new (std::nothrow) uint8_t[size]); // NOLINT: cast
69 }
70 
Free(void * ptr)71 void VideoCaptureAllocator::Free(void* ptr) // NOLINT: void*
72 {
73     if (ptr != nullptr) {
74         delete[](uint8_t*) ptr;
75     }
76 }
77 
VideoCapturePlugin(std::string name)78 VideoCapturePlugin::VideoCapturePlugin(std::string name)
79     : SourcePlugin(std::move(name)),
80       width_(DEFAULT_VIDEO_WIDTH),
81       height_(DEFAULT_VIDEO_HEIGHT)
82 {
83     MEDIA_LOG_D("IN");
84 }
85 
~VideoCapturePlugin()86 VideoCapturePlugin::~VideoCapturePlugin()
87 {
88     MEDIA_LOG_D("IN");
89 }
90 
Init()91 Status VideoCapturePlugin::Init()
92 {
93     MEDIA_LOG_D("IN");
94     return Status::OK;
95 }
96 
Deinit()97 Status VideoCapturePlugin::Deinit()
98 {
99     MEDIA_LOG_D("IN");
100     return Status::OK;
101 }
102 
ConfigSurfaceConsumer()103 void VideoCapturePlugin::ConfigSurfaceConsumer()
104 {
105     auto ret = surfaceConsumer_->SetUserData("video_width", std::to_string(width_));
106     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
107         MEDIA_LOG_E("set video width fail");
108     }
109     ret = surfaceConsumer_->SetUserData("video_height", std::to_string(height_));
110     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
111         MEDIA_LOG_E("set video height fail");
112     }
113     ret = surfaceConsumer_->SetQueueSize(DEFAULT_SURFACE_QUEUE_SIZE);
114     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
115         MEDIA_LOG_E("set queue size fail");
116     }
117     ret = surfaceConsumer_->SetUserData("surface_size", std::to_string(DEFAULT_SURFACE_SIZE));
118     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
119         MEDIA_LOG_E("set surface size fail");
120     }
121     ret = surfaceConsumer_->SetDefaultWidthAndHeight(width_, height_);
122     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
123         MEDIA_LOG_E("set surface width and height fail");
124     }
125 }
126 
Prepare()127 Status VideoCapturePlugin::Prepare()
128 {
129     MEDIA_LOG_D("IN");
130     surfaceConsumer_ = Surface::CreateSurfaceAsConsumer();
131     if (!surfaceConsumer_) {
132         MEDIA_LOG_E("CreateSurfaceAsConsumer() fail");
133         return Status::ERROR_UNKNOWN;
134     }
135     sptr<IBufferConsumerListener> consumerListener = new (std::nothrow) SurfaceConsumerListener(*this);
136     if (!consumerListener) {
137         MEDIA_LOG_E("Malloc SurfaceConsumerListener fail");
138         return Status::ERROR_NO_MEMORY;
139     }
140     if (surfaceConsumer_->RegisterConsumerListener(consumerListener) != OHOS::SurfaceError::SURFACE_ERROR_OK) {
141         MEDIA_LOG_E("RegisterConsumerListener() fail");
142         return Status::ERROR_UNKNOWN;
143     }
144     sptr<IBufferProducer> bufferProducer = surfaceConsumer_->GetProducer();
145     if (!bufferProducer) {
146         MEDIA_LOG_E("Malloc GetProducer fail");
147         return Status::ERROR_UNKNOWN;
148     }
149     surfaceProducer_ = Surface::CreateSurfaceAsProducer(bufferProducer);
150     if (!surfaceProducer_) {
151         MEDIA_LOG_E("CreateSurfaceAsProducer() fail");
152         return Status::ERROR_UNKNOWN;
153     }
154     ConfigSurfaceConsumer();
155     return Status::OK;
156 }
157 
Reset()158 Status VideoCapturePlugin::Reset()
159 {
160     MEDIA_LOG_D("IN");
161     return Status::OK;
162 }
163 
Start()164 Status VideoCapturePlugin::Start()
165 {
166     MEDIA_LOG_D("IN");
167     OHOS::Media::OSAL::ScopedLock lock(mutex_);
168     if (isStop_.load()) {
169         if (curTimestampNs_ < stopTimestampNs_) {
170             MEDIA_LOG_E("Get wrong audio time");
171         }
172         totalPauseTimeNs_ += std::fabs(curTimestampNs_ - stopTimestampNs_);
173         isStop_ = false;
174     }
175     return Status::OK;
176 }
177 
Stop()178 Status VideoCapturePlugin::Stop()
179 {
180     MEDIA_LOG_D("IN");
181     OHOS::Media::OSAL::ScopedLock lock(mutex_);
182     if (!isStop_.load()) {
183         stopTimestampNs_ = curTimestampNs_;
184         isStop_ = true;
185     }
186     return Status::OK;
187 }
188 
IsParameterSupported(Tag tag)189 bool VideoCapturePlugin::IsParameterSupported(Tag tag)
190 {
191     MEDIA_LOG_D("IN");
192     return false;
193 }
194 
GetParameter(Tag tag,ValueType & value)195 Status VideoCapturePlugin::GetParameter(Tag tag, ValueType& value)
196 {
197     MEDIA_LOG_D("IN");
198     switch (tag) {
199         case Tag::VIDEO_SURFACE: {
200             value = surfaceProducer_.GetRefPtr();
201             break;
202         }
203         default:
204             MEDIA_LOG_I("Unknown key");
205             break;
206     }
207     return Status::OK;
208 }
209 
SetParameter(Tag tag,const ValueType & value)210 Status VideoCapturePlugin::SetParameter(Tag tag, const ValueType& value)
211 {
212     switch (tag) {
213         case Tag::VIDEO_HEIGHT: {
214             if (value.SameTypeWith(typeid(uint32_t))) {
215                 height_ = Plugin::AnyCast<uint32_t>(value);
216             }
217             break;
218         }
219         case Tag::VIDEO_WIDTH: {
220             if (value.SameTypeWith(typeid(uint32_t))) {
221                 width_ = Plugin::AnyCast<uint32_t>(value);
222             }
223             break;
224         }
225         default:
226             MEDIA_LOG_I("Unknown key");
227             break;
228     }
229     return Status::OK;
230 }
231 
GetAllocator()232 std::shared_ptr<Allocator> VideoCapturePlugin::GetAllocator()
233 {
234     MEDIA_LOG_D("IN");
235     return mAllocator_;
236 }
237 
SetCallback(Callback * cb)238 Status VideoCapturePlugin::SetCallback(Callback* cb)
239 {
240     MEDIA_LOG_D("IN");
241     UNUSED_VARIABLE(cb);
242     return Status::ERROR_UNIMPLEMENTED;
243 }
244 
SetSource(std::shared_ptr<MediaSource> source)245 Status VideoCapturePlugin::SetSource(std::shared_ptr<MediaSource> source)
246 {
247     UNUSED_VARIABLE(source);
248     return Status::ERROR_UNIMPLEMENTED;
249 }
250 
AcquireSurfaceBuffer()251 Status VideoCapturePlugin::AcquireSurfaceBuffer()
252 {
253     auto ret = surfaceConsumer_->AcquireBuffer(surfaceBuffer_, fence_, timestamp_, damage_);
254     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
255         MEDIA_LOG_E("surfaceConsumer AcquireBuffer() fail: %" PUBLIC_LOG "u", ret);
256         return Status::ERROR_UNKNOWN;
257     }
258     ret = surfaceBuffer_->ExtraGet("dataSize", bufferSize_);
259     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || bufferSize_ <= 0) {
260         MEDIA_LOG_E("surfaceBuffer get data size fail: %" PUBLIC_LOG "u", ret);
261         return Status::ERROR_UNKNOWN;
262     }
263     ret = surfaceBuffer_->ExtraGet("isKeyFrame", isKeyFrame_);
264     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
265         MEDIA_LOG_E("surfaceBuffer get isKeyFrame fail: %" PUBLIC_LOG "u", ret);
266         return Status::ERROR_UNKNOWN;
267     }
268     int64_t pts;
269     ret = surfaceBuffer_->ExtraGet("timeStamp", pts);
270     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || pts < 0) {
271         MEDIA_LOG_E("surfaceBuffer get data size fail: %" PUBLIC_LOG "u", ret);
272         return Status::ERROR_UNKNOWN;
273     }
274     if (pts < curTimestampNs_) {
275         MEDIA_LOG_W("Get wrong timestamp from surface buffer");
276     }
277     curTimestampNs_ = static_cast<uint64_t>(pts);
278     return Status::OK;
279 }
280 
Read(std::shared_ptr<Buffer> & buffer,size_t expectedLen)281 Status VideoCapturePlugin::Read(std::shared_ptr<Buffer>& buffer, size_t expectedLen)
282 {
283     OHOS::Media::OSAL::ScopedLock lock(mutex_);
284     if (!buffer) {
285         return Status::ERROR_INVALID_PARAMETER;
286     }
287     auto bufferMeta = buffer->GetBufferMeta();
288     if (!bufferMeta || bufferMeta->GetType() != BufferMetaType::VIDEO ||  surfaceConsumer_ == nullptr) {
289         return Status::ERROR_INVALID_PARAMETER;
290     }
291     std::shared_ptr<Memory> bufData;
292     if (buffer->IsEmpty()) {
293         bufData = buffer->AllocMemory(GetAllocator(), expectedLen);
294     } else {
295         bufData = buffer->GetMemory();
296     }
297     if (bufData->GetMemoryType() != MemoryType::VIRTUAL_ADDR || bufData->GetCapacity() <= 0) {
298         return Status::ERROR_NO_MEMORY;
299     }
300     readCond_.Wait(lock, [this] { return bufferCnt_ > 0 || isStop_.load(); });
301     if (isStop_.load()) {
302         MEDIA_LOG_I("flush or EOS, skip read buffer");
303         return Status::END_OF_STREAM;
304     }
305     auto ret = AcquireSurfaceBuffer();
306     if (ret != Status::OK) {
307         MEDIA_LOG_E("AcquireSurfaceBuffer fail: %" PUBLIC_LOG "d", ret);
308         return ret;
309     }
310     if (bufData->Write(static_cast<const uint8_t*>(surfaceBuffer_->GetVirAddr()), bufferSize_) != bufferSize_) {
311         MEDIA_LOG_E("write buffer data fail");
312         return Status::ERROR_UNKNOWN;
313     }
314     Ns2HstTime(curTimestampNs_ - totalPauseTimeNs_, reinterpret_cast<int64_t &>(buffer->pts));
315     bufferCnt_--;
316     return Status::OK;
317 }
318 
GetSize(size_t & size)319 Status VideoCapturePlugin::GetSize(size_t& size)
320 {
321     if (bufferSize_ == 0) {
322         return Status::ERROR_INVALID_PARAMETER;
323     }
324     size = bufferSize_;
325     MEDIA_LOG_D("bufferSize_: %" PUBLIC_LOG "zu", size);
326     return Status::OK;
327 }
328 
IsSeekable()329 bool VideoCapturePlugin::IsSeekable()
330 {
331     return false;
332 }
333 
SeekTo(uint64_t offset)334 Status VideoCapturePlugin::SeekTo(uint64_t offset)
335 {
336     UNUSED_VARIABLE(offset);
337     return Status::ERROR_UNIMPLEMENTED;
338 }
339 
OnBufferAvailable()340 void VideoCapturePlugin::SurfaceConsumerListener::OnBufferAvailable()
341 {
342     return owner_.OnBufferAvailable();
343 }
344 
OnBufferAvailable()345 void VideoCapturePlugin::OnBufferAvailable()
346 {
347     if (!surfaceConsumer_) {
348         return;
349     }
350     OHOS::Media::OSAL::ScopedLock lock(mutex_);
351     bufferCnt_++;
352     if (bufferCnt_ == 1) {
353         readCond_.NotifyAll();
354     }
355 }
356 } // namespace Plugin
357 } // namespace Media
358 } // namespace OHOS
359 #endif