diff --git a/src/add-ons/media/plugins/vorbis/Jamfile b/src/add-ons/media/plugins/vorbis/Jamfile index 4487e6bb93..00da183bf7 100644 --- a/src/add-ons/media/plugins/vorbis/Jamfile +++ b/src/add-ons/media/plugins/vorbis/Jamfile @@ -5,9 +5,9 @@ UsePrivateHeaders media ; SubDirHdrs $(SUBDIR) .. ogg libogg ; SubDirHdrs $(SUBDIR) libvorbis vorbis ; -Addon vorbis_decoder : media plugins : +Addon vorbis : media plugins : vorbisCodecPlugin.cpp - : false : libvorbis.a + : false : libvorbis.a libogg.a ; LinkSharedOSLibs vorbis : be libmedia.so ; diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp index 7bb37e35c4..c782e304aa 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -16,7 +17,8 @@ vorbisDecoder::vorbisDecoder() { - vorbis_info_init(&fVorbisInfo); + vorbis_info_init(&fInfo); + vorbis_comment_init(&fComment); fResidualBytes = 0; fResidualBuffer = 0; @@ -38,48 +40,76 @@ status_t vorbisDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer, int32 infoSize) { - if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO) { - TRACE("vorbisDecoder::Setup not called with encoded video"); + if ((ioEncodedFormat->type != B_MEDIA_UNKNOWN_TYPE) + && (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO)) { + TRACE("vorbisDecoder::Setup not called with audio/unknown stream: not vorbis"); return B_ERROR; } - - // save the extractor information for future reference - fOutput = ioEncodedFormat->u.encoded_audio.output; - fBitRate = ioEncodedFormat->u.encoded_audio.bit_rate; - fFrameSize = ioEncodedFormat->u.encoded_audio.frame_size; - - printf("vorbisDecoder::Setup: bitrate %d\n", fBitRate); - - + if (infoSize != sizeof(ogg_packet)) { + TRACE("vorbisDecoder::Setup not called with ogg_packet info: not vorbis"); + return B_ERROR; + } + // parse header packet + if (vorbis_synthesis_headerin(&fInfo,&fComment,(ogg_packet*)infoBuffer) != 0) { + TRACE("vorbisDecoder::Setup: vorbis_synthesis_headerin failed: not vorbis header"); + return B_ERROR; + } + // get comment packet + ogg_packet * packet; + int32 size; + media_header mh; + if (GetNextChunk((void**)&packet, &size, &mh) != B_OK) { + TRACE("vorbisDecoder::Setup: GetNextChunk failed to get comment\n"); + return B_ERROR; + } + // parse comment packet + if (vorbis_synthesis_headerin(&fInfo,&fComment,packet) != 0) { + TRACE("vorbiseDecoder::Setup: vorbis_synthesis_headerin failed: not vorbis comment"); + return B_ERROR; + } + // get codebook packet + if (GetNextChunk((void**)&packet, &size, &mh) != B_OK) { + TRACE("vorbisDecoder::Setup: GetNextChunk failed to get codebook\n"); + return B_ERROR; + } + // parse codebook packet + if (vorbis_synthesis_headerin(&fInfo,&fComment,packet) != 0) { + TRACE("vorbiseDecoder::Setup: vorbis_synthesis_headerin failed: not vorbis codebook"); + return B_ERROR; + } + // initialize decoder + vorbis_synthesis_init(&fDspState,&fInfo); + vorbis_block_init(&fDspState,&fBlock); return B_OK; } +size_t get_audio_buffer_size(const media_raw_audio_format & raf) { + BMediaRoster * roster = BMediaRoster::Roster(); + return roster->AudioBufferSizeFor(raf.channel_count,raf.format,raf.frame_rate); +} + status_t vorbisDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat) { - // fFrameRate and fChannelCount are already valid here - // 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; - ioDecodedFormat->u.raw_audio.frame_rate = fFrameRate; - ioDecodedFormat->u.raw_audio.channel_count = fChannelCount; - ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; // XXX should support other formats, too + ioDecodedFormat->u.raw_audio.frame_rate = (float)fInfo.rate; // XXX long->float ?? + ioDecodedFormat->u.raw_audio.channel_count = fInfo.channels; + ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; // XXX verify: support others? ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too + if (ioDecodedFormat->u.raw_audio.buffer_size < 512 || ioDecodedFormat->u.raw_audio.buffer_size > 65536) ioDecodedFormat->u.raw_audio.buffer_size - = BMediaRoster::Roster()->AudioBufferSizeFor(fChannelCount, - ioDecodedFormat->u.raw_audio.format, - fFrameRate); + = get_audio_buffer_size(ioDecodedFormat->u.raw_audio); if (ioDecodedFormat->u.raw_audio.channel_mask == 0) ioDecodedFormat->u.raw_audio.channel_mask - = (fChannelCount == 1) ? B_CHANNEL_LEFT : B_CHANNEL_LEFT | B_CHANNEL_RIGHT; + = (fInfo.channels == 1) ? B_CHANNEL_LEFT : B_CHANNEL_LEFT | B_CHANNEL_RIGHT; // setup rest of the needed variables - fFrameSize = (ioDecodedFormat->u.raw_audio.format & 0xf) * fChannelCount; + fFrameSize = (ioDecodedFormat->u.raw_audio.format & 0xf) * fInfo.channels; fOutputBufferSize = ioDecodedFormat->u.raw_audio.buffer_size; return B_OK; @@ -91,8 +121,7 @@ vorbisDecoder::Seek(uint32 seekTo, int64 seekFrame, int64 *frame, bigtime_t seekTime, bigtime_t *time) { - ExitMP3(&fMpgLibPrivate); - InitMP3(&fMpgLibPrivate); + debugger("vorbisDecoder::Seek"); fResidualBytes = 0; return B_OK; } @@ -117,7 +146,7 @@ vorbisDecoder::Decode(void *buffer, int64 *frameCount, out_buffer += bytes; out_bytes_needed -= bytes; - fStartTime += (1000000LL * (bytes / fFrameSize)) / fFrameRate; + fStartTime += (1000000LL * (bytes / fFrameSize)) / fInfo.rate; //TRACE("vorbisDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0); continue; @@ -143,17 +172,19 @@ vorbisDecoder::DecodeNextChunk() TRACE("vorbisDecoder::Decode: GetNextChunk failed\n"); return B_ERROR; } + if (chunkSize != sizeof(ogg_packet)) { + TRACE("vorbisDecoder::Decode: chunk not ogg_packet-sized\n"); + return B_ERROR; + } + ogg_packet * packet = static_cast(chunkBuffer); - fStartTime = mh.start_time; + //fStartTime = mh.start_time; //TRACE("vorbisDecoder: fStartTime reset to %.6f\n", fStartTime / 1000000.0); - int outsize; - int result; - result = decodeMP3(&fMpgLibPrivate, (char *)chunkBuffer, chunkSize, (char *)fDecodeBuffer, DECODE_BUFFER_SIZE, &outsize); - if (result == MP3_ERR) { - TRACE("vorbisDecoder::Decode: decodeMP3 returned MP3_ERR\n"); - return B_ERROR; + int outsize = 0; + if (vorbis_synthesis(&fBlock,packet)==0) { + vorbis_synthesis_blockin(&fDspState,&fBlock); } //printf("vorbisDecoder::Decode: decoded %d bytes into %d bytes\n",chunkSize, outsize); @@ -181,6 +212,7 @@ vorbisDecoderPlugin::NewDecoder() status_t vorbisDecoderPlugin::RegisterPlugin() { + PublishDecoder("unknown", "vorbis", "vorbis decoder, based on libvorbis"); PublishDecoder("audiocodec/vorbis", "vorbis", "vorbis decoder, based on libvorbis"); return B_OK; } diff --git a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h index 15b50d8889..1c163af9f8 100644 --- a/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h +++ b/src/add-ons/media/plugins/vorbis/vorbisCodecPlugin.h @@ -24,9 +24,11 @@ public: status_t DecodeNextChunk(); private: - struct vorbis_dsp_state fVorbisDspState; - struct vorbis_info fVorbisInfo; - struct media_raw_video_format fOutput; + vorbis_info fInfo; + vorbis_comment fComment; + vorbis_dsp_state fDspState; + vorbis_block fBlock; + media_raw_video_format fOutput; int32 fResidualBytes; uint8 * fResidualBuffer; uint8 * fDecodeBuffer;