Commit 9dfbb97b authored by conrad's avatar conrad

add page reading, hack oggzmerge to do page by page interleaving with metrics


git-svn-id: http://svn.annodex.net/liboggz/trunk@562 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent 746dbae2
......@@ -93,6 +93,37 @@ typedef int (*OggzReadPacket) (OGGZ * oggz, ogg_packet * op, long serialno,
int oggz_set_read_callback (OGGZ * oggz, long serialno,
OggzReadPacket read_packet, void * user_data);
/**
* This is the signature of a callback which you must provide for Oggz
* to call whenever it finds a new page in the Ogg stream associated
* with \a oggz.
*
* \param oggz The OGGZ handle
* \param op The full ogg_page (see <ogg/ogg.h>)
* \param user_data A generic pointer you have provided earlier
* \returns 0 to continue, non-zero to instruct OGGZ to stop.
*/
typedef int (*OggzReadPage) (OGGZ * oggz, const ogg_page * og,
void * user_data);
/**
* Set a callback for Oggz to call when a new Ogg page is found in the
* stream.
*
* \param oggz An OGGZ handle previously opened for reading
* \param read_page Your OggzReadPage callback function
* \param user_data Arbitrary data you wish to pass to your callback
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*
* \note It is safe to call this callback from within an OggzReadPage
* function, in order to specify that subsequent pages should be handled
* by a different OggzReadPage function.
*/
int oggz_set_read_page (OGGZ * oggz, OggzReadPage read_page, void * user_data);
/**
* Read n bytes into \a oggz, calling any read callbacks on the fly.
* \param oggz An OGGZ handle previously opened for reading
......
......@@ -49,6 +49,8 @@ typedef struct _OggzWriter OggzWriter;
typedef int (*OggzReadPacket) (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data);
typedef int (*OggzReadPage) (OGGZ * oggz, const ogg_page * og,
void * user_data);
typedef ogg_int64_t (*OggzMetric) (OGGZ * oggz, long serialno,
ogg_int64_t granulepos,
......@@ -98,6 +100,9 @@ struct _OggzReader {
OggzReadPacket read_packet;
void * read_user_data;
OggzReadPage read_page;
void * read_page_user_data;
ogg_int64_t current_unit;
#if 0
......
......@@ -132,6 +132,25 @@ oggz_set_read_callback (OGGZ * oggz, long serialno,
return 0;
}
int
oggz_set_read_page (OGGZ * oggz, OggzReadPage read_page, void * user_data)
{
OggzReader * reader;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
reader = &oggz->x.reader;
if (oggz->flags & OGGZ_WRITE) {
return OGGZ_ERR_INVALID;
}
reader->read_page = read_page;
reader->read_page_user_data = user_data;
return 0;
}
/*
* oggz_get_next_page_7 (oggz, og, do_read)
*
......@@ -261,10 +280,12 @@ oggz_read_sync (OGGZ * oggz)
oggz_auto (oggz, op, serialno, NULL);
}
#if 0 /* set unit on last packet of page */
if ((oggz->metric || stream->metric) && granulepos != -1) {
reader->current_unit = oggz_get_unit (oggz, serialno, granulepos);
}
#ifndef DEBUG_BY_READING_PAGES
#endif
if (stream->read_packet) {
cb_ret =
stream->read_packet (oggz, op, serialno, stream->read_user_data);
......@@ -272,7 +293,6 @@ oggz_read_sync (OGGZ * oggz)
cb_ret =
reader->read_packet (oggz, op, serialno, reader->read_user_data);
}
#endif /* DEBUG_BY_READING_PAGES */
}
else
break;
......@@ -299,25 +319,20 @@ oggz_read_sync (OGGZ * oggz)
}
os = &stream->ogg_stream;
#ifdef DEBUG_BY_READING_PAGES
{
ogg_packet op_debug;
op_debug.packet = og.body;
op_debug.bytes = og.body_len;
op_debug.b_o_s = ogg_page_bos (&og);
op_debug.e_o_s = ogg_page_eos (&og);
op_debug.granulepos = ogg_page_granulepos (&og);
op_debug.packetno = ogg_page_packets (&og);
if (stream->read_packet) {
cb_ret = stream->read_packet (oggz, &op_debug, serialno,
stream->read_user_data);
} else if (reader->read_packet) {
cb_ret = reader->read_packet (oggz, &op_debug, serialno,
reader->read_user_data);
ogg_int64_t granulepos;
granulepos = ogg_page_granulepos (&og);
if ((oggz->metric || stream->metric) && granulepos != -1) {
reader->current_unit = oggz_get_unit (oggz, serialno, granulepos);
} else if (granulepos == 0) {
reader->current_unit = 0;
}
}
#endif
if (reader->read_page) {
cb_ret = reader->read_page (oggz, &og, reader->read_page_user_data);
}
#if 0
/* bitrate tracking; add the header's bytes here, the body bytes
......
......@@ -44,7 +44,7 @@
#define READ_SIZE 4096
static int
read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data);
read_page (OGGZ * oggz, const ogg_page * og, void * user_data);
static void
usage (char * progname)
......@@ -57,35 +57,49 @@ typedef struct _OMInput OMInput;
typedef struct _OMITrack OMITrack;
struct _OMData {
OGGZ * writer;
OggzTable * inputs;
};
struct _OMInput {
OMData * omdata;
OGGZ * reader;
OggzTable * tracks;
const ogg_page * og;
};
struct _OMITrack {
long output_serialno;
};
static ogg_page *
_ogg_page_copy (ogg_page * og)
{
ogg_page * new_og;
new_og = malloc (sizeof (*og));
new_og->header = malloc (og->header_len);
new_og->header_len = og->header_len;
memcpy (new_og->header, og->header, og->header_len);
new_og->body = malloc (og->body_len);
new_og->body_len = og->body_len;
memcpy (new_og->body, og->body, og->body_len);
return new_og;
}
static int
_ogg_page_free (ogg_page * og)
{
free (og->header);
free (og->body);
free (og);
return 0;
}
static void
ominput_delete (OMInput * input)
{
int i, ntracks;
OMITrack * track;
oggz_close (input->reader);
ntracks = oggz_table_size (input->tracks);
for (i = 0; i < ntracks; i++) {
track = oggz_table_nth (input->tracks, i, NULL);
free (track);
}
oggz_table_delete (input->tracks);
free (input);
}
......@@ -96,7 +110,6 @@ omdata_new (void)
omdata = (OMData *) malloc (sizeof (OMData));
omdata->writer = oggz_new (OGGZ_WRITE);
omdata->inputs = oggz_table_new ();
return omdata;
......@@ -108,8 +121,6 @@ omdata_delete (OMData * omdata)
OMInput * input;
int i, ninputs;
oggz_close (omdata->writer);
ninputs = oggz_table_size (omdata->inputs);
for (i = 0; i < ninputs; i++) {
input = (OMInput *) oggz_table_nth (omdata->inputs, i, NULL);
......@@ -130,10 +141,10 @@ omdata_add_input (OMData * omdata, FILE * infile)
if (input == NULL) return -1;
input->omdata = omdata;
input->reader = oggz_open_stdio (infile, OGGZ_READ);
input->tracks = oggz_table_new ();
input->reader = oggz_open_stdio (infile, OGGZ_READ|OGGZ_AUTO);
input->og = NULL;
oggz_set_read_callback (input->reader, -1, read_packet, input);
oggz_set_read_page (input->reader, read_page, input);
nfiles = oggz_table_size (omdata->inputs);
if (!oggz_table_insert (omdata->inputs, nfiles++, input)) {
......@@ -145,31 +156,11 @@ omdata_add_input (OMData * omdata, FILE * infile)
}
static int
read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
read_page (OGGZ * oggz, const ogg_page * og, void * user_data)
{
OMInput * input = (OMInput *) user_data;
OGGZ * writer = input->omdata->writer;
OMITrack * itrack;
int flush;
int ret;
itrack = oggz_table_lookup (input->tracks, serialno);
if (itrack == NULL) {
itrack = (OMITrack *) malloc (sizeof (OMITrack));
itrack->output_serialno = oggz_serialno_new (writer);
oggz_table_insert (input->tracks, serialno, itrack);
}
if (op->granulepos == -1) {
flush = 0;
} else {
flush = OGGZ_FLUSH_AFTER;
}
if ((ret = oggz_write_feed (writer, op, itrack->output_serialno,
flush, NULL)) != 0) {
printf ("oggz_write_feed: %d\n", ret);
}
input->og = _ogg_page_copy (og);
return OGGZ_STOP_OK;
}
......@@ -179,25 +170,55 @@ oggz_merge (OMData * omdata, FILE * outfile)
{
unsigned char buf[READ_SIZE];
OMInput * input;
int ninputs, i;
int ninputs, i, min_i;
long key, n;
ogg_int64_t units, min_units;
const ogg_page * og;
int active;
while ((ninputs = oggz_table_size (omdata->inputs)) > 0) {
for (i = 0; i < oggz_table_size (omdata->inputs); i++) {
min_units = -1;
min_i = -1;
active = 1;
/* Reload all pages, and find the min (earliest) */
for (i = 0; active && i < oggz_table_size (omdata->inputs); i++) {
input = (OMInput *) oggz_table_nth (omdata->inputs, i, &key);
if (input != NULL) {
n = oggz_read (input->reader, READ_SIZE);
if (n == 0) {
oggz_table_remove (omdata->inputs, key);
ominput_delete (input);
if (input->og == NULL) {
n = oggz_read (input->reader, READ_SIZE);
if (n == 0) {
oggz_table_remove (omdata->inputs, key);
ominput_delete (input);
input = NULL;
}
}
if (input && input->og) {
if (ogg_page_bos (input->og)) {
min_i = i;
active = 0;
}
units = oggz_tell_units (input->reader);
printf ("cmp units %lld < %lld ?\n", units, min_units);
if (min_units == -1 || units == 0 ||
(units > -1 && units < min_units)) {
min_units = units;
min_i = i;
}
}
}
}
while ((n = oggz_write_output (omdata->writer, buf, READ_SIZE)) > 0) {
fwrite (buf, 1, n, outfile);
}
/* Write the earliest page */
if (min_i != -1) {
input = (OMInput *) oggz_table_nth (omdata->inputs, min_i, &key);
og = input->og;
fwrite (og->header, 1, og->header_len, outfile);
fwrite (og->body, 1, og->body_len, outfile);
_ogg_page_free (og);
input->og = NULL;
}
}
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment