wavenc: add tags & toc support

Write tags as LIST INFO chunk. Format the toc as cue + LIST adtl chunk. Remove
old #ifdef'ed code.
This commit is contained in:
Anton Belka 2013-04-12 16:02:44 +03:00 committed by Stefan Sauer
parent 1f0600ee6f
commit db29522a43
2 changed files with 154 additions and 308 deletions

View file

@ -44,6 +44,7 @@
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
#include <gst/riff/riff-media.h> #include <gst/riff/riff-media.h>
#include <gst/base/gstbytewriter.h>
GST_DEBUG_CATEGORY_STATIC (wavenc_debug); GST_DEBUG_CATEGORY_STATIC (wavenc_debug);
#define GST_CAT_DEFAULT wavenc_debug #define GST_CAT_DEFAULT wavenc_debug
@ -156,6 +157,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
#define gst_wavenc_parent_class parent_class #define gst_wavenc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstWavEnc, gst_wavenc, GST_TYPE_ELEMENT, G_DEFINE_TYPE_WITH_CODE (GstWavEnc, gst_wavenc, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL)
G_IMPLEMENT_INTERFACE (GST_TYPE_TOC_SETTER, NULL) G_IMPLEMENT_INTERFACE (GST_TYPE_TOC_SETTER, NULL)
); );
@ -209,7 +211,7 @@ gst_wavenc_init (GstWavEnc * wavenc)
#define WAV_HEADER_LEN 44 #define WAV_HEADER_LEN 44
static GstBuffer * static GstBuffer *
gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size) gst_wavenc_create_header_buf (GstWavEnc * wavenc)
{ {
struct wave_header wave; struct wave_header wave;
GstBuffer *buf; GstBuffer *buf;
@ -221,25 +223,24 @@ gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size)
header = map.data; header = map.data;
memset (header, 0, WAV_HEADER_LEN); memset (header, 0, WAV_HEADER_LEN);
wave.common.wChannels = wavenc->channels;
wave.common.wBitsPerSample = wavenc->width;
wave.common.dwSamplesPerSec = wavenc->rate;
/* Fill out our wav-header with some information */
memcpy (wave.riff.id, "RIFF", 4); memcpy (wave.riff.id, "RIFF", 4);
wave.riff.len = audio_data_size + WAV_HEADER_LEN - 8; wave.riff.len =
wavenc->meta_length + wavenc->audio_length + WAV_HEADER_LEN - 8;
memcpy (wave.riff.wav_id, "WAVE", 4); memcpy (wave.riff.wav_id, "WAVE", 4);
memcpy (wave.format.id, "fmt ", 4); memcpy (wave.format.id, "fmt ", 4);
wave.format.len = 16; wave.format.len = 16;
wave.common.wChannels = wavenc->channels;
wave.common.wBitsPerSample = wavenc->width;
wave.common.dwSamplesPerSec = wavenc->rate;
wave.common.wFormatTag = wavenc->format; wave.common.wFormatTag = wavenc->format;
wave.common.wBlockAlign = (wavenc->width / 8) * wave.common.wChannels; wave.common.wBlockAlign = (wavenc->width / 8) * wave.common.wChannels;
wave.common.dwAvgBytesPerSec = wave.common.dwAvgBytesPerSec =
wave.common.wBlockAlign * wave.common.dwSamplesPerSec; wave.common.wBlockAlign * wave.common.dwSamplesPerSec;
memcpy (wave.data.id, "data", 4); memcpy (wave.data.id, "data", 4);
wave.data.len = audio_data_size; wave.data.len = wavenc->audio_length;
memcpy (header, (char *) wave.riff.id, 4); memcpy (header, (char *) wave.riff.id, 4);
GST_WRITE_UINT32_LE (header + 4, wave.riff.len); GST_WRITE_UINT32_LE (header + 4, wave.riff.len);
@ -261,7 +262,7 @@ gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size)
} }
static GstFlowReturn static GstFlowReturn
gst_wavenc_push_header (GstWavEnc * wavenc, guint audio_data_size) gst_wavenc_push_header (GstWavEnc * wavenc)
{ {
GstFlowReturn ret; GstFlowReturn ret;
GstBuffer *outbuf; GstBuffer *outbuf;
@ -271,9 +272,10 @@ gst_wavenc_push_header (GstWavEnc * wavenc, guint audio_data_size)
gst_segment_init (&segment, GST_FORMAT_BYTES); gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_pad_push_event (wavenc->srcpad, gst_event_new_segment (&segment)); gst_pad_push_event (wavenc->srcpad, gst_event_new_segment (&segment));
GST_DEBUG_OBJECT (wavenc, "writing header with datasize=%u", audio_data_size); GST_DEBUG_OBJECT (wavenc, "writing header, meta_size=%u, audio_size=%u",
wavenc->meta_length, wavenc->audio_length);
outbuf = gst_wavenc_create_header_buf (wavenc, audio_data_size); outbuf = gst_wavenc_create_header_buf (wavenc);
GST_BUFFER_OFFSET (outbuf) = 0; GST_BUFFER_OFFSET (outbuf) = 0;
ret = gst_pad_push (wavenc->srcpad, outbuf); ret = gst_pad_push (wavenc->srcpad, outbuf);
@ -357,286 +359,104 @@ fail:
return FALSE; return FALSE;
} }
#if 0 static void
static struct _maps gst_wavparse_tags_foreach (const GstTagList * tags, const gchar * tag,
gpointer data)
{ {
const guint32 id; const struct
const gchar *name;
} maps[] = {
{ {
GST_RIFF_INFO_IARL, "Location"}, { guint32 fcc;
GST_RIFF_INFO_IART, "Artist"}, { const gchar *tag;
GST_RIFF_INFO_ICMS, "Commissioner"}, { } rifftags[] = {
GST_RIFF_INFO_ICMT, "Comment"}, { {
GST_RIFF_INFO_ICOP, "Copyright"}, { GST_RIFF_INFO_IARL, GST_TAG_LOCATION}, {
GST_RIFF_INFO_ICRD, "Creation Date"}, { GST_RIFF_INFO_IART, GST_TAG_ARTIST}, {
GST_RIFF_INFO_IENG, "Engineer"}, { GST_RIFF_INFO_ICMT, GST_TAG_COMMENT}, {
GST_RIFF_INFO_IGNR, "Genre"}, { GST_RIFF_INFO_ICOP, GST_TAG_COPYRIGHT}, {
GST_RIFF_INFO_IKEY, "Keywords"}, { GST_RIFF_INFO_ICRD, GST_TAG_DATE}, {
GST_RIFF_INFO_INAM, "Title"}, { GST_RIFF_INFO_IGNR, GST_TAG_GENRE}, {
GST_RIFF_INFO_IPRD, "Product"}, { GST_RIFF_INFO_IKEY, GST_TAG_KEYWORDS}, {
GST_RIFF_INFO_ISBJ, "Subject"}, { GST_RIFF_INFO_INAM, GST_TAG_TITLE}, {
GST_RIFF_INFO_ISFT, "Software"}, { GST_RIFF_INFO_IPRD, GST_TAG_ALBUM}, {
GST_RIFF_INFO_ITCH, "Technician"} GST_RIFF_INFO_ISBJ, GST_TAG_ALBUM_ARTIST}, {
}; GST_RIFF_INFO_ISFT, GST_TAG_ENCODER}, {
GST_RIFF_INFO_ISRC, GST_TAG_ISRC}, {
static guint32 0, NULL}
get_id_from_name (const char *name) };
{ gint n;
int i; gchar *str = NULL;
GstByteWriter *bw = data;
for (i = 0; i < G_N_ELEMENTS (maps); i++) { for (n = 0; rifftags[n].fcc != 0; n++) {
if (strcasecmp (maps[i].name, name) == 0) { if (!strcmp (rifftags[n].tag, tag)) {
return maps[i].id; if (rifftags[n].fcc == GST_RIFF_INFO_ICRD) {
} GDate *date;
} /* special case for the date tag */
if (gst_tag_list_get_date (tags, tag, &date)) {
return 0; str =
} g_strdup_printf ("%04d:%02d:%02d", g_date_get_year (date),
g_date_get_month (date), g_date_get_day (date));
static void g_date_free (date);
write_metadata (GstWavEnc * wavenc) }
{ } else {
GString *info_str; gst_tag_list_get_string (tags, tag, &str);
GList *props; }
int total = 4; if (str) {
gboolean need_to_write = FALSE; gst_byte_writer_put_uint32_le (bw, rifftags[n].fcc);
gst_byte_writer_put_uint32_le (bw, GST_ROUND_UP_2 (strlen (str)));
info_str = g_string_new ("LIST INFO"); gst_byte_writer_put_string (bw, str);
g_free (str);
for (props = wavenc->metadata->properties->properties; props; str = NULL;
props = props->next) { break;
GstPropsEntry *entry = props->data;
const char *name;
guint32 id;
name = gst_props_entry_get_name (entry);
id = get_id_from_name (name);
if (id != 0) {
const char *text;
char *tmp;
int len, req, i;
need_to_write = TRUE; /* We've got at least one entry */
gst_props_entry_get_string (entry, &text);
len = strlen (text) + 1; /* The length in the file includes the \0 */
tmp = g_strdup_printf ("%" GST_FOURCC_FORMAT "%d%s", GST_FOURCC_ARGS (id),
GUINT32_TO_LE (len), text);
g_string_append (info_str, tmp);
g_free (tmp);
/* Check that we end on an even boundary */
req = ((len + 8) + 1) & ~1;
for (i = 0; i < req - len; i++) {
g_string_append_printf (info_str, "%c", 0);
} }
total += req;
} }
} }
if (need_to_write) {
GstBuffer *buf;
/* Now we've got all the strings together, we can write our length in */
info_str->str[4] = GUINT32_TO_LE (total);
buf = gst_buffer_new ();
gst_buffer_set_data (buf, info_str->str, info_str->len);
gst_pad_push (wavenc->srcpad, GST_DATA (buf));
g_string_free (info_str, FALSE);
}
} }
static void static GstFlowReturn
write_cues (GstWavEnc * wavenc) gst_wavenc_write_tags (GstWavEnc * wavenc)
{ {
GString *cue_string, *point_string; const GstTagList *user_tags;
GstTagList *tags;
guint size;
GstBuffer *buf; GstBuffer *buf;
GList *cue_list, *c; GstByteWriter bw;
int num_cues, total = 4;
if (gst_props_get (wavenc->metadata->properties, g_return_val_if_fail (wavenc != NULL, GST_FLOW_OK);
"cues", &cue_list, NULL) == FALSE) {
/* No cues, move along please, nothing to see here */ user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (wavenc));
return; if ((!wavenc->tags) && (!user_tags)) {
GST_DEBUG_OBJECT (wavenc, "have no tags");
return GST_FLOW_OK;
} }
tags =
gst_tag_list_merge (user_tags, wavenc->tags,
gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (wavenc)));
/* Space for 'cue ', chunk size and number of cuepoints */ GST_DEBUG_OBJECT (wavenc, "writing tags");
cue_string = g_string_new ("cue ");
#define CUEPOINT_SIZE 24
point_string = g_string_sized_new (CUEPOINT_SIZE);
for (c = cue_list, num_cues = 0; c; c = c->next, num_cues++) { gst_byte_writer_init_with_size (&bw, 1024, FALSE);
GstCaps *cue_caps = c->data;
guint32 pos;
gst_props_get (cue_caps->properties, "position", &pos, NULL); /* add LIST INFO chunk */
gst_byte_writer_put_data (&bw, (const guint8 *) "LIST", 4);
gst_byte_writer_put_uint32_le (&bw, 0);
gst_byte_writer_put_data (&bw, (const guint8 *) "INFO", 4);
point_string->str[0] = GUINT32_TO_LE (num_cues + 1); /* add tags */
point_string->str[4] = GUINT32_TO_LE (0); gst_tag_list_foreach (tags, gst_wavparse_tags_foreach, &bw);
/* Fixme: There is probably a macro for this */
point_string->str[8] = 'd';
point_string->str[9] = 'a';
point_string->str[10] = 't';
point_string->str[11] = 'a';
point_string->str[12] = GUINT32_TO_LE (0);
point_string->str[16] = GUINT32_TO_LE (0);
point_string->str[20] = GUINT32_TO_LE (pos);
total += CUEPOINT_SIZE; /* sets real size of LIST INFO chunk */
} size = gst_byte_writer_get_pos (&bw);
gst_byte_writer_set_pos (&bw, 4);
gst_byte_writer_put_uint32_le (&bw, size - 8);
/* Set the length and chunk size */ gst_tag_list_unref (tags);
cue_string->str[4] = GUINT32_TO_LE (total);
cue_string->str[8] = GUINT32_TO_LE (num_cues);
/* Stick the cue points on the end */
g_string_append (cue_string, point_string->str);
g_string_free (point_string, TRUE);
buf = gst_buffer_new (); buf = gst_byte_writer_reset_and_get_buffer (&bw);
gst_buffer_set_data (buf, cue_string->str, cue_string->len); wavenc->meta_length += gst_buffer_get_size (buf);
return gst_pad_push (wavenc->srcpad, buf);
gst_pad_push (wavenc->srcpad, GST_DATA (buf));
g_string_free (cue_string, FALSE);
} }
static void
write_labels (GstWavEnc * wavenc)
{
GstBuffer *buf;
GString *info_str;
int total = 4;
GList *caps;
info_str = g_string_new ("LIST adtl");
if (gst_props_get (wavenc->metadata->properties, "ltxts", &caps, NULL)) {
GList *p;
int i;
for (p = caps, i = 1; p; p = p->next, i++) {
GstCaps *ltxt_caps = p->data;
GString *ltxt;
char *label = NULL;
int len, req, j;
gst_props_get (ltxt_caps->properties, "name", &label, NULL);
len = strlen (label);
#define LTXT_SIZE 28
ltxt = g_string_new ("ltxt ");
ltxt->str[8] = GUINT32_TO_LE (i); /* Identifier */
ltxt->str[12] = GUINT32_TO_LE (0); /* Sample Length */
ltxt->str[16] = GUINT32_TO_LE (0); /* FIXME: Don't save the purpose yet */
ltxt->str[20] = GUINT16_TO_LE (0); /* Country */
ltxt->str[22] = GUINT16_TO_LE (0); /* Language */
ltxt->str[24] = GUINT16_TO_LE (0); /* Dialect */
ltxt->str[26] = GUINT16_TO_LE (0); /* Code Page */
g_string_append (ltxt, label);
g_free (label);
len += LTXT_SIZE;
ltxt->str[4] = GUINT32_TO_LE (len);
/* Check that we end on an even boundary */
req = ((len + 8) + 1) & ~1;
for (j = 0; j < req - len; j++) {
g_string_append_printf (ltxt, "%c", 0);
}
total += req;
g_string_append (info_str, ltxt->str);
g_string_free (ltxt, TRUE);
}
}
if (gst_props_get (wavenc->metadata->properties, "labels", &caps, NULL)) {
GList *p;
int i;
for (p = caps, i = 1; p; p = p->next, i++) {
GstCaps *labl_caps = p->data;
GString *labl;
char *label = NULL;
int len, req, j;
gst_props_get (labl_caps->properties, "name", &label, NULL);
len = strlen (label);
#define LABL_SIZE 4
labl = g_string_new ("labl ");
labl->str[8] = GUINT32_TO_LE (i);
g_string_append (labl, label);
g_free (label);
len += LABL_SIZE;
labl->str[4] = GUINT32_TO_LE (len);
/* Check our size */
req = ((len + 8) + 1) & ~1;
for (j = 0; j < req - len; j++) {
g_string_append_printf (labl, "%c", 0);
}
total += req;
g_string_append (info_str, labl->str);
g_string_free (labl, TRUE);
}
}
if (gst_props_get (wavenc->metadata->properties, "notes", &caps, NULL)) {
GList *p;
int i;
for (p = caps, i = 1; p; p = p->next, i++) {
GstCaps *note_caps = p->data;
GString *note;
char *label = NULL;
int len, req, j;
gst_props_get (note_caps->properties, "name", &label, NULL);
len = strlen (label);
#define NOTE_SIZE 4
note = g_string_new ("note ");
note->str[8] = GUINT32_TO_LE (i);
g_string_append (note, label);
g_free (label);
len += NOTE_SIZE;
note->str[4] = GUINT32_TO_LE (len);
/* Size check */
req = ((len + 8) + 1) & ~1;
for (j = 0; j < req - len; j++) {
g_string_append_printf (note, "%c", 0);
}
total += req;
g_string_append (info_str, note->str);
g_string_free (note, TRUE);
}
}
info_str->str[4] = GUINT32_TO_LE (total);
buf = gst_buffer_new ();
gst_buffer_set_data (buf, info_str->str, info_str->len);
gst_pad_push (wavenc->srcpad, GST_DATA (buf));
g_string_free (info_str, FALSE);
}
#endif
static gboolean static gboolean
gst_wavenc_is_cue_id_unique (guint32 id, GList * list) gst_wavenc_is_cue_id_unique (guint32 id, GList * list)
{ {
@ -793,7 +613,7 @@ gst_wavenc_write_notes (guint8 ** data, GList * list)
return TRUE; return TRUE;
} }
static gboolean static GstFlowReturn
gst_wavenc_write_toc (GstWavEnc * wavenc) gst_wavenc_write_toc (GstWavEnc * wavenc)
{ {
GList *list; GList *list;
@ -804,18 +624,21 @@ gst_wavenc_write_toc (GstWavEnc * wavenc)
guint8 *data; guint8 *data;
guint32 ncues, size, cues_size, labls_size, notes_size; guint32 ncues, size, cues_size, labls_size, notes_size;
if (!wavenc->toc) {
GST_DEBUG_OBJECT (wavenc, "have no toc, checking toc_setter");
wavenc->toc = gst_toc_setter_get_toc (GST_TOC_SETTER (wavenc));
}
if (!wavenc->toc) {
GST_WARNING_OBJECT (wavenc, "have no toc");
return GST_FLOW_OK;
}
toc = gst_toc_ref (wavenc->toc);
size = 0; size = 0;
cues_size = 0; cues_size = 0;
labls_size = 0; labls_size = 0;
notes_size = 0; notes_size = 0;
if (wavenc->toc) {
toc = gst_toc_ref (wavenc->toc);
} else {
GST_WARNING_OBJECT (wavenc, "TOC not found");
return FALSE;
}
/* check if the TOC entries is valid */ /* check if the TOC entries is valid */
list = gst_toc_get_entries (toc); list = gst_toc_get_entries (toc);
entry = list->data; entry = list->data;
@ -935,10 +758,9 @@ gst_wavenc_write_toc (GstWavEnc * wavenc)
g_list_free_full (wavenc->notes, g_free); g_list_free_full (wavenc->notes, g_free);
gst_buffer_unmap (buf, &map); gst_buffer_unmap (buf, &map);
wavenc->meta_length += gst_buffer_get_size (buf);
gst_pad_push (wavenc->srcpad, buf); return gst_pad_push (wavenc->srcpad, buf);
return TRUE;
} }
static gboolean static gboolean
@ -946,6 +768,7 @@ gst_wavenc_event (GstPad * pad, GstObject * parent, GstEvent * event)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstWavEnc *wavenc; GstWavEnc *wavenc;
GstTagList *tags;
GstToc *toc; GstToc *toc;
wavenc = GST_WAVENC (parent); wavenc = GST_WAVENC (parent);
@ -962,26 +785,24 @@ gst_wavenc_event (GstPad * pad, GstObject * parent, GstEvent * event)
gst_event_unref (event); gst_event_unref (event);
break; break;
} }
case GST_EVENT_EOS:{ case GST_EVENT_EOS:
{
GstFlowReturn flow;
GST_DEBUG_OBJECT (wavenc, "got EOS"); GST_DEBUG_OBJECT (wavenc, "got EOS");
if (!wavenc->toc) {
GST_DEBUG_OBJECT (wavenc, "have no toc, checking toc_setter"); flow = gst_wavenc_write_toc (wavenc);
wavenc->toc = gst_toc_setter_get_toc (GST_TOC_SETTER (wavenc)); if (flow != GST_FLOW_OK) {
GST_WARNING_OBJECT (wavenc, "error pushing toc: %s",
gst_flow_get_name (flow));
} }
if (wavenc->toc) { flow = gst_wavenc_write_tags (wavenc);
GST_DEBUG_OBJECT (wavenc, "have toc"); if (flow != GST_FLOW_OK) {
gst_wavenc_write_toc (wavenc); GST_WARNING_OBJECT (wavenc, "error pushing tags: %s",
gst_flow_get_name (flow));
} }
#if 0
/* Write our metadata if we have any */
if (wavenc->metadata) {
write_metadata (wavenc);
write_cues (wavenc);
write_labels (wavenc);
}
#endif
/* write header with correct length values */ /* write header with correct length values */
gst_wavenc_push_header (wavenc, wavenc->length); gst_wavenc_push_header (wavenc);
/* we're done with this file */ /* we're done with this file */
wavenc->finished_properly = TRUE; wavenc->finished_properly = TRUE;
@ -1008,6 +829,19 @@ gst_wavenc_event (GstPad * pad, GstObject * parent, GstEvent * event)
} }
res = gst_pad_event_default (pad, parent, event); res = gst_pad_event_default (pad, parent, event);
break; break;
case GST_EVENT_TAG:
gst_event_parse_tag (event, &tags);
if (tags) {
if (wavenc->tags != tags) {
if (wavenc->tags)
gst_tag_list_unref (wavenc->tags);
wavenc->tags = tags;
} else {
gst_toc_unref (tags);
}
}
res = gst_pad_event_default (pad, parent, event);
break;
default: default:
res = gst_pad_event_default (pad, parent, event); res = gst_pad_event_default (pad, parent, event);
break; break;
@ -1024,17 +858,18 @@ gst_wavenc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
g_return_val_if_fail (wavenc->channels > 0, GST_FLOW_FLUSHING); g_return_val_if_fail (wavenc->channels > 0, GST_FLOW_FLUSHING);
if (!wavenc->sent_header) { if (G_UNLIKELY (!wavenc->sent_header)) {
/* use bogus size initially, we'll write the real
* header when we get EOS and know the exact length */
flow = gst_wavenc_push_header (wavenc, 0x7FFF0000);
/* starting a file, means we have to finish it properly */ /* starting a file, means we have to finish it properly */
wavenc->finished_properly = FALSE; wavenc->finished_properly = FALSE;
if (flow != GST_FLOW_OK) /* use bogus size initially, we'll write the real
* header when we get EOS and know the exact length */
flow = gst_wavenc_push_header (wavenc);
if (flow != GST_FLOW_OK) {
GST_WARNING_OBJECT (wavenc, "error pushing header: %s",
gst_flow_get_name (flow));
return flow; return flow;
}
GST_DEBUG_OBJECT (wavenc, "wrote dummy header"); GST_DEBUG_OBJECT (wavenc, "wrote dummy header");
wavenc->sent_header = TRUE; wavenc->sent_header = TRUE;
} }
@ -1045,10 +880,10 @@ gst_wavenc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
buf = gst_buffer_make_writable (buf); buf = gst_buffer_make_writable (buf);
GST_BUFFER_OFFSET (buf) = WAV_HEADER_LEN + wavenc->length; GST_BUFFER_OFFSET (buf) = WAV_HEADER_LEN + wavenc->audio_length;
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
wavenc->length += gst_buffer_get_size (buf); wavenc->audio_length += gst_buffer_get_size (buf);
flow = gst_pad_push (wavenc->srcpad, buf); flow = gst_pad_push (wavenc->srcpad, buf);
@ -1067,7 +902,8 @@ gst_wavenc_change_state (GstElement * element, GstStateChange transition)
wavenc->channels = 0; wavenc->channels = 0;
wavenc->width = 0; wavenc->width = 0;
wavenc->rate = 0; wavenc->rate = 0;
wavenc->length = 0; wavenc->audio_length = 0;
wavenc->meta_length = 0;
wavenc->sent_header = FALSE; wavenc->sent_header = FALSE;
/* its true because we haven't writen anything */ /* its true because we haven't writen anything */
wavenc->finished_properly = TRUE; wavenc->finished_properly = TRUE;
@ -1090,11 +926,17 @@ gst_wavenc_change_state (GstElement * element, GstStateChange transition)
} }
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
GST_DEBUG_OBJECT (wavenc, "tags: %p", wavenc->tags);
if (wavenc->tags) {
gst_tag_list_unref (wavenc->tags);
wavenc->tags = NULL;
}
GST_DEBUG_OBJECT (wavenc, "toc: %p", wavenc->toc); GST_DEBUG_OBJECT (wavenc, "toc: %p", wavenc->toc);
if (wavenc->toc) { if (wavenc->toc) {
gst_toc_unref (wavenc->toc); gst_toc_unref (wavenc->toc);
wavenc->toc = NULL; wavenc->toc = NULL;
} }
gst_tag_setter_reset_tags (GST_TAG_SETTER (wavenc));
gst_toc_setter_reset (GST_TOC_SETTER (wavenc)); gst_toc_setter_reset (GST_TOC_SETTER (wavenc));
break; break;
default: default:

View file

@ -46,6 +46,7 @@ struct _GstWavEnc {
GstPad *sinkpad; GstPad *sinkpad;
GstPad *srcpad; GstPad *srcpad;
GstTagList *tags;
GstToc *toc; GstToc *toc;
GList *cues; GList *cues;
GList *labls; GList *labls;
@ -56,7 +57,10 @@ struct _GstWavEnc {
guint width; guint width;
guint rate; guint rate;
guint channels; guint channels;
guint32 length;
/* data sizes */
guint32 audio_length;
guint32 meta_length;
gboolean sent_header; gboolean sent_header;
gboolean finished_properly; gboolean finished_properly;