aboutsummaryrefslogtreecommitdiff
path: root/video
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 /video
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.
Diffstat (limited to 'video')
-rw-r--r--video/mpegps_decoder.cpp114
-rw-r--r--video/mpegps_decoder.h29
2 files changed, 138 insertions, 5 deletions
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,