[Scummvm-git-logs] scummvm master -> 328c12a28db7e41b4d6c72248b65133680f7bf18
sev-
sev at scummvm.org
Thu Sep 24 16:52:36 UTC 2020
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
328c12a28d VIDEO: Added support for PS2 audio codec in MPEG stream
Commit: 328c12a28db7e41b4d6c72248b65133680f7bf18
https://github.com/scummvm/scummvm/commit/328c12a28db7e41b4d6c72248b65133680f7bf18
Author: PaweÅ KoÅodziejski (aquadran at users.sourceforge.net)
Date: 2020-09-24T18:52:31+02:00
Commit Message:
VIDEO: Added support for PS2 audio codec in MPEG stream
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 320b922103..5f6f711d47 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -21,11 +21,13 @@
*/
#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
#include "audio/decoders/ac3.h"
#include "audio/decoders/mp3.h"
#include "common/debug.h"
#include "common/endian.h"
#include "common/stream.h"
+#include "common/memstream.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -118,9 +120,15 @@ MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::Se
case kPrivateStreamDVDPCM:
typeName = "DVD PCM";
break;
- case kPrivateStreamPS2Audio:
+ case kPrivateStreamPS2Audio: {
typeName = "PS2 Audio";
+ handled = true;
+ PS2AudioTrack *audioTrack = new PS2AudioTrack(packet, getSoundType());
+ stream = audioTrack;
+ _streamMap[startCode] = audioTrack;
+ addTrack(audioTrack);
break;
+ }
default:
typeName = "Unknown";
break;
@@ -734,4 +742,115 @@ Audio::AudioStream *MPEGPSDecoder::AC3AudioTrack::getAudioStream() const {
#endif
+MPEGPSDecoder::PS2AudioTrack::PS2AudioTrack(Common::SeekableReadStream *firstPacket, Audio::Mixer::SoundType soundType) :
+ AudioTrack(soundType) {
+ firstPacket->seek(12); // unknown data (4), 'SShd', header size (4)
+
+ _soundType = firstPacket->readUint32LE();
+
+ if (_soundType == PS2_ADPCM)
+ error("Unhandled PS2 ADPCM sound in MPEG-PS video");
+ else if (_soundType != PS2_PCM)
+ error("Unknown PS2 sound type %x", _soundType);
+
+ uint32 sampleRate = firstPacket->readUint32LE();
+ _channels = firstPacket->readUint32LE();
+ _interleave = firstPacket->readUint32LE();
+
+ byte flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
+ if (_channels == 2)
+ flags |= Audio::FLAG_STEREO;
+
+ _blockBuffer = new byte[_interleave * _channels];
+ _blockPos = _blockUsed = 0;
+ _audStream = Audio::makePacketizedRawStream(sampleRate, flags);
+ _isFirstPacket = true;
+
+ firstPacket->seek(0);
+}
+
+MPEGPSDecoder::PS2AudioTrack::~PS2AudioTrack() {
+ delete[] _blockBuffer;
+ delete _audStream;
+}
+
+bool MPEGPSDecoder::PS2AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
+ packet->skip(4);
+
+ if (_isFirstPacket) {
+ // Skip over the header which we already parsed
+ packet->skip(4);
+ packet->skip(packet->readUint32LE());
+
+ if (packet->readUint32BE() != MKTAG('S', 'S', 'b', 'd'))
+ error("Failed to find 'SSbd' tag");
+
+ packet->readUint32LE(); // body size
+ _isFirstPacket = false;
+ }
+
+ uint32 size = packet->size() - packet->pos();
+ uint32 bytesPerChunk = _interleave * _channels;
+ uint32 sampleCount = calculateSampleCount(size);
+
+ byte *buffer = (byte *)malloc(sampleCount * 2);
+ int16 *ptr = (int16 *)buffer;
+
+ // Handle any full chunks first
+ while (size >= bytesPerChunk) {
+ packet->read(_blockBuffer + _blockPos, bytesPerChunk - _blockPos);
+ size -= bytesPerChunk - _blockPos;
+ _blockPos = 0;
+
+ for (uint32 i = _blockUsed; i < _interleave / 2; i++)
+ for (uint32 j = 0; j < _channels; j++)
+ *ptr++ = READ_UINT16(_blockBuffer + i * 2 + j * _interleave);
+
+ _blockUsed = 0;
+ }
+
+ // Then fallback on loading any leftover
+ if (size > 0) {
+ packet->read(_blockBuffer, size);
+ _blockPos = size;
+
+ if (size > (_channels - 1) * _interleave) {
+ _blockUsed = (size - (_channels - 1) * _interleave) / 2;
+
+ for (uint32 i = 0; i < _blockUsed; i++)
+ for (uint32 j = 0; j < _channels; j++)
+ *ptr++ = READ_UINT16(_blockBuffer + i * 2 + j * _interleave);
+ }
+ }
+
+ _audStream->queuePacket(new Common::MemoryReadStream(buffer, sampleCount * 2, DisposeAfterUse::YES));
+
+ delete packet;
+ return true;
+}
+
+Audio::AudioStream *MPEGPSDecoder::PS2AudioTrack::getAudioStream() const {
+ return _audStream;
+}
+
+uint32 MPEGPSDecoder::PS2AudioTrack::calculateSampleCount(uint32 packetSize) const {
+ uint32 bytesPerChunk = _interleave * _channels, result = 0;
+
+ // If we have a partial block, subtract the remainder from the size. That
+ // gets put towards reading the partial block
+ if (_blockPos != 0) {
+ packetSize -= bytesPerChunk - _blockPos;
+ result += (_interleave / 2) - _blockUsed;
+ }
+
+ // Round the number of whole chunks down and then calculate how many samples that gives us
+ result += (packetSize / bytesPerChunk) * _interleave / 2;
+
+ // Total up anything we can get from the remainder
+ packetSize %= bytesPerChunk;
+ if (packetSize > (_channels - 1) * _interleave)
+ result += (packetSize - (_channels - 1) * _interleave) / 2;
+
+ return result * _channels;
+}
} // End of namespace Video
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 7960639d78..24773db9ef 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -180,6 +180,36 @@ private:
};
#endif
+ class PS2AudioTrack : public AudioTrack, public MPEGStream {
+ public:
+ PS2AudioTrack(Common::SeekableReadStream *firstPacket, Audio::Mixer::SoundType soundType);
+ ~PS2AudioTrack();
+
+ bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts);
+ StreamType getStreamType() const { return kStreamTypeAudio; }
+
+ protected:
+ Audio::AudioStream *getAudioStream() const;
+
+ private:
+ Audio::PacketizedAudioStream *_audStream;
+
+ enum {
+ PS2_PCM = 0x01,
+ PS2_ADPCM = 0x10
+ };
+
+ uint32 _channels;
+ uint32 _soundType;
+ uint32 _interleave;
+ bool _isFirstPacket;
+
+ byte *_blockBuffer;
+ uint32 _blockPos, _blockUsed;
+
+ uint32 calculateSampleCount(uint32 packetSize) const;
+ };
+
// The different types of private streams we can detect at the moment
enum PrivateStreamType {
kPrivateStreamUnknown,
More information about the Scummvm-git-logs
mailing list