mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-02 08:19:19 +00:00
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.
This commit is contained in:
parent
8b692f8d89
commit
fc7fa1de3a
48
common/inttypes.h
Normal file
48
common/inttypes.h
Normal file
@ -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
|
@ -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>
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user