summaryrefslogtreecommitdiff
path: root/samples/PlaybackTutorial1.cs
blob: c0a9ba349a3a0231487a610c4f55862e11820dcb (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Authors
//   Copyright (C) 2014 Stephan Sundermann <stephansundermann@gmail.com>

using System;
using Gst;
using System.Runtime.InteropServices;

namespace GstreamerSharp
{
	class Playback
	{
		// playbin flags
		static uint Video = (1 << 0); // We want video output
		static uint Audio = (1 << 1); // We want audio output
		static uint Text = (1 << 2);  // We want subtitle output

		static Element Playbin;
		static int NAudio, NVideo, NText;
		static int CurrentVideo, CurrentAudio, CurrentText;
		static GLib.MainLoop MainLoop;

		public static void Main (string[] args)
		{
			// Initialize GStreamer
			Application.Init (ref args);

			// Create the elements
			Playbin = ElementFactory.Make ("playbin", "playbin");

			if (Playbin == null) {
				Console.WriteLine ("Not all elements could be created.");
				return;
			}

			// Set the URI to play
			Playbin ["uri"] = "http://freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm";

			// Set flags to show Audio and Video but ignore Subtitles
			var flags = (uint)Playbin ["flags"];
			flags |= Audio | Video;
			flags &= ~Text;
			Playbin ["flags"] = flags;

			// Set connection speed. This will affect some internal decisions of playbin2
			Playbin ["connection-speed"] = 56;

			// Add a bus watch, so we get notified when a message arrives
			var bus = Playbin.Bus;
			bus.AddSignalWatch ();
			bus.Message += HandleMessage;

			// Start playing
			var ret = Playbin.SetState (State.Playing);
			if (ret == StateChangeReturn.Failure) {
				Console.WriteLine ("Unable to set the pipeline to the playing state.");
				return;
			}

			// Add a keyboard watch so we get notified of keystrokes
			GLib.Idle.Add (HandleKeyboard);
			MainLoop = new GLib.MainLoop ();
			MainLoop.Run ();

			// Free resources
			Playbin.SetState (State.Null);
		}

		static void HandleMessage (object o, MessageArgs args)
		{
			var msg = args.Message;
			switch (msg.Type) {
			case MessageType.Error:
				GLib.GException err;
				string debug;
				msg.ParseError (out err, out debug);
				Console.WriteLine ("Error received from element {0}: {1}", msg.Src, err.Message);
				Console.WriteLine ("Debugging information: {0}", debug != null ? debug : "none");
				MainLoop.Quit ();
				break;
			case MessageType.Eos:
				Console.WriteLine ("End-Of-Stream reached.");
				MainLoop.Quit ();
				break;
			case MessageType.StateChanged: {
					State oldState, newState, pendingState;
					msg.ParseStateChanged (out oldState, out newState, out pendingState);
					if (msg.Src == Playbin) {
						if (newState == State.Playing) {
							// Once we are in the playing state, analyze the streams
							AnalyzeStreams ();
						}
					}
				} break;
			default:
				break;
			}

			// We want to keep receiving messages
			args.RetVal = true;
		}

		// Extract some metadata from the streams and print it on the screen
		static void AnalyzeStreams () {
			// Read some properties
			NVideo = (int)Playbin ["n-video"];
			NAudio = (int)Playbin ["n-audio"];
			NText = (int)Playbin ["n-text"];

			Console.WriteLine ("{0} video stream(s), {1} audio stream(s), {2} text stream(s)", NVideo, NAudio, NText);

			Console.WriteLine ();
			for (int i = 0; i < NVideo; i++) {
				// Retrieve the stream's video tags
				var tags = (TagList)Playbin.Emit ("get-video-tags", new object [] { i });
				if (tags != null) {
					Console.WriteLine ("video stream {0}", i);
					string str;
					tags.GetString (Constants.TAG_VIDEO_CODEC, out str);
					Console.WriteLine ("  codec: {0}", str != null ? str : "unknown");
				}
			}

			Console.WriteLine ();
			for (int i = 0; i < NAudio; i++) {
				// Retrieve the stream's audio tags
				var tags = (TagList)Playbin.Emit ("get-audio-tags", new object [] { i });
				if (tags != null) {
					Console.WriteLine ("audio stream {0}", i);
					string str;
					if (tags.GetString (Constants.TAG_AUDIO_CODEC, out str)) {
						Console.WriteLine ("  codec: {0}", str);
					}
					if (tags.GetString (Constants.TAG_LANGUAGE_CODE, out str)) {
						Console.WriteLine ("  language: {0}", str);
					}
					uint rate;
					if (tags.GetUint (Constants.TAG_BITRATE, out rate)) {
						Console.WriteLine ("  bitrate: {0}", rate);
					}
				}
			}

			Console.WriteLine ();
			for (int i = 0; i < NText; i++) {
				// Retrieve the stream's subtitle tags
				var tags = (TagList)Playbin.Emit ("get-text-tags", new object [] { i });
				if (tags != null) {
					Console.WriteLine ("subtitle stream {0}", i);
					string str;
					if (tags.GetString (Constants.TAG_LANGUAGE_CODE, out str)) {
						Console.WriteLine ("  language: {0}", str);
					}
				}
			}

			CurrentAudio = (int)Playbin ["current-audio"];
			CurrentVideo = (int)Playbin ["current-video"];
			CurrentText = (int)Playbin ["current-text"];

			Console.WriteLine ();
			Console.WriteLine ("Currently playing video stream {0}, audio stream {1} and text stream {2}", CurrentVideo, CurrentAudio, CurrentText);
			Console.WriteLine ("Type any number to select a different audio stream");
		}

		// Process keyboard input
		static bool HandleKeyboard () {
			if (Console.KeyAvailable) {
				var key = Console.ReadKey (false);

				if (char.IsDigit (key.KeyChar)) {
					var digit = int.Parse (key.KeyChar.ToString ());

					if (digit < 0 || digit > NAudio) {
						Console.WriteLine ("Index out of bounds");
					} else {
						// If the input was a valid audio stream index, set the current audio stream
						Console.WriteLine ("Setting current audio stream to {0}", digit);
						Playbin ["current-audio"] = digit;

					}
				}
			}
			return true;
		}
	}
}