зеркало из https://github.com/mozilla/gecko-dev.git
Bug 512398 - fix liboggplay update (rev f4087c5ac148) which accidentally removed liboggplay's os2_semaphore.*. r=doublec
This commit is contained in:
Родитель
81137811d0
Коммит
19c48e0643
|
@ -292,14 +292,15 @@ public:
|
|||
}
|
||||
|
||||
// Decode one frame of data, returning the OggPlay error code. Must
|
||||
// be called only when the current state > DECODING_METADATA. The decode
|
||||
// monitor MUST NOT be locked during this call since it can take a long
|
||||
// time. liboggplay internally handles locking.
|
||||
// Any return value apart from those below is mean decoding cannot continue.
|
||||
// be called only when the current state > DECODING_METADATA. You must
|
||||
// pass the locked decode monitor to this call. liboggplay internally
|
||||
// handles its own locking. If liboggplay reaches end of file, we will
|
||||
// transition the state machine to COMPLETED state. Any return value
|
||||
// apart from those below is mean decoding cannot continue.
|
||||
// E_OGGPLAY_CONTINUE = One frame decoded and put in buffer list
|
||||
// E_OGGPLAY_USER_INTERRUPT = One frame decoded, buffer list is now full
|
||||
// E_OGGPLAY_TIMEOUT = No frames decoded, timed out
|
||||
OggPlayErrorCode DecodeFrame();
|
||||
OggPlayErrorCode DecodeFrame(nsAutoMonitor& aMonitor);
|
||||
|
||||
// Handle any errors returned by liboggplay when decoding a frame.
|
||||
// Since this function can change the decoding state it must be called
|
||||
|
@ -727,9 +728,18 @@ nsOggDecodeStateMachine::~nsOggDecodeStateMachine()
|
|||
oggplay_close(mPlayer);
|
||||
}
|
||||
|
||||
OggPlayErrorCode nsOggDecodeStateMachine::DecodeFrame()
|
||||
OggPlayErrorCode nsOggDecodeStateMachine::DecodeFrame(nsAutoMonitor& aMonitor)
|
||||
{
|
||||
NS_ASSERTION(mState != DECODER_STATE_COMPLETED &&
|
||||
mState != DECODER_STATE_SHUTDOWN,
|
||||
"Don't call DecodeFrame() after reaching EOF!");
|
||||
aMonitor.Exit();
|
||||
OggPlayErrorCode r = oggplay_step_decoding(mPlayer);
|
||||
aMonitor.Enter();
|
||||
if (r == E_OGGPLAY_OK) {
|
||||
LOG(PR_LOG_DEBUG, ("Changed state to COMPLETED"));
|
||||
mState = DECODER_STATE_COMPLETED;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1332,11 +1342,13 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
audioTime += frame->mAudioData.Length() /
|
||||
(float)mAudioRate / (float)mAudioChannels;
|
||||
}
|
||||
do {
|
||||
aMonitor.Exit();
|
||||
r = DecodeFrame();
|
||||
aMonitor.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
r = E_OGGPLAY_TIMEOUT;
|
||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||
mState != DECODER_STATE_COMPLETED &&
|
||||
r == E_OGGPLAY_TIMEOUT)
|
||||
{
|
||||
r = DecodeFrame(aMonitor);
|
||||
}
|
||||
|
||||
HandleDecodeErrors(r);
|
||||
|
||||
|
@ -1349,7 +1361,8 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
|
||||
delete frame;
|
||||
frame = nextFrame;
|
||||
} while (frame->mDecodedFrameTime < target);
|
||||
} while (frame->mDecodedFrameTime < target &&
|
||||
mState != DECODER_STATE_COMPLETED);
|
||||
|
||||
if (mState == DECODER_STATE_SHUTDOWN) {
|
||||
delete frame;
|
||||
|
@ -1427,9 +1440,7 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
|
||||
OggPlayErrorCode r = E_OGGPLAY_TIMEOUT;
|
||||
while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT) {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
r = DecodeFrame(mon);
|
||||
}
|
||||
|
||||
HandleDecodeErrors(r);
|
||||
|
@ -1623,31 +1634,31 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
continue;
|
||||
}
|
||||
|
||||
OggPlayErrorCode r;
|
||||
// Now try to decode another frame to see if we're at the end.
|
||||
do {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
OggPlayErrorCode r = E_OGGPLAY_TIMEOUT;
|
||||
// If possible decode a few more frames, so that we don't need to
|
||||
// wait for the step decode thread to start up before we can resume
|
||||
// playback. This makes playback start faster after seeking.
|
||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||
mState != DECODER_STATE_COMPLETED &&
|
||||
r == E_OGGPLAY_TIMEOUT)
|
||||
{
|
||||
r = DecodeFrame(mon);
|
||||
}
|
||||
HandleDecodeErrors(r);
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
QueueDecodedFrames();
|
||||
}
|
||||
|
||||
// Change state to DECODING now. SeekingStopped will call
|
||||
// nsOggDecodeStateMachine::Seek to reset our state to SEEKING
|
||||
// if we need to seek again.
|
||||
LOG(PR_LOG_DEBUG, ("Changed state from SEEKING (to %f) to DECODING", seekTime));
|
||||
mState = DECODER_STATE_DECODING;
|
||||
// SeekingStopped will call nsOggDecodeStateMachine::Seek to reset
|
||||
// our state to SEEKING if we need to seek again.
|
||||
nsCOMPtr<nsIRunnable> stopEvent;
|
||||
if (mDecodedFrames.GetCount() > 1) {
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped);
|
||||
mState = DECODER_STATE_DECODING;
|
||||
} else {
|
||||
if (mState == DECODER_STATE_COMPLETED) {
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd);
|
||||
mState = DECODER_STATE_COMPLETED;
|
||||
} else {
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped);
|
||||
LOG(PR_LOG_DEBUG, ("Changed state from SEEKING (to %f) to DECODING", seekTime));
|
||||
mState = DECODER_STATE_DECODING;
|
||||
}
|
||||
mon.NotifyAll();
|
||||
|
||||
|
@ -1730,19 +1741,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();
|
||||
}
|
||||
|
@ -1781,8 +1795,8 @@ void nsOggDecodeStateMachine::LoadOggHeaders(nsChannelReader* aReader)
|
|||
mAspectRatio = r == E_OGGPLAY_OK && aspectd > 0 ?
|
||||
float(aspectn)/float(aspectd) : 1.0;
|
||||
|
||||
int y_width;
|
||||
int y_height;
|
||||
int y_width = 0;
|
||||
int y_height = 0;
|
||||
oggplay_get_video_y_size(mPlayer, i, &y_width, &y_height);
|
||||
mDecoder->SetRGBData(y_width, y_height, mFramerate, mAspectRatio, nsnull);
|
||||
}
|
||||
|
|
|
@ -3,18 +3,21 @@
|
|||
// "bogus/duh" in each list.
|
||||
|
||||
// These are small test files, good for just seeing if something loads.
|
||||
// Used in test_load.html
|
||||
var gSmallTests = [
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ 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:"bogus.duh", type:"bogus/duh" }
|
||||
{ name:"bogus.duh", type:"bogus/duh" },
|
||||
{ name: "bug501279.ogg", type:"audio/ogg", duration:0 },
|
||||
];
|
||||
|
||||
// These are files that we just want to make sure we can play through.
|
||||
// We can also check metadata.
|
||||
// Put files of the same type together in this list so if something crashes
|
||||
// we have some idea of which backend is responsible.
|
||||
// Used in test_playback.html
|
||||
var gPlayTests = [
|
||||
// 8-bit samples
|
||||
{ name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
|
@ -35,6 +38,12 @@ var gPlayTests = [
|
|||
// More audio in file than video.
|
||||
{ name: "short-video.ogv", type:"video/ogg", duration:1.081 },
|
||||
|
||||
{ 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: "bug504644.ogv", type:"video/ogg", duration:1.56 },
|
||||
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
||||
|
@ -42,13 +51,8 @@ var gPlayTests = [
|
|||
// without crashing of course.
|
||||
// Put files of the same type together in this list so if something crashes
|
||||
// we have some idea of which backend is responsible.
|
||||
// Used by test_playback_errors.html
|
||||
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" },
|
||||
|
|
|
@ -412,6 +412,7 @@ fs_vorbis_reset (FishSound * fsound)
|
|||
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
|
||||
|
||||
vorbis_block_init (&fsv->vd, &fsv->vb);
|
||||
fsv->packetno = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 8640eb3fddc43ad4a5d2cdbcbc62238204e952aa.
|
||||
|
||||
The following local patches have been applied:
|
||||
|
||||
|
@ -13,37 +13,11 @@ 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.
|
||||
bug500311.patch: Fix crash during decoder initialization.
|
||||
|
||||
bug496529.patch: Bug 496529.
|
||||
|
|
|
@ -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
|
||||
@@ -301,16 +301,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) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback_info.c b/media/liboggplay/src/liboggplay/oggplay_callback_info.c
|
||||
--- a/media/liboggplay/src/liboggplay/oggplay_callback_info.c
|
||||
+++ b/media/liboggplay/src/liboggplay/oggplay_callback_info.c
|
||||
@@ -133,21 +133,23 @@ oggplay_callback_info_prepare(OggPlay *m
|
||||
@@ -185,21 +185,23 @@ oggplay_callback_info_prepare(OggPlay *m
|
||||
|
||||
track_info->available_records = count;
|
||||
track_info->required_records = 0;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
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,
|
||||
|
||||
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) {
|
||||
+ // 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,
|
|
@ -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] \
|
|
@ -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; \
|
||||
\
|
|
@ -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 \
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
|
||||
index 7683b80..ad127a0 100644
|
||||
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
|
||||
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
|
||||
@@ -536,7 +536,7 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
|
||||
decoder->content_type = content_type;
|
||||
decoder->content_type_name =
|
||||
oggz_stream_get_content_type (me->oggz, serialno);
|
||||
- decoder->active = 1;
|
||||
+ decoder->active = 0;
|
||||
decoder->final_granulepos = -1;
|
||||
decoder->player = me;
|
||||
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
|
|
@ -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;
|
||||
|
||||
/*
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
#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"
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -1,99 +0,0 @@
|
|||
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
|
||||
}
|
||||
|
||||
/*
|
||||
* set all the tracks to inactive
|
||||
*/
|
||||
for (i = 0; i < me->num_tracks; i++) {
|
||||
me->decode_data[i]->active = 0;
|
||||
}
|
||||
+ me->active_tracks = 0;
|
||||
|
||||
/*
|
||||
* if the buffer was set up before initialisation, prepare it now
|
||||
*/
|
||||
if (me->buffer != NULL) {
|
||||
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) {
|
||||
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->decoder.decoded_type = OGGPLAY_YUV_VIDEO;
|
||||
+ decoder->decoder.player->active_tracks++;
|
||||
}
|
||||
|
||||
void
|
||||
oggplay_shutdown_theora(void *user_data) {
|
||||
|
||||
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
|
||||
|
||||
if (decoder->remaining_header_packets == 0) {
|
||||
@@ -366,16 +367,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);
|
||||
|
||||
decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO;
|
||||
+ decoder->decoder.player->active_tracks++;
|
||||
}
|
||||
|
||||
void
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
decoder->serialno = serialno;
|
||||
decoder->content_type = content_type;
|
||||
decoder->content_type_name =
|
||||
oggz_stream_get_content_type (me->oggz, serialno);
|
||||
- decoder->active = 0;
|
||||
+ decoder->active = 1;
|
||||
decoder->final_granulepos = -1;
|
||||
decoder->player = me;
|
||||
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
|
||||
|
||||
/*
|
||||
* set the StreamInfo to unitialised until we get some real data in
|
||||
*/
|
||||
decoder->stream_info = OGGPLAY_STREAM_UNINITIALISED;
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
diff --git a/media/liboggplay/src/liboggplay/oggplay_private.h b/media/liboggplay/src/liboggplay/oggplay_private.h
|
||||
--- a/media/liboggplay/src/liboggplay/oggplay_private.h
|
||||
+++ b/media/liboggplay/src/liboggplay/oggplay_private.h
|
||||
@@ -62,16 +62,22 @@
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -64,16 +64,22 @@
|
||||
|
||||
#ifdef HAVE_WINSOCK2
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
|
||||
+#ifdef OS2
|
||||
+#define INCL_DOSSEMAPHORES
|
||||
+#define INCL_DOSPROCESS
|
||||
+#include <os2.h>
|
||||
#endif
|
||||
|
||||
+#endif
|
||||
+
|
||||
// for Win32 <windows.h> has to be included last
|
||||
#include "std_semaphore.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* has_been_presented: 0 until the data has been added as a "required" element,
|
||||
* then 1.
|
||||
*/
|
||||
diff --git a/media/liboggplay/src/liboggplay/oggplay_tools.c b/media/liboggplay/src/liboggplay/oggplay_tools.c
|
||||
--- a/media/liboggplay/src/liboggplay/oggplay_tools.c
|
||||
+++ b/media/liboggplay/src/liboggplay/oggplay_tools.c
|
||||
|
@ -278,7 +278,7 @@ new file mode 100644
|
|||
diff --git a/media/liboggplay/src/liboggplay/std_semaphore.h b/media/liboggplay/src/liboggplay/std_semaphore.h
|
||||
--- a/media/liboggplay/src/liboggplay/std_semaphore.h
|
||||
+++ b/media/liboggplay/src/liboggplay/std_semaphore.h
|
||||
@@ -83,16 +83,23 @@ typedef sem_t semaphore;
|
||||
@@ -87,16 +87,23 @@
|
||||
typedef sem_t semaphore;
|
||||
#elif defined(WIN32)
|
||||
#include <windows.h>
|
||||
|
|
|
@ -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,16 +25,15 @@ 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
|
||||
@@ -71,16 +71,64 @@ oggplay_seek(OggPlay *me, ogg_int64_t mi
|
||||
return E_OGGPLAY_CANT_SEEK;
|
||||
}
|
||||
}
|
||||
|
||||
oggplay_seek_cleanup(me, milliseconds);
|
||||
|
||||
return E_OGGPLAY_OK;
|
||||
|
||||
return oggplay_seek_cleanup(me, milliseconds);
|
||||
}
|
||||
|
||||
+OggPlayErrorCode
|
||||
OggPlayErrorCode
|
||||
+oggplay_seek_to_keyframe(OggPlay *me,
|
||||
+ int* tracks,
|
||||
+ int num_tracks,
|
||||
|
@ -79,13 +78,10 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/s
|
|||
+ return E_OGGPLAY_CANT_SEEK;
|
||||
+ }
|
||||
+
|
||||
+ oggplay_seek_cleanup(me, time);
|
||||
+
|
||||
+ return E_OGGPLAY_OK;
|
||||
+
|
||||
+ return oggplay_seek_cleanup(me, time);
|
||||
+}
|
||||
+
|
||||
void
|
||||
+OggPlayErrorCode
|
||||
oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
|
||||
{
|
||||
|
||||
|
@ -93,3 +89,4 @@ diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/s
|
|||
OggPlaySeekTrash ** p;
|
||||
OggPlayDataHeader ** end_of_list_p;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -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). */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,25 @@ oggplay_initialise(OggPlay *me, int block) {
|
|||
return E_OGGPLAY_OGGZ_UNHAPPY;
|
||||
|
||||
while (1) {
|
||||
|
||||
if (oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE) <= 0) {
|
||||
return E_OGGPLAY_BAD_INPUT;
|
||||
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 (me->all_tracks_initialised) {
|
||||
|
@ -134,7 +154,6 @@ oggplay_initialise(OggPlay *me, int block) {
|
|||
for (i = 0; i < me->num_tracks; i++) {
|
||||
me->decode_data[i]->active = 0;
|
||||
}
|
||||
me->active_tracks = 0;
|
||||
|
||||
/*
|
||||
* if the buffer was set up before initialisation, prepare it now
|
||||
|
@ -153,7 +172,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 +180,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 +217,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 +335,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 +352,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 +500,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 +530,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 +541,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 +561,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 +639,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 +730,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 +800,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 +855,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 +869,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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -46,28 +46,41 @@
|
|||
#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 +89,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 +219,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 +236,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 +250,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 +280,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 +292,7 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
|
|||
common->player->active_tracks--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return OGGZ_CONTINUE;
|
||||
|
||||
}
|
||||
|
||||
|
@ -224,35 +300,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 +389,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 +419,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 +473,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,56 +489,104 @@ 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++;
|
||||
}
|
||||
|
||||
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) {
|
||||
// Unrecoverable error, disable track
|
||||
op->e_o_s = 1;
|
||||
common->active = 0;
|
||||
common->player->active_tracks--;
|
||||
return OGGZ_ERR_HOLE_IN_DATA;
|
||||
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 (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 +594,7 @@ oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
|
|||
common->player->active_tracks--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return OGGZ_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -428,19 +604,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 +637,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 +671,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 +755,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 +767,7 @@ oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
|
|||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return OGGZ_CONTINUE;
|
||||
|
||||
}
|
||||
|
||||
|
@ -540,10 +779,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 +794,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 +816,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 +828,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 +847,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 +866,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 +888,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 +913,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_STOP_OK);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
typedef struct {
|
||||
OggPlayReader functions;
|
||||
char * file_name;
|
||||
const char * file_name;
|
||||
FILE * file;
|
||||
long current_position;
|
||||
long size;
|
||||
|
|
|
@ -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;
|
||||
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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -72,10 +72,7 @@ oggplay_seek(OggPlay *me, ogg_int64_t milliseconds) {
|
|||
}
|
||||
}
|
||||
|
||||
oggplay_seek_cleanup(me, milliseconds);
|
||||
|
||||
return E_OGGPLAY_OK;
|
||||
|
||||
return oggplay_seek_cleanup(me, milliseconds);
|
||||
}
|
||||
|
||||
OggPlayErrorCode
|
||||
|
@ -123,13 +120,10 @@ oggplay_seek_to_keyframe(OggPlay *me,
|
|||
return E_OGGPLAY_CANT_SEEK;
|
||||
}
|
||||
|
||||
oggplay_seek_cleanup(me, time);
|
||||
|
||||
return E_OGGPLAY_OK;
|
||||
|
||||
return oggplay_seek_cleanup(me, time);
|
||||
}
|
||||
|
||||
void
|
||||
OggPlayErrorCode
|
||||
oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
|
||||
{
|
||||
|
||||
|
@ -138,8 +132,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
|
||||
|
@ -150,13 +144,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;
|
||||
|
||||
/*
|
||||
|
@ -165,11 +159,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
|
||||
|
@ -219,6 +213,22 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
|
|||
}
|
||||
|
||||
*p = trash;
|
||||
|
||||
if (milliseconds == 0) {
|
||||
for (i = 0; i < me->num_tracks; i++) {
|
||||
OggPlayDecode *track = me->decode_data[i];
|
||||
FishSound *sound_handle;
|
||||
OggPlayAudioDecode *audio_decode;
|
||||
if (track->content_type != OGGZ_CONTENT_VORBIS) {
|
||||
continue;
|
||||
}
|
||||
audio_decode = (OggPlayAudioDecode*)track;
|
||||
sound_handle = audio_decode->sound_handle;
|
||||
fish_sound_reset(sound_handle);
|
||||
}
|
||||
}
|
||||
|
||||
return E_OGGPLAY_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
#ifndef 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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,23 +45,10 @@ 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче