aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2015-08-01 20:14:05 +0200
committerThierry Crozat2018-11-04 22:33:22 +0100
commitfc7fa1de3a204c65f73a0619199421bd7cdf780a (patch)
tree7135c6ba24b60a06006ee7d4ba596bdf171f9088
parent8b692f8d8993b977ae76a546a13e37fce7272bb2 (diff)
downloadscummvm-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.h48
-rw-r--r--image/codecs/mpeg.h23
-rw-r--r--video/mpegps_decoder.cpp114
-rw-r--r--video/mpegps_decoder.h29
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,