[xiph-commits] r3216 - liboggz/trunk/src/liboggz
shans at svn.annodex.net
shans at svn.annodex.net
Sun Sep 2 21:57:14 PDT 2007
Author: shans
Date: 2007-09-02 21:57:14 -0700 (Sun, 02 Sep 2007)
New Revision: 3216
Modified:
liboggz/trunk/src/liboggz/oggz.c
liboggz/trunk/src/liboggz/oggz_auto.c
liboggz/trunk/src/liboggz/oggz_dlist.c
liboggz/trunk/src/liboggz/oggz_private.h
liboggz/trunk/src/liboggz/oggz_read.c
liboggz/trunk/src/liboggz/oggz_stream.h
Log:
Code to generate initial granulepos values for packets before the end of the first page.
Modified: liboggz/trunk/src/liboggz/oggz.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz.c 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz.c 2007-09-03 04:57:14 UTC (rev 3216)
@@ -101,6 +101,8 @@
oggz->order = NULL;
oggz->order_user_data = NULL;
+ oggz->packet_buffer = oggz_dlist_new ();
+
if (OGGZ_CONFIG_WRITE && (oggz->flags & OGGZ_WRITE)) {
oggz_write_init (oggz);
} else if (OGGZ_CONFIG_READ) {
Modified: liboggz/trunk/src/liboggz/oggz_auto.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_auto.c 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_auto.c 2007-09-03 04:57:14 UTC (rev 3216)
@@ -444,6 +444,26 @@
}
+auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
+ ogg_packet *this_packet, ogg_packet *next_packet) {
+
+ int keyframe = (int)(next_packet_gp >> stream->granuleshift);
+ int offset = (int)(next_packet_gp - (keyframe << stream->granuleshift));
+
+ /* assume kf is 60 frames ago. NOTE: This is going to cause problems,
+ * but I can't think of what else to do. The position of the last kf
+ * is fundamentally unknowable.
+ */
+ if (offset == 0) {
+ return ((keyframe - 60L) << stream->granuleshift) + 59;
+ }
+ else {
+ return (((ogg_int64_t)keyframe) << stream->granuleshift) + (offset - 1);
+ }
+
+}
+
+
/*
* Vorbis packets can be short or long, and each packet overlaps the previous
* and next packets. The granulepos of a packet is always the last sample
@@ -721,6 +741,25 @@
}
+ogg_int64_t
+auto_rcalc_vorbis(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
+ ogg_packet *this_packet, ogg_packet *next_packet) {
+
+ auto_calc_vorbis_info_t *info =
+ (auto_calc_vorbis_info_t *)stream->calculate_data;
+
+ int mode =
+ (this_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
+ int this_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
+ int next_size;
+
+ mode = (next_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
+ next_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
+
+ return next_packet_gp - ((this_size + next_size) / 4);
+
+}
+
/**
* FLAC
* Defined at: http://flac.sourceforge.net/ogg_mapping.html
@@ -838,17 +877,17 @@
}
const oggz_auto_contenttype_t oggz_auto_codec_ident[] = {
- {"\200theora", 7, "Theora", auto_theora, auto_calc_theora},
- {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis},
- {"Speex", 5, "Speex", auto_speex, auto_calc_speex},
- {"PCM ", 8, "PCM", auto_oggpcm2, NULL},
- {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL},
- {"Annodex", 8, "Annodex", auto_annodex, NULL},
- {"fishead", 7, "Skeleton", auto_fishead, NULL},
- {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac},
- {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac},
- {"AnxData", 7, "AnxData", auto_anxdata, NULL},
- {"", 0, "Unknown", NULL, NULL}
+ {"\200theora", 7, "Theora", auto_theora, auto_calc_theora, auto_rcalc_theora},
+ {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis, auto_rcalc_vorbis},
+ {"Speex", 5, "Speex", auto_speex, auto_calc_speex, NULL},
+ {"PCM ", 8, "PCM", auto_oggpcm2, NULL, NULL},
+ {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL, NULL},
+ {"Annodex", 8, "Annodex", auto_annodex, NULL, NULL},
+ {"fishead", 7, "Skeleton", auto_fishead, NULL, NULL},
+ {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac, NULL},
+ {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac, NULL},
+ {"AnxData", 7, "AnxData", auto_anxdata, NULL, NULL},
+ {"", 0, "Unknown", NULL, NULL, NULL}
};
int oggz_auto_identify (OGGZ *oggz, ogg_page *og, long serialno) {
@@ -892,30 +931,25 @@
oggz_stream_t *stream, ogg_packet *op) {
if (oggz_auto_codec_ident[content].calculator != NULL) {
ogg_int64_t r = oggz_auto_codec_ident[content].calculator(now, stream, op);
- /*
- * this will cause a hiccough at the end of the first data page if there are
- * more than one packets on that page. In the absence of pervasive access
- * to the packets on a page, though, it might have to do.
- *
- * Why a hiccough? Because there's no granulepos attached to any packets
- * except for the last on a page. If the stream doesn't start at gp 0 (a
- * very common occurrence) then we don't realise until we get to the end of
- * the page. By that time we've already junked the first packets on the
- * page.
- */
- /*
- if (now != -1LL) {
- return op->granulepos;
- }
- */
return r;
}
return now;
-
-
}
+ogg_int64_t
+oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
+ oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet) {
+
+ if (oggz_auto_codec_ident[content].r_calculator != NULL) {
+ return oggz_auto_codec_ident[content].r_calculator(next_packet_gp,
+ stream, this_packet, next_packet);
+ }
+
+ return 0;
+
+}
+
int
oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
ogg_packet * op)
Modified: liboggz/trunk/src/liboggz/oggz_dlist.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_dlist.c 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_dlist.c 2007-09-03 04:57:14 UTC (rev 3216)
@@ -63,6 +63,8 @@
dlist->head = dummy_front;
dlist->tail = dummy_back;
+ return dlist;
+
}
void
@@ -77,6 +79,8 @@
free(dlist->tail);
free(dlist);
+ printf("dlist:DELETE complete\n");
+
}
int
@@ -137,13 +141,14 @@
void
oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
- OggzDListElem *p;
+ OggzDListElem *p, *q;
- for (p = dlist->head->next; p != dlist->tail; p = p->next) {
+ for (p = dlist->head->next; p != dlist->tail; p = q) {
if (func(p->data) == DLIST_ITER_CANCEL) {
break;
}
+ q = p->next;
p->prev->next = p->next;
p->next->prev = p->prev;
@@ -155,13 +160,14 @@
void
oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
- OggzDListElem *p;
+ OggzDListElem *p, *q;
- for (p = dlist->tail->prev; p != dlist->head; p = p->prev) {
+ for (p = dlist->tail->prev; p != dlist->head; p = q) {
if (func(p->data) == DLIST_ITER_CANCEL) {
break;
}
+ q = p->prev;
p->prev->next = p->next;
p->next->prev = p->prev;
Modified: liboggz/trunk/src/liboggz/oggz_private.h
===================================================================
--- liboggz/trunk/src/liboggz/oggz_private.h 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_private.h 2007-09-03 04:57:14 UTC (rev 3216)
@@ -42,8 +42,8 @@
#include "oggz_macros.h"
#include "oggz_vector.h"
+#include "oggz_dlist.h"
-
typedef struct _OGGZ OGGZ;
typedef struct _OggzComment OggzComment;
typedef struct _OggzIO OggzIO;
@@ -118,6 +118,7 @@
ogg_int64_t last_granulepos;
ogg_int64_t page_granulepos;
void * calculate_data;
+ ogg_packet * last_packet;
};
struct _OggzReader {
@@ -237,6 +238,8 @@
OggzReader reader;
OggzWriter writer;
} x;
+
+ OggzDList * packet_buffer;
};
OGGZ * oggz_read_init (OGGZ * oggz);
Modified: liboggz/trunk/src/liboggz/oggz_read.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_read.c 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_read.c 2007-09-03 04:57:14 UTC (rev 3216)
@@ -238,6 +238,96 @@
return ret;
}
+typedef struct {
+ ogg_packet packet;
+ ogg_int64_t calced_granulepos;
+ oggz_stream_t * stream;
+ OggzReader * reader;
+ OGGZ * oggz;
+ long serialno;
+} OggzBufferedPacket;
+
+OggzBufferedPacket *
+oggz_read_new_pbuffer_entry(OGGZ *oggz, ogg_packet *packet,
+ ogg_int64_t granulepos, long serialno, oggz_stream_t * stream,
+ OggzReader *reader) {
+
+ OggzBufferedPacket *p = malloc(sizeof(OggzBufferedPacket));
+ memcpy(&(p->packet), packet, sizeof(ogg_packet));
+ p->packet.packet = malloc(packet->bytes);
+ memcpy(p->packet.packet, packet->packet, packet->bytes);
+
+ p->calced_granulepos = granulepos;
+ p->stream = stream;
+ p->serialno = serialno;
+ p->reader = reader;
+ p->oggz = oggz;
+
+ return p;
+}
+
+void
+oggz_read_free_pbuffer_entry(OggzBufferedPacket *p) {
+
+ free(p->packet.packet);
+ free(p);
+
+}
+
+OggzDListIterResponse
+oggz_read_update_gp(void *elem) {
+
+ OggzBufferedPacket *p = (OggzBufferedPacket *)elem;
+
+ if (p->calced_granulepos == -1 && p->stream->last_granulepos != -1) {
+ int content = oggz_stream_get_content(p->oggz, p->serialno);
+ p->calced_granulepos =
+ oggz_auto_calculate_gp_backwards(content, p->stream->last_granulepos,
+ p->stream, &(p->packet), p->stream->last_packet);
+
+ p->stream->last_granulepos = p->calced_granulepos;
+ p->stream->last_packet = &(p->packet);
+ }
+
+ return DLIST_ITER_CONTINUE;
+
+}
+
+OggzDListIterResponse
+oggz_read_deliver_packet(void *elem) {
+
+ OggzBufferedPacket *p = (OggzBufferedPacket *)elem;
+ ogg_int64_t gp_stored;
+ long unit_stored;
+
+ if (p->calced_granulepos == -1) {
+ return DLIST_ITER_CANCEL;
+ }
+
+ gp_stored = p->reader->current_granulepos;
+ unit_stored = p->reader->current_unit;
+
+ p->reader->current_granulepos = p->calced_granulepos;
+
+ p->reader->current_unit =
+ oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos);
+
+ if (p->stream->read_packet) {
+ p->stream->read_packet(p->oggz, &(p->packet), p->serialno,
+ p->stream->read_user_data);
+ } else if (p->reader->read_packet) {
+ p->reader->read_packet(p->oggz, &(p->packet), p->serialno,
+ p->reader->read_user_data);
+ }
+
+ p->reader->current_granulepos = gp_stored;
+ p->reader->current_unit = unit_stored;
+
+ oggz_read_free_pbuffer_entry(p);
+
+ return DLIST_ITER_CONTINUE;
+}
+
static int
oggz_read_sync (OGGZ * oggz)
{
@@ -348,6 +438,44 @@
oggz_auto_read_comments (oggz, stream, serialno, op);
}
+ /*
+ * while we are getting invalid granulepos values, store the incoming
+ * packets in a dlist */
+ if (reader->current_granulepos == -1) {
+ OggzBufferedPacket *p = oggz_read_new_pbuffer_entry(
+ oggz, &packet, reader->current_granulepos,
+ serialno, stream, reader);
+
+ oggz_dlist_append(oggz->packet_buffer, p);
+ continue;
+ } else if (!oggz_dlist_is_empty(oggz->packet_buffer)) {
+ /*
+ * move backward through the list assigning gp values based upon
+ * the granulepos we just recieved. Then move forward through
+ * the list delivering any packets at the beginning with valid
+ * gp values
+ */
+ ogg_int64_t gp_stored = stream->last_granulepos;
+ stream->last_packet = &packet;
+ oggz_dlist_reverse_iter(oggz->packet_buffer, oggz_read_update_gp);
+ oggz_dlist_deliter(oggz->packet_buffer, oggz_read_deliver_packet);
+
+ /*
+ * fix up the stream granulepos
+ */
+ stream->last_granulepos = gp_stored;
+
+ if (!oggz_dlist_is_empty(oggz->packet_buffer)) {
+ OggzBufferedPacket *p = oggz_read_new_pbuffer_entry(
+ oggz, &packet, reader->current_granulepos,
+ serialno, stream, reader);
+
+ oggz_dlist_append(oggz->packet_buffer, p);
+ continue;
+ }
+
+ }
+
if (stream->read_packet) {
cb_ret =
stream->read_packet (oggz, op, serialno, stream->read_user_data);
Modified: liboggz/trunk/src/liboggz/oggz_stream.h
===================================================================
--- liboggz/trunk/src/liboggz/oggz_stream.h 2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_stream.h 2007-09-03 04:57:14 UTC (rev 3216)
@@ -42,6 +42,9 @@
OggzReadPacket reader;
ogg_int64_t (*calculator)(ogg_int64_t now, oggz_stream_t *stream,
ogg_packet *op);
+ ogg_int64_t (*r_calculator)(ogg_int64_t next_packet_gp,
+ oggz_stream_t *stream, ogg_packet *this_packet,
+ ogg_packet *next_packet);
} oggz_auto_contenttype_t;
extern const oggz_auto_contenttype_t oggz_auto_codec_ident[];
@@ -57,4 +60,9 @@
ogg_int64_t
oggz_auto_calculate_granulepos(int content, ogg_int64_t now,
oggz_stream_t *stream, ogg_packet *op);
+
+ogg_int64_t
+oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
+ oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet);
+
#endif /* __OGGZ_STREAM_H__ */
More information about the commits
mailing list