2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 //#define debug(format,args...) g_print(format,##args)
24 #define debug(format,args...)
27 GstRiff *gst_riff_new(GstRiffCallback function, gpointer data) {
30 riff = (GstRiff *)g_malloc(sizeof(GstRiff));
31 g_return_val_if_fail(riff != NULL, NULL);
38 riff->new_tag_found = function;
39 riff->callback_data = data;
40 riff->incomplete_chunk = NULL;
41 riff->dataleft = NULL;
46 gint gst_riff_next_buffer(GstRiff *riff,GstBuffer *buf,gulong off) {
50 g_return_val_if_fail(riff != NULL, GST_RIFF_EINVAL);
51 g_return_val_if_fail(buf != NULL, GST_RIFF_EINVAL);
52 g_return_val_if_fail(GST_BUFFER_DATA(buf) != NULL, GST_RIFF_EINVAL);
54 size = GST_BUFFER_SIZE(buf);
57 debug("offset new buffer 0x%08lx size 0x%08x\n", off, GST_BUFFER_SIZE(buf));
62 debug("recovering left data\n");
63 newsize = riff->dataleft_size + size;
64 riff->dataleft = g_realloc(riff->dataleft, newsize);
65 memcpy(riff->dataleft+riff->dataleft_size, GST_BUFFER_DATA(buf), size);
66 gst_buffer_unref(buf);
68 buf = gst_buffer_new();
69 GST_BUFFER_DATA(buf) = riff->dataleft;
70 GST_BUFFER_SIZE(buf) = newsize;
71 off -= riff->dataleft_size;
72 //last -= riff->dataleft_size;
73 riff->dataleft = NULL;
77 gulong *words = (gulong *)GST_BUFFER_DATA(buf);
79 // don't even try to parse the head if it's not there FIXME
81 riff->state = GST_RIFF_ENOTRIFF;
85 //g_print("testing is 0x%08lx '%s'\n",words[0],gst_riff_id_to_fourcc(words[0]));
86 /* verify this is a valid RIFF file, first of all */
87 if (words[0] != GST_RIFF_TAG_RIFF) {
88 riff->state = GST_RIFF_ENOTRIFF;
91 riff->form = words[2];
92 //g_print("form is 0x%08lx '%s'\n",words[2],gst_riff_id_to_fourcc(words[2]));
93 riff->nextlikely = 12; /* skip 'RIFF', length, and form */
95 riff->incomplete_chunk = NULL;
98 // if we have an incomplete chunk from the previous buffer
99 if (riff->incomplete_chunk) {
101 debug("have incomplete chunk %08x filled\n", riff->incomplete_chunk_size);
102 leftover = riff->incomplete_chunk->size - riff->incomplete_chunk_size;
103 if (leftover <= size) {
104 debug("we can fill it from %08x with %08x bytes = %08x\n", riff->incomplete_chunk_size, leftover, riff->incomplete_chunk_size+leftover);
105 memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), leftover);
107 if (riff->new_tag_found) {
108 riff->new_tag_found(riff->incomplete_chunk, riff->callback_data);
110 g_free(riff->incomplete_chunk->data);
111 g_free(riff->incomplete_chunk);
112 riff->incomplete_chunk = NULL;
115 debug("we cannot fill it %08x >= %08lx\n", leftover, size);
116 memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), size);
117 riff->incomplete_chunk_size += size;
122 if ((riff->nextlikely+12) > last) {
123 guint left = last - riff->nextlikely;
124 debug("not enough data next 0x%08x last 0x%08lx %08x %08x\n",riff->nextlikely, last, left, off);
126 riff->dataleft = g_malloc(left);
127 riff->dataleft_size = left;
128 memcpy(riff->dataleft, GST_BUFFER_DATA(buf)+size-left, left);
133 debug("next 0x%08x last 0x%08lx offset %08x\n",riff->nextlikely, last, off);
134 /* loop while the next likely chunk header is in this buffer */
135 while ((riff->nextlikely+12) <= last) {
136 gulong *words = (gulong *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely - off );
138 // loop over all of the chunks to check which one is finished
139 while (riff->chunks) {
140 chunk = g_list_nth_data(riff->chunks, 0);
142 debug("next 0x%08x offset 0x%08lx size 0x%08x\n",riff->nextlikely, chunk->offset, chunk->size);
143 if (riff->nextlikely >= chunk->offset+chunk->size) {
144 //g_print("found END LIST\n");
145 // we have the end of the chunk on the stack, remove it
146 riff->chunks = g_list_remove(riff->chunks, chunk);
151 debug("next likely chunk is at offset 0x%08x\n",riff->nextlikely);
153 chunk = (GstRiffChunk *)g_malloc(sizeof(GstRiffChunk));
154 g_return_val_if_fail(chunk != NULL, GST_RIFF_ENOMEM);
156 chunk->offset = riff->nextlikely+8; /* point to the actual data */
157 chunk->id = words[0];
158 chunk->size = words[1];
159 chunk->data = (gchar *)(words+2);
160 // we need word alignment
161 //if (chunk->size & 0x01) chunk->size++;
162 chunk->form = words[2]; /* fill in the form, might not be valid */
165 if (chunk->id == GST_RIFF_TAG_LIST) {
166 //g_print("found LIST %s\n", gst_riff_id_to_fourcc(chunk->form));
167 riff->nextlikely += 12;
168 // we push the list chunk on our 'stack'
169 riff->chunks = g_list_prepend(riff->chunks,chunk);
170 // send the buffer to the listener if we have received a function
171 if (riff->new_tag_found) {
172 riff->new_tag_found(chunk, riff->callback_data);
177 debug("chunk id offset %08x is 0x%08lx '%s' and is 0x%08lx long\n",riff->nextlikely, words[0],
178 gst_riff_id_to_fourcc(words[0]),words[1]);
180 riff->nextlikely += 8 + chunk->size; /* doesn't include hdr */
181 // if this buffer is incomplete
182 if (riff->nextlikely > last) {
183 guint left = size - (riff->nextlikely - chunk->size - off);
185 //g_print("make incomplete buffer %08x\n", left);
186 chunk->data = g_malloc(chunk->size);
187 memcpy(chunk->data, (gchar *)(words+2), left);
188 riff->incomplete_chunk = chunk;
189 riff->incomplete_chunk_size = left;
192 // send the buffer to the listener if we have received a function
193 if (riff->new_tag_found) {
194 riff->new_tag_found(chunk, riff->callback_data);
199 //riff->chunks = g_list_prepend(riff->chunks,chunk);
207 gulong gst_riff_fourcc_to_id(gchar *fourcc) {
208 g_return_val_if_fail(fourcc != NULL, 0);
210 return (fourcc[0] << 0) | (fourcc[1] << 8) |
211 (fourcc[2] << 16) | (fourcc[3] << 24);
214 gchar *gst_riff_id_to_fourcc(gulong id) {
215 gchar *fourcc = (gchar *)g_malloc(5);
217 g_return_val_if_fail(fourcc != NULL, NULL);
219 fourcc[0] = (id >> 0) & 0xff;
220 fourcc[1] = (id >> 8) & 0xff;
221 fourcc[2] = (id >> 16) & 0xff;
222 fourcc[3] = (id >> 24) & 0xff;