1 /*
2     Copyright (C) 2012 Openismus GmbH
3       @author Mathias Hasselmann <mathias@openismus.com>
4 
5     This library is free software; you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as published
7     by the Free Software Foundation; either version 2.1 of the License, or
8     (at your option) any later version.
9 
10     This program 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
13     GNU Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "discoverer.h"
19 
20 #include <QGlib/Error>
21 #include <QGst/Caps>
22 
23 #include <gst/pbutils/gstdiscoverer.h>
24 
25 namespace QGst {
26 
wrapStreamInfoList(GList * input,bool increaseRef)27 static QList<DiscovererStreamInfoPtr> wrapStreamInfoList(GList *input, bool increaseRef)
28 {
29     QList<DiscovererStreamInfoPtr> output;
30 
31     while(input) {
32         output += DiscovererStreamInfoPtr::wrap(GST_DISCOVERER_STREAM_INFO(input->data), increaseRef);
33         input = g_list_delete_link(input, input);
34     }
35 
36     return output;
37 }
38 
previous() const39 DiscovererStreamInfoPtr DiscovererStreamInfo::previous() const
40 {
41     return DiscovererStreamInfoPtr::wrap(gst_discoverer_stream_info_get_previous(object<GstDiscovererStreamInfo>()), false);
42 }
43 
next() const44 DiscovererStreamInfoPtr DiscovererStreamInfo::next() const
45 {
46     return DiscovererStreamInfoPtr::wrap(gst_discoverer_stream_info_get_next(object<GstDiscovererStreamInfo>()), false);
47 }
48 
streamTypeNick() const49 QString DiscovererStreamInfo::streamTypeNick() const
50 {
51     return QString::fromUtf8(gst_discoverer_stream_info_get_stream_type_nick(object<GstDiscovererStreamInfo>()));
52 }
53 
caps() const54 CapsPtr DiscovererStreamInfo::caps() const
55 {
56     return CapsPtr::wrap(gst_discoverer_stream_info_get_caps(object<GstDiscovererStreamInfo>()), false);
57 }
58 
tags() const59 TagList DiscovererStreamInfo::tags() const
60 {
61     return gst_discoverer_stream_info_get_tags(object<GstDiscovererStreamInfo>());
62 }
63 
misc() const64 Structure DiscovererStreamInfo::misc() const
65 {
66     const GstStructure *const misc = gst_discoverer_stream_info_get_misc(object<GstDiscovererStreamInfo>());
67     return misc ? Structure(misc) : Structure();
68 }
69 
streams() const70 QList<DiscovererStreamInfoPtr> DiscovererContainerInfo::streams() const
71 {
72     return wrapStreamInfoList(gst_discoverer_container_info_get_streams(object<GstDiscovererContainerInfo>()), false);
73 }
74 
channels() const75 uint DiscovererAudioInfo::channels() const
76 {
77     return gst_discoverer_audio_info_get_channels(object<GstDiscovererAudioInfo>());
78 }
79 
sampleRate() const80 uint DiscovererAudioInfo::sampleRate() const
81 {
82     return gst_discoverer_audio_info_get_sample_rate(object<GstDiscovererAudioInfo>());
83 }
84 
depth() const85 uint DiscovererAudioInfo::depth() const
86 {
87     return gst_discoverer_audio_info_get_depth(object<GstDiscovererAudioInfo>());
88 }
89 
bitrate() const90 uint DiscovererAudioInfo::bitrate() const
91 {
92     return gst_discoverer_audio_info_get_bitrate(object<GstDiscovererAudioInfo>());
93 }
94 
maxBitrate() const95 uint DiscovererAudioInfo::maxBitrate() const
96 {
97     return gst_discoverer_audio_info_get_max_bitrate(object<GstDiscovererAudioInfo>());
98 }
99 
language() const100 QString DiscovererAudioInfo::language() const
101 {
102     return QString::fromUtf8(gst_discoverer_audio_info_get_language(object<GstDiscovererAudioInfo>()));
103 }
104 
width() const105 uint DiscovererVideoInfo::width() const
106 {
107     return gst_discoverer_video_info_get_width(object<GstDiscovererVideoInfo>());
108 }
109 
height() const110 uint DiscovererVideoInfo::height() const
111 {
112     return gst_discoverer_video_info_get_height(object<GstDiscovererVideoInfo>());
113 }
114 
depth() const115 uint DiscovererVideoInfo::depth() const
116 {
117     return gst_discoverer_video_info_get_depth(object<GstDiscovererVideoInfo>());
118 }
119 
framerate() const120 Fraction DiscovererVideoInfo::framerate() const
121 {
122     return Fraction(gst_discoverer_video_info_get_framerate_num(object<GstDiscovererVideoInfo>()),
123                     gst_discoverer_video_info_get_framerate_denom(object<GstDiscovererVideoInfo>()));
124 }
125 
pixelAspectRatio() const126 Fraction DiscovererVideoInfo::pixelAspectRatio() const
127 {
128     return Fraction(gst_discoverer_video_info_get_par_num(object<GstDiscovererVideoInfo>()),
129                     gst_discoverer_video_info_get_par_denom(object<GstDiscovererVideoInfo>()));
130 }
131 
bitrate() const132 uint DiscovererVideoInfo::bitrate() const
133 {
134     return gst_discoverer_video_info_get_bitrate(object<GstDiscovererVideoInfo>());
135 }
136 
maxBitrate() const137 uint DiscovererVideoInfo::maxBitrate() const
138 {
139     return gst_discoverer_video_info_get_max_bitrate(object<GstDiscovererVideoInfo>());
140 }
141 
isInterlaced() const142 bool DiscovererVideoInfo::isInterlaced() const
143 {
144     return gst_discoverer_video_info_is_interlaced(object<GstDiscovererVideoInfo>());
145 }
146 
isImage() const147 bool DiscovererVideoInfo::isImage() const
148 {
149     return gst_discoverer_video_info_is_image(object<GstDiscovererVideoInfo>());
150 }
151 
language() const152 QString DiscovererSubtitleInfo::language() const
153 {
154     return QString::fromUtf8(gst_discoverer_subtitle_info_get_language(object<GstDiscovererSubtitleInfo>()));
155 }
156 
uri() const157 QUrl DiscovererInfo::uri() const
158 {
159     return QUrl::fromEncoded(gst_discoverer_info_get_uri(object<GstDiscovererInfo>()));
160 }
161 
result() const162 DiscovererResult DiscovererInfo::result() const
163 {
164     return DiscovererResult(gst_discoverer_info_get_result(object<GstDiscovererInfo>()));
165 }
166 
duration() const167 ClockTime DiscovererInfo::duration() const
168 {
169     return gst_discoverer_info_get_duration(object<GstDiscovererInfo>());
170 }
171 
seekable() const172 bool DiscovererInfo::seekable() const
173 {
174     return gst_discoverer_info_get_seekable(object<GstDiscovererInfo>());
175 }
176 
misc() const177 Structure DiscovererInfo::misc() const
178 {
179     const GstStructure *const misc = gst_discoverer_info_get_misc(object<GstDiscovererInfo>());
180     return misc ? Structure(misc) : Structure();
181 }
182 
tags() const183 TagList DiscovererInfo::tags() const
184 {
185     return gst_discoverer_info_get_tags(object<GstDiscovererInfo>());
186 }
187 
streamInfo() const188 DiscovererStreamInfoPtr DiscovererInfo::streamInfo() const
189 {
190     return DiscovererStreamInfoPtr::wrap(gst_discoverer_info_get_stream_info(object<GstDiscovererInfo>()), false);
191 }
192 
streams() const193 QList<DiscovererStreamInfoPtr> DiscovererInfo::streams() const
194 {
195     return wrapStreamInfoList(gst_discoverer_info_get_stream_list(object<GstDiscovererInfo>()), false);
196 }
197 
streams(QGlib::Type streamType) const198 QList<DiscovererStreamInfoPtr> DiscovererInfo::streams(QGlib::Type streamType) const
199 {
200     return wrapStreamInfoList(gst_discoverer_info_get_streams(object<GstDiscovererInfo>(), streamType), false);
201 }
202 
audioStreams() const203 QList<DiscovererStreamInfoPtr> DiscovererInfo::audioStreams() const
204 {
205     return wrapStreamInfoList(gst_discoverer_info_get_audio_streams(object<GstDiscovererInfo>()), false);
206 }
207 
videoStreams() const208 QList<DiscovererStreamInfoPtr> DiscovererInfo::videoStreams() const
209 {
210     return wrapStreamInfoList(gst_discoverer_info_get_video_streams(object<GstDiscovererInfo>()), false);
211 }
212 
subtitleStreams() const213 QList<DiscovererStreamInfoPtr> DiscovererInfo::subtitleStreams() const
214 {
215     return wrapStreamInfoList(gst_discoverer_info_get_subtitle_streams(object<GstDiscovererInfo>()), false);
216 }
217 
containerStreams() const218 QList<DiscovererStreamInfoPtr> DiscovererInfo::containerStreams() const
219 {
220     return wrapStreamInfoList(gst_discoverer_info_get_container_streams(object<GstDiscovererInfo>()), false);
221 }
222 
create(ClockTime timeout)223 DiscovererPtr Discoverer::create(ClockTime timeout)
224 {
225     GError *error = NULL;
226     GstDiscoverer *discoverer = gst_discoverer_new(timeout, &error);
227     if (error) {
228         throw QGlib::Error(error);
229     }
230     if (discoverer) {
231         g_object_ref_sink(discoverer);
232     }
233     return DiscovererPtr::wrap(discoverer, false);
234 }
235 
start()236 void Discoverer::start()
237 {
238     gst_discoverer_start(object<GstDiscoverer>());
239 }
240 
stop()241 void Discoverer::stop()
242 {
243     gst_discoverer_stop(object<GstDiscoverer>());
244 }
245 
discoverUriAsync(const char * uri)246 bool Discoverer::discoverUriAsync(const char *uri)
247 {
248     return gst_discoverer_discover_uri_async(object<GstDiscoverer>(), uri);
249 }
250 
discoverUri(const char * uri)251 DiscovererInfoPtr Discoverer::discoverUri(const char *uri)
252 {
253     GError *error = NULL;
254     GstDiscovererInfo *info = gst_discoverer_discover_uri(object<GstDiscoverer>(), uri, &error);
255     if (error) {
256         throw QGlib::Error(error);
257     }
258     return DiscovererInfoPtr::wrap(info, false);
259 }
260 
operator <<(QDebug debug,DiscovererResult result)261 QDebug operator<<(QDebug debug, DiscovererResult result)
262 {
263     switch(result) {
264     case DiscovererOk:
265         return debug << "QGst::DiscovererOk";
266     case DiscovererUriInvalid:
267         return debug << "QGst::DiscovererUriInvalid";
268     case DiscovererError:
269         return debug << "QGst::DiscovererError";
270     case DiscovererTimeout:
271         return debug << "QGst::DiscovererTimeout";
272     case DiscovererBusy:
273         return debug << "QGst::DiscovererBusy";
274     case DiscovererMissingPlugins:
275         return debug << "QGst::DiscovererMissingPlugins";
276     }
277 
278     return (debug.nospace() << "QGst::DiscovererResult(" << uint(result) << ")").maybeSpace();
279 }
280 
281 template <typename T>
282 static const char *typeName();
283 
284 template <typename T>
285 static QDebug printStreamInfoDetails(QDebug debug, const T &);
286 
287 template <>
typeName()288 const char *typeName<DiscovererStreamInfoPtr>()
289 {
290     return "QGst::DiscovererStreamInfoPtr";
291 }
292 
293 template <>
typeName()294 const char *typeName<DiscovererContainerInfoPtr>()
295 {
296     return "QGst::DiscovererContainerInfoPtr";
297 }
298 
299 template <>
typeName()300 const char *typeName<DiscovererAudioInfoPtr>()
301 {
302     return "QGst::DiscovererAudioInfoPtr";
303 }
304 
305 template <>
typeName()306 const char *typeName<DiscovererVideoInfoPtr>()
307 {
308     return "QGst::DiscovererVideoInfoPtr";
309 }
310 
311 template <>
typeName()312 const char *typeName<DiscovererSubtitleInfoPtr>()
313 {
314     return "QGst::DiscovererSubtitleInfoPtr";
315 }
316 
317 template <>
printStreamInfoDetails(QDebug debug,const DiscovererStreamInfoPtr &)318 QDebug printStreamInfoDetails(QDebug debug, const DiscovererStreamInfoPtr &)
319 {
320     return debug;
321 }
322 
323 template <>
printStreamInfoDetails(QDebug debug,const DiscovererContainerInfoPtr & info)324 QDebug printStreamInfoDetails(QDebug debug, const DiscovererContainerInfoPtr &info)
325 {
326     return debug.nospace()
327             << ", streams=" << info->streams();
328 }
329 
330 template <>
printStreamInfoDetails(QDebug debug,const DiscovererAudioInfoPtr & info)331 QDebug printStreamInfoDetails(QDebug debug, const DiscovererAudioInfoPtr &info)
332 {
333     return debug.nospace()
334             << ", channels=" << info->channels()
335             << ", sampleRate=" << info->sampleRate()
336             << ", depth=" << info->depth()
337             << ", bitrate=" << info->bitrate()
338             << ", maxBitrate=" << info->maxBitrate()
339             << ", language=" << info->language();
340 }
341 
342 template <>
printStreamInfoDetails(QDebug debug,const DiscovererVideoInfoPtr & info)343 QDebug printStreamInfoDetails(QDebug debug, const DiscovererVideoInfoPtr &info)
344 {
345     return debug.nospace()
346             << ", width=" << info->width()
347             << ", height=" << info->height()
348             << ", depth=" << info->depth()
349             << ", framerate=" << info->framerate()
350             << ", pixelAspectRatio=" << info->pixelAspectRatio()
351             << ", bitrate=" << info->bitrate()
352             << ", maxBitrate=" << info->maxBitrate()
353             << ", isInterlaced=" << info->isInterlaced()
354             << ", isImage=" << info->isImage();
355 }
356 
357 template <>
printStreamInfoDetails(QDebug debug,const DiscovererSubtitleInfoPtr & info)358 QDebug printStreamInfoDetails(QDebug debug, const DiscovererSubtitleInfoPtr &info)
359 {
360     return debug.nospace()
361             << ", language=" << info->language();
362 }
363 
364 template <typename T>
printStreamInfo(QDebug debug,const T & info)365 static QDebug printStreamInfo(QDebug debug, const T &info)
366 {
367     debug.nospace() << typeName<T>() << "(";
368 
369     if (info) {
370         debug.nospace() << info->streamTypeNick()
371                         << ", caps=" << info->caps();
372         debug.nospace() << ", tags=" << info->tags();
373         debug.nospace() << ", misc=" << info->misc();
374         debug.nospace() << ", hasPrevious=" << !info->previous().isNull();
375         debug.nospace() << ", hasNext=" << !info->next().isNull();
376         debug = printStreamInfoDetails(debug, info);
377     } else {
378         debug << "<null>";
379     }
380 
381     return (debug << ")").maybeSpace();
382 }
383 
operator <<(QDebug debug,const DiscovererStreamInfoPtr & info)384 QDebug operator<<(QDebug debug, const DiscovererStreamInfoPtr &info)
385 {
386     if (const DiscovererContainerInfoPtr containerInfo = info.dynamicCast<DiscovererContainerInfo>()) {
387         return printStreamInfo(debug, containerInfo);
388     }
389     if (const DiscovererAudioInfoPtr audioInfo = info.dynamicCast<DiscovererAudioInfo>()) {
390         return printStreamInfo(debug, audioInfo);
391     }
392     if (const DiscovererVideoInfoPtr videoInfo = info.dynamicCast<DiscovererVideoInfo>()) {
393         return printStreamInfo(debug, videoInfo);
394     }
395     if (const DiscovererSubtitleInfoPtr subtitleInfo = info.dynamicCast<DiscovererSubtitleInfo>()) {
396         return printStreamInfo(debug, subtitleInfo);
397     }
398 
399     return printStreamInfo(debug, info);
400 }
401 
operator <<(QDebug debug,const DiscovererInfoPtr & info)402 QDebug operator<<(QDebug debug, const DiscovererInfoPtr &info)
403 {
404     debug.nospace() << "QGst::DiscovererInfoPtr(";
405 
406     if (info) {
407         debug.nospace() << "result=" << info->result()
408                         << ", uri=" << info->uri()
409                         << ", duration=" << info->duration()
410                         << ", seekable=" << info->seekable()
411                         << ", misc=" << info->misc();
412         debug.nospace() << ", tags=" << info->tags();
413         debug.nospace() << ", streamInfo=" << info->streamInfo();
414         debug.nospace() << ", streams=" << info->streams();
415         debug.nospace() << ", audioStreams=" << info->audioStreams();
416         debug.nospace() << ", videoStreams=" << info->videoStreams();
417         debug.nospace() << ", subtitleStreams=" << info->subtitleStreams();
418         debug.nospace() << ", containerStreams=" << info->containerStreams();
419     } else {
420         debug << "<null>";
421     }
422 
423     return (debug << ")").maybeSpace();
424 }
425 
426 } // namespace QGst
427