[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