aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
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,