* 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
This commit is contained in:
Stephan Aßmus 2008-07-05 18:22:37 +00:00
parent 9b74b9cda8
commit e6ac2ec43e
9 changed files with 106 additions and 36 deletions

View File

@ -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<BMediaFile> 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<AudioTrackSupplier> 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<VideoTrackSupplier> 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 -

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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