All sorts of refactoring with regards to the audio node and format setup. At
first I tried adding support for changing the format during running the node connection, but later found out that this is not implemented in the system mixer (it has this weird setting to allow input format changes, but if you do this, the media_server will just crash, since the backend does not support it yet). Also, the Media Kit documentation is extremely lacking in this regard. I ended up re-establishing the node connection when the audio format is supposed to change, just like it is already done for video. This means that audio files now play with their native channel count and frame rate. But it isn't so well tested yet, if 48 kHz for example introduce some clicks. The channel count should not be a problem though, I've also tested that with some movies and it works fine. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33678 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -295,7 +295,7 @@ Controller::SetTo(const PlaylistItemRef& item)
|
||||
int height;
|
||||
GetSize(&width, &height);
|
||||
color_space preferredVideoFormat = B_NO_COLOR_SPACE;
|
||||
if (fVideoTrackSupplier) {
|
||||
if (fVideoTrackSupplier != NULL) {
|
||||
const media_format& format = fVideoTrackSupplier->Format();
|
||||
preferredVideoFormat = format.u.raw_video.display.format;
|
||||
}
|
||||
@@ -308,13 +308,22 @@ Controller::SetTo(const PlaylistItemRef& item)
|
||||
else
|
||||
enabledNodes = AUDIO_AND_VIDEO;
|
||||
|
||||
float audioFrameRate = 44100.0f;
|
||||
uint32 audioChannels = 2;
|
||||
if (fAudioTrackSupplier != NULL) {
|
||||
const media_format& audioTrackFormat = fAudioTrackSupplier->Format();
|
||||
audioFrameRate = audioTrackFormat.u.raw_audio.frame_rate;
|
||||
audioChannels = audioTrackFormat.u.raw_audio.channel_count;
|
||||
}
|
||||
|
||||
if (InitCheck() != B_OK) {
|
||||
Init(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
|
||||
preferredVideoFormat, LOOPING_ALL, false, 1.0, enabledNodes,
|
||||
useOverlays);
|
||||
preferredVideoFormat, audioFrameRate, audioChannels, LOOPING_ALL,
|
||||
false, 1.0, enabledNodes, useOverlays);
|
||||
} else {
|
||||
FormatChanged(BRect(0, 0, width - 1, height - 1), fVideoFrameRate,
|
||||
preferredVideoFormat, enabledNodes, useOverlays);
|
||||
preferredVideoFormat, audioFrameRate, audioChannels, enabledNodes,
|
||||
useOverlays);
|
||||
}
|
||||
|
||||
_NotifyFileChanged();
|
||||
|
||||
@@ -66,8 +66,9 @@ NodeManager::~NodeManager()
|
||||
// Init
|
||||
status_t
|
||||
NodeManager::Init(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat, int32 loopingMode,
|
||||
bool loopingEnabled, float speed, uint32 enabledNodes, bool useOverlays)
|
||||
color_space preferredVideoFormat, float audioFrameRate,
|
||||
uint32 audioChannels, int32 loopingMode, bool loopingEnabled,
|
||||
float speed, uint32 enabledNodes, bool useOverlays)
|
||||
{
|
||||
// init base class
|
||||
PlaybackManager::Init(videoFrameRate, loopingMode, loopingEnabled, speed);
|
||||
@@ -83,7 +84,7 @@ NodeManager::Init(BRect videoBounds, float videoFrameRate,
|
||||
fAudioSupplier = CreateAudioSupplier();
|
||||
|
||||
return FormatChanged(videoBounds, videoFrameRate, preferredVideoFormat,
|
||||
enabledNodes, useOverlays, true);
|
||||
audioFrameRate, audioChannels, enabledNodes, useOverlays, true);
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
@@ -118,8 +119,8 @@ NodeManager::CleanupNodes()
|
||||
// FormatChanged
|
||||
status_t
|
||||
NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat, uint32 enabledNodes, bool useOverlays,
|
||||
bool force)
|
||||
color_space preferredVideoFormat, float audioFrameRate,
|
||||
uint32 audioChannels, uint32 enabledNodes, bool useOverlays, bool force)
|
||||
{
|
||||
TRACE("NodeManager::FormatChanged()\n");
|
||||
|
||||
@@ -144,7 +145,7 @@ NodeManager::FormatChanged(BRect videoBounds, float videoFrameRate,
|
||||
SetVideoBounds(videoBounds);
|
||||
|
||||
status_t ret = _SetUpNodes(preferredVideoFormat, enabledNodes,
|
||||
useOverlays);
|
||||
useOverlays, audioFrameRate, audioChannels);
|
||||
if (ret == B_OK)
|
||||
_StartNodes();
|
||||
else
|
||||
@@ -253,7 +254,7 @@ NodeManager::SetPeakListener(BHandler* handler)
|
||||
// _SetUpNodes
|
||||
status_t
|
||||
NodeManager::_SetUpNodes(color_space preferredVideoFormat, uint32 enabledNodes,
|
||||
bool useOverlays)
|
||||
bool useOverlays, float audioFrameRate, uint32 audioChannels)
|
||||
{
|
||||
TRACE("NodeManager::_SetUpNodes()\n");
|
||||
|
||||
@@ -289,7 +290,7 @@ NodeManager::_SetUpNodes(color_space preferredVideoFormat, uint32 enabledNodes,
|
||||
|
||||
// setup the audio nodes
|
||||
if (enabledNodes != VIDEO_ONLY) {
|
||||
fStatus = _SetUpAudioNodes();
|
||||
fStatus = _SetUpAudioNodes(audioFrameRate, audioChannels);
|
||||
if (fStatus != B_OK) {
|
||||
print_error("Error setting up audio nodes", fStatus);
|
||||
fMediaRoster->Unlock();
|
||||
@@ -445,7 +446,7 @@ NodeManager::_SetUpVideoNodes(color_space preferredVideoFormat,
|
||||
|
||||
// _SetUpAudioNodes
|
||||
status_t
|
||||
NodeManager::_SetUpAudioNodes()
|
||||
NodeManager::_SetUpAudioNodes(float audioFrameRate, uint32 audioChannels)
|
||||
{
|
||||
fAudioProducer = new AudioProducer("MediaPlayer Audio Out", fAudioSupplier);
|
||||
fAudioProducer->SetPeakListener(fPeakListener);
|
||||
@@ -489,11 +490,13 @@ NodeManager::_SetUpAudioNodes()
|
||||
}
|
||||
|
||||
// got the endpoints; now we connect it!
|
||||
media_format audio_format;
|
||||
audio_format.type = B_MEDIA_RAW_AUDIO;
|
||||
audio_format.u.raw_audio = media_raw_audio_format::wildcard;
|
||||
media_format audioFormat;
|
||||
audioFormat.type = B_MEDIA_RAW_AUDIO;
|
||||
audioFormat.u.raw_audio = media_raw_audio_format::wildcard;
|
||||
audioFormat.u.raw_audio.frame_rate = audioFrameRate;
|
||||
audioFormat.u.raw_audio.channel_count = audioChannels;
|
||||
fStatus = fMediaRoster->Connect(soundOutput.source, mixerInput.destination,
|
||||
&audio_format, &soundOutput, &mixerInput);
|
||||
&audioFormat, &soundOutput, &mixerInput);
|
||||
if (fStatus != B_OK) {
|
||||
print_error("unable to connect audio nodes", fStatus);
|
||||
return fStatus;
|
||||
@@ -502,7 +505,7 @@ NodeManager::_SetUpAudioNodes()
|
||||
// the inputs and outputs might have been reassigned during the
|
||||
// nodes' negotiation of the Connect(). That's why we wait until
|
||||
// after Connect() finishes to save their contents.
|
||||
fAudioConnection.format = audio_format;
|
||||
fAudioConnection.format = audioFormat;
|
||||
fAudioConnection.source = soundOutput.source;
|
||||
fAudioConnection.destination = mixerInput.destination;
|
||||
fAudioConnection.connected = true;
|
||||
@@ -694,7 +697,6 @@ printf("performance time for %lld: %lld\n", real + latency
|
||||
}
|
||||
|
||||
if (fAudioProducer) {
|
||||
fAudioProducer->SetRunning(true);
|
||||
status = fMediaRoster->StartNode(fAudioConnection.producer, perf);
|
||||
if (status != B_OK) {
|
||||
print_error("Can't start the audio producer", status);
|
||||
@@ -715,27 +717,19 @@ void
|
||||
NodeManager::_StopNodes()
|
||||
{
|
||||
TRACE("NodeManager::_StopNodes()\n");
|
||||
// if (PlayMode() == MODE_PLAYING_PAUSED_FORWARD
|
||||
// || PlayMode() == MODE_PLAYING_PAUSED_FORWARD)
|
||||
// return;
|
||||
fMediaRoster = BMediaRoster::Roster();
|
||||
if (!fMediaRoster) {
|
||||
if (fAudioProducer)
|
||||
fAudioProducer->SetRunning(false);
|
||||
return;
|
||||
} else if (fMediaRoster->Lock()) {
|
||||
if (fMediaRoster != NULL && fMediaRoster->Lock()) {
|
||||
// begin mucking with the media roster
|
||||
if (fVideoProducer) {
|
||||
if (fVideoProducer != NULL) {
|
||||
TRACE(" stopping video producer...\n");
|
||||
fMediaRoster->StopNode(fVideoConnection.producer, 0, true);
|
||||
}
|
||||
if (fAudioProducer) {
|
||||
if (fAudioProducer != NULL) {
|
||||
TRACE(" stopping audio producer...\n");
|
||||
fAudioProducer->SetRunning(false);
|
||||
fMediaRoster->StopNode(fAudioConnection.producer, 0, true);
|
||||
// synchronous stop
|
||||
}
|
||||
if (fVideoConsumer) {
|
||||
if (fVideoConsumer != NULL) {
|
||||
TRACE(" stopping video consumer...\n");
|
||||
fMediaRoster->StopNode(fVideoConnection.consumer, 0, true);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,9 @@ class NodeManager : public PlaybackManager {
|
||||
|
||||
status_t Init(BRect videoBounds, float videoFrameRate,
|
||||
color_space preferredVideoFormat,
|
||||
int32 loopingMode,
|
||||
bool loopingEnabled,
|
||||
float speed,
|
||||
uint32 enabledNodes,
|
||||
float audioFrameRate, uint32 audioChannels,
|
||||
int32 loopingMode, bool loopingEnabled,
|
||||
float speed, uint32 enabledNodes,
|
||||
bool useOverlays);
|
||||
status_t InitCheck();
|
||||
// only call this if the
|
||||
@@ -53,9 +52,11 @@ class NodeManager : public PlaybackManager {
|
||||
status_t FormatChanged(BRect videoBounds,
|
||||
float videoFrameRate,
|
||||
color_space preferredVideoFormat,
|
||||
float audioFrameRate, uint32 audioChannels,
|
||||
uint32 enabledNodes,
|
||||
bool useOverlays,
|
||||
bool force = false);
|
||||
|
||||
virtual void SetPlayMode(int32 mode,
|
||||
bool continuePlaying = true);
|
||||
|
||||
@@ -76,11 +77,14 @@ class NodeManager : public PlaybackManager {
|
||||
|
||||
private:
|
||||
status_t _SetUpNodes(color_space preferredVideoFormat,
|
||||
uint32 enabledNodes, bool useOverlays);
|
||||
uint32 enabledNodes, bool useOverlays,
|
||||
float audioFrameRate,
|
||||
uint32 audioChannels);
|
||||
status_t _SetUpVideoNodes(
|
||||
color_space preferredVideoFormat,
|
||||
bool useOverlays);
|
||||
status_t _SetUpAudioNodes();
|
||||
status_t _SetUpAudioNodes(float audioFrameRate,
|
||||
uint32 audioChannels);
|
||||
status_t _TearDownNodes(bool disconnect = true);
|
||||
status_t _StartNodes();
|
||||
void _StopNodes();
|
||||
|
||||
@@ -55,7 +55,9 @@ AudioAdapter::AudioAdapter(AudioReader* source, const media_format& format)
|
||||
|
||||
if (fFormat.u.raw_audio.channel_count
|
||||
!= source->Format().u.raw_audio.channel_count) {
|
||||
TRACE("AudioAdapter() - using channel converter\n");
|
||||
TRACE("AudioAdapter() - using channel converter (%ld -> %ld)\n",
|
||||
source->Format().u.raw_audio.channel_count,
|
||||
fFormat.u.raw_audio.channel_count);
|
||||
fChannelConverter = new (nothrow) AudioChannelConverter(source,
|
||||
fFormat);
|
||||
source = fChannelConverter;
|
||||
|
||||
@@ -40,6 +40,8 @@ convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
|
||||
{
|
||||
// TODO: more conversions!
|
||||
switch (inChannels) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
switch (outChannels) {
|
||||
case 2:
|
||||
@@ -61,13 +63,13 @@ convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
default:
|
||||
switch (outChannels) {
|
||||
case 2:
|
||||
for (int32 i = 0; i < frames; i++) {
|
||||
outBuffer[0] = inBuffer[0];
|
||||
outBuffer[1] = inBuffer[1];
|
||||
inBuffer += 5;
|
||||
inBuffer += outChannels;
|
||||
outBuffer += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/* Copyright (c) 1998-99, Be Incorporated, All Rights Reserved.
|
||||
* Distributed under the terms of the Be Sample Code license.
|
||||
/*
|
||||
* Copyright (c) 1998-99, Be Incorporated, All Rights Reserved.
|
||||
* Distributed under the terms of the Be Sample Code license.
|
||||
*
|
||||
* Copyright (c) 2000-2008, Ingo Weinhold <[email protected]>,
|
||||
* Copyright (c) 2000-2008, Stephan Aßmus <[email protected]>,
|
||||
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||
* Copyright (c) 2000-2008, Ingo Weinhold <[email protected]>,
|
||||
* Copyright (c) 2000-2008, Stephan Aßmus <[email protected]>,
|
||||
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "AudioProducer.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -32,13 +34,15 @@
|
||||
|
||||
|
||||
// debugging
|
||||
//#define TRACE_AUDIO_PRODUCER
|
||||
#define TRACE_AUDIO_PRODUCER
|
||||
#ifdef TRACE_AUDIO_PRODUCER
|
||||
# define TRACE(x...) printf(x)
|
||||
# define ERROR(x...) fprintf(stderr, x)
|
||||
# define TRACE(x...) printf(x)
|
||||
# define TRACE_BUFFER(x...)
|
||||
# define ERROR(x...) fprintf(stderr, x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
# define ERROR(x...) fprintf(stderr, x)
|
||||
# define TRACE_BUFFER(x...)
|
||||
# define ERROR(x...) fprintf(stderr, x)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -96,7 +100,6 @@ AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier,
|
||||
fFramesSent(0),
|
||||
fStartTime(0),
|
||||
fSupplier(supplier),
|
||||
fRunning(false),
|
||||
|
||||
fPeakListener(NULL)
|
||||
{
|
||||
@@ -175,15 +178,12 @@ AudioProducer::FormatSuggestionRequested(media_type type, int32 quality,
|
||||
if (!_format)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// this is the format we'll be returning (our preferred format)
|
||||
// This is the format we'll be returning (our preferred format)
|
||||
*_format = fPreferredFormat;
|
||||
|
||||
// a wildcard type is okay; we can specialize it
|
||||
if (type == B_MEDIA_UNKNOWN_TYPE)
|
||||
type = B_MEDIA_RAW_AUDIO;
|
||||
|
||||
// we only support raw audio
|
||||
if (type != B_MEDIA_RAW_AUDIO)
|
||||
// A wildcard type is okay; we can specialize it, otherwise only raw audio
|
||||
// is supported
|
||||
if (type != B_MEDIA_UNKNOWN_TYPE && type != B_MEDIA_RAW_AUDIO)
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
|
||||
return B_OK;
|
||||
@@ -200,20 +200,28 @@ AudioProducer::FormatProposal(const media_source& output, media_format* format)
|
||||
return B_MEDIA_BAD_SOURCE;
|
||||
}
|
||||
|
||||
// TODO: we might want to support different audio formats
|
||||
// we only support floating-point raw audio, so we always return that, but
|
||||
// we supply an error code depending on whether we found the proposal
|
||||
// acceptable.
|
||||
media_type requestedType = format->type;
|
||||
*format = fPreferredFormat;
|
||||
|
||||
// raw audio or wildcard type, either is okay by us
|
||||
if (requestedType != B_MEDIA_UNKNOWN_TYPE
|
||||
&& requestedType != B_MEDIA_RAW_AUDIO) {
|
||||
// Raw audio or wildcard type, either is okay by us. If the format is
|
||||
// anything else, overwrite it with our preferred format. Also, we only support
|
||||
// floating point audio in the host native byte order at the moment.
|
||||
if ((format->type != B_MEDIA_UNKNOWN_TYPE
|
||||
&& format->type != B_MEDIA_RAW_AUDIO)
|
||||
|| (format->u.raw_audio.format
|
||||
!= media_raw_audio_format::wildcard.format
|
||||
&& format->u.raw_audio.format
|
||||
!= fPreferredFormat.u.raw_audio.format)
|
||||
|| (format->u.raw_audio.byte_order
|
||||
!= media_raw_audio_format::wildcard.byte_order
|
||||
&& format->u.raw_audio.byte_order
|
||||
!= fPreferredFormat.u.raw_audio.byte_order)) {
|
||||
TRACE(" -> B_MEDIA_BAD_FORMAT\n");
|
||||
*format = fPreferredFormat;
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
|
||||
format->type = B_MEDIA_RAW_AUDIO;
|
||||
format->u.raw_audio.format = fPreferredFormat.u.raw_audio.format;
|
||||
format->u.raw_audio.byte_order = fPreferredFormat.u.raw_audio.byte_order;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -235,13 +243,10 @@ AudioProducer::FormatChangeRequested(const media_source& source,
|
||||
return B_MEDIA_BAD_SOURCE;
|
||||
}
|
||||
|
||||
fOutput.format = *ioFormat;
|
||||
|
||||
// notify our audio supplier of the format change
|
||||
if (fSupplier)
|
||||
fSupplier->SetFormat(fOutput.format);
|
||||
// TODO: Maybe we are supposed to specialize here only and not actually change yet?
|
||||
// status_t ret = _SpecializeFormat(ioFormat);
|
||||
|
||||
return _AllocateBuffers(ioFormat);
|
||||
return ChangeFormat(ioFormat);
|
||||
}
|
||||
|
||||
|
||||
@@ -333,52 +338,19 @@ AudioProducer::PrepareToConnect(const media_source& what,
|
||||
return B_MEDIA_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
// the format may not yet be fully specialized (the consumer might have
|
||||
// passed back some wildcards). Finish specializing it now, and return an
|
||||
// error if we don't support the requested format.
|
||||
if (format->type != B_MEDIA_RAW_AUDIO) {
|
||||
TRACE(" -> B_MEDIA_BAD_FORMAT\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
// TODO: we might want to support different audio formats
|
||||
} else if (format->u.raw_audio.format
|
||||
!= fPreferredFormat.u.raw_audio.format) {
|
||||
TRACE(" -> B_MEDIA_BAD_FORMAT\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
|
||||
if (format->u.raw_audio.channel_count
|
||||
== media_raw_audio_format::wildcard.channel_count) {
|
||||
format->u.raw_audio.channel_count = 2;
|
||||
TRACE(" -> adjusting channel count, it was wildcard\n");
|
||||
}
|
||||
if (format->u.raw_audio.frame_rate
|
||||
== media_raw_audio_format::wildcard.frame_rate) {
|
||||
format->u.raw_audio.frame_rate = 44100.0;
|
||||
TRACE(" -> adjusting frame rate, it was wildcard\n");
|
||||
}
|
||||
|
||||
// check the buffer size, which may still be wildcarded
|
||||
if (format->u.raw_audio.buffer_size
|
||||
== media_raw_audio_format::wildcard.buffer_size) {
|
||||
// pick something comfortable to suggest
|
||||
TRACE(" -> adjusting buffer size, it was wildcard\n");
|
||||
|
||||
// NOTE: the (buffer_size * 1000000) needs to be dividable by
|
||||
// format->u.raw_audio.frame_rate! (We assume frame rate is a multiple of
|
||||
// 25, which it usually is.)
|
||||
format->u.raw_audio.buffer_size
|
||||
= uint32(format->u.raw_audio.frame_rate / 25.0)
|
||||
* (format->u.raw_audio.format
|
||||
& media_raw_audio_format::B_AUDIO_SIZE_MASK);
|
||||
|
||||
if (!fLowLatency)
|
||||
format->u.raw_audio.buffer_size *= 3;
|
||||
|
||||
status_t ret = _SpecializeFormat(format);
|
||||
if (ret != B_OK) {
|
||||
TRACE(" -> format error: %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Now reserve the connection, and return information about it
|
||||
fOutput.destination = where;
|
||||
fOutput.format = *format;
|
||||
|
||||
if (fSupplier != NULL)
|
||||
fSupplier->SetFormat(fOutput.format);
|
||||
|
||||
*_source = fOutput.source;
|
||||
strncpy(_name, fOutput.name, B_MEDIA_NAME_LENGTH);
|
||||
TRACE(" -> B_OK\n");
|
||||
@@ -479,8 +451,8 @@ AudioProducer::Connect(status_t error, const media_source& source,
|
||||
// us a buffer group (via SetBufferGroup()) prior to this. That can
|
||||
// happen, for example, if the consumer calls SetOutputBuffersFor() on
|
||||
// us from within its Connected() method.
|
||||
if (!fBufferGroup)
|
||||
_AllocateBuffers(&fOutput.format);
|
||||
if (fBufferGroup == NULL)
|
||||
_AllocateBuffers(fOutput.format);
|
||||
|
||||
TRACE("AudioProducer::Connect() done\n");
|
||||
}
|
||||
@@ -615,7 +587,7 @@ void
|
||||
AudioProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
|
||||
bool realTimeEvent)
|
||||
{
|
||||
TRACE("%p->AudioProducer::HandleEvent()\n", this);
|
||||
TRACE_BUFFER("%p->AudioProducer::HandleEvent()\n", this);
|
||||
|
||||
switch (event->type) {
|
||||
case BTimedEventQueue::B_START:
|
||||
@@ -639,7 +611,7 @@ printf("B_START: start time: %lld\n", fStartTime);
|
||||
break;
|
||||
|
||||
case BTimedEventQueue::B_HANDLE_BUFFER: {
|
||||
TRACE("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n");
|
||||
TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n");
|
||||
if ((RunState() == BMediaEventLooper::B_STARTED)
|
||||
&& (fOutput.destination != media_destination::null)) {
|
||||
BBuffer* buffer = _FillNextBuffer(event->event_time);
|
||||
@@ -665,9 +637,9 @@ printf("B_START: start time: %lld\n", fStartTime);
|
||||
BTimedEventQueue::B_HANDLE_BUFFER);
|
||||
EventQueue()->AddEvent(nextBufferEvent);
|
||||
} else {
|
||||
fprintf(stderr, "B_HANDLE_BUFFER, but not started!\n");
|
||||
ERROR("B_HANDLE_BUFFER, but not started!\n");
|
||||
}
|
||||
TRACE("AudioProducer::HandleEvent(B_HANDLE_BUFFER) done\n");
|
||||
TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER) done\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -676,15 +648,6 @@ printf("B_START: start time: %lld\n", fStartTime);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioProducer::SetRunning(bool running)
|
||||
{
|
||||
TRACE("%p->AudioProducer::SetRunning(%d)\n", this, running);
|
||||
|
||||
fRunning = running;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioProducer::SetPeakListener(BHandler* handler)
|
||||
{
|
||||
@@ -692,11 +655,104 @@ AudioProducer::SetPeakListener(BHandler* handler)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AudioProducer::ChangeFormat(media_format* format)
|
||||
{
|
||||
TRACE("AudioProducer::ChangeFormat()\n");
|
||||
|
||||
format->u.raw_audio.buffer_size = media_raw_audio_format::wildcard.buffer_size;
|
||||
|
||||
status_t ret = _SpecializeFormat(format);
|
||||
if (ret != B_OK) {
|
||||
TRACE(" _SpecializeFormat(): %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = BBufferProducer::ProposeFormatChange(format, fOutput.destination);
|
||||
if (ret != B_OK) {
|
||||
TRACE(" ProposeFormatChange(): %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination, format);
|
||||
if (ret != B_OK) {
|
||||
TRACE(" ChangeFormat(): %s\n", strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return _ChangeFormat(*format);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
AudioProducer::_AllocateBuffers(media_format* format)
|
||||
AudioProducer::_SpecializeFormat(media_format* format)
|
||||
{
|
||||
// the format may not yet be fully specialized (the consumer might have
|
||||
// passed back some wildcards). Finish specializing it now, and return an
|
||||
// error if we don't support the requested format.
|
||||
if (format->type != B_MEDIA_RAW_AUDIO) {
|
||||
TRACE(" not raw audio\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
// TODO: we might want to support different audio formats
|
||||
} else if (format->u.raw_audio.format
|
||||
!= fPreferredFormat.u.raw_audio.format) {
|
||||
TRACE(" format does not match\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
|
||||
if (format->u.raw_audio.channel_count
|
||||
== media_raw_audio_format::wildcard.channel_count) {
|
||||
format->u.raw_audio.channel_count = 2;
|
||||
TRACE(" -> adjusting channel count, it was wildcard\n");
|
||||
}
|
||||
|
||||
if (format->u.raw_audio.frame_rate
|
||||
== media_raw_audio_format::wildcard.frame_rate) {
|
||||
format->u.raw_audio.frame_rate = 44100.0;
|
||||
TRACE(" -> adjusting frame rate, it was wildcard\n");
|
||||
}
|
||||
|
||||
// check the buffer size, which may still be wildcarded
|
||||
if (format->u.raw_audio.buffer_size
|
||||
== media_raw_audio_format::wildcard.buffer_size) {
|
||||
// pick something comfortable to suggest
|
||||
TRACE(" -> adjusting buffer size, it was wildcard\n");
|
||||
|
||||
// NOTE: the (buffer_size * 1000000) needs to be dividable by
|
||||
// format->u.raw_audio.frame_rate! (We assume frame rate is a multiple of
|
||||
// 25, which it usually is.)
|
||||
format->u.raw_audio.buffer_size
|
||||
= uint32(format->u.raw_audio.frame_rate / 25.0)
|
||||
* (format->u.raw_audio.format
|
||||
& media_raw_audio_format::B_AUDIO_SIZE_MASK);
|
||||
|
||||
if (!fLowLatency)
|
||||
format->u.raw_audio.buffer_size *= 3;
|
||||
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AudioProducer::_ChangeFormat(const media_format& format)
|
||||
{
|
||||
fOutput.format = format;
|
||||
|
||||
// notify our audio supplier of the format change
|
||||
if (fSupplier)
|
||||
fSupplier->SetFormat(format);
|
||||
|
||||
return _AllocateBuffers(format);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AudioProducer::_AllocateBuffers(const media_format& format)
|
||||
{
|
||||
TRACE("%p->AudioProducer::_AllocateBuffers()\n", this);
|
||||
|
||||
@@ -704,7 +760,7 @@ AudioProducer::_AllocateBuffers(media_format* format)
|
||||
delete fBufferGroup;
|
||||
fBufferGroup = NULL;
|
||||
}
|
||||
size_t size = format->u.raw_audio.buffer_size;
|
||||
size_t size = format.u.raw_audio.buffer_size;
|
||||
int32 bufferDuration = BufferDuration();
|
||||
int32 count = 0;
|
||||
if (bufferDuration > 0) {
|
||||
|
||||
@@ -98,13 +98,15 @@ public:
|
||||
bigtime_t lateness,
|
||||
bool realTimeEvent = false);
|
||||
|
||||
void SetRunning(bool running);
|
||||
|
||||
// AudioProducer
|
||||
void SetPeakListener(BHandler* handler);
|
||||
|
||||
status_t ChangeFormat(media_format* format);
|
||||
|
||||
private:
|
||||
status_t _AllocateBuffers(media_format* format);
|
||||
status_t _SpecializeFormat(media_format* format);
|
||||
status_t _ChangeFormat(const media_format& format);
|
||||
status_t _AllocateBuffers(const media_format& format);
|
||||
BBuffer* _FillNextBuffer(bigtime_t eventTime);
|
||||
|
||||
void _FillSampleBuffer(float* data,
|
||||
@@ -123,7 +125,6 @@ private:
|
||||
bigtime_t fStartTime;
|
||||
|
||||
AudioSupplier* fSupplier;
|
||||
volatile bool fRunning;
|
||||
|
||||
BHandler* fPeakListener;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user