From e6ac2ec43e8d5c0215f33734b2bfbb1e69c138c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 5 Jul 2008 18:22:37 +0000 Subject: [PATCH] * The window would not reset the audio/video track to 0 on a new file if the Controller would keep the last audio/video track index across files (which would be nice for certain situations). * Better error message for unsupported files, especially for the B_MEDIA_NO_HANDLER error. * In the Controller, try to obtain the track duration and ignore tracks that return a bogus duration. I have some MP3 files on ZETA that are obviously not handled correctly by the ZETA mp3 decoder. Previously, the player would just sit there and appeared to have some other internal error. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26261 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/mediaplayer/Controller.cpp | 48 +++++++++++---- src/apps/mediaplayer/Controller.h | 2 + src/apps/mediaplayer/MainWin.cpp | 60 ++++++++++++------- .../mediaplayer/supplier/AudioTrackSupplier.h | 2 + .../supplier/MediaTrackAudioSupplier.cpp | 10 +++- .../supplier/MediaTrackAudioSupplier.h | 7 ++- .../supplier/MediaTrackVideoSupplier.cpp | 4 +- .../supplier/MediaTrackVideoSupplier.h | 7 ++- .../mediaplayer/supplier/VideoTrackSupplier.h | 2 + 9 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp index 511dd25c4e..4237f9fa30 100644 --- a/src/apps/mediaplayer/Controller.cpp +++ b/src/apps/mediaplayer/Controller.cpp @@ -125,6 +125,10 @@ Controller::~Controller() int64 Controller::Duration() { + // TODO: It is not so nice that the MediaPlayer still measures + // in video frames if only playing audio. Here for example, it will + // return a duration of 0 if the audio clip happens to be shorter than + // one video frame at 25 fps. return (int64)((double)fDuration * fVideoFrameRate / 1000000.0); } @@ -195,7 +199,7 @@ Controller::SetTo(const entry_ref &ref) status_t err; - BMediaFile *mf = new BMediaFile(&ref); + BMediaFile* mf = new BMediaFile(&ref); ObjectDeleter mediaFileDeleter(mf); err = mf->InitCheck(); @@ -213,19 +217,21 @@ Controller::SetTo(const entry_ref &ref) } for (int i = 0; i < trackcount; i++) { - BMediaTrack *t = mf->TrackAt(i); + BMediaTrack* t = mf->TrackAt(i); media_format f; err = t->EncodedFormat(&f); - if (err != B_OK) { + if (err != B_OK || t->Duration() <= 0) { printf("Controller::SetTo: EncodedFormat failed for track index %d, error 0x%08lx (%s)\n", i, err, strerror(err)); mf->ReleaseTrack(t); continue; } if (f.IsAudio()) { - fAudioTrackList.AddItem(t); + if (!fAudioTrackList.AddItem(t)) + return B_NO_MEMORY; } else if (f.IsVideo()) { - fVideoTrackList.AddItem(t); + if (!fVideoTrackList.AddItem(t)) + return B_NO_MEMORY; } else { printf("Controller::SetTo: track index %d has unknown type\n", i); mf->ReleaseTrack(t); @@ -326,7 +332,7 @@ Controller::SelectAudioTrack(int n) return B_ERROR; ObjectDeleter deleter(fAudioTrackSupplier); - fAudioTrackSupplier = new MediaTrackAudioSupplier(track); + fAudioTrackSupplier = new MediaTrackAudioSupplier(track, n); bigtime_t a = fAudioTrackSupplier->Duration(); bigtime_t v = fVideoTrackSupplier ? fVideoTrackSupplier->Duration() : 0;; @@ -334,10 +340,6 @@ Controller::SelectAudioTrack(int n) DurationChanged(); // TODO: notify duration changed! - // TODO: Not good, because the ProxyAudioSupplier currently - // uses the supplier without locking the Controller! - // This is only a problem when selecting a different audio track - // from the interface menu. fAudioSupplier->SetSupplier(fAudioTrackSupplier, fVideoFrameRate); _NotifyAudioTrackChanged(n); @@ -345,6 +347,18 @@ Controller::SelectAudioTrack(int n) } +int +Controller::CurrentAudioTrack() +{ + BAutolock _(this); + + if (fAudioTrackSupplier == NULL) + return -1; + + return fAudioTrackSupplier->TrackIndex(); +} + + status_t Controller::SelectVideoTrack(int n) { @@ -356,7 +370,7 @@ Controller::SelectVideoTrack(int n) status_t initStatus; ObjectDeleter deleter(fVideoTrackSupplier); - fVideoTrackSupplier = new MediaTrackVideoSupplier(track, initStatus); + fVideoTrackSupplier = new MediaTrackVideoSupplier(track, n, initStatus); if (initStatus < B_OK) { delete fVideoTrackSupplier; fVideoTrackSupplier = NULL; @@ -383,6 +397,18 @@ Controller::SelectVideoTrack(int n) } +int +Controller::CurrentVideoTrack() +{ + BAutolock _(this); + + if (fVideoTrackSupplier == NULL) + return -1; + + return fVideoTrackSupplier->TrackIndex(); +} + + // #pragma mark - diff --git a/src/apps/mediaplayer/Controller.h b/src/apps/mediaplayer/Controller.h index d2dc289798..0ae23c2738 100644 --- a/src/apps/mediaplayer/Controller.h +++ b/src/apps/mediaplayer/Controller.h @@ -83,7 +83,9 @@ public: int VideoTrackCount(); status_t SelectAudioTrack(int n); + int CurrentAudioTrack(); status_t SelectVideoTrack(int n); + int CurrentVideoTrack(); void Stop(); void Play(); diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index 7126243719..c8aaaa284a 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -709,10 +709,21 @@ MainWin::OpenFile(const entry_ref &ref) if (err != B_OK) { if (fPlaylist->CountItems() == 1) { // display error if this is the only file we're supposed to play - char s[300]; - sprintf(s, "Can't open file\n\n%s\n\nError 0x%08lx\n(%s)\n", - ref.name, err, strerror(err)); - (new BAlert("error", s, "OK"))->Go(); + BString message; + message << "The file '"; + message << ref.name; + message << "' could not be opened.\n\n"; + + if (err == B_MEDIA_NO_HANDLER) { + // give a more detailed message for the most likely of all + // errors + message << "There is no decoder installed to handle the " + "file format, or the decoder has trouble with the specific " + "version of the format."; + } else { + message << "Error: " << strerror(err); + } + (new BAlert("error", message.String(), "OK"))->Go(); } else { // just go to the next file and don't bother user fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1); @@ -828,9 +839,6 @@ MainWin::_SetupWindow() // Enable both if a file was loaded fAudioTrackMenu->SetEnabled(fHasFile); fVideoTrackMenu->SetEnabled(fHasFile); - // Select first track (might be "none") in both - fAudioTrackMenu->ItemAt(0)->SetMarked(true); - fVideoTrackMenu->ItemAt(0)->SetMarked(true); fVideoMenu->SetEnabled(fHasVideo); fAudioMenu->SetEnabled(fHasAudio); @@ -847,6 +855,8 @@ MainWin::_SetupWindow() } _UpdateControlsEnabledStatus(); + // TODO: Don't if the video size did not change! Also don't + // exit full screen mode. _ResizeWindow(100); fVideoView->MakeFocus(); @@ -958,26 +968,36 @@ MainWin::_SetupTrackMenus() fAudioTrackMenu->RemoveItems(0, fAudioTrackMenu->CountItems(), true); fVideoTrackMenu->RemoveItems(0, fVideoTrackMenu->CountItems(), true); - int c, i; char s[100]; - c = fController->AudioTrackCount(); - for (i = 0; i < c; i++) { + int count = fController->AudioTrackCount(); + int current = fController->CurrentAudioTrack(); + for (int i = 0; i < count; i++) { sprintf(s, "Track %d", i + 1); - fAudioTrackMenu->AddItem(new BMenuItem(s, - new BMessage(M_SELECT_AUDIO_TRACK + i))); + BMenuItem* item = new BMenuItem(s, + new BMessage(M_SELECT_AUDIO_TRACK + i)); + item->SetMarked(i == current); + fAudioTrackMenu->AddItem(item); } - if (!c) + if (!count) { fAudioTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); - - c = fController->VideoTrackCount(); - for (i = 0; i < c; i++) { - sprintf(s, "Track %d", i + 1); - fVideoTrackMenu->AddItem(new BMenuItem(s, - new BMessage(M_SELECT_VIDEO_TRACK + i))); + fAudioTrackMenu->ItemAt(0)->SetMarked(true); } - if (!c) + + + count = fController->VideoTrackCount(); + current = fController->CurrentVideoTrack(); + for (int i = 0; i < count; i++) { + sprintf(s, "Track %d", i + 1); + BMenuItem* item = new BMenuItem(s, + new BMessage(M_SELECT_VIDEO_TRACK + i)); + item->SetMarked(i == current); + fVideoTrackMenu->AddItem(item); + } + if (!count) { fVideoTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); + fVideoTrackMenu->ItemAt(0)->SetMarked(true); + } } diff --git a/src/apps/mediaplayer/supplier/AudioTrackSupplier.h b/src/apps/mediaplayer/supplier/AudioTrackSupplier.h index 0e5001ac3c..8e2bce22ba 100644 --- a/src/apps/mediaplayer/supplier/AudioTrackSupplier.h +++ b/src/apps/mediaplayer/supplier/AudioTrackSupplier.h @@ -23,6 +23,8 @@ class AudioTrackSupplier : public AudioReader { const = 0; virtual status_t GetCodecInfo(media_codec_info* info) const = 0; virtual bigtime_t Duration() const = 0; + + virtual int32 TrackIndex() const = 0; }; #endif // AUDIO_TRACK_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp index 77b93c1cc6..a702d1eca7 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp @@ -54,7 +54,8 @@ MediaTrackAudioSupplier::Buffer::CompareOffset(const void* a, const void* b) // #pragma mark - MediaTrackAudioSupplier -MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack) +MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack, + int32 trackIndex) : AudioTrackSupplier(), fMediaTrack(mediaTrack), fBuffer(NULL), @@ -63,7 +64,8 @@ MediaTrackAudioSupplier::MediaTrackAudioSupplier(BMediaTrack* mediaTrack) fBuffers(10), fHasKeyFrames(false), fCountFrames(0), - fReportSeekError(true) + fReportSeekError(true), + fTrackIndex(trackIndex) { _InitFromTrack(); } @@ -104,6 +106,7 @@ MediaTrackAudioSupplier::GetCodecInfo(media_codec_info* info) const bigtime_t MediaTrackAudioSupplier::Duration() const { + fMediaTrack, fMediaTrack ? fMediaTrack->Duration() : 0LL, fCountFrames); if (!fMediaTrack) return 0; @@ -199,6 +202,9 @@ MediaTrackAudioSupplier::_InitFromTrack() // get the length of the track fCountFrames = fMediaTrack->CountFrames(); + + TRACE("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n", + fHasKeyFrames, fCountFrames); } else fMediaTrack = NULL; } diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h index 51c2fa9494..abb76d4331 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h @@ -16,7 +16,8 @@ struct media_format; class MediaTrackAudioSupplier : public AudioTrackSupplier { public: - MediaTrackAudioSupplier(BMediaTrack* track); + MediaTrackAudioSupplier(BMediaTrack* track, + int32 trackIndex); virtual ~MediaTrackAudioSupplier(); virtual const media_format& Format() const; @@ -30,6 +31,9 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier { virtual status_t InitCheck() const; + virtual int32 TrackIndex() const + { return fTrackIndex; } + private: struct Buffer; void _InitFromTrack(); @@ -84,6 +88,7 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier { bool fHasKeyFrames; int64 fCountFrames; bool fReportSeekError; + int32 fTrackIndex; }; #endif // MEDIA_TRACK_AUDIO_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp index 6c6e09a60d..7c56f3fc99 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.cpp @@ -24,13 +24,15 @@ using std::nothrow; // constructor MediaTrackVideoSupplier::MediaTrackVideoSupplier(BMediaTrack* track, - status_t& initStatus) + int32 trackIndex, status_t& initStatus) : VideoTrackSupplier() , fVideoTrack(track) , fPerformanceTime(0) , fDuration(0) , fCurrentFrame(0) + + , fTrackIndex(trackIndex) { if (!fVideoTrack) { printf("MediaTrackVideoSupplier() - no video track\n"); diff --git a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h index f00f9901c1..93613358b9 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h +++ b/src/apps/mediaplayer/supplier/MediaTrackVideoSupplier.h @@ -17,7 +17,7 @@ class BMediaTrack; class MediaTrackVideoSupplier : public VideoTrackSupplier { public: MediaTrackVideoSupplier(BMediaTrack* track, - status_t& initStatus); + int32 trackIndex, status_t& initStatus); virtual ~MediaTrackVideoSupplier(); virtual const media_format& Format() const; @@ -42,6 +42,9 @@ class MediaTrackVideoSupplier : public VideoTrackSupplier { virtual color_space ColorSpace() const; virtual uint32 BytesPerRow() const; + virtual int32 TrackIndex() const + { return fTrackIndex; } + private: status_t _SwitchFormat(color_space format, uint32 bytesPerRow); @@ -55,6 +58,8 @@ class MediaTrackVideoSupplier : public VideoTrackSupplier { bigtime_t fPerformanceTime; bigtime_t fDuration; int64 fCurrentFrame; + + int32 fTrackIndex; }; #endif // MEDIA_TRACK_VIDEO_SUPPLIER_H diff --git a/src/apps/mediaplayer/supplier/VideoTrackSupplier.h b/src/apps/mediaplayer/supplier/VideoTrackSupplier.h index 383ee4a3dc..c6e5a7490b 100644 --- a/src/apps/mediaplayer/supplier/VideoTrackSupplier.h +++ b/src/apps/mediaplayer/supplier/VideoTrackSupplier.h @@ -31,6 +31,8 @@ class VideoTrackSupplier { virtual bigtime_t Position() const = 0; virtual bigtime_t Duration() const = 0; virtual int64 CurrentFrame() const = 0; + + virtual int32 TrackIndex() const = 0; }; #endif // VIDEO_TRACK_SUPPLIER_H