[xiph-commits] r3557 - liboggz/trunk/src/tools/oggz-chop
conrad at svn.annodex.net
conrad at svn.annodex.net
Mon Apr 14 05:33:52 PDT 2008
Author: conrad
Date: 2008-04-14 05:33:51 -0700 (Mon, 14 Apr 2008)
New Revision: 3557
Modified:
liboggz/trunk/src/tools/oggz-chop/oggz-chop.c
Log:
oggz-chop: when updating the page accumulator, don't throw away earlier pages that may contain
segments of packets in the next group of pictures. This should fix a bug (reported by Michael
Dale) where the keyframe required to decode from the chop point was sometimes not present in
the chopped file.
Modified: liboggz/trunk/src/tools/oggz-chop/oggz-chop.c
===================================================================
--- liboggz/trunk/src/tools/oggz-chop/oggz-chop.c 2008-04-14 00:39:12 UTC (rev 3556)
+++ liboggz/trunk/src/tools/oggz-chop/oggz-chop.c 2008-04-14 12:33:51 UTC (rev 3557)
@@ -209,12 +209,64 @@
accum_size = oggz_table_size (ts->page_accum);
- for (i = accum_size; i >= 0; i--) {
+ for (i = accum_size-1; i >= 0; i--) {
page_accum_delete((OCPageAccum *)oggz_table_lookup (ts->page_accum, i));
oggz_table_remove (ts->page_accum, (long)i);
}
}
+/*
+ * Advance the page accumulator:
+ * - Remove all pages that only contain packets from the previous GOP.
+ * - Shift all remaining packets to start from index 0
+ * Returns: the new size of the page accumulator.
+ */
+static int
+track_state_advance_page_accum (OCTrackState * ts)
+{
+ int i, accum_size;
+ int e, earliest_new; /* Index into page accumulator of the earliest page that
+ * contains a packet from the new GOP */
+ OCPageAccum * pa;
+
+ if (ts == NULL || ts->page_accum == NULL) return 0;
+
+ earliest_new = accum_size = oggz_table_size (ts->page_accum);
+
+ /* Working backwards through the page accumulator ... */
+ for (i = accum_size-1; i >= 0; i--) {
+ pa = (OCPageAccum *) oggz_table_lookup (ts->page_accum, i);
+
+ /* If we have a page with granulepos, it is necessarily contains the end
+ * of a packet from an earlier GOP, and thus this is the last page that
+ * we need to recover.
+ */
+ if (ogg_page_granulepos (pa->og) != -1) {
+ earliest_new = i;
+ break;
+ }
+ }
+
+ if (earliest_new > accum_size)
+ earliest_new = accum_size;
+
+ /* Delete the rest */
+ for (i = earliest_new-1; i >= 0; i--) {
+ pa = (OCPageAccum *) oggz_table_lookup (ts->page_accum, i);
+ page_accum_delete(pa);
+ oggz_table_remove (ts->page_accum, (long)i);
+ }
+
+ /* Shift the best */
+ for (i = 0, e = earliest_new; e < accum_size; i++, e++) {
+ pa = (OCPageAccum *) oggz_table_lookup (ts->page_accum, e);
+ oggz_table_insert (ts->page_accum, i, pa);
+ oggz_table_remove (ts->page_accum, (long)e);
+ }
+
+ return accum_size - earliest_new;
+}
+
/************************************************************
* chop
*/
@@ -377,15 +429,15 @@
keyframe = granulepos >> granuleshift;
if (keyframe != ts->prev_keyframe) {
- /* Clear the page accumulator */
- track_state_remove_page_accum (ts);
-#if 0
- for (i = accum_size; i >= 0; i--) {
- page_accum_delete((OCPageAccum *)oggz_table_lookup (ts->page_accum, i));
- oggz_table_remove (ts->page_accum, (long)i);
+ if (ogg_page_continued(og)) {
+ /* If this new-keyframe page is continued, advance the page accumulator,
+ * ie. recover earlier pages from this new GOP */
+ accum_size = track_state_advance_page_accum (ts);
+ } else {
+ /* Otherwise, just clear the page accumulator */
+ track_state_remove_page_accum (ts);
+ accum_size = 0;
}
-#endif
- accum_size = 0;
/* Record this as prev_keyframe */
ts->prev_keyframe = keyframe;
@@ -480,6 +532,10 @@
oggz_close (oggz);
+ if (state->outfilename != NULL) {
+ fclose (state->outfile);
+ }
+
state_clear (state);
return 0;
More information about the commits
mailing list