mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 23:18:52 +00:00
flacparse: add TOC support
Add support embedded cuesheets in flac files. Parsing METADATA_BLOCK_CUESHEET as TOC. https://bugzilla.gnome.org/show_bug.cgi?id=540891
This commit is contained in:
parent
a94d5d9f3b
commit
ffc204e6bd
2 changed files with 121 additions and 1 deletions
|
@ -295,6 +295,10 @@ gst_flac_parse_finalize (GObject * object)
|
||||||
gst_tag_list_free (flacparse->tags);
|
gst_tag_list_free (flacparse->tags);
|
||||||
flacparse->tags = NULL;
|
flacparse->tags = NULL;
|
||||||
}
|
}
|
||||||
|
if (flacparse->toc) {
|
||||||
|
gst_toc_unref (flacparse->toc);
|
||||||
|
flacparse->toc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
||||||
g_list_free (flacparse->headers);
|
g_list_free (flacparse->headers);
|
||||||
|
@ -346,6 +350,10 @@ gst_flac_parse_stop (GstBaseParse * parse)
|
||||||
gst_tag_list_free (flacparse->tags);
|
gst_tag_list_free (flacparse->tags);
|
||||||
flacparse->tags = NULL;
|
flacparse->tags = NULL;
|
||||||
}
|
}
|
||||||
|
if (flacparse->toc) {
|
||||||
|
gst_toc_unref (flacparse->toc);
|
||||||
|
flacparse->toc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
||||||
g_list_free (flacparse->headers);
|
g_list_free (flacparse->headers);
|
||||||
|
@ -969,6 +977,108 @@ gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstByteReader reader;
|
||||||
|
GstMapInfo map;
|
||||||
|
guint i, j;
|
||||||
|
guint8 n_tracks, track_num, index;
|
||||||
|
guint64 offset;
|
||||||
|
gint64 start, stop;
|
||||||
|
gchar *id;
|
||||||
|
gchar isrc[13];
|
||||||
|
GstTagList *tags;
|
||||||
|
GstToc *toc;
|
||||||
|
GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
|
||||||
|
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
gst_byte_reader_init (&reader, map.data, map.size);
|
||||||
|
|
||||||
|
toc = gst_toc_new ();
|
||||||
|
|
||||||
|
/* skip 4 bytes METADATA_BLOCK_HEADER */
|
||||||
|
/* http://flac.sourceforge.net/format.html#metadata_block_header */
|
||||||
|
if (!gst_byte_reader_skip (&reader, 4))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* skip 395 bytes from METADATA_BLOCK_CUESHEET */
|
||||||
|
/* http://flac.sourceforge.net/format.html#metadata_block_cuesheet */
|
||||||
|
if (!gst_byte_reader_skip (&reader, 395))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* CUESHEET_TRACK */
|
||||||
|
/* http://flac.sourceforge.net/format.html#cuesheet_track */
|
||||||
|
for (i = 0; i < n_tracks; i++) {
|
||||||
|
if (!gst_byte_reader_get_uint64_be (&reader, &offset))
|
||||||
|
goto error;
|
||||||
|
if (!gst_byte_reader_get_uint8 (&reader, &track_num))
|
||||||
|
goto error;
|
||||||
|
if (!gst_byte_reader_skip (&reader, 12))
|
||||||
|
goto error;
|
||||||
|
memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
|
||||||
|
/* skip 14 bytes from CUESHEET_TRACK */
|
||||||
|
if (!gst_byte_reader_skip (&reader, 14))
|
||||||
|
goto error;
|
||||||
|
if (!gst_byte_reader_get_uint8 (&reader, &index))
|
||||||
|
goto error;
|
||||||
|
/* add tracks in TOC */
|
||||||
|
/* lead-out tack has number 170 or 255 */
|
||||||
|
if (track_num != 170 && track_num != 255) {
|
||||||
|
prev_entry = cur_entry;
|
||||||
|
/* previous track stop time = current track start time */
|
||||||
|
if (prev_entry != NULL) {
|
||||||
|
gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
|
||||||
|
stop =
|
||||||
|
gst_util_uint64_scale_round (offset, GST_SECOND,
|
||||||
|
flacparse->samplerate);
|
||||||
|
gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
|
||||||
|
}
|
||||||
|
id = g_strdup_printf ("%08x", track_num);
|
||||||
|
cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
|
||||||
|
g_free (id);
|
||||||
|
start =
|
||||||
|
gst_util_uint64_scale_round (offset, GST_SECOND,
|
||||||
|
flacparse->samplerate);
|
||||||
|
gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
|
||||||
|
/* add ISRC as tag in track */
|
||||||
|
if (strlen (isrc) != 0) {
|
||||||
|
tags = gst_tag_list_new_empty ();
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
|
||||||
|
gst_toc_entry_set_tags (cur_entry, tags);
|
||||||
|
}
|
||||||
|
gst_toc_append_entry (toc, cur_entry);
|
||||||
|
/* CUESHEET_TRACK_INDEX */
|
||||||
|
/* http://flac.sourceforge.net/format.html#cuesheet_track_index */
|
||||||
|
for (j = 0; j < index; j++) {
|
||||||
|
if (!gst_byte_reader_skip (&reader, 12))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* set stop time in last track */
|
||||||
|
stop =
|
||||||
|
gst_util_uint64_scale_round (offset, GST_SECOND,
|
||||||
|
flacparse->samplerate);
|
||||||
|
gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send data as TOC */
|
||||||
|
if (!flacparse->toc)
|
||||||
|
flacparse->toc = toc;
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
GST_ERROR_OBJECT (flacparse, "Error reading data");
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
|
gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
@ -1391,13 +1501,16 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
|
||||||
if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
|
if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
|
case 5: /* CUESHEET */
|
||||||
|
if (!gst_flac_parse_handle_cuesheet (flacparse, sbuffer))
|
||||||
|
goto cleanup;
|
||||||
|
break;
|
||||||
case 6: /* PICTURE */
|
case 6: /* PICTURE */
|
||||||
if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
|
if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 1: /* PADDING */
|
case 1: /* PADDING */
|
||||||
case 2: /* APPLICATION */
|
case 2: /* APPLICATION */
|
||||||
case 5: /* CUESHEET */
|
|
||||||
default: /* RESERVED */
|
default: /* RESERVED */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1516,6 +1629,12 @@ gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
gst_event_new_tag ("GstParser", flacparse->tags));
|
gst_event_new_tag ("GstParser", flacparse->tags));
|
||||||
flacparse->tags = NULL;
|
flacparse->tags = NULL;
|
||||||
}
|
}
|
||||||
|
/* Push toc */
|
||||||
|
if (flacparse->toc) {
|
||||||
|
gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
|
||||||
|
gst_event_new_toc (flacparse->toc, FALSE));
|
||||||
|
flacparse->toc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
|
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct _GstFlacParse {
|
||||||
gboolean strategy_checked;
|
gboolean strategy_checked;
|
||||||
|
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
|
GstToc *toc;
|
||||||
|
|
||||||
GList *headers;
|
GList *headers;
|
||||||
GstBuffer *seektable;
|
GstBuffer *seektable;
|
||||||
|
|
Loading…
Reference in a new issue