Commit 5021a98c authored by conrad's avatar conrad

Handle Theora version > 3.2.0 initial granulepos 1|0

Since theora version 3.2.1, the mapping from granules to time
has been shifted by 1, such that the first frame of a newly
encoded file is numbered 1, not 0. Detect that in auto_theora(),
and also report the Theora version in oggz info.
parent 6e924a13
...@@ -80,7 +80,7 @@ oggz_metric_default_granuleshift (OGGZ * oggz, long serialno, ...@@ -80,7 +80,7 @@ oggz_metric_default_granuleshift (OGGZ * oggz, long serialno,
iframe = granulepos >> stream->granuleshift; iframe = granulepos >> stream->granuleshift;
pframe = granulepos - (iframe << stream->granuleshift); pframe = granulepos - (iframe << stream->granuleshift);
granulepos = (iframe + pframe); granulepos = (iframe + pframe) - stream->first_granule;
units = granulepos * stream->granulerate_d / stream->granulerate_n; units = granulepos * stream->granulerate_d / stream->granulerate_n;
...@@ -200,6 +200,22 @@ oggz_get_granulerate (OGGZ * oggz, long serialno, ...@@ -200,6 +200,22 @@ oggz_get_granulerate (OGGZ * oggz, long serialno,
return 0; return 0;
} }
int
oggz_set_first_granule (OGGZ * oggz, long serialno,
ogg_int64_t first_granule)
{
oggz_stream_t * stream;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
stream->first_granule = first_granule;
return oggz_metric_update (oggz, serialno);
}
/** DEPRECATED **/ /** DEPRECATED **/
int int
oggz_set_metric_linear (OGGZ * oggz, long serialno, oggz_set_metric_linear (OGGZ * oggz, long serialno,
......
...@@ -347,6 +347,7 @@ oggz_add_stream (OGGZ * oggz, long serialno) ...@@ -347,6 +347,7 @@ oggz_add_stream (OGGZ * oggz, long serialno)
stream->preroll = 0; stream->preroll = 0;
stream->granulerate_n = 1; stream->granulerate_n = 1;
stream->granulerate_d = 1; stream->granulerate_d = 1;
stream->first_granule = 0;
stream->basegranule = 0; stream->basegranule = 0;
stream->granuleshift = 0; stream->granuleshift = 0;
......
...@@ -134,10 +134,13 @@ static int intlog(int num) { ...@@ -134,10 +134,13 @@ static int intlog(int num) {
} }
#endif #endif
#define THEORA_VERSION(maj,min,rev) ((maj<<16)+(min<<8)+rev)
static int static int
auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data) auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
{ {
unsigned char * header = data; unsigned char * header = data;
int version;
ogg_int32_t fps_numerator, fps_denominator; ogg_int32_t fps_numerator, fps_denominator;
char keyframe_granule_shift = 0; char keyframe_granule_shift = 0;
int keyframe_shift; int keyframe_shift;
...@@ -145,6 +148,8 @@ auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void ...@@ -145,6 +148,8 @@ auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void
/* TODO: this should check against 42 for the relevant version numbers */ /* TODO: this should check against 42 for the relevant version numbers */
if (length < 41) return 0; if (length < 41) return 0;
version = THEORA_VERSION(header[7], header[8], header[9]);
fps_numerator = int32_be_at(&header[22]); fps_numerator = int32_be_at(&header[22]);
fps_denominator = int32_be_at(&header[26]); fps_denominator = int32_be_at(&header[26]);
...@@ -173,6 +178,8 @@ auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void ...@@ -173,6 +178,8 @@ auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void
OGGZ_AUTO_MULT * (ogg_int64_t)fps_denominator); OGGZ_AUTO_MULT * (ogg_int64_t)fps_denominator);
oggz_set_granuleshift (oggz, serialno, keyframe_shift); oggz_set_granuleshift (oggz, serialno, keyframe_shift);
if (version > THEORA_VERSION(3,2,0))
oggz_set_first_granule (oggz, serialno, 1);
oggz_stream_set_numheaders (oggz, serialno, 3); oggz_stream_set_numheaders (oggz, serialno, 3);
......
...@@ -86,6 +86,7 @@ struct _oggz_stream_t { ...@@ -86,6 +86,7 @@ struct _oggz_stream_t {
int preroll; int preroll;
ogg_int64_t granulerate_n; ogg_int64_t granulerate_n;
ogg_int64_t granulerate_d; ogg_int64_t granulerate_d;
ogg_int64_t first_granule;
ogg_int64_t basegranule; ogg_int64_t basegranule;
int granuleshift; int granuleshift;
...@@ -282,6 +283,8 @@ oggz_get_granulerate (OGGZ * oggz, long serialno, ...@@ -282,6 +283,8 @@ oggz_get_granulerate (OGGZ * oggz, long serialno,
int oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift); int oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift);
int oggz_get_granuleshift (OGGZ * oggz, long serialno); int oggz_get_granuleshift (OGGZ * oggz, long serialno);
int oggz_set_first_granule (OGGZ * oggz, long serialno, ogg_int64_t first_granule);
int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll); int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll);
int oggz_get_preroll (OGGZ * oggz, long serialno); int oggz_get_preroll (OGGZ * oggz, long serialno);
......
...@@ -141,8 +141,10 @@ ot_theora_info (unsigned char * data, long len) ...@@ -141,8 +141,10 @@ ot_theora_info (unsigned char * data, long len)
height = INT16_BE_AT(&data[18]); height = INT16_BE_AT(&data[18]);
snprintf (buf, 80, snprintf (buf, 80,
"\tTheora-Version: %d.%d.%d\n"
"\tVideo-Framerate: %.3f fps\n" "\tVideo-Framerate: %.3f fps\n"
"\tVideo-Width: %d\n\tVideo-Height: %d\n", "\tVideo-Width: %d\n\tVideo-Height: %d\n",
data[7], data[8], data[9],
(double)INT32_BE_AT(&data[22])/ (double)INT32_BE_AT(&data[26]), (double)INT32_BE_AT(&data[22])/ (double)INT32_BE_AT(&data[26]),
width, height); width, height);
......
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