~phablet-team/aethercast/fix-for-microsoft-dongle

« back to all changes in this revision

Viewing changes to src/mcs/mirsourcemediamanager.cpp

Add hardware encoding and video streaming support.

The hardware encoding is currently only for Android 5.x based devices. On all others encoding will simply not work. The streaming part of aethercast (MPEGTS packetizing, RTP sending) as based on some code from Android.

Approved by PS Jenkins bot, Thomas Voß, Jim Hodapp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2015 Canonical, Ltd.
3
 
 *
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.
7
 
 *
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.
12
 
 *
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/>.
15
 
 *
16
 
 */
17
 
 
18
 
#include <sstream>
19
 
 
20
 
#include "mirsourcemediamanager.h"
21
 
#include "utils.h"
22
 
#include "logger.h"
23
 
 
24
 
namespace mcs {
25
 
MirSourceMediaManager::MirSourceMediaManager(const std::string &remote_address) :
26
 
    remote_address_(remote_address) {
27
 
}
28
 
 
29
 
MirSourceMediaManager::~MirSourceMediaManager() {
30
 
}
31
 
 
32
 
SharedGObject<GstElement> MirSourceMediaManager::ConstructPipeline(const wds::H264VideoFormat &format) {
33
 
    int width = 0, height = 0;
34
 
    std::string profile = "constrained-baseline";
35
 
 
36
 
    switch (format.profile) {
37
 
    case wds::CBP:
38
 
        profile = "constrained-baseline";
39
 
        break;
40
 
    case wds::CHP:
41
 
        profile = "high";
42
 
        break;
43
 
    }
44
 
 
45
 
    switch (format.type) {
46
 
    case wds::CEA:
47
 
        switch (format.rate_resolution) {
48
 
        case wds::CEA640x480p60:
49
 
            width = 640;
50
 
            height = 480;
51
 
            break;
52
 
        case wds::CEA720x480p60:
53
 
        case wds::CEA720x480i60:
54
 
            width = 720;
55
 
            height = 480;
56
 
            break;
57
 
        case wds::CEA720x576p50:
58
 
        case wds::CEA720x576i50:
59
 
            width = 720;
60
 
            height = 576;
61
 
            break;
62
 
        case wds::CEA1280x720p30:
63
 
        case wds::CEA1280x720p60:
64
 
            width = 1280;
65
 
            height = 720;
66
 
            break;
67
 
        case wds::CEA1920x1080p30:
68
 
        case wds::CEA1920x1080p60:
69
 
        case wds::CEA1920x1080i60:
70
 
            width = 1920;
71
 
            height = 1080;
72
 
            break;
73
 
        case wds::CEA1280x720p25:
74
 
        case wds::CEA1280x720p50:
75
 
        case wds::CEA1280x720p24:
76
 
            width = 1280;
77
 
            height = 720;
78
 
            break;
79
 
        case wds::CEA1920x1080p25:
80
 
        case wds::CEA1920x1080p50:
81
 
        case wds::CEA1920x1080i50:
82
 
        case wds::CEA1920x1080p24:
83
 
            width = 1920;
84
 
            height = 1080;
85
 
            break;
86
 
        default:
87
 
            break;
88
 
        }
89
 
        break;
90
 
    default:
91
 
        break;
92
 
    }
93
 
 
94
 
    std::stringstream ss;
95
 
    ss << "mirimagesrc mir-socket=/run/mir_socket ! videoconvert ! videoscale ! ";
96
 
    ss << Utils::Sprintf("video/x-raw,width=%d,height=%d ! ", width, height);
97
 
    ss << "videoflip method=counterclockwise ! queue2 ! video/x-raw,format=I420 ! ";
98
 
    ss << "x264enc aud=false byte-stream=true tune=zerolatency ! ";
99
 
    ss << Utils::Sprintf("video/x-h264,profile=%s ! ", profile.c_str());
100
 
    ss << "mpegtsmux ! rtpmp2tpay ! ";
101
 
    ss << Utils::Sprintf("udpsink name=sink host=%s port=%d", remote_address_.c_str(), sink_port1_);
102
 
 
103
 
    GError *error = nullptr;
104
 
    GstElement *pipeline = gst_parse_launch(ss.str().c_str(), &error);
105
 
    if (error) {
106
 
        ERROR("Failed to setup GStreamer pipeline: %s", error->message);
107
 
        g_error_free(error);
108
 
        return nullptr;
109
 
    }
110
 
 
111
 
    return make_shared_gobject(pipeline);
112
 
}
113
 
} // namespace mcs