aboutsummaryrefslogtreecommitdiffstats
path: root/app/main.cpp
blob: 967f5e4fe1b97bac80e109ae55e892d06d5ca2ff (plain)
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
/*
 * Copyright (C) 2018 Konsulko Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>
#include <iostream>
#include <cstring>
#include <gst/gst.h>
#include "surface.hpp"

#undef DEBUG

int main(int argc, char *argv[])
{
	int port = 0;
	std::string token;
	std::string role = "receiver";

	try {
		port = std::stol(argv[1]);
		token = argv[2];
	} catch (const std::invalid_argument& e) {
		std::cerr << "Invalid argument" << std::endl;
		exit(1);
	} catch (const std::out_of_range& e) {
		std::cerr << "Port out of range" << std::endl;
		exit(1);
	}

	// NOTES:
	// (1) For reference, the pipeline used is based on the gst-launch-1.0 command in the ad hoc unit
        //     file in the previous hand-rolled CES demo:
	//
	//     udpsrc port=5005 ! application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! h264parse config-interval=1 disable-passthrough=true ! decodebin ! vaapisink
	//
	// (2) waylandsink is a bit broken, as it needs a RGB format, but its caps include non-RGB formats
	//     This results in crashes when videoconvert doesn't end up in the pipeline, so care must be taken
	//     if it is used, e.g. for testing:
	//
	//     videotestsrc pattern=smpte ! video/x-raw,format=BGRx,width=384,height=368 ! waylandsink
	//

	std::string pipeline_str = \
		"udpsrc port=5005 ! application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! h264parse config-interval=1 disable-passthrough=true ! decodebin ! ";
	GstPlugin *plugin = gst_registry_find_plugin(gst_registry_get (), "vaapisink");
	if(plugin) {
		pipeline_str += "vaapisink";
		gst_object_unref(plugin);
	} else {
		pipeline_str += "videoconvert ! video/x-raw,format=BGRx,width=384,height=368 ! waylandsink";
	}
#ifdef DEBUG
	std::cout << "Using pipeline: " << pipeline_str << std::endl;
#endif

        // Initialize GStreamer
#ifdef DEBUG
	int gargc = 2;
	char **gargv = (char**) malloc(2 * sizeof(char*));
	gargv[0] = strdup(argv[0]);
	gargv[1] = strdup("--gst-debug-level=2");
	gst_init(&gargc, &gargv);
#else
        gst_init(NULL, NULL);
#endif

	// Create our IVI surface handler
	SurfaceHandler handler(port, token, role);

	GstElement *pipeline = gst_parse_launch(pipeline_str.c_str(), NULL);
	if(!pipeline) {
		std::cerr << "gstreamer pipeline construction failed!" << std::endl;
		exit(1);
	}

	// Start pipeline
	gst_element_set_state(pipeline, GST_STATE_PLAYING);
	std::cout << "gstreamer pipeline running" << std::endl;

	// Wait until error or EOS
	GstBus *bus = gst_element_get_bus(pipeline);
	GstMessage *msg = gst_bus_timed_pop_filtered(bus,
						     GST_CLOCK_TIME_NONE,
						     (GstMessageType) (GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

	// Free resources
	if(msg != NULL)
		gst_message_unref(msg);
	gst_object_unref(bus);
	gst_element_set_state(pipeline, GST_STATE_NULL);
	gst_object_unref(pipeline);

	return 0;
}