[Scummvm-git-logs] scummvm master -> e4ff1929aa7823c3716a9ea48e1f8a9524154742
criezy
criezy at scummvm.org
Sun Nov 4 22:33:38 CET 2018
This automated email contains information about 20 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
8b692f8d89 CONFIGURE: Add detection of liba52
fc7fa1de3a VIDEO: Use liba52 to decode audio. This is still laughably broken
e9052a0085 ZVISION: Enable hi-res videos for testing purposes
ad41dfb7ff VIDEO: Committed fixes from clone2727
89ec9766a1 VIDEO: After figuring out sample rate, rewind the AC-3 stream
4cc71d42a2 ZVISION: Play hi-res videos, even if they have no low-res version
e6abe39752 VIDEO: Skip DVD code. The sound plays, but audio/video sync is off
ef70af5e99 VIDEO: Some minor cleanups to the AC-3 decoder
6705b6df9e AUDIO: Add a separate AC-3 decoder
43b29a93d7 VIDEO: Use the standalone AC-3 decoder in the MPEG-PS code
d4f8b330d6 IMAGE: Honor nb_fields when calculating frame duration
b672a694b9 VIDEO: Synchronize video to pts timestamps
ac40828ed2 VIDEO: Make the video pts sync easier to understand
1d69564876 VIDEO: Moved MPEGStream creation out of readNextPacket()
1255e8de4d VIDEO: Removed _psmESType
a5b5b68a1a VIDEO: Use all video PTS's
7c58534f4f VIDEO: Add buffering demuxer to MPEG-PS decoder
71910c2283 ZVISION: Set 800x600 mode for the DVD version of ZGI
e2935acfe4 ZVISION: Disable MPEG movies when liba52 is not enabled
e4ff1929aa ZVISION: Only add mpeg video engine options when mpeg and a52 are enabled
Commit: 8b692f8d8993b977ae76a546a13e37fce7272bb2
https://github.com/scummvm/scummvm/commit/8b692f8d8993b977ae76a546a13e37fce7272bb2
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
CONFIGURE: Add detection of liba52
This is for an experiment aiming to decode audio for the hi-res
videos in Zork: Grand Inquisitor. I don't know if we want to add
a dependency on liba52, but the license should allow us to include
the code verbatim, if that's preferrable.
Changed paths:
configure
diff --git a/configure b/configure
index f590fe6..0fbc5a1 100755
--- a/configure
+++ b/configure
@@ -149,6 +149,7 @@ _sndio=auto
_timidity=auto
_zlib=auto
_mpeg2=auto
+_a52=auto
_sparkle=auto
_osxdockplugin=auto
_jpeg=auto
@@ -1046,7 +1047,10 @@ Optional Libraries:
--with-mpeg2-prefix=DIR prefix where libmpeg2 is installed (optional)
--enable-mpeg2 enable mpeg2 codec for cutscenes [autodetect]
- --with-jpeg-prefix=DIR prefix where libjpeg is installed (optional)
+ --with-a52-prefix=DIR Prefix where liba52 is installed (optional)
+ --enable-a52 enable a52 codec for MPEG decoder [autodetect]
+
+ --with-jpeg-prefix=DIR Prefix where libjpeg is installed (optional)
--disable-jpeg disable JPEG decoder [autodetect]
--with-png-prefix=DIR prefix where libpng is installed (optional)
@@ -1176,6 +1180,8 @@ for ac_option in $@; do
--disable-nasm) _nasm=no ;;
--enable-mpeg2) _mpeg2=yes ;;
--disable-mpeg2) _mpeg2=no ;;
+ --enable-a52) _a52=yes ;;
+ --disable-a52) _a52=no ;;
--disable-jpeg) _jpeg=no ;;
--enable-jpeg) _jpeg=yes ;;
--disable-png) _png=no ;;
@@ -1233,6 +1239,11 @@ for ac_option in $@; do
MPEG2_CFLAGS="-I$arg/include"
MPEG2_LIBS="-L$arg/lib"
;;
+ --with-a52-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ A52_CFLAGS="-I$arg/include"
+ A52_LIBS="-L$arg/lib"
+ ;;
--with-alsa-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
ALSA_CFLAGS="-I$arg/include"
@@ -4428,6 +4439,46 @@ define_in_config_if_yes "$_mpeg2" 'USE_MPEG2'
echo "$_mpeg2"
#
+# Check for liba52
+#
+echocheck "liba52"
+if test "$_a52" = auto ; then
+ _a52=no
+ cat > $TMPC << EOF
+typedef signed $type_1_byte int8_t;
+typedef signed $type_2_byte int16_t;
+typedef signed $type_4_byte int32_t;
+
+typedef unsigned $type_1_byte uint8_t;
+typedef unsigned $type_2_byte uint16_t;
+typedef unsigned $type_4_byte uint32_t;
+
+extern "C" {
+#include <a52dec/a52.h>
+}
+
+int main(void) {
+ a52_init(0);
+ return 0;
+}
+EOF
+
+ if test -n "$_host"; then
+ # don't execute while cross compiling
+ cc_check $A52_CFLAGS $A52_LIBS -la52 && _a52=yes
+ else
+ cc_check_no_clean $A52_CFLAGS $A52_LIBS -la52 && $TMPO$HOSTEXEEXT && _a52=yes
+ cc_check_clean
+ fi
+fi
+if test "$_a52" = yes ; then
+ INCLUDES="$INCLUDES $A52_FLAGS"
+ LIBS="$LIBS $A52_LIBS -la52"
+fi
+define_in_config_if_yes "$_a52" 'USE_A52'
+echo "$_a52"
+
+#
# Check for Sparkle if updates support is enabled
#
case $_host_os in
Commit: fc7fa1de3a204c65f73a0619199421bd7cdf780a
https://github.com/scummvm/scummvm/commit/fc7fa1de3a204c65f73a0619199421bd7cdf780a
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
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.
Changed paths:
A common/inttypes.h
image/codecs/mpeg.h
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/common/inttypes.h b/common/inttypes.h
new file mode 100644
index 0000000..88efa6f
--- /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 82c3ad1..b711b68 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 f7063ea..af9e4f5 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 29f8c6e..39b3a47 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,
Commit: e9052a008578b42ca5f5e869ef9e6ebe969cb929
https://github.com/scummvm/scummvm/commit/e9052a008578b42ca5f5e869ef9e6ebe969cb929
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
ZVISION: Enable hi-res videos for testing purposes
Changed paths:
engines/zvision/scripting/actions.cpp
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index d77262f..50e4a41 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -980,9 +980,8 @@ bool ActionStreamVideo::execute() {
// TODO: Enable once AC3 support is implemented
if (!_engine->getSearchManager()->hasFile(_fileName)) // Check for the regular video
return true;
- warning("The hires videos of the DVD version of ZGI aren't supported yet, using lowres");
- //_fileName = hiresFileName;
- //switchToHires = true;
+ _fileName = hiresFileName;
+ switchToHires = true;
} else if (!_engine->getSearchManager()->hasFile(_fileName))
return true;
#else
Commit: ad41dfb7ff25daf9e974c6c9dbdfb099307af4f7
https://github.com/scummvm/scummvm/commit/ad41dfb7ff25daf9e974c6c9dbdfb099307af4f7
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Committed fixes from clone2727
This collects the whole frame before trying to decode it. It's
still now working right, but it's way better than it was before.
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index af9e4f5..e34053d 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -553,11 +553,14 @@ MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream *firstPac
initStream(firstPacket);
if (_sampleRate >= 0) {
_audStream = Audio::makeQueuingAudioStream(_sampleRate, true);
- decodeAC3Data(firstPacket);
} else {
_audStream = 0;
firstPacket->seek(0);
}
+
+ _inBufPtr = _inBuf;
+ _flags = 0;
+ _frameSize = 0;
}
MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() {
@@ -567,7 +570,6 @@ MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() {
bool MPEGPSDecoder::AC3AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
if (_audStream) {
- initStream(packet);
decodeAC3Data(packet);
}
delete packet;
@@ -591,47 +593,85 @@ void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet
packet->seek(i, SEEK_SET);
packet->read(buf, sizeof(buf));
- _packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate);
+ int packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate);
- if (_packetLength > 0) {
+ if (packetLength > 0) {
break;
}
}
}
+enum {
+ HEADER_SIZE = 7
+};
+
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];
+ while (packet->pos() < packet->size()) {
+ uint32 leftSize = packet->size() - packet->pos();
+ uint32 len = _inBufPtr - _inBuf;
+ if (_frameSize == 0) {
+ // No header seen: find one
+ len = HEADER_SIZE - len;
+ if (len > leftSize)
+ len = leftSize;
+ packet->read(_inBufPtr, len);
+ leftSize -= len;
+ _inBufPtr += len;
+ if ((_inBufPtr - _inBuf) == HEADER_SIZE) {
+ int sampleRate, bitRate;
+ len = a52_syncinfo(_inBuf, &_flags, &sampleRate, &bitRate);
+ if (len == 0) {
+ memmove(_inBuf, _inBuf + 1, HEADER_SIZE - 1);
+ _inBufPtr--;
+ } else {
+ _frameSize = len;
}
- outputPtr += 512;
- outputLength += 1024;
}
- }
- if (outputLength > 0) {
- _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, Audio::FLAG_STEREO);
+ } else if (len < _frameSize) {
+ len = _frameSize - len;
+ if (len > leftSize)
+ len = leftSize;
+
+ assert(len < sizeof(_inBuf) - (_inBufPtr - _inBuf));
+ packet->read(_inBufPtr, len);
+ leftSize -= len;
+ _inBufPtr += len;
+ } else {
+ int flags = A52_STEREO | A52_ADJUST_LEVEL;
+ sample_t level = 32767;
+
+ if (a52_frame(_a52State, _inBuf, &flags, &level, 0) != 0)
+ error("Frame fail");
+
+ int16 *outputBuffer = (int16 *)malloc(6 * 256 * 2 * 2);
+ int16 *outputPtr = outputBuffer;
+ int outputLength = 0;
+ for (int i = 0; i < 6; i++) {
+ if (a52_block(_a52State) == 0) {
+ sample_t *samples = a52_samples(_a52State);
+ for (int j = 0; j < 256; j++) {
+ *outputPtr++ = (int16)samples[j];
+ *outputPtr++ = (int16)samples[j + 256];
+ }
+
+ outputLength += 1024;
+ }
+ }
+
+ if (outputLength > 0) {
+ flags = Audio::FLAG_STEREO | Audio::FLAG_16BITS;
+
+#ifdef SCUMM_LITTLE_ENDIAN
+ flags |= Audio::FLAG_LITTLE_ENDIAN;
+#endif
+
+ _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, flags);
+ }
+
+ _inBufPtr = _inBuf;
+ _frameSize = 0;
}
}
-
- delete[] buf;
}
#endif
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 39b3a47..bf9c28e 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -148,8 +148,11 @@ private:
private:
Audio::QueuingAudioStream *_audStream;
a52_state_t *_a52State;
+ uint32 _frameSize;
+ byte _inBuf[4096];
+ byte *_inBufPtr;
+ int _flags;
int _sampleRate;
- int _packetLength;
void initStream(Common::SeekableReadStream *packet);
void decodeAC3Data(Common::SeekableReadStream *packet);
Commit: 89ec9766a135e5842c45d7f3dd3e6b6fe960df78
https://github.com/scummvm/scummvm/commit/89ec9766a135e5842c45d7f3dd3e6b6fe960df78
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: After figuring out sample rate, rewind the AC-3 stream
Changed paths:
video/mpegps_decoder.cpp
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index e34053d..178a2a4 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -593,12 +593,12 @@ void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet
packet->seek(i, SEEK_SET);
packet->read(buf, sizeof(buf));
- int packetLength = a52_syncinfo(buf, &flags, &_sampleRate, &bitRate);
-
- if (packetLength > 0) {
+ if (a52_syncinfo(buf, &flags, &_sampleRate, &bitRate) > 0) {
break;
}
}
+
+ packet->seek(0, SEEK_SET);
}
enum {
Commit: 4cc71d42a283b5064ad30806aa92f20e3ea69198
https://github.com/scummvm/scummvm/commit/4cc71d42a283b5064ad30806aa92f20e3ea69198
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
ZVISION: Play hi-res videos, even if they have no low-res version
This is used for some logo animations at the start of the game. I
don't know if it's used for anything else, but probably not.
Changed paths:
engines/zvision/scripting/actions.cpp
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index 50e4a41..794336e 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -977,9 +977,6 @@ bool ActionStreamVideo::execute() {
hiresFileName.setChar('b', hiresFileName.size() - 1);
if (_scriptManager->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) {
- // TODO: Enable once AC3 support is implemented
- if (!_engine->getSearchManager()->hasFile(_fileName)) // Check for the regular video
- return true;
_fileName = hiresFileName;
switchToHires = true;
} else if (!_engine->getSearchManager()->hasFile(_fileName))
Commit: e6abe39752c694ec0f873825a7465a00adc57ffe
https://github.com/scummvm/scummvm/commit/e6abe39752c694ec0f873825a7465a00adc57ffe
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Skip DVD code. The sound plays, but audio/video sync is off
Like most things that make this branch actually work, this comes
from clone2727.
Changed paths:
video/mpegps_decoder.cpp
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 178a2a4..0d91bbe 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -606,6 +606,11 @@ enum {
};
void MPEGPSDecoder::AC3AudioTrack::decodeAC3Data(Common::SeekableReadStream *packet) {
+ // Skip the DVD code
+ packet->readUint32LE();
+ if (packet->eos())
+ return;
+
while (packet->pos() < packet->size()) {
uint32 leftSize = packet->size() - packet->pos();
uint32 len = _inBufPtr - _inBuf;
Commit: ef70af5e991e0c60465385c9a84bdefdd54f9bd2
https://github.com/scummvm/scummvm/commit/ef70af5e991e0c60465385c9a84bdefdd54f9bd2
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Some minor cleanups to the AC-3 decoder
Changed paths:
video/mpegps_decoder.cpp
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 0d91bbe..f4addf9 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -555,9 +555,10 @@ MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream *firstPac
_audStream = Audio::makeQueuingAudioStream(_sampleRate, true);
} else {
_audStream = 0;
- firstPacket->seek(0);
}
+ firstPacket->seek(0);
+
_inBufPtr = _inBuf;
_flags = 0;
_frameSize = 0;
@@ -580,8 +581,12 @@ Audio::AudioStream *MPEGPSDecoder::AC3AudioTrack::getAudioStream() const {
return _audStream;
}
+enum {
+ HEADER_SIZE = 7
+};
+
void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet) {
- byte buf[7];
+ byte buf[HEADER_SIZE];
_sampleRate = -1;
@@ -597,14 +602,8 @@ void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet
break;
}
}
-
- packet->seek(0, SEEK_SET);
}
-enum {
- HEADER_SIZE = 7
-};
-
void MPEGPSDecoder::AC3AudioTrack::decodeAC3Data(Common::SeekableReadStream *packet) {
// Skip the DVD code
packet->readUint32LE();
Commit: 6705b6df9e85beb61f9824a65475cc8f26dcdc34
https://github.com/scummvm/scummvm/commit/6705b6df9e85beb61f9824a65475cc8f26dcdc34
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
AUDIO: Add a separate AC-3 decoder
This code comes from clone2727's now defunct (?) ac3 branch.
Changed paths:
A audio/decoders/ac3.cpp
A audio/decoders/ac3.h
audio/module.mk
diff --git a/audio/decoders/ac3.cpp b/audio/decoders/ac3.cpp
new file mode 100644
index 0000000..c569179
--- /dev/null
+++ b/audio/decoders/ac3.cpp
@@ -0,0 +1,201 @@
+/* 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.
+ *
+ */
+
+#include "common/inttypes.h"
+#include "common/ptr.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+
+#include "audio/audiostream.h"
+#include "audio/decoders/ac3.h"
+#include "audio/decoders/raw.h"
+
+extern "C" {
+#include <a52dec/a52.h>
+}
+
+namespace Audio {
+
+class AC3Stream : public PacketizedAudioStream {
+public:
+ AC3Stream();
+ ~AC3Stream();
+
+ bool init(Common::SeekableReadStream &firstPacket);
+ void deinit();
+
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples) { return _audStream->readBuffer(buffer, numSamples); }
+ bool isStereo() const { return _audStream->isStereo(); }
+ int getRate() const { return _audStream->getRate(); }
+ bool endOfData() const { return _audStream->endOfData(); }
+ bool endOfStream() const { return _audStream->endOfStream(); }
+
+ // PacketizedAudioStream API
+ void queuePacket(Common::SeekableReadStream *data);
+ void finish() { _audStream->finish(); }
+
+private:
+ Common::ScopedPtr<QueuingAudioStream> _audStream;
+ a52_state_t *_a52State;
+ uint32 _frameSize;
+ byte _inBuf[4096];
+ byte *_inBufPtr;
+ int _flags;
+ int _sampleRate;
+};
+
+AC3Stream::AC3Stream() : _a52State(0), _frameSize(0), _inBufPtr(0), _flags(0), _sampleRate(0) {
+}
+
+AC3Stream::~AC3Stream() {
+ deinit();
+}
+
+enum {
+ HEADER_SIZE = 7
+};
+
+bool AC3Stream::init(Common::SeekableReadStream &firstPacket) {
+ deinit();
+
+ // 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);
+
+ // Go through the header to find sync
+ byte buf[HEADER_SIZE];
+ _sampleRate = -1;
+
+ for (uint i = 0; i < firstPacket.size() - sizeof(buf); i++) {
+ int flags, bitRate;
+ firstPacket.seek(i);
+ firstPacket.read(buf, sizeof(buf));
+
+ if (a52_syncinfo(buf, &flags, &_sampleRate, &bitRate) > 0)
+ break;
+ }
+
+ // Ensure we have a valid sample rate
+ if (_sampleRate <= 0) {
+ deinit();
+ return false;
+ }
+
+ _audStream.reset(makeQueuingAudioStream(_sampleRate, true));
+ _inBufPtr = _inBuf;
+ _flags = 0;
+ _frameSize = 0;
+ return true;
+}
+
+void AC3Stream::deinit() {
+ if (!_a52State)
+ return;
+
+ _audStream.reset();
+ a52_free(_a52State);
+ _a52State = 0;
+}
+
+void AC3Stream::queuePacket(Common::SeekableReadStream *data) {
+ Common::ScopedPtr<Common::SeekableReadStream> packet(data);
+
+ while (packet->pos() < packet->size()) {
+ uint32 leftSize = packet->size() - packet->pos();
+ uint32 len = _inBufPtr - _inBuf;
+ if (_frameSize == 0) {
+ // No header seen: find one
+ len = HEADER_SIZE - len;
+ if (len > leftSize)
+ len = leftSize;
+ packet->read(_inBufPtr, len);
+ leftSize -= len;
+ _inBufPtr += len;
+ if ((_inBufPtr - _inBuf) == HEADER_SIZE) {
+ int sampleRate, bitRate;
+ len = a52_syncinfo(_inBuf, &_flags, &sampleRate, &bitRate);
+ if (len == 0) {
+ memmove(_inBuf, _inBuf + 1, HEADER_SIZE - 1);
+ _inBufPtr--;
+ } else {
+ _frameSize = len;
+ }
+ }
+ } else if (len < _frameSize) {
+ len = _frameSize - len;
+ if (len > leftSize)
+ len = leftSize;
+
+ assert(len < sizeof(_inBuf) - (_inBufPtr - _inBuf));
+ packet->read(_inBufPtr, len);
+ leftSize -= len;
+ _inBufPtr += len;
+ } else {
+ // TODO: Eventually support more than just stereo max
+ int flags = A52_STEREO | A52_ADJUST_LEVEL;
+ sample_t level = 32767;
+
+ if (a52_frame(_a52State, _inBuf, &flags, &level, 0) != 0)
+ error("Frame fail");
+
+ int16 *outputBuffer = (int16 *)malloc(6 * 256 * 2 * 2);
+ int16 *outputPtr = outputBuffer;
+ int outputLength = 0;
+ for (int i = 0; i < 6; i++) {
+ if (a52_block(_a52State) == 0) {
+ sample_t *samples = a52_samples(_a52State);
+ for (int j = 0; j < 256; j++) {
+ *outputPtr++ = (int16)samples[j];
+ *outputPtr++ = (int16)samples[j + 256];
+ }
+
+ outputLength += 1024;
+ }
+ }
+
+ if (outputLength > 0) {
+ flags = FLAG_STEREO | FLAG_16BITS;
+
+#ifdef SCUMM_LITTLE_ENDIAN
+ flags |= FLAG_LITTLE_ENDIAN;
+#endif
+
+ _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, flags);
+ }
+
+ _inBufPtr = _inBuf;
+ _frameSize = 0;
+ }
+ }
+}
+
+PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket) {
+ Common::ScopedPtr<AC3Stream> stream(new AC3Stream());
+ if (!stream->init(firstPacket))
+ return 0;
+
+ return stream.release();
+}
+
+} // End of namespace Audio
+
diff --git a/audio/decoders/ac3.h b/audio/decoders/ac3.h
new file mode 100644
index 0000000..a51107a
--- /dev/null
+++ b/audio/decoders/ac3.h
@@ -0,0 +1,51 @@
+/* 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 AUDIO_DECODERS_AC3_H
+#define AUDIO_DECODERS_AC3_H
+
+#include "common/scummsys.h"
+
+#ifdef USE_A52
+
+namespace Common {
+class SeekableReadStream;
+} // End of namespace Common
+
+namespace Audio {
+
+class PacketizedAudioStream;
+
+/**
+ * Create a PacketizedAudioStream that decodes AC-3 sound
+ *
+ * @param firstPacket The stream containing the first packet of data
+ * @return A new PacketizedAudioStream, or NULL on error
+ */
+PacketizedAudioStream *makeAC3Stream(Common::SeekableReadStream &firstPacket);
+
+} // End of namespace Audio
+
+#endif
+
+#endif
+
diff --git a/audio/module.mk b/audio/module.mk
index 49584ab..0add7cf 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -65,7 +65,10 @@ MODULE_OBJS += \
softsynth/opl/nuked.o
endif
-
+ifdef USE_A52
+MODULE_OBJS += \
+ decoders/ac3.o
+endif
ifdef USE_ALSA
MODULE_OBJS += \
Commit: 43b29a93d7920480081f8cf8ab8b59fb946a8d98
https://github.com/scummvm/scummvm/commit/43b29a93d7920480081f8cf8ab8b59fb946a8d98
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Use the standalone AC-3 decoder in the MPEG-PS code
This code comes from clone2727's now defunct (?) ac3 branch, with
some minor compile fixes. This represents the latest version of
the stalled AC-3 decoder work for Zork: Grand Inquisitor. Note,
however, that I have not yet asked for clone2727's permission to
use this. I'm just experimenting.
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index f4addf9..421ae1e 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -21,6 +21,7 @@
*/
#include "audio/audiostream.h"
+#include "audio/decoders/ac3.h"
#include "audio/decoders/mp3.h"
#include "common/debug.h"
#include "common/endian.h"
@@ -118,7 +119,7 @@ void MPEGPSDecoder::readNextPacket() {
#ifdef USE_A52
handled = true;
- AC3AudioTrack *ac3Track = new AC3AudioTrack(packet);
+ AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, getSoundType());
stream = ac3Track;
_streamMap[startCode] = ac3Track;
addTrack(ac3Track);
@@ -545,35 +546,24 @@ Audio::AudioStream *MPEGPSDecoder::MPEGAudioTrack::getAudioStream() const {
#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);
- } else {
- _audStream = 0;
- }
-
- firstPacket->seek(0);
-
- _inBufPtr = _inBuf;
- _flags = 0;
- _frameSize = 0;
+MPEGPSDecoder::AC3AudioTrack::AC3AudioTrack(Common::SeekableReadStream &firstPacket, Audio::Mixer::SoundType soundType) :
+ AudioTrack(soundType) {
+ _audStream = Audio::makeAC3Stream(firstPacket);
+ if (!_audStream)
+ error("Could not create AC-3 stream");
}
MPEGPSDecoder::AC3AudioTrack::~AC3AudioTrack() {
delete _audStream;
- a52_free(_a52State);
}
bool MPEGPSDecoder::AC3AudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
- if (_audStream) {
- decodeAC3Data(packet);
- }
- delete packet;
+ // Skip DVD code
+ packet->readUint32LE();
+ if (packet->eos())
+ return true;
+
+ _audStream->queuePacket(packet);
return true;
}
@@ -581,103 +571,6 @@ Audio::AudioStream *MPEGPSDecoder::AC3AudioTrack::getAudioStream() const {
return _audStream;
}
-enum {
- HEADER_SIZE = 7
-};
-
-void MPEGPSDecoder::AC3AudioTrack::initStream(Common::SeekableReadStream *packet) {
- byte buf[HEADER_SIZE];
-
- _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));
-
- if (a52_syncinfo(buf, &flags, &_sampleRate, &bitRate) > 0) {
- break;
- }
- }
-}
-
-void MPEGPSDecoder::AC3AudioTrack::decodeAC3Data(Common::SeekableReadStream *packet) {
- // Skip the DVD code
- packet->readUint32LE();
- if (packet->eos())
- return;
-
- while (packet->pos() < packet->size()) {
- uint32 leftSize = packet->size() - packet->pos();
- uint32 len = _inBufPtr - _inBuf;
- if (_frameSize == 0) {
- // No header seen: find one
- len = HEADER_SIZE - len;
- if (len > leftSize)
- len = leftSize;
- packet->read(_inBufPtr, len);
- leftSize -= len;
- _inBufPtr += len;
- if ((_inBufPtr - _inBuf) == HEADER_SIZE) {
- int sampleRate, bitRate;
- len = a52_syncinfo(_inBuf, &_flags, &sampleRate, &bitRate);
- if (len == 0) {
- memmove(_inBuf, _inBuf + 1, HEADER_SIZE - 1);
- _inBufPtr--;
- } else {
- _frameSize = len;
- }
- }
- } else if (len < _frameSize) {
- len = _frameSize - len;
- if (len > leftSize)
- len = leftSize;
-
- assert(len < sizeof(_inBuf) - (_inBufPtr - _inBuf));
- packet->read(_inBufPtr, len);
- leftSize -= len;
- _inBufPtr += len;
- } else {
- int flags = A52_STEREO | A52_ADJUST_LEVEL;
- sample_t level = 32767;
-
- if (a52_frame(_a52State, _inBuf, &flags, &level, 0) != 0)
- error("Frame fail");
-
- int16 *outputBuffer = (int16 *)malloc(6 * 256 * 2 * 2);
- int16 *outputPtr = outputBuffer;
- int outputLength = 0;
- for (int i = 0; i < 6; i++) {
- if (a52_block(_a52State) == 0) {
- sample_t *samples = a52_samples(_a52State);
- for (int j = 0; j < 256; j++) {
- *outputPtr++ = (int16)samples[j];
- *outputPtr++ = (int16)samples[j + 256];
- }
-
- outputLength += 1024;
- }
- }
-
- if (outputLength > 0) {
- flags = Audio::FLAG_STEREO | Audio::FLAG_16BITS;
-
-#ifdef SCUMM_LITTLE_ENDIAN
- flags |= Audio::FLAG_LITTLE_ENDIAN;
-#endif
-
- _audStream->queueBuffer((byte *)outputBuffer, outputLength, DisposeAfterUse::YES, flags);
- }
-
- _inBufPtr = _inBuf;
- _frameSize = 0;
- }
- }
-}
-
#endif
} // End of namespace Video
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index bf9c28e..cc11416 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -28,11 +28,6 @@
#include "graphics/surface.h"
#include "video/video_decoder.h"
-#ifdef USE_A52
-extern "C" {
-#include <a52dec/a52.h>
-}
-
namespace Audio {
class PacketizedAudioStream;
}
@@ -136,7 +131,7 @@ private:
#ifdef USE_A52
class AC3AudioTrack : public AudioTrack, public MPEGStream {
public:
- AC3AudioTrack(Common::SeekableReadStream *firstPacket);
+ AC3AudioTrack(Common::SeekableReadStream &firstPacket, Audio::Mixer::SoundType soundType);
~AC3AudioTrack();
bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts);
@@ -146,16 +141,7 @@ private:
Audio::AudioStream *getAudioStream() const;
private:
- Audio::QueuingAudioStream *_audStream;
- a52_state_t *_a52State;
- uint32 _frameSize;
- byte _inBuf[4096];
- byte *_inBufPtr;
- int _flags;
- int _sampleRate;
-
- void initStream(Common::SeekableReadStream *packet);
- void decodeAC3Data(Common::SeekableReadStream *packet);
+ Audio::PacketizedAudioStream *_audStream;
};
#endif
Commit: d4f8b330d61cb2457fa1c085510a5f0553b98d97
https://github.com/scummvm/scummvm/commit/d4f8b330d61cb2457fa1c085510a5f0553b98d97
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
IMAGE: Honor nb_fields when calculating frame duration
>From what I understand, this has something to do with the image
being either made up from two or three parts. When it's made from
three parts, the frame should be displayed for half again as long
as normal.
This makes the speed of the Zork: Grand Inquisitor video look
about right to me. It's still out of sync, but it doesn't seem to
get *more* out of sync as the video progresses.
Changed paths:
image/codecs/mpeg.cpp
diff --git a/image/codecs/mpeg.cpp b/image/codecs/mpeg.cpp
index beb042d..bb40fe6 100644
--- a/image/codecs/mpeg.cpp
+++ b/image/codecs/mpeg.cpp
@@ -78,8 +78,13 @@ bool MPEGDecoder::decodePacket(Common::SeekableReadStream &packet, uint32 &frame
if (_mpegInfo->display_fbuf) {
foundFrame = true;
const mpeg2_sequence_t *sequence = _mpegInfo->sequence;
+ const mpeg2_picture_t *picture = _mpegInfo->display_picture;
framePeriod += sequence->frame_period;
+ if (picture->nb_fields > 2) {
+ framePeriod += (sequence->frame_period / 2);
+
+ }
if (!dst) {
// If no destination is specified, use our internal storage
Commit: b672a694b9d14dc57e4f15ed52212d225077a07a
https://github.com/scummvm/scummvm/commit/b672a694b9d14dc57e4f15ed52212d225077a07a
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Synchronize video to pts timestamps
This is another attempts at improving the audio/video sync in the
MPEG-PS decoder. Unfortunately, the audio probably also needs to
be synced to its pts timestamps...
Changed paths:
video/mpegps_decoder.cpp
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 421ae1e..99624dd 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -486,6 +486,10 @@ bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packe
if (foundFrame) {
_curFrame++;
+ if (pts != 0xFFFFFFFF) {
+ Audio::Timestamp ptsTimestamp = Audio::Timestamp(pts / 90, 27000000);
+ framePeriod = ptsTimestamp.frameDiff(_nextFrameStartTime);
+ }
_nextFrameStartTime = _nextFrameStartTime.addFrames(framePeriod);
}
#endif
Commit: ac40828ed24ff3d42ac68f2d45f36a03c34dc54d
https://github.com/scummvm/scummvm/commit/ac40828ed24ff3d42ac68f2d45f36a03c34dc54d
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Make the video pts sync easier to understand
Changed paths:
video/mpegps_decoder.cpp
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 99624dd..81c1765 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -486,11 +486,16 @@ bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packe
if (foundFrame) {
_curFrame++;
+
+ // If there is a presentation timestamp, use that for sync. Almost all
+ // packets with a presentation timestamp will have a found frame, so
+ // it is probably not worth the trouble worrying about when they don't.
+
if (pts != 0xFFFFFFFF) {
- Audio::Timestamp ptsTimestamp = Audio::Timestamp(pts / 90, 27000000);
- framePeriod = ptsTimestamp.frameDiff(_nextFrameStartTime);
+ _nextFrameStartTime = Audio::Timestamp(pts / 90, 27000000);
+ } else {
+ _nextFrameStartTime = _nextFrameStartTime.addFrames(framePeriod);
}
- _nextFrameStartTime = _nextFrameStartTime.addFrames(framePeriod);
}
#endif
Commit: 1d69564876ad0048d49b968a5fbc01564dd74dba
https://github.com/scummvm/scummvm/commit/1d69564876ad0048d49b968a5fbc01564dd74dba
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Moved MPEGStream creation out of readNextPacket()
I think it makes things easier to read, and I have some ideas
that I want to try which should be easier this way...
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 81c1765..5d86e3f 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -79,6 +79,82 @@ void MPEGPSDecoder::close() {
memset(_psmESType, 0, 256);
}
+MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::SeekableReadStream *packet) {
+ MPEGStream *stream = 0;
+
+ if (_streamMap.contains(startCode)) {
+ // We already found the stream
+ stream = _streamMap[startCode];
+ } else {
+ // We haven't seen this before
+
+ if (startCode == kStartCodePrivateStream1) {
+ PrivateStreamType streamType = detectPrivateStreamType(packet);
+ packet->seek(0);
+
+ // TODO: Handling of these types (as needed)
+ bool handled = false;
+ const char *typeName;
+
+ switch (streamType) {
+ case kPrivateStreamAC3: {
+ typeName = "AC-3";
+
+#ifdef USE_A52
+ handled = true;
+ AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, getSoundType());
+ stream = ac3Track;
+ _streamMap[startCode] = ac3Track;
+ addTrack(ac3Track);
+#endif
+ break;
+ }
+ case kPrivateStreamDTS:
+ typeName = "DTS";
+ break;
+ case kPrivateStreamDVDPCM:
+ typeName = "DVD PCM";
+ break;
+ case kPrivateStreamPS2Audio:
+ typeName = "PS2 Audio";
+ break;
+ default:
+ typeName = "Unknown";
+ break;
+ }
+
+ if (!handled) {
+ warning("Unhandled DVD private stream: %s", typeName);
+
+ // 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
+ warning("Found extra video stream 0x%04X", startCode);
+ _streamMap[startCode] = 0;
+ } else if (startCode >= 0x1C0 && startCode <= 0x1DF) {
+#ifdef USE_MAD
+ // MPEG Audio stream
+ MPEGAudioTrack *audioTrack = new MPEGAudioTrack(*packet, getSoundType());
+ stream = audioTrack;
+ _streamMap[startCode] = audioTrack;
+ addTrack(audioTrack);
+#else
+ warning("Found audio stream 0x%04X, but no MAD support compiled in", startCode);
+ _streamMap[startCode] = 0;
+#endif
+ } else {
+ // Probably not relevant
+ debug(0, "Found unhandled MPEG-PS stream type 0x%04x", startCode);
+ _streamMap[startCode] = 0;
+ }
+ }
+
+ return stream;
+}
+
void MPEGPSDecoder::readNextPacket() {
if (_stream->eos())
return;
@@ -96,78 +172,8 @@ void MPEGPSDecoder::readNextPacket() {
return;
}
- MPEGStream *stream = 0;
Common::SeekableReadStream *packet = _stream->readStream(size);
-
- if (_streamMap.contains(startCode)) {
- // We already found the stream
- stream = _streamMap[startCode];
- } else {
- // We haven't seen this before
-
- if (startCode == kStartCodePrivateStream1) {
- PrivateStreamType streamType = detectPrivateStreamType(packet);
- packet->seek(0);
-
- // TODO: Handling of these types (as needed)
- bool handled = false;
- const char *typeName;
-
- switch (streamType) {
- case kPrivateStreamAC3: {
- typeName = "AC-3";
-
-#ifdef USE_A52
- handled = true;
- AC3AudioTrack *ac3Track = new AC3AudioTrack(*packet, getSoundType());
- stream = ac3Track;
- _streamMap[startCode] = ac3Track;
- addTrack(ac3Track);
-#endif
- break;
- }
- case kPrivateStreamDTS:
- typeName = "DTS";
- break;
- case kPrivateStreamDVDPCM:
- typeName = "DVD PCM";
- break;
- case kPrivateStreamPS2Audio:
- typeName = "PS2 Audio";
- break;
- default:
- typeName = "Unknown";
- break;
- }
-
- if (!handled) {
- warning("Unhandled DVD private stream: %s", typeName);
-
- // 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
- warning("Found extra video stream 0x%04X", startCode);
- _streamMap[startCode] = 0;
- } else if (startCode >= 0x1C0 && startCode <= 0x1DF) {
-#ifdef USE_MAD
- // MPEG Audio stream
- MPEGAudioTrack *audioTrack = new MPEGAudioTrack(*packet, getSoundType());
- stream = audioTrack;
- _streamMap[startCode] = audioTrack;
- addTrack(audioTrack);
-#else
- warning("Found audio stream 0x%04X, but no MAD support compiled in", startCode);
- _streamMap[startCode] = 0;
-#endif
- } else {
- // Probably not relevant
- debug(0, "Found unhandled MPEG-PS stream type 0x%04x", startCode);
- _streamMap[startCode] = 0;
- }
- }
+ MPEGStream *stream = getStream(startCode, packet);
if (stream) {
packet->seek(0);
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index cc11416..15a9443 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -160,6 +160,7 @@ private:
int readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts);
int findNextStartCode(uint32 &size);
+ MPEGStream *getStream(uint32 startCode, Common::SeekableReadStream *packet);
uint32 readPTS(int c);
void parseProgramStreamMap(int length);
Commit: 1255e8de4db11e3bdfaa2461cc72be6a74daa16c
https://github.com/scummvm/scummvm/commit/1255e8de4db11e3bdfaa2461cc72be6a74daa16c
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Removed _psmESType
We weren't doing anything with it anyway. And I'm not sure it's
even available in the ZGI videos.
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 5d86e3f..ee71ce2 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -47,7 +47,6 @@ enum {
MPEGPSDecoder::MPEGPSDecoder() {
_stream = 0;
- memset(_psmESType, 0, 256);
}
MPEGPSDecoder::~MPEGPSDecoder() {
@@ -75,8 +74,6 @@ void MPEGPSDecoder::close() {
_stream = 0;
_streamMap.clear();
-
- memset(_psmESType, 0, 256);
}
MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::SeekableReadStream *packet) {
@@ -376,13 +373,10 @@ void MPEGPSDecoder::parseProgramStreamMap(int length) {
int esMapLength = _stream->readUint16BE();
while (esMapLength >= 4) {
- byte type = _stream->readByte();
- byte esID = _stream->readByte();
+ _stream->readByte(); // type
+ _stream->readByte(); // esID
uint16 esInfoLength = _stream->readUint16BE();
- // Remember mapping from stream id to stream type
- _psmESType[esID] = type;
-
// Skip program stream info
_stream->skip(esInfoLength);
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 15a9443..74167a7 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -164,7 +164,6 @@ private:
uint32 readPTS(int c);
void parseProgramStreamMap(int length);
- byte _psmESType[256];
// A map from stream types to stream handlers
typedef Common::HashMap<int, MPEGStream *> StreamMap;
Commit: a5b5b68a1a1a5453b9aa8025e3a95cc10d0718d4
https://github.com/scummvm/scummvm/commit/a5b5b68a1a1a5453b9aa8025e3a95cc10d0718d4
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Use all video PTS's
Sometimes (only at the very start of a movie?) there will be a
video packet that has a PTS but no frame to display. Save that PTS
and use it for the next frame. This doesn't actually improve
anything, as far as I can tell, but feels right.
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index ee71ce2..01db2b4 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -440,6 +440,7 @@ MPEGPSDecoder::MPEGVideoTrack::MPEGVideoTrack(Common::SeekableReadStream *firstP
_surface = 0;
_endOfTrack = false;
_curFrame = -1;
+ _framePts = 0xFFFFFFFF;
_nextFrameStartTime = Audio::Timestamp(0, 27000000); // 27 MHz timer
findDimensions(firstPacket, format);
@@ -481,21 +482,27 @@ const Graphics::Surface *MPEGPSDecoder::MPEGVideoTrack::decodeNextFrame() {
bool MPEGPSDecoder::MPEGVideoTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
#ifdef USE_MPEG2
+ if (pts != 0xFFFFFFFF) {
+ _framePts = pts;
+ }
+
uint32 framePeriod;
bool foundFrame = _mpegDecoder->decodePacket(*packet, framePeriod, _surface);
if (foundFrame) {
_curFrame++;
- // If there is a presentation timestamp, use that for sync. Almost all
- // packets with a presentation timestamp will have a found frame, so
- // it is probably not worth the trouble worrying about when they don't.
+ // If there has been a timestamp since the previous frame, use that for
+ // syncing. Usually it will be the timestamp from the current packet,
+ // but it might not be.
- if (pts != 0xFFFFFFFF) {
- _nextFrameStartTime = Audio::Timestamp(pts / 90, 27000000);
+ if (_framePts != 0xFFFFFFFF) {
+ _nextFrameStartTime = Audio::Timestamp(_framePts / 90, 27000000);
} else {
_nextFrameStartTime = _nextFrameStartTime.addFrames(framePeriod);
}
+
+ _framePts = 0xFFFFFFFF;
}
#endif
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 74167a7..6111fe8 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -100,6 +100,7 @@ private:
private:
bool _endOfTrack;
int _curFrame;
+ uint32 _framePts;
Audio::Timestamp _nextFrameStartTime;
Graphics::Surface *_surface;
Commit: 7c58534f4f31a253f01a92655ecf6a3f33878e1a
https://github.com/scummvm/scummvm/commit/7c58534f4f31a253f01a92655ecf6a3f33878e1a
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
VIDEO: Add buffering demuxer to MPEG-PS decoder
In all my attempts to get the audio and video to sync up in the
ZGI videos, there have always been 9-10 frames of video before the
audio even starts, even though the audio is timestamped to start
before. This attempts to fix that by prioritizing sending audio
packets to the decoder in a timely fashion.
I do not know if this is the correct way of doing this, and there
are still some things that need to be fixed. But pragmatically, it
does procude significantly better sync, so...
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index 01db2b4..361481b 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -36,6 +36,11 @@
namespace Video {
+// --------------------------------------------------------------------------
+// Decoder - This is the part that takes a packet and figures out what to do
+// with it.
+// --------------------------------------------------------------------------
+
enum {
kStartCodePack = 0x1BA,
kStartCodeSystemHeader = 0x1BB,
@@ -46,33 +51,33 @@ enum {
};
MPEGPSDecoder::MPEGPSDecoder() {
- _stream = 0;
+ _demuxer = new MPEGPSDemuxer();
}
MPEGPSDecoder::~MPEGPSDecoder() {
close();
+ delete _demuxer;
}
bool MPEGPSDecoder::loadStream(Common::SeekableReadStream *stream) {
close();
- _stream = stream;
+ if (!_demuxer->loadStream(stream)) {
+ close();
+ return false;
+ }
if (!addFirstVideoTrack()) {
close();
return false;
}
- _stream->seek(0);
return true;
}
void MPEGPSDecoder::close() {
VideoDecoder::close();
-
- delete _stream;
- _stream = 0;
-
+ _demuxer->close();
_streamMap.clear();
}
@@ -153,15 +158,12 @@ MPEGPSDecoder::MPEGStream *MPEGPSDecoder::getStream(uint32 startCode, Common::Se
}
void MPEGPSDecoder::readNextPacket() {
- if (_stream->eos())
- return;
-
for (;;) {
int32 startCode;
uint32 pts, dts;
- int size = readNextPacketHeader(startCode, pts, dts);
+ Common::SeekableReadStream *packet = _demuxer->getNextPacket(getTime(), startCode, pts, dts);
- if (size < 0) {
+ if (!packet) {
// End of stream
for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
if ((*it)->getTrackType() == Track::kTrackTypeVideo)
@@ -169,7 +171,6 @@ void MPEGPSDecoder::readNextPacket() {
return;
}
- Common::SeekableReadStream *packet = _stream->readStream(size);
MPEGStream *stream = getStream(startCode, packet);
if (stream) {
@@ -185,30 +186,190 @@ void MPEGPSDecoder::readNextPacket() {
}
}
-#define MAX_SYNC_SIZE 100000
+bool MPEGPSDecoder::addFirstVideoTrack() {
+ int32 startCode;
+ uint32 pts, dts;
+ Common::SeekableReadStream *packet = _demuxer->getFirstVideoPacket(startCode, pts, dts);
-int MPEGPSDecoder::findNextStartCode(uint32 &size) {
- size = MAX_SYNC_SIZE;
- int32 state = 0xFF;
+ if (!packet)
+ return false;
- while (size > 0) {
- byte v = _stream->readByte();
+ // Video stream
+ // Can be MPEG-1/2 or MPEG-4/h.264. We'll assume the former and
+ // I hope we never need the latter.
+ MPEGVideoTrack *track = new MPEGVideoTrack(packet, getDefaultHighColorFormat());
+ addTrack(track);
+ _streamMap[startCode] = track;
- if (_stream->eos())
- return -1;
+ return true;
+}
- size--;
+MPEGPSDecoder::PrivateStreamType MPEGPSDecoder::detectPrivateStreamType(Common::SeekableReadStream *packet) {
+ uint32 dvdCode = packet->readUint32LE();
+ if (packet->eos())
+ return kPrivateStreamUnknown;
- if (state == 0x1)
- return ((state << 8) | v) & 0xFFFFFF;
+ uint32 ps2Header = packet->readUint32BE();
+ if (!packet->eos() && ps2Header == MKTAG('S', 'S', 'h', 'd'))
+ return kPrivateStreamPS2Audio;
- state = ((state << 8) | v) & 0xFFFFFF;
+ switch (dvdCode & 0xE0) {
+ case 0x80:
+ if ((dvdCode & 0xF8) == 0x88)
+ return kPrivateStreamDTS;
+
+ return kPrivateStreamAC3;
+ case 0xA0:
+ return kPrivateStreamDVDPCM;
}
- return -1;
+ return kPrivateStreamUnknown;
+}
+
+// --------------------------------------------------------------------------
+// Demuxer - This is the part that reads packets from the stream and delivers
+// them to the decoder.
+//
+// It will buffer a number of packets in advance, because otherwise it may
+// not encounter any audio packets until it's far too late to decode them.
+// Before I added this, there would be 9 or 10 frames of video before the
+// first audio packet, even though the timestamp indicated that the audio
+// should start slightly before the video.
+// --------------------------------------------------------------------------
+
+#define PREBUFFERED_PACKETS 150
+#define AUDIO_THRESHOLD 100
+
+MPEGPSDecoder::MPEGPSDemuxer::MPEGPSDemuxer() {
+ _stream = 0;
+}
+
+MPEGPSDecoder::MPEGPSDemuxer::~MPEGPSDemuxer() {
+ close();
+}
+
+bool MPEGPSDecoder::MPEGPSDemuxer::loadStream(Common::SeekableReadStream *stream) {
+ close();
+
+ _stream = stream;
+
+ int queuedPackets = 0;
+ while (queueNextPacket() && queuedPackets < PREBUFFERED_PACKETS) {
+ queuedPackets++;
+ }
+
+ return true;
+}
+
+void MPEGPSDecoder::MPEGPSDemuxer::close() {
+ delete _stream;
+ _stream = 0;
+
+ while (!_audioQueue.empty()) {
+ Packet packet = _audioQueue.pop();
+ delete packet._stream;
+ }
+
+ while (!_videoQueue.empty()) {
+ Packet packet = _videoQueue.pop();
+ delete packet._stream;
+ }
+}
+
+Common::SeekableReadStream *MPEGPSDecoder::MPEGPSDemuxer::getFirstVideoPacket(int32 &startCode, uint32 &pts, uint32 &dts) {
+ if (_videoQueue.empty())
+ return nullptr;
+ Packet packet = _videoQueue.front();
+ startCode = packet._startCode;
+ pts = packet._pts;
+ dts = packet._dts;
+ return packet._stream;
+}
+
+Common::SeekableReadStream *MPEGPSDecoder::MPEGPSDemuxer::getNextPacket(uint32 currentTime, int32 &startCode, uint32 &pts, uint32 &dts) {
+ queueNextPacket();
+
+ // The idea here is to prioritize the delivery of audio packets,
+ // because when the decoder wants a frame it will keep asking until it
+ // gets a frame. There is nothing like that in the decoder to ensure
+ // speedy delivery of audio.
+
+ if (!_audioQueue.empty()) {
+ Packet packet = _audioQueue.front();
+ bool usePacket = false;
+
+ if (packet._pts == 0xFFFFFFFF) {
+ // No timestamp? Use it just in case. This could be a
+ // bad idea, but in my tests all audio packets have a
+ // time stamp.
+ usePacket = true;
+ } else {
+ uint32 packetTime = packet._pts / 90;
+ if (packetTime <= currentTime || packetTime - currentTime < AUDIO_THRESHOLD || _videoQueue.empty()) {
+ // The packet is overdue, or will be soon.
+ //
+ // TODO: We should pad or trim the first audio
+ // packet based on the timestamp to get the
+ // audio to start at the exact desired time.
+ // But for some reason it seems to work well
+ // enough anyway. For now.
+ usePacket = true;
+ }
+ }
+
+ if (usePacket) {
+ _audioQueue.pop();
+ startCode = packet._startCode;
+ pts = packet._pts;
+ dts = packet._dts;
+ return packet._stream;
+ }
+ }
+
+ if (!_videoQueue.empty()) {
+ Packet packet = _videoQueue.pop();
+ startCode = packet._startCode;
+ pts = packet._pts;
+ dts = packet._dts;
+ return packet._stream;
+ }
+
+ return nullptr;
+}
+
+bool MPEGPSDecoder::MPEGPSDemuxer::queueNextPacket() {
+ if (_stream->eos())
+ return false;
+
+ for (;;) {
+ int32 startCode;
+ uint32 pts, dts;
+ int size = readNextPacketHeader(startCode, pts, dts);
+
+ if (size < 0) {
+ // End of stream
+ return false;
+ }
+
+ Common::SeekableReadStream *stream = _stream->readStream(size);
+
+ if (startCode == kStartCodePrivateStream1 || (startCode >= 0x1C0 && startCode <= 0x1DF)) {
+ // Audio packet
+ _audioQueue.push(Packet(stream, startCode, pts, dts));
+ return true;
+ }
+
+ if (startCode >= 0x1E0 && startCode <= 0x1EF) {
+ // Video packet
+ _videoQueue.push(Packet(stream, startCode, pts, dts));
+ return true;
+ }
+
+ delete _stream;
+ }
}
-int MPEGPSDecoder::readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts) {
+int MPEGPSDecoder::MPEGPSDemuxer::readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts) {
for (;;) {
uint32 size;
startCode = findNextStartCode(size);
@@ -354,7 +515,30 @@ int MPEGPSDecoder::readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &d
}
}
-uint32 MPEGPSDecoder::readPTS(int c) {
+#define MAX_SYNC_SIZE 100000
+
+int MPEGPSDecoder::MPEGPSDemuxer::findNextStartCode(uint32 &size) {
+ size = MAX_SYNC_SIZE;
+ int32 state = 0xFF;
+
+ while (size > 0) {
+ byte v = _stream->readByte();
+
+ if (_stream->eos())
+ return -1;
+
+ size--;
+
+ if (state == 0x1)
+ return ((state << 8) | v) & 0xFFFFFF;
+
+ state = ((state << 8) | v) & 0xFFFFFF;
+ }
+
+ return -1;
+}
+
+uint32 MPEGPSDecoder::MPEGPSDemuxer::readPTS(int c) {
byte buf[5];
buf[0] = (c < 0) ? _stream->readByte() : c;
@@ -363,7 +547,7 @@ uint32 MPEGPSDecoder::readPTS(int c) {
return ((buf[0] & 0x0E) << 29) | ((READ_BE_UINT16(buf + 1) >> 1) << 15) | (READ_BE_UINT16(buf + 3) >> 1);
}
-void MPEGPSDecoder::parseProgramStreamMap(int length) {
+void MPEGPSDecoder::MPEGPSDemuxer::parseProgramStreamMap(int length) {
_stream->readByte();
_stream->readByte();
@@ -386,55 +570,9 @@ void MPEGPSDecoder::parseProgramStreamMap(int length) {
_stream->readUint32BE(); // CRC32
}
-bool MPEGPSDecoder::addFirstVideoTrack() {
- for (;;) {
- int32 startCode;
- uint32 pts, dts;
- int size = readNextPacketHeader(startCode, pts, dts);
-
- // End of stream? We failed
- if (size < 0)
- return false;
-
- if (startCode >= 0x1E0 && startCode <= 0x1EF) {
- // Video stream
- // Can be MPEG-1/2 or MPEG-4/h.264. We'll assume the former and
- // I hope we never need the latter.
- Common::SeekableReadStream *firstPacket = _stream->readStream(size);
- MPEGVideoTrack *track = new MPEGVideoTrack(firstPacket, getDefaultHighColorFormat());
- addTrack(track);
- _streamMap[startCode] = track;
- delete firstPacket;
- break;
- }
-
- _stream->skip(size);
- }
-
- return true;
-}
-
-MPEGPSDecoder::PrivateStreamType MPEGPSDecoder::detectPrivateStreamType(Common::SeekableReadStream *packet) {
- uint32 dvdCode = packet->readUint32LE();
- if (packet->eos())
- return kPrivateStreamUnknown;
-
- uint32 ps2Header = packet->readUint32BE();
- if (!packet->eos() && ps2Header == MKTAG('S', 'S', 'h', 'd'))
- return kPrivateStreamPS2Audio;
-
- switch (dvdCode & 0xE0) {
- case 0x80:
- if ((dvdCode & 0xF8) == 0x88)
- return kPrivateStreamDTS;
-
- return kPrivateStreamAC3;
- case 0xA0:
- return kPrivateStreamDVDPCM;
- }
-
- return kPrivateStreamUnknown;
-}
+// --------------------------------------------------------------------------
+// Video track
+// --------------------------------------------------------------------------
MPEGPSDecoder::MPEGVideoTrack::MPEGVideoTrack(Common::SeekableReadStream *firstPacket, const Graphics::PixelFormat &format) {
_surface = 0;
@@ -536,6 +674,10 @@ void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *f
firstPacket->seek(0);
}
+// --------------------------------------------------------------------------
+// Audio track
+// --------------------------------------------------------------------------
+
#ifdef USE_MAD
// The audio code here is almost entirely based on what we do in mp3.cpp
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 6111fe8..bd703a3 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -25,6 +25,7 @@
#include "common/inttypes.h"
#include "common/hashmap.h"
+#include "common/queue.h"
#include "graphics/surface.h"
#include "video/video_decoder.h"
@@ -64,6 +65,39 @@ protected:
bool useAudioSync() const { return false; }
private:
+ class MPEGPSDemuxer {
+ public:
+ MPEGPSDemuxer();
+ ~MPEGPSDemuxer();
+
+ bool loadStream(Common::SeekableReadStream *stream);
+ void close();
+
+ Common::SeekableReadStream *getFirstVideoPacket(int32 &startCode, uint32 &pts, uint32 &dts);
+ Common::SeekableReadStream *getNextPacket(uint32 currentTime, int32 &startCode, uint32 &pts, uint32 &dts);
+
+ private:
+ class Packet {
+ public:
+ Packet(Common::SeekableReadStream *stream, int32 startCode, uint32 pts, uint32 dts) : _stream(stream), _startCode(startCode), _pts(pts), _dts(dts) {}
+
+ Common::SeekableReadStream *_stream;
+ int32 _startCode;
+ uint32 _pts;
+ uint32 _dts;
+ };
+ bool queueNextPacket();
+ bool fillQueues();
+ int readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts);
+ int findNextStartCode(uint32 &size);
+ uint32 readPTS(int c);
+ void parseProgramStreamMap(int length);
+
+ Common::SeekableReadStream *_stream;
+ Common::Queue<Packet> _videoQueue;
+ Common::Queue<Packet> _audioQueue;
+ };
+
// Base class for handling MPEG streams
class MPEGStream {
public:
@@ -74,7 +108,7 @@ private:
kStreamTypeAudio
};
- virtual bool sendPacket(Common::SeekableReadStream *firstPacket, uint32 pts, uint32 dts) = 0;
+ virtual bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) = 0;
virtual StreamType getStreamType() const = 0;
};
@@ -158,19 +192,13 @@ private:
PrivateStreamType detectPrivateStreamType(Common::SeekableReadStream *packet);
bool addFirstVideoTrack();
-
- int readNextPacketHeader(int32 &startCode, uint32 &pts, uint32 &dts);
- int findNextStartCode(uint32 &size);
MPEGStream *getStream(uint32 startCode, Common::SeekableReadStream *packet);
- uint32 readPTS(int c);
- void parseProgramStreamMap(int length);
+ MPEGPSDemuxer *_demuxer;
// A map from stream types to stream handlers
typedef Common::HashMap<int, MPEGStream *> StreamMap;
StreamMap _streamMap;
-
- Common::SeekableReadStream *_stream;
};
} // End of namespace Video
Commit: 71910c2283532a2071aed725835c66afee451e2d
https://github.com/scummvm/scummvm/commit/71910c2283532a2071aed725835c66afee451e2d
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
ZVISION: Set 800x600 mode for the DVD version of ZGI
This allows the backend to show the hi-res videos at full
resolution, rather than scaling them down.
Changed paths:
engines/zvision/zvision.cpp
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
index 9eb6465..5a53383 100644
--- a/engines/zvision/zvision.cpp
+++ b/engines/zvision/zvision.cpp
@@ -191,6 +191,12 @@ void ZVision::initialize() {
}
}
+ Graphics::ModeList modes;
+ modes.push_back(Graphics::Mode(WINDOW_WIDTH, WINDOW_HEIGHT));
+ if (getGameId() == GID_GRANDINQUISITOR && (getFeatures() & GF_DVD))
+ modes.push_back(Graphics::Mode(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT));
+ initGraphicsModes(modes);
+
initScreen();
// Register random source
Commit: e2935acfe4a6d332f7b1388fa98fce711cde8c12
https://github.com/scummvm/scummvm/commit/e2935acfe4a6d332f7b1388fa98fce711cde8c12
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
ZVISION: Disable MPEG movies when liba52 is not enabled
Changed paths:
engines/zvision/scripting/actions.cpp
engines/zvision/video/video.cpp
engines/zvision/zvision.cpp
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index 794336e..6e02123 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -967,9 +967,9 @@ bool ActionStreamVideo::execute() {
bool subtitleExists = _engine->getSearchManager()->hasFile(subname);
bool switchToHires = false;
-// NOTE: We only show the hires MPEG2 videos when libmpeg2 is compiled in,
+// NOTE: We only show the hires MPEG2 videos when libmpeg2 and liba52 are compiled in,
// otherwise we fall back to the lowres ones
-#ifdef USE_MPEG2
+#if defined(USE_MPEG2) && defined(USE_A52)
Common::String hiresFileName = _fileName;
hiresFileName.setChar('d', hiresFileName.size() - 8);
hiresFileName.setChar('v', hiresFileName.size() - 3);
diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp
index 0c19c92..01e75a4 100644
--- a/engines/zvision/video/video.cpp
+++ b/engines/zvision/video/video.cpp
@@ -23,7 +23,7 @@
#include "common/scummsys.h"
#include "common/system.h"
#include "video/video_decoder.h"
-#ifdef USE_MPEG2
+#if defined(USE_MPEG2) && defined(USE_A52)
#include "video/mpegps_decoder.h"
#endif
#include "engines/util.h"
@@ -48,7 +48,7 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) {
animation = new RLFDecoder();
else if (tmpFileName.hasSuffix(".avi"))
animation = new ZorkAVIDecoder();
-#ifdef USE_MPEG2
+#if defined(USE_MPEG2) && defined(USE_A52)
else if (tmpFileName.hasSuffix(".vob"))
animation = new Video::MPEGPSDecoder();
#endif
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
index 5a53383..7bd16cb 100644
--- a/engines/zvision/zvision.cpp
+++ b/engines/zvision/zvision.cpp
@@ -193,8 +193,11 @@ void ZVision::initialize() {
Graphics::ModeList modes;
modes.push_back(Graphics::Mode(WINDOW_WIDTH, WINDOW_HEIGHT));
+#if defined(USE_MPEG2) && defined(USE_A52)
+ // For the DVD version of ZGI we can play high resolution videos
if (getGameId() == GID_GRANDINQUISITOR && (getFeatures() & GF_DVD))
modes.push_back(Graphics::Mode(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT));
+#endif
initGraphicsModes(modes);
initScreen();
@@ -225,8 +228,8 @@ void ZVision::initialize() {
loadSettings();
-#ifndef USE_MPEG2
- // libmpeg2 not loaded, disable the MPEG2 movies option
+#if !defined(USE_MPEG2) || !defined(USE_A52)
+ // libmpeg2 or liba52 not loaded, disable the MPEG2 movies option
_scriptManager->setStateValue(StateKey_MPEGMovies, 2);
#endif
Commit: e4ff1929aa7823c3716a9ea48e1f8a9524154742
https://github.com/scummvm/scummvm/commit/e4ff1929aa7823c3716a9ea48e1f8a9524154742
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2018-11-04T22:33:22+01:00
Commit Message:
ZVISION: Only add mpeg video engine options when mpeg and a52 are enabled
Changed paths:
engines/zvision/detection_tables.h
diff --git a/engines/zvision/detection_tables.h b/engines/zvision/detection_tables.h
index 32c5104..d33d931 100644
--- a/engines/zvision/detection_tables.h
+++ b/engines/zvision/detection_tables.h
@@ -247,7 +247,11 @@ static const ZVisionGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
GF_DVD,
- GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING, GAMEOPTION_USE_HIRES_MPEG_MOVIES)
+ GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_DOUBLE_FPS, GAMEOPTION_DISABLE_ANIM_WHILE_TURNING,
+#if defined(USE_MPEG2) && defined(USE_A52)
+ GAMEOPTION_USE_HIRES_MPEG_MOVIES
+#endif
+ )
},
GID_GRANDINQUISITOR
},
More information about the Scummvm-git-logs
mailing list