1 /* GStreamer
2  *
3  * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <gst/gst.h>
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 
31 typedef struct _App App;
32 
33 struct _App
34 {
35   GstElement *playbin;
36   GstElement *textsink;
37 
38   GMainLoop *loop;
39 };
40 
41 static App s_app;
42 
43 static gboolean
bus_message(GstBus * bus,GstMessage * message,App * app)44 bus_message (GstBus * bus, GstMessage * message, App * app)
45 {
46   GST_DEBUG ("got message %s",
47       gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
48 
49   switch (GST_MESSAGE_TYPE (message)) {
50     case GST_MESSAGE_ERROR:
51     {
52       GError *gerror;
53       gchar *debug;
54 
55       gst_message_parse_error (message, &gerror, &debug);
56       gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
57       g_error_free (gerror);
58       g_free (debug);
59 
60       g_main_loop_quit (app->loop);
61       break;
62     }
63     case GST_MESSAGE_WARNING:
64     {
65       GError *gerror;
66       gchar *debug;
67 
68       gst_message_parse_warning (message, &gerror, &debug);
69       gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
70       g_error_free (gerror);
71       g_free (debug);
72       break;
73     }
74     case GST_MESSAGE_EOS:
75       g_message ("received EOS");
76       g_main_loop_quit (app->loop);
77       break;
78     default:
79       break;
80   }
81   return TRUE;
82 }
83 
84 static GstFlowReturn
have_subtitle(GstElement * appsink,App * app)85 have_subtitle (GstElement * appsink, App * app)
86 {
87   GstBuffer *buffer;
88   GstSample *sample;
89 
90   /* get the buffer, we can also wakeup the mainloop to get the subtitle from
91    * appsink in the mainloop */
92   g_signal_emit_by_name (appsink, "pull-sample", &sample);
93   if (sample) {
94     GstMapInfo map;
95     gint64 position;
96     GstClock *clock;
97     GstClockTime base_time, running_time;
98 
99     buffer = gst_sample_get_buffer (sample);
100     gst_element_query_position (appsink, GST_FORMAT_TIME, &position);
101 
102     clock = gst_element_get_clock (appsink);
103     base_time = gst_element_get_base_time (appsink);
104 
105     running_time = gst_clock_get_time (clock) - base_time;
106 
107     gst_object_unref (clock);
108 
109     g_message ("received a subtitle at position %" GST_TIME_FORMAT
110         ", running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (position),
111         GST_TIME_ARGS (running_time));
112 
113     gst_buffer_map (buffer, &map, GST_MAP_READ);
114     gst_util_dump_mem (map.data, map.size);
115     gst_buffer_unmap (buffer, &map);
116     gst_sample_unref (sample);
117   }
118   return GST_FLOW_OK;
119 }
120 
121 int
main(int argc,char * argv[])122 main (int argc, char *argv[])
123 {
124   App *app = &s_app;
125   GstBus *bus;
126   GstCaps *subcaps;
127 
128   gst_init (&argc, &argv);
129 
130   if (argc < 2) {
131     g_print ("usage: %s <uri> [<suburi>]\n", argv[0]);
132     return -1;
133   }
134 
135   /* create a mainloop to get messages */
136   app->loop = g_main_loop_new (NULL, TRUE);
137 
138   app->playbin = gst_element_factory_make ("playbin", NULL);
139   g_assert (app->playbin);
140 
141   /* set appsink to get the subtitles */
142   app->textsink = gst_element_factory_make ("appsink", "subtitle_sink");
143   g_object_set (G_OBJECT (app->textsink), "emit-signals", TRUE, NULL);
144   g_object_set (G_OBJECT (app->textsink), "ts-offset", 0 * GST_SECOND, NULL);
145   g_signal_connect (app->textsink, "new-sample", G_CALLBACK (have_subtitle),
146       app);
147   subcaps = gst_caps_from_string ("text/x-raw, format={ utf8, pango-markup }");
148   g_object_set (G_OBJECT (app->textsink), "caps", subcaps, NULL);
149   gst_caps_unref (subcaps);
150 
151   g_object_set (G_OBJECT (app->playbin), "text-sink", app->textsink, NULL);
152 
153   bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin));
154 
155   /* add watch for messages */
156   gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
157 
158   /* set to read from appsrc */
159   g_object_set (app->playbin, "uri", argv[1], NULL);
160 
161   if (argc > 2)
162     g_object_set (app->playbin, "suburi", argv[2], NULL);
163 
164   /* go to playing and wait in a mainloop. */
165   gst_element_set_state (app->playbin, GST_STATE_PLAYING);
166 
167   /* this mainloop is stopped when we receive an error or EOS */
168   g_main_loop_run (app->loop);
169 
170   g_message ("stopping");
171 
172   gst_element_set_state (app->playbin, GST_STATE_NULL);
173 
174   gst_object_unref (bus);
175   g_main_loop_unref (app->loop);
176 
177   return 0;
178 }
179