vorbis decoder take 1
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5762 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fa5c397539
commit
fac65e8045
@ -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 ;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <Autolock.h>
|
||||
#include <DataIO.h>
|
||||
#include <Locker.h>
|
||||
#include <MediaFormats.h>
|
||||
@ -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<ogg_packet*>(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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user