[xiph-cvs] cvs commit: vorbis-tools/vorbiscomment vcedit.c vcedit.h
Michael Smith
msmith at xiph.org
Sat Aug 11 07:59:08 PDT 2001
msmith 01/08/11 07:59:08
Modified: vorbiscomment vcedit.c vcedit.h
Log:
Complete rewrite of the core rewrite function so that it works in complex
edge cases (it should, for example, work for arbitrarily large comment headers
AND for files processed by vcut).
Not extensively tested, but works on normal (i.e. non-corrupt) files,
including vcut processed ones (which it previously didn't).
Revision Changes Path
1.11 +106 -54 vorbis-tools/vorbiscomment/vcedit.c
Index: vcedit.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/vorbiscomment/vcedit.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- vcedit.c 2001/03/04 06:01:27 1.10
+++ vcedit.c 2001/08/11 14:59:07 1.11
@@ -6,7 +6,7 @@
*
* Comment editing backend, suitable for use by nice frontend interfaces.
*
- * last modified: $Id: vcedit.c,v 1.10 2001/03/04 06:01:27 msmith Exp $
+ * last modified: $Id: vcedit.c,v 1.11 2001/08/11 14:59:07 msmith Exp $
*/
#include <stdio.h>
@@ -68,6 +68,53 @@
}
}
+static int _blocksize(vcedit_state *s, ogg_packet *p)
+{
+ int this = vorbis_packet_blocksize(&s->vi, p);
+ int ret = (this + s->prevW)/4;
+
+ if(!s->prevW)
+ {
+ s->prevW = this;
+ return 0;
+ }
+
+ s->prevW = this;
+ return ret;
+}
+
+static int _fetch_next_packet(vcedit_state *s, ogg_packet *p)
+{
+ int result;
+ ogg_page og;
+ char *buffer;
+ int bytes;
+
+ if(p)
+ result = ogg_stream_packetout(s->os, p);
+ else
+ result = ogg_stream_packetpeek(s->os, NULL);
+
+ if(result > 0)
+ return 1;
+ else
+ {
+ while(ogg_sync_pageout(s->oy, &og) <= 0)
+ {
+ buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
+ bytes = s->read(buffer,1, CHUNKSIZE, s->in);
+ ogg_sync_wrote(s->oy, bytes);
+ if(bytes == 0)
+ return 0;
+ else if(bytes < CHUNKSIZE)
+ s->eof=1;
+ }
+
+ ogg_stream_pagein(s->os, &og);
+ return _fetch_next_packet(s, p);
+ }
+}
+
int vcedit_open(vcedit_state *state, FILE *in)
{
return vcedit_open_callbacks(state, (void *)in,
@@ -85,8 +132,6 @@
ogg_packet header_comments;
ogg_packet header_codebooks;
ogg_page og;
- vorbis_info vi;
-
state->in = in;
state->read = read_func;
@@ -114,7 +159,7 @@
state->os = malloc(sizeof(ogg_stream_state));
ogg_stream_init(state->os, state->serial);
- vorbis_info_init(&vi);
+ vorbis_info_init(&state->vi);
state->vc = malloc(sizeof(vorbis_comment));
vorbis_comment_init(state->vc);
@@ -131,7 +176,7 @@
goto err;
}
- if(vorbis_synthesis_headerin(&vi, state->vc, &header_main) < 0)
+ if(vorbis_synthesis_headerin(&state->vi, state->vc, &header_main) < 0)
{
state->lasterror = "Ogg bitstream does not contain vorbis data.";
goto err;
@@ -159,7 +204,7 @@
state->lasterror = "Corrupt secondary header.";
goto err;
}
- vorbis_synthesis_headerin(&vi, state->vc, header);
+ vorbis_synthesis_headerin(&state->vi, state->vc, header);
if(i==1)
{
state->booklen = header->bytes;
@@ -184,7 +229,6 @@
}
/* Headers are done! */
- vorbis_info_clear(&vi);
return 0;
err:
@@ -199,11 +243,12 @@
ogg_packet header_comments;
ogg_packet header_codebooks;
- ogg_page ogout, ogin;
+ ogg_page ogout;
ogg_packet op;
+ ogg_int64_t granpos = 0;
int result;
char *buffer;
- int bytes, eosin=0, eosout=0;
+ int bytes, eosin=0;
header_main.bytes = state->mainlen;
header_main.packet = state->mainbuf;
@@ -235,60 +280,67 @@
goto cleanup;
}
- while(!eosout)
+ while(_fetch_next_packet(state, &op))
{
- while(!eosout)
+ int size;
+ size = _blocksize(state, &op);
+ granpos += size;
+
+ if(state->eof && ogg_stream_packetpeek(state->os, NULL) <= 0)
+ op.e_o_s = 1;
+
+ if(op.granulepos == -1)
{
- result = ogg_sync_pageout(state->oy, &ogin);
- if(result==0) break; /* Need more data... */
- else if(result ==-1)
- continue;
- else
+ op.granulepos = granpos;
+ ogg_stream_packetin(&streamout, &op);
+ }
+ else /* granulepos is set, validly. Use it, and force a flush to
+ account for shortened blocks (vcut) when appropriate */
+ {
+ if(granpos > op.granulepos)
{
- ogg_stream_pagein(state->os, &ogin);
-
- while(1)
+ granpos = op.granulepos;
+ ogg_stream_packetin(&streamout, &op);
+ if(ogg_stream_flush(&streamout, &ogout))
{
- result = ogg_stream_packetout(state->os, &op);
- if(result==0)break;
- else if(result==-1)
- continue;
- else
- {
- ogg_stream_packetin(&streamout, &op);
-
- while(!eosout)
- {
- int result=ogg_stream_pageout(&streamout, &ogout);
- if(result==0)break;
-
- if(state->write(ogout.header,1,ogout.header_len,
- out) != (size_t) ogout.header_len)
- goto cleanup;
- if(state->write(ogout.body,1,ogout.body_len,
- out) != (size_t) ogout.body_len)
- goto cleanup;
-
- if(ogg_page_eos(&ogout)) eosout=1;
- }
- }
+ if(state->write(ogout.header,1,ogout.header_len,
+ out) != (size_t) ogout.header_len)
+ goto cleanup;
+ if(state->write(ogout.body,1,ogout.body_len,
+ out) != (size_t) ogout.body_len)
+ goto cleanup;
}
- if(ogg_page_eos(&ogin)) eosin = 1;
}
- }
- if(!eosin)
- {
- buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
- bytes = state->read(buffer,1, CHUNKSIZE, state->in);
- ogg_sync_wrote(state->oy, bytes);
- if(bytes == 0)
+ else
{
- eosin = 1;
- break;
+ ogg_stream_packetin(&streamout, &op);
+ if(ogg_stream_pageout(&streamout, &ogout))
+ {
+ if(state->write(ogout.header,1,ogout.header_len,
+ out) != (size_t) ogout.header_len)
+ goto cleanup;
+ if(state->write(ogout.body,1,ogout.body_len,
+ out) != (size_t) ogout.body_len)
+ goto cleanup;
+ }
}
- }
+ }
}
+ while(ogg_stream_flush(&streamout, &ogout))
+ {
+ if(state->write(ogout.header,1,ogout.header_len,
+ out) != (size_t) ogout.header_len)
+ goto cleanup;
+ if(state->write(ogout.body,1,ogout.body_len,
+ out) != (size_t) ogout.body_len)
+ goto cleanup;
+ }
+
+ /* FIXME: freeing this here probably leaks memory */
+ /* Done with this, now */
+ vorbis_info_clear(&state->vi);
+
eosin=0; /* clear it, because not all paths to here do */
while(!eosin) /* We reached eos, not eof */
{
@@ -331,7 +383,7 @@
free(state->bookbuf);
vcedit_clear_internals(state);
- if(!(eosin && eosout))
+ if(!eosin)
{
state->lasterror =
"Error writing stream to output. "
1.6 +3 -0 vorbis-tools/vorbiscomment/vcedit.h
Index: vcedit.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/vorbiscomment/vcedit.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- vcedit.h 2001/03/04 06:01:27 1.5
+++ vcedit.h 2001/08/11 14:59:08 1.6
@@ -27,6 +27,7 @@
ogg_stream_state *os;
vorbis_comment *vc;
+ vorbis_info vi;
vcedit_read_func read;
vcedit_write_func write;
@@ -38,6 +39,8 @@
int mainlen;
int booklen;
char *lasterror;
+ int prevW;
+ int eof;
} vcedit_state;
extern vcedit_state * vcedit_new_state(void);
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list