raw decoder supports many samples types now, and support for them

has been added to the file readers, you can now play 24 bit integer
or 64 bit floating point files


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5770 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-12-27 14:51:14 +00:00
parent cf706dc774
commit bb1d6ef247
11 changed files with 708 additions and 44 deletions
+2 -2
View File
@@ -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,
@@ -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),
@@ -4,6 +4,7 @@
#include <DataIO.h>
#include <ByteOrder.h>
#include <InterfaceDefs.h>
#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");
@@ -4,6 +4,7 @@
#include <DataIO.h>
#include <ByteOrder.h>
#include <InterfaceDefs.h>
#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");
@@ -0,0 +1,211 @@
#include <ByteOrder.h>
#include <OS.h>
#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);
}
@@ -0,0 +1,54 @@
#ifndef _AUDIO_CONVERSION_H
#define _AUDIO_CONVERSION_H
#include <SupportDefs.h>
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
@@ -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
;
@@ -1,13 +1,17 @@
#include <stdio.h>
#include <string.h>
#include <DataIO.h>
#include <OS.h>
#include <MediaRoster.h>
#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;
}
@@ -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;
};
@@ -5,6 +5,7 @@
#include <ByteOrder.h>
#include <InterfaceDefs.h>
#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 {
+4 -1
View File
@@ -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;
}