initial commit. can be instantiated in cortex and can connected to the reader node.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1039 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shatty 2002-09-14 13:51:27 +00:00
parent 8cd0aa93ba
commit 389207789b
5 changed files with 1911 additions and 0 deletions

View File

@ -0,0 +1,10 @@
SubDir OBOS_TOP src add-ons media media-add-ons writer ;
UsePrivateHeaders media ;
Addon writer.media_addon : media :
MediaWriter.cpp
MediaWriterAddOn.cpp
;
LinkSharedOSLibs writer.media_addon : be media ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,365 @@
// MediaWriter.h
//
// Andrew Bachmann, 2002
//
// A MediaWriter is a node that
// implements FileInterface and BBufferConsumer.
// It consumes on input, which is a multistream,
// and writes the stream to a file. It has a rather
// unique interpretation of time. Time is
// distance in the file. So the duration is the
// file length. (in bytes)
#if !defined(_MEDIA_WRITER_H)
#define _MEDIA_WRITER_H
#include <MediaDefs.h>
#include <MediaNode.h>
#include <FileInterface.h>
#include <BufferConsumer.h>
#include <Controllable.h>
#include <MediaEventLooper.h>
#include <File.h>
#include <Entry.h>
#include <BufferGroup.h>
class MediaWriter :
public BFileInterface,
public BBufferConsumer,
public BControllable,
public BMediaEventLooper
{
protected:
virtual ~MediaWriter(void);
public:
explicit MediaWriter(
size_t defaultChunkSize = 8192, // chunk size = 8 KB
float defaultBitRate = 800000, // bit rate = 100.000 KB/sec = 5.85 MB/minute
const flavor_info * info = 0, // buffer period = 80 milliseconds
BMessage * config = 0,
BMediaAddOn * addOn = 0);
virtual status_t InitCheck(void) const;
// see BMediaAddOn::GetConfigurationFor
virtual status_t GetConfigurationFor(
BMessage * into_message);
/*************************/
/* begin from BMediaNode */
public:
// /* this port is what a media node listens to for commands */
// virtual port_id ControlPort(void) const;
virtual BMediaAddOn* AddOn(
int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */
protected:
/* These don't return errors; instead, they use the global error condition reporter. */
/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
/* and is recommended to allow for at least one pending command of each type. */
/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
/* cannot depend on that happening. */
virtual void Start(
bigtime_t performance_time);
virtual void Stop(
bigtime_t performance_time,
bool immediate);
virtual void Seek(
bigtime_t media_time,
bigtime_t performance_time);
virtual void SetRunMode(
run_mode mode);
virtual void TimeWarp(
bigtime_t at_real_time,
bigtime_t to_performance_time);
virtual void Preroll(void);
virtual void SetTimeSource(
BTimeSource * time_source);
public:
virtual status_t HandleMessage(
int32 message,
const void * data,
size_t size);
protected:
/* Called when requests have completed, or failed. */
virtual status_t RequestCompleted( /* reserved 0 */
const media_request_info & info);
protected:
virtual status_t DeleteHook(BMediaNode * node); /* reserved 1 */
virtual void NodeRegistered(void); /* reserved 2 */
public:
/* fill out your attributes in the provided array, returning however many you have. */
virtual status_t GetNodeAttributes( /* reserved 3 */
media_node_attribute * outAttributes,
size_t inMaxCount);
virtual status_t AddTimer(
bigtime_t at_performance_time,
int32 cookie);
/* end from BMediaNode */
/***********************/
protected:
virtual BParameterWeb * MakeParameterWeb(void);
/*****************************/
/* begin from BFileInterface */
protected:
//included from BMediaNode
//virtual status_t HandleMessage(
// int32 message,
// const void * data,
// size_t size);
virtual status_t GetNextFileFormat(
int32 * cookie,
media_file_format * out_format);
virtual void DisposeFileFormatCookie(
int32 cookie);
virtual status_t GetDuration(
bigtime_t * out_time);
virtual status_t SniffRef(
const entry_ref & file,
char * out_mime_type, /* 256 bytes */
float * out_quality);
virtual status_t SetRef(
const entry_ref & file,
bool create,
bigtime_t * out_time);
virtual status_t GetRef(
entry_ref * out_ref,
char * out_mime_type);
/* end from BFileInterface */
/***************************/
// provided for BMediaWriterAddOn
public:
static status_t StaticSniffRef(
const entry_ref & file,
char * out_mime_type, /* 256 bytes */
float * out_quality);
/******************************/
/* begin from BBufferConsumer */
//included from BMediaAddOn
//virtual status_t HandleMessage(
// int32 message,
// const void * data,
// size_t size);
/* Someone, probably the producer, is asking you about this format. Give */
/* your honest opinion, possibly modifying *format. Do not ask upstream */
/* producer about the format, since he's synchronously waiting for your */
/* reply. */
virtual status_t AcceptFormat(
const media_destination & dest,
media_format * format);
virtual status_t GetNextInput(
int32 * cookie,
media_input * out_input);
virtual void DisposeInputCookie(
int32 cookie);
virtual void BufferReceived(
BBuffer * buffer);
virtual void ProducerDataStatus(
const media_destination & for_whom,
int32 status,
bigtime_t at_performance_time);
virtual status_t GetLatencyFor(
const media_destination & for_whom,
bigtime_t * out_latency,
media_node_id * out_timesource);
virtual status_t Connected(
const media_source & producer, /* here's a good place to request buffer group usage */
const media_destination & where,
const media_format & with_format,
media_input * out_input);
virtual void Disconnected(
const media_source & producer,
const media_destination & where);
/* The notification comes from the upstream producer, so he's already cool with */
/* the format; you should not ask him about it in here. */
virtual status_t FormatChanged(
const media_source & producer,
const media_destination & consumer,
int32 change_tag,
const media_format & format);
/* Given a performance time of some previous buffer, retrieve the remembered tag */
/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
/* idea being that flags can be added later, and the understood flags returned in */
/* *out_flags. */
virtual status_t SeekTagRequested(
const media_destination & destination,
bigtime_t in_target_time,
uint32 in_flags,
media_seek_tag * out_seek_tag,
bigtime_t * out_tagged_time,
uint32 * out_flags);
/* end from BBufferConsumer */
/****************************/
/****************************/
/* begin from BControllable */
//included from BMediaNode
//virtual status_t HandleMessage(
// int32 message,
// const void * data,
// size_t size);
public:
/* These are alternate methods of accomplishing the same thing as */
/* connecting to control information source/destinations would. */
virtual status_t GetParameterValue(
int32 id,
bigtime_t * last_change,
void * value,
size_t * ioSize);
virtual void SetParameterValue(
int32 id,
bigtime_t when,
const void * value,
size_t size);
virtual status_t StartControlPanel(
BMessenger * out_messenger);
/* end from BControllable */
/**************************/
public:
// these three are related:
// DEFAULT_CHUNK_SIZE = (DEFAULT_BIT_RATE * 1024) * (DEFAULT_BUFFER_PERIOD / 8000000)
static const int32 DEFAULT_CHUNK_SIZE_PARAM; // in bytes
static const int32 DEFAULT_BIT_RATE_PARAM; // in 1000*kilobits/sec
static const int32 DEFAULT_BUFFER_PERIOD_PARAM; // milliseconds
private:
size_t defaultChunkSizeParam;
bigtime_t defaultChunkSizeParamChangeTime;
float defaultBitRateParam;
bigtime_t defaultBitRateParamChangeTime;
bigtime_t defaultBufferPeriodParam;
bigtime_t defaultBufferPeriodParamChangeTime;
// This is used to figure out which parameter to compute
// when enforcing the above constraint relating the three params
int32 lastUpdatedParameter;
int32 leastRecentlyUpdatedParameter;
/********************************/
/* start from BMediaEventLooper */
protected:
/* you must override to handle your events! */
/* you should not call HandleEvent directly */
virtual void HandleEvent( const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
/* override to clean up custom events you have added to your queue */
virtual void CleanUpEvent(const media_timed_event *event);
/* called from Offline mode to determine the current time of the node */
/* update your internal information whenever it changes */
virtual bigtime_t OfflineTime();
/* override only if you know what you are doing! */
/* otherwise much badness could occur */
/* the actual control loop function: */
/* waits for messages, Pops events off the queue and calls DispatchEvent */
virtual void ControlLoop();
/* end from BMediaEventLooper */
/******************************/
protected:
virtual status_t HandleBuffer(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual status_t HandleParameter(
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
public:
static status_t GetFlavor(int32 id, const flavor_info ** out_info);
static media_format & GetFormat();
static media_file_format & GetFileFormat();
protected:
virtual status_t ResetFormat(media_format * format);
virtual status_t ResolveWildcards(media_multistream_format * multistream_format);
virtual status_t GetFilledBuffer(BBuffer ** outBuffer);
virtual status_t FillFileBuffer(BBuffer * buffer);
private:
MediaWriter( /* private unimplemented */
const MediaWriter & clone);
MediaWriter & operator=(
const MediaWriter & clone);
status_t initCheckStatus;
BMediaAddOn * mediaWriterAddOn;
media_input input;
BFile * outputFile;
entry_ref output_ref;
char output_mime_type[B_MIME_TYPE_LENGTH+1];
BBufferGroup * bufferGroup;
bigtime_t downstreamLatency;
bigtime_t internalLatency;
bool intputEnabled;
// this is computed from the real (negotiated) chunk size and bit rate,
// not the defaults that are in the parameters
bigtime_t bufferPeriod;
/* Mmmh, stuffing! */
virtual status_t _Reserved_MediaWriter_0(void *);
virtual status_t _Reserved_MediaWriter_1(void *);
virtual status_t _Reserved_MediaWriter_2(void *);
virtual status_t _Reserved_MediaWriter_3(void *);
virtual status_t _Reserved_MediaWriter_4(void *);
virtual status_t _Reserved_MediaWriter_5(void *);
virtual status_t _Reserved_MediaWriter_6(void *);
virtual status_t _Reserved_MediaWriter_7(void *);
virtual status_t _Reserved_MediaWriter_8(void *);
virtual status_t _Reserved_MediaWriter_9(void *);
virtual status_t _Reserved_MediaWriter_10(void *);
virtual status_t _Reserved_MediaWriter_11(void *);
virtual status_t _Reserved_MediaWriter_12(void *);
virtual status_t _Reserved_MediaWriter_13(void *);
virtual status_t _Reserved_MediaWriter_14(void *);
virtual status_t _Reserved_MediaWriter_15(void *);
uint32 _reserved_media_writer_[16];
};
#endif /* _MEDIA_WRITER_H */

View File

@ -0,0 +1,268 @@
// MediaWriterAddOn.cpp
//
// Andrew Bachmann, 2002
//
// A MediaWriterAddOn is an add-on
// that can make MediaWriter nodes
//
// MediaWriter nodes write a multistream into a file
#include <MediaDefs.h>
#include <MediaAddOn.h>
#include <Errors.h>
#include <Node.h>
#include <Mime.h>
#include <StorageDefs.h>
#include "MediaWriter.h"
#include "MediaWriterAddOn.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
// instantiation function
extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
return new MediaWriterAddOn(image);
}
// -------------------------------------------------------- //
// ctor/dtor
// -------------------------------------------------------- //
MediaWriterAddOn::~MediaWriterAddOn()
{
}
MediaWriterAddOn::MediaWriterAddOn(image_id image) :
BMediaAddOn(image)
{
fprintf(stderr,"MediaWriterAddOn::MediaWriterAddOn\n");
refCount = 0;
}
// -------------------------------------------------------- //
// BMediaAddOn impl
// -------------------------------------------------------- //
status_t MediaWriterAddOn::InitCheck(
const char ** out_failure_text)
{
fprintf(stderr,"MediaWriterAddOn::InitCheck\n");
return B_OK;
}
int32 MediaWriterAddOn::CountFlavors()
{
fprintf(stderr,"MediaWriterAddOn::CountFlavors\n");
return 1;
}
status_t MediaWriterAddOn::GetFlavorAt(
int32 n,
const flavor_info ** out_info)
{
fprintf(stderr,"MediaWriterAddOn::GetFlavorAt\n");
if (out_info == 0) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
if (n != 0) {
fprintf(stderr,"<- B_BAD_INDEX\n");
return B_BAD_INDEX;
}
return MediaWriter::GetFlavor(n,out_info);
}
BMediaNode * MediaWriterAddOn::InstantiateNodeFor(
const flavor_info * info,
BMessage * config,
status_t * out_error)
{
fprintf(stderr,"MediaWriterAddOn::InstantiateNodeFor\n");
if (out_error == 0) {
fprintf(stderr,"<- NULL\n");
return 0; // we refuse to crash because you were stupid
}
size_t defaultChunkSize = size_t(8192); // XXX: read from add-on's attributes
float defaultBitRate = 800000;
MediaWriter * node = new MediaWriter(defaultChunkSize,
defaultBitRate,
info,config,this);
if (node == 0) {
*out_error = B_NO_MEMORY;
fprintf(stderr,"<- B_NO_MEMORY\n");
} else {
*out_error = node->InitCheck();
}
return node;
}
status_t MediaWriterAddOn::GetConfigurationFor(
BMediaNode * your_node,
BMessage * into_message)
{
fprintf(stderr,"MediaWriterAddOn::GetConfigurationFor\n");
if (into_message == 0) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
MediaWriter * node = dynamic_cast<MediaWriter*>(your_node);
if (node == 0) {
fprintf(stderr,"<- B_BAD_TYPE\n");
return B_BAD_TYPE;
}
return node->GetConfigurationFor(into_message);
}
bool MediaWriterAddOn::WantsAutoStart()
{
fprintf(stderr,"MediaWriterAddOn::WantsAutoStart\n");
return false;
}
status_t MediaWriterAddOn::AutoStart(
int in_count,
BMediaNode ** out_node,
int32 * out_internal_id,
bool * out_has_more)
{
fprintf(stderr,"MediaWriterAddOn::AutoStart\n");
return B_OK;
}
// -------------------------------------------------------- //
// BMediaAddOn impl for B_FILE_INTERFACE nodes
// -------------------------------------------------------- //
status_t MediaWriterAddOn::SniffRef(
const entry_ref & file,
BMimeType * io_mime_type,
float * out_quality,
int32 * out_internal_id)
{
fprintf(stderr,"MediaWriterAddOn::SniffRef\n");
if ((io_mime_type == 0) || (out_quality == 0) || (out_internal_id == 0)) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
*out_internal_id = 0; // only one flavor
char mime_string[B_MIME_TYPE_LENGTH+1];
status_t status = MediaWriter::StaticSniffRef(file,mime_string,out_quality);
io_mime_type->SetTo(mime_string);
return status;
}
// even though I implemented SniffTypeKind below and this shouldn't get called,
// I am going to implement it anyway. I'll use it later anyhow.
status_t MediaWriterAddOn::SniffType(
const BMimeType & type,
float * out_quality,
int32 * out_internal_id)
{
fprintf(stderr,"MediaWriterAddOn::SniffType\n");
if ((out_quality == 0) || (out_internal_id == 0)) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
*out_quality = 1.0;
*out_internal_id = 0;
return B_OK;
}
// This function treats null pointers slightly differently than the others.
// This is because a program could reasonably call this function with just
// about any junk, get the out_read_items and then use that to create an
// array of sufficient size to hold the result, and then recall. Also, a
// stupid program could not supply an out_read_items, but actually supply
// an out_readable_formats and then try to do something useful with it. As
// an extreme gesture of nicety we will fill the out_readable_formats with
// a valid entry, although they could easily read into garbage after that...
status_t MediaWriterAddOn::GetFileFormatList(
int32 flavor_id,
media_file_format * out_writable_formats,
int32 in_write_items,
int32 * out_write_items,
media_file_format * out_readable_formats,
int32 in_read_items,
int32 * out_read_items,
void * _reserved)
{
fprintf(stderr,"MediaWriterAddOn::GetFileFormatList\n");
if (flavor_id != 0) {
// this is a sanity check for now
fprintf(stderr,"<- B_BAD_INDEX\n");
return B_BAD_INDEX;
}
// see null check comment above
if (out_write_items != 0) {
*out_write_items = 0;
}
// see null check comment above
if (out_read_items != 0) {
*out_read_items = 1;
}
// see null check comment above
if (out_readable_formats != 0) {
// don't go off the end
if (in_read_items > 0) {
out_readable_formats[0] = MediaWriter::GetFileFormat();
}
}
return B_OK;
}
status_t MediaWriterAddOn::SniffTypeKind(
const BMimeType & type,
uint64 in_kinds,
float * out_quality,
int32 * out_internal_id,
void * _reserved)
{
fprintf(stderr,"MediaWriterAddOn::SniffTypeKind\n");
if ((out_quality == 0) || (out_internal_id == 0)) {
fprintf(stderr,"<- B_BAD_VALUE\n");
return B_BAD_VALUE; // we refuse to crash because you were stupid
}
if (in_kinds & (B_BUFFER_CONSUMER | B_FILE_INTERFACE | B_CONTROLLABLE)) {
return SniffType(type,out_quality,out_internal_id);
} else {
// They asked for some kind we don't supply. We set the output
// just in case they try to do something with it anyway (!)
*out_quality = 0;
*out_internal_id = -1;
fprintf(stderr,"<- B_BAD_TYPE\n");
return B_BAD_TYPE;
}
}
// -------------------------------------------------------- //
// stuffing
// -------------------------------------------------------- //
int main(int argc, char *argv[])
{
}
// -------------------------------------------------------- //
// stuffing
// -------------------------------------------------------- //
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_0(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_1(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_2(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_3(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_4(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_5(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_6(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_7(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_8(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_9(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_10(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_11(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_12(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_13(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_14(void *) {};
status_t MediaWriterAddOn::_Reserved_MediaWriterAddOn_15(void *) {};

View File

@ -0,0 +1,111 @@
// MediaWriterAddOn.h
//
// Andrew Bachmann, 2002
//
// A MediaWriterAddOn is an add-on
// that can make MediaWriter nodes
//
// MediaWriter nodes write a multistream into a file
#if !defined(_MEDIA_WRITER_ADD_ON_H)
#define _MEDIA_WRITER_ADD_ON_H
#include <MediaDefs.h>
#include <MediaAddOn.h>
class MediaWriterAddOn :
public BMediaAddOn
{
public:
virtual ~MediaWriterAddOn(void);
explicit MediaWriterAddOn(image_id image);
/**************************/
/* begin from BMediaAddOn */
public:
virtual status_t InitCheck(
const char ** out_failure_text);
virtual int32 CountFlavors(void);
virtual status_t GetFlavorAt(
int32 n,
const flavor_info ** out_info);
virtual BMediaNode * InstantiateNodeFor(
const flavor_info * info,
BMessage * config,
status_t * out_error);
virtual status_t GetConfigurationFor(
BMediaNode * your_node,
BMessage * into_message);
virtual bool WantsAutoStart(void);
virtual status_t AutoStart(
int in_count,
BMediaNode ** out_node,
int32 * out_internal_id,
bool * out_has_more);
/* only implement if you have a B_FILE_INTERFACE node */
virtual status_t SniffRef(
const entry_ref & file,
BMimeType * io_mime_type,
float * out_quality,
int32 * out_internal_id);
virtual status_t SniffType( // This is broken if you deal with producers
const BMimeType & type, // and consumers both. Use SniffTypeKind instead.
float * out_quality, // If you implement SniffTypeKind, this doesn't
int32 * out_internal_id); // get called.
virtual status_t GetFileFormatList(
int32 flavor_id, // for this node flavor (if it matters)
media_file_format * out_writable_formats, // don't write here if NULL
int32 in_write_items, // this many slots in out_writable_formats
int32 * out_write_items, // set this to actual # available, even if bigger than in count
media_file_format * out_readable_formats, // don't write here if NULL
int32 in_read_items, // this many slots in out_readable_formats
int32 * out_read_items, // set this to actual # available, even if bigger than in count
void * _reserved); // ignore until further notice
virtual status_t SniffTypeKind( // Like SniffType, but for the specific kind(s)
const BMimeType & type,
uint64 in_kinds,
float * out_quality,
int32 * out_internal_id,
void * _reserved);
/* end from BMediaAddOn */
/************************/
private:
MediaWriterAddOn( /* private unimplemented */
const MediaWriterAddOn & clone);
MediaWriterAddOn & operator=(
const MediaWriterAddOn & clone);
int32 refCount;
/* Mmmh, stuffing! */
virtual status_t _Reserved_MediaWriterAddOn_0(void *);
virtual status_t _Reserved_MediaWriterAddOn_1(void *);
virtual status_t _Reserved_MediaWriterAddOn_2(void *);
virtual status_t _Reserved_MediaWriterAddOn_3(void *);
virtual status_t _Reserved_MediaWriterAddOn_4(void *);
virtual status_t _Reserved_MediaWriterAddOn_5(void *);
virtual status_t _Reserved_MediaWriterAddOn_6(void *);
virtual status_t _Reserved_MediaWriterAddOn_7(void *);
virtual status_t _Reserved_MediaWriterAddOn_8(void *);
virtual status_t _Reserved_MediaWriterAddOn_9(void *);
virtual status_t _Reserved_MediaWriterAddOn_10(void *);
virtual status_t _Reserved_MediaWriterAddOn_11(void *);
virtual status_t _Reserved_MediaWriterAddOn_12(void *);
virtual status_t _Reserved_MediaWriterAddOn_13(void *);
virtual status_t _Reserved_MediaWriterAddOn_14(void *);
virtual status_t _Reserved_MediaWriterAddOn_15(void *);
uint32 _reserved_media_writer_add_on_[16];
};
#if BUILDING_MEDIA_WRITER__ADD_ON
extern "C" _EXPORT BMediaAddOn * make_media_writer_add_on(image_id you);
#endif
#endif /* _MEDIA_WRITER_ADD_ON_H */