diff options
author | Torbjörn Andersson | 2015-08-01 20:14:05 +0200 |
---|---|---|
committer | Thierry Crozat | 2018-11-04 22:33:22 +0100 |
commit | fc7fa1de3a204c65f73a0619199421bd7cdf780a (patch) | |
tree | 7135c6ba24b60a06006ee7d4ba596bdf171f9088 | |
parent | 8b692f8d8993b977ae76a546a13e37fce7272bb2 (diff) | |
download | scummvm-rg350-fc7fa1de3a204c65f73a0619199421bd7cdf780a.tar.gz scummvm-rg350-fc7fa1de3a204c65f73a0619199421bd7cdf780a.tar.bz2 scummvm-rg350-fc7fa1de3a204c65f73a0619199421bd7cdf780a.zip |
VIDEO: Use liba52 to decode audio. This is still laughably broken
At the moment, this produces nothing but misery in the form of
Valgrind warnings and horrible noise.
-rw-r--r-- | common/inttypes.h | 48 | ||||
-rw-r--r-- | image/codecs/mpeg.h | 23 | ||||
-rw-r--r-- | video/mpegps_decoder.cpp | 114 | ||||
-rw-r--r-- | video/mpegps_decoder.h | 29 |
4 files changed, 187 insertions, 27 deletions
diff --git a/common/inttypes.h b/common/inttypes.h new file mode 100644 index 0000000000..88efa6f99e --- /dev/null +++ b/common/inttypes.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef COMMON_INTTYPES_H +#define COMMON_INTTYPES_H + +#if defined(__PLAYSTATION2__) + typedef uint8 uint8_t; + typedef uint16 uint16_t; + typedef uint32 uint32_t; +#elif defined(_WIN32_WCE) + typedef signed char int8_t; + typedef signed short int16_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; +#elif defined(_MSC_VER) || defined (__SYMBIAN32__) + typedef signed char int8_t; + typedef signed short int16_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + #if !defined(SDL_COMPILEDVERSION) || (SDL_COMPILEDVERSION < 1210) + typedef signed long int32_t; + typedef unsigned long uint32_t; + #endif +#else +# include <inttypes.h> +#endif + +#endif diff --git a/image/codecs/mpeg.h b/image/codecs/mpeg.h index 82c3ad19ac..b711b680aa 100644 --- a/image/codecs/mpeg.h +++ b/image/codecs/mpeg.h @@ -25,31 +25,10 @@ #ifndef IMAGE_CODECS_MPEG_H #define IMAGE_CODECS_MPEG_H +#include "common/inttypes.h" #include "image/codecs/codec.h" #include "graphics/pixelformat.h" -#if defined(__PLAYSTATION2__) - typedef uint8 uint8_t; - typedef uint16 uint16_t; - typedef uint32 uint32_t; -#elif defined(_WIN32_WCE) - typedef signed char int8_t; - typedef signed short int16_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; -#elif defined(_MSC_VER) || defined (__SYMBIAN32__) - typedef signed char int8_t; - typedef signed short int16_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - #if !defined(SDL_COMPILEDVERSION) || (SDL_COMPILEDVERSION < 1210) - typedef signed long int32_t; - typedef unsigned long uint32_t; - #endif -#else -# include <inttypes.h> -#endif - extern "C" { #include <mpeg2dec/mpeg2.h> } diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp index f7063eada0..af9e4f5bb0 100644 --- a/video/mpegps_decoder.cpp +++ b/video/mpegps_decoder.cpp @@ -109,13 +109,22 @@ void MPEGPSDecoder::readNextPacket() { packet->seek(0); // TODO: Handling of these types (as needed) - + bool handled = false; const char *typeName; switch (streamType) { - case kPrivateStreamAC3: + case kPrivateStreamAC3: { typeName = "AC-3"; + +#ifdef USE_A52 + handled = true; + AC3AudioTrack *ac3Track = new AC3AudioTrack(packet); + stream = ac3Track; + _streamMap[startCode] = ac3Track; + addTrack(ac3Track); +#endif break; + } case kPrivateStreamDTS: typeName = "DTS"; break; @@ -130,10 +139,12 @@ void MPEGPSDecoder::readNextPacket() { break; } - warning("Unhandled DVD private stream: %s", typeName); + if (!handled) { + warning("Unhandled DVD private stream: %s", typeName); - // Make it 0 so we don't get the warning twice - _streamMap[startCode] = 0; + // Make it 0 so we don't get the warning twice + _streamMap[startCode] = 0; + } } else if (startCode >= 0x1E0 && startCode <= 0x1EF) { // Video stream // TODO: Multiple video streams @@ -532,4 +543,97 @@ Audio::AudioStream *MPEGPSDecoder::MPEGAudioTrack::getAudioStream() const { #endif +#ifdef USE_A52 + +MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream *firstPacket) { + // In theory, I should pass mm_accel() to a52_init(), but I don't know + // where that's supposed to be defined. + _a52State = a52_init(0); + + initStream(firstPacket); + if (_sampleRate >= 0) { + _audStream = Audio::makeQueuingAudioStream(_sampleRate, true); + decodeAC3Data(firstPacket); + } else { + _audStream = 0; + firstPacket->seek(0); + } +} + +MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() { + delete _audStream; + a52_free(_a52State); +} + +bool MPEGPSDecoder::AC3AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) { + if (_audStream) { + initStream(packet); + decodeAC3Data(packet); + } + delete packet; + return true; +} + +Audio::AudioStream *MPEGPSDecoder::AC3AudioTrack::getAudioStream() const { + return _audStream; +} + +void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet) { + byte buf[7]; + + _sampleRate = -1; + + // Probably not very efficient, but hopefully we never do more than a + // few iterations of this loop. + for (uint i = 0; i < packet->size() - sizeof(buf); i++) { + int flags, bitRate; + + packet->seek(i, SEEK_SET); + packet->read(buf, sizeof(buf)); + + _packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate); + + if (_packetLength > 0) { + break; + } + } +} + +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]; + } + outputPtr += 512; + outputLength += 1024; + } + } + if (outputLength > 0) { + _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, Audio::FLAG_STEREO); + } + } + + delete[] buf; +} + +#endif + } // End of namespace Video diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h index 29f8c6e945..39b3a47af9 100644 --- a/video/mpegps_decoder.h +++ b/video/mpegps_decoder.h @@ -23,10 +23,16 @@ #ifndef VIDEO_MPEGPS_DECODER_H #define VIDEO_MPEGPS_DECODER_H +#include "common/inttypes.h" #include "common/hashmap.h" #include "graphics/surface.h" #include "video/video_decoder.h" +#ifdef USE_A52 +extern "C" { +#include <a52dec/a52.h> +} + namespace Audio { class PacketizedAudioStream; } @@ -127,6 +133,29 @@ private: }; #endif +#ifdef USE_A52 + class AC3AudioTrack : public AudioTrack, public MPEGStream { + public: + AC3AudioTrack(Common::SeekableReadStream *firstPacket); + ~AC3AudioTrack(); + + bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts); + StreamType getStreamType() const { return kStreamTypeAudio; } + + protected: + Audio::AudioStream *getAudioStream() const; + + private: + Audio::QueuingAudioStream *_audStream; + a52_state_t *_a52State; + int _sampleRate; + int _packetLength; + + void initStream(Common::SeekableReadStream *packet); + void decodeAC3Data(Common::SeekableReadStream *packet); + }; +#endif + // The different types of private streams we can detect at the moment enum PrivateStreamType { kPrivateStreamUnknown, |