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, | 
