Video player task retired; minor legacy video semantical changes; improved video playback jitter compensation
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3297 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -615,8 +615,7 @@ dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
|||||||
|
|
||||||
This->length = (float) dukv->cframes / DUCK_GENERAL_FPS;
|
This->length = (float) dukv->cframes / DUCK_GENERAL_FPS;
|
||||||
This->frame_count = dukv->cframes;
|
This->frame_count = dukv->cframes;
|
||||||
This->max_frame_wait =
|
This->interframe_wait = (uint32) (1000.0 / DUCK_GENERAL_FPS);
|
||||||
(uint32) (1000.0f / DUCK_GENERAL_FPS * 1.1);
|
|
||||||
|
|
||||||
dukv->inbuf = HMalloc (DUCK_MAX_FRAME_SIZE);
|
dukv->inbuf = HMalloc (DUCK_MAX_FRAME_SIZE);
|
||||||
dukv->decbuf = HMalloc (
|
dukv->decbuf = HMalloc (
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ StopLegacyVideo (LEGACY_VIDEO_REF ref)
|
|||||||
{
|
{
|
||||||
if (!ref)
|
if (!ref)
|
||||||
return;
|
return;
|
||||||
if (TFB_VideoPlaying (ref->vidref))
|
VidStop ();
|
||||||
VidStop ();
|
|
||||||
|
|
||||||
DestroyVideo (ref->vidref);
|
DestroyVideo (ref->vidref);
|
||||||
if (ref->speechref)
|
if (ref->speechref)
|
||||||
|
|||||||
@@ -74,6 +74,14 @@ VidPlaying (void)
|
|||||||
return NULL_VIDEO_REF;
|
return NULL_VIDEO_REF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
VidProcessFrame (void)
|
||||||
|
{
|
||||||
|
if (!_cur_video)
|
||||||
|
return FALSE;
|
||||||
|
return TFB_ProcessVideoFrame (_cur_video);
|
||||||
|
}
|
||||||
|
|
||||||
// return current video position in milliseconds
|
// return current video position in milliseconds
|
||||||
DWORD
|
DWORD
|
||||||
VidGetPosition (void)
|
VidGetPosition (void)
|
||||||
@@ -173,6 +181,9 @@ DestroyVideo (VIDEO_REF vid)
|
|||||||
if (!vid)
|
if (!vid)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
// just some armouring; should already be stopped
|
||||||
|
TFB_StopVideo (vid);
|
||||||
|
|
||||||
VideoDecoder_Free (vid->decoder);
|
VideoDecoder_Free (vid->decoder);
|
||||||
DestroyMutex (vid->guard);
|
DestroyMutex (vid->guard);
|
||||||
HFree (vid);
|
HFree (vid);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "videodec.h"
|
#include "videodec.h"
|
||||||
#include "libs/sound/sound.h"
|
#include "libs/sound/sound.h"
|
||||||
#include "libs/tasklib.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tfb_videoclip
|
typedef struct tfb_videoclip
|
||||||
@@ -36,11 +35,9 @@ typedef struct tfb_videoclip
|
|||||||
RECT dst_rect; // destination screen rect
|
RECT dst_rect; // destination screen rect
|
||||||
RECT src_rect; // source rect
|
RECT src_rect; // source rect
|
||||||
MUSIC_REF hAudio;
|
MUSIC_REF hAudio;
|
||||||
Task play_task;
|
|
||||||
uint32 frame_time; // time when next frame should be rendered
|
uint32 frame_time; // time when next frame should be rendered
|
||||||
TFB_Image* frame; // frame preped and optimized for rendering
|
TFB_Image* frame; // frame preped and optimized for rendering
|
||||||
uint32 cur_frame; // index of frame currently displayed
|
uint32 cur_frame; // index of frame currently displayed
|
||||||
uint32 max_frame_wait;
|
|
||||||
bool playing;
|
bool playing;
|
||||||
bool own_audio;
|
bool own_audio;
|
||||||
uint32 loop_frame; // frame index to loop from
|
uint32 loop_frame; // frame index to loop from
|
||||||
@@ -48,6 +45,7 @@ typedef struct tfb_videoclip
|
|||||||
|
|
||||||
Mutex guard;
|
Mutex guard;
|
||||||
uint32 want_frame; // audio-signaled desired frame index
|
uint32 want_frame; // audio-signaled desired frame index
|
||||||
|
int lag_cnt; // N of frames video is behind or ahead of audio
|
||||||
|
|
||||||
void* data; // user-defined data
|
void* data; // user-defined data
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ struct tfb_videodecoder
|
|||||||
uint32 w, h;
|
uint32 w, h;
|
||||||
float length; // total length in seconds
|
float length; // total length in seconds
|
||||||
uint32 frame_count;
|
uint32 frame_count;
|
||||||
uint32 max_frame_wait; // maximum interframe delay in msecs
|
uint32 interframe_wait; // nominal interframe delay in msecs
|
||||||
bool audio_synced;
|
bool audio_synced;
|
||||||
// decoder callbacks
|
// decoder callbacks
|
||||||
TFB_VideoCallbacks callbacks;
|
TFB_VideoCallbacks callbacks;
|
||||||
|
|||||||
+113
-144
@@ -55,163 +55,130 @@ static const TFB_SoundCallbacks vp_AudioCBs =
|
|||||||
vp_QueueBuffer
|
vp_QueueBuffer
|
||||||
};
|
};
|
||||||
|
|
||||||
// inter-thread param guarded by mutex
|
|
||||||
static Semaphore vp_interthread_lock = 0;
|
|
||||||
static void* vp_interthread_clip = NULL;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TFB_InitVideoPlayer (void)
|
TFB_InitVideoPlayer (void)
|
||||||
{
|
{
|
||||||
// creation probably needs better handling
|
// now just a stub
|
||||||
vp_interthread_lock = CreateSemaphore (1, "inter-thread param lock",
|
return true;
|
||||||
SYNC_CLASS_VIDEO);
|
|
||||||
return vp_interthread_lock != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TFB_UninitVideoPlayer (void)
|
TFB_UninitVideoPlayer (void)
|
||||||
{
|
{
|
||||||
DestroySemaphore (vp_interthread_lock);
|
// now just a stub
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio-synced video playback task
|
static inline sint32
|
||||||
// the frame rate and timing is dictated by the audio
|
msecToTimeCount (sint32 msec)
|
||||||
static int
|
|
||||||
as_video_play_task (void *data)
|
|
||||||
{
|
{
|
||||||
Task task = (Task) data;
|
return msec * ONE_SECOND / 1000;
|
||||||
volatile TFB_VideoClip* vid;
|
}
|
||||||
|
|
||||||
|
// audio-synced video playback frame function
|
||||||
|
// the frame rate and timing is dictated by the audio
|
||||||
|
static bool
|
||||||
|
processAudioSyncedFrame (VIDEO_REF vid)
|
||||||
|
{
|
||||||
|
#define MAX_FRAME_LAG 8
|
||||||
|
#define LAG_FRACTION 6
|
||||||
|
#define SYNC_BIAS 1 / 3
|
||||||
int ret;
|
int ret;
|
||||||
uint32 want_frame;
|
uint32 want_frame;
|
||||||
TimeCount TimeOut;
|
uint32 prev_want_frame;
|
||||||
int bTerm;
|
sint32 wait_msec;
|
||||||
uint32 clagged;
|
CONTEXT oldContext;
|
||||||
|
TimeCount Now = GetTimeCounter ();
|
||||||
|
|
||||||
// snatch the clip pointer and release
|
if (!vid->playing)
|
||||||
vid = vp_interthread_clip;
|
return false;
|
||||||
vp_interthread_clip = NULL;
|
|
||||||
ClearSemaphore (vp_interthread_lock);
|
if (Now < vid->frame_time)
|
||||||
|
return true; // not time yet
|
||||||
|
|
||||||
LockMutex (vid->guard);
|
LockMutex (vid->guard);
|
||||||
want_frame = vid->want_frame;
|
want_frame = vid->want_frame;
|
||||||
if (vid->hAudio)
|
|
||||||
PLRPlaySong (vid->hAudio, FALSE, 1);
|
|
||||||
UnlockMutex (vid->guard);
|
UnlockMutex (vid->guard);
|
||||||
|
|
||||||
clagged = 0;
|
if (want_frame >= vid->decoder->frame_count)
|
||||||
|
{
|
||||||
|
vid->playing = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// this works like so (audio-synced):
|
// this works like so (audio-synced):
|
||||||
// 1. you call VideoDecoder_Seek() [when necessary] and
|
// 1. you call VideoDecoder_Seek() [when necessary] and
|
||||||
// VideoDecoder_Decode()
|
// VideoDecoder_Decode()
|
||||||
// 2. wait till the audio signals it's time for this frame
|
// 2. wait till it's time for this frame to be drawn
|
||||||
// or the maximum inter-frame timeout elapses; the timeout
|
// the timeout is necessary because the audio signaling is not
|
||||||
// is necessary because the audio signaling is not precise
|
// precise (see vp_AudioStart, vp_AudioEnd, vp_BufferTag)
|
||||||
// (see vp_AudioStart, vp_AudioEnd, vp_BufferTag)
|
// 3. output the frame; if the audio is behind, the lag counter
|
||||||
// 3. output the frame; if the timeout elapsed, increment the
|
// goes up; if the video is behind, the lag counter goes down
|
||||||
// the lag counter
|
// 4. set the next frame timeout; lag counter increases or
|
||||||
// 4. set the next frame timeout; lag counter increases the
|
// decreases the timeout to allow audio or video to catch up
|
||||||
// timeout to allow audio to catch up
|
|
||||||
// 5. on a seek operation, the audio stream is moved to the
|
// 5. on a seek operation, the audio stream is moved to the
|
||||||
// correct position and then the audio signals the frame
|
// correct position and then the audio signals the frame
|
||||||
// that should be rendered
|
// that should be rendered
|
||||||
// The system of timeouts and lag counts should make the video
|
// The system of timeouts and lag counts should make the video
|
||||||
// *relatively* smooth
|
// *relatively* smooth
|
||||||
//
|
//
|
||||||
ret = VideoDecoder_Decode (vid->decoder);
|
prev_want_frame = vid->cur_frame - vid->lag_cnt;
|
||||||
TimeOut = GetTimeCounter () + vid->decoder->max_frame_wait *
|
if (want_frame > prev_want_frame - MAX_FRAME_LAG
|
||||||
ONE_SECOND / 1000;
|
&& want_frame <= prev_want_frame + MAX_FRAME_LAG)
|
||||||
|
|
||||||
while (!(bTerm = Task_ReadState (task, TASK_EXIT)) && ret > 0)
|
|
||||||
{
|
{
|
||||||
// wait till its time to render next frame
|
// we will draw the next frame right now, thus +1
|
||||||
while (!(bTerm = Task_ReadState (task, TASK_EXIT))
|
vid->lag_cnt = vid->cur_frame + 1 - want_frame;
|
||||||
&& want_frame == vid->cur_frame - clagged
|
|
||||||
&& TimeOut > GetTimeCounter ())
|
|
||||||
{
|
|
||||||
TaskSwitch ();
|
|
||||||
LockMutex (vid->guard);
|
|
||||||
want_frame = vid->want_frame;
|
|
||||||
UnlockMutex (vid->guard);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bTerm)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (want_frame == vid->cur_frame - clagged)
|
|
||||||
{ // timed out - draw the next frame
|
|
||||||
++clagged;
|
|
||||||
}
|
|
||||||
else if (want_frame > vid->cur_frame - clagged
|
|
||||||
&& want_frame <= vid->cur_frame)
|
|
||||||
{
|
|
||||||
// catching up
|
|
||||||
clagged = vid->cur_frame - want_frame;
|
|
||||||
// try again
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (want_frame != vid->cur_frame + 1)
|
|
||||||
{ // out of sequence frame, let's get it
|
|
||||||
vid->cur_frame = VideoDecoder_SeekFrame (
|
|
||||||
vid->decoder, want_frame);
|
|
||||||
ret = VideoDecoder_Decode (vid->decoder);
|
|
||||||
clagged = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clagged = 0;
|
|
||||||
}
|
|
||||||
vid->cur_frame = vid->decoder->cur_frame;
|
|
||||||
|
|
||||||
// draw the frame
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
CONTEXT oldContext;
|
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
|
||||||
// We have the cliprect precalculated and don't need the rest
|
|
||||||
oldContext = SetContext (NULL);
|
|
||||||
TFB_DrawScreen_Image (vid->frame,
|
|
||||||
vid->dst_rect.corner.x, vid->dst_rect.corner.y,
|
|
||||||
GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN);
|
|
||||||
SetContext (oldContext);
|
|
||||||
UnlockMutex (GraphicsLock);
|
|
||||||
FlushGraphics (); // needed to prevent half-frame updates
|
|
||||||
}
|
|
||||||
|
|
||||||
// increase timeout with lag-count to allow audio to catch up
|
|
||||||
TimeOut = GetTimeCounter () + vid->decoder->max_frame_wait *
|
|
||||||
ONE_SECOND / 1000 + clagged * ONE_SECOND / 100;
|
|
||||||
|
|
||||||
ret = VideoDecoder_Decode (vid->decoder);
|
|
||||||
}
|
}
|
||||||
if (vid->hAudio)
|
else
|
||||||
PLRStop (vid->hAudio);
|
{ // out of sequence frame, let's get it
|
||||||
vid->playing = false;
|
vid->lag_cnt = 0;
|
||||||
|
vid->cur_frame = VideoDecoder_SeekFrame (vid->decoder, want_frame);
|
||||||
|
ret = VideoDecoder_Decode (vid->decoder);
|
||||||
|
if (ret < 0)
|
||||||
|
{ // decoder returned a failure
|
||||||
|
vid->playing = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vid->cur_frame = vid->decoder->cur_frame;
|
||||||
|
|
||||||
FinishTask (task);
|
// draw the frame
|
||||||
|
LockMutex (GraphicsLock);
|
||||||
|
// We have the cliprect precalculated and don't need the rest
|
||||||
|
oldContext = SetContext (NULL);
|
||||||
|
TFB_DrawScreen_Image (vid->frame,
|
||||||
|
vid->dst_rect.corner.x, vid->dst_rect.corner.y,
|
||||||
|
GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN);
|
||||||
|
SetContext (oldContext);
|
||||||
|
UnlockMutex (GraphicsLock);
|
||||||
|
FlushGraphics (); // needed to prevent half-frame updates
|
||||||
|
|
||||||
return 0;
|
// increase interframe with positive lag-count to allow audio to catch up
|
||||||
|
// decrease interframe with negative lag-count to allow video to catch up
|
||||||
|
wait_msec = vid->decoder->interframe_wait
|
||||||
|
- (int)vid->decoder->interframe_wait * SYNC_BIAS
|
||||||
|
+ (int)vid->decoder->interframe_wait * vid->lag_cnt / LAG_FRACTION;
|
||||||
|
vid->frame_time = Now + msecToTimeCount (wait_msec);
|
||||||
|
|
||||||
|
ret = VideoDecoder_Decode (vid->decoder);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
// TODO: decide what to do on error
|
||||||
|
}
|
||||||
|
|
||||||
|
return vid->playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio-independent video playback task
|
// audio-independent video playback frame function
|
||||||
// the frame rate and timing is dictated by the video decoder
|
// the frame rate and timing is dictated by the video decoder
|
||||||
static int
|
static bool
|
||||||
video_play_task (void *data)
|
processMuteFrame (VIDEO_REF vid)
|
||||||
{
|
{
|
||||||
Task task = (Task) data;
|
|
||||||
TFB_VideoClip* vid;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
TimeCount Now = GetTimeCounter ();
|
||||||
|
|
||||||
// snatch the clip pointer and release
|
if (!vid->playing)
|
||||||
vid = vp_interthread_clip;
|
return false;
|
||||||
vp_interthread_clip = NULL;
|
|
||||||
ClearSemaphore (vp_interthread_lock);
|
|
||||||
|
|
||||||
LockMutex (vid->guard);
|
|
||||||
if (vid->hAudio)
|
|
||||||
PLRPlaySong (vid->hAudio, (vid->loop_frame != VID_NO_LOOP), 1);
|
|
||||||
|
|
||||||
UnlockMutex (vid->guard);
|
|
||||||
|
|
||||||
// this works like so:
|
// this works like so:
|
||||||
// 1. you call VideoDecoder_Seek() [when necessary] and
|
// 1. you call VideoDecoder_Seek() [when necessary] and
|
||||||
@@ -222,14 +189,10 @@ video_play_task (void *data)
|
|||||||
// On a seek operation, the decoder should reset its internal
|
// On a seek operation, the decoder should reset its internal
|
||||||
// clock and call vp_GetTicks() again
|
// clock and call vp_GetTicks() again
|
||||||
//
|
//
|
||||||
ret = VideoDecoder_Decode (vid->decoder);
|
if (Now >= vid->frame_time)
|
||||||
|
|
||||||
while (!Task_ReadState (task, TASK_EXIT) && ret > 0)
|
|
||||||
{
|
{
|
||||||
CONTEXT oldContext;
|
CONTEXT oldContext;
|
||||||
|
|
||||||
// wait till its time to render next frame
|
|
||||||
SleepThreadUntil (vid->frame_time);
|
|
||||||
vid->cur_frame = vid->decoder->cur_frame;
|
vid->cur_frame = vid->decoder->cur_frame;
|
||||||
|
|
||||||
LockMutex (GraphicsLock);
|
LockMutex (GraphicsLock);
|
||||||
@@ -246,14 +209,11 @@ video_play_task (void *data)
|
|||||||
VideoDecoder_SeekFrame (vid->decoder, vid->loop_to);
|
VideoDecoder_SeekFrame (vid->decoder, vid->loop_to);
|
||||||
|
|
||||||
ret = VideoDecoder_Decode (vid->decoder);
|
ret = VideoDecoder_Decode (vid->decoder);
|
||||||
|
if (ret <= 0)
|
||||||
|
vid->playing = false;
|
||||||
}
|
}
|
||||||
vid->playing = false;
|
|
||||||
if (vid->hAudio)
|
|
||||||
PLRStop (vid->hAudio);
|
|
||||||
|
|
||||||
FinishTask (task);
|
return vid->playing;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -264,6 +224,8 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y)
|
|||||||
RECT vid_r = {{0, 0}, {ScreenWidth, ScreenHeight}};
|
RECT vid_r = {{0, 0}, {ScreenWidth, ScreenHeight}};
|
||||||
RECT dr = {{x, y}, {vid->w, vid->h}};
|
RECT dr = {{x, y}, {vid->w, vid->h}};
|
||||||
RECT sr;
|
RECT sr;
|
||||||
|
bool loop_music = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!vid)
|
if (!vid)
|
||||||
return false;
|
return false;
|
||||||
@@ -318,24 +280,21 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y)
|
|||||||
TFB_SetSoundSampleData (*vid->hAudio, (intptr_t)vid);
|
TFB_SetSoundSampleData (*vid->hAudio, (intptr_t)vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetSemaphore (vp_interthread_lock);
|
// get the first frame
|
||||||
vp_interthread_clip = vid;
|
ret = VideoDecoder_Decode (vid->decoder);
|
||||||
|
if (ret < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
vid->playing = true;
|
vid->playing = true;
|
||||||
|
|
||||||
|
loop_music = !vid->decoder->audio_synced && vid->loop_frame != VID_NO_LOOP;
|
||||||
|
if (vid->hAudio)
|
||||||
|
PLRPlaySong (vid->hAudio, loop_music, 1);
|
||||||
|
|
||||||
if (vid->decoder->audio_synced)
|
if (vid->decoder->audio_synced)
|
||||||
vid->play_task = AssignTask (
|
|
||||||
as_video_play_task, 4096, "a/s video player");
|
|
||||||
else
|
|
||||||
vid->play_task = AssignTask (
|
|
||||||
video_play_task, 4096, "video player");
|
|
||||||
|
|
||||||
if (!vid->play_task)
|
|
||||||
{
|
{
|
||||||
vid->playing = false;
|
// draw the first frame now
|
||||||
ClearSemaphore (vp_interthread_lock);
|
vid->frame_time = GetTimeCounter ();
|
||||||
TFB_StopVideo (vid);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -348,8 +307,6 @@ TFB_StopVideo (VIDEO_REF vid)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
vid->playing = false;
|
vid->playing = false;
|
||||||
if (vid->play_task)
|
|
||||||
ConcludeTask (vid->play_task);
|
|
||||||
|
|
||||||
if (vid->hAudio)
|
if (vid->hAudio)
|
||||||
{
|
{
|
||||||
@@ -377,6 +334,18 @@ TFB_VideoPlaying (VIDEO_REF vid)
|
|||||||
return vid->playing;
|
return vid->playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TFB_ProcessVideoFrame (VIDEO_REF vid)
|
||||||
|
{
|
||||||
|
if (!vid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vid->decoder->audio_synced)
|
||||||
|
return processAudioSyncedFrame (vid);
|
||||||
|
else
|
||||||
|
return processMuteFrame (vid);
|
||||||
|
}
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
TFB_GetVideoPosition (VIDEO_REF vid)
|
TFB_GetVideoPosition (VIDEO_REF vid)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ extern void TFB_UninitVideoPlayer (void);
|
|||||||
extern bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y);
|
extern bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y);
|
||||||
extern void TFB_StopVideo (VIDEO_REF VidRef);
|
extern void TFB_StopVideo (VIDEO_REF VidRef);
|
||||||
extern bool TFB_VideoPlaying (VIDEO_REF VidRef);
|
extern bool TFB_VideoPlaying (VIDEO_REF VidRef);
|
||||||
|
extern bool TFB_ProcessVideoFrame (VIDEO_REF vid);
|
||||||
extern uint32 TFB_GetVideoPosition (VIDEO_REF VidRef);
|
extern uint32 TFB_GetVideoPosition (VIDEO_REF VidRef);
|
||||||
extern bool TFB_SeekVideo (VIDEO_REF VidRef, uint32 pos);
|
extern bool TFB_SeekVideo (VIDEO_REF VidRef, uint32 pos);
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ extern VIDEO_TYPE VidPlayEx (VIDEO_REF VidRef, MUSIC_REF AudRef,
|
|||||||
#define VID_NO_LOOP (0U-1)
|
#define VID_NO_LOOP (0U-1)
|
||||||
extern void VidStop (void);
|
extern void VidStop (void);
|
||||||
extern VIDEO_REF VidPlaying (void);
|
extern VIDEO_REF VidPlaying (void);
|
||||||
|
extern BOOLEAN VidProcessFrame (void);
|
||||||
extern DWORD VidGetPosition (void); // position in milliseconds
|
extern DWORD VidGetPosition (void); // position in milliseconds
|
||||||
extern BOOLEAN VidSeek (DWORD pos); // position in milliseconds
|
extern BOOLEAN VidSeek (DWORD pos); // position in milliseconds
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -822,8 +822,6 @@ DoVideoInput (void *pIS)
|
|||||||
|
|
||||||
if (!PlayingLegacyVideo (pVIS->CurVideo))
|
if (!PlayingLegacyVideo (pVIS->CurVideo))
|
||||||
{ // Video probably finished
|
{ // Video probably finished
|
||||||
// Have to call VidStop anyway to cleanup
|
|
||||||
VidStop ();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,7 +830,6 @@ DoVideoInput (void *pIS)
|
|||||||
|| PulsedInputState.menu[KEY_MENU_SPECIAL]
|
|| PulsedInputState.menu[KEY_MENU_SPECIAL]
|
||||||
|| (GLOBAL (CurrentActivity) & CHECK_ABORT))
|
|| (GLOBAL (CurrentActivity) & CHECK_ABORT))
|
||||||
{ // abort movie
|
{ // abort movie
|
||||||
VidStop ();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (PulsedInputState.menu[KEY_MENU_LEFT]
|
else if (PulsedInputState.menu[KEY_MENU_LEFT]
|
||||||
@@ -850,7 +847,10 @@ DoVideoInput (void *pIS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SleepThread (ONE_SECOND / 30);
|
if (!VidProcessFrame ())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
SleepThread (ONE_SECOND / 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|||||||
Reference in New Issue
Block a user