ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ImageCapturer.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <Logging.h>
11 #include <api/video/i420_buffer.h>
12 #include <libyuv/convert.h>
13 #include <libyuv/video_common.h>
14 #include <media/base/video_broadcaster.h>
15 #include <media/base/video_common.h>
16 
17 #include <memory>
18 
19 #include "core/Tensor.h"
20 
21 namespace cloudViewer {
22 namespace visualization {
23 namespace webrtc_server {
24 
25 ImageCapturer::ImageCapturer(const std::string& url_,
26  const std::map<std::string, std::string>& opts)
27  : ImageCapturer(opts) {}
28 
30 
32  const std::string& url,
33  const std::map<std::string, std::string>& opts) {
34  std::unique_ptr<ImageCapturer> image_capturer(new ImageCapturer(url, opts));
35  return image_capturer.release();
36 }
37 
38 ImageCapturer::ImageCapturer(const std::map<std::string, std::string>& opts)
39  : width_(0), height_(0) {
40  if (opts.find("width") != opts.end()) {
41  width_ = std::stoi(opts.at("width"));
42  }
43  if (opts.find("height") != opts.end()) {
44  height_ = std::stoi(opts.at("height"));
45  }
46 }
47 
49  const std::shared_ptr<core::Tensor>& frame) {
50  int height = (int)frame->GetShape(0);
51  int width = (int)frame->GetShape(1);
52 
53  rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer =
54  webrtc::I420Buffer::Create(width, height);
55 
56  // frame->data()
57  const int conversion_result = libyuv::ConvertToI420(
58  frame->GetDataPtr<uint8_t>(), 0, i420_buffer->MutableDataY(),
59  i420_buffer->StrideY(), i420_buffer->MutableDataU(),
60  i420_buffer->StrideU(), i420_buffer->MutableDataV(),
61  i420_buffer->StrideV(), 0, 0, width, height, i420_buffer->width(),
62  i420_buffer->height(), libyuv::kRotate0, ::libyuv::FOURCC_RAW);
63 
64  if (conversion_result >= 0) {
65  webrtc::VideoFrame video_frame(i420_buffer,
66  webrtc::VideoRotation::kVideoRotation_0,
67  rtc::TimeMicros());
68  if ((height_ == 0) && (width_ == 0)) {
69  broadcaster_.OnFrame(video_frame);
70  } else {
71  int height = height_;
72  int width = width_;
73  if (height == 0) {
74  height = (video_frame.height() * width) / video_frame.width();
75  } else if (width == 0) {
76  width = (video_frame.width() * height) / video_frame.height();
77  }
78  int stride_y = width;
79  int stride_uv = (width + 1) / 2;
80  rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer =
81  webrtc::I420Buffer::Create(width, height, stride_y,
82  stride_uv, stride_uv);
83  scaled_buffer->ScaleFrom(
84  *video_frame.video_frame_buffer()->ToI420());
85  webrtc::VideoFrame frame = webrtc::VideoFrame(
86  scaled_buffer, webrtc::kVideoRotation_0, rtc::TimeMicros());
87 
88  broadcaster_.OnFrame(frame);
89  }
90  } else {
91  utility::LogError("ImageCapturer:OnCaptureResult conversion error: {}",
92  conversion_result);
93  }
94 }
95 
96 // Overide rtc::VideoSourceInterface<webrtc::VideoFrame>.
98  rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
99  const rtc::VideoSinkWants& wants) {
100  broadcaster_.AddOrUpdateSink(sink, wants);
101 }
102 
104  rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
105  broadcaster_.RemoveSink(sink);
106 }
107 
108 } // namespace webrtc_server
109 } // namespace visualization
110 } // namespace cloudViewer
Rect frame
int width
int height
static ImageCapturer * Create(const std::string &url, const std::map< std::string, std::string > &opts)
ImageCapturer(const std::string &url_, const std::map< std::string, std::string > &opts)
virtual void RemoveSink(rtc::VideoSinkInterface< webrtc::VideoFrame > *sink) override
virtual void AddOrUpdateSink(rtc::VideoSinkInterface< webrtc::VideoFrame > *sink, const rtc::VideoSinkWants &wants) override
void OnCaptureResult(const std::shared_ptr< core::Tensor > &frame)
#define LogError(...)
Definition: Logging.h:60
Generic file read and write utility for python interface.