diff --git a/headers/private/media/DecoderPlugin.h b/headers/private/media/DecoderPlugin.h new file mode 100644 index 0000000000..a484d47a86 --- /dev/null +++ b/headers/private/media/DecoderPlugin.h @@ -0,0 +1,43 @@ +#include +#include "MediaPlugin.h" + +namespace BPrivate { namespace media { + +class Decoder +{ +public: + Decoder(); + virtual ~Decoder(); + + // Sniff get's called with the data from Reader::GetStreamInfo + virtual status_t Sniff(media_format *format, void **infoBuffer, int32 *infoSize) = 0; + + virtual status_t GetOutputFormat(media_format *format) = 0; + + virtual status_t Seek(media_seek_type seekTo, + int64 *frame, bigtime_t *time) = 0; + + virtual status_t Decode(void *buffer, int64 *frameCount, + media_header *mediaHeader, media_decode_info *info) = 0; + + status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader); + +private: + void Setup(BMediaTrack *reader); + BMediaTrack * fReader; +}; + + +class DecoderPlugin : public MediaPlugin +{ +public: + virtual Decoder *NewDecoder() = 0; +}; + +MediaPlugin *instantiate_plugin(); + +} } // namespace BPrivate::media + +using namespace BPrivate::media; + diff --git a/headers/private/media/MediaPlugin.h b/headers/private/media/MediaPlugin.h new file mode 100644 index 0000000000..6112195828 --- /dev/null +++ b/headers/private/media/MediaPlugin.h @@ -0,0 +1,18 @@ +#include + +namespace BPrivate { namespace media { + +class MediaPlugin +{ +public: + MediaPlugin(); + virtual ~MediaPlugin(); +}; + +class Decoder; +class Reader; + +} } // namespace BPrivate::media + +using namespace BPrivate::media; + diff --git a/headers/private/media/ReaderPlugin.h b/headers/private/media/ReaderPlugin.h new file mode 100644 index 0000000000..05a6a7fd3c --- /dev/null +++ b/headers/private/media/ReaderPlugin.h @@ -0,0 +1,50 @@ +#include +#include "MediaPlugin.h" + +namespace BPrivate { namespace media { + +class Reader +{ +public: + Reader(); + virtual ~Reader(); + + virtual const char *Copyright() = 0; + + virtual status_t Sniff(int32 *streamCount) = 0; + + virtual status_t AllocateCookie(int32 streamNumber, void **cookie) = 0; + virtual status_t FreeCookie(void *cookie) = 0; + + virtual status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, + media_format *format, void **infoBuffer, int32 *infoSize) = 0; + + virtual status_t Seek(void *cookie, + media_seek_type seekTo, + int64 *frame, bigtime_t *time) = 0; + + virtual status_t GetNextChunk(void *cookie, + void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader) = 0; + + BDataIO * Source(); + +private: + void Setup(BDataIO *source); + + BDataIO * fSource; +}; + + +class ReaderPlugin : public MediaPlugin +{ +public: + virtual Reader *NewReader() = 0; +}; + +MediaPlugin *instantiate_plugin(); + +} } // namespace BPrivate::media + +using namespace BPrivate::media; + diff --git a/src/add-ons/media/Jamfile b/src/add-ons/media/Jamfile index e028c3f91f..ca86b87be0 100644 --- a/src/add-ons/media/Jamfile +++ b/src/add-ons/media/Jamfile @@ -1,3 +1,4 @@ SubDir OBOS_TOP src add-ons media ; SubInclude OBOS_TOP src add-ons media media-add-ons ; +SubInclude OBOS_TOP src add-ons media plugins ; diff --git a/src/add-ons/media/media-add-ons/mixer/MixerInput.h b/src/add-ons/media/media-add-ons/mixer/MixerInput.h index ac0ae1f630..ed81918c22 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.h @@ -116,7 +116,7 @@ MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos, bigtime_t tim if (!fEnabled) return false; -#if 0 +#if 1 if (time < (fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount)) || (time + duration_for_frames(fMixBufferFrameRate, debugMixBufferFrames)) >= fLastDataAvailableTime) ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %Ld to %Ld, reading from %Ld to %Ld\n", diff --git a/src/add-ons/media/plugins/Jamfile b/src/add-ons/media/plugins/Jamfile new file mode 100644 index 0000000000..1fdf676473 --- /dev/null +++ b/src/add-ons/media/plugins/Jamfile @@ -0,0 +1,4 @@ +SubDir OBOS_TOP src add-ons media plugins ; + +SubInclude OBOS_TOP src add-ons media plugins wav_reader ; +SubInclude OBOS_TOP src add-ons media plugins raw_decoder ; diff --git a/src/add-ons/media/plugins/raw_decoder/Jamfile b/src/add-ons/media/plugins/raw_decoder/Jamfile new file mode 100644 index 0000000000..8ba14a5112 --- /dev/null +++ b/src/add-ons/media/plugins/raw_decoder/Jamfile @@ -0,0 +1,9 @@ +SubDir OBOS_TOP src add-ons media plugins raw_decoder ; + +UsePrivateHeaders media ; + +Addon raw_decoder : media plugins : + RawDecoderPlugin.cpp +; + +LinkSharedOSLibs raw_decoder : be libmedia.so ; diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp new file mode 100644 index 0000000000..c09c999c0c --- /dev/null +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp @@ -0,0 +1,65 @@ +#include +#include +#include "RawDecoderPlugin.h" + +#define TRACE_THIS 1 +#if TRACE_THIS + #define TRACE printf +#else + #define TRACE ((void)0) +#endif + +RawDecoder::RawDecoder() +{ +} + +RawDecoder::~RawDecoder() +{ +} + + +status_t +RawDecoder::Sniff(media_format *format, void **infoBuffer, int32 *infoSize) +{ + if (format->type != B_MEDIA_RAW_AUDIO) + return B_ERROR; + + fFormat = *format; + return B_OK; +} + + +status_t +RawDecoder::GetOutputFormat(media_format *format) +{ + *format = fFormat; + return B_OK; +} + +status_t +RawDecoder::Seek(media_seek_type seekTo, + int64 *frame, bigtime_t *time) +{ + return B_OK; +} + + +status_t +RawDecoder::Decode(void *buffer, int64 *frameCount, + media_header *mediaHeader, media_decode_info *info) +{ + return B_OK; +} + + +Decoder * +RawDecoderPlugin::NewDecoder() +{ + return new RawDecoder; +} + + +MediaPlugin *instantiate_plugin() +{ + return new RawDecoderPlugin; +} diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h new file mode 100644 index 0000000000..6cad06540b --- /dev/null +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h @@ -0,0 +1,29 @@ +#include "DecoderPlugin.h" + +class RawDecoder : public Decoder +{ +public: + RawDecoder(); + ~RawDecoder(); + + status_t Sniff(media_format *format, void **infoBuffer, int32 *infoSize); + + status_t GetOutputFormat(media_format *format); + + status_t Seek(media_seek_type seekTo, + int64 *frame, bigtime_t *time); + + status_t Decode(void *buffer, int64 *frameCount, + media_header *mediaHeader, media_decode_info *info); +private: + media_format fFormat; +}; + + +class RawDecoderPlugin : public DecoderPlugin +{ +public: + Decoder *NewDecoder(); +}; + +MediaPlugin *instantiate_plugin(); diff --git a/src/add-ons/media/plugins/wav_reader/Jamfile b/src/add-ons/media/plugins/wav_reader/Jamfile new file mode 100644 index 0000000000..2d6b15625d --- /dev/null +++ b/src/add-ons/media/plugins/wav_reader/Jamfile @@ -0,0 +1,9 @@ +SubDir OBOS_TOP src add-ons media plugins wav_reader ; + +UsePrivateHeaders media ; + +Addon wav_reader : media plugins : + WavReaderPlugin.cpp +; + +LinkSharedOSLibs wav_reader : be libmedia.so ; diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp new file mode 100644 index 0000000000..4810eb7213 --- /dev/null +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include +#include +#include "WavReaderPlugin.h" + +#define TRACE_THIS 1 +#if TRACE_THIS + #define TRACE printf +#else + #define TRACE ((void)0) +#endif + +#define FOURCC(fcc) (*reinterpret_cast(fcc)) + +struct wavdata +{ + uint64 position; + uint64 datasize; + + int32 framesize; + int32 fps; + + void *buffer; + int32 buffersize; + + int64 framecount; + bigtime_t duration; + + media_format format; +}; + +WavReader::WavReader() +{ + TRACE("WavReader::WavReader\n"); + fSource = dynamic_cast(Reader::Source()); +} + +WavReader::~WavReader() +{ +} + +const char * +WavReader::Copyright() +{ + return "WAV reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen"; +} + + +status_t +WavReader::Sniff(int32 *streamCount) +{ + TRACE("WavReader::Sniff\n"); + + fDataSize = Source()->Seek(0, SEEK_END); + if (fDataSize < sizeof(fRawHeader)) { + TRACE("WavReader::Sniff: too small\n"); + return B_ERROR; + } + fDataSize -= sizeof(fRawHeader); + + if (sizeof(fRawHeader) != Source()->ReadAt(0, &fRawHeader, sizeof(fRawHeader))) { + TRACE("WavReader::Sniff: header reading failed\n"); + return B_ERROR; + } + + if (B_LENDIAN_TO_HOST_INT32(fRawHeader.riff.riff_id) != FOURCC("RIFF") + || B_LENDIAN_TO_HOST_INT32(fRawHeader.riff.wave_id) != FOURCC("WAVE") + || B_LENDIAN_TO_HOST_INT32(fRawHeader.format.fourcc) != FOURCC("fmt ") + || B_LENDIAN_TO_HOST_INT32(fRawHeader.data.fourcc) != FOURCC("data")) { + TRACE("WavReader::Sniff: header not recognized\n"); + return B_ERROR; + } + + TRACE("WavReader::Sniff: looks like we found something\n"); + + TRACE(" format_tag 0x%04x\n", B_LENDIAN_TO_HOST_INT16(fRawHeader.common.format_tag)); + TRACE(" channels 0x%04x\n", B_LENDIAN_TO_HOST_INT16(fRawHeader.common.channels)); + TRACE(" samples_per_sec 0x%08lx\n", B_LENDIAN_TO_HOST_INT32(fRawHeader.common.samples_per_sec)); + TRACE(" avg_bytes_per_sec 0x%08lx\n", B_LENDIAN_TO_HOST_INT32(fRawHeader.common.avg_bytes_per_sec)); + TRACE(" block_align 0x%04x\n", B_LENDIAN_TO_HOST_INT16(fRawHeader.common.block_align)); + TRACE(" bits_per_sample 0x%04x\n", B_LENDIAN_TO_HOST_INT16(fRawHeader.common.bits_per_sample)); + TRACE(" format_tag 0x%04x\n", B_LENDIAN_TO_HOST_INT16(fRawHeader.common.format_tag)); + + if (fDataSize > B_LENDIAN_TO_HOST_INT32(fRawHeader.data.len) && fDataSize < 0xffffffff) { + TRACE("WavReader::Sniff: reducing data size from %Ld to %ld\n", + fDataSize, B_LENDIAN_TO_HOST_INT32(fRawHeader.data.len)); + fDataSize = B_LENDIAN_TO_HOST_INT32(fRawHeader.data.len); + } + + TRACE("WavReader::Sniff: data size is %Ld bytes\n", fDataSize); + + *streamCount = 1; + return B_OK; +} + + +status_t +WavReader::AllocateCookie(int32 streamNumber, void **cookie) +{ + TRACE("WavReader::AllocateCookie\n"); + + wavdata *data = new wavdata; + + data->position = 0; + data->datasize = fDataSize; + data->framesize = (B_LENDIAN_TO_HOST_INT16(fRawHeader.common.bits_per_sample) / 8) * B_LENDIAN_TO_HOST_INT16(fRawHeader.common.channels); + data->fps = B_LENDIAN_TO_HOST_INT32(fRawHeader.common.samples_per_sec) / B_LENDIAN_TO_HOST_INT16(fRawHeader.common.channels); + data->buffersize = (65536 / data->framesize) * data->framesize; + data->buffer = malloc(data->buffersize); + data->framecount = fDataSize / data->framesize; + data->duration = (data->framecount * 1000000LL) / data->fps; + + TRACE(" framesize %ld\n", data->framesize); + TRACE(" fps %ld\n", data->fps); + TRACE(" buffersize %ld\n", data->buffersize); + TRACE(" framecount %Ld\n", data->framecount); + TRACE(" duration %Ld\n", data->duration); + + memset(&data->format, 0, sizeof(data->format)); + data->format.type = B_MEDIA_RAW_AUDIO; + data->format.u.raw_audio.frame_rate = data->fps; + data->format.u.raw_audio.channel_count = B_LENDIAN_TO_HOST_INT16(fRawHeader.common.channels); + data->format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; // XXX fixme + data->format.u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN; + data->format.u.raw_audio.buffer_size = data->buffersize; + return B_OK; +} + + +status_t +WavReader::FreeCookie(void *cookie) +{ + TRACE("WavReader::FreeCookie\n"); + wavdata *data = reinterpret_cast(cookie); + + free(data->buffer); + delete data; + + return B_OK; +} + + +status_t +WavReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, + media_format *format, void **infoBuffer, int32 *infoSize) +{ + wavdata *data = reinterpret_cast(cookie); + + *frameCount = data->framecount; + *duration = data->duration; + *format = data->format; + *infoBuffer = 0; + *infoSize = 0; + return B_OK; +} + + +status_t +WavReader::Seek(void *cookie, + media_seek_type seekTo, + int64 *frame, bigtime_t *time) +{ + wavdata *data = reinterpret_cast(cookie); + uint64 pos; + + if (frame) { + pos = *frame * data->framesize; + TRACE("WavReader::Seek to frame %Ld, pos %Ld\n", *frame, pos); + } else if (time) { + pos = (*time * data->fps) / 1000000LL; + TRACE("WavReader::Seek to time %Ld, pos %Ld\n", *time, pos); + *time = (pos * 1000000LL) / data->fps; + TRACE("WavReader::Seek newtime %Ld\n", *time); + } else { + return B_ERROR; + } + + if (pos < 0 || pos > data->datasize) { + TRACE("WavReader::Seek invalid position %Ld\n", pos); + return B_ERROR; + } + + data->position = pos; + return B_OK; +} + + +status_t +WavReader::GetNextChunk(void *cookie, + void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader) +{ + wavdata *data = reinterpret_cast(cookie); + status_t result = B_OK; + + int32 readsize = data->datasize - data->position; + if (readsize > data->buffersize) { + readsize = data->buffersize; + result = B_LAST_BUFFER_ERROR; + } + + if (readsize != Source()->ReadAt(44 + data->position, data->buffer, readsize)) { + TRACE("WavReader::GetNextChunk: unexpected read error\n"); + return B_ERROR; + } + + if (mediaHeader) { + // memset(mediaHeader, 0, sizeof(*mediaHeader)); + // mediaHeader->type = B_MEDIA_RAW_AUDIO; + // mediaHeader->size_used = buffersize; + // mediaHeader->start_time = ((data->position / data->framesize) * 1000000LL) / data->fps; + // mediaHeader->file_pos = 44 + data->position; + } + + data->position += readsize; + *chunkBuffer = data->buffer; + *chunkSize = readsize; + return result; +} + + +Reader * +WavReaderPlugin::NewReader() +{ + return new WavReader; +} + + +MediaPlugin *instantiate_plugin() +{ + return new WavReaderPlugin; +} diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h new file mode 100644 index 0000000000..ed8b9ddd78 --- /dev/null +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h @@ -0,0 +1,43 @@ +#include "ReaderPlugin.h" +#include "wav.h" + +class WavReader : public Reader +{ +public: + WavReader(); + ~WavReader(); + + const char *Copyright(); + + status_t Sniff(int32 *streamCount); + + status_t AllocateCookie(int32 streamNumber, void **cookie); + status_t FreeCookie(void *cookie); + + status_t GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, + media_format *format, void **infoBuffer, int32 *infoSize); + + status_t Seek(void *cookie, + media_seek_type seekTo, + int64 *frame, bigtime_t *time); + + status_t GetNextChunk(void *cookie, + void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader); + + BPositionIO *Source() { return fSource; } + +private: + BPositionIO * fSource; + uint64 fDataSize; + wave_header fRawHeader; +}; + + +class WavReaderPlugin : public ReaderPlugin +{ +public: + Reader *NewReader(); +}; + +MediaPlugin *instantiate_plugin(); diff --git a/src/kernel/core/addons/bus_managers/pci/pci.c b/src/kernel/core/addons/bus_managers/pci/pci.c index b5631c512d..d84d427c9d 100755 --- a/src/kernel/core/addons/bus_managers/pci/pci.c +++ b/src/kernel/core/addons/bus_managers/pci/pci.c @@ -869,6 +869,8 @@ print_pir_table(struct pir_table *tbl) * once we've scanned the bus on the other side of the bridge. See the URL * above for information on why this is done. */ + + /* All PCI buses located behind a PCI-PCI bridge must reside between the seondary bus number and the subordinate bus number (inclusive). */ static void pci_bridge(uint8 bus, uint8 dev, uint8 func) diff --git a/src/kits/media/DecoderPlugin.cpp b/src/kits/media/DecoderPlugin.cpp new file mode 100644 index 0000000000..3d9502a912 --- /dev/null +++ b/src/kits/media/DecoderPlugin.cpp @@ -0,0 +1,22 @@ +#include "DecoderPlugin.h" + +Decoder::Decoder() +{ +} + +Decoder::~Decoder() +{ +} + +status_t +Decoder::GetNextChunk(void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader) +{ + return fReader->ReadChunk((char **)chunkBuffer, chunkSize, mediaHeader); +} + +void +Decoder::Setup(BMediaTrack *reader) +{ + fReader = reader; +} diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index d6f4ec8ec0..0370d6309e 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -68,6 +68,11 @@ SharedLibrary media : OldMediaModule.cpp OldSoundFile.cpp OldSubscriber.cpp + + # Codec Plugin API + MediaPlugin.cpp + ReaderPlugin.cpp + DecoderPlugin.cpp ; LinkSharedOSLibs libmedia.so : diff --git a/src/kits/media/MediaPlugin.cpp b/src/kits/media/MediaPlugin.cpp new file mode 100644 index 0000000000..bb3f246817 --- /dev/null +++ b/src/kits/media/MediaPlugin.cpp @@ -0,0 +1,10 @@ +#include "MediaPlugin.h" + +MediaPlugin::MediaPlugin() +{ +} + +MediaPlugin::~MediaPlugin() +{ +} + diff --git a/src/kits/media/ReaderPlugin.cpp b/src/kits/media/ReaderPlugin.cpp new file mode 100644 index 0000000000..6f17aab365 --- /dev/null +++ b/src/kits/media/ReaderPlugin.cpp @@ -0,0 +1,23 @@ +#include "ReaderPlugin.h" + +Reader::Reader() +{ +} + + +Reader::~Reader() +{ +} + + +BDataIO * +Reader::Source() +{ + return fSource; +} + +void +Reader::Setup(BDataIO *source) +{ + fSource = source; +}