* Whether an audio and/or video node is used is now more explicit. The audio
node can now also be turned off for videos that don't have audio. * The PlaybackManager currently has the "no audio" support added in a not quite so nice way, will have to think about something, this is just quick and dirty to get it going. There is just two places where the audio time needs to be ignored, because it remains at zero. -> Especially when using OSS, the seeking latency will be much reduced when playing videos that have no sound. * The Controller now maintains the frame it wanted to seek to and does not forward "position changed" to other listeners as long as the seek frame has not been reached. This fixes the slider jumping back to the old position for a bit until jumping back to the seek frame. It also fixes another problem when switching to the next file. Because the total duration is already adopted while the old clip is still playing within the seek latency, the current position jumped to the new relative position, while it is still refering to the position within the old clip. So both seeking and switching clips looks much smoother now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -100,6 +100,7 @@ Controller::Controller()
|
||||
, fPosition(0)
|
||||
, fDuration(0)
|
||||
, fVideoFrameRate(25.0)
|
||||
, fSeekFrame(-1)
|
||||
|
||||
, fAutoplay(true)
|
||||
, fPauseAtEndOfStream(false)
|
||||
@@ -164,7 +165,7 @@ Controller::SetTo(const entry_ref &ref)
|
||||
|
||||
if (fRef == ref) {
|
||||
if (InitCheck() == B_OK) {
|
||||
SetCurrentFrame(0);
|
||||
SetPosition(0.0);
|
||||
StartPlaying();
|
||||
}
|
||||
return B_OK;
|
||||
@@ -269,17 +270,25 @@ Controller::SetTo(const entry_ref &ref)
|
||||
preferredVideoFormat = format.u.raw_video.display.format;
|
||||
}
|
||||
|
||||
uint32 enabledNodes;
|
||||
if (!fVideoTrackSupplier)
|
||||
enabledNodes = AUDIO_ONLY;
|
||||
else if (!fAudioTrackSupplier)
|
||||
enabledNodes = VIDEO_ONLY;
|
||||
else
|
||||
enabledNodes = AUDIO_AND_VIDEO;
|
||||
|
||||
if (InitCheck() != B_OK) {
|
||||
Init(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
|
||||
preferredVideoFormat, LOOPING_ALL, false);
|
||||
preferredVideoFormat, LOOPING_ALL, false, 1.0, enabledNodes);
|
||||
} else {
|
||||
FormatChanged(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
|
||||
preferredVideoFormat);
|
||||
preferredVideoFormat, enabledNodes);
|
||||
}
|
||||
|
||||
_NotifyFileChanged();
|
||||
|
||||
SetCurrentFrame(0);
|
||||
SetPosition(0.0);
|
||||
if (fAutoplay)
|
||||
StartPlaying(true);
|
||||
|
||||
@@ -420,7 +429,7 @@ Controller::Stop()
|
||||
BAutolock _(this);
|
||||
|
||||
StopPlaying();
|
||||
SetCurrentFrame(0);
|
||||
SetPosition(0.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -559,8 +568,14 @@ Controller::SetPosition(float value)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
SetCurrentFrame(Duration() * value);
|
||||
fSeekFrame = (int32)(Duration() * value);
|
||||
int32 currentFrame = CurrentFrame();
|
||||
if (fSeekFrame != currentFrame)
|
||||
SetCurrentFrame(fSeekFrame);
|
||||
else
|
||||
fSeekFrame = -1;
|
||||
|
||||
// TODO: What was this used for in the old framework?
|
||||
fSeekToStartAfterPause = false;
|
||||
}
|
||||
|
||||
@@ -891,6 +906,12 @@ Controller::NotifyFPSChanged(float fps) const
|
||||
void
|
||||
Controller::NotifyCurrentFrameChanged(int32 frame) const
|
||||
{
|
||||
// check if we are still waiting to reach the seekframe,
|
||||
// don't pass the event on to the listeners in that case
|
||||
if (fSeekFrame >= 0 && frame != fSeekFrame)
|
||||
return;
|
||||
fSeekFrame = -1;
|
||||
|
||||
float position = 0.0;
|
||||
double duration = (double)fDuration * fVideoFrameRate / 1000000.0;
|
||||
if (duration > 0)
|
||||
|
||||
@@ -174,6 +174,7 @@ private:
|
||||
mutable bigtime_t fPosition;
|
||||
bigtime_t fDuration;
|
||||
float fVideoFrameRate;
|
||||
mutable int32 fSeekFrame;
|
||||
|
||||
bool fAutoplay;
|
||||
volatile bool fPauseAtEndOfStream;
|
||||
|
||||
@@ -67,7 +67,7 @@ NodeManager::~NodeManager()
|
||||
status_t
|
||||
NodeManager::Init(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat, int32 loopingMode,
|
||||
bool loopingEnabled, float speed)
|
||||
bool loopingEnabled, float speed, uint32 enabledNodes)
|
||||
{
|
||||
// init base class
|
||||
PlaybackManager::Init(videoFrameRate, loopingMode, loopingEnabled, speed);
|
||||
@@ -83,7 +83,7 @@ NodeManager::Init(BRect videoBounds, float videoFrameRate,
|
||||
fAudioSupplier = CreateAudioSupplier();
|
||||
|
||||
return FormatChanged(videoBounds, videoFrameRate, preferredVideoFormat,
|
||||
true);
|
||||
enabledNodes, true);
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
@@ -118,13 +118,16 @@ NodeManager::CleanupNodes()
|
||||
// FormatChanged
|
||||
status_t
|
||||
NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat, bool force)
|
||||
color_space preferredVideoFormat, uint32 enabledNodes, bool force)
|
||||
{
|
||||
TRACE("NodeManager::FormatChanged()\n");
|
||||
|
||||
if (!force && videoBounds == VideoBounds()
|
||||
&& videoFrameRate == FramesPerSecond()) {
|
||||
TRACE(" -> reusing existing nodes\n");
|
||||
// TODO: if enabledNodes would indicate that audio or video
|
||||
// is no longer needed, or, worse yet, suddenly needed when
|
||||
// it wasn't before, then we should not return here!
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -139,7 +142,7 @@ NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
|
||||
|
||||
SetVideoBounds(videoBounds);
|
||||
|
||||
status_t ret = _SetUpNodes(preferredVideoFormat);
|
||||
status_t ret = _SetUpNodes(preferredVideoFormat, enabledNodes);
|
||||
if (ret == B_OK)
|
||||
_StartNodes();
|
||||
else
|
||||
@@ -247,7 +250,7 @@ NodeManager::SetPeakListener(BHandler* handler)
|
||||
|
||||
// _SetUpNodes
|
||||
status_t
|
||||
NodeManager::_SetUpNodes(color_space preferredVideoFormat)
|
||||
NodeManager::_SetUpNodes(color_space preferredVideoFormat, uint32 enabledNodes)
|
||||
{
|
||||
TRACE("NodeManager::_SetUpNodes()\n");
|
||||
|
||||
@@ -271,7 +274,7 @@ NodeManager::_SetUpNodes(color_space preferredVideoFormat)
|
||||
}
|
||||
|
||||
// setup the video nodes
|
||||
if (fVideoBounds.IsValid()) {
|
||||
if (enabledNodes != AUDIO_ONLY) {
|
||||
fStatus = _SetUpVideoNodes(preferredVideoFormat);
|
||||
if (fStatus != B_OK) {
|
||||
print_error("Error setting up video nodes", fStatus);
|
||||
@@ -282,11 +285,17 @@ NodeManager::_SetUpNodes(color_space preferredVideoFormat)
|
||||
printf("running without video node\n");
|
||||
|
||||
// setup the audio nodes
|
||||
fStatus = _SetUpAudioNodes();
|
||||
if (fStatus != B_OK) {
|
||||
print_error("Error setting up audio nodes", fStatus);
|
||||
fMediaRoster->Unlock();
|
||||
return fStatus;
|
||||
if (enabledNodes != VIDEO_ONLY) {
|
||||
fStatus = _SetUpAudioNodes();
|
||||
if (fStatus != B_OK) {
|
||||
print_error("Error setting up audio nodes", fStatus);
|
||||
fMediaRoster->Unlock();
|
||||
return fStatus;
|
||||
}
|
||||
fNoAudio = false;
|
||||
} else {
|
||||
fNoAudio = true;
|
||||
printf("running without audio node\n");
|
||||
}
|
||||
|
||||
// we're done mocking with the media roster
|
||||
@@ -589,7 +598,7 @@ status_t
|
||||
NodeManager::_StartNodes()
|
||||
{
|
||||
status_t status = B_NO_INIT;
|
||||
if (!fMediaRoster || !fAudioProducer)
|
||||
if (!fMediaRoster)
|
||||
return status;
|
||||
// begin mucking with the media roster
|
||||
if (!fMediaRoster->Lock())
|
||||
@@ -623,10 +632,13 @@ NodeManager::_StartNodes()
|
||||
}
|
||||
initLatency += estimate_max_scheduling_latency();
|
||||
|
||||
bigtime_t audioLatency = 0;
|
||||
status = fMediaRoster->GetLatencyFor(fAudioConnection.producer,
|
||||
&audioLatency);
|
||||
TRACE("audio latency: %Ld\n", audioLatency);
|
||||
if (fAudioProducer) {
|
||||
// TODO: was this supposed to be added to initLatency?!?
|
||||
bigtime_t audioLatency = 0;
|
||||
status = fMediaRoster->GetLatencyFor(fAudioConnection.producer,
|
||||
&audioLatency);
|
||||
TRACE("audio latency: %Ld\n", audioLatency);
|
||||
}
|
||||
|
||||
BTimeSource* timeSource;
|
||||
if (fVideoProducer) {
|
||||
@@ -677,11 +689,13 @@ printf("performance time for %lld: %lld\n", real + latency
|
||||
}
|
||||
}
|
||||
|
||||
fAudioProducer->SetRunning(true);
|
||||
status = fMediaRoster->StartNode(fAudioConnection.producer, perf);
|
||||
if (status != B_OK) {
|
||||
print_error("Can't start the audio producer", status);
|
||||
return status;
|
||||
if (fAudioProducer) {
|
||||
fAudioProducer->SetRunning(true);
|
||||
status = fMediaRoster->StartNode(fAudioConnection.producer, perf);
|
||||
if (status != B_OK) {
|
||||
print_error("Can't start the audio producer", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
fPerformanceTimeBase = perf;
|
||||
|
||||
@@ -32,11 +32,18 @@ class NodeManager : public PlaybackManager {
|
||||
virtual AudioSupplier* CreateAudioSupplier() = 0;
|
||||
|
||||
// NodeManager
|
||||
enum {
|
||||
AUDIO_AND_VIDEO = 0,
|
||||
VIDEO_ONLY,
|
||||
AUDIO_ONLY
|
||||
};
|
||||
|
||||
status_t Init(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat,
|
||||
int32 loopingMode = LOOPING_ALL,
|
||||
bool loopingEnabled = true,
|
||||
float speed = 1.0);
|
||||
float speed = 1.0,
|
||||
uint32 enabledNodes = AUDIO_AND_VIDEO);
|
||||
status_t InitCheck();
|
||||
// only call this if the
|
||||
// media_server has died!
|
||||
@@ -45,6 +52,7 @@ class NodeManager : public PlaybackManager {
|
||||
status_t FormatChanged(BRect videoBounds,
|
||||
float videoFrameRate,
|
||||
color_space preferredVideoFormat,
|
||||
uint32 enabledNodes = AUDIO_AND_VIDEO,
|
||||
bool force = false);
|
||||
virtual void SetPlayMode(int32 mode,
|
||||
bool continuePlaying = true);
|
||||
@@ -65,7 +73,8 @@ class NodeManager : public PlaybackManager {
|
||||
void SetPeakListener(BHandler* handler);
|
||||
|
||||
private:
|
||||
status_t _SetUpNodes(color_space preferredVideoFormat);
|
||||
status_t _SetUpNodes(color_space preferredVideoFormat,
|
||||
uint32 enabledNodes);
|
||||
status_t _SetUpVideoNodes(
|
||||
color_space preferredVideoFormat);
|
||||
status_t _SetUpAudioNodes();
|
||||
|
||||
@@ -67,7 +67,8 @@ PlaybackManager::PlaybackManager()
|
||||
fPerformanceTime(0),
|
||||
fFrameRate(1.0),
|
||||
fStopPlayingFrame(-1),
|
||||
fListeners()
|
||||
fListeners(),
|
||||
fNoAudio(false)
|
||||
{
|
||||
Run();
|
||||
}
|
||||
@@ -452,8 +453,11 @@ PlaybackManager::SetSpeed(float speed)
|
||||
int64
|
||||
PlaybackManager::NextFrame() const
|
||||
{
|
||||
if (fNoAudio)
|
||||
return FrameForTime(fCurrentVideoTime - 1) + 1;
|
||||
|
||||
return FrameForTime(max((bigtime_t)fCurrentAudioTime,
|
||||
(bigtime_t)fCurrentVideoTime) - 1) + 1;
|
||||
(bigtime_t)fCurrentVideoTime) - 1) + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1549,6 +1553,9 @@ PlaybackManager::_UpdateSpeedInfos()
|
||||
bigtime_t
|
||||
PlaybackManager::_TimeForLastFrame() const
|
||||
{
|
||||
if (fNoAudio)
|
||||
return TimeForFrame(FrameForTime(fCurrentVideoTime));
|
||||
|
||||
return TimeForFrame(FrameForTime(min((bigtime_t)fCurrentAudioTime,
|
||||
(bigtime_t)fCurrentVideoTime)));
|
||||
}
|
||||
|
||||
@@ -228,6 +228,8 @@ public:
|
||||
// disabled: -1
|
||||
|
||||
BList fListeners;
|
||||
protected:
|
||||
bool fNoAudio;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user