* 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)
|
, 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)
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user