mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
MTROPOLIS: Add AVI movie support
This commit is contained in:
parent
d70dfb7210
commit
80a75d7236
@ -65,6 +65,8 @@ SIAssetFactory *getAssetFactoryForDataObjectType(const Data::DataObjectTypes::Da
|
||||
return AssetFactory<AudioAsset, Data::AudioAsset>::getInstance();
|
||||
case Data::DataObjectTypes::kMovieAsset:
|
||||
return AssetFactory<MovieAsset, Data::MovieAsset>::getInstance();
|
||||
case Data::DataObjectTypes::kAVIMovieAsset:
|
||||
return AssetFactory<AVIMovieAsset, Data::AVIMovieAsset>::getInstance();
|
||||
case Data::DataObjectTypes::kImageAsset:
|
||||
return AssetFactory<ImageAsset, Data::ImageAsset>::getInstance();
|
||||
case Data::DataObjectTypes::kMToonAsset:
|
||||
|
@ -802,6 +802,21 @@ void MovieAsset::addDamagedFrame(int frame) {
|
||||
_damagedFrames.push_back(frame);
|
||||
}
|
||||
|
||||
bool AVIMovieAsset::load(AssetLoaderContext &context, const Data::AVIMovieAsset &data) {
|
||||
_assetID = data.assetID;
|
||||
_extFileName = data.extFileName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AssetType AVIMovieAsset::getAssetType() const {
|
||||
return kAssetTypeAVIMovie;
|
||||
}
|
||||
|
||||
const Common::String &AVIMovieAsset::getExtFileName() const {
|
||||
return _extFileName;
|
||||
}
|
||||
|
||||
const Common::Array<int> &MovieAsset::getDamagedFrames() const {
|
||||
return _damagedFrames;
|
||||
}
|
||||
|
@ -230,6 +230,17 @@ private:
|
||||
Common::Array<int> _damagedFrames;
|
||||
};
|
||||
|
||||
class AVIMovieAsset : public Asset {
|
||||
public:
|
||||
bool load(AssetLoaderContext &context, const Data::AVIMovieAsset &data);
|
||||
AssetType getAssetType() const override;
|
||||
|
||||
const Common::String &getExtFileName() const;
|
||||
|
||||
private:
|
||||
Common::String _extFileName;
|
||||
};
|
||||
|
||||
class CachedImage {
|
||||
public:
|
||||
CachedImage();
|
||||
|
@ -33,6 +33,7 @@ namespace DataObjectTypes {
|
||||
bool isValidSceneRootElement(DataObjectType type) {
|
||||
switch (type) {
|
||||
case kGraphicElement:
|
||||
case kAVIMovieElement:
|
||||
case kMovieElement:
|
||||
case kMToonElement:
|
||||
case kImageElement:
|
||||
@ -45,6 +46,7 @@ bool isValidSceneRootElement(DataObjectType type) {
|
||||
bool isVisualElement(DataObjectType type) {
|
||||
switch (type) {
|
||||
case kGraphicElement:
|
||||
case kAVIMovieElement:
|
||||
case kMovieElement:
|
||||
case kMToonElement:
|
||||
case kImageElement:
|
||||
@ -67,6 +69,7 @@ bool isNonVisualElement(DataObjectType type) {
|
||||
bool isElement(DataObjectType type) {
|
||||
switch (type) {
|
||||
case kGraphicElement:
|
||||
case kAVIMovieElement:
|
||||
case kMovieElement:
|
||||
case kMToonElement:
|
||||
case kImageElement:
|
||||
@ -140,6 +143,7 @@ bool isModifier(DataObjectType type) {
|
||||
bool isAsset(DataObjectType type) {
|
||||
switch (type) {
|
||||
case kMovieAsset:
|
||||
case kAVIMovieAsset:
|
||||
case kAudioAsset:
|
||||
case kColorTableAsset:
|
||||
case kImageAsset:
|
||||
@ -950,11 +954,11 @@ DataReadErrorCode SoundElement::load(DataReader& reader) {
|
||||
return kDataReadErrorNone;
|
||||
}
|
||||
|
||||
MovieElement::MovieElement()
|
||||
MovieElement::MovieElement(bool avi)
|
||||
: sizeIncludingTag(0), guid(0), lengthOfName(0), elementFlags(0), layer(0),
|
||||
unknown3{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
sectionID(0), unknown5{0, 0}, assetID(0), unknown7(0), volume(0), animationFlags(0),
|
||||
unknown10{0, 0, 0, 0}, unknown11{0, 0, 0, 0}, streamLocator(0), unknown13{0, 0, 0, 0} {
|
||||
unknown10{0, 0, 0, 0}, unknown11{0, 0, 0, 0}, streamLocator(0), unknown13{0, 0, 0, 0}, isAVI(avi) {
|
||||
}
|
||||
|
||||
DataReadErrorCode MovieElement::load(DataReader &reader) {
|
||||
@ -2078,6 +2082,25 @@ DataReadErrorCode MovieAsset::load(DataReader &reader) {
|
||||
return kDataReadErrorNone;
|
||||
}
|
||||
|
||||
AVIMovieAsset::AVIMovieAsset() : unknown1{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, assetID(0), unknown2{0, 0, 0, 0},
|
||||
extFileNameLength(0) {
|
||||
for (uint8 &v : unknown3)
|
||||
v = 0;
|
||||
}
|
||||
|
||||
DataReadErrorCode AVIMovieAsset::load(DataReader &reader) {
|
||||
if (_revision != 0)
|
||||
return kDataReadErrorUnsupportedRevision;
|
||||
|
||||
if (!reader.readBytes(unknown1) || !reader.readU32(assetID) || !reader.readBytes(unknown2) || !reader.readU16(extFileNameLength) || !reader.readBytes(unknown3))
|
||||
return kDataReadErrorReadFailed;
|
||||
|
||||
if (!reader.readTerminatedStr(extFileName, extFileNameLength))
|
||||
return kDataReadErrorReadFailed;
|
||||
|
||||
return kDataReadErrorNone;
|
||||
}
|
||||
|
||||
AudioAsset::AudioAsset()
|
||||
: persistFlags(0), assetAndDataCombinedSize(0), unknown2{0, 0, 0, 0}, assetID(0),
|
||||
unknown3{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, sampleRate1(0), bitsPerSample(0),
|
||||
@ -2421,7 +2444,10 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry ®istry, DataRea
|
||||
dataObject = new GraphicElement();
|
||||
break;
|
||||
case DataObjectTypes::kMovieElement:
|
||||
dataObject = new MovieElement();
|
||||
dataObject = new MovieElement(false);
|
||||
break;
|
||||
case DataObjectTypes::kAVIMovieElement:
|
||||
dataObject = new MovieElement(true);
|
||||
break;
|
||||
case DataObjectTypes::kMToonElement:
|
||||
dataObject = new MToonElement();
|
||||
@ -2561,6 +2587,10 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry ®istry, DataRea
|
||||
dataObject = new ColorTableAsset();
|
||||
break;
|
||||
|
||||
case DataObjectTypes::kAVIMovieAsset:
|
||||
dataObject = new AVIMovieAsset();
|
||||
break;
|
||||
|
||||
case DataObjectTypes::kMovieAsset:
|
||||
dataObject = new MovieAsset();
|
||||
break;
|
||||
|
@ -100,6 +100,7 @@ enum DataObjectType : uint {
|
||||
kSoundElement = 0xa,
|
||||
kTextLabelElement = 0x15,
|
||||
|
||||
kAVIMovieElement = 0x25,
|
||||
kAliasModifier = 0x27,
|
||||
kChangeSceneModifier = 0x136,
|
||||
kReturnModifier = 0x140,
|
||||
@ -148,6 +149,7 @@ enum DataObjectType : uint {
|
||||
kImageAsset = 0xe,
|
||||
kMToonAsset = 0xf,
|
||||
kTextAsset = 0x1f,
|
||||
kAVIMovieAsset = 0x24,
|
||||
|
||||
kAssetDataChunk = 0xffff,
|
||||
};
|
||||
@ -752,7 +754,7 @@ protected:
|
||||
};
|
||||
|
||||
struct MovieElement : public StructuralDef {
|
||||
MovieElement();
|
||||
explicit MovieElement(bool avi);
|
||||
|
||||
// Possible flags: NotDirectToScreen, CacheBitmap, Hidden, Loop, Loop + Alternate, Paused
|
||||
uint32 sizeIncludingTag;
|
||||
@ -776,6 +778,8 @@ struct MovieElement : public StructuralDef {
|
||||
|
||||
Common::String name;
|
||||
|
||||
bool isAVI;
|
||||
|
||||
protected:
|
||||
DataReadErrorCode load(DataReader &reader) override;
|
||||
};
|
||||
@ -1851,6 +1855,21 @@ protected:
|
||||
DataReadErrorCode load(DataReader &reader) override;
|
||||
};
|
||||
|
||||
struct AVIMovieAsset : public DataObject {
|
||||
AVIMovieAsset();
|
||||
|
||||
uint8 unknown1[12];
|
||||
uint32 assetID;
|
||||
uint8 unknown2[4];
|
||||
uint16 extFileNameLength;
|
||||
uint8 unknown3[60];
|
||||
|
||||
Common::String extFileName;
|
||||
|
||||
protected:
|
||||
DataReadErrorCode load(DataReader &reader) override;
|
||||
};
|
||||
|
||||
struct AudioAsset : public DataObject {
|
||||
struct MacPart {
|
||||
uint8 unknown4[4];
|
||||
|
@ -64,6 +64,7 @@ SIElementFactory *getElementFactoryForDataObjectType(const Data::DataObjectTypes
|
||||
switch (dataObjectType) {
|
||||
case Data::DataObjectTypes::kGraphicElement:
|
||||
return ElementFactory<GraphicElement, Data::GraphicElement>::getInstance();
|
||||
case Data::DataObjectTypes::kAVIMovieElement:
|
||||
case Data::DataObjectTypes::kMovieElement:
|
||||
return ElementFactory<MovieElement, Data::MovieElement>::getInstance();
|
||||
case Data::DataObjectTypes::kImageElement:
|
||||
|
@ -21,7 +21,9 @@
|
||||
|
||||
#include "video/video_decoder.h"
|
||||
#include "video/qt_decoder.h"
|
||||
#include "video/avi_decoder.h"
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/substream.h"
|
||||
|
||||
#include "graphics/macgui/macfontmanager.h"
|
||||
@ -618,42 +620,67 @@ void MovieElement::activate() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (asset->getAssetType() != kAssetTypeMovie) {
|
||||
warning("Movie element assigned an asset that isn't a movie");
|
||||
if (asset->getAssetType() == kAssetTypeMovie) {
|
||||
MovieAsset *movieAsset = static_cast<MovieAsset *>(asset.get());
|
||||
size_t streamIndex = movieAsset->getStreamIndex();
|
||||
int segmentIndex = project->getSegmentForStreamIndex(streamIndex);
|
||||
project->openSegmentStream(segmentIndex);
|
||||
Common::SeekableReadStream *stream = project->getStreamForSegment(segmentIndex);
|
||||
|
||||
if (!stream) {
|
||||
warning("Movie element stream could not be opened");
|
||||
return;
|
||||
}
|
||||
|
||||
Video::QuickTimeDecoder *qtDecoder = new Video::QuickTimeDecoder();
|
||||
qtDecoder->setChunkBeginOffset(movieAsset->getMovieDataPos());
|
||||
qtDecoder->setVolume(_volume * 255 / 100);
|
||||
|
||||
_videoDecoder.reset(qtDecoder);
|
||||
_damagedFrames = movieAsset->getDamagedFrames();
|
||||
|
||||
Common::SafeSeekableSubReadStream *movieDataStream = new Common::SafeSeekableSubReadStream(stream, movieAsset->getMovieDataPos(), movieAsset->getMovieDataPos() + movieAsset->getMovieDataSize(), DisposeAfterUse::NO);
|
||||
|
||||
if (!_videoDecoder->loadStream(movieDataStream))
|
||||
_videoDecoder.reset();
|
||||
else {
|
||||
if (getRuntime()->getHacks().removeQuickTimeEdits)
|
||||
qtDecoder->flattenEditLists();
|
||||
|
||||
_timeScale = qtDecoder->getTimeScale();
|
||||
|
||||
_maxTimestamp = qtDecoder->getDuration().convertToFramerate(qtDecoder->getTimeScale()).totalNumberOfFrames();
|
||||
}
|
||||
|
||||
_unloadSignaller = project->notifyOnSegmentUnload(segmentIndex, this);
|
||||
} else if (asset->getAssetType() == kAssetTypeAVIMovie) {
|
||||
AVIMovieAsset *aviAsset = static_cast<AVIMovieAsset *>(asset.get());
|
||||
|
||||
Common::File *f = new Common::File();
|
||||
if (!f->open(Common::Path(Common::String("VIDEO/") + aviAsset->getExtFileName()))) {
|
||||
warning("Movie asset could not be opened");
|
||||
delete f;
|
||||
return;
|
||||
}
|
||||
|
||||
Video::AVIDecoder *aviDec = new Video::AVIDecoder();
|
||||
aviDec->setVolume(_volume * 255 / 100);
|
||||
|
||||
_videoDecoder.reset(aviDec);
|
||||
|
||||
if (!_videoDecoder->loadStream(f))
|
||||
_videoDecoder.reset();
|
||||
else {
|
||||
_timeScale = 1000;
|
||||
_maxTimestamp = aviDec->getDuration().convertToFramerate(1000).totalNumberOfFrames();
|
||||
}
|
||||
} else {
|
||||
warning("Movie element referenced a non-movie asset");
|
||||
return;
|
||||
}
|
||||
|
||||
MovieAsset *movieAsset = static_cast<MovieAsset *>(asset.get());
|
||||
size_t streamIndex = movieAsset->getStreamIndex();
|
||||
int segmentIndex = project->getSegmentForStreamIndex(streamIndex);
|
||||
project->openSegmentStream(segmentIndex);
|
||||
Common::SeekableReadStream *stream = project->getStreamForSegment(segmentIndex);
|
||||
|
||||
if (!stream) {
|
||||
warning("Movie element stream could not be opened");
|
||||
return;
|
||||
}
|
||||
|
||||
Video::QuickTimeDecoder *qtDecoder = new Video::QuickTimeDecoder();
|
||||
qtDecoder->setChunkBeginOffset(movieAsset->getMovieDataPos());
|
||||
qtDecoder->setVolume(_volume * 255 / 100);
|
||||
|
||||
_videoDecoder.reset(qtDecoder);
|
||||
_damagedFrames = movieAsset->getDamagedFrames();
|
||||
|
||||
Common::SafeSeekableSubReadStream *movieDataStream = new Common::SafeSeekableSubReadStream(stream, movieAsset->getMovieDataPos(), movieAsset->getMovieDataPos() + movieAsset->getMovieDataSize(), DisposeAfterUse::NO);
|
||||
|
||||
if (!_videoDecoder->loadStream(movieDataStream))
|
||||
_videoDecoder.reset();
|
||||
|
||||
if (getRuntime()->getHacks().removeQuickTimeEdits)
|
||||
qtDecoder->flattenEditLists();
|
||||
_timeScale = qtDecoder->getTimeScale();
|
||||
|
||||
_unloadSignaller = project->notifyOnSegmentUnload(segmentIndex, this);
|
||||
_playMediaSignaller = project->notifyOnPlayMedia(this);
|
||||
|
||||
_maxTimestamp = qtDecoder->getDuration().convertToFramerate(qtDecoder->getTimeScale()).totalNumberOfFrames();
|
||||
_playRange = IntRange(0, 0);
|
||||
_currentTimestamp = 0;
|
||||
|
||||
@ -704,6 +731,9 @@ void MovieElement::queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying) {
|
||||
void MovieElement::render(Window *window) {
|
||||
const IntRange realRange = computeRealRange();
|
||||
|
||||
if (!_videoDecoder)
|
||||
return;
|
||||
|
||||
if (_needsReset) {
|
||||
_videoDecoder->setReverse(_reversed);
|
||||
_videoDecoder->seek(Audio::Timestamp(0, _timeScale).addFrames(_currentTimestamp));
|
||||
|
@ -3040,6 +3040,7 @@ enum AssetType {
|
||||
kAssetTypeImage,
|
||||
kAssetTypeText,
|
||||
kAssetTypeMToon,
|
||||
kAssetTypeAVIMovie,
|
||||
};
|
||||
|
||||
class AssetHooks {
|
||||
|
Loading…
Reference in New Issue
Block a user