diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/mpegps_decoder.cpp | 104 | ||||
-rw-r--r-- | video/mpegps_decoder.h | 5 |
2 files changed, 76 insertions, 33 deletions
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp index af9e4f5bb0..e34053da73 100644 --- a/video/mpegps_decoder.cpp +++ b/video/mpegps_decoder.cpp @@ -553,11 +553,14 @@ MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream *firstPac initStream(firstPacket); if (_sampleRate >= 0) { _audStream = Audio::makeQueuingAudioStream(_sampleRate, true); - decodeAC3Data(firstPacket); } else { _audStream = 0; firstPacket->seek(0); } + + _inBufPtr = _inBuf; + _flags = 0; + _frameSize = 0; } MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() { @@ -567,7 +570,6 @@ MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() { bool MPEGPSDecoder::AC3AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) { if (_audStream) { - initStream(packet); decodeAC3Data(packet); } delete packet; @@ -591,47 +593,85 @@ void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet packet->seek(i, SEEK_SET); packet->read(buf, sizeof(buf)); - _packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate); + int packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate); - if (_packetLength > 0) { + if (packetLength > 0) { break; } } } +enum { + HEADER_SIZE = 7 +}; + void MPEGPSDecoder::AC3AudioTrack::decodeAC3Data(Common::SeekableReadStream *packet) { - // This doesn't work since _packetLength is often longer than the, - // stream, which may go a long way towards explaining all the Valgrind - // errors I'm getting. Not to mention that the output sounds nothing - // at all like what I want. - byte *buf = new byte[_packetLength]; - packet->read(buf, _packetLength); - - int flags = A52_STEREO | A52_ADJUST_LEVEL; - sample_t level = 32767; - int bias = 0; - - if (a52_frame(_a52State, buf, &flags, &level, bias) == 0) { - int16 *outputBuffer = (int16 *)malloc(6 * 512 * sizeof(int16)); - int16 *outputPtr = outputBuffer; - int outputLength = 0; - for (int i = 0; i < 6; i++) { - if (a52_block(_a52State)) { - sample_t *samples = a52_samples(_a52State); - for (int j = 0; j < 256; j++) { - outputPtr[j * 2] = (int16)samples[j]; - outputPtr[j * 2 + 1] = (int16)samples[256 + j]; + while (packet->pos() < packet->size()) { + uint32 leftSize = packet->size() - packet->pos(); + uint32 len = _inBufPtr - _inBuf; + if (_frameSize == 0) { + // No header seen: find one + len = HEADER_SIZE - len; + if (len > leftSize) + len = leftSize; + packet->read(_inBufPtr, len); + leftSize -= len; + _inBufPtr += len; + if ((_inBufPtr - _inBuf) == HEADER_SIZE) { + int sampleRate, bitRate; + len = a52_syncinfo(_inBuf, &_flags, &sampleRate, &bitRate); + if (len == 0) { + memmove(_inBuf, _inBuf + 1, HEADER_SIZE - 1); + _inBufPtr--; + } else { + _frameSize = len; } - outputPtr += 512; - outputLength += 1024; } - } - if (outputLength > 0) { - _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, Audio::FLAG_STEREO); + } else if (len < _frameSize) { + len = _frameSize - len; + if (len > leftSize) + len = leftSize; + + assert(len < sizeof(_inBuf) - (_inBufPtr - _inBuf)); + packet->read(_inBufPtr, len); + leftSize -= len; + _inBufPtr += len; + } else { + int flags = A52_STEREO | A52_ADJUST_LEVEL; + sample_t level = 32767; + + if (a52_frame(_a52State, _inBuf, &flags, &level, 0) != 0) + error("Frame fail"); + + int16 *outputBuffer = (int16 *)malloc(6 * 256 * 2 * 2); + int16 *outputPtr = outputBuffer; + int outputLength = 0; + for (int i = 0; i < 6; i++) { + if (a52_block(_a52State) == 0) { + sample_t *samples = a52_samples(_a52State); + for (int j = 0; j < 256; j++) { + *outputPtr++ = (int16)samples[j]; + *outputPtr++ = (int16)samples[j + 256]; + } + + outputLength += 1024; + } + } + + if (outputLength > 0) { + flags = Audio::FLAG_STEREO | Audio::FLAG_16BITS; + +#ifdef SCUMM_LITTLE_ENDIAN + flags |= Audio::FLAG_LITTLE_ENDIAN; +#endif + + _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, flags); + } + + _inBufPtr = _inBuf; + _frameSize = 0; } } - - delete[] buf; } #endif diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h index 39b3a47af9..bf9c28e952 100644 --- a/video/mpegps_decoder.h +++ b/video/mpegps_decoder.h @@ -148,8 +148,11 @@ private: private: Audio::QueuingAudioStream *_audStream; a52_state_t *_a52State; + uint32 _frameSize; + byte _inBuf[4096]; + byte *_inBufPtr; + int _flags; int _sampleRate; - int _packetLength; void initStream(Common::SeekableReadStream *packet); void decodeAC3Data(Common::SeekableReadStream *packet); |