Rewrote audio decoding to provide timing information

that is used to sync with video.
Separated audio decoding and playing into two threads, 
the same applies to video decoding and playback.
This was inspired from code written by Stephan.
Added video decoding and display, added play/pause/stop.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17533 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen
2006-05-22 15:56:10 +00:00
parent d6b1b60ed4
commit 453f642e2e
7 changed files with 521 additions and 158 deletions
+440 -137
View File
@@ -21,6 +21,9 @@
#include <string.h>
#include <Debug.h>
#include <Entry.h>
#include <Window.h>
#include <Bitmap.h>
#include <Autolock.h>
#include <MediaFile.h>
#include <MediaTrack.h>
@@ -30,8 +33,10 @@
#include "SoundOutput.h"
#define AUDIO_PRIORITY 10
#define VIDEO_PRIORITY 10
#define AUDIO_PLAY_PRIORITY 10
#define VIDEO_PLAY_PRIORITY 10
#define AUDIO_DECODE_PRIORITY 10
#define VIDEO_DECODE_PRIORITY 10
void
HandleError(const char *text, status_t err)
@@ -53,36 +58,61 @@ Controller::Controller()
, fMediaFile(0)
, fAudioTrack(0)
, fVideoTrack(0)
, fAudioTrackLock("audio track lock")
, fVideoTrackLock("video track lock")
, fAudioTrackList(new BList)
, fVideoTrackList(new BList)
, fPosition(0)
, fAudioPlaySem(create_sem(1, "audio playing"))
, fVideoPlaySem(create_sem(1, "video playing"))
, fAudioDecodeSem(-1)
, fVideoDecodeSem(-1)
, fAudioPlaySem(-1)
, fVideoPlaySem(-1)
, fAudioDecodeThread(-1)
, fVideoDecodeThread(-1)
, fAudioPlayThread(-1)
, fVideoPlayThread(-1)
, fStopAudioPlayback(false)
, fStopVideoPlayback(false)
, fSoundOutput(NULL)
, fSeekAudio(false)
, fSeekVideo(false)
, fSeekPosition(0)
, fDuration(0)
, fAudioBufferCount(MAX_AUDIO_BUFFERS)
, fAudioBufferReadIndex(0)
, fAudioBufferWriteIndex(0)
, fVideoBufferCount(MAX_VIDEO_BUFFERS)
, fVideoBufferReadIndex(0)
, fVideoBufferWriteIndex(0)
, fTimeSourceLock("time source lock")
, fTimeSourceSysTime(0)
, fTimeSourcePerfTime(0)
, fAutoplay(true)
, fCurrentBitmap(NULL)
{
for (int i = 0; i < MAX_AUDIO_BUFFERS; i++) {
fAudioBuffer[i].bitmap = NULL;
fAudioBuffer[i].buffer = NULL;
fAudioBuffer[i].sizeMax = 0;
}
for (int i = 0; i < MAX_VIDEO_BUFFERS; i++) {
fVideoBuffer[i].bitmap = NULL;
fVideoBuffer[i].buffer = NULL;
fVideoBuffer[i].sizeMax = 0;
}
fStopped = fAutoplay ? false : true;
}
Controller::~Controller()
{
StopAudioPlayback();
StopVideoPlayback();
StopThreads();
if (fMediaFile)
fMediaFile->ReleaseAllTracks();
delete fMediaFile;
delete fAudioTrackList;
delete fVideoTrackList;
delete_sem(fVideoPlaySem);
delete_sem(fAudioPlaySem);
}
@@ -90,6 +120,7 @@ void
Controller::SetVideoView(VideoView *view)
{
fVideoView = view;
fVideoView->SetController(this);
}
@@ -103,11 +134,12 @@ Controller::SetControllerView(ControllerView *view)
status_t
Controller::SetTo(const entry_ref &ref)
{
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
StopAudioPlayback();
StopVideoPlayback();
StopThreads();
UpdatePosition(0);
BAutolock al(fAudioTrackLock);
BAutolock vl(fVideoTrackLock);
fAudioTrackList->MakeEmpty();
fVideoTrackList->MakeEmpty();
@@ -118,11 +150,13 @@ Controller::SetTo(const entry_ref &ref)
fVideoTrack = 0;
fMediaFile = 0;
fPosition = 0;
fSeekAudio = false;
fSeekVideo = false;
fPaused = false;
fStopped = true;
fStopped = fAutoplay ? false : true;
fDuration = 0;
fName = ref.name;
status_t err;
BMediaFile *mf = new BMediaFile(&ref);
@@ -130,8 +164,6 @@ Controller::SetTo(const entry_ref &ref)
if (err != B_OK) {
printf("Controller::SetTo: initcheck failed\n");
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return err;
}
@@ -139,8 +171,6 @@ Controller::SetTo(const entry_ref &ref)
if (trackcount <= 0) {
printf("Controller::SetTo: trackcount %d\n", trackcount);
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return B_MEDIA_NO_HANDLER;
}
@@ -167,8 +197,6 @@ Controller::SetTo(const entry_ref &ref)
if (AudioTrackCount() == 0 && VideoTrackCount() == 0) {
printf("Controller::SetTo: no audio or video tracks found\n");
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return B_MEDIA_NO_HANDLER;
}
@@ -178,14 +206,34 @@ Controller::SetTo(const entry_ref &ref)
SelectAudioTrack(0);
SelectVideoTrack(0);
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
StartThreads();
return B_OK;
}
void
Controller::GetSize(int *width, int *height)
{
/*
media_format fmt;
buffer->mediaFormat.type = B_MEDIA_RAW_VIDEO;
buffer->mediaFormat.u.raw_video = media_raw_video_format::wildcard;
buffer->mediaFormat.u.raw_video.display.format = IsOverlayActive() ? B_YCbCr422 : B_RGB32;
if (fVideoTrack || B_OK != fVideoTrack->DecodedFormat(&fmt)) {
*/
*height = 480;
*width = 640;
/*
} else {
*height = fmt.u.raw_video.display.line_count;
*width = fmt.u.raw_video.display.line_width;
}
*/
}
int
Controller::VideoTrackCount()
{
@@ -202,9 +250,9 @@ Controller::AudioTrackCount()
status_t
Controller::SelectAudioTrack(int n)
{
StopAudioPlayback();
{
BAutolock al(fAudioTrackLock);
BMediaTrack *t = (BMediaTrack *)fAudioTrackList->ItemAt(n);
if (!t)
return B_ERROR;
@@ -214,7 +262,6 @@ Controller::SelectAudioTrack(int n)
bigtime_t v = fVideoTrack ? fVideoTrack->Duration() : 0;
fDuration = max_c(a, v);
StartAudioPlayback();
return B_OK;
}
@@ -222,7 +269,7 @@ Controller::SelectAudioTrack(int n)
status_t
Controller::SelectVideoTrack(int n)
{
StopVideoPlayback();
BAutolock vl(fVideoTrackLock);
BMediaTrack *t = (BMediaTrack *)fVideoTrackList->ItemAt(n);
if (!t)
@@ -233,7 +280,6 @@ Controller::SelectVideoTrack(int n)
bigtime_t v = fVideoTrack ? fVideoTrack->Duration() : 0;
fDuration = max_c(a, v);
StartVideoPlayback();
return B_OK;
}
@@ -307,7 +353,8 @@ Controller::UpdatePosition(float value)
bool
Controller::IsOverlayActive()
{
return true;
// return true;
return false;
}
@@ -326,47 +373,51 @@ Controller::UnlockBitmap()
BBitmap *
Controller::Bitmap()
{
return NULL;
return fCurrentBitmap;
}
void
Controller::Stop()
{
printf("Controller::Stop\n");
if (fStopped)
return;
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
fPaused = false;
fStopped = true;
fPosition = 0;
// böse...
snooze(30000);
fSeekAudio = true;
fSeekVideo = true;
fSeekPosition = 0;
snooze(30000);
UpdatePosition(0);
}
void
Controller::Play()
{
printf("Controller::Play\n");
if (!fPaused && !fStopped)
return;
fStopped =
fPaused = false;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
}
void
Controller::Pause()
{
printf("Controller::Pause\n");
if (fStopped || fPaused)
return;
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
fPaused = true;
}
@@ -379,6 +430,351 @@ Controller::IsPaused()
}
bool
Controller::IsStopped()
{
return fStopped;
}
void
Controller::AudioDecodeThread()
{
BMediaTrack *lastTrack = 0;
size_t bufferSize = 0;
size_t frameSize = 0;
bool decodeError = false;
status_t status;
printf("audio decode start\n");
if (fAudioTrack == 0) {
return;
}
while (acquire_sem(fAudioDecodeSem) == B_OK) {
//printf("audio decoding..\n");
buffer_info *buffer = &fAudioBuffer[fAudioBufferWriteIndex];
fAudioBufferWriteIndex = (fAudioBufferWriteIndex + 1) % fAudioBufferCount;
BAutolock lock(fAudioTrackLock);
if (lastTrack != fAudioTrack) {
//printf("audio track changed\n");
lastTrack = fAudioTrack;
buffer->formatChanged = true;
buffer->mediaFormat.type = B_MEDIA_RAW_AUDIO;
buffer->mediaFormat.u.raw_audio = media_multi_audio_format::wildcard;
#ifdef __HAIKU__
buffer->mediaFormat.u.raw_audio.format = media_multi_audio_format::B_AUDIO_FLOAT;
#endif
status = fAudioTrack->DecodedFormat(&buffer->mediaFormat);
if (status != B_OK) {
printf("audio decoded format status %08x %s\n", status, strerror(status));
return;
}
bufferSize = buffer->mediaFormat.u.raw_audio.buffer_size;
frameSize = (buffer->mediaFormat.u.raw_audio.format & 0xf) * buffer->mediaFormat.u.raw_audio.channel_count;
} else {
buffer->formatChanged = false;
}
if (buffer->sizeMax < bufferSize) {
delete buffer->buffer;
buffer->buffer = new char [bufferSize];
buffer->sizeMax = bufferSize;;
}
if (fSeekAudio) {
bigtime_t pos = fSeekPosition;
fAudioTrack->SeekToTime(&pos);
fSeekAudio = false;
decodeError = false;
}
int64 frames;
media_header mh;
if (!decodeError) {
decodeError = B_OK != fAudioTrack->ReadFrames(buffer->buffer, &frames, &mh);
}
if (!decodeError) {
buffer->sizeUsed = frames * frameSize;
buffer->startTime = mh.start_time;
} else {
buffer->sizeUsed = 0;
buffer->startTime = 0;
}
release_sem(fAudioPlaySem);
}
}
void
Controller::AudioPlayThread()
{
SoundOutput *output = NULL;
bigtime_t bufferDuration = 0;
status_t status;
printf("audio play start\n");
if (fAudioTrack == 0) {
fTimeSourceSysTime = 0;
fTimeSourcePerfTime = 0;
return;
}
while (acquire_sem(fAudioPlaySem) == B_OK) {
//printf("audio playing..\n");
buffer_info *buffer = &fAudioBuffer[fAudioBufferReadIndex];
fAudioBufferReadIndex = (fAudioBufferReadIndex + 1) % fAudioBufferCount;
wait:
if (fPaused || fStopped) {
//printf("waiting..\n");
status = acquire_sem_etc(fThreadWaitSem, 1, B_RELATIVE_TIMEOUT, 50000);
if (status != B_TIMED_OUT)
break;
goto wait;
}
if (buffer->formatChanged) {
//printf("format changed..\n");
delete output;
output = new SoundOutput(fName.String(), buffer->mediaFormat.u.raw_audio);
bufferDuration = bigtime_t(1000000.0 * (buffer->mediaFormat.u.raw_audio.buffer_size / (buffer->mediaFormat.u.raw_audio.channel_count * (buffer->mediaFormat.u.raw_audio.format & 0xf))) / buffer->mediaFormat.u.raw_audio.frame_rate);
printf("audio format changed, new buffer duration %Ld\n", bufferDuration);
fSoundOutput = output; // hack...
}
if (output) {
if (buffer->sizeUsed)
output->Play(buffer->buffer, buffer->sizeUsed);
BAutolock lock(fTimeSourceLock);
fTimeSourceSysTime = system_time() + output->Latency() - bufferDuration;
fTimeSourcePerfTime = buffer->startTime;
// printf("timesource: sys: %Ld perf: %Ld\n", fTimeSourceSysTime, fTimeSourcePerfTime);
UpdatePosition(buffer->startTime / (float)Duration());
} else {
debugger("kein SoundOutput");
}
release_sem(fAudioDecodeSem);
}
delete output;
fSoundOutput = NULL; // hack...
}
void
Controller::VideoDecodeThread()
{
BMediaTrack *lastTrack = 0;
size_t bufferSize = 0;
size_t bytePerRow = 0;
int lineWidth = 0;
int lineCount = 0;
bool decodeError = false;
status_t status;
printf("video decode start\n");
if (fVideoTrack == 0) {
return;
}
while (acquire_sem(fVideoDecodeSem) == B_OK) {
buffer_info *buffer = &fVideoBuffer[fVideoBufferWriteIndex];
fVideoBufferWriteIndex = (fVideoBufferWriteIndex + 1) % fVideoBufferCount;
BAutolock lock(fVideoTrackLock);
if (lastTrack != fVideoTrack) {
//printf("Video track changed\n");
lastTrack = fVideoTrack;
buffer->formatChanged = true;
buffer->mediaFormat.type = B_MEDIA_RAW_VIDEO;
buffer->mediaFormat.u.raw_video = media_raw_video_format::wildcard;
buffer->mediaFormat.u.raw_video.display.format = IsOverlayActive() ? B_YCbCr422 : B_RGB32;
status = fVideoTrack->DecodedFormat(&buffer->mediaFormat);
if (status != B_OK) {
printf("video decoded format status %08x %s\n", status, strerror(status));
return;
}
bytePerRow = buffer->mediaFormat.u.raw_video.display.bytes_per_row;
lineWidth = buffer->mediaFormat.u.raw_video.display.line_width;
lineCount = buffer->mediaFormat.u.raw_video.display.line_count;
bufferSize = lineCount * bytePerRow;
} else {
buffer->formatChanged = false;
}
if (buffer->sizeMax != bufferSize) {
BRect r(0, 0, lineWidth - 1, lineCount - 1);
delete buffer->bitmap;
printf("allocating bitmap %d %d %d\n", lineWidth, lineCount, bytePerRow);
if (IsOverlayActive())
buffer->bitmap = new BBitmap(r, B_BITMAP_WILL_OVERLAY | (fVideoBufferWriteIndex == 1) ? B_BITMAP_RESERVE_OVERLAY_CHANNEL : 0, IsOverlayActive() ? B_YCbCr422 : B_RGB32, bytePerRow);
else
buffer->bitmap = new BBitmap(r, 0, B_RGB32, bytePerRow);
status = buffer->bitmap->InitCheck();
if (status != B_OK) {
printf("video decoded format status %08x %s\n", status, strerror(status));
return;
}
buffer->buffer = (char *)buffer->bitmap->Bits();
buffer->sizeMax = bufferSize;
}
if (fSeekVideo) {
bigtime_t pos = fSeekPosition;
fVideoTrack->SeekToTime(&pos);
fSeekVideo = false;
decodeError = false;
}
int64 frames;
media_header mh;
if (!decodeError) {
// printf("reading video frame...\n");
decodeError = B_OK != fVideoTrack->ReadFrames(buffer->buffer, &frames, &mh);
}
if (!decodeError) {
buffer->sizeUsed = buffer->sizeMax;
buffer->startTime = mh.start_time;
} else {
buffer->sizeUsed = 0;
buffer->startTime = 0;
}
release_sem(fVideoPlaySem);
}
}
void
Controller::VideoPlayThread()
{
status_t status;
printf("video decode start\n");
if (fVideoTrack == 0) {
return;
}
while (acquire_sem(fVideoPlaySem) == B_OK) {
buffer_info *buffer = &fVideoBuffer[fVideoBufferReadIndex];
fVideoBufferReadIndex = (fVideoBufferReadIndex + 1) % fVideoBufferCount;
wait:
if (fPaused || fStopped) {
//printf("waiting..\n");
status = acquire_sem_etc(fThreadWaitSem, 1, B_RELATIVE_TIMEOUT, 50000);
if (status != B_TIMED_OUT)
break;
goto wait;
}
bigtime_t waituntil;
bigtime_t waitdelta;
char test[100];
{
BAutolock lock(fTimeSourceLock);
waituntil = fTimeSourceSysTime - fTimeSourcePerfTime + buffer->startTime;
waitdelta = waituntil - system_time();
/*
sprintf(test, "sys %.6f perf %.6f, vid %.6f, waituntil %.6f, waitdelta %.6f",
fTimeSourceSysTime / 1000000.0f,
fTimeSourcePerfTime / 1000000.0f,
buffer->startTime / 1000000.0f,
waituntil / 1000000.0f,
waitdelta / 1000000.0f);
*/
// if (status != B_TIMED_OUT)
}
/*
if (fVideoView->LockLooperWithTimeout(5000) == B_OK) {
fVideoView->Window()->SetTitle(test);
fVideoView->UnlockLooper();
}
*/
status = acquire_sem_etc(fThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, waituntil);
if (status != B_TIMED_OUT)
break;
fCurrentBitmap = buffer->bitmap;
fVideoView->DrawFrame();
// snooze(60000);
release_sem(fVideoDecodeSem);
}
// status_t status = acquire_sem_etc(fThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, buffer->startTime);
// if (status != B_TIMED_OUT)
// return;
}
void
Controller::StartThreads()
{
if (fAudioDecodeSem > 0)
return;
fAudioBufferReadIndex = 0;
fAudioBufferWriteIndex = 0;
fVideoBufferReadIndex = 0;
fVideoBufferWriteIndex = 0;
fAudioDecodeSem = create_sem(fAudioBufferCount, "audio decode sem");
fVideoDecodeSem = create_sem(fVideoBufferCount - 2, "video decode sem");
fAudioPlaySem = create_sem(0, "audio play sem");
fVideoPlaySem = create_sem(0, "video play sem");
fThreadWaitSem = create_sem(0, "thread wait sem");
fAudioDecodeThread = spawn_thread(audio_decode_thread, "audio decode", AUDIO_DECODE_PRIORITY, this);
fVideoDecodeThread = spawn_thread(video_decode_thread, "video decode", VIDEO_DECODE_PRIORITY, this);
fAudioPlayThread = spawn_thread(audio_play_thread, "audio play", AUDIO_PLAY_PRIORITY, this);
fVideoPlayThread = spawn_thread(video_play_thread, "video play", VIDEO_PLAY_PRIORITY, this);
resume_thread(fAudioDecodeThread);
resume_thread(fVideoDecodeThread);
resume_thread(fAudioPlayThread);
resume_thread(fVideoPlayThread);
}
void
Controller::StopThreads()
{
if (fAudioDecodeSem < 0)
return;
delete_sem(fAudioDecodeSem);
delete_sem(fVideoDecodeSem);
delete_sem(fAudioPlaySem);
delete_sem(fVideoPlaySem);
delete_sem(fThreadWaitSem);
status_t dummy;
wait_for_thread(fAudioDecodeThread, &dummy);
wait_for_thread(fVideoDecodeThread, &dummy);
wait_for_thread(fAudioPlayThread, &dummy);
wait_for_thread(fVideoPlayThread, &dummy);
fAudioDecodeThread = -1;
fVideoDecodeThread = -1;
fAudioPlayThread = -1;
fVideoPlayThread = -1;
fThreadWaitSem = -1;
fAudioDecodeSem = -1;
fVideoDecodeSem = -1;
fAudioPlaySem = -1;
fVideoPlaySem = -1;
}
int32
Controller::audio_decode_thread(void *self)
{
static_cast<Controller *>(self)->AudioDecodeThread();
return 0;
}
int32
Controller::video_decode_thread(void *self)
{
static_cast<Controller *>(self)->VideoDecodeThread();
return 0;
}
int32
Controller::audio_play_thread(void *self)
{
@@ -393,96 +789,3 @@ Controller::video_play_thread(void *self)
static_cast<Controller *>(self)->VideoPlayThread();
return 0;
}
void
Controller::AudioPlayThread()
{
// this is a test...
media_format fmt;
fmt.type = B_MEDIA_RAW_AUDIO;
fmt.u.raw_audio = media_multi_audio_format::wildcard;
#ifdef __HAIKU__
fmt.u.raw_audio.format = media_multi_audio_format::B_AUDIO_FLOAT;
#endif
fAudioTrack->DecodedFormat(&fmt);
SoundOutput out(fName.String(), fmt.u.raw_audio);
out.SetVolume(1.0);
UpdateVolume(1.0);
int frame_size = (fmt.u.raw_audio.format & 0xf) * fmt.u.raw_audio.channel_count;
uint8 buffer[fmt.u.raw_audio.buffer_size];
int64 frames;
media_header mh;
fSoundOutput = &out;
while (!fStopAudioPlayback) {
if (B_OK == fAudioTrack->ReadFrames(buffer, &frames, &mh)) {
out.Play(buffer, frames * frame_size);
UpdatePosition(mh.start_time / (float)Duration());
} else {
snooze(50000);
}
if (fSeekAudio) {
bigtime_t pos = fSeekPosition;
fAudioTrack->SeekToTime(&pos);
fSeekAudio = false;
}
}
fSoundOutput = NULL;
}
void
Controller::VideoPlayThread()
{
}
void
Controller::StartAudioPlayback()
{
if (fAudioPlayThread > 0)
return;
fStopAudioPlayback = false;
fAudioPlayThread = spawn_thread(audio_play_thread, "audio playback", AUDIO_PRIORITY, this);
resume_thread(fAudioPlayThread);
}
void
Controller::StartVideoPlayback()
{
if (fVideoPlayThread > 0)
return;
fStopVideoPlayback = false;
fVideoPlayThread = spawn_thread(video_play_thread, "video playback", VIDEO_PRIORITY, this);
resume_thread(fVideoPlayThread);
}
void
Controller::StopAudioPlayback()
{
if (fAudioPlayThread < 0)
return;
fStopAudioPlayback = true;
status_t dummy;
wait_for_thread(fAudioPlayThread, &dummy);
fAudioPlayThread = -1;
}
void
Controller::StopVideoPlayback()
{
if (fVideoPlayThread < 0)
return;
fStopVideoPlayback = true;
status_t dummy;
wait_for_thread(fVideoPlayThread, &dummy);
fVideoPlayThread = -1;
}
+58 -9
View File
@@ -22,6 +22,7 @@
#include <MediaDefs.h>
#include <MediaNode.h>
#include <Locker.h>
#include <String.h>
class BBitmap;
@@ -38,6 +39,7 @@ public:
virtual ~Controller();
status_t SetTo(const entry_ref &ref);
void GetSize(int *width, int *height);
int AudioTrackCount();
int VideoTrackCount();
@@ -54,6 +56,7 @@ public:
void Play();
void Pause();
bool IsPaused();
bool IsStopped();
void SetVideoView(VideoView *view);
void SetControllerView(ControllerView *view);
@@ -75,43 +78,89 @@ public:
void UpdatePosition(float value);
private:
static int32 audio_decode_thread(void *self);
static int32 video_decode_thread(void *self);
static int32 audio_play_thread(void *self);
static int32 video_play_thread(void *self);
void AudioDecodeThread();
void VideoDecodeThread();
void AudioPlayThread();
void VideoPlayThread();
void StartThreads();
void StopThreads();
void StartAudioPlayback();
void StartVideoPlayback();
void StopAudioPlayback();
void StopVideoPlayback();
private:
enum {
MAX_AUDIO_BUFFERS = 8,
MAX_VIDEO_BUFFERS = 3,
};
struct buffer_info {
char * buffer;
BBitmap * bitmap;
size_t sizeUsed;
size_t sizeMax;
bigtime_t startTime;
bool formatChanged;
media_format mediaFormat;
};
VideoView * fVideoView;
ControllerView * fControllerView;
BString fName;
bool fPaused;
bool fStopped;
volatile bool fPaused;
volatile bool fStopped;
BMediaFile * fMediaFile;
BMediaTrack * fAudioTrack;
BMediaTrack * fVideoTrack;
BLocker fAudioTrackLock;
BLocker fVideoTrackLock;
BList * fAudioTrackList;
BList * fVideoTrackList;
bigtime_t fPosition;
media_format fAudioFormat;
media_format fVideoFormat;
sem_id fAudioDecodeSem;
sem_id fVideoDecodeSem;
sem_id fAudioPlaySem;
sem_id fVideoPlaySem;
sem_id fThreadWaitSem;
thread_id fAudioDecodeThread;
thread_id fVideoDecodeThread;
thread_id fAudioPlayThread;
thread_id fVideoPlayThread;
volatile bool fStopAudioPlayback;
volatile bool fStopVideoPlayback;
SoundOutput * fSoundOutput;
volatile bool fSeekAudio;
volatile bool fSeekVideo;
volatile bigtime_t fSeekPosition;
bigtime_t fDuration;
int32 fAudioBufferCount;
int32 fAudioBufferReadIndex;
int32 fAudioBufferWriteIndex;
int32 fVideoBufferCount;
int32 fVideoBufferReadIndex;
int32 fVideoBufferWriteIndex;
buffer_info fAudioBuffer[MAX_AUDIO_BUFFERS];
buffer_info fVideoBuffer[MAX_VIDEO_BUFFERS];
BLocker fTimeSourceLock;
bigtime_t fTimeSourceSysTime;
bigtime_t fTimeSourcePerfTime;
bool fAutoplay;
BBitmap * fCurrentBitmap;
};
#endif
+1 -1
View File
@@ -77,7 +77,7 @@ void
ControllerView::TogglePlaying()
{
printf("ControllerView::TogglePlaying()\n");
if (fController->IsPaused())
if (fController->IsPaused() || fController->IsStopped())
fController->Play();
else
fController->Pause();
+3 -4
View File
@@ -199,10 +199,9 @@ MainWin::SetupWindow()
fVideoMenu->ItemAt(0)->SetMarked(true);
if (fHasVideo) {
fSourceWidth = 320;
fSourceHeight = 240;
fWidthScale = 1.24;
fHeightScale = 1.35;
fController->GetSize(&fSourceWidth, &fSourceHeight);
fWidthScale = 1.0;
fHeightScale = 1.0;
} else {
fSourceWidth = 0;
fSourceHeight = 0;
+1 -1
View File
@@ -108,7 +108,7 @@ void
SoundOutput::PlayBuffer(void *buffer)
{
if (acquire_sem_etc(fBufferReadable, 1, B_RELATIVE_TIMEOUT, fBufferDuration / 2) != B_OK) {
printf("SoundOutput: buffer not ready, playing silence\n");
// printf("SoundOutput: buffer not ready, playing silence\n");
memset(buffer, 0, fBufferSize);
return;
}
+16 -6
View File
@@ -29,8 +29,10 @@ VideoView::VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 fl
, fController(NULL)
, fOverlayActive(false)
{
// SetViewColor(B_TRANSPARENT_COLOR);
SetViewColor(127,255,127);
SetViewColor(B_TRANSPARENT_COLOR);
// SetViewColor(127,255,127);
rgb_color r = {255, 0, 0, 255};
fOverlayKeyColor = r;
}
@@ -39,6 +41,13 @@ VideoView::~VideoView()
}
void
VideoView::SetController(Controller *controller)
{
fController = controller;
}
void
VideoView::AttachedToWindow()
{
@@ -163,12 +172,13 @@ VideoView::DrawFrame()
printf("can't ClearViewOverlay, as LockLooperWithTimeout failed\n");
}
}
if (want_overlay && !fOverlayActive) {
if (want_overlay && !fOverlayActive ) {
fController->LockBitmap();
BBitmap *bmp = 0; // fController->Bitmap();
BBitmap *bmp = fController->Bitmap();
if (bmp && LockLooperWithTimeout(50000) == B_OK) {
SetViewOverlay(bmp, bmp->Bounds(), Bounds(), &fOverlayKeyColor,
B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL);
B_FOLLOW_ALL,
/*B_OVERLAY_TRANSFER_CHANNEL | */B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL );
fOverlayActive = true;
Invalidate();
@@ -228,7 +238,7 @@ VideoView::IsOverlaySupported()
bool supported = false;
for (int i = 0; colspace[i].name; i++) {
BBitmap *test = new BBitmap(BRect(0,0,320,240), B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, colspace[i].colspace);
BBitmap *test = new BBitmap(BRect(0,0,319,239), B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, colspace[i].colspace);
if (test->InitCheck() == B_OK) {
printf("Display supports %s (0x%08x) overlay\n", colspace[i].name, colspace[i].colspace);
supported = true;
+2
View File
@@ -28,6 +28,8 @@ class VideoView : public BView
public:
VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags);
~VideoView();
void SetController(Controller *controller);
void RemoveVideoDisplay();
void RemoveOverlay();