2
* Copyright (C) 2015 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3, as published
6
* by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranties of
10
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License along
14
* with this program. If not, see <http://www.gnu.org/licenses/>.
18
#include "mcs/logger.h"
20
#include "mcs/common/threadedexecutor.h"
22
#include "mcs/video/statistics.h"
23
#include "mcs/video/videoformat.h"
25
#include "mcs/streaming/mpegtspacketizer.h"
26
#include "mcs/streaming/rtpsender.h"
28
#include "mcs/mir/sourcemediamanager.h"
30
#include "mcs/android/h264encoder.h"
35
SourceMediaManager::Ptr SourceMediaManager::Create(const std::string &remote_address) {
36
return std::shared_ptr<SourceMediaManager>(new SourceMediaManager(remote_address));
39
SourceMediaManager::SourceMediaManager(const std::string &remote_address) :
40
remote_address_(remote_address),
41
state_(State::Stopped) {
44
SourceMediaManager::~SourceMediaManager() {
45
if (state_ != State::Stopped)
48
mcs::video::Statistics::Instance()->Dump();
51
bool SourceMediaManager::Configure() {
52
auto rr = mcs::video::ExtractRateAndResolution(format_);
54
MCS_DEBUG("dimensions: %dx%d@%d", rr.width, rr.height, rr.framerate);
56
// FIXME we don't support any other mode than extend for now as that means some
57
// additional work from mir to still give us properly sized frames we can hand
59
Screencast::DisplayOutput output{Screencast::DisplayMode::kExtend, rr.width, rr.height};
61
connector_ = std::make_shared<mcs::mir::Screencast>(output);
62
if (!connector_->IsValid())
65
encoder_ = mcs::android::H264Encoder::Create();
67
int profile = 0, level = 0, constraint = 0;
68
mcs::video::ExtractProfileLevel(format_, &profile, &level, &constraint);
70
auto config = mcs::android::H264Encoder::DefaultConfiguration();
71
config.width = rr.width;
72
config.height = rr.height;
73
config.framerate = rr.framerate;
74
config.profile_idc = profile;
75
config.level_idc = level;
76
config.constraint_set = constraint;
78
if (!encoder_->Configure(config)) {
79
MCS_ERROR("Failed to configure encoder");
83
encoder_executor_ = mcs::common::ThreadedExecutor::Create(encoder_, "Encoder");
85
renderer_ = mcs::mir::StreamRenderer::Create(connector_, encoder_);
86
renderer_->SetDimensions(rr.width, rr.height);
88
auto rtp_sender = mcs::streaming::RTPSender::Create(remote_address_, sink_port1_);
89
auto mpegts_packetizer = mcs::streaming::MPEGTSPacketizer::Create();
91
sender_ = mcs::streaming::MediaSender::Create(mpegts_packetizer, rtp_sender, config);
92
encoder_->SetDelegate(sender_);
97
void SourceMediaManager::StartPipeline() {
99
encoder_executor_->Start();
100
renderer_->StartThreaded();
103
void SourceMediaManager::StopPipeline() {
105
encoder_executor_->Stop();
109
void SourceMediaManager::Play() {
110
if (!IsPaused() || !renderer_)
117
state_ = State::Playing;
120
void SourceMediaManager::Pause() {
121
if (IsPaused()|| !renderer_)
128
state_ = State::Paused;
131
void SourceMediaManager::Teardown() {
132
if (state_ == State::Stopped || !renderer_)
139
state_ = State::Stopped;
142
bool SourceMediaManager::IsPaused() const {
143
return state_ == State::Paused ||
144
state_ == State::Stopped;
147
void SourceMediaManager::SendIDRPicture() {
151
encoder_->SendIDRFrame();
154
int SourceMediaManager::GetLocalRtpPort() const {
155
MCS_DEBUG("local port %d", sender_->LocalRTPPort());
156
return sender_->LocalRTPPort();