diff --git a/headers/private/media/RawFormats.h b/headers/private/media/RawFormats.h index af3bfc9184..e3419e8769 100644 --- a/headers/private/media/RawFormats.h +++ b/headers/private/media/RawFormats.h @@ -14,10 +14,10 @@ enum { B_AUDIO_FORMAT_UINT8 = 0x0011, B_AUDIO_FORMAT_INT8 = 0x0001, B_AUDIO_FORMAT_INT16 = 0x0002, - B_AUDIO_FORMAT_INT24 = 0x0003, + B_AUDIO_FORMAT_INT24 = 0x1003, B_AUDIO_FORMAT_INT32 = 0x0004, B_AUDIO_FORMAT_FLOAT32 = 0x0024, - B_AUDIO_FORMAT_FLOAT64 = 0x0028, + B_AUDIO_FORMAT_FLOAT64 = 0x1008, B_AUDIO_FORMAT_MASK = 0xffff, B_AUDIO_FORMAT_SIZE_MASK = 0xf, B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE = 0x100000, diff --git a/src/add-ons/media/plugins/aiff_reader/aiff.h b/src/add-ons/media/plugins/aiff_reader/aiff.h index 3742906982..c9e58031a4 100644 --- a/src/add-ons/media/plugins/aiff_reader/aiff.h +++ b/src/add-ons/media/plugins/aiff_reader/aiff.h @@ -70,6 +70,10 @@ inline const char * string_for_compression(uint32 compression) case 'Qclp': return "Qualcomm PureVoice"; case 'rt24': return "RT24 50:1"; case 'rt29': return "RT29 50:1"; + case 'G722': return "G722"; + case 'G726': return "G726"; + case 'G728': return "G728"; + case 'GSM ': return "GSM"; default: sprintf(s, "unknown compression %c%c%c%c", (int)((compression >> 24) & 0xff), diff --git a/src/add-ons/media/plugins/aiff_reader/aiff_reader.cpp b/src/add-ons/media/plugins/aiff_reader/aiff_reader.cpp index 016f01e6d8..35ee7a20eb 100644 --- a/src/add-ons/media/plugins/aiff_reader/aiff_reader.cpp +++ b/src/add-ons/media/plugins/aiff_reader/aiff_reader.cpp @@ -4,6 +4,7 @@ #include #include #include +#include "RawFormats.h" #include "aiff_reader.h" #define TRACE_THIS 1 @@ -36,7 +37,7 @@ aiffReader::~aiffReader() const char * aiffReader::Copyright() { - return ".au & .snd reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen"; + return "AIFF & AIFF-C reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen"; } @@ -222,8 +223,7 @@ aiffReader::Sniff(int32 *streamCount) fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; break; case 3: - // XXX broken - fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; + fFormat.u.raw_audio.format = B_AUDIO_FORMAT_INT24; break; case 4: fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; @@ -240,8 +240,7 @@ aiffReader::Sniff(int32 *streamCount) fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; break; case FOURCC('f','l','6','4'): - // XXX broken - fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; + fFormat.u.raw_audio.format = B_AUDIO_FORMAT_FLOAT64; break; default: TRACE("aiffReader::Sniff: unknown raw format\n"); diff --git a/src/add-ons/media/plugins/au_reader/au_reader.cpp b/src/add-ons/media/plugins/au_reader/au_reader.cpp index c65ef64183..8e09b5f140 100644 --- a/src/add-ons/media/plugins/au_reader/au_reader.cpp +++ b/src/add-ons/media/plugins/au_reader/au_reader.cpp @@ -4,6 +4,7 @@ #include #include #include +#include "RawFormats.h" #include "au_reader.h" #define TRACE_THIS 1 @@ -204,8 +205,7 @@ auReader::Sniff(int32 *streamCount) fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; break; case SND_FORMAT_LINEAR_24: - // XXX broken - fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; + fFormat.u.raw_audio.format = B_AUDIO_FORMAT_INT24; break; case SND_FORMAT_LINEAR_32: fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; @@ -214,8 +214,7 @@ auReader::Sniff(int32 *streamCount) fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; break; case SND_FORMAT_DOUBLE: - // XXX broken - fFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; + fFormat.u.raw_audio.format = B_AUDIO_FORMAT_FLOAT64; break; default: TRACE("WavReader::Sniff: unhandled raw format\n"); diff --git a/src/add-ons/media/plugins/raw_decoder/AudioConversion.cpp b/src/add-ons/media/plugins/raw_decoder/AudioConversion.cpp new file mode 100644 index 0000000000..c9405aee35 --- /dev/null +++ b/src/add-ons/media/plugins/raw_decoder/AudioConversion.cpp @@ -0,0 +1,211 @@ +#include +#include +#include "AudioConversion.h" +#include "RawFormats.h" + +// XXX GCC doesn't always generate nice code... + +typedef float float32; +typedef double float64; + +class uint8_sample +{ +public: + inline operator uint8() { return data; } + inline operator int8() { return (int32)data - 128; } + inline operator int16() { return ((int32)data - 128) << 8; } + inline operator int32() { return ((int32)data - 128) << 24; } + inline operator float() { return ((int32)data - 128) * (1.0f / 127.0f); } +private: + uint8 data; +} _PACKED; + +class int8_sample +{ +public: + inline operator uint8() { return (int32)data + 128; } + inline operator int8() { return data; } + inline operator int16() { return (int16)data << 8; } + inline operator int32() { return (int32)data << 24; } + inline operator float() { return (int32)data * (1.0f / 127.0f); } +private: + int8 data; +} _PACKED; + +class int16_sample +{ +public: + inline operator uint8() { return (uint8)((int8)(data >> 8) + 128); } + inline operator int8() { return (int8)(data >> 8); } + inline operator int16() { return data; } + inline operator int32() { return (int32)data << 16; } + inline operator float() { return data * (1.0f / 32767.0f); } +private: + int16 data; +} _PACKED; + +class int24_sample +{ +public: +#if B_HOST_IS_LENDIAN + inline operator uint8() { return (int32)data[2] + 128; } + inline operator int8() { return (int8)data[2]; } + inline operator int16() { return (int16)((uint32)data[2] << 8 | (uint32)data[1]); } + inline operator int32() { return (int32)((uint32)data[2] << 24 | (uint32)data[1] << 16 | (uint32)data[0] << 8); } + inline operator float() { return (int32)((uint32)data[2] << 24 | (uint32)data[1] << 16 | (uint32)data[0] << 8) * (1.0f / 2147483647.0f); } +#else + inline operator uint8() { return (int32)data[0] + 128; } + inline operator int8() { return (int8)data[1]; } + inline operator int16() { return (int16)((uint32)data[0] << 8 | (uint32)data[1]); } + inline operator int32() { return (int32)((uint32)data[0] << 24 | (uint32)data[1] << 16 | (uint32)data[2] << 8); } + inline operator float() { return (int32)((uint32)data[0] << 24 | (uint32)data[1] << 16 | (uint32)data[2] << 8) * (1.0f / 2147483647.0f); } +#endif +private: + uint8 data[3]; +} _PACKED; + +class int32_sample +{ +public: + inline operator uint8() { return (int8)(data >> 24) + 128; } + inline operator int8() { return (int8)(data >> 24); } + inline operator int16() { return (int16)(data >> 16); } + inline operator int32() { return data; } + inline operator float() { return data * (1.0f / 2147483647.0f); } +private: + int32 data; +} _PACKED; + +class float32_sample +{ +public: + inline operator uint8() { return (int32)(data * 127.0f) + 128; } + inline operator int8() { return (int8)(data * 127.0f); } + inline operator int16() { return (int16)(data * 32767.0f); } + inline operator int32() { return (int32)(data * 2147483647.0f); } + inline operator float() { return data; } +private: + float32 data; +} _PACKED; + +class float64_sample +{ +public: + inline operator uint8() { return (int32)(data * 127.0) + 128; } + inline operator int8() { return (int8)(data * 127.0); } + inline operator int16() { return (int16)(data * 32767.0); } + inline operator int32() { return (int32)(data * 2147483647.0); } + inline operator float() { return data; } +private: + float64 data; +} _PACKED; + +#define CONVERT(src_type, dst_type) \ +void src_type##_to_##dst_type (void *dst, void *src, int32 count) \ +{ \ + register src_type##_sample *s = (src_type##_sample *) src; \ + register dst_type *d = (dst_type *) dst; \ + register int32 c = count >> 4; \ + if (!c) goto fin1; \ + do { \ + d[0] = s[0]; d[1] = s[1]; \ + d[2] = s[2]; d[3] = s[3]; \ + d[4] = s[4]; d[5] = s[5]; \ + d[6] = s[6]; d[7] = s[7]; \ + d[8] = s[8]; d[9] = s[9]; \ + d[10] = s[10]; d[11] = s[11]; \ + d[12] = s[12]; d[13] = s[13]; \ + d[14] = s[14]; d[15] = s[15]; \ + s += 16; d += 16; \ + } while (--c); \ +fin1: \ + c = count & 15; \ + if (!c) goto fin2; \ + do { \ + *(d++) = *(s++); \ + } while (--c); \ +fin2: \ + ; \ +} + + +CONVERT(uint8, uint8) +CONVERT(uint8, int8) +CONVERT(uint8, int16) +CONVERT(uint8, int32) +CONVERT(uint8, float32) + +CONVERT(int8, uint8) +CONVERT(int8, int8) +CONVERT(int8, int16) +CONVERT(int8, int32) +CONVERT(int8, float32) + +CONVERT(int16, uint8) +CONVERT(int16, int8) +CONVERT(int16, int16) +CONVERT(int16, int32) +CONVERT(int16, float32) + +CONVERT(int24, uint8) +CONVERT(int24, int8) +CONVERT(int24, int16) +CONVERT(int24, int32) +CONVERT(int24, float32) + +CONVERT(int32, uint8) +CONVERT(int32, int8) +CONVERT(int32, int16) +CONVERT(int32, int32) +CONVERT(int32, float32) + +CONVERT(float32, uint8) +CONVERT(float32, int8) +CONVERT(float32, int16) +CONVERT(float32, int32) +CONVERT(float32, float32) + +CONVERT(float64, uint8) +CONVERT(float64, int8) +CONVERT(float64, int16) +CONVERT(float64, int32) +CONVERT(float64, float32) + +void +swap_int16(void *data, int32 count) +{ + swap_data(B_INT16_TYPE, data, count * 2, B_SWAP_ALWAYS); +} + +void +swap_int24(void *data, int32 count) +{ + register int32 c = count; + register uint8 *d = (uint8 *)data; + if (!c) + return; + do { + register uint8 temp = d[0]; + d[0] = d[2]; + d[2] = temp; + d += 3; + } while (--c); +} + +void +swap_int32(void *data, int32 count) +{ + swap_data(B_INT32_TYPE, data, count * 4, B_SWAP_ALWAYS); +} + +void +swap_float32(void *data, int32 count) +{ + swap_data(B_FLOAT_TYPE, data, count * 4, B_SWAP_ALWAYS); +} + +void +swap_float64(void *data, int32 count) +{ + swap_data(B_INT64_TYPE, data, count * 8, B_SWAP_ALWAYS); +} diff --git a/src/add-ons/media/plugins/raw_decoder/AudioConversion.h b/src/add-ons/media/plugins/raw_decoder/AudioConversion.h new file mode 100644 index 0000000000..d63b2570cc --- /dev/null +++ b/src/add-ons/media/plugins/raw_decoder/AudioConversion.h @@ -0,0 +1,54 @@ +#ifndef _AUDIO_CONVERSION_H +#define _AUDIO_CONVERSION_H + +#include + +void uint8_to_uint8(void *dst, void *src, int32 count); +void uint8_to_int8(void *dst, void *src, int32 count); +void uint8_to_int16(void *dst, void *src, int32 count); +void uint8_to_int32(void *dst, void *src, int32 count); +void uint8_to_float32(void *dst, void *src, int32 count); + +void int8_to_uint8(void *dst, void *src, int32 count); +void int8_to_int8(void *dst, void *src, int32 count); +void int8_to_int16(void *dst, void *src, int32 count); +void int8_to_int32(void *dst, void *src, int32 count); +void int8_to_float32(void *dst, void *src, int32 count); + +void int16_to_uint8(void *dst, void *src, int32 count); +void int16_to_int8(void *dst, void *src, int32 count); +void int16_to_int16(void *dst, void *src, int32 count); +void int16_to_int32(void *dst, void *src, int32 count); +void int16_to_float32(void *dst, void *src, int32 count); + +void int24_to_uint8(void *dst, void *src, int32 count); +void int24_to_int8(void *dst, void *src, int32 count); +void int24_to_int16(void *dst, void *src, int32 count); +void int24_to_int32(void *dst, void *src, int32 count); +void int24_to_float32(void *dst, void *src, int32 count); + +void int32_to_uint8(void *dst, void *src, int32 count); +void int32_to_int8(void *dst, void *src, int32 count); +void int32_to_int16(void *dst, void *src, int32 count); +void int32_to_int32(void *dst, void *src, int32 count); +void int32_to_float32(void *dst, void *src, int32 count); + +void float32_to_uint8(void *dst, void *src, int32 count); +void float32_to_int8(void *dst, void *src, int32 count); +void float32_to_int16(void *dst, void *src, int32 count); +void float32_to_int32(void *dst, void *src, int32 count); +void float32_to_float32(void *dst, void *src, int32 count); + +void float64_to_uint8(void *dst, void *src, int32 count); +void float64_to_int8(void *dst, void *src, int32 count); +void float64_to_int16(void *dst, void *src, int32 count); +void float64_to_int32(void *dst, void *src, int32 count); +void float64_to_float32(void *dst, void *src, int32 count); + +void swap_int16(void *data, int32 count); +void swap_int24(void *data, int32 count); +void swap_int32(void *data, int32 count); +void swap_float32(void *data, int32 count); +void swap_float64(void *data, int32 count); + +#endif // _AUDIO_CONVERSION_H diff --git a/src/add-ons/media/plugins/raw_decoder/Jamfile b/src/add-ons/media/plugins/raw_decoder/Jamfile index 8ba14a5112..e5fc7930c0 100644 --- a/src/add-ons/media/plugins/raw_decoder/Jamfile +++ b/src/add-ons/media/plugins/raw_decoder/Jamfile @@ -3,6 +3,7 @@ SubDir OBOS_TOP src add-ons media plugins raw_decoder ; UsePrivateHeaders media ; Addon raw_decoder : media plugins : + AudioConversion.cpp RawDecoderPlugin.cpp ; diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp index 4225d4db2c..28ab1124b0 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp @@ -1,13 +1,17 @@ #include #include #include +#include +#include +#include "RawFormats.h" #include "RawDecoderPlugin.h" +#include "AudioConversion.h" #define TRACE_THIS 1 #if TRACE_THIS #define TRACE printf #else - #define TRACE TRACE(a...) + #define TRACE(a...) #endif @@ -15,15 +19,49 @@ status_t RawDecoder::Setup(media_format *ioEncodedFormat, const void *infoBuffer, int32 infoSize) { + char s[200]; + string_for_format(*ioEncodedFormat, s, sizeof(s)); + TRACE("RawDecoder::Setup: %s\n", s); + if (ioEncodedFormat->type != B_MEDIA_RAW_AUDIO && ioEncodedFormat->type != B_MEDIA_RAW_VIDEO) return B_ERROR; fInputFormat = *ioEncodedFormat; - if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO) - fFrameSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row; - else - fFrameSize = (ioEncodedFormat->u.raw_audio.format & 0xf) * ioEncodedFormat->u.raw_audio.channel_count; + if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO) { + fInputSampleSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row; + fInputFrameSize = fInputSampleSize; + } else { + fInputSampleSize = (ioEncodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK); + fInputFrameSize = fInputSampleSize * ioEncodedFormat->u.raw_audio.channel_count; + } + + // since ioEncodedFormat is later passed to the application by BMediaTrack::EncodedFormat() + // we need to remove non public format specifications + + // remove non format bits, like channel order + ioEncodedFormat->u.raw_audio.format &= B_AUDIO_FORMAT_MASK; + + switch (ioEncodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + case B_AUDIO_FORMAT_INT8: + case B_AUDIO_FORMAT_INT16: + case B_AUDIO_FORMAT_INT32: + case B_AUDIO_FORMAT_FLOAT32: + break; // ok to pass through + + case B_AUDIO_FORMAT_INT24: + ioEncodedFormat->u.raw_audio.format = B_AUDIO_FORMAT_INT32; + break; + + case B_AUDIO_FORMAT_FLOAT64: + ioEncodedFormat->u.raw_audio.format = B_AUDIO_FORMAT_FLOAT32; + break; + + default: + TRACE("RawDecoder::Setup: unknown input format\n"); + return B_ERROR; + } return B_OK; } @@ -35,19 +73,331 @@ RawDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat) // 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 - + if (ioDecodedFormat->type == B_MEDIA_RAW_VIDEO) + return NegotiateVideoOutputFormat(ioDecodedFormat); + if (ioDecodedFormat->type == B_MEDIA_RAW_AUDIO) + return NegotiateAudioOutputFormat(ioDecodedFormat); + return B_ERROR; +} + + +status_t +RawDecoder::NegotiateVideoOutputFormat(media_format *ioDecodedFormat) +{ + return B_ERROR; +} + + +status_t +RawDecoder::NegotiateAudioOutputFormat(media_format *ioDecodedFormat) +{ char s[1024]; + + string_for_format(*ioDecodedFormat, s, sizeof(s)); + TRACE("RawDecoder::NegotiateAudioOutputFormat enter: %s\n", s); + + ioDecodedFormat->type = B_MEDIA_RAW_AUDIO; + switch (ioDecodedFormat->u.raw_audio.format) { + case media_raw_audio_format::B_AUDIO_FLOAT: + case media_raw_audio_format::B_AUDIO_SHORT: + case media_raw_audio_format::B_AUDIO_UCHAR: + case media_raw_audio_format::B_AUDIO_CHAR: + ioDecodedFormat->u.raw_audio.valid_bits = 0; + break; // we can produce this on request + + case media_raw_audio_format::B_AUDIO_INT: + ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits; + break; // we can produce this on request + + default: + switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { + case media_raw_audio_format::B_AUDIO_SHORT: + case media_raw_audio_format::B_AUDIO_UCHAR: + case media_raw_audio_format::B_AUDIO_CHAR: + ioDecodedFormat->u.raw_audio.format = fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK; + ioDecodedFormat->u.raw_audio.valid_bits = 0; + break; + + case media_raw_audio_format::B_AUDIO_INT: + case B_AUDIO_FORMAT_INT24: + ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; + ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits; + break; + + case media_raw_audio_format::B_AUDIO_FLOAT: + case B_AUDIO_FORMAT_FLOAT64: + default: + ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; + ioDecodedFormat->u.raw_audio.valid_bits = 0; + break; + } + break; + } + + fFrameRate = (int32) ioDecodedFormat->u.raw_audio.frame_rate; + ioDecodedFormat->u.raw_audio.frame_rate = fInputFormat.u.raw_audio.frame_rate; + ioDecodedFormat->u.raw_audio.channel_count = fInputFormat.u.raw_audio.channel_count; + + fOutputSampleSize = (ioDecodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK); + fOutputFrameSize = fOutputSampleSize * ioDecodedFormat->u.raw_audio.channel_count; + + if (ioDecodedFormat->u.raw_audio.byte_order == 0) + ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; + + ioDecodedFormat->u.raw_audio.channel_mask = 0; + ioDecodedFormat->u.raw_audio.matrix_mask = 0; + + if (ioDecodedFormat->u.raw_audio.buffer_size < 128 || ioDecodedFormat->u.raw_audio.buffer_size > 65536) { + ioDecodedFormat->u.raw_audio.buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor( + ioDecodedFormat->u.raw_audio.channel_count, + ioDecodedFormat->u.raw_audio.format, + ioDecodedFormat->u.raw_audio.frame_rate); + } else { + // round down to exact multiple of output frame size + ioDecodedFormat->u.raw_audio.buffer_size = (ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize) * fOutputFrameSize; + } + + fOutputBufferFrameCount = ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize; + + // setup input swapping function + if (fInputFormat.u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) { + fSwapInput = 0; + } else { + switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { + case B_AUDIO_FORMAT_INT16: + fSwapInput = &swap_int16; + break; + case B_AUDIO_FORMAT_INT24: + fSwapInput = &swap_int24; + break; + case B_AUDIO_FORMAT_INT32: + fSwapInput = &swap_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fSwapInput = &swap_float32; + break; + case B_AUDIO_FORMAT_FLOAT64: + fSwapInput = &swap_float64; + break; + case B_AUDIO_FORMAT_UINT8: + case B_AUDIO_FORMAT_INT8: + fSwapInput = 0; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown input format\n"); + break; + } + } + + // setup output swapping function + if (ioDecodedFormat->u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) { + fSwapOutput = 0; + } else { + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_INT16: + fSwapOutput = &swap_int16; + break; + case B_AUDIO_FORMAT_INT32: + fSwapOutput = &swap_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fSwapOutput = &swap_float32; + break; + case B_AUDIO_FORMAT_UINT8: + case B_AUDIO_FORMAT_INT8: + fSwapOutput = 0; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + } + + // setup sample conversation function + switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { + case B_AUDIO_FORMAT_UINT8: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &uint8_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &uint8_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &uint8_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &uint8_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &uint8_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_INT8: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &int8_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &int8_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &int8_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &int8_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &int8_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_INT16: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &int16_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &int16_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &int16_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &int16_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &int16_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_INT24: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &int24_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &int24_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &int24_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &int24_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &int24_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_INT32: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &int32_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &int32_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &int32_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &int32_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &int32_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_FLOAT32: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &float32_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &float32_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &float32_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &float32_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &float32_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + case B_AUDIO_FORMAT_FLOAT64: + switch (ioDecodedFormat->u.raw_audio.format) { + case B_AUDIO_FORMAT_UINT8: + fConvert = &float64_to_uint8; + break; + case B_AUDIO_FORMAT_INT8: + fConvert = &float64_to_int8; + break; + case B_AUDIO_FORMAT_INT16: + fConvert = &float64_to_int16; + break; + case B_AUDIO_FORMAT_INT32: + fConvert = &float64_to_int32; + break; + case B_AUDIO_FORMAT_FLOAT32: + fConvert = &float64_to_float32; + break; + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown output format\n"); + break; + } + break; + + default: + debugger("RawDecoder::NegotiateAudioOutputFormat unkown input format\n"); + break; + } + + fChunkBuffer = 0; + fChunkSize = 0; + fStartTime = 0; string_for_format(*ioDecodedFormat, s, sizeof(s)); - printf("RawDecoder::NegotiateOutputFormat enter: %s\n", s); - - // XXX we should allow different buffer size, sample format and byte order and do translation in decode! - - *ioDecodedFormat = fInputFormat; - - string_for_format(*ioDecodedFormat, s, sizeof(s)); - printf("RawDecoder::NegotiateOutputFormat leave: %s\n", s); - + TRACE("RawDecoder::NegotiateAudioOutputFormat leave: %s\n", s); +/* + TRACE("fFrameRate %ld\n", fFrameRate); + TRACE("fInputFrameSize %ld\n", fInputFrameSize); + TRACE("fOutputFrameSize %ld\n", fOutputFrameSize); + TRACE("fInputSampleSize %ld\n", fInputSampleSize); + TRACE("fOutputSampleSize %ld\n", fOutputSampleSize); + TRACE("fOutputBufferFrameCount %ld\n", fOutputBufferFrameCount); + TRACE("fSwapInput %p\n", fSwapInput); + TRACE("fConvert %p\n", fConvert); + TRACE("fSwapOutput %p\n", fSwapOutput); +*/ return B_OK; } @@ -57,6 +407,8 @@ RawDecoder::Seek(uint32 seekTo, int64 seekFrame, int64 *frame, bigtime_t seekTime, bigtime_t *time) { + fChunkSize = 0; + fStartTime = *time; return B_OK; } @@ -65,18 +417,38 @@ status_t RawDecoder::Decode(void *buffer, int64 *frameCount, media_header *mediaHeader, media_decode_info *info /* = 0 */) { - void *chunkBuffer; - int32 chunkSize; - status_t err; - - err = GetNextChunk(&chunkBuffer, &chunkSize, mediaHeader); - if (err != B_OK) - return err; + char *output_buffer = (char *)buffer; + mediaHeader->start_time = fStartTime; + *frameCount = 0; + while (*frameCount < fOutputBufferFrameCount) { + if (fChunkSize == 0) { + media_header mh; + status_t err; + err = GetNextChunk((void **)&fChunkBuffer, &fChunkSize, &mh); + if (err != B_OK || fChunkSize < fInputFrameSize) { + fChunkSize = 0; + break; + } + if (fSwapInput) + fSwapInput(fChunkBuffer, fChunkSize / fInputSampleSize); + fStartTime = mh.start_time; + continue; + } + int32 frames = min_c(fOutputBufferFrameCount - *frameCount, fChunkSize / fInputFrameSize); + int32 samples = frames * fInputFormat.u.raw_audio.channel_count; + fConvert(output_buffer, fChunkBuffer, samples); + fChunkBuffer += frames * fInputFrameSize; + fChunkSize -= frames * fInputFrameSize; + output_buffer += frames * fOutputFrameSize; + *frameCount += frames; + fStartTime += (1000000LL * frames) / fFrameRate; + } + // XXX should change channel order here for + // B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE and B_AUDIO_FORMAT_CHANNEL_ORDER_AIFF - memcpy(buffer, chunkBuffer, chunkSize); - *frameCount = chunkSize / fFrameSize; - - return B_OK; + if (fSwapOutput) + fSwapOutput(buffer, *frameCount * fInputFormat.u.raw_audio.channel_count); + return *frameCount ? B_OK : B_ERROR; } @@ -89,7 +461,7 @@ RawDecoderPlugin::NewDecoder() status_t RawDecoderPlugin::RegisterPlugin() { - PublishDecoder("audiocodec/raw", "raw", "RAW audio decoder", "{ WAV : 0x1 }, { QT : 0x20776172, 0x736f7774, 0x74776f73 }"); + PublishDecoder("audiocodec/raw", "raw", "RAW audio decoder"); PublishDecoder("videocodec/raw", "raw", "RAW video decoder"); return B_OK; } diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h index b5b91524d5..6e98cfee92 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h @@ -14,8 +14,27 @@ public: status_t Decode(void *buffer, int64 *frameCount, media_header *mediaHeader, media_decode_info *info); + private: - int32 fFrameSize; + status_t NegotiateVideoOutputFormat(media_format *ioDecodedFormat); + status_t NegotiateAudioOutputFormat(media_format *ioDecodedFormat); + +private: + int32 fFrameRate; + int32 fInputFrameSize; + int32 fOutputFrameSize; + int32 fInputSampleSize; + int32 fOutputSampleSize; + int32 fOutputBufferFrameCount; + void (*fSwapInput)(void *data, int32 count); + void (*fConvert)(void *dst, void *src, int32 count); + void (*fSwapOutput)(void *data, int32 count); + + char * fChunkBuffer; + int32 fChunkSize; + + bigtime_t fStartTime; + media_format fInputFormat; }; diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp index fb1c460c32..de4edb8d04 100644 --- a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp @@ -5,6 +5,7 @@ #include #include #include "WavReaderPlugin.h" +#include "RawFormats.h" #define TRACE_THIS 1 #if TRACE_THIS @@ -258,21 +259,22 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie) data->format.u.raw_audio.channel_count = fChannelCount; switch (fBitsPerSample) { case 8: - data->format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_UCHAR; + data->format.u.raw_audio.format = B_AUDIO_FORMAT_UINT8; break; case 16: - data->format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; + data->format.u.raw_audio.format = B_AUDIO_FORMAT_INT16; break; case 24: - data->format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; + data->format.u.raw_audio.format = B_AUDIO_FORMAT_INT24; break; case 32: - data->format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; + data->format.u.raw_audio.format = B_AUDIO_FORMAT_INT32; break; default: TRACE("WavReader::AllocateCookie: unhandled bits per sample %d\n", fBitsPerSample); return B_ERROR; } + data->format.u.raw_audio.format |= B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE; data->format.u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN; data->format.u.raw_audio.buffer_size = data->buffersize; } else { diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index f4699c25bd..84c2371652 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -2696,7 +2696,10 @@ BMediaRoster::AudioBufferSizeFor(int32 channel_count, bus_type bus_kind) { UNIMPLEMENTED(); - return 4096; + int size = 4096; + int framesize = (sample_format & 0xf) * channel_count; + size = (size / framesize) * framesize; + return size; }