aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorDavid Turner2010-06-16 04:47:18 +0000
committerDavid Turner2010-06-16 04:47:18 +0000
commit408bfa20981bfef70b904cdc396c175c9612b7c7 (patch)
tree5b187d806dd40e9f49f745842118093b6a199f70 /graphics
parente7275161f431d0025a7e2bb47bc2d442670fd155 (diff)
downloadscummvm-rg350-408bfa20981bfef70b904cdc396c175c9612b7c7.tar.gz
scummvm-rg350-408bfa20981bfef70b904cdc396c175c9612b7c7.tar.bz2
scummvm-rg350-408bfa20981bfef70b904cdc396c175c9612b7c7.zip
Fixed QDM2 to working state.
Major issue was that the input frames are reused 16 times to produce output frames. Thanks to clone2727 for helping with this. svn-id: r49900
Diffstat (limited to 'graphics')
-rw-r--r--graphics/video/codecs/qdm2.cpp159
-rw-r--r--graphics/video/qt_decoder.cpp4
2 files changed, 60 insertions, 103 deletions
diff --git a/graphics/video/codecs/qdm2.cpp b/graphics/video/codecs/qdm2.cpp
index e12be21303..9f151b4ba8 100644
--- a/graphics/video/codecs/qdm2.cpp
+++ b/graphics/video/codecs/qdm2.cpp
@@ -157,7 +157,7 @@ public:
~QDM2Stream();
bool isStereo() const { return _channels == 2; }
- bool endOfData() const { return ((_stream->pos() == _stream->size()) && (_outputSamples.size() == 0)); }
+ bool endOfData() const { return _stream->pos() >= _stream->size() && _outputSamples.size() == 0 && _subPacket == 0; }
int getRate() const { return _sampleRate; }
int readBuffer(int16 *buffer, const int numSamples);
@@ -199,7 +199,7 @@ private:
int _fftCoefsMinIndex[5];
int _fftCoefsMaxIndex[5];
int _fftLevelExp[6];
- //RDFTContext _rdftCtx;
+ RDFTContext _rdftCtx;
QDM2FFT _fft;
// I/O data
@@ -230,6 +230,7 @@ private:
int _doSynthFilter; // used to perform or skip synthesis filter
uint8 _subPacket; // 0 to 15
+ uint32 _superBlockStart;
int _noiseIdx; // index for dithering noise table
byte _emptyBuffer[FF_INPUT_BUFFER_PADDING_SIZE];
@@ -261,8 +262,6 @@ private:
float _noiseSamples[128];
void initNoiseSamples(void);
- RDFTContext _rdftCtx;
-
void average_quantized_coeffs(void);
void build_sb_samples_from_noise(int sb);
void fix_coding_method_array(int sb, int channels, sb_int8_array coding_method);
@@ -331,8 +330,6 @@ static inline int scummvm_log2(int n) {
static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize) {
int bufferSize = (bitSize + 7) >> 3;
- debug(1, "void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize)");
-
if (bufferSize < 0 || bitSize < 0) {
bufferSize = bitSize = 0;
buffer = NULL;
@@ -345,7 +342,6 @@ static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSiz
}
static inline int getBitsCount(GetBitContext *s) {
- debug(1, "int getBitsCount(GetBitContext *s)");
return s->index;
}
@@ -353,13 +349,9 @@ static inline unsigned int getBits1(GetBitContext *s) {
int index;
uint8 result;
- debug(1, "unsigned int getBits1(GetBitContext *s)");
-
index = s->index;
result = s->buffer[index >> 3];
- debug(1, "index : %d", index);
-
result >>= (index & 0x07);
result &= 1;
index++;
@@ -371,12 +363,8 @@ static inline unsigned int getBits1(GetBitContext *s) {
static inline unsigned int getBits(GetBitContext *s, int n) {
int tmp, reCache, reIndex;
- debug(1, "unsigned int getBits(GetBitContext *s, int n)");
-
reIndex = s->index;
- debug(1, "reIndex : %d", reIndex);
-
reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
tmp = (reCache) & ((uint32)0xffffffff >> (32 - n));
@@ -389,13 +377,9 @@ static inline unsigned int getBits(GetBitContext *s, int n) {
static inline void skipBits(GetBitContext *s, int n) {
int reIndex, reCache;
- debug(1, "void skipBits(GetBitContext *s, int n)");
-
reIndex = s->index;
reCache = 0;
- debug(1, "reIndex : %d", reIndex);
-
reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
s->index = reIndex + n;
}
@@ -1331,20 +1315,12 @@ static int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth)
int code;
int n;
- debug(1, "int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth)");
-
reIndex = s->index;
reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
index = reCache & (0xffffffff >> (32 - bits));
code = table[index][0];
n = table[index][1];
- debug(1, "reIndex : %d", reIndex);
- debug(1, "reCache : %d", reCache);
- debug(1, "index : %d", index);
- debug(1, "code : %d", code);
- debug(1, "n : %d", n);
-
if (maxDepth > 1 && n < 0){
reIndex += bits;
reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
@@ -1416,7 +1392,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
table_size = 1 << table_nb_bits;
table_index = allocTable(vlc, table_size, flags & 4);
- debug(2, "QDM2 new table index=%d size=%d code_prefix=%x n=%d", table_index, table_size, code_prefix, n_prefix);
if (table_index < 0)
return -1;
table = &vlc->table[table_index];
@@ -1437,7 +1412,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
symbol = i;
else
GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size);
- debug(2, "QDM2 i=%d n=%d code=0x%x", i, n, code);
// if code matches the prefix, it is in the table
n -= n_prefix;
if(flags & 2)
@@ -1452,7 +1426,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
for(k = 0; k < nb; k++) {
if(flags & 2)
j = (code >> n_prefix) + (k<<n);
- debug(2, "QDM2 %4x: code=%d n=%d",j, i, n);
if (table[j][1] /*bits*/ != 0) {
error("QDM2 incorrect codes");
return -1;
@@ -1464,7 +1437,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
} else {
n -= table_nb_bits;
j = (code >> ((flags & 2) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
- debug(2, "QDM2 %4x: n=%d (subtable)", j, n);
// compute table size
n1 = -table[j][1]; //bits
if (n > n1)
@@ -1537,8 +1509,6 @@ void initVlcSparse(VLC *vlc, int nb_bits, int nb_codes,
error("called on a partially initialized table");
}
- debug(2, "QDM2 build table nb_codes=%d", nb_codes);
-
if (build_table(vlc, nb_bits, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
@@ -1754,6 +1724,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
_stream = stream;
_compressedData = NULL;
_subPacket = 0;
+ _superBlockStart = 0;
memset(_quantizedCoeffs, 0, sizeof(_quantizedCoeffs));
memset(_fftLevelExp, 0, sizeof(_fftLevelExp));
_noiseIdx = 0;
@@ -2015,8 +1986,6 @@ static void qdm2_decode_sub_packet_header(GetBitContext *gb, QDM2SubPacket *sub_
sub_packet->data = &gb->buffer[getBitsCount(gb) / 8]; // FIXME: this depends on bitreader internal data
}
-
- debug(1, "QDM2 Subpacket: type=%d size=%d start_offs=%x", sub_packet->type, sub_packet->size, getBitsCount(gb) / 8);
}
/**
@@ -2881,7 +2850,6 @@ void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int durat
}
void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() duration: %d b:%d", duration, b);
int channel, stereo, phase, exp;
int local_int_4, local_int_8, stereo_phase, local_int_10;
int local_int_14, stereo_exp, local_int_20, local_int_28;
@@ -2896,9 +2864,7 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
while (1) {
if (_superblocktype_2_3) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8);
while ((n = qdm2_get_vlc(gb, &_vlcTabFftToneOffset[local_int_8], 1, 2)) < 2) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8);
offset = 1;
if (n == 0) {
local_int_4 += local_int_10;
@@ -2959,7 +2925,6 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
}
void QDM2Stream::qdm2_decode_fft_packets(void) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets()");
int i, j, min, max, value, type, unknown_flag;
GetBitContext gb;
@@ -2994,7 +2959,6 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
return;
// decode FFT tones
- debug(1, "QDM2Stream::qdm2_decode_fft_packets initGetBits() packet->size*8: %d", packet->size*8);
initGetBits(&gb, packet->data, packet->size*8);
if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16])
@@ -3008,19 +2972,16 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
int duration = _subSampling + 5 - (type & 15);
if (duration >= 0 && duration < 4) { // TODO: Should be <= 4?
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #1");
qdm2_fft_decode_tones(duration, &gb, unknown_flag);
}
} else if (type == 31) {
for (j=0; j < 4; j++) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #2");
qdm2_fft_decode_tones(j, &gb, unknown_flag);
}
} else if (type == 46) {
for (j=0; j < 6; j++)
_fftLevelExp[j] = getBits(&gb, 6);
for (j=0; j < 4; j++) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #3");
qdm2_fft_decode_tones(j, &gb, unknown_flag);
}
}
@@ -3151,16 +3112,12 @@ void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) {
}
void QDM2Stream::qdm2_calculate_fft(int channel) {
- debug(1, "QDM2Stream::qdm2_calculate_fft channel: %d", channel);
const float gain = (_channels == 1 && _channels == 2) ? 0.5f : 1.0f;
int i;
_fft.complex[channel][0].re *= 2.0f;
_fft.complex[channel][0].im = 0.0f;
- //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].re: %lf", _fft.complex[channel][0].re);
- //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].im: %lf", _fft.complex[channel][0].im);
-
rdftCalc(&_rdftCtx, (float *)_fft.complex[channel]);
// add samples to output buffer
@@ -3209,82 +3166,80 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
int ch, i;
const int frame_size = (_sFrameSize * _channels);
+ // If we're in any packet but the first, seek back to the first
+ if (_subPacket == 0)
+ _superBlockStart = in->pos();
+ else
+ in->seek(_superBlockStart);
+
// select input buffer
- if(in->eos() || in->size() == in->pos()) {
+ if (in->eos() || in->pos() >= in->size()) {
debug(1, "QDM2Stream::qdm2_decodeFrame End of Input Stream");
return 0;
}
- if((in->size() - in->pos()) < _packetSize) {
+
+ if ((in->size() - in->pos()) < _packetSize) {
debug(1, "QDM2Stream::qdm2_decodeFrame Insufficient Packet Data in Input Stream Found: %d Need: %d", in->size() - in->pos(), _packetSize);
return 0;
}
- in->read(_compressedData, _packetSize);
- debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data");
+ if (!in->eos()) {
+ in->read(_compressedData, _packetSize);
+ debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data");
+ }
// copy old block, clear new block of output samples
memmove(_outputBuffer, &_outputBuffer[frame_size], frame_size * sizeof(float));
memset(&_outputBuffer[frame_size], 0, frame_size * sizeof(float));
debug(1, "QDM2Stream::qdm2_decodeFrame cleared outputBuffer");
- // decode block of QDM2 compressed data
- debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data");
- if (_subPacket == 0) {
- _hasErrors = false; // reset it for a new super block
- debug(1, "QDM2 : Superblock follows");
- qdm2_decode_super_block();
- }
-
- // parse subpackets
- debug(1, "QDM2Stream::qdm2_decodeFrame parse subpackets");
- if (!_hasErrors) {
- if (_subPacket == 2) {
- debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_decode_fft_packets()");
- qdm2_decode_fft_packets();
+ if (!in->eos()) {
+ // decode block of QDM2 compressed data
+ debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data");
+ if (_subPacket == 0) {
+ _hasErrors = false; // reset it for a new super block
+ debug(1, "QDM2 : Superblock follows");
+ qdm2_decode_super_block();
}
- debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket);
- qdm2_fft_tone_synthesizer(_subPacket);
- }
-
- // sound synthesis stage 1 (FFT)
- debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 1 (FFT)");
- for (ch = 0; ch < _channels; ch++) {
- qdm2_calculate_fft(ch);
+ // parse subpackets
+ debug(1, "QDM2Stream::qdm2_decodeFrame parse subpackets");
+ if (!_hasErrors) {
+ if (_subPacket == 2) {
+ debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_decode_fft_packets()");
+ qdm2_decode_fft_packets();
+ }
- if (!_hasErrors && _subPacketListC[0].packet != NULL) {
- error("QDM2 : has errors, and C list is not empty");
- return 0;
+ debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket);
+ qdm2_fft_tone_synthesizer(_subPacket);
}
- }
- // sound synthesis stage 2 (MPEG audio like synthesis filter)
- debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 2 (MPEG audio like synthesis filter)");
- if (!_hasErrors && _doSynthFilter)
- qdm2_synthesis_filter(_subPacket);
+ // sound synthesis stage 1 (FFT)
+ debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 1 (FFT)");
+ for (ch = 0; ch < _channels; ch++) {
+ qdm2_calculate_fft(ch);
- _subPacket = (_subPacket + 1) % 16;
+ if (!_hasErrors && _subPacketListC[0].packet != NULL) {
+ error("QDM2 : has errors, and C list is not empty");
+ return 0;
+ }
+ }
- if(_hasErrors)
- warning("QDM2 Packet error...");
+ // sound synthesis stage 2 (MPEG audio like synthesis filter)
+ debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 2 (MPEG audio like synthesis filter)");
+ if (!_hasErrors && _doSynthFilter)
+ qdm2_synthesis_filter(_subPacket);
- // clip and convert output float[] to 16bit signed samples
- debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples");
+ _subPacket = (_subPacket + 1) % 16;
-/*
- debugN(1, "Input Data Packet:");
- for(i = 0; i < _packetSize; i++) {
- debugN(1, " %d", _compressedData[i]);
- }
- debugN(1, " Output Data Packet:");
- for(i = 0; i < frame_size; i++) {
- debugN(1, " %d", (int)_outputBuffer[i]);
+ if(_hasErrors)
+ warning("QDM2 Packet error...");
+
+ // clip and convert output float[] to 16bit signed samples
+ debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples");
}
- debug(1, "");
-*/
for (i = 0; i < frame_size; i++) {
- //debug(1, "QDM2Stream::qdm2_decodeFrame i: %d", i);
int value = (int)_outputBuffer[i];
if (value > SOFTCLIP_THRESHOLD)
@@ -3302,17 +3257,17 @@ int QDM2Stream::readBuffer(int16 *buffer, const int numSamples) {
int32 decodedSamples = _outputSamples.size();
int32 i;
- //while((int)_outputSamples.size() < numSamples) {
- while(!_stream->eos() && _stream->pos() != _stream->size()) {
+ while (decodedSamples < numSamples) {
i = qdm2_decodeFrame(_stream);
- if(i == 0)
+ if (i == 0)
break; // Out Of Decode Frames...
decodedSamples += i;
}
- if(decodedSamples > numSamples)
+
+ if (decodedSamples > numSamples)
decodedSamples = numSamples;
- for(i = 0; i < decodedSamples; i++)
+ for (i = 0; i < decodedSamples; i++)
buffer[i] = _outputSamples.remove_at(0);
return decodedSamples;
diff --git a/graphics/video/qt_decoder.cpp b/graphics/video/qt_decoder.cpp
index 49d2b0aed9..842c38f315 100644
--- a/graphics/video/qt_decoder.cpp
+++ b/graphics/video/qt_decoder.cpp
@@ -191,8 +191,10 @@ Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) {
}
void QuickTimeDecoder::startAudio() {
- if (_audStream) // No audio/audio not supported
+ if (_audStream) { // No audio/audio not supported
+ updateAudioBuffer();
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream);
+ }
}
void QuickTimeDecoder::stopAudio() {