1 /* GStreamer
2 * Copyright (C) 2010 Collabora Multimedia
3 * 2010 Nokia Corporation
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 "pbutils.h"
26 #include "pbutils-private.h"
27
28 static GstDiscovererStreamInfo
29 * gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
30 GHashTable * stream_map);
31
32 static GstDiscovererContainerInfo
33 * gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr,
34 GHashTable * stream_map);
35
36 static GstDiscovererAudioInfo
37 * gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr);
38
39 static GstDiscovererVideoInfo
40 * gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr);
41
42 static GstDiscovererSubtitleInfo
43 * gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr);
44
45 /* Per-stream information */
46
47 G_DEFINE_TYPE (GstDiscovererStreamInfo, gst_discoverer_stream_info,
48 G_TYPE_OBJECT);
49
50 static void
gst_discoverer_stream_info_init(GstDiscovererStreamInfo * info)51 gst_discoverer_stream_info_init (GstDiscovererStreamInfo * info)
52 {
53 info->stream_number = -1;
54 }
55
56 static void
gst_discoverer_stream_info_finalize(GObject * object)57 gst_discoverer_stream_info_finalize (GObject * object)
58 {
59 GstDiscovererStreamInfo *info = (GstDiscovererStreamInfo *) object;
60
61 if (info->next)
62 g_object_unref ((GObject *) info->next);
63
64 if (info->caps)
65 gst_caps_unref (info->caps);
66
67 if (info->tags)
68 gst_tag_list_unref (info->tags);
69
70 if (info->toc)
71 gst_toc_unref (info->toc);
72
73 g_free (info->stream_id);
74
75 if (info->misc)
76 gst_structure_free (info->misc);
77
78 G_OBJECT_CLASS (gst_discoverer_stream_info_parent_class)->finalize (object);
79 }
80
81 static void
gst_discoverer_stream_info_class_init(GObjectClass * klass)82 gst_discoverer_stream_info_class_init (GObjectClass * klass)
83 {
84 klass->finalize = gst_discoverer_stream_info_finalize;
85 }
86
87 static GstDiscovererStreamInfo *
gst_discoverer_stream_info_new(void)88 gst_discoverer_stream_info_new (void)
89 {
90 return (GstDiscovererStreamInfo *)
91 g_object_new (GST_TYPE_DISCOVERER_STREAM_INFO, NULL);
92 }
93
94 static GstDiscovererStreamInfo *
gst_discoverer_info_copy_int(GstDiscovererStreamInfo * info,GHashTable * stream_map)95 gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
96 GHashTable * stream_map)
97 {
98 GstDiscovererStreamInfo *ret;
99 GType ltyp;
100
101 g_return_val_if_fail (info != NULL, NULL);
102
103 ltyp = G_TYPE_FROM_INSTANCE (info);
104
105 if (ltyp == GST_TYPE_DISCOVERER_CONTAINER_INFO) {
106 ret = (GstDiscovererStreamInfo *)
107 gst_stream_container_info_copy_int (
108 (GstDiscovererContainerInfo *) info, stream_map);
109 } else if (ltyp == GST_TYPE_DISCOVERER_AUDIO_INFO) {
110 ret = (GstDiscovererStreamInfo *)
111 gst_discoverer_audio_info_copy_int ((GstDiscovererAudioInfo *) info);
112
113 } else if (ltyp == GST_TYPE_DISCOVERER_VIDEO_INFO) {
114 ret = (GstDiscovererStreamInfo *)
115 gst_discoverer_video_info_copy_int ((GstDiscovererVideoInfo *) info);
116
117 } else if (ltyp == GST_TYPE_DISCOVERER_SUBTITLE_INFO) {
118 ret = (GstDiscovererStreamInfo *)
119 gst_discoverer_subtitle_info_copy_int ((GstDiscovererSubtitleInfo *)
120 info);
121
122 } else
123 ret = gst_discoverer_stream_info_new ();
124
125 if (info->next) {
126 ret->next = gst_discoverer_info_copy_int (info->next, stream_map);
127 ret->next->previous = ret;
128 }
129
130 if (info->caps)
131 ret->caps = gst_caps_copy (info->caps);
132
133 if (info->tags)
134 ret->tags = gst_tag_list_copy (info->tags);
135
136 if (info->toc)
137 ret->toc = gst_toc_ref (info->toc);
138
139 if (info->stream_id)
140 ret->stream_id = g_strdup (info->stream_id);
141
142 if (info->misc)
143 ret->misc = gst_structure_copy (info->misc);
144
145 if (stream_map)
146 g_hash_table_insert (stream_map, info, ret);
147
148 ret->stream_number = info->stream_number;
149
150 return ret;
151 }
152
153 /* Container information */
154 G_DEFINE_TYPE (GstDiscovererContainerInfo, gst_discoverer_container_info,
155 GST_TYPE_DISCOVERER_STREAM_INFO);
156
157 static void
gst_discoverer_container_info_init(GstDiscovererContainerInfo * info)158 gst_discoverer_container_info_init (GstDiscovererContainerInfo * info)
159 {
160 /* Nothing to initialize */
161 }
162
163 static GstDiscovererContainerInfo *
gst_discoverer_container_info_new(void)164 gst_discoverer_container_info_new (void)
165 {
166 return (GstDiscovererContainerInfo *)
167 g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
168 }
169
170 static void
gst_discoverer_container_info_finalize(GObject * object)171 gst_discoverer_container_info_finalize (GObject * object)
172 {
173 GstDiscovererContainerInfo *info = (GstDiscovererContainerInfo *) object;
174 GList *tmp;
175
176 for (tmp = ((GstDiscovererContainerInfo *) info)->streams; tmp;
177 tmp = tmp->next)
178 g_object_unref ((GObject *) tmp->data);
179
180 gst_discoverer_stream_info_list_free (info->streams);
181
182 if (info->tags)
183 gst_tag_list_unref (info->tags);
184
185 G_OBJECT_CLASS (gst_discoverer_container_info_parent_class)->finalize
186 (object);
187 }
188
189 static void
gst_discoverer_container_info_class_init(GObjectClass * klass)190 gst_discoverer_container_info_class_init (GObjectClass * klass)
191 {
192 klass->finalize = gst_discoverer_container_info_finalize;
193 }
194
195 static GstDiscovererContainerInfo *
gst_stream_container_info_copy_int(GstDiscovererContainerInfo * ptr,GHashTable * stream_map)196 gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr,
197 GHashTable * stream_map)
198 {
199 GstDiscovererContainerInfo *ret;
200 GList *tmp;
201
202 g_return_val_if_fail (ptr != NULL, NULL);
203
204 ret = gst_discoverer_container_info_new ();
205
206 for (tmp = ((GstDiscovererContainerInfo *) ptr)->streams; tmp;
207 tmp = tmp->next) {
208 GstDiscovererStreamInfo *subtop = gst_discoverer_info_copy_int (tmp->data,
209 stream_map);
210 ret->streams = g_list_append (ret->streams, subtop);
211 if (stream_map)
212 g_hash_table_insert (stream_map, tmp->data, subtop);
213 }
214
215 if (ptr->tags)
216 ret->tags = gst_tag_list_copy (ptr->tags);
217
218 return ret;
219 }
220
221 /* Audio information */
222 G_DEFINE_TYPE (GstDiscovererAudioInfo, gst_discoverer_audio_info,
223 GST_TYPE_DISCOVERER_STREAM_INFO);
224
225 static void
gst_discoverer_audio_info_finalize(GObject * object)226 gst_discoverer_audio_info_finalize (GObject * object)
227 {
228 GstDiscovererAudioInfo *info = (GstDiscovererAudioInfo *) object;
229
230 g_free (info->language);
231
232 G_OBJECT_CLASS (gst_discoverer_audio_info_parent_class)->finalize (object);
233 }
234
235 static void
gst_discoverer_audio_info_class_init(GObjectClass * klass)236 gst_discoverer_audio_info_class_init (GObjectClass * klass)
237 {
238 klass->finalize = gst_discoverer_audio_info_finalize;
239 }
240
241 static void
gst_discoverer_audio_info_init(GstDiscovererAudioInfo * info)242 gst_discoverer_audio_info_init (GstDiscovererAudioInfo * info)
243 {
244 info->language = NULL;
245 }
246
247 static GstDiscovererAudioInfo *
gst_discoverer_audio_info_new(void)248 gst_discoverer_audio_info_new (void)
249 {
250 return (GstDiscovererAudioInfo *)
251 g_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO, NULL);
252 }
253
254 static GstDiscovererAudioInfo *
gst_discoverer_audio_info_copy_int(GstDiscovererAudioInfo * ptr)255 gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr)
256 {
257 GstDiscovererAudioInfo *ret;
258
259 ret = gst_discoverer_audio_info_new ();
260
261 ret->channels = ptr->channels;
262 ret->channel_mask = ptr->channel_mask;
263 ret->sample_rate = ptr->sample_rate;
264 ret->depth = ptr->depth;
265 ret->bitrate = ptr->bitrate;
266 ret->max_bitrate = ptr->max_bitrate;
267 ret->language = g_strdup (ptr->language);
268
269 return ret;
270 }
271
272 /* Subtitle information */
273 G_DEFINE_TYPE (GstDiscovererSubtitleInfo, gst_discoverer_subtitle_info,
274 GST_TYPE_DISCOVERER_STREAM_INFO);
275
276 static void
gst_discoverer_subtitle_info_init(GstDiscovererSubtitleInfo * info)277 gst_discoverer_subtitle_info_init (GstDiscovererSubtitleInfo * info)
278 {
279 info->language = NULL;
280 }
281
282 static void
gst_discoverer_subtitle_info_finalize(GObject * object)283 gst_discoverer_subtitle_info_finalize (GObject * object)
284 {
285 GstDiscovererSubtitleInfo *info = (GstDiscovererSubtitleInfo *) object;
286
287 g_free (info->language);
288
289 G_OBJECT_CLASS (gst_discoverer_subtitle_info_parent_class)->finalize (object);
290 }
291
292 static void
gst_discoverer_subtitle_info_class_init(GObjectClass * klass)293 gst_discoverer_subtitle_info_class_init (GObjectClass * klass)
294 {
295 klass->finalize = gst_discoverer_subtitle_info_finalize;
296 }
297
298 static GstDiscovererSubtitleInfo *
gst_discoverer_subtitle_info_new(void)299 gst_discoverer_subtitle_info_new (void)
300 {
301 return (GstDiscovererSubtitleInfo *)
302 g_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO, NULL);
303 }
304
305 static GstDiscovererSubtitleInfo *
gst_discoverer_subtitle_info_copy_int(GstDiscovererSubtitleInfo * ptr)306 gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr)
307 {
308 GstDiscovererSubtitleInfo *ret;
309
310 ret = gst_discoverer_subtitle_info_new ();
311
312 ret->language = g_strdup (ptr->language);
313
314 return ret;
315 }
316
317 /* Video information */
318 G_DEFINE_TYPE (GstDiscovererVideoInfo, gst_discoverer_video_info,
319 GST_TYPE_DISCOVERER_STREAM_INFO);
320
321 static void
gst_discoverer_video_info_class_init(GObjectClass * klass)322 gst_discoverer_video_info_class_init (GObjectClass * klass)
323 {
324 /* Nothing to initialize */
325 }
326
327 static void
gst_discoverer_video_info_init(GstDiscovererVideoInfo * info)328 gst_discoverer_video_info_init (GstDiscovererVideoInfo * info)
329 {
330 /* Nothing to initialize */
331 }
332
333 static GstDiscovererVideoInfo *
gst_discoverer_video_info_new(void)334 gst_discoverer_video_info_new (void)
335 {
336 return (GstDiscovererVideoInfo *)
337 g_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO, NULL);
338 }
339
340 static GstDiscovererVideoInfo *
gst_discoverer_video_info_copy_int(GstDiscovererVideoInfo * ptr)341 gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr)
342 {
343 GstDiscovererVideoInfo *ret;
344
345 ret = gst_discoverer_video_info_new ();
346
347 ret->width = ptr->width;
348 ret->height = ptr->height;
349 ret->depth = ptr->depth;
350 ret->framerate_num = ptr->framerate_num;
351 ret->framerate_denom = ptr->framerate_denom;
352 ret->par_num = ptr->par_num;
353 ret->par_denom = ptr->par_denom;
354 ret->interlaced = ptr->interlaced;
355 ret->bitrate = ptr->bitrate;
356 ret->max_bitrate = ptr->max_bitrate;
357 ret->is_image = ptr->is_image;
358
359 return ret;
360 }
361
362 /* Global stream information */
363 G_DEFINE_TYPE (GstDiscovererInfo, gst_discoverer_info, G_TYPE_OBJECT);
364
365 static void
gst_discoverer_info_init(GstDiscovererInfo * info)366 gst_discoverer_info_init (GstDiscovererInfo * info)
367 {
368 info->missing_elements_details = g_ptr_array_new_with_free_func (g_free);
369 }
370
371 static void
gst_discoverer_info_finalize(GObject * object)372 gst_discoverer_info_finalize (GObject * object)
373 {
374 GstDiscovererInfo *info = (GstDiscovererInfo *) object;
375 g_free (info->uri);
376
377 if (info->stream_info)
378 g_object_unref ((GObject *) info->stream_info);
379
380 if (info->misc)
381 gst_structure_free (info->misc);
382
383 g_list_free (info->stream_list);
384
385 if (info->tags)
386 gst_tag_list_unref (info->tags);
387
388 if (info->toc)
389 gst_toc_unref (info->toc);
390
391 g_free (info->cachefile);
392
393 g_ptr_array_unref (info->missing_elements_details);
394
395 G_OBJECT_CLASS (gst_discoverer_info_parent_class)->finalize (object);
396 }
397
398 static GstDiscovererInfo *
gst_discoverer_info_new(void)399 gst_discoverer_info_new (void)
400 {
401 return (GstDiscovererInfo *) g_object_new (GST_TYPE_DISCOVERER_INFO, NULL);
402 }
403
404 /**
405 * gst_discoverer_info_copy:
406 * @ptr: (transfer none): a #GstDiscovererInfo
407 *
408 * Returns: (transfer full): A copy of the #GstDiscovererInfo
409 */
410 GstDiscovererInfo *
gst_discoverer_info_copy(GstDiscovererInfo * ptr)411 gst_discoverer_info_copy (GstDiscovererInfo * ptr)
412 {
413 GstDiscovererInfo *ret;
414 GHashTable *stream_map;
415 GList *tmp;
416
417 g_return_val_if_fail (ptr != NULL, NULL);
418
419 stream_map = g_hash_table_new (g_direct_hash, NULL);
420
421 ret = gst_discoverer_info_new ();
422
423 ret->uri = g_strdup (ptr->uri);
424 if (ptr->stream_info) {
425 ret->stream_info = gst_discoverer_info_copy_int (ptr->stream_info,
426 stream_map);
427 }
428 ret->duration = ptr->duration;
429 ret->result = ptr->result;
430 ret->seekable = ptr->seekable;
431 ret->live = ptr->live;
432 if (ptr->misc)
433 ret->misc = gst_structure_copy (ptr->misc);
434
435 /* We need to set up the new list of streams to correspond to old one. The
436 * list just contains a set of pointers to streams in the stream_info tree,
437 * so we keep a map of old stream info objects to the corresponding new
438 * ones and use that to figure out correspondence in stream_list. */
439 for (tmp = ptr->stream_list; tmp; tmp = tmp->next) {
440 GstDiscovererStreamInfo *old_stream = (GstDiscovererStreamInfo *) tmp->data;
441 GstDiscovererStreamInfo *new_stream = g_hash_table_lookup (stream_map,
442 old_stream);
443 g_assert (new_stream != NULL);
444 ret->stream_list = g_list_append (ret->stream_list, new_stream);
445 }
446
447 if (ptr->tags)
448 ret->tags = gst_tag_list_copy (ptr->tags);
449
450 if (ptr->toc)
451 ret->toc = gst_toc_ref (ptr->toc);
452
453 g_hash_table_destroy (stream_map);
454 return ret;
455 }
456
457 static void
gst_discoverer_info_class_init(GObjectClass * klass)458 gst_discoverer_info_class_init (GObjectClass * klass)
459 {
460 klass->finalize = gst_discoverer_info_finalize;
461 }
462
463 /**
464 * gst_discoverer_stream_info_list_free:
465 * @infos: (element-type GstPbutils.DiscovererStreamInfo): a #GList of #GstDiscovererStreamInfo
466 *
467 * Decrements the reference count of all contained #GstDiscovererStreamInfo
468 * and fress the #GList.
469 */
470 void
gst_discoverer_stream_info_list_free(GList * infos)471 gst_discoverer_stream_info_list_free (GList * infos)
472 {
473 GList *tmp;
474
475 for (tmp = infos; tmp; tmp = tmp->next)
476 gst_discoverer_stream_info_unref ((GstDiscovererStreamInfo *) tmp->data);
477 g_list_free (infos);
478 }
479
480 /**
481 * gst_discoverer_info_get_streams:
482 * @info: a #GstDiscovererInfo
483 * @streamtype: a #GType derived from #GstDiscovererStreamInfo
484 *
485 * Finds the #GstDiscovererStreamInfo contained in @info that match the
486 * given @streamtype.
487 *
488 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
489 * matching #GstDiscovererStreamInfo. The caller should free it with
490 * gst_discoverer_stream_info_list_free().
491 */
492 GList *
gst_discoverer_info_get_streams(GstDiscovererInfo * info,GType streamtype)493 gst_discoverer_info_get_streams (GstDiscovererInfo * info, GType streamtype)
494 {
495 GList *tmp, *res = NULL;
496
497 for (tmp = info->stream_list; tmp; tmp = tmp->next) {
498 GstDiscovererStreamInfo *stmp = (GstDiscovererStreamInfo *) tmp->data;
499
500 if (G_TYPE_CHECK_INSTANCE_TYPE (stmp, streamtype))
501 res = g_list_append (res, gst_discoverer_stream_info_ref (stmp));
502 }
503
504 return res;
505 }
506
507 /**
508 * gst_discoverer_info_get_audio_streams:
509 * @info: a #GstDiscovererInfo
510 *
511 * Finds all the #GstDiscovererAudioInfo contained in @info
512 *
513 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
514 * matching #GstDiscovererStreamInfo. The caller should free it with
515 * gst_discoverer_stream_info_list_free().
516 */
517 GList *
gst_discoverer_info_get_audio_streams(GstDiscovererInfo * info)518 gst_discoverer_info_get_audio_streams (GstDiscovererInfo * info)
519 {
520 return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_AUDIO_INFO);
521 }
522
523 /**
524 * gst_discoverer_info_get_video_streams:
525 * @info: a #GstDiscovererInfo
526 *
527 * Finds all the #GstDiscovererVideoInfo contained in @info
528 *
529 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
530 * matching #GstDiscovererStreamInfo. The caller should free it with
531 * gst_discoverer_stream_info_list_free().
532 */
533 GList *
gst_discoverer_info_get_video_streams(GstDiscovererInfo * info)534 gst_discoverer_info_get_video_streams (GstDiscovererInfo * info)
535 {
536 return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_VIDEO_INFO);
537 }
538
539 /**
540 * gst_discoverer_info_get_subtitle_streams:
541 * @info: a #GstDiscovererInfo
542 *
543 * Finds all the #GstDiscovererSubtitleInfo contained in @info
544 *
545 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
546 * matching #GstDiscovererStreamInfo. The caller should free it with
547 * gst_discoverer_stream_info_list_free().
548 */
549 GList *
gst_discoverer_info_get_subtitle_streams(GstDiscovererInfo * info)550 gst_discoverer_info_get_subtitle_streams (GstDiscovererInfo * info)
551 {
552 return gst_discoverer_info_get_streams (info,
553 GST_TYPE_DISCOVERER_SUBTITLE_INFO);
554 }
555
556 /**
557 * gst_discoverer_info_get_container_streams:
558 * @info: a #GstDiscovererInfo
559 *
560 * Finds all the #GstDiscovererContainerInfo contained in @info
561 *
562 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
563 * matching #GstDiscovererStreamInfo. The caller should free it with
564 * gst_discoverer_stream_info_list_free().
565 */
566 GList *
gst_discoverer_info_get_container_streams(GstDiscovererInfo * info)567 gst_discoverer_info_get_container_streams (GstDiscovererInfo * info)
568 {
569 return gst_discoverer_info_get_streams (info,
570 GST_TYPE_DISCOVERER_CONTAINER_INFO);
571 }
572
573 /**
574 * gst_discoverer_stream_info_get_stream_type_nick:
575 * @info: a #GstDiscovererStreamInfo
576 *
577 * Returns: a human readable name for the stream type of the given @info (ex : "audio",
578 * "container",...).
579 */
580 const gchar *
gst_discoverer_stream_info_get_stream_type_nick(GstDiscovererStreamInfo * info)581 gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info)
582 {
583 if (GST_IS_DISCOVERER_CONTAINER_INFO (info))
584 return "container";
585 if (GST_IS_DISCOVERER_AUDIO_INFO (info))
586 return "audio";
587 if (GST_IS_DISCOVERER_VIDEO_INFO (info)) {
588 if (gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *)
589 info))
590 return "video(image)";
591 else
592 return "video";
593 }
594 if (GST_IS_DISCOVERER_SUBTITLE_INFO (info))
595 return "subtitles";
596 return "unknown";
597 }
598
599 /* ACCESSORS */
600
601
602 #define GENERIC_ACCESSOR_CODE(parent, parenttype, parentgtype, fieldname, type, failval) \
603 type parent##_get_##fieldname(const parenttype info) { \
604 g_return_val_if_fail(G_TYPE_CHECK_INSTANCE_TYPE((info), parentgtype), failval); \
605 return (info)->fieldname; \
606 }
607
608 /**
609 * gst_discoverer_stream_info_get_previous:
610 * @info: a #GstDiscovererStreamInfo
611 *
612 * Returns: (transfer full): the previous #GstDiscovererStreamInfo in a chain.
613 * %NULL for starting points. Unref with #gst_discoverer_stream_info_unref
614 * after usage.
615 */
616 GstDiscovererStreamInfo *
gst_discoverer_stream_info_get_previous(GstDiscovererStreamInfo * info)617 gst_discoverer_stream_info_get_previous (GstDiscovererStreamInfo * info)
618 {
619 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
620
621 if (info->previous)
622 return gst_discoverer_stream_info_ref (info->previous);
623 return NULL;
624 }
625
626 /**
627 * gst_discoverer_stream_info_get_next:
628 * @info: a #GstDiscovererStreamInfo
629 *
630 * Returns: (transfer full): the next #GstDiscovererStreamInfo in a chain. %NULL
631 * for final streams.
632 * Unref with #gst_discoverer_stream_info_unref after usage.
633 */
634 GstDiscovererStreamInfo *
gst_discoverer_stream_info_get_next(GstDiscovererStreamInfo * info)635 gst_discoverer_stream_info_get_next (GstDiscovererStreamInfo * info)
636 {
637 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
638
639 if (info->next)
640 return gst_discoverer_stream_info_ref (info->next);
641 return NULL;
642 }
643
644
645 /**
646 * gst_discoverer_stream_info_get_caps:
647 * @info: a #GstDiscovererStreamInfo
648 *
649 * Returns: (transfer full): the #GstCaps of the stream. Unref with
650 * #gst_caps_unref after usage.
651 */
652 GstCaps *
gst_discoverer_stream_info_get_caps(GstDiscovererStreamInfo * info)653 gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info)
654 {
655 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
656
657 if (info->caps)
658 return gst_caps_ref (info->caps);
659 return NULL;
660 }
661
662 /**
663 * gst_discoverer_stream_info_get_tags:
664 * @info: a #GstDiscovererStreamInfo
665 *
666 * Returns: (transfer none): the tags contained in this stream. If you wish to
667 * use the tags after the life-time of @info you will need to copy them.
668 */
669 const GstTagList *
gst_discoverer_stream_info_get_tags(GstDiscovererStreamInfo * info)670 gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
671 {
672 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
673
674 return info->tags;
675 }
676
677 /**
678 * gst_discoverer_stream_info_get_toc:
679 * @info: a #GstDiscovererStreamInfo
680 *
681 * Returns: (transfer none): the TOC contained in this stream. If you wish to
682 * use the TOC after the life-time of @info you will need to copy it.
683 */
684 const GstToc *
gst_discoverer_stream_info_get_toc(GstDiscovererStreamInfo * info)685 gst_discoverer_stream_info_get_toc (GstDiscovererStreamInfo * info)
686 {
687 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
688
689 return info->toc;
690 }
691
692 /**
693 * gst_discoverer_stream_info_get_stream_id:
694 * @info: a #GstDiscovererStreamInfo
695 *
696 * Returns: (transfer none): the stream ID of this stream. If you wish to
697 * use the stream ID after the life-time of @info you will need to copy it.
698 */
699 const gchar *
gst_discoverer_stream_info_get_stream_id(GstDiscovererStreamInfo * info)700 gst_discoverer_stream_info_get_stream_id (GstDiscovererStreamInfo * info)
701 {
702 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
703
704 return info->stream_id;
705 }
706
707 #ifndef GST_REMOVE_DEPRECATED
708 /**
709 * gst_discoverer_stream_info_get_misc:
710 * @info: a #GstDiscovererStreamInfo
711 *
712 * Deprecated: This functions is deprecated since version 1.4, use
713 * #gst_discoverer_info_get_missing_elements_installer_details
714 *
715 * Returns: (transfer none): additional information regarding the stream (for
716 * example codec version, profile, etc..). If you wish to use the #GstStructure
717 * after the life-time of @info you will need to copy it.
718 */
719 const GstStructure *
gst_discoverer_stream_info_get_misc(GstDiscovererStreamInfo * info)720 gst_discoverer_stream_info_get_misc (GstDiscovererStreamInfo * info)
721 {
722 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
723
724 return info->misc;
725 }
726 #endif
727
728 /**
729 * gst_discoverer_stream_info_get_stream_number:
730 * @info: a #GstDiscovererStreamInfo
731 *
732 * Returns: the stream number, -1 if no index could be determined. This property
733 * acts as a unique identifier as a 'int' for the stream.
734 *
735 * Since: 1.20
736 */
737 gint
gst_discoverer_stream_info_get_stream_number(GstDiscovererStreamInfo * info)738 gst_discoverer_stream_info_get_stream_number (GstDiscovererStreamInfo * info)
739 {
740 g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), -1);
741
742 return info->stream_number;
743 }
744
745 /* GstDiscovererContainerInfo */
746
747 /**
748 * gst_discoverer_container_info_get_streams:
749 * @info: a #GstDiscovererStreamInfo
750 *
751 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): the list of
752 * #GstDiscovererStreamInfo this container stream offers.
753 * Free with gst_discoverer_stream_info_list_free() after usage.
754 */
755
756 GList *
gst_discoverer_container_info_get_streams(GstDiscovererContainerInfo * info)757 gst_discoverer_container_info_get_streams (GstDiscovererContainerInfo * info)
758 {
759 GList *res = NULL, *tmp;
760
761 g_return_val_if_fail (GST_IS_DISCOVERER_CONTAINER_INFO (info), NULL);
762
763 for (tmp = info->streams; tmp; tmp = tmp->next)
764 res =
765 g_list_append (res,
766 gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data));
767
768 return res;
769 }
770
771 /**
772 * gst_discoverer_container_info_get_tags:
773 * @info: a #GstDiscovererStreamInfo
774 *
775 * Returns: (transfer none): tags specific to the given container. If you wish to use
776 * the tags after the life-time of @info, you will need to copy them.
777 *
778 * Since: 1.20
779 */
780 const GstTagList *
gst_discoverer_container_info_get_tags(const GstDiscovererContainerInfo * info)781 gst_discoverer_container_info_get_tags (const GstDiscovererContainerInfo * info)
782 {
783 g_return_val_if_fail (GST_IS_DISCOVERER_CONTAINER_INFO (info), NULL);
784
785 return info->tags;
786 }
787
788 /* GstDiscovererAudioInfo */
789
790 #define AUDIO_INFO_ACCESSOR_CODE(fieldname, type, failval) \
791 GENERIC_ACCESSOR_CODE(gst_discoverer_audio_info, GstDiscovererAudioInfo*, \
792 GST_TYPE_DISCOVERER_AUDIO_INFO, \
793 fieldname, type, failval)
794
795 /**
796 * gst_discoverer_audio_info_get_channels:
797 * @info: a #GstDiscovererAudioInfo
798 *
799 * Returns: the number of channels in the stream.
800 */
801
802 AUDIO_INFO_ACCESSOR_CODE (channels, guint, 0);
803
804 /**
805 * gst_discoverer_audio_info_get_channel_mask:
806 * @info: a #GstDiscovererAudioInfo
807 *
808 * Returns: the channel-mask of the stream, refer to
809 * gst_audio_channel_positions_from_mask() for more
810 * information.
811 *
812 * Since: 1.14
813 */
814
815 AUDIO_INFO_ACCESSOR_CODE (channel_mask, guint64, G_MAXUINT64);
816
817 /**
818 * gst_discoverer_audio_info_get_sample_rate:
819 * @info: a #GstDiscovererAudioInfo
820 *
821 * Returns: the sample rate of the stream in Hertz.
822 */
823
824 AUDIO_INFO_ACCESSOR_CODE (sample_rate, guint, 0);
825
826 /**
827 * gst_discoverer_audio_info_get_depth:
828 * @info: a #GstDiscovererAudioInfo
829 *
830 * Returns: the number of bits used per sample in each channel.
831 */
832
833 AUDIO_INFO_ACCESSOR_CODE (depth, guint, 0);
834
835 /**
836 * gst_discoverer_audio_info_get_bitrate:
837 * @info: a #GstDiscovererAudioInfo
838 *
839 * Returns: the average or nominal bitrate of the stream in bits/second.
840 */
841
842 AUDIO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
843
844 /**
845 * gst_discoverer_audio_info_get_max_bitrate:
846 * @info: a #GstDiscovererAudioInfo
847 *
848 * Returns: the maximum bitrate of the stream in bits/second.
849 */
850
851 AUDIO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
852
853 /**
854 * gst_discoverer_audio_info_get_language:
855 * @info: a #GstDiscovererAudioInfo
856 *
857 * Returns: the language of the stream, or NULL if unknown.
858 */
859
860 AUDIO_INFO_ACCESSOR_CODE (language, const gchar *, NULL);
861
862 /* GstDiscovererVideoInfo */
863
864 #define VIDEO_INFO_ACCESSOR_CODE(fieldname, type, failval) \
865 GENERIC_ACCESSOR_CODE(gst_discoverer_video_info, GstDiscovererVideoInfo*, \
866 GST_TYPE_DISCOVERER_VIDEO_INFO, \
867 fieldname, type, failval)
868
869 /**
870 * gst_discoverer_video_info_get_width:
871 * @info: a #GstDiscovererVideoInfo
872 *
873 * Returns: the width of the video stream in pixels.
874 */
875
876 VIDEO_INFO_ACCESSOR_CODE (width, guint, 0);
877
878 /**
879 * gst_discoverer_video_info_get_height:
880 * @info: a #GstDiscovererVideoInfo
881 *
882 * Returns: the height of the video stream in pixels.
883 */
884
885 VIDEO_INFO_ACCESSOR_CODE (height, guint, 0);
886
887 /**
888 * gst_discoverer_video_info_get_depth:
889 * @info: a #GstDiscovererVideoInfo
890 *
891 * Returns: the depth in bits of the video stream.
892 */
893
894 VIDEO_INFO_ACCESSOR_CODE (depth, guint, 0);
895
896 /**
897 * gst_discoverer_video_info_get_framerate_num:
898 * @info: a #GstDiscovererVideoInfo
899 *
900 * Returns: the framerate of the video stream (numerator).
901 */
902
903 VIDEO_INFO_ACCESSOR_CODE (framerate_num, guint, 0);
904
905 /**
906 * gst_discoverer_video_info_get_framerate_denom:
907 * @info: a #GstDiscovererVideoInfo
908 *
909 * Returns: the framerate of the video stream (denominator).
910 */
911
912 VIDEO_INFO_ACCESSOR_CODE (framerate_denom, guint, 0);
913
914 /**
915 * gst_discoverer_video_info_get_par_num:
916 * @info: a #GstDiscovererVideoInfo
917 *
918 * Returns: the Pixel Aspect Ratio (PAR) of the video stream (numerator).
919 */
920
921 VIDEO_INFO_ACCESSOR_CODE (par_num, guint, 0);
922
923 /**
924 * gst_discoverer_video_info_get_par_denom:
925 * @info: a #GstDiscovererVideoInfo
926 *
927 * Returns: the Pixel Aspect Ratio (PAR) of the video stream (denominator).
928 */
929
930 VIDEO_INFO_ACCESSOR_CODE (par_denom, guint, 0);
931
932 /**
933 * gst_discoverer_video_info_is_interlaced:
934 * @info: a #GstDiscovererVideoInfo
935 *
936 * Returns: %TRUE if the stream is interlaced, else %FALSE.
937 */
938 gboolean
gst_discoverer_video_info_is_interlaced(const GstDiscovererVideoInfo * info)939 gst_discoverer_video_info_is_interlaced (const GstDiscovererVideoInfo * info)
940 {
941 g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE);
942
943 return info->interlaced;
944 }
945
946 /**
947 * gst_discoverer_video_info_get_bitrate:
948 * @info: a #GstDiscovererVideoInfo
949 *
950 * Returns: the average or nominal bitrate of the video stream in bits/second.
951 */
952
953 VIDEO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
954
955 /**
956 * gst_discoverer_video_info_get_max_bitrate:
957 * @info: a #GstDiscovererVideoInfo
958 *
959 * Returns: the maximum bitrate of the video stream in bits/second.
960 */
961
962 VIDEO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
963
964 /**
965 * gst_discoverer_video_info_is_image:
966 * @info: a #GstDiscovererVideoInfo
967 *
968 * Returns: %TRUE if the video stream corresponds to an image (i.e. only contains
969 * one frame).
970 */
971 gboolean
gst_discoverer_video_info_is_image(const GstDiscovererVideoInfo * info)972 gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info)
973 {
974 g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE);
975
976 return info->is_image;
977 }
978
979 /* GstDiscovererSubtitleInfo */
980
981 #define SUBTITLE_INFO_ACCESSOR_CODE(fieldname, type, failval) \
982 GENERIC_ACCESSOR_CODE(gst_discoverer_subtitle_info, GstDiscovererSubtitleInfo*, \
983 GST_TYPE_DISCOVERER_SUBTITLE_INFO, \
984 fieldname, type, failval)
985
986 /**
987 * gst_discoverer_subtitle_info_get_language:
988 * @info: a #GstDiscovererSubtitleInfo
989 *
990 * Returns: the language of the stream, or NULL if unknown.
991 */
992
993 SUBTITLE_INFO_ACCESSOR_CODE (language, const gchar *, NULL);
994
995 /* GstDiscovererInfo */
996
997 #define DISCOVERER_INFO_ACCESSOR_CODE(fieldname, type, failval) \
998 GENERIC_ACCESSOR_CODE(gst_discoverer_info, GstDiscovererInfo*, \
999 GST_TYPE_DISCOVERER_INFO, \
1000 fieldname, type, failval)
1001
1002 /**
1003 * gst_discoverer_info_get_uri:
1004 * @info: a #GstDiscovererInfo
1005 *
1006 * Returns: (transfer none): the URI to which this information corresponds to.
1007 * Copy it if you wish to use it after the life-time of @info.
1008 */
1009
1010 DISCOVERER_INFO_ACCESSOR_CODE (uri, const gchar *, NULL);
1011
1012 /**
1013 * gst_discoverer_info_get_result:
1014 * @info: a #GstDiscovererInfo
1015 *
1016 * Returns: the result of the discovery as a #GstDiscovererResult.
1017 */
1018
1019 DISCOVERER_INFO_ACCESSOR_CODE (result, GstDiscovererResult, GST_DISCOVERER_OK);
1020
1021 /**
1022 * gst_discoverer_info_get_stream_info:
1023 * @info: a #GstDiscovererInfo
1024 *
1025 * Returns: (transfer full): the structure (or topology) of the URI as a
1026 * #GstDiscovererStreamInfo.
1027 * This structure can be traversed to see the original hierarchy. Unref with
1028 * gst_discoverer_stream_info_unref() after usage.
1029 */
1030
1031 GstDiscovererStreamInfo *
gst_discoverer_info_get_stream_info(GstDiscovererInfo * info)1032 gst_discoverer_info_get_stream_info (GstDiscovererInfo * info)
1033 {
1034 g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL);
1035
1036 if (info->stream_info)
1037 return gst_discoverer_stream_info_ref (info->stream_info);
1038 return NULL;
1039 }
1040
1041 /**
1042 * gst_discoverer_info_get_stream_list:
1043 * @info: a #GstDiscovererInfo
1044 *
1045 * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): the list of
1046 * all streams contained in the #info. Free after usage
1047 * with gst_discoverer_stream_info_list_free().
1048 */
1049 GList *
gst_discoverer_info_get_stream_list(GstDiscovererInfo * info)1050 gst_discoverer_info_get_stream_list (GstDiscovererInfo * info)
1051 {
1052 GList *res = NULL, *tmp;
1053
1054 g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL);
1055
1056 for (tmp = info->stream_list; tmp; tmp = tmp->next)
1057 res =
1058 g_list_append (res,
1059 gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data));
1060
1061 return res;
1062 }
1063
1064 /**
1065 * gst_discoverer_info_get_duration:
1066 * @info: a #GstDiscovererInfo
1067 *
1068 * Returns: the duration of the URI in #GstClockTime (nanoseconds).
1069 */
1070
1071 DISCOVERER_INFO_ACCESSOR_CODE (duration, GstClockTime, GST_CLOCK_TIME_NONE);
1072
1073 /**
1074 * gst_discoverer_info_get_seekable:
1075 * @info: a #GstDiscovererInfo
1076 *
1077 * Returns: the whether the URI is seekable.
1078 */
1079
1080 DISCOVERER_INFO_ACCESSOR_CODE (seekable, gboolean, FALSE);
1081
1082 /**
1083 * gst_discoverer_info_get_live:
1084 * @info: a #GstDiscovererInfo
1085 *
1086 * Returns: whether the URI is live.
1087 *
1088 * Since: 1.14
1089 */
1090
1091 DISCOVERER_INFO_ACCESSOR_CODE (live, gboolean, FALSE);
1092
1093 #ifndef GST_REMOVE_DEPRECATED
1094 /**
1095 * gst_discoverer_info_get_misc:
1096 * @info: a #GstDiscovererInfo
1097 *
1098 * Deprecated: This functions is deprecated since version 1.4, use
1099 * #gst_discoverer_info_get_missing_elements_installer_details
1100 *
1101 * Returns: (transfer none): Miscellaneous information stored as a #GstStructure
1102 * (for example: information about missing plugins). If you wish to use the
1103 * #GstStructure after the life-time of @info, you will need to copy it.
1104 */
1105
1106 DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL);
1107
1108 /**
1109 * gst_discoverer_info_get_tags:
1110 * @info: a #GstDiscovererInfo
1111 *
1112 * Returns: (transfer none): all tags contained in the URI. If you wish to use
1113 * the tags after the life-time of @info, you will need to copy them.
1114 *
1115 * Deprecated: 1.20: Use gst_discoverer_{container,stream}_info_get_tags() instead.
1116 */
1117
1118 DISCOVERER_INFO_ACCESSOR_CODE (tags, const GstTagList *, NULL);
1119 #endif
1120
1121 /**
1122 * gst_discoverer_info_get_toc:
1123 * @info: a #GstDiscovererInfo
1124 *
1125 * Returns: (transfer none): TOC contained in the URI. If you wish to use
1126 * the TOC after the life-time of @info, you will need to copy it.
1127 */
1128
1129 DISCOVERER_INFO_ACCESSOR_CODE (toc, const GstToc *, NULL);
1130
1131 /**
1132 * gst_discoverer_info_ref:
1133 * @info: a #GstDiscovererInfo
1134 *
1135 * Increments the reference count of @info.
1136 *
1137 * Returns: the same #GstDiscovererInfo object
1138 */
1139
1140 /**
1141 * gst_discoverer_info_unref:
1142 * @info: a #GstDiscovererInfo
1143 *
1144 * Decrements the reference count of @info.
1145 */
1146
1147 /**
1148 * gst_discoverer_stream_info_ref:
1149 * @info: a #GstDiscovererStreamInfo
1150 *
1151 * Increments the reference count of @info.
1152 *
1153 * Returns: the same #GstDiscovererStreamInfo object
1154 */
1155
1156 /**
1157 * gst_discoverer_stream_info_unref:
1158 * @info: a #GstDiscovererStreamInfo
1159 *
1160 * Decrements the reference count of @info.
1161 */
1162
1163
1164 /**
1165 * gst_discoverer_info_get_missing_elements_installer_details:
1166 * @info: a #GstDiscovererStreamInfo to retrieve installer detail
1167 * for the missing element
1168 *
1169 * Get the installer details for missing elements
1170 *
1171 * Returns: (transfer none) (array zero-terminated=1): An array of strings
1172 * containing information about how to install the various missing elements
1173 * for @info to be usable. If you wish to use the strings after the life-time
1174 * of @info, you will need to copy them.
1175 *
1176 * Since: 1.4
1177 */
1178 const gchar **
gst_discoverer_info_get_missing_elements_installer_details(const GstDiscovererInfo * info)1179 gst_discoverer_info_get_missing_elements_installer_details (const
1180 GstDiscovererInfo * info)
1181 {
1182
1183 if (info->result != GST_DISCOVERER_MISSING_PLUGINS) {
1184 GST_WARNING_OBJECT (info, "Trying to get missing element installed details "
1185 "but result is not 'MISSING_PLUGINS'");
1186
1187 return NULL;
1188 }
1189
1190 if (info->missing_elements_details->pdata[info->missing_elements_details->
1191 len]) {
1192 GST_DEBUG ("Adding NULL pointer to the end of missing_elements_details");
1193 g_ptr_array_add (info->missing_elements_details, NULL);
1194 }
1195
1196 return (const gchar **) info->missing_elements_details->pdata;
1197 }
1198