-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
v4l2_track_source.cpp
97 lines (78 loc) · 3.27 KB
/
v4l2_track_source.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "v4l2_track_source.h"
#include <cmath>
// WebRTC
#include <api/video/i420_buffer.h>
#include <api/video/video_frame_buffer.h>
#include <rtc_base/timestamp_aligner.h>
#include <third_party/libyuv/include/libyuv.h>
static const int kBufferAlignment = 64;
rtc::scoped_refptr<V4L2TrackSource> V4L2TrackSource::Create(
std::shared_ptr<V4L2Capture> capture) {
auto obj = rtc::make_ref_counted<V4L2TrackSource>(std::move(capture));
obj->StartTrack();
return obj;
}
V4L2TrackSource::V4L2TrackSource(std::shared_ptr<V4L2Capture> capture)
: capture_(capture),
width_(capture->width()),
height_(capture->height()),
config_width_(capture->width()),
config_height_(capture->height()),
src_video_type_(capture->type()) {}
V4L2TrackSource::~V4L2TrackSource() {
// todo: tell capture unsubscribe observer.
}
void V4L2TrackSource::StartTrack() {
Init();
auto observer = capture_->AsObservable();
observer->Subscribe([&](Buffer buffer) {
OnFrameCaptured(buffer);
});
}
void V4L2TrackSource::OnFrameCaptured(Buffer buffer) {
rtc::scoped_refptr<webrtc::VideoFrameBuffer> dst_buffer = nullptr;
rtc::TimestampAligner timestamp_aligner_;
const int64_t timestamp_us = rtc::TimeMicros();
const int64_t translated_timestamp_us =
timestamp_aligner_.TranslateTimestamp(timestamp_us, rtc::TimeMicros());
int adapted_width, adapted_height, crop_width, crop_height, crop_x, crop_y;
if (!AdaptFrame(width_, height_, timestamp_us, &adapted_width, &adapted_height,
&crop_width, &crop_height, &crop_x, &crop_y)) {
return;
}
rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer(webrtc::I420Buffer::Create(width_, height_));
i420_buffer->InitializeData();
if (libyuv::ConvertToI420((uint8_t *)buffer.start, buffer.length,
i420_buffer.get()->MutableDataY(), i420_buffer.get()->StrideY(),
i420_buffer.get()->MutableDataU(), i420_buffer.get()->StrideU(),
i420_buffer.get()->MutableDataV(), i420_buffer.get()->StrideV(),
0, 0, width_, height_, width_, height_, libyuv::kRotate0,
ConvertVideoType(src_video_type_)) < 0) {
// "ConvertToI420 Failed"
}
dst_buffer = i420_buffer;
if (adapted_width != width_ || adapted_height != height_) {
int dst_stride = std::ceil((double)adapted_width / kBufferAlignment) * kBufferAlignment;
i420_buffer = webrtc::I420Buffer::Create(adapted_width, adapted_height,
dst_stride, dst_stride/2, dst_stride/2);
i420_buffer->ScaleFrom(*dst_buffer->ToI420());
dst_buffer = i420_buffer;
}
OnFrame(webrtc::VideoFrame::Builder()
.set_video_frame_buffer(dst_buffer)
.set_rotation(webrtc::kVideoRotation_0)
.set_timestamp_us(translated_timestamp_us)
.build());
}
webrtc::MediaSourceInterface::SourceState V4L2TrackSource::state() const {
return SourceState::kLive;
}
bool V4L2TrackSource::remote() const {
return false;
}
bool V4L2TrackSource::is_screencast() const {
return false;
}
absl::optional<bool> V4L2TrackSource::needs_denoising() const {
return false;
}