aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/gstreamer_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gstreamer_extractor.c')
-rw-r--r--src/plugins/gstreamer_extractor.c393
1 files changed, 205 insertions, 188 deletions
diff --git a/src/plugins/gstreamer_extractor.c b/src/plugins/gstreamer_extractor.c
index 5fe2126..fa3eaf8 100644
--- a/src/plugins/gstreamer_extractor.c
+++ b/src/plugins/gstreamer_extractor.c
@@ -1186,9 +1186,8 @@ send_tag_foreach (const GstTagList * tags, const gchar * tag,
1186 struct KnownTag unknown_tag = {NULL, EXTRACTOR_METATYPE_UNKNOWN}; 1186 struct KnownTag unknown_tag = {NULL, EXTRACTOR_METATYPE_UNKNOWN};
1187 1187
1188 1188
1189 GValue val = { 0, };
1190 gchar *str = NULL;
1191 GQuark tag_quark; 1189 GQuark tag_quark;
1190 guint vallen;
1192 1191
1193 GstSample *sample; 1192 GstSample *sample;
1194 1193
@@ -1205,220 +1204,238 @@ send_tag_foreach (const GstTagList * tags, const gchar * tag,
1205 if (kt == NULL) 1204 if (kt == NULL)
1206 kt = &unknown_tag; 1205 kt = &unknown_tag;
1207 1206
1208 gst_tag_list_copy_value (&val, tags, tag); 1207 vallen = gst_tag_list_get_tag_size (tags, tag);
1208 if (vallen == 0)
1209 return;
1209 1210
1210 tag_quark = g_quark_from_string (tag); 1211 tag_quark = g_quark_from_string (tag);
1211 1212
1212 switch (G_VALUE_TYPE (&val)) 1213 for (i = 0; i < vallen; i++)
1213 { 1214 {
1214 case G_TYPE_STRING: 1215 GValue val = { 0, };
1215 str = g_value_dup_string (&val); 1216 const GValue *val_ref;
1216 break; 1217 gchar *str = NULL;
1217 case G_TYPE_UINT: 1218
1218 case G_TYPE_INT: 1219 val_ref = gst_tag_list_get_value_index (tags, tag, i);
1219 case G_TYPE_DOUBLE: 1220 if (val_ref == NULL)
1220 case G_TYPE_BOOLEAN:
1221 str = gst_value_serialize (&val);
1222 break;
1223 default:
1224 if (G_VALUE_TYPE (&val) == GST_TYPE_SAMPLE && (sample = gst_value_get_sample (&val)))
1225 { 1221 {
1226 GstMapInfo mi; 1222 g_value_unset (&val);
1227 const gchar *structname; 1223 continue;
1228 GstCaps *caps; 1224 }
1225 g_value_init (&val, G_VALUE_TYPE (val_ref));
1226 g_value_copy (val_ref, &val);
1229 1227
1230 caps = gst_sample_get_caps (sample); 1228 switch (G_VALUE_TYPE (&val))
1231 if (caps) 1229 {
1230 case G_TYPE_STRING:
1231 str = g_value_dup_string (&val);
1232 break;
1233 case G_TYPE_UINT:
1234 case G_TYPE_INT:
1235 case G_TYPE_DOUBLE:
1236 case G_TYPE_BOOLEAN:
1237 str = gst_value_serialize (&val);
1238 break;
1239 default:
1240 if (G_VALUE_TYPE (&val) == GST_TYPE_SAMPLE && (sample = gst_value_get_sample (&val)))
1232 { 1241 {
1233 GstTagImageType imagetype; 1242 GstMapInfo mi;
1234 const GstStructure *info; 1243 const gchar *structname;
1235 GstBuffer *buf; 1244 GstCaps *caps;
1236 const gchar *mime_type; 1245
1237 enum EXTRACTOR_MetaType le_type; 1246 caps = gst_sample_get_caps (sample);
1238 1247 if (caps)
1239 mime_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
1240 info = gst_sample_get_info (sample);
1241
1242 if (!gst_structure_get (info, "image-type", GST_TYPE_TAG_IMAGE_TYPE, &imagetype, NULL))
1243 le_type = EXTRACTOR_METATYPE_PICTURE;
1244 else
1245 { 1248 {
1246 switch (imagetype) 1249 GstTagImageType imagetype;
1247 { 1250 const GstStructure *info;
1248 case GST_TAG_IMAGE_TYPE_NONE: 1251 GstBuffer *buf;
1249 case GST_TAG_IMAGE_TYPE_UNDEFINED: 1252 const gchar *mime_type;
1250 case GST_TAG_IMAGE_TYPE_FISH: 1253 enum EXTRACTOR_MetaType le_type;
1251 case GST_TAG_IMAGE_TYPE_ILLUSTRATION: 1254
1252 default: 1255 mime_type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
1256 info = gst_sample_get_info (sample);
1257
1258 if (!gst_structure_get (info, "image-type", GST_TYPE_TAG_IMAGE_TYPE, &imagetype, NULL))
1253 le_type = EXTRACTOR_METATYPE_PICTURE; 1259 le_type = EXTRACTOR_METATYPE_PICTURE;
1254 break; 1260 else
1255 case GST_TAG_IMAGE_TYPE_FRONT_COVER: 1261 {
1256 case GST_TAG_IMAGE_TYPE_BACK_COVER: 1262 switch (imagetype)
1257 case GST_TAG_IMAGE_TYPE_LEAFLET_PAGE: 1263 {
1258 case GST_TAG_IMAGE_TYPE_MEDIUM: 1264 case GST_TAG_IMAGE_TYPE_NONE:
1259 le_type = EXTRACTOR_METATYPE_COVER_PICTURE; 1265 case GST_TAG_IMAGE_TYPE_UNDEFINED:
1260 break; 1266 case GST_TAG_IMAGE_TYPE_FISH:
1261 case GST_TAG_IMAGE_TYPE_LEAD_ARTIST: 1267 case GST_TAG_IMAGE_TYPE_ILLUSTRATION:
1262 case GST_TAG_IMAGE_TYPE_ARTIST: 1268 default:
1263 case GST_TAG_IMAGE_TYPE_CONDUCTOR: 1269 le_type = EXTRACTOR_METATYPE_PICTURE;
1264 case GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA: 1270 break;
1265 case GST_TAG_IMAGE_TYPE_COMPOSER: 1271 case GST_TAG_IMAGE_TYPE_FRONT_COVER:
1266 case GST_TAG_IMAGE_TYPE_LYRICIST: 1272 case GST_TAG_IMAGE_TYPE_BACK_COVER:
1267 le_type = EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE; 1273 case GST_TAG_IMAGE_TYPE_LEAFLET_PAGE:
1268 break; 1274 case GST_TAG_IMAGE_TYPE_MEDIUM:
1269 case GST_TAG_IMAGE_TYPE_RECORDING_LOCATION: 1275 le_type = EXTRACTOR_METATYPE_COVER_PICTURE;
1270 case GST_TAG_IMAGE_TYPE_DURING_RECORDING: 1276 break;
1271 case GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE: 1277 case GST_TAG_IMAGE_TYPE_LEAD_ARTIST:
1272 case GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE: 1278 case GST_TAG_IMAGE_TYPE_ARTIST:
1273 le_type = EXTRACTOR_METATYPE_EVENT_PICTURE; 1279 case GST_TAG_IMAGE_TYPE_CONDUCTOR:
1274 break; 1280 case GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA:
1275 case GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO: 1281 case GST_TAG_IMAGE_TYPE_COMPOSER:
1276 case GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO: 1282 case GST_TAG_IMAGE_TYPE_LYRICIST:
1277 le_type = EXTRACTOR_METATYPE_LOGO; 1283 le_type = EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE;
1278 break; 1284 break;
1285 case GST_TAG_IMAGE_TYPE_RECORDING_LOCATION:
1286 case GST_TAG_IMAGE_TYPE_DURING_RECORDING:
1287 case GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE:
1288 case GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE:
1289 le_type = EXTRACTOR_METATYPE_EVENT_PICTURE;
1290 break;
1291 case GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO:
1292 case GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO:
1293 le_type = EXTRACTOR_METATYPE_LOGO;
1294 break;
1295 }
1279 } 1296 }
1280 }
1281 1297
1282 buf = gst_sample_get_buffer (sample); 1298 buf = gst_sample_get_buffer (sample);
1283 gst_buffer_map (buf, &mi, GST_MAP_READ); 1299 gst_buffer_map (buf, &mi, GST_MAP_READ);
1284 ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", le_type, 1300 ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", le_type,
1285 EXTRACTOR_METAFORMAT_BINARY, mime_type, 1301 EXTRACTOR_METAFORMAT_BINARY, mime_type,
1286 (const char *) mi.data, mi.size); 1302 (const char *) mi.data, mi.size);
1287 gst_buffer_unmap (buf, &mi); 1303 gst_buffer_unmap (buf, &mi);
1288 } 1304 }
1289 }
1290 else if ((G_VALUE_TYPE (&val) == G_TYPE_UINT64) &&
1291 (tag_quark == duration_quark))
1292 {
1293 GstClockTime duration = (GstClockTime) g_value_get_uint64 (&val);
1294 if ((GST_CLOCK_TIME_IS_VALID (duration)) && (duration > 0))
1295 str = g_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (duration));
1296 }
1297 else
1298 str = gst_value_serialize (&val);
1299 break;
1300 }
1301 if (str != NULL)
1302 {
1303 /* Discoverer internally uses some tags to provide streaminfo;
1304 * ignore these tags to avoid duplicates.
1305 * This MIGHT be fixed in new GStreamer versions, but won't affect
1306 * this code (we simply won't get the tags that we think we should skip).
1307 */
1308 gboolean skip = FALSE;
1309 /* We have one tag-processing routine and use it for different
1310 * stream types. However, tags themselves don't know the type of the
1311 * stream they are attached to. We remember that before listing the
1312 * tags, and adjust LE type accordingly.
1313 */
1314 enum EXTRACTOR_MetaType le_type = kt->le_type;
1315 switch (kt->le_type)
1316 {
1317 case EXTRACTOR_METATYPE_LANGUAGE:
1318 switch (ps->st)
1319 {
1320 case STREAM_TYPE_AUDIO:
1321 skip = TRUE;
1322 break;
1323 case STREAM_TYPE_SUBTITLE:
1324 skip = TRUE;
1325 break;
1326 case STREAM_TYPE_VIDEO:
1327 le_type = EXTRACTOR_METATYPE_VIDEO_LANGUAGE;
1328 break;
1329 default:
1330 break;
1331 }
1332 break;
1333 case EXTRACTOR_METATYPE_BITRATE:
1334 switch (ps->st)
1335 {
1336 case STREAM_TYPE_AUDIO:
1337 skip = TRUE;
1338 break;
1339 case STREAM_TYPE_VIDEO:
1340 skip = TRUE;
1341 break;
1342 default:
1343 break;
1344 } 1305 }
1345 break; 1306 else if ((G_VALUE_TYPE (&val) == G_TYPE_UINT64) &&
1346 case EXTRACTOR_METATYPE_MAXIMUM_BITRATE: 1307 (tag_quark == duration_quark))
1347 switch (ps->st)
1348 { 1308 {
1349 case STREAM_TYPE_AUDIO: 1309 GstClockTime duration = (GstClockTime) g_value_get_uint64 (&val);
1350 skip = TRUE; 1310 if ((GST_CLOCK_TIME_IS_VALID (duration)) && (duration > 0))
1351 break; 1311 str = g_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (duration));
1352 case STREAM_TYPE_VIDEO:
1353 skip = TRUE;
1354 break;
1355 default:
1356 break;
1357 } 1312 }
1313 else
1314 str = gst_value_serialize (&val);
1358 break; 1315 break;
1359 case EXTRACTOR_METATYPE_NOMINAL_BITRATE: 1316 }
1360 switch (ps->st) 1317 if (str != NULL)
1318 {
1319 /* Discoverer internally uses some tags to provide streaminfo;
1320 * ignore these tags to avoid duplicates.
1321 * This MIGHT be fixed in new GStreamer versions, but won't affect
1322 * this code (we simply won't get the tags that we think we should skip).
1323 */
1324 gboolean skip = FALSE;
1325 /* We have one tag-processing routine and use it for different
1326 * stream types. However, tags themselves don't know the type of the
1327 * stream they are attached to. We remember that before listing the
1328 * tags, and adjust LE type accordingly.
1329 */
1330 enum EXTRACTOR_MetaType le_type = kt->le_type;
1331 switch (kt->le_type)
1361 { 1332 {
1362 case STREAM_TYPE_AUDIO: 1333 case EXTRACTOR_METATYPE_LANGUAGE:
1363 skip = TRUE; 1334 switch (ps->st)
1364 break; 1335 {
1365 case STREAM_TYPE_VIDEO: 1336 case STREAM_TYPE_AUDIO:
1366 skip = TRUE; 1337 skip = TRUE;
1338 break;
1339 case STREAM_TYPE_SUBTITLE:
1340 skip = TRUE;
1341 break;
1342 case STREAM_TYPE_VIDEO:
1343 le_type = EXTRACTOR_METATYPE_VIDEO_LANGUAGE;
1344 break;
1345 default:
1346 break;
1347 }
1367 break; 1348 break;
1368 default: 1349 case EXTRACTOR_METATYPE_BITRATE:
1350 switch (ps->st)
1351 {
1352 case STREAM_TYPE_AUDIO:
1353 skip = TRUE;
1354 break;
1355 case STREAM_TYPE_VIDEO:
1356 skip = TRUE;
1357 break;
1358 default:
1359 break;
1360 }
1369 break; 1361 break;
1370 } 1362 case EXTRACTOR_METATYPE_MAXIMUM_BITRATE:
1371 break; 1363 switch (ps->st)
1372 case EXTRACTOR_METATYPE_IMAGE_DIMENSIONS: 1364 {
1373 switch (ps->st) 1365 case STREAM_TYPE_AUDIO:
1374 { 1366 skip = TRUE;
1375 case STREAM_TYPE_VIDEO: 1367 break;
1376 le_type = EXTRACTOR_METATYPE_VIDEO_DIMENSIONS; 1368 case STREAM_TYPE_VIDEO:
1369 skip = TRUE;
1370 break;
1371 default:
1372 break;
1373 }
1377 break; 1374 break;
1378 default: 1375 case EXTRACTOR_METATYPE_NOMINAL_BITRATE:
1376 switch (ps->st)
1377 {
1378 case STREAM_TYPE_AUDIO:
1379 skip = TRUE;
1380 break;
1381 case STREAM_TYPE_VIDEO:
1382 skip = TRUE;
1383 break;
1384 default:
1385 break;
1386 }
1379 break; 1387 break;
1380 } 1388 case EXTRACTOR_METATYPE_IMAGE_DIMENSIONS:
1381 break; 1389 switch (ps->st)
1382 case EXTRACTOR_METATYPE_DURATION: 1390 {
1383 switch (ps->st) 1391 case STREAM_TYPE_VIDEO:
1384 { 1392 le_type = EXTRACTOR_METATYPE_VIDEO_DIMENSIONS;
1385 case STREAM_TYPE_VIDEO: 1393 break;
1386 le_type = EXTRACTOR_METATYPE_VIDEO_DURATION; 1394 default:
1395 break;
1396 }
1387 break; 1397 break;
1388 case STREAM_TYPE_AUDIO: 1398 case EXTRACTOR_METATYPE_DURATION:
1389 le_type = EXTRACTOR_METATYPE_AUDIO_DURATION; 1399 switch (ps->st)
1400 {
1401 case STREAM_TYPE_VIDEO:
1402 le_type = EXTRACTOR_METATYPE_VIDEO_DURATION;
1403 break;
1404 case STREAM_TYPE_AUDIO:
1405 le_type = EXTRACTOR_METATYPE_AUDIO_DURATION;
1406 break;
1407 case STREAM_TYPE_SUBTITLE:
1408 le_type = EXTRACTOR_METATYPE_SUBTITLE_DURATION;
1409 break;
1410 default:
1411 break;
1412 }
1390 break; 1413 break;
1391 case STREAM_TYPE_SUBTITLE: 1414 case EXTRACTOR_METATYPE_UNKNOWN:
1392 le_type = EXTRACTOR_METATYPE_SUBTITLE_DURATION; 1415 /* Convert to "key=value" form */
1416 {
1417 gchar *new_str;
1418 /* GST_TAG_EXTENDED_COMMENT is already in key=value form */
1419 if ((0 != strcmp (tag, "extended-comment")) || !strchr (str, '='))
1420 {
1421 new_str = g_strdup_printf ("%s=%s", tag, str);
1422 g_free (str);
1423 str = new_str;
1424 }
1425 }
1393 break; 1426 break;
1394 default: 1427 default:
1395 break; 1428 break;
1396 } 1429 }
1397 break; 1430 if (!skip)
1398 case EXTRACTOR_METATYPE_UNKNOWN: 1431 ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", le_type,
1399 /* Convert to "key=value" form */ 1432 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
1400 { 1433 (const char *) str, strlen (str) + 1);
1401 gchar *new_str;
1402 /* GST_TAG_EXTENDED_COMMENT is already in key=value form */
1403 if ((0 != strcmp (tag, "extended-comment")) || !strchr (str, '='))
1404 {
1405 new_str = g_strdup_printf ("%s=%s", tag, str);
1406 g_free (str);
1407 str = new_str;
1408 }
1409 }
1410 break;
1411 default:
1412 break;
1413 } 1434 }
1414 if (!skip)
1415 ps->time_to_leave = ps->ec->proc (ps->ec->cls, "gstreamer", le_type,
1416 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
1417 (const char *) str, strlen (str) + 1);
1418 }
1419 1435
1420 g_free (str); 1436 g_free (str);
1421 g_value_unset (&val); 1437 g_value_unset (&val);
1438 }
1422} 1439}
1423 1440
1424static void 1441static void