diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-09-25 13:57:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-09-25 13:57:45 +0000 |
commit | 3a10e7b630e4c5e6f7c534e7f762fbb733a03ab3 (patch) | |
tree | 95b9bfc7b5a7178bf56d7533ff5198ad9aa0b1c8 | |
parent | ac15ab4bc2928e9cfbbcd53dce67d3aa80034dda (diff) | |
download | libextractor-3a10e7b630e4c5e6f7c534e7f762fbb733a03ab3.tar.gz libextractor-3a10e7b630e4c5e6f7c534e7f762fbb733a03ab3.zip |
documenting the code a bit
-rw-r--r-- | src/plugins/gstreamer_extractor.c | 396 |
1 files changed, 297 insertions, 99 deletions
diff --git a/src/plugins/gstreamer_extractor.c b/src/plugins/gstreamer_extractor.c index 34c10e3..8e4a2ee 100644 --- a/src/plugins/gstreamer_extractor.c +++ b/src/plugins/gstreamer_extractor.c | |||
@@ -757,61 +757,181 @@ struct NamedTag named_tags[] = | |||
757 | }; | 757 | }; |
758 | 758 | ||
759 | 759 | ||
760 | /** | ||
761 | * | ||
762 | */ | ||
760 | enum CurrentStreamType | 763 | enum CurrentStreamType |
761 | { | 764 | { |
765 | /** | ||
766 | * | ||
767 | */ | ||
762 | STREAM_TYPE_NONE = 0, | 768 | STREAM_TYPE_NONE = 0, |
769 | |||
770 | /** | ||
771 | * | ||
772 | */ | ||
763 | STREAM_TYPE_AUDIO = 1, | 773 | STREAM_TYPE_AUDIO = 1, |
774 | |||
775 | /** | ||
776 | * | ||
777 | */ | ||
764 | STREAM_TYPE_VIDEO = 2, | 778 | STREAM_TYPE_VIDEO = 2, |
779 | |||
780 | /** | ||
781 | * | ||
782 | */ | ||
765 | STREAM_TYPE_SUBTITLE = 3, | 783 | STREAM_TYPE_SUBTITLE = 3, |
784 | |||
785 | /** | ||
786 | * | ||
787 | */ | ||
766 | STREAM_TYPE_CONTAINER = 4, | 788 | STREAM_TYPE_CONTAINER = 4, |
789 | |||
790 | /** | ||
791 | * | ||
792 | */ | ||
767 | STREAM_TYPE_IMAGE = 5 | 793 | STREAM_TYPE_IMAGE = 5 |
768 | }; | 794 | }; |
769 | 795 | ||
770 | 796 | ||
797 | /** | ||
798 | * Closure we pass when processing a request. | ||
799 | */ | ||
771 | struct PrivStruct | 800 | struct PrivStruct |
772 | { | 801 | { |
802 | /** | ||
803 | * Tracks the time from the last IO request so that we can decide | ||
804 | * to terminate processing if GStreamer just takes far too long. | ||
805 | * Values are based on 'g_get_monotonic_time()', in milliseconds. | ||
806 | */ | ||
807 | gint64 last_data_request_time; | ||
808 | |||
809 | /** | ||
810 | * Current read-offset in the 'ec' context (based on our read/seek calls). | ||
811 | */ | ||
812 | guint64 offset; | ||
813 | |||
814 | /** | ||
815 | * Overall size of the file we're processing, UINT64_MAX if unknown. | ||
816 | */ | ||
817 | uint64_t length; | ||
818 | |||
819 | /** | ||
820 | * | ||
821 | */ | ||
773 | GstElement *source; | 822 | GstElement *source; |
823 | |||
824 | /** | ||
825 | * Extraction context for IO on the underlying data. | ||
826 | */ | ||
774 | struct EXTRACTOR_ExtractContext *ec; | 827 | struct EXTRACTOR_ExtractContext *ec; |
775 | long length; | 828 | |
776 | guint64 offset; | 829 | /** |
777 | int toc_depth; | 830 | * Glib main loop. |
778 | size_t toc_length; | 831 | */ |
779 | size_t toc_pos; | ||
780 | gchar *toc; | ||
781 | gboolean toc_print_phase; | ||
782 | unsigned char time_to_leave; | ||
783 | enum CurrentStreamType st; | ||
784 | GMainLoop *loop; | 832 | GMainLoop *loop; |
833 | |||
834 | /** | ||
835 | * Discoverer object we are using. | ||
836 | */ | ||
785 | GstDiscoverer *dc; | 837 | GstDiscoverer *dc; |
838 | |||
839 | /** | ||
840 | * Location for building the XML 'table of contents' (EXTRACTOR_METATYPE_TOC) for | ||
841 | * the input. Used only during 'send_info'. | ||
842 | */ | ||
843 | gchar *toc; | ||
844 | |||
845 | /** | ||
846 | * Length of the 'toc' string. | ||
847 | */ | ||
848 | size_t toc_length; | ||
849 | |||
850 | /** | ||
851 | * Current position (used when creating the 'toc' string). | ||
852 | */ | ||
853 | size_t toc_pos; | ||
854 | |||
855 | /** | ||
856 | * | ||
857 | */ | ||
786 | guint timeout_id; | 858 | guint timeout_id; |
787 | gint64 last_data_request_time; | 859 | |
860 | /** | ||
861 | * Counter used to determine our current depth in the TOC hierarchy. | ||
862 | */ | ||
863 | int toc_depth; | ||
864 | |||
865 | /** | ||
866 | * | ||
867 | */ | ||
868 | enum CurrentStreamType st; | ||
869 | |||
870 | /** | ||
871 | * Last return value from the meta data processor. Set to | ||
872 | * 1 to abort, 0 to continue extracting. | ||
873 | */ | ||
874 | int time_to_leave; | ||
875 | |||
876 | /** | ||
877 | * TOC generation is executed in two phases. First phase determines | ||
878 | * the size of the string and the second phase actually does the | ||
879 | * 'printing' (string construction). This bit is TRUE if we are | ||
880 | * in the 'printing' phase. | ||
881 | */ | ||
882 | gboolean toc_print_phase; | ||
883 | |||
788 | }; | 884 | }; |
789 | 885 | ||
790 | 886 | ||
887 | /** | ||
888 | * | ||
889 | */ | ||
791 | static GQuark *audio_quarks; | 890 | static GQuark *audio_quarks; |
792 | 891 | ||
892 | /** | ||
893 | * | ||
894 | */ | ||
793 | static GQuark *video_quarks; | 895 | static GQuark *video_quarks; |
794 | 896 | ||
897 | /** | ||
898 | * | ||
899 | */ | ||
795 | static GQuark *subtitle_quarks; | 900 | static GQuark *subtitle_quarks; |
796 | 901 | ||
902 | /** | ||
903 | * | ||
904 | */ | ||
797 | static GQuark duration_quark; | 905 | static GQuark duration_quark; |
798 | 906 | ||
799 | 907 | ||
908 | /** | ||
909 | * Implementation of GstElement's "need-data" callback. Reads data from | ||
910 | * the extraction context and passes it to GStreamer. | ||
911 | * | ||
912 | * @param appsrc the GstElement for which we are implementing "need-data" | ||
913 | * @param size number of bytes requested | ||
914 | * @param ps our execution context | ||
915 | */ | ||
800 | static void | 916 | static void |
801 | feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps) | 917 | feed_data (GstElement * appsrc, |
918 | guint size, | ||
919 | struct PrivStruct * ps) | ||
802 | { | 920 | { |
803 | long data_len; | 921 | ssize_t data_len; |
804 | uint8_t *le_data; | 922 | uint8_t *le_data; |
805 | guint accumulated; | 923 | guint accumulated; |
806 | GstMemory *mem; | 924 | GstMemory *mem; |
807 | GstMapInfo mi; | 925 | GstMapInfo mi; |
926 | GstBuffer *buffer; | ||
808 | 927 | ||
809 | GST_DEBUG ("Request %u bytes", size); | 928 | GST_DEBUG ("Request %u bytes", size); |
810 | 929 | ||
811 | /* Update it now, in case we bail out due to error */ | 930 | /* Update it now, in case we bail out due to error */ |
812 | ps->last_data_request_time = g_get_monotonic_time (); | 931 | ps->last_data_request_time = g_get_monotonic_time (); |
813 | 932 | ||
814 | if (ps->length > 0 && ps->offset >= ps->length) { | 933 | if ( (ps->length > 0) && (ps->offset >= ps->length) ) |
934 | { | ||
815 | /* we are at the EOS, send end-of-stream */ | 935 | /* we are at the EOS, send end-of-stream */ |
816 | gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); | 936 | gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); |
817 | return; | 937 | return; |
@@ -831,7 +951,7 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps) | |||
831 | 951 | ||
832 | accumulated = 0; | 952 | accumulated = 0; |
833 | data_len = 1; | 953 | data_len = 1; |
834 | while (accumulated < size && data_len > 0) | 954 | while ( (accumulated < size) && (data_len > 0) ) |
835 | { | 955 | { |
836 | data_len = ps->ec->read (ps->ec->cls, (void **) &le_data, size - accumulated); | 956 | data_len = ps->ec->read (ps->ec->cls, (void **) &le_data, size - accumulated); |
837 | if (data_len > 0) | 957 | if (data_len > 0) |
@@ -841,9 +961,8 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps) | |||
841 | } | 961 | } |
842 | } | 962 | } |
843 | gst_memory_unmap (mem, &mi); | 963 | gst_memory_unmap (mem, &mi); |
844 | if (data_len > 0) | 964 | if (size == accumulated) |
845 | { | 965 | { |
846 | GstBuffer *buffer; | ||
847 | buffer = gst_buffer_new (); | 966 | buffer = gst_buffer_new (); |
848 | gst_buffer_append_memory (buffer, mem); | 967 | gst_buffer_append_memory (buffer, mem); |
849 | 968 | ||
@@ -851,8 +970,8 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps) | |||
851 | GST_BUFFER_OFFSET (buffer) = ps->offset; | 970 | GST_BUFFER_OFFSET (buffer) = ps->offset; |
852 | GST_BUFFER_OFFSET_END (buffer) = ps->offset + size; | 971 | GST_BUFFER_OFFSET_END (buffer) = ps->offset + size; |
853 | 972 | ||
854 | GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, | 973 | GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", |
855 | ps->offset, size); | 974 | buffer, ps->offset, size); |
856 | gst_app_src_push_buffer (GST_APP_SRC (ps->source), buffer); | 975 | gst_app_src_push_buffer (GST_APP_SRC (ps->source), buffer); |
857 | ps->offset += size; | 976 | ps->offset += size; |
858 | } | 977 | } |
@@ -860,33 +979,43 @@ feed_data (GstElement * appsrc, guint size, struct PrivStruct * ps) | |||
860 | { | 979 | { |
861 | gst_memory_unref (mem); | 980 | gst_memory_unref (mem); |
862 | gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); | 981 | gst_app_src_end_of_stream (GST_APP_SRC (ps->source)); |
982 | ps->offset = UINT64_MAX; /* set to invalid value */ | ||
863 | } | 983 | } |
864 | 984 | ||
865 | /* Update it again to account for time we spent fulfilling the request */ | 985 | /* Update it again to account for time we spent fulfilling the request */ |
866 | ps->last_data_request_time = g_get_monotonic_time (); | 986 | ps->last_data_request_time = g_get_monotonic_time (); |
867 | return; | ||
868 | } | 987 | } |
869 | 988 | ||
870 | 989 | ||
990 | /** | ||
991 | * Implementation of GstElement's "seek-data" callback. Seeks to a new | ||
992 | * position in the extraction context. | ||
993 | * | ||
994 | * @param appsrc the GstElement for which we are implementing "need-data" | ||
995 | * @param position new desired absolute position in the file | ||
996 | * @param ps our execution context | ||
997 | * @return TRUE if seeking succeeded, FALSE if not | ||
998 | */ | ||
871 | static gboolean | 999 | static gboolean |
872 | seek_data (GstElement * appsrc, guint64 position, struct PrivStruct * ps) | 1000 | seek_data (GstElement * appsrc, |
1001 | guint64 position, | ||
1002 | struct PrivStruct * ps) | ||
873 | { | 1003 | { |
874 | GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); | 1004 | GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); |
875 | ps->offset = ps->ec->seek (ps->ec->cls, position, SEEK_SET); | 1005 | ps->offset = ps->ec->seek (ps->ec->cls, position, SEEK_SET); |
876 | |||
877 | ps->last_data_request_time = g_get_monotonic_time (); | 1006 | ps->last_data_request_time = g_get_monotonic_time (); |
878 | return ps->offset >= 0; | 1007 | return ps->offset == position; |
879 | } | ||
880 | |||
881 | |||
882 | static gboolean | ||
883 | _run_async (struct PrivStruct * ps) | ||
884 | { | ||
885 | gst_discoverer_discover_uri_async (ps->dc, "appsrc://"); | ||
886 | return FALSE; | ||
887 | } | 1008 | } |
888 | 1009 | ||
889 | 1010 | ||
1011 | /** | ||
1012 | * FIXME | ||
1013 | * | ||
1014 | * @param field_id FIXME | ||
1015 | * @param value FIXME | ||
1016 | * @param user_data our 'struct PrivStruct' | ||
1017 | * @return TRUE to continue processing, FALSE to abort | ||
1018 | */ | ||
890 | static gboolean | 1019 | static gboolean |
891 | send_structure_foreach (GQuark field_id, | 1020 | send_structure_foreach (GQuark field_id, |
892 | const GValue *value, | 1021 | const GValue *value, |
@@ -922,7 +1051,6 @@ send_structure_foreach (GQuark field_id, | |||
922 | break; | 1051 | break; |
923 | } | 1052 | } |
924 | 1053 | ||
925 | |||
926 | switch (G_VALUE_TYPE (value)) | 1054 | switch (G_VALUE_TYPE (value)) |
927 | { | 1055 | { |
928 | case G_TYPE_STRING: | 1056 | case G_TYPE_STRING: |
@@ -948,7 +1076,7 @@ send_structure_foreach (GQuark field_id, | |||
948 | str = NULL; | 1076 | str = NULL; |
949 | break; | 1077 | break; |
950 | } | 1078 | } |
951 | if (NULL != str) | 1079 | if (NULL != str) |
952 | { | 1080 | { |
953 | unsigned int i; | 1081 | unsigned int i; |
954 | 1082 | ||
@@ -969,16 +1097,24 @@ send_structure_foreach (GQuark field_id, | |||
969 | gchar *senddata = g_strdup_printf ("%s=%s", field_name, str); | 1097 | gchar *senddata = g_strdup_printf ("%s=%s", field_name, str); |
970 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1098 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
971 | EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", | 1099 | EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", |
972 | (const char *) senddata, strlen (senddata) + 1); | 1100 | (const char *) senddata, |
1101 | strlen (senddata) + 1); | ||
973 | g_free (senddata); | 1102 | g_free (senddata); |
974 | } | 1103 | } |
975 | g_free (str); | 1104 | g_free (str); |
976 | 1105 | ||
977 | return !ps->time_to_leave; | 1106 | return ! ps->time_to_leave; |
978 | } | 1107 | } |
979 | 1108 | ||
980 | 1109 | ||
981 | static int | 1110 | /** |
1111 | * FIXME | ||
1112 | * | ||
1113 | * @param info FIXME | ||
1114 | * @param ps processing context | ||
1115 | * @return FALSE to continue processing, TRUE to abort | ||
1116 | */ | ||
1117 | static gboolean | ||
982 | send_audio_info (GstDiscovererAudioInfo *info, | 1118 | send_audio_info (GstDiscovererAudioInfo *info, |
983 | struct PrivStruct *ps) | 1119 | struct PrivStruct *ps) |
984 | { | 1120 | { |
@@ -1059,15 +1195,24 @@ send_audio_info (GstDiscovererAudioInfo *info, | |||
1059 | } | 1195 | } |
1060 | 1196 | ||
1061 | 1197 | ||
1198 | /** | ||
1199 | * FIXME | ||
1200 | * | ||
1201 | * @param info FIXME | ||
1202 | * @param ps processing context | ||
1203 | * @return FALSE to continue processing, TRUE to abort | ||
1204 | */ | ||
1062 | static int | 1205 | static int |
1063 | send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | 1206 | send_video_info (GstDiscovererVideoInfo *info, |
1207 | struct PrivStruct *ps) | ||
1064 | { | 1208 | { |
1065 | gchar *tmp; | 1209 | gchar *tmp; |
1066 | guint u, u2; | 1210 | guint u; |
1211 | guint u2; | ||
1067 | 1212 | ||
1068 | u = gst_discoverer_video_info_get_width (info); | 1213 | u = gst_discoverer_video_info_get_width (info); |
1069 | u2 = gst_discoverer_video_info_get_height (info); | 1214 | u2 = gst_discoverer_video_info_get_height (info); |
1070 | if (u > 0 && u2 > 0) | 1215 | if ( (u > 0) && (u2 > 0) ) |
1071 | { | 1216 | { |
1072 | tmp = g_strdup_printf ("%ux%u", u, u2); | 1217 | tmp = g_strdup_printf ("%ux%u", u, u2); |
1073 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1218 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
@@ -1092,7 +1237,7 @@ send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | |||
1092 | 1237 | ||
1093 | u = gst_discoverer_video_info_get_framerate_num (info); | 1238 | u = gst_discoverer_video_info_get_framerate_num (info); |
1094 | u2 = gst_discoverer_video_info_get_framerate_denom (info); | 1239 | u2 = gst_discoverer_video_info_get_framerate_denom (info); |
1095 | if (u > 0 && u2 > 0) | 1240 | if ( (u > 0) && (u2 > 0) ) |
1096 | { | 1241 | { |
1097 | tmp = g_strdup_printf ("%u/%u", u, u2); | 1242 | tmp = g_strdup_printf ("%u/%u", u, u2); |
1098 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1243 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
@@ -1105,7 +1250,7 @@ send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | |||
1105 | 1250 | ||
1106 | u = gst_discoverer_video_info_get_par_num (info); | 1251 | u = gst_discoverer_video_info_get_par_num (info); |
1107 | u2 = gst_discoverer_video_info_get_par_denom (info); | 1252 | u2 = gst_discoverer_video_info_get_par_denom (info); |
1108 | if (u > 0 && u2 > 0) | 1253 | if ( (u > 0) && (u2 > 0) ) |
1109 | { | 1254 | { |
1110 | tmp = g_strdup_printf ("%u/%u", u, u2); | 1255 | tmp = g_strdup_printf ("%u/%u", u, u2); |
1111 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1256 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
@@ -1119,7 +1264,7 @@ send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | |||
1119 | /* gst_discoverer_video_info_is_interlaced (info) I don't trust it... */ | 1264 | /* gst_discoverer_video_info_is_interlaced (info) I don't trust it... */ |
1120 | 1265 | ||
1121 | u = gst_discoverer_video_info_get_bitrate (info); | 1266 | u = gst_discoverer_video_info_get_bitrate (info); |
1122 | if (u > 0 && u2 > 0) | 1267 | if (u > 0) |
1123 | { | 1268 | { |
1124 | tmp = g_strdup_printf ("%u", u); | 1269 | tmp = g_strdup_printf ("%u", u); |
1125 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1270 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
@@ -1131,7 +1276,7 @@ send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | |||
1131 | } | 1276 | } |
1132 | 1277 | ||
1133 | u = gst_discoverer_video_info_get_max_bitrate (info); | 1278 | u = gst_discoverer_video_info_get_max_bitrate (info); |
1134 | if (u > 0 && u2 > 0) | 1279 | if (u > 0) |
1135 | { | 1280 | { |
1136 | tmp = g_strdup_printf ("%u", u); | 1281 | tmp = g_strdup_printf ("%u", u); |
1137 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1282 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
@@ -1146,18 +1291,27 @@ send_video_info (GstDiscovererVideoInfo *info, struct PrivStruct *ps) | |||
1146 | } | 1291 | } |
1147 | 1292 | ||
1148 | 1293 | ||
1294 | /** | ||
1295 | * FIXME | ||
1296 | * | ||
1297 | * @param info FIXME | ||
1298 | * @param ps processing context | ||
1299 | * @return FALSE to continue processing, TRUE to abort | ||
1300 | */ | ||
1149 | static int | 1301 | static int |
1150 | send_subtitle_info (GstDiscovererSubtitleInfo *info, struct PrivStruct *ps) | 1302 | send_subtitle_info (GstDiscovererSubtitleInfo *info, |
1303 | struct PrivStruct *ps) | ||
1151 | { | 1304 | { |
1152 | const gchar *ctmp; | 1305 | const gchar *ctmp; |
1153 | 1306 | ||
1154 | ctmp = gst_discoverer_subtitle_info_get_language (info); | 1307 | ctmp = gst_discoverer_subtitle_info_get_language (info); |
1155 | if (ctmp) | 1308 | if ( (NULL != ctmp) && |
1156 | if ((ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1309 | (0 != (ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
1157 | EXTRACTOR_METATYPE_SUBTITLE_LANGUAGE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", | 1310 | EXTRACTOR_METATYPE_SUBTITLE_LANGUAGE, |
1158 | (const char *) ctmp, strlen (ctmp) + 1))) | 1311 | EXTRACTOR_METAFORMAT_UTF8, |
1159 | return TRUE; | 1312 | "text/plain", |
1160 | 1313 | (const char *) ctmp, strlen (ctmp) + 1))) ) | |
1314 | return TRUE; | ||
1161 | return FALSE; | 1315 | return FALSE; |
1162 | } | 1316 | } |
1163 | 1317 | ||
@@ -1167,11 +1321,11 @@ send_tag_foreach (const GstTagList * tags, | |||
1167 | const gchar * tag, | 1321 | const gchar * tag, |
1168 | gpointer user_data) | 1322 | gpointer user_data) |
1169 | { | 1323 | { |
1324 | static struct KnownTag unknown_tag = {NULL, EXTRACTOR_METATYPE_UNKNOWN}; | ||
1170 | struct PrivStruct *ps = user_data; | 1325 | struct PrivStruct *ps = user_data; |
1171 | size_t i; | 1326 | size_t i; |
1172 | size_t tagl = sizeof (__known_tags) / sizeof (struct KnownTag); | 1327 | size_t tagl = sizeof (__known_tags) / sizeof (struct KnownTag); |
1173 | struct KnownTag *kt = NULL; | 1328 | const struct KnownTag *kt = NULL; |
1174 | struct KnownTag unknown_tag = {NULL, EXTRACTOR_METATYPE_UNKNOWN}; | ||
1175 | GQuark tag_quark; | 1329 | GQuark tag_quark; |
1176 | guint vallen; | 1330 | guint vallen; |
1177 | GstSample *sample; | 1331 | GstSample *sample; |
@@ -1517,12 +1671,13 @@ send_stream_info (GstDiscovererStreamInfo * info, | |||
1517 | 1671 | ||
1518 | 1672 | ||
1519 | static void | 1673 | static void |
1520 | send_streams (GstDiscovererStreamInfo *info, struct PrivStruct *ps) | 1674 | send_streams (GstDiscovererStreamInfo *info, |
1675 | struct PrivStruct *ps) | ||
1521 | { | 1676 | { |
1677 | GstDiscovererStreamInfo *next; | ||
1678 | |||
1522 | while ( (NULL != info) && (! ps->time_to_leave) ) | 1679 | while ( (NULL != info) && (! ps->time_to_leave) ) |
1523 | { | 1680 | { |
1524 | GstDiscovererStreamInfo *next; | ||
1525 | |||
1526 | send_stream_info (info, ps); | 1681 | send_stream_info (info, ps); |
1527 | next = gst_discoverer_stream_info_get_next (info); | 1682 | next = gst_discoverer_stream_info_get_next (info); |
1528 | gst_discoverer_stream_info_unref (info); | 1683 | gst_discoverer_stream_info_unref (info); |
@@ -1531,6 +1686,13 @@ send_streams (GstDiscovererStreamInfo *info, struct PrivStruct *ps) | |||
1531 | } | 1686 | } |
1532 | 1687 | ||
1533 | 1688 | ||
1689 | /** | ||
1690 | * Callback used to construct the XML 'toc'. | ||
1691 | * | ||
1692 | * @param tags FIXME | ||
1693 | * @param tag FIXME | ||
1694 | * @param user_data the 'struct PrivStruct' with the 'toc' string we are assembling | ||
1695 | */ | ||
1534 | static void | 1696 | static void |
1535 | send_toc_tags_foreach (const GstTagList * tags, | 1697 | send_toc_tags_foreach (const GstTagList * tags, |
1536 | const gchar * tag, | 1698 | const gchar * tag, |
@@ -1588,6 +1750,12 @@ send_toc_tags_foreach (const GstTagList * tags, | |||
1588 | } | 1750 | } |
1589 | 1751 | ||
1590 | 1752 | ||
1753 | /** | ||
1754 | * Top-level callback used to construct the XML 'toc'. | ||
1755 | * | ||
1756 | * @param data the GstTocEntry we're processing | ||
1757 | * @param user_data the 'struct PrivStruct' with the 'toc' string we are assembling | ||
1758 | */ | ||
1591 | static void | 1759 | static void |
1592 | send_toc_foreach (gpointer data, gpointer user_data) | 1760 | send_toc_foreach (gpointer data, gpointer user_data) |
1593 | { | 1761 | { |
@@ -1595,68 +1763,72 @@ send_toc_foreach (gpointer data, gpointer user_data) | |||
1595 | struct PrivStruct *ps = user_data; | 1763 | struct PrivStruct *ps = user_data; |
1596 | GstTagList *tags; | 1764 | GstTagList *tags; |
1597 | GList *subentries; | 1765 | GList *subentries; |
1598 | gint64 start, stop; | 1766 | gint64 start; |
1767 | gint64 stop; | ||
1599 | GstTocEntryType entype; | 1768 | GstTocEntryType entype; |
1769 | gchar *s; | ||
1600 | 1770 | ||
1601 | entype = gst_toc_entry_get_entry_type (entry); | 1771 | entype = gst_toc_entry_get_entry_type (entry); |
1602 | if (GST_TOC_ENTRY_TYPE_INVALID != entype) | 1772 | if (GST_TOC_ENTRY_TYPE_INVALID == entype) |
1603 | { | 1773 | return; |
1604 | char *s; | 1774 | gst_toc_entry_get_start_stop_times (entry, &start, &stop); |
1605 | 1775 | s = g_strdup_printf ("%*.*s<%s start=\"%" GST_TIME_FORMAT "\" stop=\"%" | |
1606 | gst_toc_entry_get_start_stop_times (entry, &start, &stop); | 1776 | GST_TIME_FORMAT"\">\n", ps->toc_depth * 2, ps->toc_depth * 2, " ", |
1607 | s = g_strdup_printf ("%*.*s<%s start=\"%" GST_TIME_FORMAT "\" stop=\"%" | 1777 | gst_toc_entry_type_get_nick (entype), GST_TIME_ARGS (start), |
1608 | GST_TIME_FORMAT"\">\n", ps->toc_depth * 2, ps->toc_depth * 2, " ", | 1778 | GST_TIME_ARGS (stop)); |
1609 | gst_toc_entry_type_get_nick (entype), GST_TIME_ARGS (start), | 1779 | if (ps->toc_print_phase) |
1610 | GST_TIME_ARGS (stop)); | 1780 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, "%s", s); |
1611 | if (ps->toc_print_phase) | 1781 | else |
1612 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, "%s", s); | 1782 | ps->toc_length += strlen (s); |
1613 | else | 1783 | g_free (s); |
1614 | ps->toc_length += strlen (s); | 1784 | ps->toc_depth++; |
1615 | g_free (s); | 1785 | tags = gst_toc_entry_get_tags (entry); |
1616 | ps->toc_depth++; | 1786 | if (tags) |
1617 | tags = gst_toc_entry_get_tags (entry); | ||
1618 | if (tags) | ||
1619 | { | 1787 | { |
1620 | if (ps->toc_print_phase) | 1788 | if (ps->toc_print_phase) |
1621 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, | 1789 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, |
1622 | "%*.*s<tags>\n", ps->toc_depth * 2, ps->toc_depth * 2, " "); | 1790 | "%*.*s<tags>\n", ps->toc_depth * 2, ps->toc_depth * 2, " "); |
1623 | else | 1791 | else |
1624 | ps->toc_length += strlen ("<tags>\n") + ps->toc_depth * 2; | 1792 | ps->toc_length += strlen ("<tags>\n") + ps->toc_depth * 2; |
1625 | ps->toc_depth++; | 1793 | ps->toc_depth++; |
1626 | gst_tag_list_foreach (tags, send_toc_tags_foreach, ps); | 1794 | gst_tag_list_foreach (tags, &send_toc_tags_foreach, ps); |
1627 | ps->toc_depth--; | 1795 | ps->toc_depth--; |
1628 | if (ps->toc_print_phase) | 1796 | if (ps->toc_print_phase) |
1629 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, | 1797 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, |
1630 | "%*.*s</tags>\n", ps->toc_depth * 2, ps->toc_depth * 2, " "); | 1798 | "%*.*s</tags>\n", ps->toc_depth * 2, ps->toc_depth * 2, " "); |
1631 | else | 1799 | else |
1632 | ps->toc_length += strlen ("</tags>\n") + ps->toc_depth * 2; | 1800 | ps->toc_length += strlen ("</tags>\n") + ps->toc_depth * 2; |
1633 | } | 1801 | } |
1634 | 1802 | ||
1635 | subentries = gst_toc_entry_get_sub_entries (entry); | 1803 | subentries = gst_toc_entry_get_sub_entries (entry); |
1636 | g_list_foreach (subentries, send_toc_foreach, ps); | 1804 | g_list_foreach (subentries, send_toc_foreach, ps); |
1637 | ps->toc_depth--; | 1805 | ps->toc_depth--; |
1638 | 1806 | ||
1639 | s = g_strdup_printf ("%*.*s</%s>\n", ps->toc_depth * 2, ps->toc_depth * 2, " ", | 1807 | s = g_strdup_printf ("%*.*s</%s>\n", ps->toc_depth * 2, ps->toc_depth * 2, " ", |
1640 | gst_toc_entry_type_get_nick (entype)); | 1808 | gst_toc_entry_type_get_nick (entype)); |
1641 | if (ps->toc_print_phase) | 1809 | if (ps->toc_print_phase) |
1642 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, "%s", s); | 1810 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, "%s", s); |
1643 | else | 1811 | else |
1644 | ps->toc_length += strlen (s); | 1812 | ps->toc_length += strlen (s); |
1645 | g_free (s); | 1813 | g_free (s); |
1646 | } | ||
1647 | } | 1814 | } |
1648 | 1815 | ||
1649 | 1816 | ||
1817 | /** | ||
1818 | * XML header for the table-of-contents meta data. | ||
1819 | */ | ||
1650 | #define TOC_XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" | 1820 | #define TOC_XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" |
1651 | 1821 | ||
1652 | 1822 | ||
1653 | static void | 1823 | static void |
1654 | send_info (GstDiscovererInfo * info, struct PrivStruct *ps) | 1824 | send_info (GstDiscovererInfo * info, |
1825 | struct PrivStruct *ps) | ||
1655 | { | 1826 | { |
1656 | const GstToc *toc; | 1827 | const GstToc *toc; |
1657 | gchar *s; | 1828 | gchar *s; |
1658 | GstDiscovererStreamInfo *sinfo; | 1829 | GstDiscovererStreamInfo *sinfo; |
1659 | GstClockTime duration; | 1830 | GstClockTime duration; |
1831 | GList *entries; | ||
1660 | 1832 | ||
1661 | duration = gst_discoverer_info_get_duration (info); | 1833 | duration = gst_discoverer_info_get_duration (info); |
1662 | if ((GST_CLOCK_TIME_IS_VALID (duration)) && (duration > 0)) | 1834 | if ((GST_CLOCK_TIME_IS_VALID (duration)) && (duration > 0)) |
@@ -1684,12 +1856,10 @@ send_info (GstDiscovererInfo * info, struct PrivStruct *ps) | |||
1684 | 1856 | ||
1685 | if ((toc = gst_discoverer_info_get_toc (info))) | 1857 | if ((toc = gst_discoverer_info_get_toc (info))) |
1686 | { | 1858 | { |
1687 | GList *entries; | ||
1688 | |||
1689 | entries = gst_toc_get_entries (toc); | 1859 | entries = gst_toc_get_entries (toc); |
1690 | ps->toc_print_phase = FALSE; | 1860 | ps->toc_print_phase = FALSE; |
1691 | ps->toc_length = 0; | 1861 | ps->toc_length = 0; |
1692 | g_list_foreach (entries, send_toc_foreach, ps); | 1862 | g_list_foreach (entries, &send_toc_foreach, ps); |
1693 | 1863 | ||
1694 | if (ps->toc_length > 0) | 1864 | if (ps->toc_length > 0) |
1695 | { | 1865 | { |
@@ -1697,18 +1867,24 @@ send_info (GstDiscovererInfo * info, struct PrivStruct *ps) | |||
1697 | ps->toc_length += 1 + strlen (TOC_XML_HEADER); | 1867 | ps->toc_length += 1 + strlen (TOC_XML_HEADER); |
1698 | ps->toc = g_malloc (ps->toc_length); | 1868 | ps->toc = g_malloc (ps->toc_length); |
1699 | ps->toc_pos = 0; | 1869 | ps->toc_pos = 0; |
1700 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], ps->toc_length - ps->toc_pos, "%s", TOC_XML_HEADER); | 1870 | ps->toc_pos += g_snprintf (&ps->toc[ps->toc_pos], |
1701 | g_list_foreach (entries, send_toc_foreach, ps); | 1871 | ps->toc_length - ps->toc_pos, |
1872 | "%s", | ||
1873 | TOC_XML_HEADER); | ||
1874 | g_list_foreach (entries, &send_toc_foreach, ps); | ||
1702 | ps->toc[ps->toc_length - 1] = '\0'; | 1875 | ps->toc[ps->toc_length - 1] = '\0'; |
1703 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", | 1876 | ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", |
1704 | EXTRACTOR_METATYPE_TOC, EXTRACTOR_METAFORMAT_C_STRING, "application/xml", | 1877 | EXTRACTOR_METATYPE_TOC, |
1705 | (const char *) ps->toc, ps->toc_length); | 1878 | EXTRACTOR_METAFORMAT_C_STRING, |
1879 | "application/xml", | ||
1880 | (const char *) ps->toc, | ||
1881 | ps->toc_length); | ||
1706 | g_free (ps->toc); | 1882 | g_free (ps->toc); |
1707 | ps->toc = NULL; | 1883 | ps->toc = NULL; |
1708 | } | 1884 | } |
1709 | } | 1885 | } |
1710 | 1886 | ||
1711 | if (ps->time_to_leave) | 1887 | if (0 != ps->time_to_leave) |
1712 | return; | 1888 | return; |
1713 | 1889 | ||
1714 | sinfo = gst_discoverer_info_get_stream_info (info); | 1890 | sinfo = gst_discoverer_info_get_stream_info (info); |
@@ -1717,7 +1893,8 @@ send_info (GstDiscovererInfo * info, struct PrivStruct *ps) | |||
1717 | 1893 | ||
1718 | 1894 | ||
1719 | static void | 1895 | static void |
1720 | send_discovered_info (GstDiscovererInfo * info, struct PrivStruct * ps) | 1896 | send_discovered_info (GstDiscovererInfo * info, |
1897 | struct PrivStruct * ps) | ||
1721 | { | 1898 | { |
1722 | GstDiscovererResult result; | 1899 | GstDiscovererResult result; |
1723 | 1900 | ||
@@ -1765,6 +1942,7 @@ _discoverer_finished (GstDiscoverer * dc, struct PrivStruct *ps) | |||
1765 | g_main_loop_quit (ps->loop); | 1942 | g_main_loop_quit (ps->loop); |
1766 | } | 1943 | } |
1767 | 1944 | ||
1945 | |||
1768 | static gboolean | 1946 | static gboolean |
1769 | _data_timeout (struct PrivStruct *ps) | 1947 | _data_timeout (struct PrivStruct *ps) |
1770 | { | 1948 | { |
@@ -1780,11 +1958,17 @@ _data_timeout (struct PrivStruct *ps) | |||
1780 | return TRUE; | 1958 | return TRUE; |
1781 | } | 1959 | } |
1782 | 1960 | ||
1961 | |||
1783 | /** | 1962 | /** |
1784 | * This callback is called when discoverer has constructed a source object to | 1963 | * This callback is called when discoverer has constructed a source object to |
1785 | * read from. Since we provided the appsrc:// uri to discoverer, this will be | 1964 | * read from. Since we provided the appsrc:// uri to discoverer, this will be |
1786 | * the appsrc that we must handle. We set up some signals - one to push data | 1965 | * the appsrc that we must handle. We set up some signals - one to push data |
1787 | * into appsrc and one to perform a seek. */ | 1966 | * into appsrc and one to perform a seek. |
1967 | * | ||
1968 | * @param dc | ||
1969 | * @param source | ||
1970 | * @param ps | ||
1971 | */ | ||
1788 | static void | 1972 | static void |
1789 | _source_setup (GstDiscoverer * dc, | 1973 | _source_setup (GstDiscoverer * dc, |
1790 | GstElement * source, | 1974 | GstElement * source, |
@@ -1816,6 +2000,20 @@ _source_setup (GstDiscoverer * dc, | |||
1816 | 2000 | ||
1817 | 2001 | ||
1818 | /** | 2002 | /** |
2003 | * Task run from the main loop to call 'gst_discoverer_uri_async'. | ||
2004 | * | ||
2005 | * @param ps our execution context | ||
2006 | * @return FALSE (always) | ||
2007 | */ | ||
2008 | static gboolean | ||
2009 | _run_async (struct PrivStruct * ps) | ||
2010 | { | ||
2011 | gst_discoverer_discover_uri_async (ps->dc, "appsrc://"); | ||
2012 | return FALSE; | ||
2013 | } | ||
2014 | |||
2015 | |||
2016 | /** | ||
1819 | * This will be the main method of your plugin. | 2017 | * This will be the main method of your plugin. |
1820 | * Describe a bit what it does here. | 2018 | * Describe a bit what it does here. |
1821 | * | 2019 | * |