* 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)
, 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)
+1
View File
@@ -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;
};