[xiph-commits] r16390 - in trunk/xiph-qt: . OggImport/src build-macosx/XiphQT.xcodeproj
arek at svn.xiph.org
arek at svn.xiph.org
Sat Aug 1 16:30:49 PDT 2009
Author: arek
Date: 2009-08-01 16:30:49 -0700 (Sat, 01 Aug 2009)
New Revision: 16390
Added:
trunk/xiph-qt/OggImport/src/stream_private_vorbis.c
trunk/xiph-qt/OggImport/src/stream_private_vorbis.h
Modified:
trunk/xiph-qt/ChangeLog
trunk/xiph-qt/OggImport/src/OggImport.c
trunk/xiph-qt/OggImport/src/importer_types.h
trunk/xiph-qt/OggImport/src/samplerefs.c
trunk/xiph-qt/OggImport/src/samplerefs.h
trunk/xiph-qt/OggImport/src/stream_flac.h
trunk/xiph-qt/OggImport/src/stream_speex.h
trunk/xiph-qt/OggImport/src/stream_theora.c
trunk/xiph-qt/OggImport/src/stream_theora.h
trunk/xiph-qt/OggImport/src/stream_types_vorbis.h
trunk/xiph-qt/OggImport/src/stream_vorbis.c
trunk/xiph-qt/OggImport/src/stream_vorbis.h
trunk/xiph-qt/OggImport/src/utils.c
trunk/xiph-qt/OggImport/src/utils.h
trunk/xiph-qt/build-macosx/XiphQT.xcodeproj/project.pbxproj
Log:
* OggImport/src/stream_private_vorbis.h (added):
* OggImport/src/stream_private_vorbis.c (added):
* OggImport/src/stream_types_vorbis.h:
* build-macosx/XiphQT.xcodeproj/project.pbxproj:
Add code to calculate duration of Vorbis ogg page.
* OggImport/src/OggImport.c:
* OggImport/src/importer_types.h:
* OggImport/src/stream_theora.c:
* OggImport/src/stream_theora.h:
* OggImport/src/stream_vorbis.c:
* OggImport/src/stream_vorbis.h:
Add code to calculate base granulepos for each group of streams
and use it to correctly synchronize the streams withing the
groups.
* OggImport/src/samplerefs.h:
* OggImport/src/samplerefs.c:
Add method for updating the duration of the first pending sample
reference.
* OggImport/src/utils.h:
* OggImport/src/utils.c:
Add granulepos -> time conversion utility.
* OggImport/src/stream_flac.h:
* OggImport/src/stream_speex.h:
Adapt to changes.
Modified: trunk/xiph-qt/ChangeLog
===================================================================
--- trunk/xiph-qt/ChangeLog 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/ChangeLog 2009-08-01 23:30:49 UTC (rev 16390)
@@ -1,3 +1,34 @@
+2009-08-02 Arek Korbik <arkadini at gmail.com>
+
+ * OggImport/src/stream_private_vorbis.h (added):
+ * OggImport/src/stream_private_vorbis.c (added):
+ * OggImport/src/stream_types_vorbis.h:
+ * build-macosx/XiphQT.xcodeproj/project.pbxproj:
+ Add code to calculate duration of Vorbis ogg page.
+
+ * OggImport/src/OggImport.c:
+ * OggImport/src/importer_types.h:
+ * OggImport/src/stream_theora.c:
+ * OggImport/src/stream_theora.h:
+ * OggImport/src/stream_vorbis.c:
+ * OggImport/src/stream_vorbis.h:
+ Add code to calculate base granulepos for each group of streams
+ and use it to correctly synchronize the streams withing the
+ groups.
+
+ * OggImport/src/samplerefs.h:
+ * OggImport/src/samplerefs.c:
+ Add method for updating the duration of the first pending sample
+ reference.
+
+ * OggImport/src/utils.h:
+ * OggImport/src/utils.c:
+ Add granulepos -> time conversion utility.
+
+ * OggImport/src/stream_flac.h:
+ * OggImport/src/stream_speex.h:
+ Adapt to changes.
+
2009-07-18 Arek Korbik <arkadini at gmail.com>
* OggImport/src/OggImport.r:
Modified: trunk/xiph-qt/OggImport/src/OggImport.c
===================================================================
--- trunk/xiph-qt/OggImport/src/OggImport.c 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/OggImport.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -363,6 +363,12 @@
// si->sampleOffset = 0;
+ si->baseGranulePosFound = false;
+ si->baseGranulePos = 0;
+ si->baseGranuleTime = -1;
+ si->baseGranuleTimeSubSecond = 0.0;
+ si->groupBaseOffsetApplied = false;
+
globals->numTracksStarted++;
}
@@ -775,6 +781,9 @@
SetTrackEnabled(si->theTrack, true);
si->lastGranulePos = 0;
+ si->baseGranulePos = 0;
+ si->baseGranulePosFound = false;
+ si->groupBaseOffsetApplied = false;
}
else
{
@@ -1059,6 +1068,67 @@
/* =============================================================== */
+static Boolean found_all_base_gps(OggImportGlobalsPtr globals) {
+ int i;
+ Boolean found_all = true;
+
+ for (i = 0; i < globals->streamCount; i++) {
+ StreamInfoPtr si = &(*globals->streamInfoHandle)[i];
+ if (!si->baseGranulePosFound) {
+ found_all = false;
+ break;
+ }
+ }
+
+ return found_all;
+}
+
+#define TIME_SUBSEC_EARLIER(t1, t1ss, t2, t2ss) (((t1) < (t2)) || (((t1) == (t2)) && ((t1ss) < (t2ss))))
+
+static void set_group_base(OggImportGlobalsPtr globals) {
+ int i;
+ ComponentResult err = noErr;
+ TimeValue64 min = -1;
+ Float64 min_subsec = 0.0;
+
+ dbg_printf("[OI ] >> [%08lx] :: set_group_base()\n", (UInt32) globals);
+
+ for (i = 0; i < globals->streamCount; i++) {
+ StreamInfoPtr si = &(*globals->streamInfoHandle)[i];
+
+ dbg_printf("[OI ] [%08lx] :: set_group_base(): comparing %lld %lf < %lld %lf\n", (UInt32) globals, si->baseGranuleTime, si->baseGranuleTimeSubSecond,
+ min, min_subsec);
+
+ if (min == -1 || TIME_SUBSEC_EARLIER(si->baseGranuleTime, si->baseGranuleTimeSubSecond, min, min_subsec)) {
+ min = si->baseGranuleTime;
+ min_subsec = si->baseGranuleTimeSubSecond;
+ }
+ }
+
+ globals->currentGroupBase = min;
+ globals->currentGroupBaseSubSecond = min_subsec;
+
+ dbg_printf("[OI ] < [%08lx] :: set_group_base() = %lld %lf\n", (UInt32) globals, globals->currentGroupBase, globals->currentGroupBaseSubSecond);
+}
+
+static ComponentResult update_stream_base_offsets(OggImportGlobalsPtr globals) {
+ int i;
+ ComponentResult ret = noErr;
+
+ for (i = 0; i < globals->streamCount; i++) {
+ StreamInfoPtr si = &(*globals->streamInfoHandle)[i];
+
+ if (si->sfhf->update_group_gp != NULL) {
+ ret = (*si->sfhf->update_group_gp)(globals, si);
+
+ if (ret != noErr)
+ break;
+ }
+ }
+
+ return ret;
+}
+
static ComponentResult ProcessPage(OggImportGlobalsPtr globals, ogg_page *op) {
ComponentResult ret = noErr;
long serialno;
@@ -1113,6 +1183,10 @@
if (si != NULL) {
if (process_page) {
ret = ProcessStreamPage(globals, si, op);
+ if (globals->currentGroupBase < 0 && found_all_base_gps(globals)) {
+ set_group_base(globals);
+ update_stream_base_offsets(globals);
+ }
}
if (ogg_page_eos(op)) {
@@ -1122,6 +1196,8 @@
globals->groupStreamsFound = false;
globals->currentGroupOffset = -1;
globals->currentGroupOffsetSubSecond = 0.0;
+ globals->currentGroupBase = -1;
+ globals->currentGroupBaseSubSecond = 0.0;
}
}
}
@@ -1185,6 +1261,9 @@
globals->currentGroupOffsetSubSecond = (Float64) (globals->startTime % GetMovieTimeScale(globals->theMovie)) / (Float64) GetMovieTimeScale(globals->theMovie);
globals->groupStreamsFound = false;
+ globals->currentGroupBase = -1;
+ globals->currentGroupBaseSubSecond = 0.0;
+
if (!globals->sizeInitialised) {
result = XQTGetFileSize(globals);
}
Modified: trunk/xiph-qt/OggImport/src/importer_types.h
===================================================================
--- trunk/xiph-qt/OggImport/src/importer_types.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/importer_types.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -101,6 +101,11 @@
SampleDescriptionHandle sampleDesc;
ogg_int64_t lastGranulePos;
+ ogg_int64_t baseGranulePos;
+ Boolean baseGranulePosFound;
+ TimeValue64 baseGranuleTime;
+ Float64 baseGranuleTimeSubSecond;
+ Boolean groupBaseOffsetApplied;
TimeValue incompleteCompensation;
@@ -167,6 +172,9 @@
TimeValue currentGroupOffset;
Float64 currentGroupOffsetSubSecond; // same as with timeLoaded
+ TimeValue64 currentGroupBase;
+ Float64 currentGroupBaseSubSecond; // same as with timeLoaded
+
long newMovieFlags;
ComponentInstance dataReader;
@@ -247,7 +255,9 @@
typedef ComponentResult (*granulepos_to_time) (StreamInfo *si, ogg_int64_t *gp, TimeRecord *time);
+typedef ComponentResult (*update_group_granulepos) (OggImportGlobals *globals, StreamInfo *si);
+
typedef struct stream_format_handle_funcs {
process_stream_page process_page;
@@ -264,8 +274,10 @@
clear_stream clear;
granulepos_to_time gp_to_time;
+
+ update_group_granulepos update_group_gp;
} stream_format_handle_funcs;
-#define HANDLE_FUNCTIONS__NULL { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+#define HANDLE_FUNCTIONS__NULL { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
#endif /* __importer_types_h__ */
Modified: trunk/xiph-qt/OggImport/src/samplerefs.c
===================================================================
--- trunk/xiph-qt/OggImport/src/samplerefs.c 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/samplerefs.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -124,3 +124,23 @@
return err;
}
+
+ComponentResult _add_first_duration(StreamInfo *si, TimeValue duration)
+{
+ ComponentResult err = noErr;
+ SampleReference64Record *srptr = NULL;
+
+ if (si->sample_refs_count < 1)
+ return -1;
+
+ srptr = &si->sample_refs[0];
+
+ dbg_printf("[OIsr] =! _add_first_duration(): dur: %d += %d [%08lx, %08lx]\n", srptr->durationPerSample, duration,
+ (UInt32) si->sample_refs, (UInt32) srptr);
+ srptr->durationPerSample += duration;
+ si->sample_refs_duration += duration;
+
+
+ return err;
+}
+
Modified: trunk/xiph-qt/OggImport/src/samplerefs.h
===================================================================
--- trunk/xiph-qt/OggImport/src/samplerefs.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/samplerefs.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -37,6 +37,7 @@
extern ComponentResult _store_sample_reference(StreamInfo *si, SInt64 *dataOffset, int size, TimeValue duration, short smp_flags);
extern ComponentResult _commit_srefs(OggImportGlobals *globals, StreamInfo *si, Boolean *movie_changed);
+extern ComponentResult _add_first_duration(StreamInfo *si, TimeValue duration);
#endif /* __samplerefs_h__ */
Modified: trunk/xiph-qt/OggImport/src/stream_flac.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_flac.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_flac.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -51,7 +51,7 @@
#define HANDLE_FUNCTIONS__FLAC { &process_stream_page__flac, &recognize_header__flac, \
&verify_header__flac, &process_first_packet__flac, &create_sample_description__flac, \
- NULL, NULL, &initialize_stream__flac, &flush_stream__flac, &clear_stream__flac, NULL }
+ NULL, NULL, &initialize_stream__flac, &flush_stream__flac, &clear_stream__flac, NULL, NULL }
#endif /* __stream_flac_h__ */
Added: trunk/xiph-qt/OggImport/src/stream_private_vorbis.c
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_private_vorbis.c (rev 0)
+++ trunk/xiph-qt/OggImport/src/stream_private_vorbis.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -0,0 +1,105 @@
+/*
+ * stream_types_vorbis.h
+ *
+ * Definition of private Vorbis specific data structures.
+ *
+ *
+ * Copyright (c) 2009 Arek Korbik
+ *
+ * This file is part of XiphQT, the Xiph QuickTime Components.
+ *
+ * XiphQT is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * XiphQT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with XiphQT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ * Last modified: $Id$
+ *
+ */
+
+
+#include "stream_vorbis.h"
+#include "debug.h"
+
+
+int
+vorbis_private_extract_info(StreamInfo *si)
+{
+ StreamPrivate__vorbis *info = &(si->si_vorbis.private);
+ _codec_setup_info *ci = (_codec_setup_info *) si->si_vorbis.vi.codec_setup;
+ int i, size;
+
+ long short_size = ci->blocksizes[0];
+ long long_size = ci->blocksizes[1];
+
+ size = info->num_modes = ci->modes;
+
+ i = -1;
+ while ((1 << (++i)) < size);
+ info->mask_modes = (1 << i) - 1;
+
+ for (i = 0; i < size; i++) {
+ info->mode_sizes[i] = (ci->mode_param[i]->blockflag ?
+ long_size : short_size);
+ }
+
+ return 0;
+}
+
+static long
+_vorbis_private_packet_duration(StreamInfo *si, ogg_packet *current,
+ ogg_packet *previous)
+{
+ StreamPrivate__vorbis *info = &(si->si_vorbis.private);
+ int mode = (current->packet[0] >> 1) & info->mask_modes;
+ int current_size = info->mode_sizes[mode];
+
+ mode = (previous->packet[0] >> 1) & info->mask_modes;
+
+ return (info->mode_sizes[mode] + current_size) / 4;
+}
+
+long
+vorbis_private_page_duration(StreamInfo *si /*, ogg_page *og */)
+{
+ long duration = 0;
+ int ovret = -1;
+ ogg_packet p1, p2;
+ ogg_packet *previous = NULL;
+ ogg_packet *current = &p1;
+ ogg_packet *other = &p2;
+
+ while (ovret < 0) {
+ ovret = ogg_stream_packetout(&si->os, previous);
+ }
+
+ if (ovret == 0)
+ return -1;
+
+ while (1) {
+ ovret = ogg_stream_packetout(&si->os, current);
+ if (ovret < 0)
+ continue;
+ else if (ovret < 1)
+ break;
+ if (previous != NULL) {
+ duration += _vorbis_private_packet_duration(si, current, previous);
+ }
+
+ previous = current;
+ current = other;
+ other = (other == &p1 ? &p2 : &p1);
+ };
+
+ return duration;
+}
Property changes on: trunk/xiph-qt/OggImport/src/stream_private_vorbis.c
___________________________________________________________________
Added: svn:keywords
+ Id
Added: trunk/xiph-qt/OggImport/src/stream_private_vorbis.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_private_vorbis.h (rev 0)
+++ trunk/xiph-qt/OggImport/src/stream_private_vorbis.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -0,0 +1,100 @@
+/*
+ * stream_types_vorbis.h
+ *
+ * Definition of private Vorbis specific data structures.
+ *
+ *
+ * Copyright (c) 2009 Arek Korbik
+ *
+ * This file is part of XiphQT, the Xiph QuickTime Components.
+ *
+ * XiphQT is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * XiphQT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with XiphQT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ * Last modified: $Id$
+ *
+ */
+
+
+#if !defined(__stream_private_vorbis_h__)
+#define __stream_private_vorbis_h__
+
+
+/* The following two structures were almost literally copied from
+ codec_internal.h in libvorbis, at version 1.2.3, and need to be in
+ sync with the libvorbis linked against - otherwise things will
+ break horribly.
+
+ (Yes, I wish there was a cleaner way of getting the needed info...)
+*/
+
+typedef struct {
+ int blockflag;
+ int windowtype;
+ int transformtype;
+ int mapping;
+} _vorbis_info_mode;
+
+typedef struct _codec_setup_info {
+
+ /* Vorbis supports only short and long blocks, but allows the
+ encoder to choose the sizes */
+
+ long blocksizes[2];
+
+ /* modes are the primary means of supporting on-the-fly different
+ blocksizes, different channel mappings (LR or M/A),
+ different residue backends, etc. Each mode consists of a
+ blocksize flag and a mapping (along with the mapping setup */
+
+ int modes;
+ int maps;
+ int floors;
+ int residues;
+ int books;
+ int psys; /* encode only */
+
+ _vorbis_info_mode *mode_param[64];
+ int map_type[64];
+
+#if 0 /* we don't need the rest, so... */
+ vorbis_info_mapping *map_param[64];
+ int floor_type[64];
+ vorbis_info_floor *floor_param[64];
+ int residue_type[64];
+ vorbis_info_residue *residue_param[64];
+ static_codebook *book_param[256];
+ codebook *fullbooks;
+
+ vorbis_info_psy *psy_param[4]; /* encode only */
+ vorbis_info_psy_global psy_g_param;
+
+ bitrate_manager_info bi;
+ highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a
+ highly redundant structure, but
+ improves clarity of program flow. */
+ int halfrate_flag; /* painless downsample for decode */
+#endif /* 0 */
+} _codec_setup_info;
+
+
+typedef struct {
+ int num_modes;
+ int mask_modes;
+ long mode_sizes[64];
+} StreamPrivate__vorbis;
+
+
+#endif /* __stream_private_vorbis_h__ */
Property changes on: trunk/xiph-qt/OggImport/src/stream_private_vorbis.h
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: trunk/xiph-qt/OggImport/src/stream_speex.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_speex.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_speex.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -49,7 +49,7 @@
#define HANDLE_FUNCTIONS__SPEEX { &process_stream_page__speex, &recognize_header__speex, \
&verify_header__speex, &process_first_packet__speex, &create_sample_description__speex, \
- NULL, NULL, &initialize_stream__speex, &flush_stream__speex, &clear_stream__speex, NULL }
+ NULL, NULL, &initialize_stream__speex, &flush_stream__speex, &clear_stream__speex, NULL, NULL }
#endif /* __stream_vorbis_h__ */
Modified: trunk/xiph-qt/OggImport/src/stream_theora.c
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_theora.c 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_theora.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -83,6 +83,56 @@
return a;
}
+/* TEMPORARILY here */
+long
+theora_private_page_duration(StreamInfo *si /*, ogg_page *og */)
+{
+ long count = 0;
+ int oret = 0;
+ ogg_packet op;
+
+ while (1) {
+ oret = ogg_stream_packetout(&si->os, &op);
+ if (oret < 0)
+ continue;
+ else if (oret < 1)
+ break;
+ count += 1;
+ };
+
+ return count;
+}
+
+
+static void _gp_to_time_subsec(StreamInfo *si, ogg_int64_t gp, TimeValue64 *ts, Float64 *subsec)
+{
+ ogg_int64_t frames = gp >> si->si_theora.granulepos_shift;
+ frames += gp - (frames << si->si_theora.granulepos_shift);
+
+ *ts = frames * si->si_theora.fps_framelen / si->rate;
+ *subsec = (Float64) (frames - *ts * si->rate / si->si_theora.fps_framelen) * (Float64) si->si_theora.fps_framelen / (Float64) si->rate;
+}
+
+static void _find_base_gp(StreamInfo *si, ogg_page *opg)
+{
+ ogg_int64_t grpos = ogg_page_granulepos(opg);
+ if (grpos >= 0) {
+ ogg_int64_t duration = theora_private_page_duration(si); // will use page that's been recently pagein-ed, assumes
+ // we've been consistently packeting-out so far...
+ dbg_printf("---/t / page duration: %lld, %lld (%lld)\n", duration, ogg_page_granulepos(opg), si->lastGranulePos);
+ if (duration >= 0) {
+ si->baseGranulePos = grpos - (duration << si->si_theora.granulepos_shift); // subtracting from the "frames at last keyframe" part directly
+ if (si->baseGranulePos < 0)
+ si->baseGranulePos = 0;
+ _gp_to_time_subsec(si, si->baseGranulePos, &si->baseGranuleTime, &si->baseGranuleTimeSubSecond);
+ si->baseGranulePosFound = true;
+ dbg_printf("---/t / found base grpos: %lld, %lf\n", si->baseGranuleTime, si->baseGranuleTimeSubSecond);
+ }
+ } else {
+ dbg_printf("---/t / page no duration: %lld (nr: %ld) (%lld)\n", ogg_page_granulepos(opg), ogg_page_pageno(opg), si->lastGranulePos);
+ }
+}
+
int recognize_header__theora(ogg_page *op)
{
dbg_printf("! -- - theora_recognise_header: '%4.4s'\n", ((char *)op->body) + 1);
@@ -285,6 +335,13 @@
case kTStateReadingCodebooks:
ogg_stream_pagein(&si->os, opg);
break;
+
+ case kTStateReadingFirstPacket:
+ case kTStateReadingPackets:
+ if (!si->baseGranulePosFound)
+ ogg_stream_pagein(&si->os, opg);
+ break;
+
default:
break;
}
@@ -357,14 +414,13 @@
break;
case kTStateReadingFirstPacket:
- if (ogg_page_pageno(opg) > 3) {
- si->lastGranulePos = ogg_page_granulepos(opg);
- dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
- loop = false;
+ si->lastGranulePos = 0;
- if (si->lastGranulePos < 0)
- si->lastGranulePos = 0;
- }
+ _find_base_gp(si, opg);
+
+ if (si->baseGranulePosFound)
+ si->lastGranulePos = si->baseGranulePos;
+
si->si_theora.state = kTStateReadingPackets;
break;
@@ -377,13 +433,13 @@
int i, segments;
Boolean continued = ogg_page_continued(opg);
TimeValue durationPerSample = 0;
- ogg_int64_t last_packet_pos = si->lastGranulePos >> si->si_theora.granulepos_shift;
- last_packet_pos += si->lastGranulePos - (last_packet_pos << si->si_theora.granulepos_shift);
- loop = false;
- if (ovret < 0) {
- ret = invalidMedia;
- break;
+ if (!si->baseGranulePosFound) {
+ _find_base_gp(si, opg);
+
+ if (si->baseGranulePosFound) {
+ si->lastGranulePos = si->baseGranulePos;
+ }
}
if (continued)
@@ -467,7 +523,7 @@
}
if (!globals->usingIdle) {
- if (si->sample_refs_count >= kTSRefsInitial)
+ if (si->sample_refs_count >= kTSRefsInitial && si->baseGranulePosFound)
ret = _commit_srefs(globals, si, &movie_changed);
}
@@ -493,6 +549,11 @@
ComponentResult err = noErr;
Boolean movie_changed = false;
+ if (!si->baseGranulePosFound) {
+ dbg_printf("[OIv ] = [%08lx] :: flush_stream() - asked to flush but still no base grpos!!\n", (UInt32) globals);
+ return err;
+ }
+
err = _commit_srefs(globals, si, &movie_changed);
if (movie_changed && notify)
@@ -516,3 +577,44 @@
return err;
};
+
+ComponentResult update_group_gp__theora(OggImportGlobals *globals, StreamInfo *si)
+{
+ ComponentResult ret = noErr;
+ TimeValue offset;
+ Float64 offset_subsec;
+
+ if (si->groupBaseOffsetApplied)
+ return ret;
+
+ if (globals->currentGroupBase == si->baseGranuleTime && globals->currentGroupBaseSubSecond == si->baseGranuleTimeSubSecond)
+ return ret;
+
+ offset = si->baseGranuleTime - globals->currentGroupBase;
+ offset_subsec = si->baseGranuleTimeSubSecond - globals->currentGroupBaseSubSecond;
+ if (offset_subsec < 0.0) {
+ offset -= 1;
+ offset_subsec += 1.0;
+ }
+
+ dbg_printf("---/t / offset diff: %ld %lf\n", offset, offset_subsec);
+
+ if (offset > 0) {
+ si->streamOffset += offset * GetMovieTimeScale(globals->theMovie);
+ dbg_printf("---/t / adjusting streamOffset: %ld (dt: %ld)\n", si->streamOffset, offset * GetMovieTimeScale(globals->theMovie));
+ }
+
+ if (offset_subsec > 0.0) {
+ dbg_printf("---/t / adjusting streamOffsetSamples: %ld (dt: %ld)\n", si->streamOffsetSamples, (UInt32) (offset_subsec * si->rate));
+ if (_add_first_duration(si, offset_subsec * si->rate) != noErr)
+ si->streamOffsetSamples += offset_subsec * si->rate;
+ }
+
+ si->groupBaseOffsetApplied = true;
+
+ dbg_printf("[OIt ] = [%08lx] :: update_group_gp(): group base: (%lld, %lf) stream base: (%lld, %lf)\n", (UInt32) globals,
+ globals->currentGroupBase, globals->currentGroupBaseSubSecond, si->baseGranuleTime, si->baseGranuleTimeSubSecond);
+
+
+ return ret;
+};
Modified: trunk/xiph-qt/OggImport/src/stream_theora.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_theora.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_theora.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -51,11 +51,12 @@
extern ComponentResult flush_stream__theora(OggImportGlobals *globals, StreamInfo *si, Boolean notify);
extern ComponentResult granulepos_to_time__theora(StreamInfo *si, ogg_int64_t *gp, TimeRecord *time);
+extern ComponentResult update_group_gp__theora(OggImportGlobals *globals, StreamInfo *si);
#define HANDLE_FUNCTIONS__THEORA { &process_stream_page__theora, &recognize_header__theora, \
&verify_header__theora, &process_first_packet__theora, &create_sample_description__theora, \
&create_track__theora, &create_track_media__theora, &initialize_stream__theora, flush_stream__theora, \
- &clear_stream__theora, &granulepos_to_time__theora }
+ &clear_stream__theora, &granulepos_to_time__theora, &update_group_gp__theora }
#endif /* __stream_theora_h__ */
Modified: trunk/xiph-qt/OggImport/src/stream_types_vorbis.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_types_vorbis.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_types_vorbis.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -34,6 +34,7 @@
#if !defined(_NO_VORBIS_SUPPORT)
#include <Vorbis/codec.h>
+#include "stream_private_vorbis.h"
typedef enum VorbisImportStates {
kVStateInitial,
@@ -54,6 +55,8 @@
vorbis_info vi;
vorbis_comment vc;
+
+ StreamPrivate__vorbis private;
} StreamInfo__vorbis;
Modified: trunk/xiph-qt/OggImport/src/stream_vorbis.c
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_vorbis.c 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_vorbis.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -39,8 +39,32 @@
#include "data_types.h"
#include "samplerefs.h"
+#include "utils.h"
+extern int vorbis_private_extract_info(StreamInfo *si);
+extern long vorbis_private_page_duration(StreamInfo *si);
+
+static void _find_base_gp(StreamInfo *si, ogg_page *opg)
+{
+ ogg_int64_t grpos = ogg_page_granulepos(opg);
+ if (grpos >= 0) {
+ ogg_int64_t duration = vorbis_private_page_duration(si); // will use page that's been recently pagein-ed, assumes
+ // we've been consistently packeting-out so far...
+ dbg_printf("---/v / page duration: %lld, %lld (%lld)\n", duration, ogg_page_granulepos(opg), si->lastGranulePos);
+ if (duration >= 0) {
+ si->baseGranulePos = grpos - duration;
+ if (si->baseGranulePos < 0)
+ si->baseGranulePos = 0;
+ gp_to_time_subsec(si->rate, si->baseGranulePos, &si->baseGranuleTime, &si->baseGranuleTimeSubSecond);
+ si->baseGranulePosFound = true;
+ dbg_printf("---/v / found base grpos: %lld, %lf\n", si->baseGranuleTime, si->baseGranuleTimeSubSecond);
+ }
+ } else {
+ dbg_printf("---/v / page no duration: %lld (nr: %ld) (%lld)\n", ogg_page_granulepos(opg), ogg_page_pageno(opg), si->lastGranulePos);
+ }
+}
+
int recognize_header__vorbis(ogg_page *op)
{
if (!strncmp("\1vorbis", (char *)op->body, 7))
@@ -205,6 +229,13 @@
case kVStateReadingCodebooks:
ogg_stream_pagein(&si->os, opg);
break;
+
+ case kVStateReadingFirstPacket:
+ case kVStateReadingPackets:
+ if (!si->baseGranulePosFound)
+ ogg_stream_pagein(&si->os, opg);
+ break;
+
default:
break;
}
@@ -261,18 +292,20 @@
dbg_printf("---/ / streamOffset: [%ld, %ld], %lg\n", si->streamOffset, si->streamOffsetSamples, globals->currentGroupOffsetSubSecond);
si->incompleteCompensation = 0;
loop = false; //there should be an end of page here according to specs...
+
+ vorbis_private_extract_info(si);
}
break;
case kVStateReadingFirstPacket:
- if (ogg_page_pageno(opg) > 3) {
- si->lastGranulePos = ogg_page_granulepos(opg);
- dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
- loop = false;
+ si->lastGranulePos = 0;
- if (si->lastGranulePos < 0)
- si->lastGranulePos = 0;
- }
+ _find_base_gp(si, opg);
+
+ if (si->baseGranulePosFound)
+ si->lastGranulePos = si->baseGranulePos;
+
+ // now update the sound desc
{
unsigned long pagenoatom[3] = { EndianU32_NtoB(sizeof(pagenoatom)), EndianU32_NtoB(kCookieTypeVorbisFirstPageNo),
EndianU32_NtoB(ogg_page_pageno(opg)) };
@@ -298,6 +331,16 @@
TimeValue duration = pos - si->lastGranulePos;
short smp_flags = 0;
+ if (!si->baseGranulePosFound) {
+ _find_base_gp(si, opg);
+
+ if (si->baseGranulePosFound) {
+ si->lastGranulePos = si->baseGranulePos;
+ // update current page duration as we now know it
+ duration = pos - si->lastGranulePos;
+ }
+ }
+
if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
smp_flags |= mediaSampleNotSync;
@@ -317,6 +360,9 @@
if (si->insertTime == 0 && si->streamOffsetSamples > 0) {
dbg_printf(" - :++: increasing duration (%ld) by sampleOffset: %ld\n", duration, si->streamOffsetSamples);
duration += si->streamOffsetSamples;
+
+ si->streamOffsetSamples = 0;
+
}
ret = _store_sample_reference(si, &globals->dataOffset, len, duration, smp_flags);
@@ -327,7 +373,7 @@
if (!globals->usingIdle) {
//if (si->sample_refs_count >= si->sample_refs_size)
- if (si->sample_refs_count >= kVSRefsInitial)
+ if (si->sample_refs_count >= kVSRefsInitial && si->baseGranulePosFound)
ret = _commit_srefs(globals, si, &movie_changed);
}
@@ -353,6 +399,11 @@
ComponentResult ret = noErr;
Boolean movie_changed = false;
+ if (!si->baseGranulePosFound) {
+ dbg_printf("[OIv ] = [%08lx] :: flush_stream() - asked to flush but still no base grpos!!\n", (UInt32) globals);
+ return ret;
+ }
+
ret = _commit_srefs(globals, si, &movie_changed);
if (movie_changed && notify)
@@ -360,3 +411,43 @@
return ret;
};
+
+ComponentResult update_group_gp__vorbis(OggImportGlobals *globals, StreamInfo *si)
+{
+ ComponentResult ret = noErr;
+ TimeValue offset;
+ Float64 offset_subsec;
+
+ if (si->groupBaseOffsetApplied)
+ return ret;
+
+ if (globals->currentGroupBase == si->baseGranuleTime && globals->currentGroupBaseSubSecond == si->baseGranuleTimeSubSecond)
+ return ret;
+
+ offset = si->baseGranuleTime - globals->currentGroupBase;
+ offset_subsec = si->baseGranuleTimeSubSecond - globals->currentGroupBaseSubSecond;
+ if (offset_subsec < 0.0) {
+ offset -= 1;
+ offset_subsec += 1.0;
+ }
+
+ dbg_printf("---/v / offset diff: %ld %lf\n", offset, offset_subsec);
+
+ if (offset > 0) {
+ si->streamOffset += offset * GetMovieTimeScale(globals->theMovie);
+ dbg_printf("---/v / adjusting streamOffset: %ld (dt: %ld)\n", si->streamOffset, offset * GetMovieTimeScale(globals->theMovie));
+ }
+
+ if (offset_subsec > 0.0) {
+ dbg_printf("---/v / adjusting streamOffsetSamples: %ld (dt: %ld)\n", si->streamOffsetSamples, (UInt32) (offset_subsec * si->rate));
+ if (_add_first_duration(si, offset_subsec * si->rate) != noErr)
+ si->streamOffsetSamples += offset_subsec * si->rate;
+ }
+
+ si->groupBaseOffsetApplied = true;
+
+ dbg_printf("[OIv ] = [%08lx] :: update_group_gp(): group base: (%lld, %lf) stream base: (%lld, %lf)\n", (UInt32) globals,
+ globals->currentGroupBase, globals->currentGroupBaseSubSecond, si->baseGranuleTime, si->baseGranuleTimeSubSecond);
+
+ return ret;
+};
Modified: trunk/xiph-qt/OggImport/src/stream_vorbis.h
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_vorbis.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/stream_vorbis.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -46,10 +46,12 @@
extern int process_first_packet__vorbis(StreamInfo *si, ogg_page *op, ogg_packet *opckt);
extern ComponentResult process_stream_page__vorbis(OggImportGlobals *globals, StreamInfo *si, ogg_page *opg);
extern ComponentResult flush_stream__vorbis(OggImportGlobals *globals, StreamInfo *si, Boolean notify);
+extern ComponentResult update_group_gp__vorbis(OggImportGlobals *globals, StreamInfo *si);
#define HANDLE_FUNCTIONS__VORBIS { &process_stream_page__vorbis, &recognize_header__vorbis, \
&verify_header__vorbis, &process_first_packet__vorbis, &create_sample_description__vorbis, \
- NULL, NULL, &initialize_stream__vorbis, &flush_stream__vorbis, &clear_stream__vorbis, NULL }
+ NULL, NULL, &initialize_stream__vorbis, &flush_stream__vorbis, &clear_stream__vorbis, NULL, \
+ &update_group_gp__vorbis }
#endif /* __stream_vorbis_h__ */
Modified: trunk/xiph-qt/OggImport/src/utils.c
===================================================================
--- trunk/xiph-qt/OggImport/src/utils.c 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/utils.c 2009-08-01 23:30:49 UTC (rev 16390)
@@ -84,3 +84,9 @@
}
}
}
+
+void gp_to_time_subsec(int rate, ogg_int64_t gp, TimeValue64 *ts, Float64 *subsec)
+{
+ *ts = gp / rate;
+ *subsec = (Float64) (gp - *ts * rate) / (Float64) rate;
+}
Modified: trunk/xiph-qt/OggImport/src/utils.h
===================================================================
--- trunk/xiph-qt/OggImport/src/utils.h 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/OggImport/src/utils.h 2009-08-01 23:30:49 UTC (rev 16390)
@@ -38,6 +38,7 @@
extern int unpack_vorbis_comments(vorbis_comment *vc, const void *data, UInt32 data_size);
extern void find_last_page_GP(const unsigned char *data, UInt32 data_size,
ogg_int64_t *gp, long *serialno);
+extern void gp_to_time_subsec(int rate, ogg_int64_t gp, TimeValue64 *ts, Float64 *subsec);
#endif /* __ogg_utils_h__ */
Modified: trunk/xiph-qt/build-macosx/XiphQT.xcodeproj/project.pbxproj
===================================================================
--- trunk/xiph-qt/build-macosx/XiphQT.xcodeproj/project.pbxproj 2009-08-01 22:23:02 UTC (rev 16389)
+++ trunk/xiph-qt/build-macosx/XiphQT.xcodeproj/project.pbxproj 2009-08-01 23:30:49 UTC (rev 16390)
@@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */
09C8F66C0C82FC7D00F72188 /* libtheoradec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 09C8F6460C82FBE500F72188 /* libtheoradec.a */; };
+ 37B42EC70FF5453E00FC88AE /* stream_private_vorbis.c in Sources */ = {isa = PBXBuildFile; fileRef = 37B42EC50FF5453E00FC88AE /* stream_private_vorbis.c */; };
+ 37B42EC80FF5453E00FC88AE /* stream_private_vorbis.c in Sources */ = {isa = PBXBuildFile; fileRef = 37B42EC50FF5453E00FC88AE /* stream_private_vorbis.c */; };
37CA8E6D0DD74A65005C8CB6 /* libtheoradec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 09C8F6460C82FBE500F72188 /* libtheoradec.a */; };
7326B5130B5AC44B004CE9D3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
7326B5160B5AC44B004CE9D3 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 7374489F0B19EC05002B059E /* common.c */; };
@@ -391,6 +393,8 @@
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
08EA7FFBFE8413EDC02AAC07 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
32BAE0B30371A71500C91783 /* XiphQT_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XiphQT_Prefix.pch; sourceTree = "<group>"; };
+ 37B42EC50FF5453E00FC88AE /* stream_private_vorbis.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = stream_private_vorbis.c; path = ../OggImport/src/stream_private_vorbis.c; sourceTree = SOURCE_ROOT; };
+ 37B42EC60FF5453E00FC88AE /* stream_private_vorbis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stream_private_vorbis.h; path = ../OggImport/src/stream_private_vorbis.h; sourceTree = SOURCE_ROOT; };
7326B5510B5AC44B004CE9D3 /* XiphQT (decoders).component */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "XiphQT (decoders).component"; sourceTree = BUILT_PRODUCTS_DIR; };
7326B5520B5AC44B004CE9D3 /* Info (decoders).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (decoders).plist"; sourceTree = "<group>"; };
73271C820B610B2400175874 /* RingBufferTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RingBufferTests.h; path = ../tests/common/RingBufferTests.h; sourceTree = SOURCE_ROOT; };
@@ -750,6 +754,8 @@
737448C10B19EC3E002B059E /* vorbis */ = {
isa = PBXGroup;
children = (
+ 37B42EC50FF5453E00FC88AE /* stream_private_vorbis.c */,
+ 37B42EC60FF5453E00FC88AE /* stream_private_vorbis.h */,
737448B00B19EC05002B059E /* stream_types_vorbis.h */,
737448B10B19EC05002B059E /* stream_vorbis.c */,
737448B20B19EC05002B059E /* stream_vorbis.h */,
@@ -1351,6 +1357,7 @@
7326B5320B5AC44B004CE9D3 /* CAOggFLACDecoder.cpp in Sources */,
7326B5330B5AC44B004CE9D3 /* flac_entrypoints.cpp in Sources */,
7373EDD20B7BDCAA00591836 /* samplerefs.c in Sources */,
+ 37B42EC80FF5453E00FC88AE /* stream_private_vorbis.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1415,6 +1422,7 @@
73744CAE0B1A3D07002B059E /* stream_audio.c in Sources */,
73744CB20B1A3D07002B059E /* stream_video.c in Sources */,
7373EDD00B7BDCAA00591836 /* samplerefs.c in Sources */,
+ 37B42EC70FF5453E00FC88AE /* stream_private_vorbis.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
More information about the commits
mailing list