-
Notifications
You must be signed in to change notification settings - Fork 0
/
media_source_stream.cpp
113 lines (87 loc) · 3.33 KB
/
media_source_stream.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// Created by disc on 1/16/2021.
//
#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mf")
#pragma comment(lib, "mfuuid")
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <utility>
#include "media_source_stream.h"
#include "utils.h"
media_source_stream::media_source_stream(ComPtr<IMFMediaSource> &&source,
properties props)
: source_(std::move(source)), target_props_(props) {
create_reader();
}
void media_source_stream::start(OnDataCallback on_data_cb) {
on_data_cb_ = std::move(on_data_cb);
active_ = true;
capture_thread_ = std::thread([this]() { run_capture(); });
}
void media_source_stream::create_reader() {
ComPtr<IMFAttributes> attributes;
THROW_IF_FAILED(MFCreateSourceReaderFromMediaSource(source_.Get(), nullptr,
&mf_reader_));
find_resolution();
// check if yuy2
ComPtr<IMFMediaType> curr_type;
mf_reader_->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
&curr_type);
GUID pixel_format;
curr_type->GetGUID(MF_MT_SUBTYPE, &pixel_format);
std::cout << "is yuy2? " << (pixel_format == MFVideoFormat_YUY2)
<< std::endl;
}
void media_source_stream::run_capture() {
ComPtr<IMFSample> sample;
DWORD stream_flags = 0;
while (active_) {
THROW_IF_FAILED(mf_reader_->ReadSample(
MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, nullptr, &stream_flags,
nullptr, &sample));
if (stream_flags & MF_SOURCE_READERF_STREAMTICK) { continue; }
if (!on_data_cb_) { continue; }
on_data_cb_(sample);
}
}
void media_source_stream::stop() {
active_ = false;
if (capture_thread_.joinable()) { capture_thread_.join(); }
}
media_source_stream::properties media_source_stream::get_properties() const {
ComPtr<IMFMediaType> media_type;
THROW_IF_FAILED(mf_reader_->GetCurrentMediaType(
MF_SOURCE_READER_FIRST_VIDEO_STREAM, &media_type));
properties p{};
THROW_IF_FAILED(MFGetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE,
&p.width, &p.height));
return p;
}
media_source_stream::~media_source_stream() {
if (active_) { stop(); }
}
void media_source_stream::find_resolution() {
const std::vector<std::pair<int, int>> candidates = {
{3840, 2160}, {2560, 1440}, {1920, 1080}, {1600, 900},
{1400, 900}, {1280, 720}, {854, 480}};
ComPtr<IMFMediaType> media_type;
THROW_IF_FAILED(mf_reader_->GetCurrentMediaType(
MF_SOURCE_READER_FIRST_VIDEO_STREAM, &media_type));
for (const auto &[width, height] : candidates) {
if (width * height > target_props_.width * target_props_.height) {
continue;
}
THROW_IF_FAILED(MFSetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE,
width, height));
if (mf_reader_->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
nullptr,
media_type.Get()) == S_OK) {
std::cout << "selected resolution: " << width << " x " << height
<< std::endl;
break;
}
}
}