* 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:
Stephan Aßmus
2008-07-14 21:58:07 +00:00
parent 67ca609fdc
commit eb91d0058d
6 changed files with 85 additions and 31 deletions
+27 -6
View File
@@ -100,6 +100,7 @@ Controller::Controller()
, fPosition(0) , fPosition(0)
, fDuration(0) , fDuration(0)
, fVideoFrameRate(25.0) , fVideoFrameRate(25.0)
, fSeekFrame(-1)
, fAutoplay(true) , fAutoplay(true)
, fPauseAtEndOfStream(false) , fPauseAtEndOfStream(false)
@@ -164,7 +165,7 @@ Controller::SetTo(const entry_ref &ref)
if (fRef == ref) { if (fRef == ref) {
if (InitCheck() == B_OK) { if (InitCheck() == B_OK) {
SetCurrentFrame(0); SetPosition(0.0);
StartPlaying(); StartPlaying();
} }
return B_OK; return B_OK;
@@ -269,17 +270,25 @@ Controller::SetTo(const entry_ref &ref)
preferredVideoFormat = format.u.raw_video.display.format; 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) { if (InitCheck() != B_OK) {
Init(BRect(0, 0, width - 1, height - 1), fVideoFrameRate, Init(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
preferredVideoFormat, LOOPING_ALL, false); preferredVideoFormat, LOOPING_ALL, false, 1.0, enabledNodes);
} else { } else {
FormatChanged(BRect(0, 0, width - 1, height - 1), fVideoFrameRate, FormatChanged(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
preferredVideoFormat); preferredVideoFormat, enabledNodes);
} }
_NotifyFileChanged(); _NotifyFileChanged();
SetCurrentFrame(0); SetPosition(0.0);
if (fAutoplay) if (fAutoplay)
StartPlaying(true); StartPlaying(true);
@@ -420,7 +429,7 @@ Controller::Stop()
BAutolock _(this); BAutolock _(this);
StopPlaying(); StopPlaying();
SetCurrentFrame(0); SetPosition(0.0);
} }
@@ -559,8 +568,14 @@ Controller::SetPosition(float value)
{ {
BAutolock _(this); 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; fSeekToStartAfterPause = false;
} }
@@ -891,6 +906,12 @@ Controller::NotifyFPSChanged(float fps) const
void void
Controller::NotifyCurrentFrameChanged(int32 frame) const 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; float position = 0.0;
double duration = (double)fDuration * fVideoFrameRate / 1000000.0; double duration = (double)fDuration * fVideoFrameRate / 1000000.0;
if (duration > 0) if (duration > 0)
+1
View File
@@ -174,6 +174,7 @@ private:
mutable bigtime_t fPosition; mutable bigtime_t fPosition;
bigtime_t fDuration; bigtime_t fDuration;
float fVideoFrameRate; float fVideoFrameRate;
mutable int32 fSeekFrame;
bool fAutoplay; bool fAutoplay;
volatile bool fPauseAtEndOfStream; volatile bool fPauseAtEndOfStream;
@@ -67,7 +67,7 @@ NodeManager::~NodeManager()
status_t status_t
NodeManager::Init(BRect videoBounds, float videoFrameRate, NodeManager::Init(BRect videoBounds, float videoFrameRate,
color_space preferredVideoFormat, int32 loopingMode, color_space preferredVideoFormat, int32 loopingMode,
bool loopingEnabled, float speed) bool loopingEnabled, float speed, uint32 enabledNodes)
{ {
// init base class // init base class
PlaybackManager::Init(videoFrameRate, loopingMode, loopingEnabled, speed); PlaybackManager::Init(videoFrameRate, loopingMode, loopingEnabled, speed);
@@ -83,7 +83,7 @@ NodeManager::Init(BRect videoBounds, float videoFrameRate,
fAudioSupplier = CreateAudioSupplier(); fAudioSupplier = CreateAudioSupplier();
return FormatChanged(videoBounds, videoFrameRate, preferredVideoFormat, return FormatChanged(videoBounds, videoFrameRate, preferredVideoFormat,
true); enabledNodes, true);
} }
// InitCheck // InitCheck
@@ -118,13 +118,16 @@ NodeManager::CleanupNodes()
// FormatChanged // FormatChanged
status_t status_t
NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate, NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
color_space preferredVideoFormat, bool force) color_space preferredVideoFormat, uint32 enabledNodes, bool force)
{ {
TRACE("NodeManager::FormatChanged()\n"); TRACE("NodeManager::FormatChanged()\n");
if (!force && videoBounds == VideoBounds() if (!force && videoBounds == VideoBounds()
&& videoFrameRate == FramesPerSecond()) { && videoFrameRate == FramesPerSecond()) {
TRACE(" -> reusing existing nodes\n"); 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; return B_OK;
} }
@@ -139,7 +142,7 @@ NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
SetVideoBounds(videoBounds); SetVideoBounds(videoBounds);
status_t ret = _SetUpNodes(preferredVideoFormat); status_t ret = _SetUpNodes(preferredVideoFormat, enabledNodes);
if (ret == B_OK) if (ret == B_OK)
_StartNodes(); _StartNodes();
else else
@@ -247,7 +250,7 @@ NodeManager::SetPeakListener(BHandler* handler)
// _SetUpNodes // _SetUpNodes
status_t status_t
NodeManager::_SetUpNodes(color_space preferredVideoFormat) NodeManager::_SetUpNodes(color_space preferredVideoFormat, uint32 enabledNodes)
{ {
TRACE("NodeManager::_SetUpNodes()\n"); TRACE("NodeManager::_SetUpNodes()\n");
@@ -271,7 +274,7 @@ NodeManager::_SetUpNodes(color_space preferredVideoFormat)
} }
// setup the video nodes // setup the video nodes
if (fVideoBounds.IsValid()) { if (enabledNodes != AUDIO_ONLY) {
fStatus = _SetUpVideoNodes(preferredVideoFormat); fStatus = _SetUpVideoNodes(preferredVideoFormat);
if (fStatus != B_OK) { if (fStatus != B_OK) {
print_error("Error setting up video nodes", fStatus); print_error("Error setting up video nodes", fStatus);
@@ -282,11 +285,17 @@ NodeManager::_SetUpNodes(color_space preferredVideoFormat)
printf("running without video node\n"); printf("running without video node\n");
// setup the audio nodes // setup the audio nodes
fStatus = _SetUpAudioNodes(); if (enabledNodes != VIDEO_ONLY) {
if (fStatus != B_OK) { fStatus = _SetUpAudioNodes();
print_error("Error setting up audio nodes", fStatus); if (fStatus != B_OK) {
fMediaRoster->Unlock(); print_error("Error setting up audio nodes", fStatus);
return fStatus; fMediaRoster->Unlock();
return fStatus;
}
fNoAudio = false;
} else {
fNoAudio = true;
printf("running without audio node\n");
} }
// we're done mocking with the media roster // we're done mocking with the media roster
@@ -589,7 +598,7 @@ status_t
NodeManager::_StartNodes() NodeManager::_StartNodes()
{ {
status_t status = B_NO_INIT; status_t status = B_NO_INIT;
if (!fMediaRoster || !fAudioProducer) if (!fMediaRoster)
return status; return status;
// begin mucking with the media roster // begin mucking with the media roster
if (!fMediaRoster->Lock()) if (!fMediaRoster->Lock())
@@ -623,10 +632,13 @@ NodeManager::_StartNodes()
} }
initLatency += estimate_max_scheduling_latency(); initLatency += estimate_max_scheduling_latency();
bigtime_t audioLatency = 0; if (fAudioProducer) {
status = fMediaRoster->GetLatencyFor(fAudioConnection.producer, // TODO: was this supposed to be added to initLatency?!?
&audioLatency); bigtime_t audioLatency = 0;
TRACE("audio latency: %Ld\n", audioLatency); status = fMediaRoster->GetLatencyFor(fAudioConnection.producer,
&audioLatency);
TRACE("audio latency: %Ld\n", audioLatency);
}
BTimeSource* timeSource; BTimeSource* timeSource;
if (fVideoProducer) { if (fVideoProducer) {
@@ -677,11 +689,13 @@ printf("performance time for %lld: %lld\n", real + latency
} }
} }
fAudioProducer->SetRunning(true); if (fAudioProducer) {
status = fMediaRoster->StartNode(fAudioConnection.producer, perf); fAudioProducer->SetRunning(true);
if (status != B_OK) { status = fMediaRoster->StartNode(fAudioConnection.producer, perf);
print_error("Can't start the audio producer", status); if (status != B_OK) {
return status; print_error("Can't start the audio producer", status);
return status;
}
} }
fPerformanceTimeBase = perf; fPerformanceTimeBase = perf;
@@ -32,11 +32,18 @@ class NodeManager : public PlaybackManager {
virtual AudioSupplier* CreateAudioSupplier() = 0; virtual AudioSupplier* CreateAudioSupplier() = 0;
// NodeManager // NodeManager
enum {
AUDIO_AND_VIDEO = 0,
VIDEO_ONLY,
AUDIO_ONLY
};
status_t Init(BRect videoBounds, float videoFrameRate, status_t Init(BRect videoBounds, float videoFrameRate,
color_space preferredVideoFormat, color_space preferredVideoFormat,
int32 loopingMode = LOOPING_ALL, int32 loopingMode = LOOPING_ALL,
bool loopingEnabled = true, bool loopingEnabled = true,
float speed = 1.0); float speed = 1.0,
uint32 enabledNodes = AUDIO_AND_VIDEO);
status_t InitCheck(); status_t InitCheck();
// only call this if the // only call this if the
// media_server has died! // media_server has died!
@@ -45,6 +52,7 @@ class NodeManager : public PlaybackManager {
status_t FormatChanged(BRect videoBounds, status_t FormatChanged(BRect videoBounds,
float videoFrameRate, float videoFrameRate,
color_space preferredVideoFormat, color_space preferredVideoFormat,
uint32 enabledNodes = AUDIO_AND_VIDEO,
bool force = false); bool force = false);
virtual void SetPlayMode(int32 mode, virtual void SetPlayMode(int32 mode,
bool continuePlaying = true); bool continuePlaying = true);
@@ -65,7 +73,8 @@ class NodeManager : public PlaybackManager {
void SetPeakListener(BHandler* handler); void SetPeakListener(BHandler* handler);
private: private:
status_t _SetUpNodes(color_space preferredVideoFormat); status_t _SetUpNodes(color_space preferredVideoFormat,
uint32 enabledNodes);
status_t _SetUpVideoNodes( status_t _SetUpVideoNodes(
color_space preferredVideoFormat); color_space preferredVideoFormat);
status_t _SetUpAudioNodes(); status_t _SetUpAudioNodes();
@@ -67,7 +67,8 @@ PlaybackManager::PlaybackManager()
fPerformanceTime(0), fPerformanceTime(0),
fFrameRate(1.0), fFrameRate(1.0),
fStopPlayingFrame(-1), fStopPlayingFrame(-1),
fListeners() fListeners(),
fNoAudio(false)
{ {
Run(); Run();
} }
@@ -452,8 +453,11 @@ PlaybackManager::SetSpeed(float speed)
int64 int64
PlaybackManager::NextFrame() const PlaybackManager::NextFrame() const
{ {
if (fNoAudio)
return FrameForTime(fCurrentVideoTime - 1) + 1;
return FrameForTime(max((bigtime_t)fCurrentAudioTime, return FrameForTime(max((bigtime_t)fCurrentAudioTime,
(bigtime_t)fCurrentVideoTime) - 1) + 1; (bigtime_t)fCurrentVideoTime) - 1) + 1;
} }
@@ -1549,6 +1553,9 @@ PlaybackManager::_UpdateSpeedInfos()
bigtime_t bigtime_t
PlaybackManager::_TimeForLastFrame() const PlaybackManager::_TimeForLastFrame() const
{ {
if (fNoAudio)
return TimeForFrame(FrameForTime(fCurrentVideoTime));
return TimeForFrame(FrameForTime(min((bigtime_t)fCurrentAudioTime, return TimeForFrame(FrameForTime(min((bigtime_t)fCurrentAudioTime,
(bigtime_t)fCurrentVideoTime))); (bigtime_t)fCurrentVideoTime)));
} }
@@ -228,6 +228,8 @@ public:
// disabled: -1 // disabled: -1
BList fListeners; BList fListeners;
protected:
bool fNoAudio;
}; };