BMediaRecorder: fix a few issues, fix style, remove unused SoundUtils
* Use the preferred time source (GetTimeSource) for the node * Fix node releasing when creating the connection fails * Add virtual slots and padding * Refactor _Connect method
This commit is contained in:
@@ -6,16 +6,31 @@
|
|||||||
#define _MEDIA_RECORDER_H
|
#define _MEDIA_RECORDER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <MediaDefs.h>
|
||||||
#include <MediaNode.h>
|
#include <MediaNode.h>
|
||||||
#include <TimeSource.h>
|
|
||||||
|
|
||||||
#include "MediaRecorderNode.h"
|
|
||||||
#include "SoundUtils.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
|
|
||||||
|
class BMediaRecorderNode;
|
||||||
|
|
||||||
class BMediaRecorder {
|
class BMediaRecorder {
|
||||||
|
public:
|
||||||
|
enum notification {
|
||||||
|
B_WILL_START = 1, // performance_time
|
||||||
|
B_WILL_STOP, // performance_time immediate
|
||||||
|
B_WILL_SEEK, // performance_time media_time
|
||||||
|
B_WILL_TIMEWARP, // real_time performance_time
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*ProcessFunc)(void* cookie,
|
||||||
|
bigtime_t timestamp, void* data,
|
||||||
|
size_t size, const media_format& format);
|
||||||
|
|
||||||
|
typedef void (*NotifyFunc)(void* cookie,
|
||||||
|
notification what, ...);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BMediaRecorder(const char* name,
|
BMediaRecorder(const char* name,
|
||||||
media_type type
|
media_type type
|
||||||
@@ -25,14 +40,6 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
typedef void (*ProcessFunc)(void* cookie,
|
|
||||||
bigtime_t timestamp, void* data,
|
|
||||||
size_t datasize,
|
|
||||||
const media_format& format);
|
|
||||||
|
|
||||||
typedef void (*NotifyFunc)(void* cookie,
|
|
||||||
int32 code, ...);
|
|
||||||
|
|
||||||
status_t SetHooks(ProcessFunc recordFunc = NULL,
|
status_t SetHooks(ProcessFunc recordFunc = NULL,
|
||||||
NotifyFunc notifyFunc = NULL,
|
NotifyFunc notifyFunc = NULL,
|
||||||
void* cookie = NULL);
|
void* cookie = NULL);
|
||||||
@@ -43,17 +50,14 @@ public:
|
|||||||
virtual status_t Start(bool force = false);
|
virtual status_t Start(bool force = false);
|
||||||
virtual status_t Stop(bool force = false);
|
virtual status_t Stop(bool force = false);
|
||||||
|
|
||||||
virtual status_t Connect(const media_format& format,
|
virtual status_t Connect(const media_format& format);
|
||||||
uint32 flags = 0);
|
|
||||||
|
|
||||||
virtual status_t Connect(const dormant_node_info& dormantInfo,
|
virtual status_t Connect(const dormant_node_info& dormantInfo,
|
||||||
const media_format* format = NULL,
|
const media_format& format);
|
||||||
uint32 flags = 0);
|
|
||||||
|
|
||||||
virtual status_t Connect(const media_node& node,
|
virtual status_t Connect(const media_node& node,
|
||||||
const media_output* useOutput = NULL,
|
const media_output* output = NULL,
|
||||||
const media_format* format = NULL,
|
const media_format* format = NULL);
|
||||||
uint32 flags = 0);
|
|
||||||
|
|
||||||
virtual status_t Disconnect();
|
virtual status_t Disconnect();
|
||||||
|
|
||||||
@@ -67,37 +71,42 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void BufferReceived(void* buffer,
|
virtual void BufferReceived(void* buffer, size_t size,
|
||||||
size_t size,
|
|
||||||
const media_header& header);
|
const media_header& header);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
status_t _Connect(
|
status_t _Connect(const media_node& mediaNode,
|
||||||
const media_format* format,
|
const media_output* output,
|
||||||
uint32 flags,
|
const media_format& format);
|
||||||
const dormant_node_info* dormantNode,
|
|
||||||
const media_node* mediaNode,
|
|
||||||
const media_output* output);
|
|
||||||
|
|
||||||
status_t fInitErr;
|
virtual void _ReservedMediaRecorder0();
|
||||||
|
virtual void _ReservedMediaRecorder1();
|
||||||
|
virtual void _ReservedMediaRecorder2();
|
||||||
|
virtual void _ReservedMediaRecorder3();
|
||||||
|
virtual void _ReservedMediaRecorder4();
|
||||||
|
virtual void _ReservedMediaRecorder5();
|
||||||
|
virtual void _ReservedMediaRecorder6();
|
||||||
|
virtual void _ReservedMediaRecorder7();
|
||||||
|
|
||||||
bool fConnected;
|
status_t fInitErr;
|
||||||
bool fRunning;
|
|
||||||
|
|
||||||
BTimeSource* fTimeSource;
|
bool fConnected;
|
||||||
|
bool fRunning;
|
||||||
|
bool fReleaseOutputNode;
|
||||||
|
|
||||||
ProcessFunc fRecordHook;
|
ProcessFunc fRecordHook;
|
||||||
NotifyFunc fNotifyHook;
|
NotifyFunc fNotifyHook;
|
||||||
|
|
||||||
media_node fOutputNode;
|
media_node fOutputNode;
|
||||||
media_output fOutput;
|
media_output fOutput;
|
||||||
|
|
||||||
BMediaRecorderNode* fNode;
|
BMediaRecorderNode* fNode;
|
||||||
media_input fInput;
|
media_input fInput;
|
||||||
|
|
||||||
void* fBufferCookie;
|
void* fBufferCookie;
|
||||||
|
uint32 fPadding[32];
|
||||||
|
|
||||||
friend class BMediaRecorderNode;
|
friend class BMediaRecorderNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999, Be Incorporated
|
|
||||||
* Copyright 2014, Dario Casalinuovo
|
* Copyright 2014, Dario Casalinuovo
|
||||||
|
* Copyright 1999, Be Incorporated
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* This file may be used under the terms of the Be Sample Code License.
|
* This file may be used under the terms of the Be Sample Code License.
|
||||||
*/
|
*/
|
||||||
@@ -76,27 +76,23 @@ protected:
|
|||||||
virtual void BufferReceived(BBuffer* buffer);
|
virtual void BufferReceived(BBuffer* buffer);
|
||||||
|
|
||||||
virtual void ProducerDataStatus(
|
virtual void ProducerDataStatus(
|
||||||
const media_destination& forWhom,
|
const media_destination& destination,
|
||||||
int32 status,
|
int32 status,
|
||||||
bigtime_t performanceTime);
|
bigtime_t performanceTime);
|
||||||
|
|
||||||
virtual status_t GetLatencyFor(
|
virtual status_t GetLatencyFor(const media_destination& destination,
|
||||||
const media_destination& forWhom,
|
bigtime_t* outLatency,
|
||||||
bigtime_t* outLatency,
|
media_node_id* outTimesource);
|
||||||
media_node_id* outTimesource);
|
|
||||||
|
|
||||||
virtual status_t Connected(
|
virtual status_t Connected(const media_source& producer,
|
||||||
const media_source& producer,
|
|
||||||
const media_destination& where,
|
const media_destination& where,
|
||||||
const media_format& withFormat,
|
const media_format& format,
|
||||||
media_input* outInput);
|
media_input* outInput);
|
||||||
|
|
||||||
virtual void Disconnected(
|
virtual void Disconnected(const media_source& producer,
|
||||||
const media_source& producer,
|
|
||||||
const media_destination& where);
|
const media_destination& where);
|
||||||
|
|
||||||
virtual status_t FormatChanged(
|
virtual status_t FormatChanged(const media_source& producer,
|
||||||
const media_source& producer,
|
|
||||||
const media_destination& consumer,
|
const media_destination& consumer,
|
||||||
int32 tag,
|
int32 tag,
|
||||||
const media_format& format);
|
const media_format& format);
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
/
|
|
||||||
/ File: SoundUtils.h
|
|
||||||
/
|
|
||||||
/ Description: Utility functions for handling audio data.
|
|
||||||
/
|
|
||||||
/ Copyright 1998-1999, Be Incorporated, All Rights Reserved
|
|
||||||
/
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#if ! defined( _SoundUtils_h )
|
|
||||||
#define _SoundUtils_h
|
|
||||||
|
|
||||||
#include <MediaDefs.h>
|
|
||||||
|
|
||||||
// Simple helper functions that come in handy when doing
|
|
||||||
// buffer calculations.
|
|
||||||
double us_to_s(bigtime_t usecs);
|
|
||||||
bigtime_t s_to_us(double secs);
|
|
||||||
|
|
||||||
int bytes_per_frame(const media_raw_audio_format & format);
|
|
||||||
int frames_per_buffer(const media_raw_audio_format & format);
|
|
||||||
bigtime_t buffer_duration(const media_raw_audio_format & format);
|
|
||||||
bigtime_t frames_duration(const media_raw_audio_format & format,
|
|
||||||
int64 num_frames);
|
|
||||||
int64 frames_for_duration(const media_raw_audio_format & format,
|
|
||||||
bigtime_t duration);
|
|
||||||
int buffers_for_duration(const media_raw_audio_format & format,
|
|
||||||
bigtime_t duration);
|
|
||||||
|
|
||||||
// This is a common hook function interface for
|
|
||||||
// SoundConsumer and SoundProducer to use.
|
|
||||||
typedef void (*SoundProcessFunc)(void * cookie,
|
|
||||||
bigtime_t timestamp, void * data, size_t datasize,
|
|
||||||
const media_raw_audio_format & format);
|
|
||||||
typedef void (*SoundNotifyFunc)(void * cookie,
|
|
||||||
int32 code, ...);
|
|
||||||
|
|
||||||
// These are special codes that we use in the Notify
|
|
||||||
// function hook.
|
|
||||||
enum {
|
|
||||||
B_WILL_START = 1, // performance_time
|
|
||||||
B_WILL_STOP, // performance_time immediate
|
|
||||||
B_WILL_SEEK, // performance_time media_time
|
|
||||||
B_WILL_TIMEWARP, // real_time performance_time
|
|
||||||
B_CONNECTED, // name (char*)
|
|
||||||
B_DISCONNECTED, //
|
|
||||||
B_FORMAT_CHANGED, // media_raw_audio_format*
|
|
||||||
B_NODE_DIES, // node will die!
|
|
||||||
B_HOOKS_CHANGED, //
|
|
||||||
B_OP_TIMED_OUT, // timeout that expired -- Consumer only
|
|
||||||
B_PRODUCER_DATA_STATUS, // status performance_time -- Consumer only
|
|
||||||
B_LATE_NOTICE // how_much performance_time -- Producer only
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _SoundUtils_h */
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Jérôme Duval. All rights reserved.
|
|
||||||
* Copyright 2014, Dario Casalinuovo. All rights reserved.
|
* Copyright 2014, Dario Casalinuovo. All rights reserved.
|
||||||
|
* Copyright 2005, Jérôme Duval. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
* Inspired by SoundCapture from Be newsletter (Media Kit Basics:
|
||||||
@@ -43,7 +43,6 @@
|
|||||||
#include <TimeSource.h>
|
#include <TimeSource.h>
|
||||||
#include <NodeInfo.h>
|
#include <NodeInfo.h>
|
||||||
|
|
||||||
#include "SoundUtils.h"
|
|
||||||
#include "RecorderWindow.h"
|
#include "RecorderWindow.h"
|
||||||
#include "FileUtils.h"
|
#include "FileUtils.h"
|
||||||
|
|
||||||
@@ -1224,9 +1223,10 @@ RecorderWindow::RecordFile(void* cookie, bigtime_t timestamp,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RecorderWindow::NotifyRecordFile(void * cookie, int32 code, ...)
|
RecorderWindow::NotifyRecordFile(void * cookie,
|
||||||
|
BMediaRecorder::notification code, ...)
|
||||||
{
|
{
|
||||||
if ((code == B_WILL_STOP) || (code == B_NODE_DIES)) {
|
if (code == BMediaRecorder::B_WILL_STOP) {
|
||||||
RecorderWindow * window = (RecorderWindow *)cookie;
|
RecorderWindow * window = (RecorderWindow *)cookie;
|
||||||
// Tell the window we've stopped, if it doesn't
|
// Tell the window we've stopped, if it doesn't
|
||||||
// already know.
|
// already know.
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ private:
|
|||||||
void ErrorAlert(const char * action, status_t err);
|
void ErrorAlert(const char * action, status_t err);
|
||||||
|
|
||||||
static void RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t size, const media_format & format);
|
static void RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t size, const media_format & format);
|
||||||
static void NotifyRecordFile(void * cookie, int32 code, ...);
|
static void NotifyRecordFile(void * cookie, BMediaRecorder::notification code, ...);
|
||||||
|
|
||||||
static void PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format);
|
static void PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format);
|
||||||
static void NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...);
|
static void NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
# Private Media Kit
|
# Private Media Kit
|
||||||
!missing_symbols.cpp
|
!missing_symbols.cpp
|
||||||
MediaRecorder.cpp
|
MediaRecorder.cpp
|
||||||
MediaRecorderNode.cpp
|
|
||||||
|
|
||||||
# Public Media Kit
|
# Public Media Kit
|
||||||
Buffer.cpp
|
Buffer.cpp
|
||||||
@@ -58,6 +57,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
DefaultMediaTheme.cpp
|
DefaultMediaTheme.cpp
|
||||||
DormantNodeManager.cpp
|
DormantNodeManager.cpp
|
||||||
FormatManager.cpp
|
FormatManager.cpp
|
||||||
|
MediaRecorderNode.cpp
|
||||||
Notifications.cpp
|
Notifications.cpp
|
||||||
request_data.cpp
|
request_data.cpp
|
||||||
SharedBufferList.cpp
|
SharedBufferList.cpp
|
||||||
@@ -66,7 +66,6 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
TimeSourceObject.cpp
|
TimeSourceObject.cpp
|
||||||
TimeSourceObjectManager.cpp
|
TimeSourceObjectManager.cpp
|
||||||
SoundPlayNode.cpp
|
SoundPlayNode.cpp
|
||||||
SoundUtils.cpp
|
|
||||||
|
|
||||||
# Old (R3) Media Kit (built only for GCC2)
|
# Old (R3) Media Kit (built only for GCC2)
|
||||||
OldAudioModule.cpp
|
OldAudioModule.cpp
|
||||||
|
|||||||
@@ -1,51 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999, Be Incorporated
|
* Copyright 2015, Hamish Morrison <[email protected]>
|
||||||
* Copyright 2014, Dario Casalinuovo
|
* Copyright 2014, Dario Casalinuovo
|
||||||
|
* Copyright 1999, Be Incorporated
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* This file may be used under the terms of the Be Sample Code License.
|
* This file may be used under the terms of the Be Sample Code License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "MediaRecorder.h"
|
#include <MediaRecorder.h>
|
||||||
|
|
||||||
#include <MediaAddOn.h>
|
#include <MediaAddOn.h>
|
||||||
#include <MediaRoster.h>
|
#include <MediaRoster.h>
|
||||||
#include <TimeSource.h>
|
#include <TimeSource.h>
|
||||||
|
|
||||||
#include "MediaDebug.h"
|
#include <MediaDebug.h>
|
||||||
#include "MediaRecorderNode.h"
|
#include <MediaRecorderNode.h>
|
||||||
|
|
||||||
|
|
||||||
class MediaNodeReleaser {
|
|
||||||
public:
|
|
||||||
MediaNodeReleaser(media_node& mediaNode,
|
|
||||||
bool release = true)
|
|
||||||
:
|
|
||||||
fNode(mediaNode),
|
|
||||||
fRelease(release)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~MediaNodeReleaser()
|
|
||||||
{
|
|
||||||
if (fRelease)
|
|
||||||
BMediaRoster::Roster()->ReleaseNode(fNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTo(media_node& node)
|
|
||||||
{
|
|
||||||
fNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetRelease(bool release)
|
|
||||||
{
|
|
||||||
fRelease = release;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
media_node& fNode;
|
|
||||||
bool fRelease;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BMediaRecorder::BMediaRecorder(const char* name, media_type type)
|
BMediaRecorder::BMediaRecorder(const char* name, media_type type)
|
||||||
@@ -53,7 +22,7 @@ BMediaRecorder::BMediaRecorder(const char* name, media_type type)
|
|||||||
fInitErr(B_OK),
|
fInitErr(B_OK),
|
||||||
fConnected(false),
|
fConnected(false),
|
||||||
fRunning(false),
|
fRunning(false),
|
||||||
fTimeSource(NULL),
|
fReleaseOutputNode(false),
|
||||||
fRecordHook(NULL),
|
fRecordHook(NULL),
|
||||||
fNotifyHook(NULL),
|
fNotifyHook(NULL),
|
||||||
fNode(NULL),
|
fNode(NULL),
|
||||||
@@ -64,7 +33,10 @@ BMediaRecorder::BMediaRecorder(const char* name, media_type type)
|
|||||||
BMediaRoster::Roster(&fInitErr);
|
BMediaRoster::Roster(&fInitErr);
|
||||||
|
|
||||||
if (fInitErr == B_OK) {
|
if (fInitErr == B_OK) {
|
||||||
fNode = new BMediaRecorderNode(name, this, type);
|
fNode = new(std::nothrow) BMediaRecorderNode(name, this, type);
|
||||||
|
if (fNode == NULL)
|
||||||
|
fInitErr = B_NO_MEMORY;
|
||||||
|
|
||||||
fInitErr = BMediaRoster::CurrentRoster()->RegisterNode(fNode);
|
fInitErr = BMediaRoster::CurrentRoster()->RegisterNode(fNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,10 +51,6 @@ BMediaRecorder::~BMediaRecorder()
|
|||||||
Disconnect();
|
Disconnect();
|
||||||
fNode->Release();
|
fNode->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fTimeSource != NULL)
|
|
||||||
fTimeSource->Release();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -132,7 +100,7 @@ BMediaRecorder::BufferReceived(void* buffer, size_t size,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRecorder::Connect(const media_format& format, uint32 flags)
|
BMediaRecorder::Connect(const media_format& format)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
@@ -142,13 +110,42 @@ BMediaRecorder::Connect(const media_format& format, uint32 flags)
|
|||||||
if (fConnected)
|
if (fConnected)
|
||||||
return B_MEDIA_ALREADY_CONNECTED;
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
|
||||||
return _Connect(&format, flags, NULL, NULL, NULL);
|
status_t err = B_OK;
|
||||||
|
media_node node;
|
||||||
|
|
||||||
|
switch (format.type) {
|
||||||
|
// switch on format for default
|
||||||
|
case B_MEDIA_RAW_AUDIO:
|
||||||
|
err = BMediaRoster::Roster()->GetAudioMixer(&node);
|
||||||
|
break;
|
||||||
|
case B_MEDIA_RAW_VIDEO:
|
||||||
|
case B_MEDIA_ENCODED_VIDEO:
|
||||||
|
err = BMediaRoster::Roster()->GetVideoInput(&node);
|
||||||
|
break;
|
||||||
|
// give up?
|
||||||
|
default:
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
fReleaseOutputNode = true;
|
||||||
|
|
||||||
|
err = _Connect(node, NULL, format);
|
||||||
|
|
||||||
|
if (err != B_OK) {
|
||||||
|
BMediaRoster::Roster()->ReleaseNode(node);
|
||||||
|
fReleaseOutputNode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRecorder::Connect(const dormant_node_info& dormantInfo,
|
BMediaRecorder::Connect(const dormant_node_info& dormantNode,
|
||||||
const media_format* format, uint32 flags)
|
const media_format& format)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
@@ -158,14 +155,29 @@ BMediaRecorder::Connect(const dormant_node_info& dormantInfo,
|
|||||||
if (fConnected)
|
if (fConnected)
|
||||||
return B_MEDIA_ALREADY_CONNECTED;
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
|
||||||
return _Connect(format, flags, &dormantInfo, NULL, NULL);
|
media_node node;
|
||||||
|
status_t err = BMediaRoster::Roster()->InstantiateDormantNode(dormantNode,
|
||||||
|
&node, B_FLAVOR_IS_GLOBAL);
|
||||||
|
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
fReleaseOutputNode = true;
|
||||||
|
|
||||||
|
err = _Connect(node, NULL, format);
|
||||||
|
|
||||||
|
if (err != B_OK) {
|
||||||
|
BMediaRoster::Roster()->ReleaseNode(node);
|
||||||
|
fReleaseOutputNode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRecorder::Connect(const media_node& node,
|
BMediaRecorder::Connect(const media_node& node,
|
||||||
const media_output* useOutput, const media_format* format,
|
const media_output* output, const media_format* format)
|
||||||
uint32 flags)
|
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
@@ -175,7 +187,10 @@ BMediaRecorder::Connect(const media_node& node,
|
|||||||
if (fConnected)
|
if (fConnected)
|
||||||
return B_MEDIA_ALREADY_CONNECTED;
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
|
||||||
return _Connect(format, flags, NULL, &node, useOutput);
|
if (format == NULL && output != NULL)
|
||||||
|
format = &output->format;
|
||||||
|
|
||||||
|
return _Connect(node, output, *format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -206,11 +221,9 @@ BMediaRecorder::Disconnect()
|
|||||||
fOutputNode.node, fOutput.source,
|
fOutputNode.node, fOutput.source,
|
||||||
fNode->Node().node, fInput.destination);
|
fNode->Node().node, fInput.destination);
|
||||||
|
|
||||||
BMediaRoster::Roster()->ReleaseNode(fOutputNode);
|
if (fReleaseOutputNode) {
|
||||||
|
BMediaRoster::Roster()->ReleaseNode(fOutputNode);
|
||||||
if (fTimeSource != NULL) {
|
fReleaseOutputNode = false;
|
||||||
fTimeSource->Release();
|
|
||||||
fTimeSource = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fConnected = false;
|
fConnected = false;
|
||||||
@@ -240,12 +253,12 @@ BMediaRecorder::Start(bool force)
|
|||||||
// start node here
|
// start node here
|
||||||
status_t err = B_OK;
|
status_t err = B_OK;
|
||||||
|
|
||||||
if (fNode->Node().kind & B_TIME_SOURCE)
|
if ((fOutputNode.kind & B_TIME_SOURCE) != 0)
|
||||||
err = BMediaRoster::CurrentRoster()->StartTimeSource(
|
err = BMediaRoster::CurrentRoster()->StartTimeSource(
|
||||||
fOutputNode, BTimeSource::RealTime());
|
fOutputNode, BTimeSource::RealTime());
|
||||||
else
|
else
|
||||||
err = BMediaRoster::CurrentRoster()->StartNode(
|
err = BMediaRoster::CurrentRoster()->StartNode(
|
||||||
fOutputNode, fTimeSource->Now());
|
fOutputNode, fNode->TimeSource()->Now());
|
||||||
|
|
||||||
// then un-mute it
|
// then un-mute it
|
||||||
if (err == B_OK) {
|
if (err == B_OK) {
|
||||||
@@ -327,99 +340,42 @@ BMediaRecorder::Format() const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRecorder::_Connect(const media_format* format,
|
BMediaRecorder::_Connect(const media_node& node,
|
||||||
uint32 flags, const dormant_node_info* dormantNode,
|
const media_output* output, const media_format& format)
|
||||||
const media_node* mediaNode, const media_output* output)
|
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
status_t err = B_OK;
|
status_t err = B_OK;
|
||||||
media_format ourFormat;
|
media_format ourFormat = format;
|
||||||
media_node node;
|
|
||||||
MediaNodeReleaser away(node, false);
|
|
||||||
media_output ourOutput;
|
media_output ourOutput;
|
||||||
|
|
||||||
// argument checking and set-up
|
|
||||||
if (format != NULL)
|
|
||||||
ourFormat = *format;
|
|
||||||
|
|
||||||
if (fNode == NULL)
|
if (fNode == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
if (mediaNode == NULL && output != NULL)
|
|
||||||
return B_MISMATCHED_VALUES;
|
|
||||||
|
|
||||||
if (dormantNode != NULL && (mediaNode != NULL || output != NULL))
|
|
||||||
return B_MISMATCHED_VALUES;
|
|
||||||
|
|
||||||
if (format == NULL && output != NULL)
|
|
||||||
ourFormat = output->format;
|
|
||||||
|
|
||||||
fNode->SetAcceptedFormat(ourFormat);
|
fNode->SetAcceptedFormat(ourFormat);
|
||||||
|
|
||||||
// figure out the node to instantiate
|
|
||||||
if (dormantNode != NULL) {
|
|
||||||
|
|
||||||
err = BMediaRoster::Roster()->InstantiateDormantNode(
|
|
||||||
*dormantNode, &node, B_FLAVOR_IS_GLOBAL);
|
|
||||||
|
|
||||||
away.SetRelease(true);
|
|
||||||
|
|
||||||
} else if (mediaNode != NULL) {
|
|
||||||
node = *mediaNode;
|
|
||||||
} else {
|
|
||||||
switch (ourFormat.type) {
|
|
||||||
|
|
||||||
// switch on format for default
|
|
||||||
case B_MEDIA_RAW_AUDIO:
|
|
||||||
err = BMediaRoster::Roster()->GetAudioInput(&node);
|
|
||||||
away.SetRelease(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_MEDIA_RAW_VIDEO:
|
|
||||||
case B_MEDIA_ENCODED_VIDEO:
|
|
||||||
err = BMediaRoster::Roster()->GetVideoInput(&node);
|
|
||||||
away.SetRelease(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// give up?
|
|
||||||
default:
|
|
||||||
return B_MEDIA_BAD_FORMAT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fOutputNode = node;
|
fOutputNode = node;
|
||||||
|
|
||||||
// figure out the output provided
|
// figure out the output provided
|
||||||
|
|
||||||
if (output != NULL) {
|
if (output != NULL) {
|
||||||
ourOutput = *output;
|
ourOutput = *output;
|
||||||
} else if (err == B_OK) {
|
} else if (err == B_OK) {
|
||||||
|
|
||||||
media_output outputs[10];
|
media_output outputs[10];
|
||||||
int32 count = 10;
|
int32 count = 10;
|
||||||
|
|
||||||
err = BMediaRoster::Roster()->GetFreeOutputsFor(node,
|
err = BMediaRoster::Roster()->GetFreeOutputsFor(fOutputNode,
|
||||||
outputs, count, &count, ourFormat.type);
|
outputs, count, &count, ourFormat.type);
|
||||||
|
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = B_MEDIA_BAD_SOURCE;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (format_is_compatible(outputs[i].format, ourFormat)) {
|
if (format_is_compatible(outputs[i].format, ourFormat)) {
|
||||||
ourOutput = outputs[i];
|
ourOutput = outputs[i];
|
||||||
err = B_OK;
|
|
||||||
ourFormat = outputs[i].format;
|
ourFormat = outputs[i].format;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ourOutput.source == media_source::null)
|
if (ourOutput.source == media_source::null)
|
||||||
@@ -427,30 +383,26 @@ BMediaRecorder::_Connect(const media_format* format,
|
|||||||
|
|
||||||
// find our Node's free input
|
// find our Node's free input
|
||||||
media_input ourInput;
|
media_input ourInput;
|
||||||
|
|
||||||
err = fNode->GetInput(&ourInput);
|
err = fNode->GetInput(&ourInput);
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
media_node time_source;
|
media_node timeSource;
|
||||||
if (node.kind & B_TIME_SOURCE)
|
if ((node.kind & B_TIME_SOURCE) != 0)
|
||||||
time_source = node;
|
timeSource = node;
|
||||||
else
|
else
|
||||||
BMediaRoster::Roster()->GetSystemTimeSource(&time_source);
|
BMediaRoster::Roster()->GetTimeSource(&timeSource);
|
||||||
|
|
||||||
// set time source
|
// set time source
|
||||||
BMediaRoster::Roster()->SetTimeSourceFor(
|
err = BMediaRoster::Roster()->SetTimeSourceFor(fNode->Node().node,
|
||||||
fNode->Node().node, time_source.node);
|
timeSource.node);
|
||||||
|
|
||||||
fTimeSource = BMediaRoster::CurrentRoster()->MakeTimeSourceFor(
|
|
||||||
fNode->Node());
|
|
||||||
|
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
// start the recorder node (it's always running)
|
// start the recorder node (it's always running)
|
||||||
err = BMediaRoster::CurrentRoster()->StartNode(
|
err = BMediaRoster::CurrentRoster()->StartNode(fOutputNode,
|
||||||
fOutputNode, fTimeSource->Now());
|
fNode->TimeSource()->Now());
|
||||||
|
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
@@ -467,7 +419,16 @@ BMediaRecorder::_Connect(const media_format* format,
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
fConnected = true;
|
fConnected = true;
|
||||||
away.SetRelease(false);
|
return B_OK;
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder0() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder1() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder2() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder3() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder4() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder5() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder6() { }
|
||||||
|
void BMediaRecorder::_ReservedMediaRecorder7() { }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999, Be Incorporated
|
|
||||||
* Copyright 2014, Dario Casalinuovo
|
* Copyright 2014, Dario Casalinuovo
|
||||||
|
* Copyright 1999, Be Incorporated
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* This file may be used under the terms of the Be Sample Code License.
|
* This file may be used under the terms of the Be Sample Code License.
|
||||||
*/
|
*/
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
#include <TimedEventQueue.h>
|
#include <TimedEventQueue.h>
|
||||||
#include <TimeSource.h>
|
#include <TimeSource.h>
|
||||||
|
|
||||||
#include "MediaDebug.h"
|
#include <MediaDebug.h>
|
||||||
#include "MediaRecorder.h"
|
#include <MediaRecorder.h>
|
||||||
|
|
||||||
|
|
||||||
BMediaRecorderNode::BMediaRecorderNode(const char* name,
|
BMediaRecorderNode::BMediaRecorderNode(const char* name,
|
||||||
@@ -146,7 +146,7 @@ BMediaRecorderNode::Start(bigtime_t performanceTime)
|
|||||||
|
|
||||||
if (fRecorder->fNotifyHook)
|
if (fRecorder->fNotifyHook)
|
||||||
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
||||||
B_WILL_START, performanceTime);
|
BMediaRecorder::B_WILL_START, performanceTime);
|
||||||
|
|
||||||
fRecorder->fRunning = true;
|
fRecorder->fRunning = true;
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ BMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate)
|
|||||||
|
|
||||||
if (fRecorder->fNotifyHook)
|
if (fRecorder->fNotifyHook)
|
||||||
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
||||||
B_WILL_STOP, performanceTime, immediate);
|
BMediaRecorder::B_WILL_STOP, performanceTime, immediate);
|
||||||
|
|
||||||
fRecorder->fRunning = false;
|
fRecorder->fRunning = false;
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ BMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
|
|||||||
|
|
||||||
if (fRecorder->fNotifyHook)
|
if (fRecorder->fNotifyHook)
|
||||||
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
||||||
B_WILL_SEEK, performanceTime, mediaTime);
|
BMediaRecorder::B_WILL_SEEK, performanceTime, mediaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ BMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime)
|
|||||||
// at them, so we can ignore the time warp as a consumer.
|
// at them, so we can ignore the time warp as a consumer.
|
||||||
if (fRecorder->fNotifyHook)
|
if (fRecorder->fNotifyHook)
|
||||||
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
||||||
B_WILL_TIMEWARP, realTime, performanceTime);
|
BMediaRecorder::B_WILL_TIMEWARP, realTime, performanceTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
/
|
|
||||||
/ File: SoundUtils.cpp
|
|
||||||
/
|
|
||||||
/ Description: Utility functions for handling audio data.
|
|
||||||
/
|
|
||||||
/ Copyright 1998-1999, Be Incorporated, All Rights Reserved
|
|
||||||
/
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "SoundUtils.h"
|
|
||||||
|
|
||||||
// These two conversions seem to pop up all the time in media code.
|
|
||||||
// I guess it's the curse of microsecond resolution... ;-)
|
|
||||||
double
|
|
||||||
us_to_s(bigtime_t usecs)
|
|
||||||
{
|
|
||||||
return (usecs / 1000000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bigtime_t
|
|
||||||
s_to_us(double secs)
|
|
||||||
{
|
|
||||||
return (bigtime_t) (secs * 1000000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
bytes_per_frame(
|
|
||||||
const media_raw_audio_format & format)
|
|
||||||
{
|
|
||||||
// The media_raw_audio_format format constants encode the
|
|
||||||
// bytes-per-sample value in the low nybble. Having a fixed
|
|
||||||
// number of bytes-per-sample, and no inter-sample relationships,
|
|
||||||
// is what makes a format "raw".
|
|
||||||
int bytesPerSample = format.format & 0xf;
|
|
||||||
return bytesPerSample * format.channel_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
frames_per_buffer(
|
|
||||||
const media_raw_audio_format & format)
|
|
||||||
{
|
|
||||||
// This will give us the number of full-sized frames that will fit
|
|
||||||
// in a buffer. (Remember, integer division automatically rounds
|
|
||||||
// down.)
|
|
||||||
int frames = 0;
|
|
||||||
if (bytes_per_frame(format) > 0) {
|
|
||||||
frames = format.buffer_size / bytes_per_frame(format);
|
|
||||||
}
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
bigtime_t
|
|
||||||
buffer_duration(
|
|
||||||
const media_raw_audio_format & format)
|
|
||||||
{
|
|
||||||
// Figuring out duration is easy. We take extra precaution to
|
|
||||||
// not divide by zero or return irrelevant results.
|
|
||||||
bigtime_t duration = 0;
|
|
||||||
if (format.buffer_size > 0 && format.frame_rate > 0
|
|
||||||
&& bytes_per_frame(format) > 0) {
|
|
||||||
// In these kinds of calculations, it's always useful to double-check
|
|
||||||
// the unit conversions. (Anyone remember high school physics?)
|
|
||||||
// bytes/(bytes/frame) / frames/sec
|
|
||||||
// = frames * sec/frames
|
|
||||||
// = secs which is what we want.
|
|
||||||
duration = s_to_us((format.buffer_size / bytes_per_frame(format))
|
|
||||||
/ format.frame_rate);
|
|
||||||
}
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
bigtime_t
|
|
||||||
frames_duration(
|
|
||||||
const media_raw_audio_format & format, int64 num_frames)
|
|
||||||
{
|
|
||||||
// Tells us how long in us it will take to produce num_frames,
|
|
||||||
// with the given format.
|
|
||||||
bigtime_t duration = 0;
|
|
||||||
if (format.frame_rate > 0) {
|
|
||||||
duration = s_to_us(num_frames/format.frame_rate);
|
|
||||||
}
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
buffers_for_duration(
|
|
||||||
const media_raw_audio_format & format, bigtime_t duration)
|
|
||||||
{
|
|
||||||
// Double-checking those unit conversions again:
|
|
||||||
// secs * ( (frames/sec) / (frames/buffer) ) = secs * (buffers/sec)
|
|
||||||
// = buffers
|
|
||||||
int buffers = 0;
|
|
||||||
if (frames_per_buffer(format) > 0) {
|
|
||||||
buffers = (int) ceil(us_to_s(duration)
|
|
||||||
*(format.frame_rate/frames_per_buffer(format)));
|
|
||||||
}
|
|
||||||
return buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64
|
|
||||||
frames_for_duration(
|
|
||||||
const media_raw_audio_format & format, bigtime_t duration)
|
|
||||||
{
|
|
||||||
return (int64) ceil(format.frame_rate*us_to_s(duration));
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user