matroskademux: Matroska tag TargetType support

* Reads TargetType and TargetTypeValue from a Tag.
* After Tag is completely read, processes taglist, substituting some of the
tags depending on target type value and the presence of video/subtitle streams.
* Supports reading two new simpletags - PART_NUMBER and TOTAL_PARTS

Depends on #682448
Fixes #682524
This commit is contained in:
Руслан Ижбулатов 2012-08-23 15:07:22 +04:00 committed by Sebastian Dröge
parent b75628f041
commit 71fd688ef0
2 changed files with 176 additions and 5 deletions

View file

@ -410,6 +410,8 @@
#define GST_MATROSKA_TAG_ID_COMPOSER "COMPOSER"
#define GST_MATROSKA_TAG_ID_LEAD_PERFORMER "LEAD_PERFOMER"
#define GST_MATROSKA_TAG_ID_GENRE "GENRE"
#define GST_MATROSKA_TAG_ID_TOTAL_PARTS "TOTAL_PARTS"
#define GST_MATROSKA_TAG_ID_PART_NUMBER "PART_NUMBER"
/*
* TODO: add this tag & mappings

View file

@ -60,6 +60,15 @@ GST_DEBUG_CATEGORY (matroskareadcommon_debug);
#define GST_MATROSKA_TOC_UID_EDITION "edition"
#define GST_MATROSKA_TOC_UID_EMPTY "empty"
typedef struct
{
GstTagList *result;
guint64 target_type_value;
gchar *target_type;
gboolean audio_only;
} TargetTypeContext;
static gboolean
gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
gpointer * data_out, gsize * size_out,
@ -764,14 +773,19 @@ gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
static GstFlowReturn
gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
GArray * track_targets)
GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
{
GstFlowReturn ret = GST_FLOW_OK;
guint32 id;
guint64 uid;
guint64 tmp;
gchar *str;
DEBUG_ELEMENT_START (common, ebml, "TagTargets");
*target_type_value = 50;
*target_type = NULL;
if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
return ret;
@ -797,6 +811,19 @@ gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
g_array_append_val (track_targets, uid);
break;
case GST_MATROSKA_ID_TARGETTYPEVALUE:
if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
*target_type_value = tmp;
break;
case GST_MATROSKA_ID_TARGETTYPE:
if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
if (*target_type != NULL)
g_free (*target_type);
*target_type = str;
}
break;
default:
ret =
gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
@ -1777,7 +1804,9 @@ gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}
};
GstFlowReturn ret;
guint32 id;
@ -1873,6 +1902,137 @@ gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
return ret;
}
static void
gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
gint * a, gint * v, gint * s)
{
gint i;
gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
for (i = 0; i < common->src->len; i++) {
GstMatroskaTrackContext *stream;
stream = g_ptr_array_index (common->src, i);
if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
video_streams += 1;
else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
audio_streams += 1;
else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
subtitle_streams += 1;
}
*v = video_streams;
*a = audio_streams;
*v = subtitle_streams;
}
static void
gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
const gchar * tag, gpointer user_data)
{
guint vallen;
guint i;
TargetTypeContext *ctx = (TargetTypeContext *) user_data;
vallen = gst_tag_list_get_tag_size (list, tag);
if (vallen == 0)
return;
for (i = 0; i < vallen; i++) {
GValue val = { 0 };
const GValue *val_ref;
val_ref = gst_tag_list_get_value_index (list, tag, i);
if (val_ref == NULL)
continue;
g_value_init (&val, G_VALUE_TYPE (val_ref));
g_value_copy (val_ref, &val);
/* TODO: use the optional ctx->target_type somehow */
if (strcmp (tag, GST_TAG_TITLE) == 0) {
if (ctx->target_type_value >= 70 && !ctx->audio_only) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_SHOW_NAME, &val);
continue;
} else if (ctx->target_type_value >= 50) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM, &val);
continue;
}
} else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
if (ctx->target_type_value >= 70 && !ctx->audio_only) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_SHOW_SORTNAME, &val);
continue;
} else if (ctx->target_type_value >= 50) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM_SORTNAME, &val);
continue;
}
} else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
if (ctx->target_type_value >= 50) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM_ARTIST, &val);
continue;
}
} else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
if (ctx->target_type_value >= 50) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM_ARTIST_SORTNAME, &val);
continue;
}
} else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
if (ctx->target_type_value >= 60) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM_VOLUME_COUNT, &val);
continue;
}
} else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
if (ctx->target_type_value >= 60 && !ctx->audio_only) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_SHOW_SEASON_NUMBER, &val);
continue;
} else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_SHOW_EPISODE_NUMBER, &val);
continue;
} else if (ctx->target_type_value >= 50) {
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
GST_TAG_ALBUM_VOLUME_NUMBER, &val);
continue;
}
}
gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, &val);
g_value_unset (&val);
}
}
static GstTagList *
gst_matroska_read_common_apply_target_type (GstMatroskaReadCommon * common,
GstTagList * taglist, guint64 target_type_value, gchar * target_type)
{
TargetTypeContext ctx;
gint a = 0;
gint v = 0;
gint s = 0;
gst_matroska_read_common_count_streams (common, &a, &v, &s);
ctx.audio_only = (a > 0 && v == 0 && s == 0);
ctx.result = gst_tag_list_new_empty ();
ctx.target_type_value = target_type_value;
ctx.target_type = target_type;
gst_tag_list_foreach (taglist,
gst_matroska_read_common_apply_target_type_foreach, &ctx);
gst_tag_list_unref (taglist);
return ctx.result;
}
static GstFlowReturn
gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
GstEbmlRead * ebml, GstTagList ** p_taglist)
@ -1882,6 +2042,8 @@ gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
GArray *chapter_targets, *edition_targets, *track_targets;
GstTagList *taglist;
GList *cur;
guint64 target_type_value;
gchar *target_type;
DEBUG_ELEMENT_START (common, ebml, "Tag");
@ -1894,6 +2056,7 @@ gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
chapter_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
track_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
taglist = gst_tag_list_new_empty ();
target_type = NULL;
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
/* read all sub-entries */
@ -1908,9 +2071,11 @@ gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
break;
case GST_MATROSKA_ID_TARGETS:
ret =
gst_matroska_read_common_parse_metadata_targets (common, ebml,
edition_targets, chapter_targets, track_targets);
g_free (target_type);
target_type = NULL;
ret = gst_matroska_read_common_parse_metadata_targets (common, ebml,
edition_targets, chapter_targets, track_targets,
&target_type_value, &target_type);
break;
default:
@ -1921,6 +2086,10 @@ gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
taglist = gst_matroska_read_common_apply_target_type (common, taglist,
target_type_value, target_type);
g_free (target_type);
/* if tag is chapter/edition specific - try to find that entry */
if (G_UNLIKELY (chapter_targets->len > 0 || edition_targets->len > 0 ||
track_targets->len > 0)) {