Commit 94b328c7 authored by shans's avatar shans

Added oggz_tell_granulepos function to query liboggz for granulepos values.

Added calculation of lost granulepos values for packets that are not on end of 
page (theora and speex codecs only at this point).



git-svn-id: http://svn.annodex.net/liboggz/trunk@2341 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent 59092e21
......@@ -105,6 +105,17 @@ ogg_int64_t oggz_tell_units (OGGZ * oggz);
*/
ogg_int64_t oggz_seek_units (OGGZ * oggz, ogg_int64_t units, int whence);
/**
* Provide the exact stored granulepos (from the page header) if relevant to
* the current packet, or a constructed granulepos if the stored granulepos
* does not belong to this packet, or -1 if this codec does not have support
* for granulepos interpolation
* \param oggz An OGGZ handle
* \returns the granulepos of the \a current packet (if available)
*/
ogg_int64_t
oggz_tell_granulepos (OGGZ * oggz);
/**
* Query the file offset in bytes corresponding to the data read.
* \param oggz An OGGZ handle
......
......@@ -39,6 +39,7 @@
oggz_get_granuleshift;
oggz_tell;
oggz_tell_granulepos;
oggz_tell_units;
oggz_seek;
oggz_seek_units;
......
......@@ -173,6 +173,9 @@ oggz_stream_clear (void * data)
if (stream->metric_internal)
oggz_free (stream->metric_user_data);
if (stream->calculate_data != NULL)
oggz_free (stream->calculate_data);
oggz_free (stream);
return 0;
......@@ -239,6 +242,22 @@ oggz_tell_units (OGGZ * oggz)
}
}
ogg_int64_t
oggz_tell_granulepos (OGGZ * oggz)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->flags & OGGZ_WRITE) {
return OGGZ_ERR_INVALID;
}
if (OGGZ_CONFIG_READ) {
return oggz->x.reader.current_granulepos;
} else {
return OGGZ_ERR_DISABLED;
}
}
long
oggz_run (OGGZ * oggz)
{
......@@ -319,6 +338,8 @@ oggz_add_stream (OGGZ * oggz, long serialno)
stream->read_page = NULL;
stream->read_page_user_data = NULL;
stream->calculate_data = NULL;
oggz_vector_insert_p (oggz->streams, stream);
return stream;
......
......@@ -42,11 +42,8 @@
#include <stdlib.h>
#include <string.h>
#include <oggz/oggz.h>
#include "oggz_auto.h"
#include "oggz_private.h"
#include "oggz_byteorder.h"
#include "oggz_macros.h"
#include "oggz_stream.h"
/*#define DEBUG*/
......@@ -317,18 +314,93 @@ auto_fishead (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
return 1;
}
static ogg_int64_t
auto_calc_speex(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
/*
* on the first (b_o_s) packet, set calculate_data to be the number
* of speex frames per packet
*/
if (stream->calculate_data == NULL) {
stream->calculate_data = malloc(sizeof(int));
*(int *)stream->calculate_data =
(*(int *)(op->packet + 64)) * (*(int *)(op->packet + 56));
}
if (now > -1)
return now;
/*
* the first data packet has smaller-than-usual granulepos to account
* for the fact that several of the output samples from the beginning
* of this packet need to be thrown away. We calculate the granulepos
* by taking the mod of the page's granulepos with respect to the increment
* between packets.
*/
if (stream->last_granulepos == 0) {
return stream->page_granulepos % *(int *)(stream->calculate_data);
}
return stream->last_granulepos + *(int *)(stream->calculate_data);
}
static ogg_int64_t
auto_calc_theora(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
long keyframe_no;
int keyframe_shift;
unsigned char first_byte;
if (now > (ogg_int64_t)(-1))
return now;
first_byte = op->packet[0];
if (first_byte & 0x80)
{
/* header packet */
return (ogg_int64_t)0;
}
if (first_byte & 0x40)
{
/* inter-coded packet */
return stream->last_granulepos + 1;
}
/* intra-coded packet */
if (stream->last_granulepos == 0)
{
/* first intra-coded packet */
return (ogg_int64_t)0;
}
keyframe_shift = stream->granuleshift;
/*
* retrieve last keyframe number
*/
keyframe_no = (int)(stream->last_granulepos >> keyframe_shift);
/*
* add frames since last keyframe number
*/
keyframe_no += (stream->last_granulepos & ((1 << keyframe_shift) - 1)) + 1;
return ((ogg_int64_t)keyframe_no) << keyframe_shift;
}
const oggz_auto_contenttype_t oggz_auto_codec_ident[] = {
{"\200theora", 7, "Theora", auto_theora},
{"\001vorbis", 7, "Vorbis", auto_vorbis},
{"Speex", 5, "Speex", auto_speex},
{"PCM ", 8, "PCM", auto_oggpcm2},
{"CMML\0\0\0\0", 8, "CMML", auto_cmml},
{"Annodex", 8, "Annodex", auto_annodex},
{"fishead", 7, "Skeleton", auto_fishead},
{"fLaC", 4, "Flac0", auto_flac0},
{"\177FLAC", 4, "Flac", auto_flac},
{"AnxData", 7, "AnxData", auto_anxdata},
{"", 0, "Unknown"}
{"\200theora", 7, "Theora", auto_theora, auto_calc_theora},
{"\001vorbis", 7, "Vorbis", auto_vorbis, NULL},
{"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, NULL},
{"\177FLAC", 4, "Flac", auto_flac, NULL},
{"AnxData", 7, "AnxData", auto_anxdata, NULL},
{"", 0, "Unknown", NULL}
};
int oggz_auto_identify (OGGZ *oggz, ogg_page *og, long serialno) {
......@@ -354,8 +426,7 @@ int oggz_auto_identify (OGGZ *oggz, ogg_page *og, long serialno) {
int
oggz_auto_get_granulerate (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data)
{
void * user_data) {
OggzReadPacket read_packet;
int content = 0;
int will_run_function;
......@@ -369,4 +440,15 @@ oggz_auto_get_granulerate (OGGZ * oggz, ogg_packet * op, long serialno,
return 0;
}
ogg_int64_t
oggz_auto_calculate_granulepos(int content, ogg_int64_t now,
oggz_stream_t *stream, ogg_packet *op) {
if (oggz_auto_codec_ident[content].calculator != NULL) {
return oggz_auto_codec_ident[content].calculator(now, stream, op);
} else {
return now;
}
}
#endif /* OGGZ_CONFIG_READ */
......@@ -106,6 +106,11 @@ struct _oggz_stream_t {
OggzReadPage read_page;
void * read_page_user_data;
/* calculated granulepos values, not extracted values */
ogg_int64_t last_granulepos;
ogg_int64_t page_granulepos;
void * calculate_data;
};
struct _OggzReader {
......@@ -122,6 +127,7 @@ struct _OggzReader {
void * read_page_user_data;
ogg_int64_t current_unit;
ogg_int64_t current_granulepos;
#if 0
off_t offset_page_end; /* offset of end of current page */
......
......@@ -290,21 +290,16 @@ oggz_read_sync (OGGZ * oggz)
}
if(result > 0){
int content;
/* got a packet. process it */
granulepos = op->granulepos;
/*
* need to call oggz_auto to process Anx v2 streams which were headed
* with AnxData packets. This enables the AnxData-provided granulerate
* to be overridden by the stream's rate if present
*/
content = oggz_stream_get_content(oggz, serialno);
if
(
(
!stream->metric
||
(oggz_stream_get_content(oggz, serialno) == OGGZ_CONTENT_SKELETON)
)
(!stream->metric || (content == OGGZ_CONTENT_SKELETON))
&&
(oggz->flags & OGGZ_AUTO)
)
......@@ -312,6 +307,15 @@ oggz_read_sync (OGGZ * oggz)
oggz_auto_get_granulerate (oggz, op, serialno, NULL);
}
/* attempt to determine granulepos for this packet */
if (oggz->flags & OGGZ_AUTO) {
reader->current_granulepos = oggz_auto_calculate_granulepos (content,
granulepos, stream, op);
} else {
reader->current_granulepos = granulepos;
}
stream->last_granulepos = reader->current_granulepos;
/* set unit on last packet of page */
if ((oggz->metric || stream->metric) && granulepos != -1) {
reader->current_unit = oggz_get_unit (oggz, serialno, granulepos);
......@@ -365,6 +369,7 @@ oggz_read_sync (OGGZ * oggz)
ogg_int64_t granulepos;
granulepos = ogg_page_granulepos (&og);
stream->page_granulepos = granulepos;
if ((oggz->metric || stream->metric) && granulepos != -1) {
reader->current_unit = oggz_get_unit (oggz, serialno, granulepos);
......
......@@ -33,16 +33,19 @@
#ifndef __OGGZ_STREAM_H__
#define __OGGZ_STREAM_H__
typedef struct _oggz_stream_t oggz_stream_t;
typedef struct {
const char *bos_str;
int bos_str_len;
const char *content_type;
OggzReadPacket reader;
ogg_int64_t (*calculator)(ogg_int64_t now, oggz_stream_t *stream,
ogg_packet *op);
} oggz_auto_contenttype_t;
extern const oggz_auto_contenttype_t oggz_auto_codec_ident[];
typedef struct _oggz_stream_t oggz_stream_t;
oggz_stream_t * oggz_get_stream (OGGZ * oggz, long serialno);
oggz_stream_t * oggz_add_stream (OGGZ * oggz, long serialno);
......
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