Bug 512328 - Update liboggplay to rev 404316e595. r=doublec

This commit is contained in:
Chris Pearce 2009-09-24 16:22:23 +12:00
parent 049a9fbdc8
commit 06cefa67d6
55 changed files with 2492 additions and 2021 deletions

View File

@ -855,11 +855,11 @@ void nsOggDecodeStateMachine::HandleVideoData(FrameData* aFrame, int aTrackNum,
if (!aVideoHeader)
return;
int y_width;
int y_height;
int y_width = 0;
int y_height = 0;
oggplay_get_video_y_size(mPlayer, aTrackNum, &y_width, &y_height);
int uv_width;
int uv_height;
int uv_width = 0;
int uv_height = 0;
oggplay_get_video_uv_size(mPlayer, aTrackNum, &uv_width, &uv_height);
if (y_width >= MAX_VIDEO_WIDTH || y_height >= MAX_VIDEO_HEIGHT) {
@ -1720,19 +1720,22 @@ nsresult nsOggDecodeStateMachine::Run()
if (mState != DECODER_STATE_COMPLETED)
continue;
}
if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) {
// We were playing, we need to move the current time to the end of
// media, and send an 'ended' event.
mCurrentFrameTime += mCallbackPeriod;
if (mDuration >= 0) {
mCurrentFrameTime = PR_MAX(mCurrentFrameTime, mDuration / 1000.0);
}
// Set the right current time
mCurrentFrameTime += mCallbackPeriod;
if (mDuration >= 0) {
mCurrentFrameTime = PR_MAX(mCurrentFrameTime, mDuration / 1000.0);
mon.Exit();
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
mon.Enter();
}
mon.Exit();
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
mon.Enter();
while (mState == DECODER_STATE_COMPLETED) {
mon.Wait();
}

View File

@ -8,6 +8,11 @@ var gSmallTests = [
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240 },
{ name:"bug499519.ogv", type:"video/ogg", duration:0.24 },
{ name:"bug506094.ogv", type:"video/ogg", duration:0 },
{ name:"bug501279.ogg", type:"audio/ogg", duration:0 },
{ name:"bug498855-1.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug498855-2.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug498855-3.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug504644.ogv", type:"video/ogg", duration:1.56 },
{ name:"bogus.duh", type:"bogus/duh" }
];
@ -45,15 +50,10 @@ var gPlayTests = [
// Put files of the same type together in this list so if something crashes
// we have some idea of which backend is responsible.
var gErrorTests = [
{ name:"bug495129.ogv", type:"video/ogg", duration:2.52 },
{ name:"bug498855-1.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug498855-2.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug498855-3.ogv", type:"video/ogg", duration:0.2 },
{ name:"bug501279.ogg", type:"audio/ogg", duration:0 },
{ name:"bug504644.ogv", type:"video/ogg", duration:1.56 },
{ name:"bogus.wav", type:"audio/x-wav" },
{ name:"bogus.ogv", type:"video/ogg" },
{ name:"448636.ogv", type:"video/ogg" },
{ name:"bug495129.ogv", type:"video/ogg", duration:2.52 },
{ name:"bogus.duh", type:"bogus/duh" }
];

View File

@ -22,8 +22,8 @@ For the core library (liboggplay), you need
* liboggz and libfishsound -- from svn.annodex.net:
svn co http://svn.annodex.net/liboggz/trunk liboggz
svn co http://svn.annodex.net/libfishsound/trunk libfishsound
git clone git://git.xiph.org/liboggz.git
git clone git://git.xiph.org/libfishsound.git
Optionally, for Kate stream support, you need

View File

@ -5,7 +5,7 @@ the Mozilla build system.
git://git.xiph.org/liboggplay.git
The git commit ID used was b4a7efa06d46596515071490cb255c3548d90371.
The git commit ID used was 404316e5957370b3c854a86910c237c90746c325.
The following local patches have been applied:
@ -13,37 +13,26 @@ endian: pick up NSPR's little/big endian defines in oggplay's config.h.
bug481921: fix a crash in oggplay_callback_info_prepare().
trac466: Fix for infinite loop in liboggplay when running decoder on its own thread. Cherry picked from liboggplay git commit e6871f.
bug492436: Fix for that bug cherry picked from liboggplay git commit 4b97ad.
bug493140: Fix for offsets not being used.
aspect-ratio: Adds oggplay_get_video_aspect_ratio, used for bug 480058.
bug493678.patch: fix for infinite loop in oggplay_step_decode. See bug 493678.
bug493224.patch: Fix for bug 493224.
seek_to_key_frame.patch: Adds oggplay_seek_to_keyframe(), as per bug 463358.
bug488951: Fix for YUV conversion for odd sized frames. Cherrypicked from
upstream commits dabde8, 683f23, and 4d7581.
bug488951_fix_yuv: Additional fixes to YUV conversion that have not been
upstreamed yet.
bug488951_fix_yuv_2: Additional fix to YUV conversion for odd height videos
that has not been upstreamed yet.
bug495129a.patch: Fix from liboggplay commit 6c8e11.
bug495129b.patch: Fix from liboggplay commit 3602bf.
bug487519.patch: Fix for bug 487519.
oggplay_os2.patch: Bug 448918 - add OS/2 support (this patch should be
removed when OS/2 support is added upstream)
bug498815.patch: Fix for bug 498815.
bug498824.patch: Fix for bug 498824.
bug496529.patch: Fix bug 496529.
bug500311.patch: Fix crash during decoder initialization.
faster_seek.patch: Fix for bug 501031, make seeking faster over HTTP.
fix-17ef4ca82df28.patch: Fix oggplay_callback_predetected() to return
value interpreted as success upon success.
Fixes liboggplay changeset 17ef4ca82df28.
handle-read-errors.patch: Make oggplay_initialise() handle closing of stream
while reading. Prevents infinite loop. Further fix
to 17ef4ca82df28.

View File

@ -1,11 +1,11 @@
diff --git a/media/liboggplay/include/oggplay/oggplay.h b/media/liboggplay/include/oggplay/oggplay.h
--- a/media/liboggplay/include/oggplay/oggplay.h
+++ b/media/liboggplay/include/oggplay/oggplay.h
@@ -110,16 +110,19 @@ oggplay_get_audio_channels(OggPlay *me,
OggPlayErrorCode
oggplay_get_audio_samplerate(OggPlay *me, int track, int *samplerate);
@@ -226,16 +226,19 @@ oggplay_get_audio_samplerate(OggPlay *me
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num);
@ -13,7 +13,7 @@ diff --git a/media/liboggplay/include/oggplay/oggplay.h b/media/liboggplay/inclu
+oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_num);
+
+OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert);
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb);
OggPlayErrorCode
oggplay_get_kate_category(OggPlay *me, int track, const char** category);
@ -24,7 +24,7 @@ diff --git a/media/liboggplay/include/oggplay/oggplay.h b/media/liboggplay/inclu
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -280,16 +280,45 @@ oggplay_get_video_fps(OggPlay *me, int t
@@ -297,16 +297,45 @@ oggplay_get_video_fps(OggPlay *me, int t
(*fps_denom) = decode->video_info.fps_denominator;
(*fps_num) = decode->video_info.fps_numerator;
@ -62,7 +62,7 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/li
+}
+
+OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert) {
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb) {
OggPlayTheoraDecode *decode;
if (me == NULL) {

View File

@ -1,19 +1,30 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index 428faee..344599a 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -388,7 +388,13 @@ oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
@@ -543,16 +543,26 @@ oggplay_callback_audio (OGGZ * oggz, ogg
}
default:
/* there was no problem with decoding */
if (!common->num_header_packets) common->initialised |= 1;
break;
}
fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
op->e_o_s);
- fish_sound_decode (decoder->sound_handle, op->packet, op->bytes);
+ if (fish_sound_decode (decoder->sound_handle, op->packet, op->bytes) != 0) {
+ if (bytes_read < 0) {
+ printf("\nERROR HADNLING MISMATCH BETWEEN liboggplay AND mozilla\n\n");
+ // Unrecoverable error, disable track
+ op->e_o_s = 1;
+ common->active = 0;
+ common->player->active_tracks--;
+ return OGGZ_ERR_HOLE_IN_DATA;
+ }
+
+
if (decoder->sound_info.channels == 0) {
fish_sound_command(decoder->sound_handle, FISH_SOUND_GET_INFO,
&(decoder->sound_info), sizeof(FishSoundInfo));
}
if (op->e_o_s) {
common->active = 0;
common->player->active_tracks--;

View File

@ -1,564 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
@@ -42,76 +42,55 @@
*/
#include "oggplay_private.h"
#include "oggplay_yuv2rgb_template.h"
/* cpu extension detection */
#include "cpu.c"
-/* although we use cpu runtime detection, we still need these
- * macros as there's no way e.g. we could compile a x86 asm code
- * on a ppc machine and vica-versa
+/**
+ * yuv_convert_fptr type is a function pointer type for
+ * the various yuv-rgb converters
*/
-#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
-#include "oggplay_yuv2rgb_x86.c"
-#elif defined(__ppc__) || defined(__ppc64__)
-//altivec intristics only working with -maltivec gcc flag,
-//but we want runtime altivec detection, hence this has to be
-//fixed!
-//#include "oggplay_yuv2rgb_altivec.c"
-#endif
+typedef void (*yuv_convert_fptr) (const OggPlayYUVChannels *yuv,
+ OggPlayRGBChannels *rgb);
-static int yuv_initialized;
-static ogg_uint32_t cpu_features;
+/* it is useless to determine each YUV conversion run
+ * the cpu type/featurs, thus we save the conversion function
+ * pointers
+ */
+static struct OggPlayYUVConverters {
+ yuv_convert_fptr yuv2rgba; /**< YUV420 to RGBA */
+ yuv_convert_fptr yuv2bgra; /**< YUV420 to BGRA */
+ yuv_convert_fptr yuv2argb; /**< YUV420 to ARGB */
+} yuv_conv = {NULL, NULL, NULL};
/**
* vanilla implementation of YUV-to-RGB conversion.
*
* - using table-lookups instead of multiplication
* - avoid CLAMPing by incorporating
*
*/
-#define CLAMP(v) ((v) > 255 ? 255 : (v) < 0 ? 0 : (v))
-
#define prec 15
static const int CoY = (int)(1.164 * (1 << prec) + 0.5);
static const int CoRV = (int)(1.596 * (1 << prec) + 0.5);
static const int CoGU = (int)(0.391 * (1 << prec) + 0.5);
static const int CoGV = (int)(0.813 * (1 << prec) + 0.5);
static const int CoBU = (int)(2.018 * (1 << prec) + 0.5);
-static int CoefsGU[256];
+static int CoefsGU[256] = {0};
static int CoefsGV[256];
static int CoefsBU[256];
static int CoefsRV[256];
static int CoefsY[256];
-/**
- * Initialize the lookup-table for vanilla yuv to rgb conversion
- * and the cpu_features global.
- */
-static void
-init_yuv_converters()
-{
- int i;
-
- for(i = 0; i < 256; ++i)
- {
- CoefsGU[i] = -CoGU * (i - 128);
- CoefsGV[i] = -CoGV * (i - 128);
- CoefsBU[i] = CoBU * (i - 128);
- CoefsRV[i] = CoRV * (i - 128);
- CoefsY[i] = CoY * (i - 16) + (prec/2);
- }
-
- cpu_features = oc_cpu_flags_get();
- yuv_initialized = 1;
-}
+#define CLAMP(v) ((v) > 255 ? 255 : (v) < 0 ? 0 : (v))
#define VANILLA_YUV2RGB_PIXEL(y, ruv, guv, buv) \
r = (CoefsY[y] + ruv) >> prec; \
g = (CoefsY[y] + guv) >> prec; \
b = (CoefsY[y] + buv) >> prec; \
#define VANILLA_RGBA_OUT(out, r, g, b) \
out[0] = CLAMP(r); \
@@ -132,105 +111,155 @@ out[2] = CLAMP(g); \
out[3] = CLAMP(b);
#define VANILLA_ABGR_OUT(out, r, g, b) \
out[0] = 255; \
out[1] = CLAMP(b); \
out[2] = CLAMP(g); \
out[3] = CLAMP(r);
-/* yuv420p -> */
#define LOOKUP_COEFFS int ruv = CoefsRV[*pv]; \
int guv = CoefsGU[*pu] + CoefsGV[*pv]; \
int buv = CoefsBU[*pu]; \
int r, g, b;
+/* yuv420p -> */
#define CONVERT(OUTPUT_FUNC) LOOKUP_COEFFS \
- VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv);\
- OUTPUT_FUNC(dst, r, g, b); \
- VANILLA_YUV2RGB_PIXEL(py[1], ruv, guv, buv);\
- OUTPUT_FUNC((dst+4), r, g, b);
+ VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
+ OUTPUT_FUNC(dst, r, g, b) \
+ VANILLA_YUV2RGB_PIXEL(py[1], ruv, guv, buv) \
+ OUTPUT_FUNC((dst+4), r, g, b)
#define CLEANUP
-YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), 2, 8, 2, 1)
-YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), 2, 8, 2, 1)
-YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), 2, 8, 2, 1)
-YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), 2, 8, 2, 1)
+YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1)
+YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1)
+YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1)
+YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1)
#undef CONVERT
#undef CLEANUP
+/* although we use cpu runtime detection, we still need these
+ * macros as there's no way e.g. we could compile a x86 asm code
+ * on a ppc machine and vica-versa
+ */
+#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
+#include "x86/oggplay_yuv2rgb_x86.c"
+#elif defined(__ppc__) || defined(__ppc64__)
+//altivec intristics only working with -maltivec gcc flag,
+//but we want runtime altivec detection, hence this has to be
+//fixed!
+//#include "oggplay_yuv2rgb_altivec.c"
+#endif
+
+
+/**
+ * Initialize the lookup-table for vanilla yuv to rgb conversion.
+ */
+static void
+init_vanilla_coeffs (void)
+{
+ int i;
+
+ for(i = 0; i < 256; ++i)
+ {
+ CoefsGU[i] = -CoGU * (i - 128);
+ CoefsGV[i] = -CoGV * (i - 128);
+ CoefsBU[i] = CoBU * (i - 128);
+ CoefsRV[i] = CoRV * (i - 128);
+ CoefsY[i] = CoY * (i - 16) + (prec/2);
+ }
+}
+
+/**
+ * Initialize the function pointers in yuv_conv.
+ *
+ * Initialize the function pointers in yuv_conv, based on the
+ * the available CPU extensions.
+ */
+static void
+init_yuv_converters(void)
+{
+ ogg_uint32_t features = 0;
+
+ if ( yuv_conv.yuv2rgba == NULL )
+ {
+ init_vanilla_coeffs ();
+ features = oc_cpu_flags_get();
+#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
+#if defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
+ if (features & OC_CPU_X86_SSE2)
+ {
+ yuv_conv.yuv2rgba = yuv420_to_rgba_sse2;
+ yuv_conv.yuv2bgra = yuv420_to_bgra_sse2;
+ yuv_conv.yuv2argb = yuv420_to_argb_sse2;
+ return;
+ }
+ else
+#endif /* ATTRIBUTE_ALIGNED_MAX */
+ if (features & OC_CPU_X86_MMXEXT)
+ {
+ yuv_conv.yuv2rgba = yuv420_to_rgba_sse;
+ yuv_conv.yuv2bgra = yuv420_to_bgra_sse;
+ yuv_conv.yuv2argb = yuv420_to_argb_sse;
+ return;
+ }
+ else if (features & OC_CPU_X86_MMX)
+ {
+ yuv_conv.yuv2rgba = yuv420_to_rgba_mmx;
+ yuv_conv.yuv2bgra = yuv420_to_bgra_mmx;
+ yuv_conv.yuv2argb = yuv420_to_argb_mmx;
+ return;
+ }
+#elif defined(__ppc__) || defined(__ppc64__)
+ if (features & OC_CPU_PPC_ALTIVEC)
+ {
+ yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
+ yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
+ yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
+ return;
+ }
+#endif
+ /*
+ * no CPU extension was found... using vanilla converter, with respect
+ * to the endianness of the host
+ */
+#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
+ yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
+ yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
+ yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
+#else
+ yuv_conv.yuv2rgba = yuv420_to_rgba_vanilla;
+ yuv_conv.yuv2bgra = yuv420_to_bgra_vanilla;
+ yuv_conv.yuv2argb = yuv420_to_argb_vanilla;
+#endif
+ }
+}
+
+
void
oggplay_yuv2rgba(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb)
{
- if (!yuv_initialized)
+ if (yuv_conv.yuv2rgba == NULL)
init_yuv_converters();
-#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
-#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
- if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
- return yuv420_to_rgba_sse2(yuv, rgb);
-#endif
- if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
- return yuv420_to_rgba_mmx(yuv, rgb);
-#elif defined(__ppc__) || defined(__ppc64__)
- if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
- return yuv420_to_abgr_vanilla(yuv, rgb);
-#endif
-
-#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
- return yuv420_to_abgr_vanilla(yuv, rgb);
-#else
- return yuv420_to_rgba_vanilla(yuv, rgb);
-#endif
+ yuv_conv.yuv2rgba(yuv, rgb);
}
void
oggplay_yuv2bgra(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
- if (!yuv_initialized)
+ if (yuv_conv.yuv2bgra == NULL)
init_yuv_converters();
-#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
-#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
- if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
- return yuv420_to_bgra_sse2(yuv, rgb);
-#endif
- if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
- return yuv420_to_bgra_mmx(yuv, rgb);
-#elif defined(__ppc__) || defined(__ppc64__)
- if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
- return yuv420_to_argb_vanilla(yuv, rgb);
-#endif
-
-#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
- return yuv420_to_argb_vanilla(yuv, rgb);
-#else
- return yuv420_to_bgra_vanilla(yuv, rgb);
-#endif
+ yuv_conv.yuv2bgra(yuv, rgb);
}
void
oggplay_yuv2argb(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
- if (!yuv_initialized)
+ if (yuv_conv.yuv2argb == NULL)
init_yuv_converters();
-#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
-#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
- if (yuv->y_width % 16 == 0 && cpu_features & OC_CPU_X86_SSE2)
- return yuv420_to_argb_sse2(yuv, rgb);
-#endif
- if (yuv->y_width % 8 == 0 && cpu_features & OC_CPU_X86_MMX)
- return yuv420_to_argb_mmx(yuv, rgb);
-#elif defined(__ppc__) || defined(__ppc64__)
- if (yuv->y_width % 16 == 0 && yuv->y_height % 2 == 0 && cpu_features & OC_CPU_PPC_ALTIVEC)
- return yuv420_to_bgra_vanilla(yuv, rgb);
-#endif
-
-#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
- return yuv420_to_bgra_vanilla(yuv, rgb);
-#else
- return yuv420_to_argb_vanilla(yuv, rgb);
-#endif
+ yuv_conv.yuv2argb(yuv, rgb);
}
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
@@ -8,55 +8,80 @@
#define restrict __restrict__
#endif
#endif
/**
* Template for YUV to RGB conversion
*
* @param FUNC function name
- * @param CONVERT a macro that defines
+ * @param CONVERT a macro that defines the actual conversion function
+ * @param VANILLA_OUT
* @param NUM_PIXELS number of pixels processed in one iteration
* @param OUT_SHIFT number of pixels to shift after one iteration in rgb data stream
* @param Y_SHIFT number of pixels to shift after one iteration in Y data stream
* @param UV_SHIFT
*/
-#define YUV_CONVERT(FUNC, CONVERT, NUM_PIXELS, OUT_SHIFT, Y_SHIFT, UV_SHIFT)\
+#define YUV_CONVERT(FUNC, CONVERT, VANILLA_OUT, NUM_PIXELS, OUT_SHIFT, Y_SHIFT, UV_SHIFT)\
static void \
(FUNC)(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb) \
{ \
- int i,j, w, h; \
+ int i,j, w, h, r; \
unsigned char* restrict ptry; \
unsigned char* restrict ptru; \
unsigned char* restrict ptrv; \
unsigned char* restrict ptro; \
unsigned char *dst, *py, *pu, *pv; \
\
ptro = rgb->ptro; \
ptry = yuv->ptry; \
ptru = yuv->ptru; \
ptrv = yuv->ptrv; \
\
- w = yuv->y_width/NUM_PIXELS; \
+ w = yuv->y_width / NUM_PIXELS; \
h = yuv->y_height; \
+ r = yuv->y_width % NUM_PIXELS; \
for (i = 0; i < h; ++i) \
{ \
py = ptry; \
pu = ptru; \
pv = ptrv; \
dst = ptro; \
for (j = 0; j < w; ++j, \
dst += OUT_SHIFT, \
py += Y_SHIFT, \
pu += UV_SHIFT, \
pv += UV_SHIFT) \
{ \
/* use the given conversion function */ \
CONVERT \
} \
+ /* \
+ * the video frame is not the multiple of NUM_PIXELS, \
+ * thus we have to deal with remaning pixels using \
+ * vanilla implementation. \
+ */ \
+ if (r) { \
+ for \
+ ( \
+ j=(yuv->y_width-r); j < yuv->y_width; \
+ ++j, \
+ dst += 4, \
+ py += 1 \
+ ) \
+ { \
+ LOOKUP_COEFFS \
+ VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
+ VANILLA_OUT(dst, r, g, b) \
+ if (!(j%2)) { \
+ pu += 1; pv += 1; \
+ } \
+ } \
+ } \
+ \
ptro += rgb->rgb_width * 4; \
ptry += yuv->y_width; \
\
if (i & 0x1) \
{ \
ptru += yuv->uv_width; \
ptrv += yuv->uv_width; \
} \
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_x86.c b/media/liboggplay/src/liboggplay/x86/oggplay_yuv2rgb_x86.c
rename from media/liboggplay/src/liboggplay/oggplay_yuv2rgb_x86.c
rename to media/liboggplay/src/liboggplay/x86/oggplay_yuv2rgb_x86.c
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_x86.c
+++ b/media/liboggplay/src/liboggplay/x86/oggplay_yuv2rgb_x86.c
@@ -28,16 +28,19 @@
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* YUV to RGB conversion using x86 CPU extensions
*/
+#include "oggplay_private.h"
+#include "oggplay_yuv2rgb_template.h"
+#include "cpu.h"
#if defined(_MSC_VER)
#include "yuv2rgb_x86_vs.h"
#elif defined(__GNUC__)
#include "yuv2rgb_x86.h"
#endif
typedef union
@@ -78,59 +81,72 @@ static const simd_t simd_table[9] = {
{{ALFA, ALFA}}
};
/**
* the conversion functions using MMX instructions
*/
/* template for the MMX conversion functions */
-#define YUV_CONVERT_MMX(FUNC, CONVERT) YUV_CONVERT(FUNC, CONVERT, 8, 32, 8, 4)
+#define YUV_CONVERT_MMX(FUNC, CONVERT, CONV_BY_PIXEL) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIXEL, 8, 32, 8, 4)
+
#define CLEANUP emms()
#define OUT_RGBA_32 OUTPUT_RGBA_32(movq, mm, 8, 16, 24)
#define OUT_ARGB_32 OUTPUT_ARGB_32(movq, mm, 8, 16, 24)
#define OUT_BGRA_32 OUTPUT_BGRA_32(movq, mm, 8, 16, 24)
#define MOVNTQ MMX_MOVNTQ
/* yuv420 -> */
#define CONVERT(OUTPUT_FUNC) LOAD_YUV_PLANAR_2(movq, mm) \
- YUV_2_RGB(movq, mm) \
- OUTPUT_FUNC
+ YUV_2_RGB(movq, mm) \
+ OUTPUT_FUNC
-YUV_CONVERT_MMX(yuv420_to_rgba_mmx, CONVERT(OUT_RGBA_32))
-YUV_CONVERT_MMX(yuv420_to_bgra_mmx, CONVERT(OUT_BGRA_32))
-YUV_CONVERT_MMX(yuv420_to_argb_mmx, CONVERT(OUT_ARGB_32))
+YUV_CONVERT_MMX(yuv420_to_rgba_mmx, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
+YUV_CONVERT_MMX(yuv420_to_bgra_mmx, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
+YUV_CONVERT_MMX(yuv420_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
+
+#undef MOVNTQ
+
+
+/* template for the SSE conversion functions */
+#define MOVNTQ SSE_MOVNTQ
+
+YUV_CONVERT_MMX(yuv420_to_rgba_sse, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
+YUV_CONVERT_MMX(yuv420_to_bgra_sse, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
+YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
+
#undef CONVERT
-
#undef CLEANUP
#undef OUT_RGBA_32
#undef OUT_ARGB_32
#undef OUT_BGRA_32
#undef MOVNTQ
+
/**
* the conversion functions using SSE2 instructions
*/
/* template for the SSE2 conversion functions */
-#define YUV_CONVERT_SSE2(FUNC, CONVERT) YUV_CONVERT(FUNC, CONVERT, 16, 64, 16, 8)
+#define YUV_CONVERT_SSE2(FUNC, CONVERT, CONV_BY_PIX) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIX, 16, 64, 16, 8)
+
#define OUT_RGBA_32 OUTPUT_RGBA_32(movdqa, xmm, 16, 32, 48)
#define OUT_ARGB_32 OUTPUT_ARGB_32(movdqa, xmm, 16, 32, 48)
#define OUT_BGRA_32 OUTPUT_BGRA_32(movdqa, xmm, 16, 32, 48)
#define MOVNTQ SSE2_MOVNTQ
#define CLEANUP
/* yuv420 -> */
#define CONVERT(OUTPUT_FUNC) LOAD_YUV_PLANAR_2(movdqu, xmm) \
- YUV_2_RGB(movdqa, xmm) \
- OUTPUT_FUNC
+ YUV_2_RGB(movdqa, xmm) \
+ OUTPUT_FUNC
-YUV_CONVERT_SSE2(yuv420_to_rgba_sse2, CONVERT(OUT_RGBA_32))
-YUV_CONVERT_SSE2(yuv420_to_bgra_sse2, CONVERT(OUT_BGRA_32))
-YUV_CONVERT_SSE2(yuv420_to_argb_sse2, CONVERT(OUT_ARGB_32))
+YUV_CONVERT_SSE2(yuv420_to_rgba_sse2, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
+YUV_CONVERT_SSE2(yuv420_to_bgra_sse2, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
+YUV_CONVERT_SSE2(yuv420_to_argb_sse2, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
+
#undef CONVERT
-
#undef OUT_RGBA_32
#undef OUT_ARGB_32
#undef OUT_BGRA_32
#undef MOVNTQ
-#undef CLEANUP
+#undef CLEANUP
diff --git a/media/liboggplay/src/liboggplay/yuv2rgb_x86.h b/media/liboggplay/src/liboggplay/x86/yuv2rgb_x86.h
rename from media/liboggplay/src/liboggplay/yuv2rgb_x86.h
rename to media/liboggplay/src/liboggplay/x86/yuv2rgb_x86.h
--- a/media/liboggplay/src/liboggplay/yuv2rgb_x86.h
+++ b/media/liboggplay/src/liboggplay/x86/yuv2rgb_x86.h
@@ -3,17 +3,18 @@
# ifdef ATTRIBUTE_ALIGNED_MAX
#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
# else
#define ATTR_ALIGN(align)
# endif
#define emms() __asm__ __volatile__ ( "emms;" );
-#define MMX_MOVNTQ "movntq"
+#define MMX_MOVNTQ "movq"
+#define SSE_MOVNTQ "movntq"
#define SSE2_MOVNTQ "movdqu"
#define YUV_2_RGB(mov_instr, reg_type) \
__asm__ __volatile__ ( \
"punpcklbw %%"#reg_type"4, %%"#reg_type"0;" /* mm0 = u3 u2 u1 u0 */\
"punpcklbw %%"#reg_type"4, %%"#reg_type"1;" /* mm1 = v3 v2 v1 v0 */\
"psubsw (%0), %%"#reg_type"0;" /* u -= 128 */\
"psubsw (%0), %%"#reg_type"1;" /* v -= 128 */\
diff --git a/media/liboggplay/src/liboggplay/yuv2rgb_x86_vs.h b/media/liboggplay/src/liboggplay/x86/yuv2rgb_x86_vs.h
rename from media/liboggplay/src/liboggplay/yuv2rgb_x86_vs.h
rename to media/liboggplay/src/liboggplay/x86/yuv2rgb_x86_vs.h
--- a/media/liboggplay/src/liboggplay/yuv2rgb_x86_vs.h
+++ b/media/liboggplay/src/liboggplay/x86/yuv2rgb_x86_vs.h
@@ -1,15 +1,16 @@
#ifndef __OGGPLAY_YUV2RGB_VS_H__
#define __OGGPLAY_YUV2RGB_VS_H__
#define ATTR_ALIGN(_align) __declspec(align(_align))
#define emms() __asm emms
-#define MMX_MOVNTQ movntq
+#define MMX_MOVNTQ movq
+#define SSE_MOVNTQ movntq
#define SSE2_MOVNTQ movdqu
#define LOAD_YUV_PLANAR_2(mov_instr, reg_type) \
__asm { \
__asm mov eax, py \
__asm mov edx, pu \
__asm mov_instr reg_type##6, [eax] \
__asm mov_instr reg_type##0, [edx] \

View File

@ -1,43 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
@@ -55,28 +55,38 @@ static void
CONVERT \
} \
/* \
* the video frame is not the multiple of NUM_PIXELS, \
* thus we have to deal with remaning pixels using \
* vanilla implementation. \
*/ \
if (r) { \
+ /* if there's only 1 remaining pixel to process \
+ and the luma width is odd, the for loop above \
+ has already advanced pu and pv too far. */ \
+ if (r==1 && yuv->y_width&1) { \
+ pu -= 1; pv -= 1; \
+ } \
for \
( \
j=(yuv->y_width-r); j < yuv->y_width; \
++j, \
dst += 4, \
py += 1 \
) \
{ \
LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
VANILLA_OUT(dst, r, g, b) \
- if (!(j%2)) { \
+ /* advance chroma ptrs every second sample, except \
+ when the luma width is odd, in which case the \
+ chroma samples are truncated and we must reuse \
+ the previous chroma sample */ \
+ if (j%2 && !(j+1==yuv->y_width-1 && yuv->y_width&1)) { \
pu += 1; pv += 1; \
} \
} \
} \
\
ptro += rgb->rgb_width * 4; \
ptry += yuv->y_width; \
\

View File

@ -1,22 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb_template.h
@@ -85,17 +85,17 @@ static void
pu += 1; pv += 1; \
} \
} \
} \
\
ptro += rgb->rgb_width * 4; \
ptry += yuv->y_width; \
\
- if (i & 0x1) \
+ if (i & 0x1 && !(i+1==h-1 && h&1)) \
{ \
ptru += yuv->uv_width; \
ptrv += yuv->uv_width; \
} \
} \
CLEANUP \
}

View File

@ -1,52 +0,0 @@
diff --git a/media/liboggplay/include/oggplay/oggplay_enums.h b/media/liboggplay/include/oggplay/oggplay_enums.h
index aff0e51..ffb7cb4 100644
--- a/media/liboggplay/include/oggplay/oggplay_enums.h
+++ b/media/liboggplay/include/oggplay/oggplay_enums.h
@@ -64,6 +64,9 @@ typedef enum OggPlayErrorCode {
E_OGGPLAY_NO_KATE_SUPPORT = -19,
E_OGGPLAY_NO_TIGER_SUPPORT = -20,
E_OGGPLAY_OUT_OF_MEMORY = -21,
+ E_OGGPLAY_TYPE_OVERFLOW = -22, /**< Integer overflow detected */
+
+ E_OGGPLAY_TRACK_IS_UNKNOWN = -23, /**< The selected track's content type is UNKNOWN */
E_OGGPLAY_NOTCHICKENPAYBACK = -777
} OggPlayErrorCode;
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index 05cf363..593691f 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -508,6 +508,7 @@ OggPlayCallbackFunctions callbacks[] = {
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* CELT */
{oggplay_init_kate, oggplay_callback_kate, oggplay_shutdown_kate,
sizeof(OggPlayKateDecode)}, /* KATE */
+ {NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* DIRAC */
{NULL, NULL, NULL, sizeof(OggPlayDecode)} /* UNKNOWN */
};
diff --git a/media/liboggplay/src/liboggplay/oggplay_query.c b/media/liboggplay/src/liboggplay/oggplay_query.c
index 2a69beb..6344ec8 100644
--- a/media/liboggplay/src/liboggplay/oggplay_query.c
+++ b/media/liboggplay/src/liboggplay/oggplay_query.c
@@ -131,6 +131,10 @@ oggplay_set_track_active(OggPlay *me, int track_num) {
return E_OGGPLAY_TRACK_IS_SKELETON;
}
+ if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_UNKNOWN) {
+ return E_OGGPLAY_TRACK_IS_UNKNOWN;
+ }
+
if ((p = me->decode_data[track_num]->final_granulepos) != -1) {
if (p * me->decode_data[track_num]->granuleperiod > me->target) {
return E_OGGPLAY_TRACK_IS_OVER;
@@ -179,6 +183,10 @@ oggplay_set_track_inactive(OggPlay *me, int track_num) {
return E_OGGPLAY_TRACK_IS_SKELETON;
}
+ if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_UNKNOWN) {
+ return E_OGGPLAY_TRACK_IS_UNKNOWN;
+ }
+
if (me->decode_data[track_num]->active == 1) {
me->decode_data[track_num]->active = 0;

View File

@ -1,52 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index 593691f..7683b80 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -107,6 +107,11 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height / 2;
if (--(decoder->remaining_header_packets) == 0) {
+ /* Ensure the offsets do not push the viewable area outside of the decoded frame. */
+ if (((decoder->video_info.height - decoder->video_info.offset_y)<decoder->video_info.frame_height)||
+ ((decoder->video_info.width - decoder->video_info.offset_x)<decoder->video_info.frame_width))
+ return -1;
+
theora_decode_init(&(decoder->video_handle), &(decoder->video_info));
}
return 0;
diff --git a/media/liboggplay/src/liboggplay/oggplay_data.c b/media/liboggplay/src/liboggplay/oggplay_data.c
index 57a9458..c519d59 100644
--- a/media/liboggplay/src/liboggplay/oggplay_data.c
+++ b/media/liboggplay/src/liboggplay/oggplay_data.c
@@ -323,6 +323,7 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
int size = sizeof (OggPlayVideoRecord);
int i;
+ int uv_offset;
unsigned char * p;
unsigned char * q;
unsigned char * p2;
@@ -359,17 +360,20 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
* a row-by-row copy (stride may be negative)
*/
p = data->y;
- q = buffer->y;
+ q = buffer->y + (decode->video_info.offset_x&~1)+buffer->y_stride*(decode->video_info.offset_y&~1);
for (i = 0; i < decode->y_height; i++) {
memcpy(p, q, decode->y_width);
p += decode->y_width;
q += buffer->y_stride;
}
+ uv_offset = (decode->video_info.offset_x/(decode->y_width/decode->uv_width)) +
+ (buffer->uv_stride) *(decode->video_info.offset_y/(decode->y_height/decode->uv_height));
+
p = data->u;
- q = buffer->u;
+ q = buffer->u + uv_offset;
p2 = data->v;
- q2 = buffer->v;
+ q2 = buffer->v + uv_offset;
for (i = 0; i < decode->uv_height; i++) {
memcpy(p, q, decode->uv_width);
memcpy(p2, q2, decode->uv_width);

View File

@ -1,106 +0,0 @@
diff --git a/src/liboggplay/oggplay_callback.c b/src/liboggplay/oggplay_callback.c
index f3e2339..39380e7 100644
--- a/src/liboggplay/oggplay_callback.c
+++ b/src/liboggplay/oggplay_callback.c
@@ -109,6 +109,15 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
int musec;
#endif
+ if ( (granulepos > 0) && (common->last_granulepos > granulepos)) {
+ /*
+ * the granule position is not monotonically increasing,
+ * something wrong with the page!
+ * skipping this page.....
+ */
+ return 0;
+ }
+
/*
* always decode headers
*/
@@ -174,10 +183,19 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
#endif
if (granulepos != -1) {
+ /*
+ * save last granule position in order to be able to validate
+ * that it's monotonically increasing
+ */
+ common->last_granulepos = granulepos;
+
+ /* calculate the frame number */
granuleshift = oggz_get_granuleshift(oggz, serialno);
frame = (granulepos >> granuleshift);
frame += (granulepos & ((1 << granuleshift) - 1));
- common->current_loc = frame * common->granuleperiod;
+
+ /* calculate the current location in the stream */
+ common->current_loc = frame * common->granuleperiod;
} else {
common->current_loc = -1;
}
diff --git a/src/liboggplay/oggplay_private.h b/src/liboggplay/oggplay_private.h
index fb73f1d..1455c68 100644
--- a/src/liboggplay/oggplay_private.h
+++ b/src/liboggplay/oggplay_private.h
@@ -142,22 +142,22 @@ struct _OggPlayCallbackInfo {
* track
*/
typedef struct {
- long serialno;
- int content_type;
- const char * content_type_name;
- OggPlayDataType decoded_type;
- ogg_int64_t granuleperiod;
- ogg_int64_t last_granulepos;
- ogg_int64_t offset;
- ogg_int64_t current_loc;
- int active;
- ogg_int64_t final_granulepos;
- struct _OggPlay * player;
- OggPlayDataHeader * data_list;
- OggPlayDataHeader * end_of_data_list;
- OggPlayDataHeader * untimed_data_list;
- OggPlayStreamInfo stream_info;
- int preroll;
+ long serialno; /**< identifies the logical bit stream */
+ int content_type;
+ const char * content_type_name;
+ OggPlayDataType decoded_type; /**< type of the track @see OggPlayDataType */
+ ogg_int64_t granuleperiod;
+ ogg_int64_t last_granulepos; /**< last seen granule position */
+ ogg_int64_t offset; /**< */
+ ogg_int64_t current_loc; /**< current location in the stream (in ) */
+ int active; /**< indicates whether the track is active or not */
+ ogg_int64_t final_granulepos; /**< */
+ struct _OggPlay * player; /**< reference to the OggPlay handle */
+ OggPlayDataHeader * data_list;
+ OggPlayDataHeader * end_of_data_list;
+ OggPlayDataHeader * untimed_data_list;
+ OggPlayStreamInfo stream_info; /**< @see OggPlayStreamInfo */
+ int preroll; /**< num. of past content packets to take into account when decoding the current Ogg page */
} OggPlayDecode;
typedef struct {
@@ -190,6 +190,9 @@ typedef struct {
int granuleshift;
} OggPlayCmmlDecode;
+/**
+ * OggPlaySkeletonDecode
+ */
typedef struct {
OggPlayDecode decoder;
ogg_int64_t presentation_time;
diff --git a/src/liboggplay/oggplay_seek.c b/src/liboggplay/oggplay_seek.c
index e74c136..ef150b8 100644
--- a/src/liboggplay/oggplay_seek.c
+++ b/src/liboggplay/oggplay_seek.c
@@ -133,6 +133,7 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
track->data_list = track->end_of_data_list = NULL;
track->untimed_data_list = NULL;
track->current_loc = -1;
+ track->last_granulepos = -1;
track->stream_info = OGGPLAY_STREAM_JUST_SEEKED;
}

View File

@ -1,22 +0,0 @@
commit 6c8e110015c829e04d8f5fb2ac53b23f468d58ed
Author: Viktor Gal <viktor.gal@maeth.com>
Date: Thu May 28 10:02:27 2009 +1000
Fix for ticket 475: fix NULL pointer dereference in oggplay_seek_cleanup function.
The fix proposed by Chris Double in annodex trac could cause another
NULL pointer dereference, in case of not enough memory for allocating new buffer.
diff --git a/src/liboggplay/oggplay_seek.c b/src/liboggplay/oggplay_seek.c
index ef150b8..7d7073d 100644
--- a/src/liboggplay/oggplay_seek.c
+++ b/src/liboggplay/oggplay_seek.c
@@ -104,6 +104,9 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
/*
* store the old buffer in it next.
*/
+ if (me->buffer == NULL)
+ return;
+
trash->old_buffer = (OggPlayBuffer *)me->buffer;
/*

View File

@ -1,23 +0,0 @@
commit 3602bf643830c63f499928623f47ae9635a8db51
Author: Viktor Gal <viktor.gal@maeth.com>
Date: Tue Apr 14 17:20:24 2009 +1000
Fix for Mozilla 481933.
WARNING:
You will need the patch of 38b6dffb5ec8b32119704bd048d722a281d9fd79
in oggz repository, otherwise you won't be able to play back chopped Ogg content!
diff --git a/src/liboggplay/oggplay.c b/src/liboggplay/oggplay.c
index 3296fea..0b03a3a 100644
--- a/src/liboggplay/oggplay.c
+++ b/src/liboggplay/oggplay.c
@@ -687,6 +687,8 @@ read_more_data:
}
return E_OGGPLAY_OK;
+ } else if (r == OGGZ_ERR_HOLE_IN_DATA) {
+ return E_OGGPLAY_BAD_INPUT;
}
}

View File

@ -1,22 +1,22 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
@@ -181,17 +181,17 @@ init_yuv_converters(void)
{
ogg_uint32_t features = 0;
if ( yuv_conv.yuv2rgba == NULL )
{
init_vanilla_coeffs ();
features = oc_cpu_flags_get();
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
@@ -174,17 +174,17 @@ YUV_CONVERT(yuv444_to_argb_vanilla, CONV
* macros as there's no way e.g. we could compile a x86 asm code
* on a ppc machine and vica-versa
*/
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
#if !defined(_M_AMD64)
#define ENABLE_MMX
#endif
#include "x86/oggplay_yuv2rgb_x86.c"
-#if defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
+#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
if (features & OC_CPU_X86_SSE2)
{
yuv_conv.yuv2rgba = yuv420_to_rgba_sse2;
yuv_conv.yuv2bgra = yuv420_to_bgra_sse2;
yuv_conv.yuv2argb = yuv420_to_argb_sse2;
return;
}
else
+#if defined(_MSC_VER) || defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
#define ENABLE_SSE2
#endif
#elif defined(__ppc__) || defined(__ppc64__)
#define ENABLE_ALTIVEC
//altivec intristics only working with -maltivec gcc flag,
//but we want runtime altivec detection, hence this has to be
//fixed!
//#include "oggplay_yuv2rgb_altivec.c"

View File

@ -1,15 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index 8706014..bd45123 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -701,8 +701,8 @@ oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
- callbacks[content_type].callback(oggz, op, serialno,
- me->decode_data[me->num_tracks - 1]);
+ return callbacks[content_type].callback(oggz, op, serialno,
+ me->decode_data[me->num_tracks - 1]);
}
return 0;

View File

@ -1,32 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index b046618..5f4ab31 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -642,15 +642,15 @@ oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
*/
for (i = 0; i < me->num_tracks; i++) {
if (serialno == me->decode_data[i]->serialno) {
-
+ int ret = 0;
me->all_tracks_initialised = 1;
/*
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
- callbacks[content_type].callback(oggz, op, serialno,
- me->decode_data[i]);
+ ret = callbacks[content_type].callback(oggz, op, serialno,
+ me->decode_data[i]);
}
/*
@@ -668,7 +668,7 @@ oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
*/
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
- return 0;
+ return ret < 0 ? OGGZ_ERR_HOLE_IN_DATA : ret;
}
}

View File

@ -1,56 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -115,6 +115,15 @@
decoder->y_height = decoder->video_info.frame_height;
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height / 2;
+
+ if (decoder->y_width == 0 ||
+ decoder->y_height == 0 ||
+ decoder->uv_width == 0 ||
+ decoder->uv_height == 0) {
+ decoder->decoder.active = 0;
+ return 0;
+ }
+
if (--(decoder->remaining_header_packets) == 0) {
/* Ensure the offsets do not push the viewable area outside of the decoded frame. */
if (((decoder->video_info.height - decoder->video_info.offset_y)<decoder->video_info.frame_height)||
diff --git a/media/liboggplay/src/liboggplay/oggplay_data.c b/media/liboggplay/src/liboggplay/oggplay_data.c
--- a/media/liboggplay/src/liboggplay/oggplay_data.c
+++ b/media/liboggplay/src/liboggplay/oggplay_data.c
@@ -317,6 +317,23 @@
}
+static int
+get_uv_offset(OggPlayTheoraDecode *decode, yuv_buffer *buffer)
+{
+ int xo=0, yo = 0;
+ if (decode->y_width != 0 &&
+ decode->uv_width != 0 &&
+ decode->y_width/decode->uv_width != 0) {
+ xo = (decode->video_info.offset_x/(decode->y_width/decode->uv_width));
+ }
+ if (decode->y_height != 0 &&
+ decode->uv_height != 0 &&
+ decode->y_height/decode->uv_height != 0) {
+ yo = (buffer->uv_stride)*(decode->video_info.offset_y/(decode->y_height/decode->uv_height));
+ }
+ return xo + yo;
+}
+
void
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv_buffer *buffer) {
@@ -367,8 +384,7 @@
q += buffer->y_stride;
}
- uv_offset = (decode->video_info.offset_x/(decode->y_width/decode->uv_width)) +
- (buffer->uv_stride) *(decode->video_info.offset_y/(decode->y_height/decode->uv_height));
+ uv_offset = get_uv_offset(decode, buffer);
p = data->u;
q = buffer->u + uv_offset;

View File

@ -1,7 +1,7 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -129,16 +129,17 @@ oggplay_initialise(OggPlay *me, int bloc
@@ -149,16 +149,17 @@ oggplay_initialise(OggPlay *me, int bloc
}
/*
@ -19,54 +19,34 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/li
oggplay_buffer_prepare(me);
}
@@ -693,18 +694,18 @@ read_more_data:
/* end-of-file */
if (r == 0) {
num_records = oggplay_callback_info_prepare(me, &info);
/*
* set all of the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
- me->active_tracks = 0;
}
+ me->active_tracks = 0;
if (info != NULL) {
me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy(me, info);
}
/*
* ensure all tracks have their final data packet set to end_of_stream
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -54,16 +54,17 @@ oggplay_init_theora(void *user_data) {
@@ -60,16 +60,17 @@ oggplay_init_theora(void *user_data) {
theora_info_init(&(decoder->video_info));
theora_comment_init(&(decoder->video_comment));
decoder->remaining_header_packets = 3;
decoder->granulepos_seen = 0;
decoder->frame_delta = 0;
decoder->y_width = 0;
decoder->convert_to_rgb = 0;
decoder->swap_rgb = 0;
decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO;
+ decoder->decoder.player->active_tracks++;
}
void
oggplay_shutdown_theora(void *user_data) {
OggPlayDecode * common;
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
if (decoder->remaining_header_packets == 0) {
@@ -366,16 +367,17 @@ oggplay_init_audio (void * user_data) {
if (decoder == NULL) {
@@ -499,16 +500,17 @@ oggplay_init_audio (void * user_data) {
}
decoder->sound_info.channels = 0;
fish_sound_set_interleave(decoder->sound_handle, 1);
fish_sound_set_decoded_float_ilv(decoder->sound_handle,
oggplay_fish_sound_callback_floats,
(void *)decoder);
oggplay_fish_sound_callback_floats,
(void *)decoder);
decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO;
+ decoder->decoder.player->active_tracks++;
@ -76,9 +56,9 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggpl
oggplay_shutdown_audio(void *user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
fish_sound_delete(decoder->sound_handle);
@@ -566,17 +568,17 @@ oggplay_initialise_decoder(OggPlay *me,
if (decoder == NULL) {
@@ -814,17 +816,17 @@ oggplay_initialise_decoder(OggPlay *me,
if (decoder == NULL)
return NULL;
@ -92,8 +72,8 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggpl
decoder->final_granulepos = -1;
decoder->player = me;
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
decoder->num_header_packets =
oggz_stream_get_numheaders (me->oggz, serialno);
/*
* set the StreamInfo to unitialised until we get some real data in
*/
decoder->stream_info = OGGPLAY_STREAM_UNINITIALISED;

View File

@ -1,7 +1,7 @@
diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/include/oggplay/oggplay_seek.h
--- a/media/liboggplay/include/oggplay/oggplay_seek.h
+++ b/media/liboggplay/include/oggplay/oggplay_seek.h
@@ -42,15 +42,13 @@
@@ -53,15 +53,13 @@
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
@ -20,11 +20,11 @@ diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -75,54 +75,38 @@ oggplay_seek(OggPlay *me, ogg_int64_t mi
oggplay_seek_cleanup(me, milliseconds);
return E_OGGPLAY_OK;
@@ -186,54 +186,39 @@ oggplay_take_out_trash(OggPlay *me, OggP
if (p != NULL) {
oggplay_free(p);
}
}
OggPlayErrorCode
@ -60,7 +60,7 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/s
- for (i=0; i<num_tracks; i++) {
- serial_nos[i] = me->decode_data[tracks[i]]->serialno;
- }
-
time = oggz_keyframe_seek_set(me->oggz,
- serial_nos,
- num_tracks,

View File

@ -0,0 +1,15 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -977,10 +982,10 @@ oggplay_callback_predetected (OGGZ *oggz
}
}
/* disable the callback for unforeseen streams */
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
}
/* read the header part of the ogg content in a packet-by-packet manner */
- return ((ret < 0) ? ret : OGGZ_STOP_OK);
+ return ((ret < 0) ? ret : OGGZ_CONTINUE);
}

View File

@ -0,0 +1,26 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -136,16 +136,22 @@ oggplay_initialise(OggPlay *me, int bloc
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
case OGGZ_ERR_STOP_ERR:
/* */
return E_OGGPLAY_BAD_OGGPLAY;
+
+ default:
+ /* If the read otherwise failed, bail out. */
+ if (i < 0)
+ return E_OGGPLAY_BAD_INPUT;
+ break;
}
if (me->all_tracks_initialised) {
break;
}
}
/*

View File

@ -56,7 +56,7 @@
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.0.1.svn"
#define VERSION "0.2.0"
/* Request Winsock 2.2 */
#define HAVE_WINSOCK2 1
@ -75,4 +75,4 @@
/* #undef const */
/* Maximum supported data alignment */
/* #undef ATTRIBUTE_ALIGNED_MAX */
#define ATTRIBUTE_ALIGNED_MAX 16

View File

@ -30,13 +30,16 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* oggplay.h
/** @file
*
* The liboggplay C API.
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_H__
#define __OGGPLAY_H__
@ -46,11 +49,32 @@ extern "C" {
#include <oggplay/oggplay_enums.h>
#include <oggplay/oggplay_reader.h>
/**
* This is returned by oggplay_open_with_reader() or oggplay_new_with_reader().
*/
typedef struct _OggPlay OggPlay;
/**
* A structure for storing the decoded frames for the various streams in the
* Ogg container.
*/
typedef struct _OggPlayCallbackInfo OggPlayCallbackInfo;
typedef int (OggPlayDataCallback)(OggPlay *player, int num_records,
OggPlayCallbackInfo **records, void *user);
/**
* This is the signature of a callback which you must provide for OggPlay
* to call whenever there's any unpresented decoded frame available.
*
* @see oggplay_step_decoding
* @param player The OggPlay handle
* @param num_records size of the OggPlayCallbackInfo array
* @param records array of OggPlayCallbackInfo
* @param user A generic pointer for the data the user provided earlier.
* @returns 0 to continue, non-zero to instruct OggPlay to stop.
*
*/
typedef int (OggPlayDataCallback) (OggPlay *player, int num_records,
OggPlayCallbackInfo **records, void *user);
#include <oggplay/oggplay_query.h>
#include <oggplay/oggplay_callback_info.h>
@ -59,9 +83,10 @@ typedef int (OggPlayDataCallback)(OggPlay *player, int num_records,
/**
* Create an OggPlay handle associated with the given reader.
* The functions creates a new OggPlay handle and associates with
* the given OggPlayReader and initialises the buffer.
*
* This functions creates a new OggPlay handle associated with
* the OggPlayReader and it calls oggplay_initialise to
* read the header packets of the Ogg container.
*
* @param reader an OggPlayReader handle associated with the Ogg content
* @return A new OggPlay handle
@ -73,22 +98,50 @@ oggplay_open_with_reader(OggPlayReader *reader);
/**
* Create a new OggPlay handle associated with the given reader.
*
* \param reader OggPlayReader handle associated with the Ogg content
* \return A new OggPlay handle
* \retval NULL in case of error.
* @param reader OggPlayReader handle associated with the Ogg content
* @return A new OggPlay handle
* @retval NULL in case of error.
*/
OggPlay *
oggplay_new_with_reader(OggPlayReader *reader);
/**
* Initialise the OggPlay handle.
*
* This function creates an Oggz handle and sets it's OggzIO*
* functions to the OggPlayReader's io_* functions. Moreover
* it reads the Ogg container's content until it hasn't got
* all the streams' headers.
*
* @param me OggPlay handle
* @param block passed as the second argument to the OggPlayReader's initialise
* function. E.g. in case of OggPlayTCPReader block == 0 sets the socket to non-blocking
* mode.
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_OGGZ_UNHAPPY something went wrong while calling oggz_io_set_* functions.
* @retval E_OGGPLAY_BAD_INPUT got EOF or OGGZ_ERR_HOLE_IN_DATA occured.
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block);
OggPlayErrorCode
oggplay_set_source(OggPlay *OS, char *source);
/**
* Sets a user defined OggPlayDataCallback function for the OggPlay handle.
*
* @param me OggPlay handle.
* @param callback A custom callback function.
* @param user Arbitrary data one wishes to pass to the callback function.
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BUFFER_MODE We are running in buffer mode, i.e. oggplay_use_buffer
* has been called earlier.
* @retval E_OGGPLAY_BAD_OGGPLAY Invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_set_data_callback(OggPlay *me, OggPlayDataCallback callback,
void *user);
void *user);
OggPlayErrorCode
oggplay_set_callback_num_frames(OggPlay *me, int stream, int frames);
@ -99,18 +152,81 @@ oggplay_set_callback_period(OggPlay *me, int stream, int milliseconds);
OggPlayErrorCode
oggplay_set_offset(OggPlay *me, int track, ogg_int64_t offset);
/**
* Get the given video track's Y-plane's width and height.
*
* @param me OggPlay handle
* @param track the track number of the video track
* @param y_width the width of the Y-plane
* @param y_height the height of the Y-plane
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_y_size(OggPlay *me, int track, int *y_width, int *y_height);
/**
* Get the given video track's UV-plane's width and height.
*
* @param me OggPlay handle
* @param track the track number of the video track
* @param uv_width the width of the UV-plane
* @param uv_height the height of the UV-plane
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_uv_size(OggPlay *me, int track, int *uv_width, int *uv_height);
/**
* Get the number of channels of the audio track.
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param channels the number of channels of the given audio track.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_audio_channels(OggPlay *me, int track, int *channels);
/**
* Get the sample rate of the of the audio track
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param samplerate the sample rate of the audio track.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_audio_samplerate(OggPlay *me, int track, int *samplerate);
/**
* Get the frame-per-second value the of a given video track.
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param fps_denom the denumerator of the FPS
* @param fps_num the numerator of the FPS
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num);
@ -118,7 +234,7 @@ OggPlayErrorCode
oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_num);
OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert);
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb);
OggPlayErrorCode
oggplay_get_kate_category(OggPlay *me, int track, const char** category);
@ -127,7 +243,7 @@ OggPlayErrorCode
oggplay_get_kate_language(OggPlay *me, int track, const char** language);
OggPlayErrorCode
oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger);
oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger, int swap_rgb, int default_width, int default_height);
OggPlayErrorCode
oggplay_overlay_kate_track_on_video(OggPlay *me, int kate_track, int video_track);
@ -135,15 +251,72 @@ oggplay_overlay_kate_track_on_video(OggPlay *me, int kate_track, int video_track
OggPlayErrorCode
oggplay_start_decoding(OggPlay *me);
/**
* Decode the streams in the Ogg container until we find data that hasn't
* been presented, yet.
*
* Whenever there is data that hasn't been presented the OggPlayDataCallback
* function will be called.
*
* @param me OggPlay handle
* @retval E_OGGPLAY_OK reached the end of the stream or shutdown detected
* @retval E_OGGPLAY_CONTINUE successfully decoded the frames.
* @retval E_OGGPLAY_BAD_INPUT OGGZ_ERR_HOLE_IN_DATA occured while decoding
* @retval E_OGGPLAY_UNINITIALISED the OggPlayDataCallback of the OggPlay handle is not set.
* @retval E_OGGPLAY_USER_INTERRUPT user interrupted the decoding
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while decoding
*/
OggPlayErrorCode
oggplay_step_decoding(OggPlay *me);
/**
* Use the built-in OggPlayBuffer for buffering the decoded frames
*
* The built-in OggPlayBuffer implements a simple lock-free FIFO for
* storing the decoded frames.
*
* It tries to set the OggPlay handle's OggPlayDataCallback function to it's
* own implementation (oggplay_buffer_callback). Thus it will fail if
* a user already set OggPlayDataCallback of the OggPlay handle
* with oggplay_set_data_callback.
*
* One can retrive the next record in the queue by
* calling oggplay_buffer_retrieve_next.
*
* @param player the OggPlay handle
* @param size The size of the buffer, i.e. the number of records it can store
* @retval E_OGGPLAY_OK on succsess
* @retval E_OGGPLAY_BAD_OGGPLAY The supplied OggPlay handle is not valid
* @retval E_OGGPLAY_CALLBACK_MODE The given OggPlay handle's OggPlayDataCallback
* function is already set, i.e. running in callback-mode.
* @retval E_OGGPLAY_OUT_OF_MEMORY Ran out of memory while trying to allocate memory for the buffer.
*/
OggPlayErrorCode
oggplay_use_buffer(OggPlay *player, int size);
/**
* Retrive the next element in the buffer.
*
* @param player OggPlay handle
* @return array of OggPlayCallbackInfo - one per track.
* @retval NULL if there was no available.
*/
OggPlayCallbackInfo **
oggplay_buffer_retrieve_next(OggPlay *player);
/**
* Release the given buffer item.
*
* After retrieving and processing one buffer item, in order
* to remove the given item from the queue and release the
* memory allocated by the buffer item one needs to call this
* function.
*
* @param player OggPlay handle
* @param track_info OggPlayCallbackInfo array to release.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_buffer_release(OggPlay *player, OggPlayCallbackInfo **track_info);
@ -151,7 +324,7 @@ void
oggplay_prepare_for_close(OggPlay *me);
/**
* @brief Destroys the OggPlay handle along with the associated OggPlayReader
* Destroys the OggPlay handle along with the associated OggPlayReader
* and clears out the buffer and shuts down the callback function.
*
* @param player an OggPlay handle
@ -163,6 +336,13 @@ oggplay_close(OggPlay *player);
int
oggplay_get_available(OggPlay *player);
/**
* Get the duration of the Ogg content.
*
* @param player OggPlay handle.
* @return The duration of the content in milliseconds.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
*/
ogg_int64_t
oggplay_get_duration(OggPlay * player);
@ -173,4 +353,4 @@ oggplay_media_finished_retrieving(OggPlay * player);
}
#endif
#endif
#endif /* __OGGPLAY_H__ */

View File

@ -30,69 +30,143 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
/** @file
* oggplay_callback_info.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_CALLBACK_INFO__
#define __OGGPLAY_CALLBACK_INFO__
/** structure for storing a YUV video frame */
typedef struct {
unsigned char * y;
unsigned char * u;
unsigned char * v;
unsigned char * y; /**< Y-plane */
unsigned char * u; /**< U-plane*/
unsigned char * v; /**< V-plane */
} OggPlayVideoData;
/** structure for storing a video frame in RGB fromat */
typedef struct {
unsigned char * rgba; /* may be NULL if no alpha */
unsigned char * rgb; /* may be NULL if alpha */
size_t width; /* in pixels */
size_t height; /* in pixels */
size_t stride; /* in bytes */
unsigned char * rgba; /**< may be NULL if no alpha */
unsigned char * rgb; /**< may be NULL if alpha */
size_t width; /**< width in pixels */
size_t height; /**< height in pixels */
size_t stride; /**< stride */
} OggPlayOverlayData;
/** Type for representing audio data */
typedef void * OggPlayAudioData;
/** Type for representing text data */
typedef char OggPlayTextData;
struct _OggPlayDataHeader;
/** Header for the various data formats */
typedef struct _OggPlayDataHeader OggPlayDataHeader;
/**
* Get the data type of the given OggPlayCallbackInfo.
*
* @param info
* @returns The data type of the given OggPlayCallbackInfo
* @see OggPlayDataType
*/
OggPlayDataType
oggplay_callback_info_get_type(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_available(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_required(OggPlayCallbackInfo *info);
/**
* Get the array of records stored in the OggPlayCallbackInfo
*
* @param info
* @returns array of records
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayDataHeader **
oggplay_callback_info_get_headers(OggPlayCallbackInfo *info);
/**
* Get the size of the given record.
*
* @param header
* @returns The number of samples in the record.
*/
ogg_int64_t
oggplay_callback_info_get_record_size(OggPlayDataHeader *header);
/**
* Extract the video frame from the supplied record.
*
* @param header
* @returns the video frame
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayVideoData *
oggplay_callback_info_get_video_data(OggPlayDataHeader *header);
/**
* Extract the overlay data from the supplied record.
*
* @param header
* @returns OggPlayOverlayData
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayOverlayData *
oggplay_callback_info_get_overlay_data(OggPlayDataHeader *header);
/**
* Extract the audio data from the supplied record.
*
* @param header
* @returns OggPlayAudioData.
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayAudioData *
oggplay_callback_info_get_audio_data(OggPlayDataHeader *header);
/**
* Extract the text data from the supplied record.
*
* @param header
* @returns OggPlayTextData
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayTextData *
oggplay_callback_info_get_text_data(OggPlayDataHeader *header);
/**
* Get the state of the stream.
*
* @param info
* @returns State of the given stream.
* @see OggPlayStreamInfo
*/
OggPlayStreamInfo
oggplay_callback_info_get_stream_info(OggPlayCallbackInfo *info);
void
oggplay_callback_info_lock_item(OggPlayDataHeader *header);
void
oggplay_callback_info_unlock_item(OggPlayDataHeader *header);
/**
* Get the presentation time of the given record.
*
* @param header
* @returns presentation time of the given frame in milliseconds.
*/
long
oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header);

View File

@ -30,63 +30,74 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* oggplay_enums.h
/** @file
* General constants used by liboggplay
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_ENUMS_H__
#define __OGGPLAY_ENUMS_H__
/**
* Definitions of error return values.
*/
typedef enum OggPlayErrorCode {
E_OGGPLAY_CONTINUE = 1,
E_OGGPLAY_OK = 0,
E_OGGPLAY_BAD_OGGPLAY = -1,
E_OGGPLAY_BAD_READER = -2,
E_OGGPLAY_BAD_INPUT = -3,
E_OGGPLAY_NO_SUCH_CHUNK = -4,
E_OGGPLAY_BAD_TRACK = -5,
E_OGGPLAY_TRACK_IS_SKELETON = -6,
E_OGGPLAY_OGGZ_UNHAPPY = -7,
E_OGGPLAY_END_OF_FILE = -8,
E_OGGPLAY_TRACK_IS_OVER = -9,
E_OGGPLAY_BAD_CALLBACK_INFO = -10,
E_OGGPLAY_WRONG_TRACK_TYPE = -11,
E_OGGPLAY_UNINITIALISED = -12,
E_OGGPLAY_CALLBACK_MODE = -13,
E_OGGPLAY_BUFFER_MODE = -14,
E_OGGPLAY_USER_INTERRUPT = -15,
E_OGGPLAY_SOCKET_ERROR = -16,
E_OGGPLAY_TIMEOUT = -17,
E_OGGPLAY_CANT_SEEK = -18,
E_OGGPLAY_NO_KATE_SUPPORT = -19,
E_OGGPLAY_NO_TIGER_SUPPORT = -20,
E_OGGPLAY_OUT_OF_MEMORY = -21,
E_OGGPLAY_TYPE_OVERFLOW = -22, /**< Integer overflow detected */
E_OGGPLAY_TRACK_IS_UNKNOWN = -23, /**< The selected track's content type is UNKNOWN */
E_OGGPLAY_NOTCHICKENPAYBACK = -777
E_OGGPLAY_CONTINUE = 1,
E_OGGPLAY_OK = 0, /**< No error */
E_OGGPLAY_BAD_OGGPLAY = -1, /**< supplied oggplay is not a valid OggPlay */
E_OGGPLAY_BAD_READER = -2, /**< OggPlayReader is invalid */
E_OGGPLAY_BAD_INPUT = -3, /**< Error in the input */
E_OGGPLAY_NO_SUCH_CHUNK = -4,
E_OGGPLAY_BAD_TRACK = -5, /**< The requested track number does not exists */
E_OGGPLAY_TRACK_IS_SKELETON = -6, /**< Trying to activate a Skeleton track */
E_OGGPLAY_OGGZ_UNHAPPY = -7, /**< OGGZ error occured */
E_OGGPLAY_END_OF_FILE = -8, /**< End of file */
E_OGGPLAY_TRACK_IS_OVER = -9, /**< A given track has ended */
E_OGGPLAY_BAD_CALLBACK_INFO = -10, /**< Invalid OggPlayCallbackInfo */
E_OGGPLAY_WRONG_TRACK_TYPE = -11, /**< */
E_OGGPLAY_UNINITIALISED = -12, /**< The OggPlay handle is not initialised */
E_OGGPLAY_CALLBACK_MODE = -13, /**< OggPlay is used in callback mode */
E_OGGPLAY_BUFFER_MODE = -14, /**< OggPlay is used in buffer mode */
E_OGGPLAY_USER_INTERRUPT = -15, /**< User interrupt received */
E_OGGPLAY_SOCKET_ERROR = -16, /**< Error while creating socket */
E_OGGPLAY_TIMEOUT = -17, /**< TCP connection timeouted */
E_OGGPLAY_CANT_SEEK = -18, /**< Could not performed the requested seek */
E_OGGPLAY_NO_KATE_SUPPORT = -19, /**< LibKate is not supported */
E_OGGPLAY_NO_TIGER_SUPPORT = -20, /**< LibTiger is not supported */
E_OGGPLAY_OUT_OF_MEMORY = -21, /**< Out of memory */
E_OGGPLAY_TYPE_OVERFLOW = -22, /**< Integer overflow detected */
E_OGGPLAY_TRACK_IS_UNKNOWN = -23, /**< The selected track's content type is UNKNOWN */
E_OGGPLAY_TRACK_UNINITIALISED = -24, /**< Track is not initialised, i.e. bad headers or haven't seen them */
E_OGGPLAY_NOTCHICKENPAYBACK = -777
} OggPlayErrorCode;
/**
* Definitions of the various record types
*/
typedef enum OggPlayDataType {
OGGPLAY_INACTIVE = -1,
OGGPLAY_YUV_VIDEO = 0,
OGGPLAY_RGBA_VIDEO = 1,
OGGPLAY_SHORTS_AUDIO = 1000,
OGGPLAY_FLOATS_AUDIO = 1001,
OGGPLAY_CMML = 2000,
OGGPLAY_KATE = 3000,
OGGPLAY_TYPE_UNKNOWN = 9000 /* higher to be able to add more types without changing value */
OGGPLAY_INACTIVE = -1, /**< record is inactive */
OGGPLAY_YUV_VIDEO = 0, /**< record is a YUV format video */
OGGPLAY_RGBA_VIDEO = 1, /**< record is a video in RGB format */
OGGPLAY_SHORTS_AUDIO = 1000, /**< audio record in short format */
OGGPLAY_FLOATS_AUDIO = 1001, /**< audio record in float format */
OGGPLAY_CMML = 2000, /**< CMML record */
OGGPLAY_KATE = 3000, /**< KATE record */
OGGPLAY_TYPE_UNKNOWN = 9000 /**< content type of the record is unknown */
} OggPlayDataType;
/**
* Definitions of the various states of a stream.
*/
typedef enum OggPlayStreamInfo {
OGGPLAY_STREAM_UNINITIALISED = 0,
OGGPLAY_STREAM_FIRST_DATA = 1,
OGGPLAY_STREAM_INITIALISED = 2,
OGGPLAY_STREAM_LAST_DATA = 3,
OGGPLAY_STREAM_JUST_SEEKED = 4
OGGPLAY_STREAM_UNINITIALISED = 0, /**< Stream is not initialised */
OGGPLAY_STREAM_FIRST_DATA = 1, /**< Stream received it's first data frame */
OGGPLAY_STREAM_INITIALISED = 2, /**< Stream is initialised */
OGGPLAY_STREAM_LAST_DATA = 3, /**< Stream received it's last data frame */
OGGPLAY_STREAM_JUST_SEEKED = 4 /**< We've just seeked in the stream */
} OggPlayStreamInfo;
#endif

View File

@ -30,29 +30,86 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
/** @file
* oggplay_query.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Viktor Gal
*/
#ifndef __OGGPLAY_QUERY_H__
#define __OGGPLAY_QUERY_H__
#include <oggz/oggz.h>
/**
* Get the number of tracks in the Ogg container.
*
* @param me OggPlay handle
* @retval "> 0" number of tracks
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay
* @retval E_OGGPLAY_BAD_READER
* @retval E_OGGPLAY_UNINITIALISED the is not initialised.
*/
int
oggplay_get_num_tracks (OggPlay * me);
/**
* Retrieve the type of a track.
*
* @param me OggPlay handle
* @param track_num the desired track's number
* @retval "> 0" the track's type (see OggzStreamContent)
* @retval "< 0" error occured
*/
OggzStreamContent
oggplay_get_track_type (OggPlay * me, int track_num);
/**
* Get a track's type name.
*
* @param me OggPlay handle
* @param track_num the desired track's number
* @retval typa name of the track
* @retval NULL in case of error.
*/
const char *
oggplay_get_track_typename (OggPlay * me, int track_num);
/**
* Set a track active.
*
* @param me OggPlay handle
* @param track_num the desired track's number for activation
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay is invalid
* @retval E_OGGPLAY_BAD_READER the OggPlayReader associated with the Ogg
* container is invalid
* @retval E_OGGPLAY_UNINITIALISED the tracks are not initialised
* @retval E_OGGPLAY_BAD_TRACK invalid track number
* @retval E_OGGPLAY_TRACK_IS_SKELETON the chosen track is a Skeleton track
* @retval E_OGGPLAY_TRACK_IS_UNKNOWN the chosen track's content type is unknown
* @retval E_OGGPLAY_TRACK_UNINITIALISED the chosen track was not initialised
* @retval E_OGGPLAY_TRACK_IS_OVER the track is over.
*/
OggPlayErrorCode
oggplay_set_track_active(OggPlay *me, int track_num);
/**
* Inactivate a given track.
*
* @param me OggPlay handle
* @param track_num the desired track's number for inactivation
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay is invalid
* @retval E_OGGPLAY_BAD_READER the OggPlayReader associated with the Ogg
* container is invalid
* @retval E_OGGPLAY_UNINITIALISED the tracks are not initialised
* @retval E_OGGPLAY_BAD_TRACK invalid track number
* @retval E_OGGPLAY_TRACK_IS_SKELETON the chosen track is a Skeleton track
* @retval E_OGGPLAY_TRACK_IS_UNKNOWN the chosen track's content type is unknown
*/
OggPlayErrorCode
oggplay_set_track_inactive(OggPlay *me, int track_num);

View File

@ -30,9 +30,10 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
/** @file
* oggplay_reader.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
@ -46,15 +47,16 @@
struct _OggPlayReader;
/** */
typedef struct _OggPlayReader {
OggPlayErrorCode (*initialise)(struct _OggPlayReader * me, int block);
OggPlayErrorCode (*destroy)(struct _OggPlayReader * me);
OggPlayErrorCode (*seek)(struct _OggPlayReader *me, OGGZ *oggz,
ogg_int64_t milliseconds);
int (*available)(struct _OggPlayReader *me,
ogg_int64_t current_bytes,
ogg_int64_t current_time);
ogg_int64_t (*duration)(struct _OggPlayReader *me);
OggPlayErrorCode (*initialise) (struct _OggPlayReader * me, int block);
OggPlayErrorCode (*destroy) (struct _OggPlayReader * me);
OggPlayErrorCode (*seek) (struct _OggPlayReader *me, OGGZ *oggz,
ogg_int64_t milliseconds);
int (*available) (struct _OggPlayReader *me,
ogg_int64_t current_bytes,
ogg_int64_t current_time);
ogg_int64_t (*duration) (struct _OggPlayReader *me);
int (*finished_retrieving)(struct _OggPlayReader *me);
/* low-level io functions for oggz */
@ -68,10 +70,10 @@ typedef struct _OggPlayReader {
*
* @param filename The file to open
* @return A new OggPlayReader handle
* @retval NULL on error.
* @retval NULL if error occured.
*/
OggPlayReader *
oggplay_file_reader_new(char *filename);
oggplay_file_reader_new(const char *filename);
/**
* Create and initialise an OggPlayReader for an Ogg content at a given URI.
@ -83,6 +85,6 @@ oggplay_file_reader_new(char *filename);
* @retval NULL on error.
*/
OggPlayReader *
oggplay_tcp_reader_new(char *uri, char *proxy, int proxy_port);
oggplay_tcp_reader_new(const char *uri, const char *proxy, int proxy_port);
#endif

View File

@ -30,15 +30,26 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* oggplay_enums.h
/** @file
* oggplay_seek.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_SEEK_H__
#define __OGGPLAY_SEEK_H__
/**
* Seeks to a requested position.
*
* @param me OggPlay handle associated with the stream
* @param milliseconds
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay handle was invalid
* @retval E_OGGPLAY_CANT_SEEK error occured while trying to seek
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while trying to allocate the new buffer and trash.
*/
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);

View File

@ -30,9 +30,10 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
/** @file
* oggplay_tools.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
@ -53,24 +54,25 @@ extern "C" {
#include <time.h>
#endif
/* structure holds pointers to y, u, v channels */
/** structure holds pointers to y, u, v channels */
typedef struct _OggPlayYUVChannels {
unsigned char * ptry;
unsigned char * ptru;
unsigned char * ptrv;
int y_width;
int y_height;
int uv_width;
int uv_height;
unsigned char * ptry; /**< Y channel */
unsigned char * ptru; /**< U channel */
unsigned char * ptrv; /**< V channel*/
int y_width; /**< the width of the Y plane */
int y_height; /**< the height of the Y plane */
int uv_width; /**< the width of the U/V plane */
int uv_height; /**< the height of the U/V plane*/
} OggPlayYUVChannels;
/* structure holds pointers to y, u, v channels */
/** structure holds pointers to RGB packets */
typedef struct _OggPlayRGBChannels {
unsigned char * ptro;
int rgb_width;
int rgb_height;
unsigned char * ptro; /**< the RGB stream in the requested packaging format */
int rgb_width; /**< width of the RGB frame */
int rgb_height; /**< height of the RGB frame */
} OggPlayRGBChannels;
void
oggplay_yuv2rgba(const OggPlayYUVChannels *yuv, OggPlayRGBChannels * rgb);

View File

@ -0,0 +1,50 @@
commit 199a8cea6c4fd6d765254e7a384ac9df21ee2656
Author: Viktor Gal <viktor.gal@maeth.com>
Date: Fri May 8 15:44:51 2009 +1000
In the commit of 34c82de a bug was introduced in 'oggplay_data_handle_audio_data' function:
the number of samples in the record was not the correct value! The value of it
was incorrectly the size of the samples in the record.
diff --git a/src/liboggplay/oggplay_data.c b/src/liboggplay/oggplay_data.c
index 4df5275..9376938 100644
--- a/src/liboggplay/oggplay_data.c
+++ b/src/liboggplay/oggplay_data.c
@@ -301,6 +301,7 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int num_channels, ret;
size_t record_size = sizeof(OggPlayAudioRecord);
+ long samples_size;
OggPlayAudioRecord * record = NULL;
num_channels = ((OggPlayAudioDecode *)decode)->sound_info.channels;
@@ -310,17 +311,17 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
return E_OGGPLAY_TYPE_OVERFLOW;
}
- ret = oggplay_mul_signed_overflow (samples, num_channels, &samples);
+ ret = oggplay_mul_signed_overflow (samples, num_channels, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
- ret = oggplay_mul_signed_overflow (samples, samplesize, &samples);
+ ret = oggplay_mul_signed_overflow (samples_size, samplesize, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
- ret = oggplay_check_add_overflow (record_size, samples, &record_size);
+ ret = oggplay_check_add_overflow (record_size, samples_size, &record_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
@@ -339,7 +340,7 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
record->data = (void *)(record + 1);
/* copy the received data - the header has been initialised! */
- memcpy (record->data, data, samples);
+ memcpy (record->data, data, samples_size);
/*
printf("[%f%f%f]\n", ((float *)record->data)[0], ((float *)record->data)[1],
((float *)record->data)[2]);

View File

@ -1,12 +1,12 @@
diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/include/oggplay/oggplay_seek.h
--- a/media/liboggplay/include/oggplay/oggplay_seek.h
+++ b/media/liboggplay/include/oggplay/oggplay_seek.h
@@ -37,9 +37,20 @@
@@ -48,9 +48,20 @@
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay handle was invalid
* @retval E_OGGPLAY_CANT_SEEK error occured while trying to seek
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while trying to allocate the new buffer and trash.
*/
#ifndef __OGGPLAY_SEEK_H__
#define __OGGPLAY_SEEK_H__
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
@ -25,15 +25,16 @@ diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -73,16 +73,67 @@ oggplay_seek(OggPlay *me, ogg_int64_t mi
@@ -183,8 +183,59 @@ oggplay_take_out_trash(OggPlay *me, OggP
}
p = trash;
}
oggplay_seek_cleanup(me, milliseconds);
return E_OGGPLAY_OK;
if (p != NULL) {
oggplay_free(p);
}
}
+
+OggPlayErrorCode
+oggplay_seek_to_keyframe(OggPlay *me,
+ int* tracks,
@ -84,12 +85,3 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/s
+ return E_OGGPLAY_OK;
+
+}
+
void
oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
{
OggPlaySeekTrash * trash;
OggPlaySeekTrash ** p;
OggPlayDataHeader ** end_of_list_p;
int i;

View File

@ -17,7 +17,7 @@
#define HAVE_FISHSOUND /**/
/* Define if we have GLUT. */
#define HAVE_GLUT /**/
/* #undef HAVE_GLUT */
/* Define if have Imlib2 */
/* #undef HAVE_IMLIB2 */
@ -29,7 +29,7 @@
/* #undef HAVE_KATE */
/* Define if have libsndfile */
#define HAVE_LIBSNDFILE1 /**/
/* #undef HAVE_LIBSNDFILE1 */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@ -90,7 +90,7 @@
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.0.1"
#define VERSION "0.2.0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */

View File

@ -1,270 +1,284 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 *
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* *
********************************************************************
CPU capability detection for x86 processors.
Originally written by Rudolf Marek.
function:
last mod: $Id$
********************************************************************/
#include "cpu.h"
/* for detecting AltiVec support */
# if (defined(__ppc__) || defined(__ppc64__))
# if defined(__APPLE__) || defined(__MACOSX__)
#include <sys/sysctl.h>
# else
#include <signal.h>
#include <setjmp.h>
# endif
# endif
# if (defined(__ppc__) || defined(__ppc64__)) && !(defined(__APPLE__) || defined(__MACOSX__))
static jmp_buf jmpbuf;
static void illegal_instruction(int sig)
{
longjmp(jmpbuf, 1);
}
# endif
# if !defined(_MSC_VER)
# if defined(__amd64__)||defined(__x86_64__)
/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
compiling with -fPIC.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"cpuid\n\t" \
:[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# else
/*On x86-32, not so much.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"xchgl %%ebx,%[ebx]\n\t" \
"cpuid\n\t" \
"xchgl %%ebx,%[ebx]\n\t" \
:[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# endif
# else
/*Why does MSVC need this complicated rigamarole?
At this point I honestly do not care.*/
/*Visual C cpuid helper function.
For VS2005 we could as well use the _cpuid builtin, but that wouldn't work
for VS2003 users, so we do it in inline assembler.*/
static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){
_asm {
mov eax,[_op]
mov esi,_cpu_info
cpuid
mov [esi+0],eax
mov [esi+4],ebx
mov [esi+8],ecx
mov [esi+12],edx
}
}
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
do{ \
ogg_uint32_t cpu_info[4]; \
oc_cpuid_helper(cpu_info,_op); \
(_eax)=cpu_info[0]; \
(_ebx)=cpu_info[1]; \
(_ecx)=cpu_info[2]; \
(_edx)=cpu_info[3]; \
}while(0)
static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
_asm{
pushfd
pushfd
pop eax
mov ebx,eax
xor eax,200000h
push eax
popfd
pushfd
pop eax
popfd
mov ecx,_eax
mov [ecx],eax
mov ecx,_ebx
mov [ecx],ebx
}
}
# endif
static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
return flags;
}
static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
return flags;
}
static ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t flags = 0;
# if defined(__ppc__) || defined(__ppc64__)
/* detect AltiVec extension if compiling it for ppc */
# if defined(__APPLE__) || defined(__MACOSX__) || defined(__DARWIN__)
int selectors[2] = { CTL_HW, HW_VECTORUNIT };
int i_has_altivec = 0;
size_t i_length = sizeof( i_has_altivec );
int i_error = sysctl( selectors, 2, &i_has_altivec, &i_length, NULL, 0);
if( i_error == 0 && i_has_altivec != 0 )
flags |= OC_CPU_PPC_ALTIVEC;
# else
void (*handler) (int sig);
handler = signal(SIGILL, illegal_instruction);
if (setjmp(jmpbuf) == 0)
{
__asm__ __volatile__ (
"mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
: : "r"(-1) );
flags |= OC_CPU_PPC_ALTIVEC;
}
signal(SIGILL, handler);
# endif
/* detect x86 CPU extensions */
# elif defined(i386) || defined(__x86_64__) || defined(_M_IX86)
ogg_uint32_t eax;
ogg_uint32_t ebx;
ogg_uint32_t ecx;
ogg_uint32_t edx;
# if !defined(__amd64__)&&!defined(__x86_64__)
/*Not all x86-32 chips support cpuid, so we have to check.*/
# if !defined(_MSC_VER)
__asm__ __volatile__(
"pushfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"movl %[a],%[b]\n\t"
"xorl $0x200000,%[a]\n\t"
"pushl %[a]\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"popfl\n\t"
:[a]"=r"(eax),[b]"=r"(ebx)
:
:"cc"
);
# else
oc_detect_cpuid_helper(&eax,&ebx);
# endif
/*No cpuid.*/
if(eax==ebx)return 0;
# endif
cpuid(0,eax,ebx,ecx,edx);
/* l e t n I e n i u n e G*/
if((ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547)||
/* 6 8 x M T e n i u n e G*/
(ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547)) {
/*Intel, Transmeta (tested with Crusoe TM5800):*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
}
/* D M A c i t n e h t u A*/
else if((ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541)||
/* C S N y b e d o e G*/
(ecx==0x43534E20&&edx==0x79622065&&ebx==0x646F6547)){
/*AMD, Geode:*/
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax<0x80000001)flags=0;
else{
cpuid(0x80000001,eax,ebx,ecx,edx);
flags=oc_parse_amd_flags(edx,ecx);
}
/*Also check for SSE.*/
cpuid(1,eax,ebx,ecx,edx);
flags|=oc_parse_intel_flags(edx,ecx);
}
/*Technically some VIA chips can be configured in the BIOS to return any
string here the user wants.
There is a special detection method that can be used to identify such
processors, but in my opinion, if the user really wants to change it, they
deserve what they get.*/
/* s l u a H r u a t n e C*/
else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
/*VIA:*/
/*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
chips (thanks to the engineers from Centaur Technology who provided it).
These chips support Intel-like cpuid info.
The C3-2 (Nehemiah) cores appear to, as well.*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax>=0x80000001){
/*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
We need to check this even if the Intel test succeeds to pick up 3DNow!
support on these processors.
Unlike actual AMD processors, we cannot _rely_ on this info, since
some cores (e.g., the 693 stepping of the Nehemiah) claim to support
this function, yet return edx=0, despite the Intel test indicating
MMX support.
Therefore the features detected here are strictly added to those
detected by the Intel test.*/
/*TODO: How about earlier chips?*/
cpuid(0x80000001,eax,ebx,ecx,edx);
/*Note: As of the C7, this function returns Intel-style extended feature
flags, not AMD-style.
Currently, this only defines bits 11, 20, and 29 (0x20100800), which
do not conflict with any of the AMD flags we inspect.
For the remaining bits, Intel tells us, "Do not count on their value",
but VIA assures us that they will all be zero (at least on the C7 and
Isaiah chips).
In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
(0xC0C00000) for something else, we will have to add code to detect
the model to decide when it is appropriate to inspect them.*/
flags|=oc_parse_amd_flags(edx,ecx);
}
}
else{
/*Implement me.*/
flags=0;
}
# else
/* not x86 or ppc */
# endif
return flags;
}
/********************************************************************
* *
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 *
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* *
********************************************************************
CPU capability detection for x86 processors.
Originally written by Rudolf Marek.
function:
last mod: $Id$
********************************************************************/
#include "cpu.h"
/* for detecting AltiVec support */
# if (defined(__ppc__) || defined(__ppc64__))
# if defined(__APPLE__) || defined(__MACOSX__)
#include <sys/sysctl.h>
# else
#include <signal.h>
#include <setjmp.h>
# endif
# endif
# if (defined(__ppc__) || defined(__ppc64__)) && !(defined(__APPLE__) || defined(__MACOSX__))
static jmp_buf jmpbuf;
static void illegal_instruction(int sig)
{
longjmp(jmpbuf, 1);
}
# endif
#if defined(i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
# if !defined(_MSC_VER)
# if defined(__amd64__)||defined(__x86_64__)
/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
compiling with -fPIC.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"cpuid\n\t" \
:[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# else
/*On x86-32, not so much.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"xchgl %%ebx,%[ebx]\n\t" \
"cpuid\n\t" \
"xchgl %%ebx,%[ebx]\n\t" \
:[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# endif
# else
# if defined(_M_IX86)
/*Why does MSVC need this complicated rigamarole?
At this point I honestly do not care.*/
/*Visual C cpuid helper function.
For VS2005 we could as well use the _cpuid builtin, but that wouldn't work
for VS2003 users, so we do it in inline assembler.*/
static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){
_asm {
mov eax,[_op]
mov esi,_cpu_info
cpuid
mov [esi+0],eax
mov [esi+4],ebx
mov [esi+8],ecx
mov [esi+12],edx
}
}
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
do{ \
ogg_uint32_t cpu_info[4]; \
oc_cpuid_helper(cpu_info,_op); \
(_eax)=cpu_info[0]; \
(_ebx)=cpu_info[1]; \
(_ecx)=cpu_info[2]; \
(_edx)=cpu_info[3]; \
}while(0)
static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
_asm{
pushfd
pushfd
pop eax
mov ebx,eax
xor eax,200000h
push eax
popfd
pushfd
pop eax
popfd
mov ecx,_eax
mov [ecx],eax
mov ecx,_ebx
mov [ecx],ebx
}
}
# elif defined(_M_AMD64)
# include <intrin.h>
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
do{ \
int cpu_info[4]; \
__cpuid(cpu_info,_op); \
(_eax)=cpu_info[0]; \
(_ebx)=cpu_info[1]; \
(_ecx)=cpu_info[2]; \
(_edx)=cpu_info[3]; \
}while(0)
# endif
# endif
#endif /* x86-only cpuid */
static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
return flags;
}
static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
return flags;
}
static ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t flags = 0;
# if defined(__ppc__) || defined(__ppc64__)
/* detect AltiVec extension if compiling it for ppc */
# if defined(__APPLE__) || defined(__MACOSX__) || defined(__DARWIN__)
int selectors[2] = { CTL_HW, HW_VECTORUNIT };
int i_has_altivec = 0;
size_t i_length = sizeof( i_has_altivec );
int i_error = sysctl( selectors, 2, &i_has_altivec, &i_length, NULL, 0);
if( i_error == 0 && i_has_altivec != 0 )
flags |= OC_CPU_PPC_ALTIVEC;
# else
void (*handler) (int sig);
handler = signal(SIGILL, illegal_instruction);
if (setjmp(jmpbuf) == 0)
{
__asm__ __volatile__ (
"mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
: : "r"(-1) );
flags |= OC_CPU_PPC_ALTIVEC;
}
signal(SIGILL, handler);
# endif
/* detect x86 CPU extensions */
# elif defined(i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
ogg_uint32_t eax;
ogg_uint32_t ebx;
ogg_uint32_t ecx;
ogg_uint32_t edx;
# if !defined(__amd64__)&&!defined(__x86_64__)&&!defined(_M_AMD64)
/*Not all x86-32 chips support cpuid, so we have to check.*/
# if !defined(_MSC_VER)
__asm__ __volatile__(
"pushfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"movl %[a],%[b]\n\t"
"xorl $0x200000,%[a]\n\t"
"pushl %[a]\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"popfl\n\t"
:[a]"=r"(eax),[b]"=r"(ebx)
:
:"cc"
);
# else
oc_detect_cpuid_helper(&eax,&ebx);
# endif
/*No cpuid.*/
if(eax==ebx)return 0;
# endif
cpuid(0,eax,ebx,ecx,edx);
/* l e t n I e n i u n e G*/
if((ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547)||
/* 6 8 x M T e n i u n e G*/
(ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547)) {
/*Intel, Transmeta (tested with Crusoe TM5800):*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
}
/* D M A c i t n e h t u A*/
else if((ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541)||
/* C S N y b e d o e G*/
(ecx==0x43534E20&&edx==0x79622065&&ebx==0x646F6547)){
/*AMD, Geode:*/
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax<0x80000001)flags=0;
else{
cpuid(0x80000001,eax,ebx,ecx,edx);
flags=oc_parse_amd_flags(edx,ecx);
}
/*Also check for SSE.*/
cpuid(1,eax,ebx,ecx,edx);
flags|=oc_parse_intel_flags(edx,ecx);
}
/*Technically some VIA chips can be configured in the BIOS to return any
string here the user wants.
There is a special detection method that can be used to identify such
processors, but in my opinion, if the user really wants to change it, they
deserve what they get.*/
/* s l u a H r u a t n e C*/
else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
/*VIA:*/
/*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
chips (thanks to the engineers from Centaur Technology who provided it).
These chips support Intel-like cpuid info.
The C3-2 (Nehemiah) cores appear to, as well.*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax>=0x80000001){
/*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
We need to check this even if the Intel test succeeds to pick up 3DNow!
support on these processors.
Unlike actual AMD processors, we cannot _rely_ on this info, since
some cores (e.g., the 693 stepping of the Nehemiah) claim to support
this function, yet return edx=0, despite the Intel test indicating
MMX support.
Therefore the features detected here are strictly added to those
detected by the Intel test.*/
/*TODO: How about earlier chips?*/
cpuid(0x80000001,eax,ebx,ecx,edx);
/*Note: As of the C7, this function returns Intel-style extended feature
flags, not AMD-style.
Currently, this only defines bits 11, 20, and 29 (0x20100800), which
do not conflict with any of the AMD flags we inspect.
For the remaining bits, Intel tells us, "Do not count on their value",
but VIA assures us that they will all be zero (at least on the C7 and
Isaiah chips).
In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
(0xC0C00000) for something else, we will have to add code to detect
the model to decide when it is appropriate to inspect them.*/
flags|=oc_parse_amd_flags(edx,ecx);
}
}
else{
/*Implement me.*/
flags=0;
}
# else
/* not x86 or ppc */
# endif
return flags;
}

View File

@ -84,6 +84,10 @@ oggplay_initialise(OggPlay *me, int block) {
OggPlayErrorCode return_val;
int i;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
return_val = me->reader->initialise(me->reader, block);
if (return_val != E_OGGPLAY_OK) {
@ -118,9 +122,31 @@ oggplay_initialise(OggPlay *me, int block) {
return E_OGGPLAY_OGGZ_UNHAPPY;
while (1) {
i = oggz_read (me->oggz, OGGZ_READ_CHUNK_SIZE);
switch (i) {
case 0:
/*
* EOF reached while processing headers,
* possible erroneous file, mark it as such.
*/
case OGGZ_ERR_HOLE_IN_DATA:
/* there was a whole in the data */
return E_OGGPLAY_BAD_INPUT;
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
case OGGZ_ERR_STOP_ERR:
/* */
return E_OGGPLAY_BAD_OGGPLAY;
if (oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE) <= 0) {
return E_OGGPLAY_BAD_INPUT;
default:
/* If the read otherwise failed, bail out. */
if (i < 0)
return E_OGGPLAY_BAD_INPUT;
break;
}
if (me->all_tracks_initialised) {
@ -153,7 +179,7 @@ oggplay_open_with_reader(OggPlayReader *reader) {
OggPlay *me = NULL;
int r = E_OGGPLAY_TIMEOUT;
if ( (me = oggplay_new_with_reader(reader)) == NULL)
if ((me = oggplay_new_with_reader(reader)) == NULL)
return NULL;
while (r == E_OGGPLAY_TIMEOUT) {
@ -161,6 +187,7 @@ oggplay_open_with_reader(OggPlayReader *reader) {
}
if (r != E_OGGPLAY_OK) {
/* in case of error close the OggPlay handle */
oggplay_close(me);
@ -197,7 +224,7 @@ oggplay_set_data_callback(OggPlay *me, OggPlayDataCallback callback,
*/
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user) {
void *user) {
me->callback = callback;
me->callback_user_ptr = user;
@ -315,7 +342,7 @@ oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* a
}
OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert) {
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb) {
OggPlayTheoraDecode *decode;
if (me == NULL) {
@ -332,8 +359,9 @@ oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert) {
decode = (OggPlayTheoraDecode *)(me->decode_data[track]);
if (decode->convert_to_rgb != convert) {
if (decode->convert_to_rgb != convert || decode->swap_rgb != swap_rgb) {
decode->convert_to_rgb = convert;
decode->swap_rgb = swap_rgb;
me->decode_data[track]->decoded_type = convert ? OGGPLAY_RGBA_VIDEO : OGGPLAY_YUV_VIDEO;
/* flush any records created with previous type */
@ -479,8 +507,8 @@ oggplay_get_kate_category(OggPlay *me, int track, const char** category) {
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
if (decode->init) {
(*category) = decode->k.ki->category;
if (decode->decoder.initialised) {
(*category) = decode->k_state.ki->category;
return E_OGGPLAY_OK;
}
else return E_OGGPLAY_UNINITIALISED;
@ -509,8 +537,8 @@ oggplay_get_kate_language(OggPlay *me, int track, const char** language) {
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
if (decode->init) {
(*language) = decode->k.ki->language;
if (decode->decoder.initialised) {
(*language) = decode->k_state.ki->language;
return E_OGGPLAY_OK;
}
else return E_OGGPLAY_UNINITIALISED;
@ -520,7 +548,7 @@ oggplay_get_kate_language(OggPlay *me, int track, const char** language) {
}
OggPlayErrorCode
oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger) {
oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger, int swap_rgb, int default_width, int default_height) {
OggPlayKateDecode * decode;
@ -540,8 +568,11 @@ oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger) {
#ifdef HAVE_KATE
#ifdef HAVE_TIGER
if (decode->init && decode->tr) {
if (decode->decoder.initialised && decode->tr) {
decode->use_tiger = use_tiger;
decode->swap_rgb = swap_rgb;
decode->default_width = default_width;
decode->default_height = default_height;
decode->decoder.decoded_type = use_tiger ? OGGPLAY_RGBA_VIDEO : OGGPLAY_KATE;
return E_OGGPLAY_OK;
}
@ -615,13 +646,28 @@ oggplay_step_decoding(OggPlay *me) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
/*
* check whether the OggPlayDataCallback is set for the given
* OggPlay handle. If not return with error as there's no callback
* function processing the decoded data.
*/
if (me->callback == NULL) {
return E_OGGPLAY_UNINITIALISED;
}
/*
* clean up any trash pointers. As soon as the current buffer has a
* frame taken out, we know the old buffer will no longer be used.
*/
if (me->trash != NULL && me->buffer->last_emptied > -1) {
if
(
me->trash != NULL
&&
(me->buffer == NULL || me->buffer->last_emptied > -1)
)
{
oggplay_take_out_trash(me, me->trash);
me->trash = NULL;
}
@ -691,36 +737,58 @@ read_more_data:
r = oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE);
/* end-of-file */
if (r == 0) {
num_records = oggplay_callback_info_prepare(me, &info);
/*
* set all of the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
me->active_tracks = 0;
switch (r) {
case 0:
/* end-of-file */
num_records = oggplay_callback_info_prepare(me, &info);
/*
* set all of the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
me->active_tracks = 0;
if (info != NULL) {
me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy(me, info);
}
if (info != NULL) {
me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy(me, info);
}
/*
* ensure all tracks have their final data packet set to end_of_stream
* But skip doing this if we're shutting down --- me->buffer may not
* be in a safe state.
*/
if (me->buffer != NULL && !me->shutdown) {
oggplay_buffer_set_last_data(me, me->buffer);
}
/*
* ensure all tracks have their final data packet set to end_of_stream
* But skip doing this if we're shutting down --- me->buffer may not
* be in a safe state.
*/
if (me->buffer != NULL && !me->shutdown) {
oggplay_buffer_set_last_data(me, me->buffer);
}
return E_OGGPLAY_OK;
} else if (r == OGGZ_ERR_HOLE_IN_DATA) {
return E_OGGPLAY_BAD_INPUT;
/* we reached the end of the stream */
return E_OGGPLAY_OK;
case OGGZ_ERR_HOLE_IN_DATA:
/* there was a whole in the data */
return E_OGGPLAY_BAD_INPUT;
case OGGZ_ERR_STOP_ERR:
/*
* one of the callback functions requested us to stop.
* as this currently happens only when one of the
* OggzReadPacket callback functions does not receive
* the user provided data, i.e. the OggPlayDecode struct
* for the track mark it as a memory problem, since this
* could happen only if something is wrong with the memory,
* e.g. some buffer overflow.
*/
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
default:
break;
}
}
/*
* prepare a callback
@ -739,11 +807,21 @@ read_more_data:
for (i = 0; i < me->num_tracks; i++) {
oggplay_data_clean_list (me->decode_data[i]);
}
/*
* there was an error during info prepare!
* abort decoding!
*/
if (num_records < 0) {
return num_records;
}
/* if we received an shutdown event, dont try to read more data...*/
if (me->shutdown) {
return E_OGGPLAY_OK;
}
/* we require more data for decoding */
if (info == NULL) {
goto read_more_data;
}
@ -784,8 +862,8 @@ oggplay_close(OggPlay *me) {
me->reader->destroy(me->reader);
}
if (me->decode_data) {
/* */
if (me->decode_data != NULL) {
for (i = 0; i < me->num_tracks; i++) {
oggplay_callback_shutdown(me->decode_data[i]);
}
@ -798,7 +876,10 @@ oggplay_close(OggPlay *me) {
oggplay_buffer_shutdown(me, me->buffer);
}
oggplay_free(me->callback_info);
if (me->callback_info != NULL) {
oggplay_free(me->callback_info);
}
oggplay_free(me->decode_data);
oggplay_free(me);

View File

@ -99,21 +99,34 @@ oggplay_buffer_shutdown(OggPlay *me, volatile OggPlayBuffer *vbuffer) {
int j;
OggPlayBuffer *buffer = (OggPlayBuffer *)vbuffer;
for (i = 0; i < buffer->buffer_size; i++) {
if (buffer->buffer_mirror[i] != NULL) {
OggPlayCallbackInfo *ti = (OggPlayCallbackInfo *)buffer->buffer_mirror[i];
for (j = 0; j < me->num_tracks; j++) {
oggplay_free((ti + j)->records);
}
oggplay_free(ti);
}
if (buffer == NULL) {
return;
}
oggplay_free(buffer->buffer_list);
oggplay_free(buffer->buffer_mirror);
if (buffer->buffer_mirror != NULL) {
for (i = 0; i < buffer->buffer_size; i++) {
if (buffer->buffer_mirror[i] != NULL) {
OggPlayCallbackInfo *ti = (OggPlayCallbackInfo *)buffer->buffer_mirror[i];
for (j = 0; j < me->num_tracks; j++) {
if ( (ti+j) != NULL) {
oggplay_free((ti + j)->records);
}
}
oggplay_free(ti);
}
}
oggplay_free(buffer->buffer_mirror);
}
if (buffer->buffer_list != NULL)
oggplay_free(buffer->buffer_list);
SEM_CLOSE(buffer->frame_sem);
oggplay_free(buffer);
buffer = NULL;
}
int
@ -154,7 +167,7 @@ oggplay_buffer_set_last_data(OggPlay *me, volatile OggPlayBuffer *buffer)
int
oggplay_buffer_callback(OggPlay *me, int tracks,
OggPlayCallbackInfo **track_info, void *user) {
OggPlayCallbackInfo **track_info, void *user) {
int i;
int j;
@ -199,7 +212,8 @@ oggplay_buffer_callback(OggPlay *me, int tracks,
(buffer->buffer_list[k] == NULL)
&&
(buffer->buffer_mirror[k] != NULL)
) {
)
{
OggPlayCallbackInfo *ti = (OggPlayCallbackInfo *)buffer->buffer_mirror[k];
for (i = 0; i < tracks; i++) {
headers = oggplay_callback_info_get_headers(ti + i);
@ -210,7 +224,9 @@ oggplay_buffer_callback(OggPlay *me, int tracks,
/* free these here, because we couldn't free them in
* oggplay_callback_info_destroy for buffer mode
*/
oggplay_free((ti + i)->records);
if ((ti + i) != NULL) {
oggplay_free((ti + i)->records);
}
}
oggplay_free(ti);
buffer->buffer_mirror[k] = NULL;
@ -254,7 +270,7 @@ oggplay_buffer_callback(OggPlay *me, int tracks,
OggPlayCallbackInfo **
oggplay_buffer_retrieve_next(OggPlay *me) {
OggPlayBuffer * buffer;
OggPlayBuffer * buffer = NULL;
int next_loc;
OggPlayCallbackInfo * next_item;
OggPlayCallbackInfo ** return_val;
@ -280,9 +296,10 @@ oggplay_buffer_retrieve_next(OggPlay *me) {
buffer->last_emptied = next_loc;
return_val = oggplay_calloc(me->num_tracks, sizeof (OggPlayCallbackInfo *));
if (return_val == NULL)
if (return_val == NULL) {
return NULL;
}
for (i = 0; i < me->num_tracks; i++) {
return_val[i] = next_item + i;
}
@ -294,7 +311,7 @@ oggplay_buffer_retrieve_next(OggPlay *me) {
OggPlayErrorCode
oggplay_buffer_release(OggPlay *me, OggPlayCallbackInfo **track_info) {
OggPlayBuffer *buffer;
OggPlayBuffer *buffer = NULL;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
@ -314,7 +331,9 @@ oggplay_buffer_release(OggPlay *me, OggPlayCallbackInfo **track_info) {
return E_OGGPLAY_UNINITIALISED;
}
oggplay_free(track_info);
if (track_info != NULL) {
oggplay_free(track_info);
}
buffer->buffer_list[buffer->last_emptied] = NULL;

View File

@ -46,28 +46,42 @@
#include <time.h>
#include <string.h>
#define THEORA_VERSION(maj,min,rev) ((maj<<16)+(min<<8)+rev)
void
oggplay_init_theora(void *user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
if (decoder == NULL) {
return;
}
theora_info_init(&(decoder->video_info));
theora_comment_init(&(decoder->video_comment));
decoder->remaining_header_packets = 3;
decoder->granulepos_seen = 0;
decoder->frame_delta = 0;
decoder->y_width = 0;
decoder->convert_to_rgb = 0;
decoder->swap_rgb = 0;
decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO;
decoder->decoder.player->active_tracks++;
}
void
oggplay_shutdown_theora(void *user_data) {
OggPlayDecode * common;
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
if (decoder->remaining_header_packets == 0) {
if (decoder == NULL) {
return;
}
if ((common = &(decoder->decoder)) == NULL) {
return;
}
if (common->initialised == 1 && decoder->decoder.num_header_packets == 0) {
theora_clear(&(decoder->video_handle));
}
theora_info_clear(&(decoder->video_info));
@ -76,80 +90,122 @@ oggplay_shutdown_theora(void *user_data) {
int
oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
void * user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
OggPlayDecode * common = NULL;
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
yuv_buffer buffer;
int granuleshift;
long frame;
int granuleshift;
long frame;
OggPlayErrorCode ret;
/* check whether user_data is valid */
if (decoder == NULL) {
return OGGZ_STOP_ERR;
}
if ((common = &(decoder->decoder)) == NULL) {
return OGGZ_STOP_ERR;
}
#if TIME_THEORA_DECODE
struct timeval tv;
struct timeval tv2;
int musec;
#endif
if ( (granulepos > 0) && (common->last_granulepos > granulepos)) {
if (!common->active) {
/*
* don't decode other packets
*/
return OGGZ_CONTINUE;
}
if ((granulepos > 0) && (common->last_granulepos > granulepos)) {
/*
* the granule position is not monotonically increasing,
* something wrong with the page!
* skipping this page.....
*/
return 0;
return OGGZ_CONTINUE;
}
/*
* always decode headers
*/
if (theora_packet_isheader(op)) {
if (theora_decode_header(&(decoder->video_info), &(decoder->video_comment), op) < 0)
return -1;
if (theora_packet_isheader(op) &&
common->num_header_packets > 0 &&
common->initialised != -1)
{
if (theora_decode_header(&(decoder->video_info), &(decoder->video_comment), op) < 0) {
common->initialised |= -1;
return OGGZ_CONTINUE;
}
/*
* initialise width/stride/height data (this is common to all frames).
* Use the buffer stride for the width to avoid passing negative stride
* issues on to the user.
*/
decoder->y_width = decoder->y_stride = decoder->video_info.frame_width;
decoder->y_height = decoder->video_info.frame_height;
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height / 2;
if (decoder->y_width == 0 ||
decoder->y_height == 0 ||
decoder->uv_width == 0 ||
decoder->uv_height == 0) {
decoder->decoder.active = 0;
return 0;
}
if (--(decoder->remaining_header_packets) == 0) {
if (--(common->num_header_packets) == 0) {
decoder->y_width = decoder->y_stride = decoder->video_info.frame_width;
decoder->y_height = decoder->video_info.frame_height;
if (decoder->video_info.pixelformat == OC_PF_444) {
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width;
decoder->uv_height = decoder->video_info.frame_height;
} else if (decoder->video_info.pixelformat == OC_PF_422) {
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height;
} else if (decoder->video_info.pixelformat == OC_PF_420) {
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height / 2;
} else {
common->initialised |= -1;
return OGGZ_CONTINUE;
}
if (decoder->y_width == 0 ||
decoder->y_height == 0 ||
decoder->uv_width == 0 ||
decoder->uv_height == 0) {
/* it's a theora track with one of it's plane's dimension 0
* decoding this track is not possible.
*/
common->initialised |= -1;
return OGGZ_CONTINUE;
}
/* Ensure the offsets do not push the viewable area outside of the decoded frame. */
if (((decoder->video_info.height - decoder->video_info.offset_y)<decoder->video_info.frame_height)||
((decoder->video_info.width - decoder->video_info.offset_x)<decoder->video_info.frame_width))
return -1;
theora_decode_init(&(decoder->video_handle), &(decoder->video_info));
if
(
((decoder->video_info.height - decoder->video_info.offset_y)<decoder->video_info.frame_height)
||
((decoder->video_info.width - decoder->video_info.offset_x)<decoder->video_info.frame_width)
)
{
common->initialised |= -1;
return OGGZ_CONTINUE;
}
if (theora_decode_init(&(decoder->video_handle), &(decoder->video_info))) {
common->initialised |= -1;
return OGGZ_CONTINUE;
}
common->initialised |= 1;
}
return 0;
}
else if (decoder->remaining_header_packets != 0) {
return OGGZ_CONTINUE;
} else if (common->num_header_packets != 0) {
/*
* Invalid Ogg file. Missing headers
*
*/
return -1;
}
if (!decoder->decoder.active) {
/*
* don't decode other packets
*/
return 0;
}
/*
* if we get to here then we've passed all the header packets
*/
@ -164,11 +220,13 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
gettimeofday(&tv, NULL);
#endif
if (theora_decode_packetin(&(decoder->video_handle), op) < 0)
return -1;
if (theora_decode_packetin(&(decoder->video_handle), op) < 0) {
return OGGZ_CONTINUE;
}
if (theora_decode_YUVout(&(decoder->video_handle), &buffer) < 0)
return -1;
if (theora_decode_YUVout(&(decoder->video_handle), &buffer) < 0) {
return OGGZ_CONTINUE;
}
#if TIME_THEORA_DECODE
gettimeofday(&tv2, NULL);
@ -179,6 +237,11 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
#endif
if (granulepos != -1) {
int version =
THEORA_VERSION(decoder->video_info.version_major,
decoder->video_info.version_minor,
decoder->video_info.version_subminor);
/*
* save last granule position in order to be able to validate
* that it's monotonically increasing
@ -188,6 +251,17 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
/* calculate the frame number */
granuleshift = oggz_get_granuleshift(oggz, serialno);
frame = (granulepos >> granuleshift);
/* From theora bitstream version 3.2.1 onwards, frame granule numbers are
* relative to the end of the frame, i.e. frame granule numbers start at 1.
* We calcualte the presentation time as frame_number * granule_period,
* but that's only correct if frame numbers start at 0 (else it's the end
* time), so subtract 1 from the frame number if this is a theora stream
* of version 3.2.1 or greater to ensure correct presentation time
* calculation.
*/
if (version >= THEORA_VERSION(3,2,1)) {
frame--;
}
frame += (granulepos & ((1 << granuleshift) - 1));
/* calculate the current location in the stream */
@ -207,8 +281,11 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
* store the frame,
* use the buffer stride for the width to avoid passing negative stride
* issues on to the user.
* */
oggplay_data_handle_theora_frame(decoder, &buffer);
*/
ret = oggplay_data_handle_theora_frame(decoder, &buffer);
if (ret != E_OGGPLAY_CONTINUE) {
return OGGZ_ERR_OUT_OF_MEMORY;
}
}
if (op->e_o_s) {
@ -216,7 +293,7 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
common->player->active_tracks--;
}
return 0;
return OGGZ_CONTINUE;
}
@ -224,35 +301,72 @@ void
oggplay_init_cmml (void * user_data) {
OggPlayCmmlDecode * decoder = (OggPlayCmmlDecode *)user_data;
if (decoder == NULL) {
return;
}
decoder->decoder.decoded_type = OGGPLAY_CMML;
decoder->granuleshift = 32; /* default */
}
int
oggplay_callback_cmml (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
void * user_data) {
OggPlayCmmlDecode * decoder = (OggPlayCmmlDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
OggPlayDecode * common = NULL;
ogg_int64_t granulepos = oggz_tell_granulepos (oggz);
OggPlayErrorCode ret;
if (decoder == NULL) {
return OGGZ_STOP_ERR;
}
if ((common = &(decoder->decoder)) == NULL) {
return OGGZ_STOP_ERR;
}
if (granulepos == 0) {
if (memcmp(op->packet, "CMML\0\0\0\0", 8) == 0) {
decoder->granuleshift = op->packet[28];
if (common->num_header_packets) {
/*
* Process the headers of the CMML stream.
*/
if (common->num_header_packets == 3) {
/* The CMML ident header packet */
if (memcmp(op->packet, "CMML\0\0\0\0", 8) == 0) {
decoder->granuleshift = op->packet[28];
} else {
/* Missing ident header ... */
common->initialised |= -1;
}
} else if (common->num_header_packets == 2) {
/* CMML secondary header, with xml preamble and cmml tag */
} else if (common->num_header_packets == 1) {
/* CMML secondary header, head tag */
}
} else {
if (!(--common->num_header_packets))
common->initialised |= 1;
} else {
/*
* Process the CMML stream content.
*/
if (decoder->granuleshift > 0) {
granulepos >>= decoder->granuleshift;
}
common->current_loc = granulepos * common->granuleperiod;
common->last_granulepos = granulepos;
oggplay_data_handle_cmml_data (&(decoder->decoder), op->packet, op->bytes);
ret = oggplay_data_handle_cmml_data (common, op->packet, op->bytes);
if (ret != E_OGGPLAY_CONTINUE) {
return OGGZ_ERR_OUT_OF_MEMORY;
}
}
return 0;
return OGGZ_CONTINUE;
}
@ -276,10 +390,15 @@ static inline ogg_int64_t extract_int64(unsigned char *data) {
int
oggplay_callback_skel (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
void * user_data) {
OggPlaySkeletonDecode * decoder = (OggPlaySkeletonDecode *)user_data;
/* check whether user_input is valid */
if (decoder == NULL) {
return OGGZ_STOP_ERR;
}
if (strncmp((char *)op->packet, "fishead", 7) == 0) {
ogg_int64_t pt_num, pt_den, bt_num, bt_den;
@ -301,30 +420,42 @@ oggplay_callback_skel (OGGZ * oggz, ogg_packet * op, long serialno,
/* initialise the presentation times in the player to the values recorded in the skeleton */
decoder->decoder.player->presentation_time = decoder->presentation_time;
decoder->decoder.initialised = 1;
decoder->decoder.num_header_packets--;
} else {
int i;
long preroll = extract_int32(op->packet + 44);
long serialno = extract_int32(op->packet + 12);
OggPlay * player = decoder->decoder.player;
//ogg_int64_t start_granule = extract_int64(op->packet + 36);
for (i = 1; i < decoder->decoder.player->num_tracks; i++) {
if (decoder->decoder.player->decode_data[i]->serialno == serialno) {
decoder->decoder.player->decode_data[i]->preroll = preroll;
for (i = 1; i < player->num_tracks; i++) {
if (player->decode_data[i]->serialno == serialno) {
player->decode_data[i]->preroll = preroll;
break;
}
}
}
return 0;
return OGGZ_CONTINUE;
}
int
oggplay_fish_sound_callback_floats(FishSound * fsound, float ** pcm,
long frames, void *user_data) {
long frames, void *user_data) {
OggPlayAudioDecode *decoder = (OggPlayAudioDecode *)user_data;
OggPlayDecode *common = &(decoder->decoder);
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
OggPlayDecode * common = NULL;
if (decoder == NULL) {
return FISH_SOUND_STOP_ERR;
}
if ((common = &(decoder->decoder)) == NULL) {
return FISH_SOUND_STOP_ERR;
}
/*
* calculate the current location here so that it's only updated when
@ -343,15 +474,13 @@ oggplay_fish_sound_callback_floats(FishSound * fsound, float ** pcm,
(common->current_loc >= common->player->presentation_time)
)
{
/*
* store the frame
*/
oggplay_data_handle_audio_data(&(decoder->decoder), (short *)pcm, frames,
sizeof(float));
oggplay_data_handle_audio_data(common, (short *)pcm,
frames, sizeof(float));
return FISH_SOUND_STOP_ERR;
return FISH_SOUND_STOP_ERR;
}
return FISH_SOUND_CONTINUE;
@ -361,15 +490,22 @@ void
oggplay_init_audio (void * user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
if (decoder == NULL) {
return;
}
decoder->sound_handle = fish_sound_new(FISH_SOUND_DECODE,
&(decoder->sound_info));
&(decoder->sound_info));
if (decoder->sound_handle == NULL) {
return;
}
decoder->sound_info.channels = 0;
fish_sound_set_interleave(decoder->sound_handle, 1);
fish_sound_set_decoded_float_ilv(decoder->sound_handle,
oggplay_fish_sound_callback_floats,
(void *)decoder);
oggplay_fish_sound_callback_floats,
(void *)decoder);
decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO;
decoder->decoder.player->active_tracks++;
@ -379,28 +515,79 @@ void
oggplay_shutdown_audio(void *user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
if (decoder == NULL) {
return;
}
fish_sound_delete(decoder->sound_handle);
}
int
oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
void * user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
OggPlayDecode * common = NULL;
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
long bytes_read;
if (granulepos > 0 && (!decoder->decoder.active)) {
return 0;
/* check user input (user_data) */
if (decoder == NULL) {
return OGGZ_STOP_ERR;
}
if ((common = &(decoder->decoder)) == NULL) {
return OGGZ_STOP_ERR;
}
if (granulepos > 0 && (!common->active)) {
return OGGZ_CONTINUE;
}
if ((granulepos > 0) && (common->last_granulepos > granulepos)) {
return OGGZ_CONTINUE;
}
/* Blindly register that we've processed a header packet. */
if (common->num_header_packets) --common->num_header_packets;
common->last_granulepos = granulepos;
fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
op->e_o_s);
if (fish_sound_decode (decoder->sound_handle, op->packet, op->bytes) == -1) {
fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
op->e_o_s);
bytes_read = fish_sound_decode (decoder->sound_handle, op->packet, op->bytes);
switch (bytes_read) {
case FISH_SOUND_ERR_OUT_OF_MEMORY:
/* we ran out of memory... stop decoding. */
return OGGZ_ERR_OUT_OF_MEMORY;
case FISH_SOUND_ERR_GENERIC:
{
/*
* error occured while decoding the audio track
* disable the track, but if there are other tracks to decode
* contine decoding...
*/
common->active = 0;
if (common->player->active_tracks) common->player->active_tracks--;
if (common->num_header_packets >= 0) common->initialised |= -1;
return OGGZ_CONTINUE;
}
default:
/* there was no problem with decoding */
if (!common->num_header_packets) common->initialised |= 1;
break;
}
if (bytes_read < 0) {
printf("\nERROR HADNLING MISMATCH BETWEEN liboggplay AND mozilla\n\n");
// Unrecoverable error, disable track
op->e_o_s = 1;
common->active = 0;
@ -408,9 +595,10 @@ oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
return OGGZ_ERR_HOLE_IN_DATA;
}
if (decoder->sound_info.channels == 0) {
fish_sound_command(decoder->sound_handle, FISH_SOUND_GET_INFO,
&(decoder->sound_info), sizeof(FishSoundInfo));
&(decoder->sound_info), sizeof(FishSoundInfo));
}
if (op->e_o_s) {
@ -418,7 +606,7 @@ oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
common->player->active_tracks--;
}
return 0;
return OGGZ_CONTINUE;
}
void
@ -428,19 +616,20 @@ oggplay_init_kate(void *user_data) {
int ret;
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
decoder->init = 0;
ret = kate_high_decode_init(&(decoder->k));
if (ret < 0) {
/* what to do ? */
}
else {
decoder->init = 1;
if (decoder == NULL) {
return;
}
decoder->decoder.decoded_type = OGGPLAY_KATE;
kate_info_init (&(decoder->k_info));
kate_comment_init (&(decoder->k_comment));
#ifdef HAVE_TIGER
decoder->use_tiger = 1;
decoder->overlay_dest = -1;
decoder->swap_rgb = 0;
decoder->default_width = -1;
decoder->default_height = -1;
ret = tiger_renderer_create(&(decoder->tr));
if (ret < 0) {
@ -460,26 +649,33 @@ oggplay_shutdown_kate(void *user_data) {
#ifdef HAVE_KATE
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
if (decoder == NULL) {
return;
}
#ifdef HAVE_TIGER
if (decoder->tr) {
tiger_renderer_destroy(decoder->tr);
}
#endif
if (decoder->init) {
kate_high_decode_clear(&(decoder->k));
if (decoder->decoder.initialised == 1) {
kate_clear (&(decoder->k_state));
}
kate_info_clear (&(decoder->k_info));
kate_comment_clear (&(decoder->k_comment));
#endif
}
int
oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
void * user_data) {
#ifdef HAVE_KATE
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
OggPlayDecode * common = NULL;
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
int granuleshift;
ogg_int64_t base, offset;
@ -487,22 +683,75 @@ oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
const kate_event *ev = NULL;
int ret;
if (!decoder->init) {
return E_OGGPLAY_UNINITIALISED;
/*
* Basic error checking.
*/
if (decoder == NULL) {
return OGGZ_STOP_ERR;
}
if ((common = &(decoder->decoder)) == NULL) {
return OGGZ_STOP_ERR;
}
kate_packet_wrap(&kp, op->bytes, op->packet);
ret = kate_high_decode_packetin(&(decoder->k), &kp, &ev);
/*
* Stop processing the Ogg packet if the stream is not active.
*/
if (!common->active) {
return OGGZ_CONTINUE;
}
/* create a kate_packet from the received ogg_packet */
kate_packet_wrap (&kp, op->bytes, op->packet);
/*
* Decode the headers of the kate stream.
*/
if (common->num_header_packets) {
ret = kate_decode_headerin (&(decoder->k_info), &(decoder->k_comment), &kp);
if (ret == KATE_E_OUT_OF_MEMORY) {
return OGGZ_ERR_OUT_OF_MEMORY;
}
common->initialised |= (ret < 0 ? -1 : ret);
common->num_header_packets--;
/* if we _successfully_ processed all the headers initialise the decoder */
if (!common->num_header_packets && (common->initialised == 1)) {
ret = kate_decode_init (&(decoder->k_state), &(decoder->k_info));
if (ret == KATE_E_OUT_OF_MEMORY) {
return OGGZ_ERR_OUT_OF_MEMORY;
} else if (ret < 0) {
common->initialised |= -1;
}
}
return OGGZ_CONTINUE;
}
/*
* Decode the payload of the stream.
*/
ret = kate_decode_packetin (&(decoder->k_state), &kp);
if (ret == KATE_E_OUT_OF_MEMORY) {
return OGGZ_ERR_OUT_OF_MEMORY;
} else if (ret < 0){
return OGGZ_CONTINUE;
}
ret = kate_decode_eventout (&(decoder->k_state), &ev);
if (ret < 0) {
return E_OGGPLAY_BAD_INPUT;
return OGGZ_CONTINUE;
}
if (granulepos != -1) {
granuleshift = oggz_get_granuleshift(oggz, serialno);
base = (granulepos >> granuleshift);
offset = granulepos - (base << granuleshift);
common->current_loc = (base+offset) * common->granuleperiod;
common->last_granulepos = granulepos;
} else {
common->current_loc = -1;
}
@ -518,7 +767,9 @@ oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
* process the data from the packet
* */
if (ev) {
oggplay_data_handle_kate_data(decoder, ev);
if (oggplay_data_handle_kate_data(decoder, ev) != E_OGGPLAY_CONTINUE) {
return OGGZ_ERR_OUT_OF_MEMORY;
}
}
}
@ -528,7 +779,7 @@ oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
#endif
return 0;
return OGGZ_CONTINUE;
}
@ -540,10 +791,10 @@ OggPlayCallbackFunctions callbacks[] = {
{oggplay_init_audio, oggplay_callback_audio, oggplay_shutdown_audio,
sizeof(OggPlayAudioDecode)}, /* SPEEX */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* PCM */
{oggplay_init_cmml, oggplay_callback_cmml, NULL, sizeof(OggPlayCmmlDecode)},
{oggplay_init_cmml, oggplay_callback_cmml, NULL, sizeof(OggPlayCmmlDecode)}, /* CMML */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* ANX2 */
{oggplay_init_skel, oggplay_callback_skel, NULL,
sizeof(OggPlaySkeletonDecode)},
sizeof(OggPlaySkeletonDecode)}, /* SKELETON */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* FLAC0 */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* FLAC */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* ANXDATA */
@ -555,7 +806,7 @@ OggPlayCallbackFunctions callbacks[] = {
};
OggPlayDecode *
oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
oggplay_initialise_decoder(OggPlay *me, int content_type, long serialno) {
ogg_int64_t num;
ogg_int64_t denom;
@ -577,6 +828,8 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
decoder->final_granulepos = -1;
decoder->player = me;
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
decoder->num_header_packets =
oggz_stream_get_numheaders (me->oggz, serialno);
/*
* set the StreamInfo to unitialised until we get some real data in
@ -587,7 +840,7 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
* set to -1 until headers decoded
*/
decoder->current_loc = -1;
decoder->last_granulepos = -1;
decoder->last_granulepos = 0;
/*
* the offset is how far advanced or delayed this track is to the "standard"
@ -606,9 +859,12 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
} else {
decoder->granuleperiod = 0;
}
if (callbacks[content_type].init != NULL) {
callbacks[content_type].init(decoder);
decoder->initialised = 0;
} else {
decoder->initialised = -1;
}
oggplay_data_initialise_list(decoder);
@ -622,7 +878,11 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
*/
void
oggplay_callback_shutdown(OggPlayDecode *decoder) {
if (decoder == NULL) {
return;
}
if (callbacks[decoder->content_type].shutdown != NULL) {
callbacks[decoder->content_type].shutdown(decoder);
}
@ -640,23 +900,24 @@ oggplay_callback_shutdown(OggPlayDecode *decoder) {
*/
int
oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
void *user_data) {
void *user_data) {
OggPlay * me;
OggPlay * me = (OggPlay *)user_data;
int i;
int content_type = 0;
me = (OggPlay *)user_data;
int ret = OGGZ_CONTINUE;
short new_stream = 1;
short read_more = 0;
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
if (me == NULL) {
return OGGZ_STOP_ERR;
}
content_type = oggz_stream_get_content (me->oggz, serialno);
/*
* if we encounter a serialno for the second time, then we've reached the
* end of the b_o_s packets
*/
for (i = 0; i < me->num_tracks; i++) {
if (serialno == me->decode_data[i]->serialno) {
int ret = 0;
/*
* call appropriate callback
*/
@ -664,59 +925,87 @@ oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
ret = callbacks[content_type].callback(oggz, op, serialno,
me->decode_data[i]);
}
if
(
(op->granulepos >= 0)
||
(op->granulepos == -1 && me->decode_data[i]->last_granulepos != -1)
)
{
/*
* set up all the other callbacks
*/
for (i = 0; i < me->num_tracks; i++) {
serialno = me->decode_data[i]->serialno;
content_type = oggz_stream_get_content (me->oggz, serialno);
oggz_set_read_callback(me->oggz, serialno,
callbacks[content_type].callback, me->decode_data[i]);
}
/*
* destroy this callback
*/
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
me->all_tracks_initialised = 1;
}
return ret < 0 ? OGGZ_ERR_HOLE_IN_DATA : ret;
new_stream = 0;
}
/* a track that hasn't got all it's headers, but others are already having
* valueable data. A badly multiplexed Ogg file, as the specification
* requires that all headers has to be before any data comes.
* Instead of marking the whole file as a bad one, try to decode
* the streams, which headers are successfully decoded.
* and disable the tracks that haven't got enough header info.
*/
if (granulepos && me->decode_data[i]->num_header_packets) {
me->decode_data[i]->initialised = -1;
}
/*
* check whether there is a stream that has not
* decoded all it's headers
*/
read_more |= (me->decode_data[i]->num_header_packets && (me->decode_data[i]->initialised != -1));
}
me->callback_info = oggplay_realloc (me->callback_info,
sizeof (OggPlayCallbackInfo) * ++me->num_tracks);
if (me->callback_info == NULL)
return -1;
if (new_stream) {
/* check for possible overflow ... */
if
(
(++me->num_tracks <= 0)
||
(OGGPLAY_TYPE_MAX(size_t)/(me->num_tracks) < sizeof(OggPlayCallbackInfo))
||
(OGGPLAY_TYPE_MAX(size_t)/me->num_tracks < sizeof(long))
)
{
return OGGZ_STOP_ERR;
}
me->callback_info = oggplay_realloc (me->callback_info,
sizeof (OggPlayCallbackInfo) * me->num_tracks);
if (me->callback_info == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
me->decode_data = oggplay_realloc (me->decode_data, sizeof (long) * me->num_tracks);
if (me->decode_data == NULL)
return -1;
me->decode_data = oggplay_realloc (me->decode_data,
sizeof (long) * me->num_tracks);
if (me->decode_data == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
me->decode_data[me->num_tracks - 1] = oggplay_initialise_decoder(me,
content_type, serialno);
if (me->decode_data[me->num_tracks - 1] == NULL)
return -1;
me->decode_data[me->num_tracks - 1] =
oggplay_initialise_decoder(me, content_type, serialno);
if (me->decode_data[me->num_tracks - 1] == NULL)
return OGGZ_ERR_OUT_OF_MEMORY;
/*me->decode_data->callback_info = me->callback_info + (me->num_tracks - 1);*/
/*
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
return callbacks[content_type].callback(oggz, op, serialno,
me->decode_data[me->num_tracks - 1]);
/*
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
ret = callbacks[content_type].callback(oggz, op, serialno,
me->decode_data[me->num_tracks - 1]);
}
} else if (!read_more) {
/*
* all tracks' headers has been processed
* initialisation phase done, process the payloads.
*/
me->all_tracks_initialised = 1;
/* set up all the callbacks for the detected streams */
for (i = 0; i < me->num_tracks; i++) {
serialno = me->decode_data[i]->serialno;
content_type = oggz_stream_get_content (me->oggz, serialno);
if (oggz_set_read_callback (me->oggz, serialno,
callbacks[content_type].callback,
me->decode_data[i]) != 0)
{
return OGGZ_STOP_ERR;
}
}
/* disable the callback for unforeseen streams */
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
}
return 0;
/* read the header part of the ogg content in a packet-by-packet manner */
return ((ret < 0) ? ret : OGGZ_CONTINUE);
}

View File

@ -57,7 +57,7 @@ oggplay_process_leftover_packet(OggPlay *me);
* @retval NULL in case of error.
*/
OggPlayDecode *
oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno);
oggplay_initialise_decoder(OggPlay *me, int content_type, long serialno);
int
oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info);

View File

@ -40,6 +40,19 @@
extern void _print_list(char *name, OggPlayDataHeader *p);
static void
clear_callback_info (OggPlay *me, OggPlayCallbackInfo ***info) {
int i;
for (i = 0; i < me->num_tracks; ++i) {
if (((*info)[i] != NULL) && ((*info)[i]->records != NULL)) {
oggplay_free ((*info)[i]->records);
}
}
oggplay_free (*info);
*info = NULL;
}
int
oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
@ -56,15 +69,15 @@ oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
*/
(*info) = oggplay_calloc (me->num_tracks, sizeof (OggPlayCallbackInfo *));
if ((*info) == NULL)
return -1;
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* fill in each active track. Leave gaps for inactive tracks.
*/
for (i = 0; i < me->num_tracks; i++) {
OggPlayDecode * track = me->decode_data[i];
OggPlayCallbackInfo * track_info = me->callback_info + i;
int count = 0;
size_t count = 0;
OggPlayDataHeader * p;
OggPlayDataHeader * q = NULL;
@ -110,7 +123,18 @@ oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
if (q == NULL) {
q = p;
}
count++;
/* check for overflow */
if
(
oggplay_check_add_overflow (count, 1, &count)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
clear_callback_info (me, info);
return E_OGGPLAY_TYPE_OVERFLOW;
}
}
}
@ -144,18 +168,17 @@ oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
} else {
track_info->stream_info = OGGPLAY_STREAM_UNINITIALISED;
}
if ((count+1) < count) {
clear_callback_info (me, info);
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* null-terminate the record list for the python interface */
track_info->records = oggplay_calloc ((count + 1), sizeof (OggPlayDataHeader *));
if (track_info->records == NULL)
{
for (i = 0; i < me->num_tracks; i++) {
if ((*info)[i]->records != NULL)
oggplay_free ((*info)[i]->records);
}
oggplay_free (*info);
*info = NULL;
return -1;
track_info->records =
oggplay_calloc ((count+1), sizeof (OggPlayDataHeader *));
if (track_info->records == NULL) {
clear_callback_info (me, info);
return E_OGGPLAY_OUT_OF_MEMORY;
}
track_info->records[count] = NULL;
@ -250,7 +273,7 @@ oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
added_required_record --;
}
}
} /* end of for loop, that fills each track */
me->pt_update_valid = 0;
@ -435,7 +458,6 @@ oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header) {
return -1;
}
/* SGS: is this correct? */
return OGGPLAY_TIME_FP_TO_INT(header->presentation_time);
}

View File

@ -70,6 +70,10 @@
void
oggplay_data_initialise_list (OggPlayDecode *decode) {
if (decode == NULL) {
return;
}
decode->data_list = decode->end_of_data_list = NULL;
decode->untimed_data_list = NULL;
@ -81,6 +85,10 @@ oggplay_data_initialise_list (OggPlayDecode *decode) {
void
oggplay_data_add_to_list_end(OggPlayDecode *decode, OggPlayDataHeader *data) {
if (decode == NULL) {
return;
}
data->next = NULL;
if (decode->data_list == NULL) {
@ -98,6 +106,10 @@ oggplay_data_add_to_list_end(OggPlayDecode *decode, OggPlayDataHeader *data) {
*/
void
oggplay_data_add_to_list_front(OggPlayDecode *decode, OggPlayDataHeader *data) {
if (decode == NULL) {
return;
}
if (decode->data_list == NULL) {
decode->data_list = decode->end_of_data_list = data;
data->next = NULL;
@ -111,7 +123,7 @@ void
_print_list(char *name, OggPlayDataHeader *p) {
printf("%s: ", name);
for (; p != NULL; p = p->next) {
printf("%"PRId64"[%d]", p->presentation_time >> 32, p->lock);
printf("%"PRId64"[%d]", OGGPLAY_TIME_FP_TO_INT (p->presentation_time), p->lock);
if (p->next != NULL) printf("->");
}
printf("\n");
@ -128,6 +140,10 @@ oggplay_data_add_to_list (OggPlayDecode *decode, OggPlayDataHeader *data) {
ogg_int64_t samples_in_next_in_list;
if ((decode == NULL) || (data == NULL)) {
return;
}
//_print_list("before", decode->data_list);
//_print_list("untimed before", decode->untimed_data_list);
@ -194,6 +210,10 @@ oggplay_data_free_list(OggPlayDataHeader *list) {
void
oggplay_data_shutdown_list (OggPlayDecode *decode) {
if (decode == NULL) {
return;
}
oggplay_data_free_list(decode->data_list);
oggplay_data_free_list(decode->untimed_data_list);
@ -208,10 +228,16 @@ oggplay_data_shutdown_list (OggPlayDecode *decode) {
void
oggplay_data_clean_list (OggPlayDecode *decode) {
ogg_int64_t target = decode->player->target;
OggPlayDataHeader * header = decode->data_list;
ogg_int64_t target;
OggPlayDataHeader * header = NULL;
OggPlayDataHeader * p = NULL;
if (decode == NULL) {
return;
}
header = decode->data_list;
target = decode->player->target;
while (header != NULL) {
if
(
@ -252,8 +278,13 @@ oggplay_data_clean_list (OggPlayDecode *decode) {
}
void
oggplay_data_initialise_header (OggPlayDecode *decode,
OggPlayDataHeader *header) {
oggplay_data_initialise_header (const OggPlayDecode *decode,
OggPlayDataHeader *header) {
if ((decode == NULL) || (header == NULL)) {
return;
}
/*
* the frame is not cleaned until its presentation time has passed. We'll
* check presentation times in oggplay_data_clean_list.
@ -262,59 +293,106 @@ oggplay_data_initialise_header (OggPlayDecode *decode,
header->next = NULL;
header->presentation_time = decode->current_loc;
header->has_been_presented = 0;
}
void
OggPlayErrorCode
oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int samples, int samplesize) {
long samples, size_t samplesize) {
int num_channels;
int num_channels, ret;
size_t record_size = sizeof(OggPlayAudioRecord);
long samples_size;
OggPlayAudioRecord * record = NULL;
num_channels = ((OggPlayAudioDecode *)decode)->sound_info.channels;
record = (OggPlayAudioRecord*)oggplay_calloc(sizeof(OggPlayAudioRecord) +
samples * samplesize * num_channels, 1);
/* check for possible integer overflows....*/
if ((samples < 0) || (num_channels < 0)) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
if (record == NULL)
return;
ret = oggplay_mul_signed_overflow (samples, num_channels, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (samples_size, samplesize, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (record_size, samples_size, &record_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/* try to allocate the memory for the record */
record = (OggPlayAudioRecord*)oggplay_calloc(record_size, 1);
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
/* initialise the header of OggPlayAudioRecord struct */
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = samples;
record->data = (void *)(record + 1);
memcpy(record->data, data, samples * samplesize * num_channels);
/* copy the received data - the header has been initialised! */
memcpy (record->data, data, samples_size);
/*
printf("[%f%f%f]\n", ((float *)record->data)[0], ((float *)record->data)[1],
((float *)record->data)[2]);
*/
oggplay_data_add_to_list(decode, &(record->header));
return E_OGGPLAY_CONTINUE;
}
void
oggplay_data_handle_cmml_data(OggPlayDecode *decode, unsigned char *data,
int size) {
OggPlayErrorCode
oggplay_data_handle_cmml_data(OggPlayDecode *decode,
unsigned char *data,
long size) {
OggPlayTextRecord * record = NULL;
size_t record_size = sizeof(OggPlayTextRecord);
record =
(OggPlayTextRecord*)oggplay_calloc (sizeof(OggPlayTextRecord) + size + 1, 1);
if (record == NULL)
return;
/* check that the size we want to allocate doesn't overflow */
if ((size < 0) || (size+1 < 0)) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
size += 1;
if
(
oggplay_check_add_overflow (record_size, size, &record_size)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* allocate the memory for the record */
record = (OggPlayTextRecord*)oggplay_calloc (record_size, 1);
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
/* initialise the record's header */
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = 1;
record->data = (char *)(record + 1);
/* copy the data */
memcpy(record->data, data, size);
record->data[size] = '\0';
oggplay_data_add_to_list(decode, &(record->header));
return E_OGGPLAY_CONTINUE;
}
static int
@ -334,13 +412,13 @@ get_uv_offset(OggPlayTheoraDecode *decode, yuv_buffer *buffer)
return xo + yo;
}
void
int
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv_buffer *buffer) {
const yuv_buffer *buffer) {
int size = sizeof (OggPlayVideoRecord);
int i;
int uv_offset;
size_t size = sizeof (OggPlayVideoRecord);
int i, ret;
long y_size, uv_size, y_offset, uv_offset;
unsigned char * p;
unsigned char * q;
unsigned char * p2;
@ -348,12 +426,37 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
OggPlayVideoRecord * record;
OggPlayVideoData * data;
/* check for possible integer overflows */
ret =
oggplay_mul_signed_overflow (buffer->y_height, buffer->y_stride, &y_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret =
oggplay_mul_signed_overflow (buffer->uv_height, buffer->uv_stride, &uv_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (uv_size, 2, &uv_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
if (buffer->y_stride < 0) {
size -= buffer->y_stride * buffer->y_height;
size -= buffer->uv_stride * buffer->uv_height * 2;
} else {
size += buffer->y_stride * buffer->y_height;
size += buffer->uv_stride * buffer->uv_height * 2;
y_size *= -1;
uv_size *= -1;
}
ret = oggplay_check_add_overflow (size, y_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (size, uv_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/*
@ -362,9 +465,10 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
*/
record = (OggPlayVideoRecord*)oggplay_malloc (size);
if (record == NULL)
return;
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
record->header.samples_in_record = 1;
data = &(record->data);
@ -376,8 +480,10 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
* *grumble* theora plays silly buggers with pointers so we need to do
* a row-by-row copy (stride may be negative)
*/
y_offset = (decode->video_info.offset_x&~1)
+ buffer->y_stride*(decode->video_info.offset_y&~1);
p = data->y;
q = buffer->y + (decode->video_info.offset_x&~1)+buffer->y_stride*(decode->video_info.offset_y&~1);
q = buffer->y + y_offset;
for (i = 0; i < decode->y_height; i++) {
memcpy(p, q, decode->y_width);
p += decode->y_width;
@ -385,7 +491,6 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
}
uv_offset = get_uv_offset(decode, buffer);
p = data->u;
q = buffer->u + uv_offset;
p2 = data->v;
@ -405,6 +510,7 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
OggPlayRGBChannels rgb;
OggPlayOverlayRecord * orecord;
OggPlayOverlayData * odata;
long overlay_size;
yuv.ptry = data->y;
yuv.ptru = data->u;
@ -414,9 +520,27 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv.uv_width = decode->uv_width;
yuv.uv_height = decode->uv_height;
size = sizeof(OggPlayOverlayRecord) + decode->y_width * decode->y_height * 4;
size = sizeof(OggPlayOverlayRecord);
/* check for possible integer oveflows */
ret = oggplay_mul_signed_overflow(decode->y_width, decode->y_height,
&overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow(overlay_size, 4, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (size, overlay_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/* allocate memory for the overlay record */
orecord = (OggPlayOverlayRecord*) oggplay_malloc (size);
if (orecord) {
if (orecord != NULL) {
oggplay_data_initialise_header((OggPlayDecode *)decode, &(orecord->header));
orecord->header.samples_in_record = 1;
odata = &(orecord->data);
@ -425,10 +549,12 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
rgb.rgb_width = yuv.y_width;
rgb.rgb_height = yuv.y_height;
oggplay_yuv2rgba(&yuv, &rgb);
// odata->rgb = NULL;
// odata->rgba = rgb.ptro;
if (!decode->swap_rgb) {
oggplay_yuv2bgra(&yuv, &rgb);
} else {
oggplay_yuv2rgba(&yuv, &rgb);
}
odata->rgb = rgb.ptro;
odata->rgba = NULL;
odata->width = rgb.rgb_width;
@ -438,20 +564,31 @@ oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
oggplay_free(record);
oggplay_data_add_to_list((OggPlayDecode *)decode, &(orecord->header));
} else {
/* memory allocation failed! */
oggplay_free (record);
return E_OGGPLAY_OUT_OF_MEMORY;
}
}
else {
oggplay_data_initialise_header((OggPlayDecode *)decode, &(record->header));
oggplay_data_add_to_list((OggPlayDecode *)decode, &(record->header));
}
return E_OGGPLAY_CONTINUE;
}
#ifdef HAVE_KATE
void
OggPlayErrorCode
oggplay_data_handle_kate_data(OggPlayKateDecode *decode, const kate_event *ev) {
OggPlayTextRecord * record = NULL;
size_t rec_size = sizeof(OggPlayTextRecord);
if (decode == NULL) {
return -1;
}
#ifdef HAVE_TIGER
tiger_renderer_add_event(decode->tr, ev->ki, ev);
@ -462,9 +599,21 @@ oggplay_data_handle_kate_data(OggPlayKateDecode *decode, const kate_event *ev) {
else
#endif
{
record = (OggPlayTextRecord*)oggplay_calloc (sizeof(OggPlayTextRecord) + ev->len0, 1);
if (!record)
return;
/* check for integer overflow */
if
(
oggplay_check_add_overflow (rec_size, ev->len0, &rec_size)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
record = (OggPlayTextRecord*)oggplay_calloc (rec_size, 1);
if (!record) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
oggplay_data_initialise_header(&decode->decoder, &(record->header));
@ -476,20 +625,23 @@ oggplay_data_handle_kate_data(OggPlayKateDecode *decode, const kate_event *ev) {
oggplay_data_add_to_list(&decode->decoder, &(record->header));
}
return E_OGGPLAY_CONTINUE;
}
#endif
#ifdef HAVE_TIGER
void
OggPlayErrorCode
oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t presentation_time, OggPlayCallbackInfo *info) {
OggPlayOverlayRecord * record = NULL;
OggPlayOverlayData * data = NULL;
size_t size = sizeof (OggPlayOverlayRecord);
int track = active && decode->use_tiger;
int ret;
kate_float t = OGGPLAY_TIME_FP_TO_INT(presentation_time) / 1000.0f;
if (!decode->init) return;
if (!decode->decoder.initialised) return -1;
if (track) {
if (info) {
@ -497,33 +649,59 @@ oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t pre
OggPlayDataHeader *header = info->records[0];
data = (OggPlayOverlayData*)(header+1);
if (decode->tr && data->rgb) {
#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 0);
#else
tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 1);
#endif
}
else {
/* we're supposed to overlay on a frame, but the available frame has no RGB buffer */
/* fprintf(stderr,"no RGB buffer found for video frame\n"); */
return;
return -1;
}
}
else {
/* we're supposed to overlay on a frame, but there is no frame available */
/* fprintf(stderr,"no video frame to overlay on\n"); */
return;
return -1;
}
}
else {
// TODO: some way of knowing the size of the video we'll be drawing onto, if any
int width = decode->k.ki->original_canvas_width;
int height = decode->k.ki->original_canvas_height;
int width = decode->k_state.ki->original_canvas_width;
int height = decode->k_state.ki->original_canvas_height;
long overlay_size;
if (width <= 0 || height <= 0) {
/* some default resolution if we're not overlaying onto a video and the canvas size is unknown */
width = 640;
height = 480;
if (decode->default_width > 0 && decode->default_height > 0) {
width = decode->default_width;
height = decode->default_height;
}
else {
width = 640;
height = 480;
}
}
size = sizeof (OggPlayOverlayRecord) + width*height*4;
/* check for integer overflow */
ret = oggplay_mul_signed_overflow (width, height, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (overlay_size, 4, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
ret = oggplay_check_add_overflow (size, overlay_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
record = (OggPlayOverlayRecord*)oggplay_calloc (1, size);
if (!record)
return;
return E_OGGPLAY_OUT_OF_MEMORY;
record->header.samples_in_record = 1;
data= &(record->data);
@ -536,7 +714,7 @@ oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t pre
data->stride = width*4;
if (decode->tr && data->rgba) {
tiger_renderer_set_buffer(decode->tr, data->rgba, data->width, data->height, data->stride, 1);
tiger_renderer_set_buffer(decode->tr, data->rgba, data->width, data->height, data->stride, decode->swap_rgb);
}
oggplay_data_add_to_list(&decode->decoder, &(record->header));
@ -554,6 +732,8 @@ oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t pre
tiger_renderer_render(decode->tr);
}
}
return E_OGGPLAY_CONTINUE;
}
#endif

View File

@ -41,26 +41,26 @@
void
oggplay_data_initialise_list (OggPlayDecode *decode);
void
OggPlayErrorCode
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv_buffer *buffer);
const yuv_buffer *buffer);
void
oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int samples, int samplesize);
OggPlayErrorCode
oggplay_data_handle_audio_data (OggPlayDecode *decode,
void *data, long samples, size_t samplesize);
void
oggplay_data_handle_cmml_data(OggPlayDecode *decode, unsigned char *data,
int size);
OggPlayErrorCode
oggplay_data_handle_cmml_data(OggPlayDecode *decode,
unsigned char *data, long size);
#ifdef HAVE_KATE
void
OggPlayErrorCode
oggplay_data_handle_kate_data(OggPlayKateDecode *decode,
const kate_event *ev);
#endif
#ifdef HAVE_TIGER
void
OggPlayErrorCode
oggplay_data_update_tiger(OggPlayKateDecode *decode,
int active, ogg_int64_t presentation_time,
OggPlayCallbackInfo *info);

View File

@ -72,10 +72,17 @@ OggPlayErrorCode
oggplay_file_reader_destroy(OggPlayReader * opr) {
OggPlayFileReader * me;
if (opr == NULL) {
return E_OGGPLAY_BAD_READER;
}
me = (OggPlayFileReader *)opr;
fclose(me->file);
if (me->file != NULL) {
fclose(me->file);
}
oggplay_free(me);
return E_OGGPLAY_OK;
@ -83,9 +90,14 @@ oggplay_file_reader_destroy(OggPlayReader * opr) {
int
oggplay_file_reader_available(OggPlayReader * opr, ogg_int64_t current_bytes,
ogg_int64_t current_time) {
ogg_int64_t current_time) {
OggPlayFileReader *me = (OggPlayFileReader *)opr;
if (me == NULL) {
return -1;
}
return me->size;
}
@ -103,6 +115,11 @@ oggplay_file_reader_io_read(void * user_handle, void * buf, size_t n) {
OggPlayFileReader *me = (OggPlayFileReader *)user_handle;
int r;
if (me == NULL) {
return -1;
}
r = fread(buf, 1, n, me->file);
if (r > 0) {
me->current_position += r;
@ -117,6 +134,10 @@ oggplay_file_reader_io_seek(void * user_handle, long offset, int whence) {
OggPlayFileReader * me = (OggPlayFileReader *)user_handle;
int r;
if (me == NULL) {
return -1;
}
r = fseek(me->file, offset, whence);
me->current_position = ftell(me->file);
return r;
@ -128,12 +149,16 @@ oggplay_file_reader_io_tell(void * user_handle) {
OggPlayFileReader * me = (OggPlayFileReader *)user_handle;
if (me == NULL) {
return -1;
}
return ftell(me->file);
}
OggPlayReader *
oggplay_file_reader_new(char *file_name) {
oggplay_file_reader_new(const char *file_name) {
OggPlayFileReader * me = oggplay_malloc (sizeof (OggPlayFileReader));

View File

@ -47,7 +47,7 @@
typedef struct {
OggPlayReader functions;
char * file_name;
const char * file_name;
FILE * file;
long current_position;
long size;

View File

@ -168,6 +168,8 @@ typedef struct {
OggPlayDataHeader * untimed_data_list;
OggPlayStreamInfo stream_info; /**< @see OggPlayStreamInfo */
int preroll; /**< num. of past content packets to take into account when decoding the current Ogg page */
short initialised; /**< */
int num_header_packets; /**< number of header packets left to process for the stream.*/
} OggPlayDecode;
typedef struct {
@ -175,7 +177,6 @@ typedef struct {
theora_state video_handle;
theora_info video_info;
theora_comment video_comment;
int remaining_header_packets;
int granulepos_seen;
int frame_delta;
int y_width;
@ -186,6 +187,7 @@ typedef struct {
int uv_stride;
int cached_keyframe;
int convert_to_rgb;
int swap_rgb;
} OggPlayTheoraDecode;
typedef struct {
@ -212,60 +214,71 @@ typedef struct {
OggPlayDecode decoder;
#ifdef HAVE_KATE
int granuleshift;
kate_state k;
kate_state k_state;
kate_info k_info;
kate_comment k_comment;
int init;
#ifdef HAVE_TIGER
int use_tiger;
int overlay_dest;
tiger_renderer *tr;
int default_width;
int default_height;
int swap_rgb;
#endif
#endif
} OggPlayKateDecode;
struct OggPlaySeekTrash;
/**
*
*/
typedef struct OggPlaySeekTrash {
OggPlayDataHeader * old_data;
OggPlayBuffer * old_buffer;
struct OggPlaySeekTrash * next;
} OggPlaySeekTrash;
/**
*
*/
struct _OggPlay {
OggPlayReader * reader;
OGGZ * oggz;
OggPlayDecode ** decode_data;
OggPlayCallbackInfo * callback_info;
int num_tracks;
int all_tracks_initialised;
ogg_int64_t callback_period;
OggPlayDataCallback * callback;
void * callback_user_ptr;
ogg_int64_t target;
int active_tracks;
volatile OggPlayBuffer * buffer;
ogg_int64_t presentation_time; /**< presentation time in seconds in 32.32 fixed point format */
OggPlaySeekTrash * trash;
int shutdown;
int pt_update_valid;
ogg_int64_t duration; /**< The value of the duration the last time it was retrieved.*/
OggPlayReader * reader; /**< @see OggPlayReader */
OGGZ * oggz; /**< @see OGGZ */
OggPlayDecode ** decode_data; /**< */
OggPlayCallbackInfo * callback_info; /**< */
int num_tracks; /**< number of tracks in the Ogg container */
int all_tracks_initialised; /**< "= 1" indicates that all tracks are initialised */
ogg_int64_t callback_period; /**< */
OggPlayDataCallback * callback; /**< */
void * callback_user_ptr; /**< */
ogg_int64_t target; /**< */
int active_tracks; /**< number of active tracks */
volatile OggPlayBuffer * buffer; /**< @see OggPlayBuffer */
ogg_int64_t presentation_time; /**< */
OggPlaySeekTrash * trash; /**< @see OggPlaySeekTrash */
int shutdown; /**< "= 1" indicates shutdown event */
int pt_update_valid; /**< */
ogg_int64_t duration; /**< The value of the duration the last time it was retrieved.*/
};
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user);
void *user);
void
oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash);
void
OggPlayErrorCode
oggplay_seek_cleanup(OggPlay *me, ogg_int64_t milliseconds);
typedef struct {
void (*init)(void *user_data);
int (*callback)(OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data);
void (*shutdown)(void *user_data);
int size;
void (*init) (void *user_data);
int (*callback) (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data);
void (*shutdown) (void *user_data);
int size;
} OggPlayCallbackFunctions;
/**
@ -290,6 +303,153 @@ typedef struct {
#define oggplay_realloc _ogg_realloc
#define oggplay_free _ogg_free
/**
* macros for obtaining a type's max and min values
* http://www.fefe.de/intof.html
*/
#define OGGPLAY_TYPE_HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
#define OGGPLAY_TYPE_MAX_SIGNED(type) (OGGPLAY_TYPE_HALF_MAX_SIGNED(type) - 1 + OGGPLAY_TYPE_HALF_MAX_SIGNED(type))
#define OGGPLAY_TYPE_MIN_SIGNED(type) (-1 - OGGPLAY_TYPE_MAX_SIGNED(type))
#define OGGPLAY_TYPE_MIN(type) ((type)-1 < 1?OGGPLAY_TYPE_MIN_SIGNED(type):(type)0)
#define OGGPLAY_TYPE_MAX(type) ((type)~OGGPLAY_TYPE_MIN(type))
static inline int
oggplay_check_add_overflow (size_t a, long b, size_t* r) {
/* we cannot assume that sizeof(size_t) >= sizeof(long) !!! */
if (sizeof(size_t) < sizeof(long)) {
/* check whether the number fits into a size_t */
if
(
(b < 0) ?
((OGGPLAY_TYPE_MAX(size_t)+b >= 0) ? 0 : 1) :
((OGGPLAY_TYPE_MAX(size_t)-b >= 0) ? 0 : 1)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
}
/* check whether the sum of the 'a' and 'b' fits into a size_t */
if
(
(b < 0) ?
((OGGPLAY_TYPE_MIN(size_t)-b <= a) ? 0 : 1) :
((OGGPLAY_TYPE_MAX(size_t)-b >= a) ? 0 : 1)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* if 'r' is supplied give back the sum of 'a' and 'b' */
if (r != NULL)
*r = a+b;
return 0;
}
static inline int
oggplay_mul_signed_overflow_generic(long a, long b, long *re) {
long _a, _b, ah, bh, x, y, r = 0;
int sign = 1;
_a = a;
_b = b;
ah = _a >> (sizeof(long)*4);
bh = _b >> (sizeof(long)*4);
if (a < 0) {
_a = -_a;
if (_a < 0) {
if (_b == 0 || _b == 1) {
r = _a*_b;
goto ok;
} else {
goto overflow;
}
}
sign = -sign;
ah = _a >> (sizeof(long)*4);
}
if (_b < 0) {
_b = -_b;
if (_b < 0) {
if (_a == 0 || (_a == 1 && sign == 1)) {
r = _a*_b;
goto ok;
} else {
goto overflow;
}
}
sign = -sign;
bh = _b >> (sizeof(long)*4);
}
if (ah != 0 && bh != 0) {
goto overflow;
}
if (ah == 0 && bh == 0) {
r = _a*_b;
if (r < 0)
goto overflow;
goto ok;
}
if (_a < _b) {
x = _a;
_a = _b;
_b = x;
ah = bh;
}
y = ah*_b;
if (y >= (1L << (sizeof(long)*4 - 1)))
goto overflow;
_a &= (1L << sizeof(long)*4) - 1;
x = _a*_b;
if (x < 0)
goto overflow;
x += (y << sizeof(long)*4);
if (x < 0)
goto overflow;
ok:
if (re != NULL) {
*re = sign*r;
}
return 0;
overflow:
return E_OGGPLAY_TYPE_OVERFLOW;
}
static inline int
oggplay_mul_signed_overflow(long a, long b, long *r) {
if (sizeof(long) > 4) {
return oggplay_mul_signed_overflow_generic (a, b, r);
} else {
ogg_int64_t c = (ogg_int64_t) a*b;
/* check whether the result fits in a long bit */
if
(
(c < 1) ?
((OGGPLAY_TYPE_MIN (long) > c) ? 1 : 0) :
((OGGPLAY_TYPE_MAX (long) < c) ? 1 : 0)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
if (r != NULL) {
*r = (long)c;
}
return 0;
}
}
#include "oggplay_callback.h"
#include "oggplay_data.h"
#include "oggplay_buffer.h"

View File

@ -130,11 +130,16 @@ oggplay_set_track_active(OggPlay *me, int track_num) {
if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_SKELETON) {
return E_OGGPLAY_TRACK_IS_SKELETON;
}
if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_UNKNOWN) {
return E_OGGPLAY_TRACK_IS_UNKNOWN;
}
/* there was an error while decoding the headers of this track! */
if (me->decode_data[track_num]->initialised != 1) {
return E_OGGPLAY_TRACK_UNINITIALISED;
}
if ((p = me->decode_data[track_num]->final_granulepos) != -1) {
if (p * me->decode_data[track_num]->granuleperiod > me->target) {
return E_OGGPLAY_TRACK_IS_OVER;

View File

@ -72,48 +72,10 @@ oggplay_seek(OggPlay *me, ogg_int64_t milliseconds) {
}
}
oggplay_seek_cleanup(me, milliseconds);
return E_OGGPLAY_OK;
return oggplay_seek_cleanup(me, milliseconds);
}
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end)
{
ogg_int64_t eof, time;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (milliseconds < 0)
return E_OGGPLAY_CANT_SEEK;
eof = oggplay_get_duration(me);
if (eof > -1 && milliseconds > eof) {
return E_OGGPLAY_CANT_SEEK;
}
time = oggz_keyframe_seek_set(me->oggz,
milliseconds,
offset_begin,
offset_end);
if (time == -1) {
return E_OGGPLAY_CANT_SEEK;
}
oggplay_seek_cleanup(me, time);
return E_OGGPLAY_OK;
}
void
oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
{
@ -122,8 +84,8 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
OggPlayDataHeader ** end_of_list_p;
int i;
if (me == NULL)
return;
if (me == NULL)
return E_OGGPLAY_BAD_OGGPLAY;
/*
* first, create a trash object to store the context that we want to
@ -134,13 +96,13 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
trash = oggplay_calloc(1, sizeof(OggPlaySeekTrash));
if (trash == NULL)
return;
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* store the old buffer in it next.
*/
if (me->buffer != NULL) {
trash->old_buffer = (OggPlayBuffer *)me->buffer;
/*
@ -149,11 +111,11 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
*/
me->buffer = oggplay_buffer_new_buffer(me->buffer->buffer_size);
if (me->buffer == NULL) {
return;
if (me->buffer == NULL)
{
return E_OGGPLAY_OUT_OF_MEMORY;
}
}
/*
* strip all of the data packets out of the streams and put them into the
* trash. We can free the untimed packets immediately - they are USELESS
@ -203,6 +165,8 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
}
*p = trash;
return E_OGGPLAY_OK;
}
void
@ -224,3 +188,39 @@ oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash) {
oggplay_free(p);
}
}
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end)
{
ogg_int64_t eof, time;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (milliseconds < 0)
return E_OGGPLAY_CANT_SEEK;
eof = oggplay_get_duration(me);
if (eof > -1 && milliseconds > eof) {
return E_OGGPLAY_CANT_SEEK;
}
time = oggz_keyframe_seek_set(me->oggz,
milliseconds,
offset_begin,
offset_end);
if (time == -1) {
return E_OGGPLAY_CANT_SEEK;
}
oggplay_seek_cleanup(me, time);
return E_OGGPLAY_OK;
}

View File

@ -161,7 +161,7 @@ oggplay_create_socket() {
* @retval -1 in case of error, 0 otherwise.
*/
int
oggplay_hostname_and_path(char *location, char *proxy, int proxy_port,
oggplay_hostname_and_path(const char *location, const char *proxy, int proxy_port,
char **host, int *port, char **path) {
@ -298,7 +298,7 @@ oggplay_tcp_reader_initialise(OggPlayReader * opr, int block) {
int r;
char * pos;
int len;
size_t len;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
@ -359,6 +359,15 @@ oggplay_tcp_reader_initialise(OggPlayReader * opr, int block) {
printf("Host not found\n");
return E_OGGPLAY_BAD_INPUT;
}
/*
* currently we only support IPv4
* TODO: switch to getaddrinfo and support IPv6!
*/
if (sizeof(addr.sin_addr.s_addr) != he->h_length) {
printf("No IPv6 support, yet!\n");
return E_OGGPLAY_BAD_INPUT;
}
memcpy(&addr.sin_addr.s_addr, he->h_addr, he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
@ -446,9 +455,9 @@ oggplay_tcp_reader_initialise(OggPlayReader * opr, int block) {
(
(!found_http_response)
&&
strncmp((char *)me->buffer, "HTTP/1.1 200 OK", 15) != 0
strncmp((char *)me->buffer, "HTTP/1.1 200 ", 13) != 0
&&
strncmp((char *)me->buffer, "HTTP/1.0 200 OK", 15) != 0
strncmp((char *)me->buffer, "HTTP/1.0 200 ", 13) != 0
)
{
return E_OGGPLAY_BAD_INPUT;
@ -537,6 +546,10 @@ oggplay_tcp_reader_destroy(OggPlayReader * opr) {
OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->socket != INVALID_SOCKET) {
#ifdef WIN32
#ifdef HAVE_WINSOCK2
@ -564,6 +577,10 @@ grab_some_data(OggPlayTCPReader *me, int block) {
int remaining;
int r;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->socket == INVALID_SOCKET) return E_OGGPLAY_OK;
/*
@ -623,6 +640,10 @@ oggplay_tcp_reader_available(OggPlayReader * opr, ogg_int64_t current_bytes,
me = (OggPlayTCPReader *)opr;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->socket == INVALID_SOCKET) {
return me->duration;
}
@ -639,6 +660,11 @@ oggplay_tcp_reader_available(OggPlayReader * opr, ogg_int64_t current_bytes,
ogg_int64_t
oggplay_tcp_reader_duration(OggPlayReader * opr) {
OggPlayTCPReader *me = (OggPlayTCPReader *)opr;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->duration;
}
@ -648,6 +674,10 @@ oggplay_tcp_reader_io_read(void * user_handle, void * buf, size_t n) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
int len;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
grab_some_data(me, 0);
fseek(me->backing_store, me->current_position, SEEK_SET);
@ -676,6 +706,10 @@ oggplay_tcp_reader_io_seek(void * user_handle, long offset, int whence) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
int r;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
fseek(me->backing_store, me->current_position, SEEK_SET);
r = fseek(me->backing_store, offset, whence);
me->current_position = ftell(me->backing_store);
@ -689,12 +723,16 @@ oggplay_tcp_reader_io_tell(void * user_handle) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->current_position;
}
OggPlayReader *
oggplay_tcp_reader_new(char *location, char *proxy, int proxy_port) {
oggplay_tcp_reader_new(const char *location, const char *proxy, int proxy_port) {
OggPlayTCPReader * me = (OggPlayTCPReader *)oggplay_malloc (sizeof (OggPlayTCPReader));

View File

@ -74,7 +74,7 @@ typedef struct {
int buffer_size;
int current_position;
char * location;
char * proxy;
const char * proxy;
int proxy_port;
int amount_in_memory;
FILE * backing_store;

View File

@ -39,30 +39,44 @@
* Michael Martin
* Marcin Lubonski
* Viktor Gal
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
*/
#include "oggplay_private.h"
#include "oggplay_yuv2rgb_template.h"
#ifdef __SUNPRO_C
#define DISABLE_CPU_FEATURES
/* gcc inline asm and intristics have problems with Sun Studio.
* We need to fix it.
*/
#else
/* cpu extension detection */
#include "cpu.c"
#endif
/**
* yuv_convert_fptr type is a function pointer type for
* the various yuv-rgb converters
*/
typedef void (*yuv_convert_fptr) (const OggPlayYUVChannels *yuv,
OggPlayRGBChannels *rgb);
OggPlayRGBChannels *rgb);
/* it is useless to determine each YUV conversion run
* the cpu type/featurs, thus we save the conversion function
* pointers
*/
static struct OggPlayYUVConverters {
yuv_convert_fptr yuv2rgba; /**< YUV420 to RGBA */
yuv_convert_fptr yuv2bgra; /**< YUV420 to BGRA */
yuv_convert_fptr yuv2argb; /**< YUV420 to ARGB */
} yuv_conv = {NULL, NULL, NULL};
yuv_convert_fptr yuv420rgba; /**< YUV420 to RGBA */
yuv_convert_fptr yuv420bgra; /**< YUV420 to BGRA */
yuv_convert_fptr yuv420argb; /**< YUV420 to ARGB */
yuv_convert_fptr yuv422rgba; /**< YUV422 to RGBA */
yuv_convert_fptr yuv422bgra; /**< YUV422 to BGRA */
yuv_convert_fptr yuv422argb; /**< YUV422 to ARGB */
yuv_convert_fptr yuv444rgba; /**< YUV444 to RGBA */
yuv_convert_fptr yuv444bgra; /**< YUV444 to BGRA */
yuv_convert_fptr yuv444argb; /**< YUV444 to ARGB */
} yuv_conv = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
/**
* vanilla implementation of YUV-to-RGB conversion.
@ -121,7 +135,7 @@ out[3] = CLAMP(r);
int buv = CoefsBU[*pu]; \
int r, g, b;
/* yuv420p -> */
/* yuv420p, yuv422p -> */
#define CONVERT(OUTPUT_FUNC) LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
OUTPUT_FUNC(dst, r, g, b) \
@ -130,26 +144,52 @@ out[3] = CLAMP(r);
#define CLEANUP
YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1)
YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv422_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1, 1)
#undef CONVERT
/* yuv444p -> */
#define CONVERT(OUTPUT_FUNC) LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
OUTPUT_FUNC(dst, r, g, b)
YUV_CONVERT(yuv444_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 1, 4, 1, 1, 1)
#undef CONVERT
#undef CLEANUP
#ifndef DISABLE_CPU_FEATURES
/* although we use cpu runtime detection, we still need these
* macros as there's no way e.g. we could compile a x86 asm code
* on a ppc machine and vica-versa
*/
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
#if !defined(_M_AMD64)
#define ENABLE_MMX
#endif
#include "x86/oggplay_yuv2rgb_x86.c"
#if defined(_MSC_VER) || defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
#define ENABLE_SSE2
#endif
#elif defined(__ppc__) || defined(__ppc64__)
#define ENABLE_ALTIVEC
//altivec intristics only working with -maltivec gcc flag,
//but we want runtime altivec detection, hence this has to be
//fixed!
//#include "oggplay_yuv2rgb_altivec.c"
#endif
#endif
/**
@ -181,56 +221,97 @@ init_yuv_converters(void)
{
ogg_uint32_t features = 0;
if ( yuv_conv.yuv2rgba == NULL )
if ( yuv_conv.yuv420rgba == NULL )
{
init_vanilla_coeffs ();
features = oc_cpu_flags_get();
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86)
#if defined(_MSC_VER) || (defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16)
#ifndef DISABLE_CPU_FEATURES
features = oc_cpu_flags_get();
#endif
#ifdef ENABLE_SSE2
if (features & OC_CPU_X86_SSE2)
{
yuv_conv.yuv2rgba = yuv420_to_rgba_sse2;
yuv_conv.yuv2bgra = yuv420_to_bgra_sse2;
yuv_conv.yuv2argb = yuv420_to_argb_sse2;
yuv_conv.yuv420rgba = yuv420_to_rgba_sse2;
yuv_conv.yuv420bgra = yuv420_to_bgra_sse2;
yuv_conv.yuv420argb = yuv420_to_argb_sse2;
yuv_conv.yuv422rgba = yuv422_to_rgba_sse2;
yuv_conv.yuv422bgra = yuv422_to_bgra_sse2;
yuv_conv.yuv422argb = yuv422_to_argb_sse2;
yuv_conv.yuv444rgba = yuv444_to_rgba_sse2;
yuv_conv.yuv444bgra = yuv444_to_bgra_sse2;
yuv_conv.yuv444argb = yuv444_to_argb_sse2;
return;
}
#endif /* SSE2 */
#ifdef ENABLE_MMX
#ifdef ENABLE_SSE2
else
#endif /* ATTRIBUTE_ALIGNED_MAX */
#endif
if (features & OC_CPU_X86_MMXEXT)
{
yuv_conv.yuv2rgba = yuv420_to_rgba_sse;
yuv_conv.yuv2bgra = yuv420_to_bgra_sse;
yuv_conv.yuv2argb = yuv420_to_argb_sse;
yuv_conv.yuv420rgba = yuv420_to_rgba_sse;
yuv_conv.yuv420bgra = yuv420_to_bgra_sse;
yuv_conv.yuv420argb = yuv420_to_argb_sse;
yuv_conv.yuv422rgba = yuv422_to_rgba_sse;
yuv_conv.yuv422bgra = yuv422_to_bgra_sse;
yuv_conv.yuv422argb = yuv422_to_argb_sse;
yuv_conv.yuv444rgba = yuv444_to_rgba_sse;
yuv_conv.yuv444bgra = yuv444_to_bgra_sse;
yuv_conv.yuv444argb = yuv444_to_argb_sse;
return;
}
else if (features & OC_CPU_X86_MMX)
{
yuv_conv.yuv2rgba = yuv420_to_rgba_mmx;
yuv_conv.yuv2bgra = yuv420_to_bgra_mmx;
yuv_conv.yuv2argb = yuv420_to_argb_mmx;
yuv_conv.yuv420rgba = yuv420_to_rgba_mmx;
yuv_conv.yuv420bgra = yuv420_to_bgra_mmx;
yuv_conv.yuv420argb = yuv420_to_argb_mmx;
yuv_conv.yuv422rgba = yuv422_to_rgba_mmx;
yuv_conv.yuv422bgra = yuv422_to_bgra_mmx;
yuv_conv.yuv422argb = yuv422_to_argb_mmx;
yuv_conv.yuv444rgba = yuv444_to_rgba_mmx;
yuv_conv.yuv444bgra = yuv444_to_bgra_mmx;
yuv_conv.yuv444argb = yuv444_to_argb_mmx;
return;
}
#elif defined(__ppc__) || defined(__ppc64__)
#elif defined(ENABLE_ALTIVEC)
if (features & OC_CPU_PPC_ALTIVEC)
{
yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv420rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv420bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv420argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv422rgba = yuv422_to_abgr_vanilla;
yuv_conv.yuv422bgra = yuv422_to_argb_vanilla;
yuv_conv.yuv422argb = yuv422_to_bgra_vanilla;
yuv_conv.yuv444rgba = yuv444_to_abgr_vanilla;
yuv_conv.yuv444bgra = yuv444_to_argb_vanilla;
yuv_conv.yuv444argb = yuv444_to_bgra_vanilla;
return;
}
#endif
#endif
/*
* no CPU extension was found... using vanilla converter, with respect
* to the endianness of the host
*/
#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
yuv_conv.yuv2rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv2bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv2argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv420rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv420bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv420argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv422rgba = yuv422_to_abgr_vanilla;
yuv_conv.yuv422bgra = yuv422_to_argb_vanilla;
yuv_conv.yuv422argb = yuv422_to_bgra_vanilla;
yuv_conv.yuv444rgba = yuv444_to_abgr_vanilla;
yuv_conv.yuv444bgra = yuv444_to_argb_vanilla;
yuv_conv.yuv444argb = yuv444_to_bgra_vanilla;
#else
yuv_conv.yuv2rgba = yuv420_to_rgba_vanilla;
yuv_conv.yuv2bgra = yuv420_to_bgra_vanilla;
yuv_conv.yuv2argb = yuv420_to_argb_vanilla;
yuv_conv.yuv420rgba = yuv420_to_rgba_vanilla;
yuv_conv.yuv420bgra = yuv420_to_bgra_vanilla;
yuv_conv.yuv420argb = yuv420_to_argb_vanilla;
yuv_conv.yuv422rgba = yuv422_to_rgba_vanilla;
yuv_conv.yuv422bgra = yuv422_to_bgra_vanilla;
yuv_conv.yuv422argb = yuv422_to_argb_vanilla;
yuv_conv.yuv444rgba = yuv444_to_rgba_vanilla;
yuv_conv.yuv444bgra = yuv444_to_bgra_vanilla;
yuv_conv.yuv444argb = yuv444_to_argb_vanilla;
#endif
}
}
@ -239,27 +320,41 @@ init_yuv_converters(void)
void
oggplay_yuv2rgba(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb)
{
if (yuv_conv.yuv2rgba == NULL)
init_yuv_converters();
if (yuv_conv.yuv420rgba == NULL)
init_yuv_converters();
yuv_conv.yuv2rgba(yuv, rgb);
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420rgba(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422rgba(yuv,rgb);
else
yuv_conv.yuv444rgba(yuv,rgb);
}
void
oggplay_yuv2bgra(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
if (yuv_conv.yuv2bgra == NULL)
init_yuv_converters();
if (yuv_conv.yuv420bgra == NULL)
init_yuv_converters();
yuv_conv.yuv2bgra(yuv, rgb);
}
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420bgra(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422bgra(yuv,rgb);
else
yuv_conv.yuv444bgra(yuv,rgb);}
void
oggplay_yuv2argb(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
if (yuv_conv.yuv2argb == NULL)
init_yuv_converters();
if (yuv_conv.yuv420argb == NULL)
init_yuv_converters();
yuv_conv.yuv2argb(yuv, rgb);
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420argb(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422argb(yuv,rgb);
else
yuv_conv.yuv444argb(yuv,rgb);
}

View File

@ -19,8 +19,9 @@
* @param OUT_SHIFT number of pixels to shift after one iteration in rgb data stream
* @param Y_SHIFT number of pixels to shift after one iteration in Y data stream
* @param UV_SHIFT
* @param UV_VERT_SUB
*/
#define YUV_CONVERT(FUNC, CONVERT, VANILLA_OUT, NUM_PIXELS, OUT_SHIFT, Y_SHIFT, UV_SHIFT)\
#define YUV_CONVERT(FUNC, CONVERT, VANILLA_OUT, NUM_PIXELS, OUT_SHIFT, Y_SHIFT, UV_SHIFT, UV_VERT_SUB)\
static void \
(FUNC)(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb) \
{ \
@ -60,12 +61,10 @@ static void \
* vanilla implementation. \
*/ \
if (r) { \
/* if there's only 1 remaining pixel to process \
and the luma width is odd, the for loop above \
has already advanced pu and pv too far. */ \
if (r==1 && yuv->y_width&1) { \
if (r==1 && yuv->y_width&1) { \
pu -= 1; pv -= 1; \
} \
} \
\
for \
( \
j=(yuv->y_width-r); j < yuv->y_width; \
@ -77,11 +76,12 @@ static void \
LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
VANILLA_OUT(dst, r, g, b) \
/* advance chroma ptrs every second sample, except \
when the luma width is odd, in which case the \
chroma samples are truncated and we must reuse \
the previous chroma sample */ \
if (j%2 && !(j+1==yuv->y_width-1 && yuv->y_width&1)) { \
if \
( \
(j%2 && !(j+1==yuv->y_width-1 && yuv->y_width&1)) \
|| \
UV_VERT_SUB==1 \
) { \
pu += 1; pv += 1; \
} \
} \
@ -90,7 +90,12 @@ static void \
ptro += rgb->rgb_width * 4; \
ptry += yuv->y_width; \
\
if (i & 0x1 && !(i+1==h-1 && h&1)) \
if \
( \
(i & 0x1 && !(i+1==h-1 && h&1)) \
|| \
UV_VERT_SUB==1 \
) \
{ \
ptru += yuv->uv_width; \
ptrv += yuv->uv_width; \

View File

@ -74,9 +74,13 @@
* @retval non-zero on error
*/
#if defined(linux) || defined(SOLARIS)
#if defined(linux) || defined(SOLARIS) || defined(AIX) || defined(__FreeBSD__)
#include <semaphore.h>
#if defined(__FreeBSD__)
#define SEM_CREATE(p,s) sem_init(&(p), 0, s)
#else
#define SEM_CREATE(p,s) sem_init(&(p), 1, s)
#endif
#define SEM_SIGNAL(p) sem_post(&(p))
#define SEM_WAIT(p) sem_wait(&(p))
#define SEM_CLOSE(p) sem_destroy(&(p))

View File

@ -38,6 +38,10 @@
#include "cpu.h"
#if defined(_MSC_VER)
# if defined(_M_AMD64)
/* MSVC with x64 doesn't support inline assembler */
#include <emmintrin.h>
# endif
#include "yuv2rgb_x86_vs.h"
#elif defined(__GNUC__)
#include "yuv2rgb_x86.h"
@ -81,12 +85,14 @@ static const simd_t simd_table[9] = {
{{ALFA, ALFA}}
};
/* MMX intristics are not supported by VS in x64 mode, thus disable it */
#if !(defined(_MSC_VER) && defined(_M_AMD64))
/**
* the conversion functions using MMX instructions
*/
/* template for the MMX conversion functions */
#define YUV_CONVERT_MMX(FUNC, CONVERT, CONV_BY_PIXEL) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIXEL, 8, 32, 8, 4)
#define YUV_CONVERT_MMX(FUNC, CONVERT, CONV_BY_PIXEL, UV_SHIFT, UV_VERT_SUB) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIXEL, 8, 32, 8, UV_SHIFT, UV_VERT_SUB)
#define CLEANUP emms()
#define OUT_RGBA_32 OUTPUT_RGBA_32(movq, mm, 8, 16, 24)
@ -99,9 +105,17 @@ static const simd_t simd_table[9] = {
YUV_2_RGB(movq, mm) \
OUTPUT_FUNC
YUV_CONVERT_MMX(yuv420_to_rgba_mmx, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
YUV_CONVERT_MMX(yuv420_to_bgra_mmx, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
YUV_CONVERT_MMX(yuv420_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
YUV_CONVERT_MMX(yuv420_to_rgba_mmx, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 4, 2)
YUV_CONVERT_MMX(yuv420_to_bgra_mmx, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 4, 2)
YUV_CONVERT_MMX(yuv420_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 4, 2)
YUV_CONVERT_MMX(yuv422_to_rgba_mmx, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 4, 1)
YUV_CONVERT_MMX(yuv422_to_bgra_mmx, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 4, 1)
YUV_CONVERT_MMX(yuv422_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 4, 1)
YUV_CONVERT_MMX(yuv444_to_rgba_mmx, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 8, 1)
YUV_CONVERT_MMX(yuv444_to_bgra_mmx, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 8, 1)
YUV_CONVERT_MMX(yuv444_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 8, 1)
#undef MOVNTQ
@ -109,9 +123,17 @@ YUV_CONVERT_MMX(yuv420_to_argb_mmx, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
/* template for the SSE conversion functions */
#define MOVNTQ SSE_MOVNTQ
YUV_CONVERT_MMX(yuv420_to_rgba_sse, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
YUV_CONVERT_MMX(yuv420_to_bgra_sse, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
YUV_CONVERT_MMX(yuv420_to_rgba_sse, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 4, 2)
YUV_CONVERT_MMX(yuv420_to_bgra_sse, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 4, 2)
YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 4, 2)
YUV_CONVERT_MMX(yuv422_to_rgba_sse, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 4, 1)
YUV_CONVERT_MMX(yuv422_to_bgra_sse, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 4, 1)
YUV_CONVERT_MMX(yuv422_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 4, 1)
YUV_CONVERT_MMX(yuv444_to_rgba_sse, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 8, 1)
YUV_CONVERT_MMX(yuv444_to_bgra_sse, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 8, 1)
YUV_CONVERT_MMX(yuv444_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 8, 1)
#undef CONVERT
#undef CLEANUP
@ -119,6 +141,7 @@ YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
#undef OUT_ARGB_32
#undef OUT_BGRA_32
#undef MOVNTQ
#endif
/**
@ -126,7 +149,7 @@ YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
*/
/* template for the SSE2 conversion functions */
#define YUV_CONVERT_SSE2(FUNC, CONVERT, CONV_BY_PIX) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIX, 16, 64, 16, 8)
#define YUV_CONVERT_SSE2(FUNC, CONVERT, CONV_BY_PIX, UV_SHIFT, UV_VERT_SUB) YUV_CONVERT(FUNC, CONVERT, CONV_BY_PIX, 16, 64, 16, UV_SHIFT, UV_VERT_SUB)
#define OUT_RGBA_32 OUTPUT_RGBA_32(movdqa, xmm, 16, 32, 48)
#define OUT_ARGB_32 OUTPUT_ARGB_32(movdqa, xmm, 16, 32, 48)
@ -135,13 +158,28 @@ YUV_CONVERT_MMX(yuv420_to_argb_sse, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
#define CLEANUP
/* yuv420 -> */
#if defined(_MSC_VER) && defined(_M_AMD64)
#define CONVERT(OUTPUT_FUNC) __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; \
LOAD_YUV_PLANAR_2(movdqu, xmm) \
YUV_2_RGB(movdqa, xmm) \
OUTPUT_FUNC
#else
#define CONVERT(OUTPUT_FUNC) LOAD_YUV_PLANAR_2(movdqu, xmm) \
YUV_2_RGB(movdqa, xmm) \
OUTPUT_FUNC
#endif
YUV_CONVERT_SSE2(yuv420_to_rgba_sse2, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 8, 2)
YUV_CONVERT_SSE2(yuv420_to_bgra_sse2, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 8, 2)
YUV_CONVERT_SSE2(yuv420_to_argb_sse2, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 8, 2)
YUV_CONVERT_SSE2(yuv420_to_rgba_sse2, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT)
YUV_CONVERT_SSE2(yuv420_to_bgra_sse2, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT)
YUV_CONVERT_SSE2(yuv420_to_argb_sse2, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT)
YUV_CONVERT_SSE2(yuv422_to_rgba_sse2, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 8, 1)
YUV_CONVERT_SSE2(yuv422_to_bgra_sse2, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 8, 1)
YUV_CONVERT_SSE2(yuv422_to_argb_sse2, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 8, 1)
YUV_CONVERT_SSE2(yuv444_to_rgba_sse2, CONVERT(OUT_RGBA_32), VANILLA_RGBA_OUT, 16, 1)
YUV_CONVERT_SSE2(yuv444_to_bgra_sse2, CONVERT(OUT_BGRA_32), VANILLA_BGRA_OUT, 16, 1)
YUV_CONVERT_SSE2(yuv444_to_argb_sse2, CONVERT(OUT_ARGB_32), VANILLA_ARGB_OUT, 16, 1)
#undef CONVERT
#undef OUT_RGBA_32

View File

@ -8,6 +8,7 @@
#define SSE_MOVNTQ movntq
#define SSE2_MOVNTQ movdqu
#if defined(_M_IX86)
#define LOAD_YUV_PLANAR_2(mov_instr, reg_type) \
__asm { \
__asm mov eax, py \
@ -18,7 +19,17 @@
__asm mov_instr reg_type##1, [eax] \
__asm pxor reg_type##4, reg_type##4 \
}
#elif defined(_M_AMD64)
#define LOAD_YUV_PLANAR_2(mov_instr, reg_type) \
{ \
xmm6 = _mm_loadu_si128((__m128i*)py); \
xmm0 = _mm_loadu_si128((__m128i*)pu); \
xmm1 = _mm_loadu_si128((__m128i*)pv); \
xmm4 = _mm_setzero_si128(); \
}
#endif
#if defined(_M_IX86)
#define OUTPUT_RGBA_32(mov_instr, reg_type, offset0, offset1, offset2) \
__asm { \
__asm mov eax, dst \
@ -40,7 +51,26 @@
__asm MOVNTQ [eax+offset1], reg_type##4 \
__asm MOVNTQ [eax+offset2], reg_type##7 \
}
#elif defined(_M_AMD64)
#define OUTPUT_RGBA_32(mov_instr, reg_type, offset0, offset1, offset2) \
{ \
xmm3 = _mm_load_si128((__m128i*)simd_table+8); \
xmm4 = _mm_unpackhi_epi8(xmm1, xmm2); \
xmm1 = _mm_unpacklo_epi8(xmm1, xmm2); \
xmm5 = _mm_unpackhi_epi8(xmm0, xmm3); \
xmm0 = _mm_unpacklo_epi8(xmm0, xmm3); \
xmm6 = _mm_unpackhi_epi8(xmm1, xmm0); \
xmm1 = _mm_unpacklo_epi8(xmm1, xmm0); \
xmm7 = _mm_unpackhi_epi8(xmm4, xmm5); \
xmm4 = _mm_unpacklo_epi8(xmm4, xmm5); \
_mm_storeu_si128(dst, xmm1); \
_mm_storeu_si128(dst + offset0, xmm6); \
_mm_storeu_si128(dst + offset1, xmm4); \
_mm_storeu_si128(dst + offset2, xmm7); \
}
#endif
#if defined(_M_IX86)
#define OUTPUT_ARGB_32(mov_instr, reg_type, offset0, offset1, offset2) \
__asm { \
__asm mov eax, dst \
@ -62,7 +92,26 @@
__asm MOVNTQ [eax+offset1], reg_type##4 \
__asm MOVNTQ [eax+offset2], reg_type##1 \
}
#elif defined(_M_AMD64)
#define OUTPUT_ARGB_32(mov_instr, reg_type, offset0, offset1, offset2) \
{ \
xmm3 = _mm_load_si128((__m128i*)simd_table+8); \
xmm5 = _mm_unpackhi_epi8(xmm2, xmm0); \
xmm2 = _mm_unpacklo_epi8(xmm2, xmm0); \
xmm4 = _mm_unpackhi_epi8(xmm3, xmm1); \
xmm3 = _mm_unpacklo_epi8(xmm3, xmm1); \
xmm0 = _mm_unpackhi_epi16(xmm3, xmm2); \
xmm3 = _mm_unpacklo_epi16(xmm3, xmm2); \
xmm1 = _mm_unpackhi_epi16(xmm4, xmm5); \
xmm4 = _mm_unpacklo_epi16(xmm4, xmm5); \
_mm_storeu_si128(dst, xmm3); \
_mm_storeu_si128(dst + offset0, xmm0); \
_mm_storeu_si128(dst + offset1, xmm4); \
_mm_storeu_si128(dst + offset2, xmm1); \
}
#endif
#if defined(_M_IX86)
#define OUTPUT_BGRA_32(mov_instr, reg_type, offset0, offset1, offset2) \
__asm { \
__asm mov eax, dst \
@ -84,7 +133,26 @@
__asm MOVNTQ [eax+offset1], reg_type##4 \
__asm MOVNTQ [eax+offset2], reg_type##7 \
}
#elif defined(_M_AMD64)
#define OUTPUT_BGRA_32(mov_instr, reg_type, offset0, offset1, offset2) \
{ \
xmm3 = _mm_load_si128((__m128i*)simd_table+8); \
xmm4 = _mm_unpackhi_epi8(xmm0, xmm2); \
xmm0 = _mm_unpacklo_epi8(xmm0, xmm2); \
xmm5 = _mm_unpackhi_epi8(xmm1, xmm3); \
xmm1 = _mm_unpacklo_epi8(xmm1, xmm3); \
xmm6 = _mm_unpackhi_epi8(xmm0, xmm1); \
xmm0 = _mm_unpacklo_epi8(xmm0, xmm1); \
xmm7 = _mm_unpackhi_epi8(xmm4, xmm5); \
xmm4 = _mm_unpacklo_epi8(xmm4, xmm5); \
_mm_storeu_si128(dst, xmm0); \
_mm_storeu_si128(dst + offset0, xmm6); \
_mm_storeu_si128(dst + offset1, xmm4); \
_mm_storeu_si128(dst + offset2, xmm7); \
}
#endif
#if defined(_M_IX86)
#define YUV_2_RGB(mov_instr, reg_type) \
__asm { \
__asm punpcklbw reg_type##0, reg_type##4 /* mm0 = u3 u2 u1 u0 */\
@ -127,6 +195,48 @@
__asm punpcklbw reg_type##1, reg_type##4 /* mm1 = R7 R6 R5 R4 R3 R2 R1 R0 */\
__asm punpcklbw reg_type##2, reg_type##5 /* mm2 = G7 G6 G5 G4 G3 G2 G1 G0 */\
}
#elif defined(_M_AMD64)
#define YUV_2_RGB(mov_instr, reg_type) \
{ \
xmm0 = _mm_unpacklo_epi8(xmm0, xmm4); /* mm0 = u3 u2 u1 u0 */\
xmm1 = _mm_unpacklo_epi8(xmm1, xmm4); /* mm1 = v3 v2 v1 v0 */\
xmm0 = _mm_subs_epi16(xmm0, _mm_load_si128((__m128i*)simd_table)); /* u -= 128 */\
xmm1 = _mm_subs_epi16(xmm1, _mm_load_si128((__m128i*)simd_table)); /* v -= 128 */\
xmm0 = _mm_slli_epi16(xmm0, 3); /* promote precision */\
xmm1 = _mm_slli_epi16(xmm1, 3); /* promote precision */\
xmm2 = _mm_mulhi_epi16(xmm0, _mm_load_si128((__m128i*)simd_table+1)); /* mm2 = u * u_green */\
xmm3 = _mm_mulhi_epi16(xmm1, _mm_load_si128((__m128i*)simd_table+2)); /* mm3 = v * v_green */\
xmm0 = _mm_mulhi_epi16(xmm0, _mm_load_si128((__m128i*)simd_table+3)); /* mm0 = chroma_b */\
xmm1 = _mm_mulhi_epi16(xmm1, _mm_load_si128((__m128i*)simd_table+4)); /* mm1 = chroma_r */\
xmm2 = _mm_adds_epi16(xmm2, xmm3); /* mm2 = chroma_g */\
xmm6 = _mm_subs_epu8(xmm6, _mm_load_si128((__m128i*)simd_table+5)); /* Y -= 16 */\
xmm7 = xmm6; /* mm7 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */\
xmm6 = _mm_and_si128(xmm6, _mm_load_si128((__m128i*)simd_table+7); /* mm6 = Y6 Y4 Y2 Y0 */\
xmm7 = _mm_srli_epi16(xmm7, 8); /* mm7 = Y7 Y5 Y3 Y1 */\
xmm6 = _mm_slli_epi16(xmm6, 3); /* promote precision */\
xmm7 = _mm_slli_epi16(xmm7, 3); /* promote precision */\
xmm6 = _mm_mulhi_epi16(xmm6, _mm_load_si128((__m128i*)simd_table+6)); /* mm6 = luma_rgb even */\
xmm7 = _mm_mulhi_epi16(xmm7, _mm_load_si128((__m128i*)simd_table+6)); /* mm7 = luma_rgb odd */\
xmm3 = xmm0; /* mm3 = chroma_b */\
xmm4 = xmm1; /* mm4 = chroma_r */\
xmm5 = xmm2; /* mm5 = chroma_g */\
xmm0 = _mm_adds_epi16(xmm0, xmm6); /* mm0 = B6 B4 B2 B0 */\
xmm3 = _mm_adds_epi16(xmm3, xmm7); /* mm3 = B7 B5 B3 B1 */\
xmm1 = _mm_adds_epi16(xmm1, xmm6); /* mm1 = R6 R4 R2 R0 */\
xmm4 = _mm_adds_epi16(xmm4, xmm7); /* mm4 = R7 R5 R3 R1 */\
xmm2 = _mm_adds_epi16(xmm2, xmm6); /* mm2 = G6 G4 G2 G0 */\
xmm5 = _mm_adds_epi16(xmm5, xmm7); /* mm5 = G7 G5 G3 G1 */\
xmm0 = _mm_packus_epi16(xmm0, xmm0); /* saturate to 0-255 */\
xmm1 = _mm_packus_epi16(xmm1, xmm1); /* saturate to 0-255 */\
xmm2 = _mm_packus_epi16(xmm2, xmm2); /* saturate to 0-255 */\
xmm3 = _mm_packus_epi16(xmm3, xmm3); /* saturate to 0-255 */\
xmm4 = _mm_packus_epi16(xmm4, xmm4); /* saturate to 0-255 */\
xmm5 = _mm_packus_epi16(xmm5, xmm5); /* saturate to 0-255 */\
xmm0 = _mm_unpacklo_epi8(xmm0, xmm3); /* mm0 = B7 B6 B5 B4 B3 B2 B1 B0 */\
xmm1 = _mm_unpacklo_epi8(xmm1, xmm4); /* mm1 = R7 R6 R5 R4 R3 R2 R1 R0 */\
xmm2 = _mm_unpacklo_epi8(xmm2, xmm5); /* mm2 = G7 G6 G5 G4 G3 G2 G1 G0 */\
}
#endif
#endif

View File

@ -1,23 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
index 3296fea..d6256c6 100644
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -708,14 +708,15 @@ read_more_data:
oggplay_data_clean_list (me->decode_data[i]);
}
+ if (me->shutdown) {
+ return E_OGGPLAY_OK;
+ }
+
if (info == NULL) {
goto read_more_data;
}
me->target += me->callback_period;
- if (me->shutdown) {
- return E_OGGPLAY_OK;
- }
if (r == -1) {
return E_OGGPLAY_USER_INTERRUPT;
}

View File

@ -33,9 +33,9 @@ cp $1/src/liboggplay/oggplay_query.c ./src/liboggplay/oggplay_query.c
cp $1/src/liboggplay/cpu.c ./src/liboggplay/cpu.c
cp $1/src/liboggplay/cpu.h ./src/liboggplay/cpu.h
cp $1/src/liboggplay/oggplay_yuv2rgb_template.h ./src/liboggplay/oggplay_yuv2rgb_template.h
cp $1/src/liboggplay/oggplay_yuv2rgb_x86.c ./src/liboggplay/oggplay_yuv2rgb_x86.c
cp $1/src/liboggplay/yuv2rgb_x86.h ./src/liboggplay/yuv2rgb_x86.h
cp $1/src/liboggplay/yuv2rgb_x86_vs.h ./src/liboggplay/yuv2rgb_x86_vs.h
cp $1/src/liboggplay/x86/oggplay_yuv2rgb_x86.c ./src/liboggplay/x86/oggplay_yuv2rgb_x86.c
cp $1/src/liboggplay/x86/yuv2rgb_x86.h ./src/liboggplay/x86/yuv2rgb_x86.h
cp $1/src/liboggplay/x86/yuv2rgb_x86_vs.h ./src/liboggplay/x86/yuv2rgb_x86_vs.h
sed 's/#include "config_win32.h"//g' $1/src/liboggplay/oggplay_private.h >./src/liboggplay/oggplay_private.h1
sed 's/#include <config.h>/#ifdef WIN32\
#include "config_win32.h"\
@ -45,24 +45,17 @@ sed 's/#include <config.h>/#ifdef WIN32\
rm ./src/liboggplay/oggplay_private.h1
sed s/\#ifdef\ HAVE_INTTYPES_H/\#if\ HAVE_INTTYPES_H/g $1/src/liboggplay/oggplay_data.c >./src/liboggplay/oggplay_data.c
patch -p3 < endian.patch
patch -p3 < trac466.patch
patch -p3 < bug492436.patch
patch -p3 < bug493140.patch
patch -p3 < bug481921.patch
patch -p3 < aspect_ratio.patch
patch -p3 < bug493678.patch
patch -p1 < bug493224.patch
patch -p3 < seek_to_key_frame.patch
patch -p3 < bug488951.patch
patch -p3 < bug488951_yuv_fix.patch
patch -p3 < bug488951_yuv_fix_2.patch
patch -p3 < bug495129a.patch
patch -p3 < bug495129b.patch
patch -p3 < bug487519.patch
rm -f src/liboggplay/os2_semaphore.c
rm -f src/liboggplay/os2_semaphore.h
patch -p3 < oggplay_os2.patch
patch -p3 < bug498815.patch
patch -p3 < bug498824.patch
patch -p3 < bug496529.patch
patch -p3 < bug499519.patch
patch -p3 < bug500311.patch
patch -p3 < faster_seek.patch
patch -p3 < fix-17ef4ca82df28.patch
patch -p3 < handle-read-errors.patch