From 07ae6ce8a6c629a078e433febcfb683d09f23a97 Mon Sep 17 00:00:00 2001 From: shatty Date: Sun, 25 Jan 2004 06:04:28 +0000 Subject: [PATCH] ogg pseudo-seeking git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6266 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/media/plugins/ogg/Jamfile | 1 + .../media/plugins/ogg/OggReaderPlugin.cpp | 51 +++- .../media/plugins/ogg/OggReaderPlugin.h | 5 + .../plugins/ogg/OggReaderStreamInterface.h | 7 - src/add-ons/media/plugins/ogg/OggStream.cpp | 77 +++++- src/add-ons/media/plugins/ogg/OggStream.h | 8 + .../media/plugins/ogg/OggVorbisStream.cpp | 10 +- .../media/plugins/speex/speexCodecPlugin.cpp | 13 +- .../plugins/vorbis/vorbisCodecPlugin.cpp | 227 +++++++++++------- .../media/plugins/vorbis/vorbisCodecPlugin.h | 16 +- 10 files changed, 291 insertions(+), 124 deletions(-) delete mode 100644 src/add-ons/media/plugins/ogg/OggReaderStreamInterface.h diff --git a/src/add-ons/media/plugins/ogg/Jamfile b/src/add-ons/media/plugins/ogg/Jamfile index 2fe2abc21e..e2a5260c9c 100644 --- a/src/add-ons/media/plugins/ogg/Jamfile +++ b/src/add-ons/media/plugins/ogg/Jamfile @@ -5,6 +5,7 @@ UsePrivateHeaders media ; SubDirHdrs [ FDirName $(SUBDIR) libogg ] ; Addon ogg : media plugins : + OggFrameInfo.cpp OggReaderPlugin.cpp OggStream.cpp OggSpeexStream.cpp diff --git a/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp b/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp index 535312ddb3..a5732defbb 100644 --- a/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp +++ b/src/add-ons/media/plugins/ogg/OggReaderPlugin.cpp @@ -130,6 +130,10 @@ retry: } while (ogg_page_serialno(&next_page) != serialno); return B_OK; } + virtual status_t GetPageAt(off_t position, ogg_stream_state * stream, + int read_size = 4*B_PAGE_SIZE) { + return reader->GetPageAt(position,stream,read_size); + } }; fStreams[serialno] = OggStream::makeOggStream(new Interface(this, serialno), serialno, packet); fCookies.push_back(fStreams[serialno]); @@ -138,6 +142,51 @@ retry: } +status_t +OggReader::GetPageAt(off_t position, ogg_stream_state * stream, int read_size) +{ + if (!fSeekable) { + return B_ERROR; + } + ogg_sync_state sync; + ogg_sync_init(&sync); + ogg_page page; + int result; + while ((result = ogg_sync_pageout(&sync,&page)) == 0) { + char * buffer = ogg_sync_buffer(&sync,read_size); + ssize_t bytes = fSeekable->ReadAt(position,buffer,read_size); + position += read_size; + if (bytes == 0) { + TRACE("OggReader::GetPage: Read: no data\n"); + return B_LAST_BUFFER_ERROR; + } + if (bytes < 0) { + TRACE("OggReader::GetPage: Read: error\n"); + return bytes; + } + if (ogg_sync_wrote(&sync,bytes) != 0) { + TRACE("OggReader::GetPage: ogg_sync_wrote failed?: error\n"); + return B_ERROR; + } + } + if (result == -1) { + TRACE("OggReader::GetPageAt: ogg_sync_pageout: not synced??\n"); + return B_ERROR; + } +#ifdef STRICT_OGG + if (ogg_page_version(page) != 0) { + TRACE("OggReader::GetPageAt: ogg_page_version: error in page encoding??\n"); + return B_ERROR; + } +#endif + if (ogg_stream_pagein(stream, &page) != 0) { + TRACE("oggReader::GetPageAt: ogg_stream_pagein: failed??\n"); + return B_ERROR; + } + ogg_sync_clear(&sync); + return B_OK; +} + static BPositionIO * get_seekable(BDataIO * data) { @@ -283,7 +332,7 @@ OggReader::GetNextChunk(void *cookie, void **chunkBuffer, int32 *chunkSize, media_header *mediaHeader) { - TRACE("OggReader::GetNextChunk\n"); +// TRACE("OggReader::GetNextChunk\n"); OggStream * stream = static_cast(cookie); return stream->GetNextChunk(chunkBuffer,chunkSize,mediaHeader); } diff --git a/src/add-ons/media/plugins/ogg/OggReaderPlugin.h b/src/add-ons/media/plugins/ogg/OggReaderPlugin.h index a6a830c0db..4ad48fb155 100644 --- a/src/add-ons/media/plugins/ogg/OggReaderPlugin.h +++ b/src/add-ons/media/plugins/ogg/OggReaderPlugin.h @@ -39,8 +39,11 @@ public: media_header *mediaHeader); protected: + // called by OggStream through GetPageInterface status_t GetPage(ogg_page * page, int read_size = 4*B_PAGE_SIZE, bool short_page = false); + status_t GetPageAt(off_t position, ogg_stream_state * stream, + int read_size = 4*B_PAGE_SIZE); ogg_sync_state fSync; serialno_OggStream_map fStreams; @@ -51,6 +54,8 @@ private: class GetPageInterface { public: virtual status_t GetNextPage() = 0; + virtual status_t GetPageAt(off_t position, ogg_stream_state * stream, + int read_size = 4*B_PAGE_SIZE) = 0; }; }; diff --git a/src/add-ons/media/plugins/ogg/OggReaderStreamInterface.h b/src/add-ons/media/plugins/ogg/OggReaderStreamInterface.h deleted file mode 100644 index 75077fadf3..0000000000 --- a/src/add-ons/media/plugins/ogg/OggReaderStreamInterface.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _OGG_READER_STREAM_INTERFACE_H_ -#define _OGG_READER_STREAM_INTERFACE_H_ - -#include - - -#endif // _OGG_READER_STREAM_INTERFACE_H_ diff --git a/src/add-ons/media/plugins/ogg/OggStream.cpp b/src/add-ons/media/plugins/ogg/OggStream.cpp index 4bde687df5..ada707195e 100644 --- a/src/add-ons/media/plugins/ogg/OggStream.cpp +++ b/src/add-ons/media/plugins/ogg/OggStream.cpp @@ -57,13 +57,19 @@ OggStream::OggStream(long serialno) { TRACE("OggStream::OggStream\n"); this->fSerialno = serialno; + fCurrentFrame = 0; + fCurrentTime = 0; ogg_stream_init(&fStreamState,serialno); + fCurrentPage = 0; + fCurrentPacket = 0; + ogg_stream_init(&fSeekStreamState,serialno); } OggStream::~OggStream() { - + ogg_stream_clear(&fStreamState); + ogg_stream_clear(&fSeekStreamState); } @@ -142,7 +148,40 @@ OggStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration, status_t OggStream::Seek(uint32 seekTo, int64 *frame, bigtime_t *time) { - debugger("OggStream::Seek"); + TRACE("OggStream::Seek to %lld : %lld\n",*frame,*time); + if (seekTo & B_MEDIA_SEEK_TO_FRAME) { + *frame = max_c(0, *frame); // clip to zero + *frame = min_c(*frame, fOggFrameInfos.size()-1); // clip to max + // input the page into a temporary seek stream + ogg_stream_state seekStreamState; + uint pageno = fOggFrameInfos[*frame].GetPage(); + off_t position = fPagePositions[pageno]; + ogg_stream_init(&seekStreamState, fSerialno); + status_t result = fReaderInterface->GetPageAt(position, &seekStreamState); + if (result != B_OK) { + return result; // pageno/fPagePosition corrupted? + } + // discard earlier packets from this page + uint packetno = fOggFrameInfos[*frame].GetPacket(); + while (packetno-- > 0) { + ogg_packet packet; + if (ogg_stream_packetout(&fSeekStreamState, &packet) != 1) { + return B_ERROR; // packetno corrupted? + } + } + // clear out the former seek stream state + // this will delete its internal storage + ogg_stream_clear(&fSeekStreamState); + // initialize it with the temporary seek stream + // this will transfer the internal storage to it + fSeekStreamState = seekStreamState; + // we notably do not clear our temporary stream + // instead we just let it go out of scope + fCurrentFrame = *frame; + } else if (seekTo & B_MEDIA_SEEK_TO_TIME) { + *frame = *time/50000; + return Seek(B_MEDIA_SEEK_TO_FRAME,frame,time); + } return B_OK; } @@ -166,12 +205,36 @@ OggStream::GetNextChunk(void **chunkBuffer, int32 *chunkSize, status_t OggStream::GetPacket(ogg_packet * packet) { - while (ogg_stream_packetpeek(&fStreamState,NULL) != 1) { - fReaderInterface->GetNextPage(); - } - if (ogg_stream_packetout(&fStreamState,packet) != 1) { - return B_ERROR; + if (fCurrentFrame == fOggFrameInfos.size()) { + // at the end, pull the packet + uint old_page = fCurrentPage; + uint old_packet = fCurrentPacket; + while (ogg_stream_packetpeek(&fStreamState, NULL) != 1) { + fReaderInterface->GetNextPage(); + fCurrentPage++; + } + if (ogg_stream_packetout(&fStreamState, packet) != 1) { + return B_ERROR; + } + OggFrameInfo info(old_page, old_packet); + fOggFrameInfos.push_back(info); + if (fCurrentPage != old_page) { + fCurrentPacket = 0; + } else { + fCurrentPacket++; + } + } else { + // in the middle, get packet at position + uint pageno = fOggFrameInfos[fCurrentFrame].GetPage(); + while (ogg_stream_packetpeek(&fSeekStreamState, NULL) != 1) { + off_t position = fPagePositions[pageno++]; + fReaderInterface->GetPageAt(position, &fSeekStreamState); + } + if (ogg_stream_packetout(&fSeekStreamState, packet) != 1) { + return B_ERROR; + } } + fCurrentFrame++; // ever moving forward! return B_OK; } diff --git a/src/add-ons/media/plugins/ogg/OggStream.h b/src/add-ons/media/plugins/ogg/OggStream.h index 489c98fc7a..89a025bb12 100644 --- a/src/add-ons/media/plugins/ogg/OggStream.h +++ b/src/add-ons/media/plugins/ogg/OggStream.h @@ -5,6 +5,8 @@ #include #include "ogg/ogg.h" #include "OggReaderPlugin.h" +#include "OggFrameInfo.h" +#include #include namespace BPrivate { namespace media { @@ -47,8 +49,14 @@ protected: virtual off_t TimeToPosition(bigtime_t time); private: long fSerialno; + int64 fCurrentFrame; + bigtime_t fCurrentTime; std::vector fPagePositions; + std::vector fOggFrameInfos; ogg_stream_state fStreamState; + uint fCurrentPage; + uint fCurrentPacket; + ogg_stream_state fSeekStreamState; OggReader::GetPageInterface * fReaderInterface; }; diff --git a/src/add-ons/media/plugins/ogg/OggVorbisStream.cpp b/src/add-ons/media/plugins/ogg/OggVorbisStream.cpp index 8c0c6969c2..f137bbcda1 100644 --- a/src/add-ons/media/plugins/ogg/OggVorbisStream.cpp +++ b/src/add-ons/media/plugins/ogg/OggVorbisStream.cpp @@ -85,7 +85,7 @@ OggVorbisStream::IsValidHeader(const ogg_packet & packet) OggVorbisStream::OggVorbisStream(long serialno) : OggStream(serialno) { - + TRACE("OggVorbisStream::OggVorbisStream\n"); } OggVorbisStream::~OggVorbisStream() @@ -151,9 +151,6 @@ OggVorbisStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration, } // fill out format from header packet - format->type = B_MEDIA_ENCODED_AUDIO; - format->user_data_type = B_CODEC_TYPE_INFO; - strncpy((char*)format->user_data, "vorb", 4); if (info.bitrate_nominal > 0) { format->u.encoded_audio.bit_rate = info.bitrate_nominal; } else if (info.bitrate_upper > 0) { @@ -166,11 +163,8 @@ OggVorbisStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration, } else { format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; } - format->u.encoded_audio.frame_size = sizeof(ogg_packet); format->u.encoded_audio.output.frame_rate = (float)info.rate; format->u.encoded_audio.output.channel_count = info.channels; - format->u.encoded_audio.output.format = media_raw_audio_format::B_AUDIO_FLOAT; - format->u.encoded_audio.output.byte_order = B_MEDIA_HOST_ENDIAN; format->u.encoded_audio.output.buffer_size = AudioBufferSize(&format->u.encoded_audio.output); @@ -192,7 +186,7 @@ OggVorbisStream::GetStreamInfo(int64 *frameCount, bigtime_t *duration, SaveHeaderPacket(packet); } - format->SetMetaData((void*)&fHeaderPackets,sizeof(&fHeaderPackets)); + format->SetMetaData((void*)&fHeaderPackets,sizeof(fHeaderPackets)); *duration = 80000000; *frameCount = 60000; return B_OK; diff --git a/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp b/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp index 95774b7889..01549dfa15 100644 --- a/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp +++ b/src/add-ons/media/plugins/speex/speexCodecPlugin.cpp @@ -148,7 +148,6 @@ speexDecoder::Setup(media_format *inputFormat, speex_decoder_ctl(fDecoderState, SPEEX_SET_ENH, &enabled); } speex_decoder_ctl(fDecoderState, SPEEX_GET_FRAME_SIZE, &fHeader->frame_size); - fSpeexOutputLength = fHeader->frame_size * sizeof(float) * fHeader->nb_channels; if (fHeader->nb_channels == 2) { SpeexCallback callback; SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; @@ -197,13 +196,17 @@ void speexDecoder::CopyInfoToDecodedFormat(media_raw_audio_format * raf) { raf->channel_count = fHeader->nb_channels; raf->format = media_raw_audio_format::B_AUDIO_FLOAT; // XXX verify: support others? raf->byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too - if (raf->buffer_size < 512 || raf->buffer_size > 65536) { - raf->buffer_size = AudioBufferSize(raf); + int buffer_size = raf->buffer_size; + if (buffer_size < 512 || buffer_size > 65536) { + buffer_size = AudioBufferSize(raf); } - raf->buffer_size = ((raf->buffer_size - 1) / fSpeexOutputLength + 1) * fSpeexOutputLength; + int output_length = fHeader->frame_size * fHeader->nb_channels * (raf->format & 0xf); + buffer_size = ((buffer_size - 1) / output_length + 1) * output_length; + raf->buffer_size = buffer_size; // setup output variables fFrameSize = (raf->format & 0xf) * raf->channel_count; - fOutputBufferSize = raf->buffer_size; + fOutputBufferSize = buffer_size; + fSpeexOutputLength = output_length; } status_t diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp index 1044328142..30f1d550f0 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp @@ -16,6 +16,7 @@ #define DECODE_BUFFER_SIZE (32 * 1024) + inline size_t AudioBufferSize(media_raw_audio_format * raf, bigtime_t buffer_duration = 50000 /* 50 ms */) { @@ -23,56 +24,106 @@ AudioBufferSize(media_raw_audio_format * raf, bigtime_t buffer_duration = 50000 * (size_t)((raf->frame_rate * buffer_duration) / 1000000.0); } -vorbisDecoder::vorbisDecoder() + +/* + * vorbis descriptions/formats + */ + + +static media_format_description +vorbis_description() { - TRACE("vorbisDecoder::vorbisDecoder\n"); + media_format_description description; + description.family = B_MISC_FORMAT_FAMILY; + description.u.misc.file_format = 'OggS'; + description.u.misc.codec = 'vorb'; + return description; +} + + +static void +init_vorbis_media_raw_audio_format(media_raw_audio_format * output) +{ + output->format = media_raw_audio_format::B_AUDIO_FLOAT; + output->byte_order = B_MEDIA_HOST_ENDIAN; +} + + +static media_format +vorbis_encoded_media_format() +{ + media_format format; + format.type = B_MEDIA_ENCODED_AUDIO; + format.user_data_type = B_CODEC_TYPE_INFO; + strncpy((char*)format.user_data, "vorb", 4); + format.u.encoded_audio.frame_size = sizeof(ogg_packet); + init_vorbis_media_raw_audio_format(&format.u.encoded_audio.output); + return format; +} + + +static media_format +vorbis_decoded_media_format() +{ + media_format format; + format.type = B_MEDIA_RAW_AUDIO; + init_vorbis_media_raw_audio_format(&format.u.raw_audio); + return format; +} + + +/* + * VorbisDecoder + */ + + +VorbisDecoder::VorbisDecoder() +{ + TRACE("VorbisDecoder::VorbisDecoder\n"); vorbis_info_init(&fInfo); vorbis_comment_init(&fComment); - + fStartTime = 0; fFrameSize = 0; fOutputBufferSize = 0; } -vorbisDecoder::~vorbisDecoder() +VorbisDecoder::~VorbisDecoder() { - TRACE("vorbisDecoder::~vorbisDecoder\n"); + TRACE("VorbisDecoder::~VorbisDecoder\n"); } void -vorbisDecoder::GetCodecInfo(media_codec_info &info) +VorbisDecoder::GetCodecInfo(media_codec_info &info) { - strcpy(info.short_name, "vorbis"); - strcpy(info.pretty_name, "vorbis decoder, based on libvorbis"); + strncpy(info.short_name, "vorbis", sizeof(info.short_name)); + strncpy(info.pretty_name, "vorbis decoder, by Andrew Bachmann, based on libvorbis", sizeof(info.pretty_name)); } status_t -vorbisDecoder::Setup(media_format *inputFormat, +VorbisDecoder::Setup(media_format *inputFormat, const void *infoBuffer, int32 infoSize) { - if (inputFormat->type != B_MEDIA_ENCODED_AUDIO) { - TRACE("vorbisDecoder::Setup not called with audio stream: not vorbis\n"); - return B_ERROR; + TRACE("VorbisDecoder::Setup\n"); + if (!format_is_compatible(vorbis_encoded_media_format(),*inputFormat)) { + return B_MEDIA_BAD_FORMAT; } - if (inputFormat->u.encoded_audio.encoding != 'vorb') { - TRACE("vorbisDecoder::Setup not called with 'vorb' stream: not vorbis\n"); - return B_ERROR; - } - if (inputFormat->MetaDataSize() != sizeof(std::vector *)) { - TRACE("vorbisDecoder::Setup not called with ogg_packet meta data: not vorbis\n"); + // grab header packets from meta data + if (inputFormat->MetaDataSize() != sizeof(std::vector)) { + TRACE("VorbisDecoder::Setup not called with ogg_packet meta data: not vorbis\n"); return B_ERROR; } std::vector * packets = (std::vector *)inputFormat->MetaData(); if (packets->size() != 3) { - TRACE("vorbisDecoder::Setup not called with three ogg_packets: not vorbis\n"); + TRACE("VorbisDecoder::Setup not called with three ogg_packets: not vorbis\n"); return B_ERROR; } // parse header packet if (vorbis_synthesis_headerin(&fInfo,&fComment,&(*packets)[0]) != 0) { - TRACE("vorbisDecoder::Setup: vorbis_synthesis_headerin failed: not vorbis header\n"); + TRACE("VorbisDecoder::Setup: vorbis_synthesis_headerin failed: not vorbis header\n"); return B_ERROR; } // parse comment packet @@ -88,68 +139,58 @@ vorbisDecoder::Setup(media_format *inputFormat, // initialize decoder vorbis_synthesis_init(&fDspState,&fInfo); vorbis_block_init(&fDspState,&fBlock); - // fill out the encoding format - CopyInfoToEncodedFormat(inputFormat); - return B_OK; + // setup default output + media_format requested_format = vorbis_decoded_media_format(); + ((media_raw_audio_format)requested_format.u.raw_audio) = inputFormat->u.encoded_audio.output; + return NegotiateOutputFormat(&requested_format); } -void vorbisDecoder::CopyInfoToEncodedFormat(media_format * format) { - format->type = B_MEDIA_ENCODED_AUDIO; -// ToDo: this won't work any longer -// format->u.encoded_audio.encoding -// = (media_encoded_audio_format::audio_encoding)'vorb'; - if (fInfo.bitrate_nominal > 0) { - format->u.encoded_audio.bit_rate = fInfo.bitrate_nominal; - } else if (fInfo.bitrate_upper > 0) { - format->u.encoded_audio.bit_rate = fInfo.bitrate_upper; - } else if (fInfo.bitrate_lower > 0) { - format->u.encoded_audio.bit_rate = fInfo.bitrate_lower; - } - CopyInfoToDecodedFormat(&format->u.encoded_audio.output); - format->u.encoded_audio.frame_size = sizeof(ogg_packet); -} - -void vorbisDecoder::CopyInfoToDecodedFormat(media_raw_audio_format * raf) { - raf->frame_rate = (float)fInfo.rate; // XXX long->float ?? - raf->channel_count = fInfo.channels; - raf->format = media_raw_audio_format::B_AUDIO_FLOAT; // XXX verify: support others? - raf->byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too - - if (raf->buffer_size < 512 || raf->buffer_size > 65536) { - raf->buffer_size = AudioBufferSize(raf); - } - // setup output variables - fFrameSize = (raf->format & 0xf) * raf->channel_count; - fOutputBufferSize = raf->buffer_size; -} status_t -vorbisDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat) +VorbisDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat) { - TRACE("vorbisDecoder::NegotiateOutputFormat\n"); - // BeBook says: The codec will find and return in ioFormat its best matching format - // => This means, we never return an error, and always change the format values - // that we don't support to something more applicable - ioDecodedFormat->type = B_MEDIA_RAW_AUDIO; - CopyInfoToDecodedFormat(&ioDecodedFormat->u.raw_audio); - // add the media_mult_audio_format fields - if (ioDecodedFormat->u.raw_audio.channel_mask == 0) { - if (fInfo.channels == 1) { - ioDecodedFormat->u.raw_audio.channel_mask = B_CHANNEL_LEFT; - } else { - ioDecodedFormat->u.raw_audio.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; - } + TRACE("VorbisDecoder::NegotiateOutputFormat\n"); + // BMediaTrack::DecodedFormat + // Pass in ioFormat the format that you want (with wildcards + // as applicable). The codec will find and return in ioFormat + // its best matching format. + // + // BMediaDecoder::SetOutputFormat + // sets the format the decoder should output. On return, + // the outputFormat is changed to match the actual format + // that will be output; this can be different if you + // specified any wildcards. + // + media_format format = vorbis_decoded_media_format(); + format.u.raw_audio.frame_rate = (float)fInfo.rate; + format.u.raw_audio.channel_count = fInfo.channels; + format.u.raw_audio.channel_mask = B_CHANNEL_LEFT | (fInfo.channels != 1 ? B_CHANNEL_RIGHT : 0); + if (ioDecodedFormat->u.raw_audio.buffer_size < 512) { + format.u.raw_audio.buffer_size = AudioBufferSize(&format.u.raw_audio); } + if (!format_is_compatible(format,*ioDecodedFormat)) { +#ifdef NegotiateOutputFormat_AS_BEBOOK_SPEC + return B_ERROR; +#else + // Be R5 behavior: never fail (?) => nuke the input format + *ioDecodedFormat = format; +#endif + } + ioDecodedFormat->SpecializeTo(&format); + // setup output variables + fFrameSize = (ioDecodedFormat->u.raw_audio.format & 0xf) * + (ioDecodedFormat->u.raw_audio.channel_count); + fOutputBufferSize = ioDecodedFormat->u.raw_audio.buffer_size; return B_OK; } status_t -vorbisDecoder::Seek(uint32 seekTo, +VorbisDecoder::Seek(uint32 seekTo, int64 seekFrame, int64 *frame, bigtime_t seekTime, bigtime_t *time) { - TRACE("vorbisDecoder::Seek\n"); + TRACE("VorbisDecoder::Seek\n"); float **pcm; // throw the old samples away! int samples = vorbis_synthesis_pcmout(&fDspState,&pcm); @@ -159,15 +200,15 @@ vorbisDecoder::Seek(uint32 seekTo, status_t -vorbisDecoder::Decode(void *buffer, int64 *frameCount, +VorbisDecoder::Decode(void *buffer, int64 *frameCount, media_header *mediaHeader, media_decode_info *info /* = 0 */) { -// TRACE("vorbisDecoder::Decode\n"); +// TRACE("VorbisDecoder::Decode\n"); uint8 * out_buffer = static_cast(buffer); int32 out_bytes_needed = fOutputBufferSize; mediaHeader->start_time = fStartTime; - //TRACE("vorbisDecoder: Decoding start time %.6f\n", fStartTime / 1000000.0); + //TRACE("VorbisDecoder: Decoding start time %.6f\n", fStartTime / 1000000.0); while (out_bytes_needed > 0) { int samples; @@ -182,11 +223,11 @@ vorbisDecoder::Decode(void *buffer, int64 *frameCount, goto done; } if (status != B_OK) { - TRACE("vorbisDecoder::Decode: GetNextChunk failed\n"); + TRACE("VorbisDecoder::Decode: GetNextChunk failed\n"); return status; } if (chunkSize != sizeof(ogg_packet)) { - TRACE("vorbisDecoder::Decode: chunk not ogg_packet-sized\n"); + TRACE("VorbisDecoder::Decode: chunk not ogg_packet-sized\n"); return B_ERROR; } ogg_packet * packet = static_cast(chunkBuffer); @@ -207,7 +248,7 @@ vorbisDecoder::Decode(void *buffer, int64 *frameCount, vorbis_synthesis_read(&fDspState,samples); fStartTime += (1000000LL * samples) / fInfo.rate; - //TRACE("vorbisDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0); + //TRACE("VorbisDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0); } done: @@ -219,8 +260,14 @@ done: return B_LAST_BUFFER_ERROR; } + +/* + * VorbisDecoderPlugin + */ + + Decoder * -vorbisDecoderPlugin::NewDecoder() +VorbisDecoderPlugin::NewDecoder() { static BLocker locker; static bool initdone = false; @@ -228,28 +275,30 @@ vorbisDecoderPlugin::NewDecoder() if (!initdone) { initdone = true; } - return new vorbisDecoder; + return new VorbisDecoder; } - status_t -vorbisDecoderPlugin::RegisterDecoder() +VorbisDecoderPlugin::RegisterDecoder() { - media_format_description description; - // ToDo: what about B_OGG_FORMAT_FAMILY? - description.family = B_MISC_FORMAT_FAMILY; - description.u.misc.file_format = 'ogg '; - description.u.misc.codec = 'vorb'; + media_format_description description = vorbis_description(); + media_format format = vorbis_encoded_media_format(); - media_format format; - format.type = B_MEDIA_ENCODED_AUDIO; - format.u.encoded_audio = media_encoded_audio_format::wildcard; - - return BMediaFormats().MakeFormatFor(&description, 1, &format); + BMediaFormats formats; + status_t result = formats.InitCheck(); + if (result != B_OK) { + return result; + } + return formats.MakeFormatFor(&description, 1, &format); } +/* + * instantiate_plugin + */ + + MediaPlugin *instantiate_plugin() { - return new vorbisDecoderPlugin; + return new VorbisDecoderPlugin; } diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h index c91d0c23d5..b03ce36c74 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h @@ -1,12 +1,15 @@ +#ifndef _VORBIS_CODEC_PLUGIN_H_ +#define _VORBIS_CODEC_PLUGIN_H_ + #include "DecoderPlugin.h" #include "libvorbis/vorbis/codec.h" -class vorbisDecoder : public Decoder +class VorbisDecoder : public Decoder { public: - vorbisDecoder(); - ~vorbisDecoder(); + VorbisDecoder(); + ~VorbisDecoder(); void GetCodecInfo(media_codec_info &info); status_t Setup(media_format *inputFormat, @@ -23,9 +26,6 @@ public: media_header *mediaHeader, media_decode_info *info); private: - void CopyInfoToEncodedFormat(media_format * format); - void CopyInfoToDecodedFormat(media_raw_audio_format * raf); - vorbis_info fInfo; vorbis_comment fComment; vorbis_dsp_state fDspState; @@ -36,9 +36,11 @@ private: }; -class vorbisDecoderPlugin : public DecoderPlugin +class VorbisDecoderPlugin : public DecoderPlugin { public: Decoder * NewDecoder(); status_t RegisterDecoder(); }; + +#endif _VORBIS_CODEC_PLUGIN_H_