VIDEO: Begin splitting video-specific QuickTime sample description code

This commit is contained in:
Matthew Hoops 2011-04-06 23:06:44 -04:00
parent 82a417b40c
commit b71d2038ae
2 changed files with 54 additions and 35 deletions

View File

@ -186,7 +186,7 @@ void QuickTimeDecoder::seekToFrame(uint32 frame) {
_audioStartOffset = curVideoTime; _audioStartOffset = curVideoTime;
// Re-create the audio stream // Re-create the audio stream
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0]; AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
_audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2); _audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2);
// First, we need to track down what audio sample we need // First, we need to track down what audio sample we need
@ -318,10 +318,10 @@ void QuickTimeDecoder::pauseVideoIntern(bool pause) {
} }
Codec *QuickTimeDecoder::findDefaultVideoCodec() const { Codec *QuickTimeDecoder::findDefaultVideoCodec() const {
if (_videoStreamIndex < 0 || !_streams[_videoStreamIndex]->stsdEntryCount) if (_videoStreamIndex < 0 || _streams[_videoStreamIndex]->sampleDescs.empty())
return 0; return 0;
return _streams[_videoStreamIndex]->stsdEntries[0].videoCodec; return ((VideoSampleDesc *)_streams[_videoStreamIndex]->sampleDescs[0])->videoCodec;
} }
const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() { const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() {
@ -341,11 +341,11 @@ const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() {
uint32 descId; uint32 descId;
Common::SeekableReadStream *frameData = getNextFramePacket(descId); Common::SeekableReadStream *frameData = getNextFramePacket(descId);
if (!frameData || !descId || descId > _streams[_videoStreamIndex]->stsdEntryCount) if (!frameData || !descId || descId > _streams[_videoStreamIndex]->sampleDescs.size())
return 0; return 0;
// Find which video description entry we want // Find which video description entry we want
STSDEntry *entry = &_streams[_videoStreamIndex]->stsdEntries[descId - 1]; VideoSampleDesc *entry = (VideoSampleDesc *)_streams[_videoStreamIndex]->sampleDescs[descId - 1];
if (!entry->videoCodec) if (!entry->videoCodec)
return 0; return 0;
@ -500,7 +500,7 @@ void QuickTimeDecoder::init() {
// Initialize audio, if present // Initialize audio, if present
if (_audioStreamIndex >= 0) { if (_audioStreamIndex >= 0) {
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0]; AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
if (checkAudioCodecSupport(entry->codecTag)) { if (checkAudioCodecSupport(entry->codecTag)) {
_audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2); _audStream = Audio::makeQueuingAudioStream(entry->sampleRate, entry->channels == 2);
@ -518,8 +518,8 @@ void QuickTimeDecoder::init() {
// Initialize video, if present // Initialize video, if present
if (_videoStreamIndex >= 0) { if (_videoStreamIndex >= 0) {
for (uint32 i = 0; i < _streams[_videoStreamIndex]->stsdEntryCount; i++) { for (uint32 i = 0; i < _streams[_videoStreamIndex]->sampleDescs.size(); i++) {
STSDEntry *entry = &_streams[_videoStreamIndex]->stsdEntries[i]; VideoSampleDesc *entry = (VideoSampleDesc *)_streams[_videoStreamIndex]->sampleDescs[i];
entry->videoCodec = createCodec(entry->codecTag, entry->bitsPerSample & 0x1F); entry->videoCodec = createCodec(entry->codecTag, entry->bitsPerSample & 0x1F);
} }
@ -916,12 +916,10 @@ int QuickTimeDecoder::readSTSD(MOVatom atom) {
_fd->readByte(); // version _fd->readByte(); // version
_fd->readByte(); _fd->readByte(); _fd->readByte(); // flags _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags
st->stsdEntryCount = _fd->readUint32BE(); uint32 entryCount = _fd->readUint32BE();
st->stsdEntries = new STSDEntry[st->stsdEntryCount]; st->sampleDescs.resize(entryCount);
for (uint32 i = 0; i < st->stsdEntryCount; i++) { // Parsing Sample description table
STSDEntry *entry = &st->stsdEntries[i];
for (uint32 i = 0; i < entryCount; i++) { // Parsing Sample description table
MOVatom a = { 0, 0, 0 }; MOVatom a = { 0, 0, 0 };
uint32 start_pos = _fd->pos(); uint32 start_pos = _fd->pos();
int size = _fd->readUint32BE(); // size int size = _fd->readUint32BE(); // size
@ -933,11 +931,14 @@ int QuickTimeDecoder::readSTSD(MOVatom atom) {
debug(0, "size=%d 4CC= %s codec_type=%d", size, tag2str(format), st->codec_type); debug(0, "size=%d 4CC= %s codec_type=%d", size, tag2str(format), st->codec_type);
entry->codecTag = format;
if (st->codec_type == CODEC_TYPE_VIDEO) { if (st->codec_type == CODEC_TYPE_VIDEO) {
debug(0, "Video Codec FourCC: \'%s\'", tag2str(format)); debug(0, "Video Codec FourCC: \'%s\'", tag2str(format));
VideoSampleDesc *entry = new VideoSampleDesc();
st->sampleDescs[i] = entry;
entry->codecTag = format;
_fd->readUint16BE(); // version _fd->readUint16BE(); // version
_fd->readUint16BE(); // revision level _fd->readUint16BE(); // revision level
_fd->readUint32BE(); // vendor _fd->readUint32BE(); // vendor
@ -1025,6 +1026,11 @@ int QuickTimeDecoder::readSTSD(MOVatom atom) {
} else if (st->codec_type == CODEC_TYPE_AUDIO) { } else if (st->codec_type == CODEC_TYPE_AUDIO) {
debug(0, "Audio Codec FourCC: \'%s\'", tag2str(format)); debug(0, "Audio Codec FourCC: \'%s\'", tag2str(format));
AudioSampleDesc *entry = new AudioSampleDesc();
st->sampleDescs[i] = entry;
entry->codecTag = format;
uint16 stsdVersion = _fd->readUint16BE(); uint16 stsdVersion = _fd->readUint16BE();
_fd->readUint16BE(); // revision level _fd->readUint16BE(); // revision level
_fd->readUint32BE(); // vendor _fd->readUint32BE(); // vendor
@ -1229,7 +1235,7 @@ int QuickTimeDecoder::readWAVE(MOVatom atom) {
if (atom.size > (1 << 30)) if (atom.size > (1 << 30))
return -1; return -1;
if (st->stsdEntries[0].codecTag == MKID_BE('QDM2')) // Read extradata for QDM2 if (st->sampleDescs[0]->codecTag == MKID_BE('QDM2')) // Read extradata for QDM2
st->extradata = _fd->readStream(atom.size - 8); st->extradata = _fd->readStream(atom.size - 8);
else if (atom.size > 8) else if (atom.size > 8)
return readDefault(atom); return readDefault(atom);
@ -1336,7 +1342,7 @@ Audio::AudioStream *QuickTimeDecoder::createAudioStream(Common::SeekableReadStre
if (!stream || _audioStreamIndex < 0) if (!stream || _audioStreamIndex < 0)
return NULL; return NULL;
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0]; AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
if (entry->codecTag == MKID_BE('twos') || entry->codecTag == MKID_BE('raw ')) { if (entry->codecTag == MKID_BE('twos') || entry->codecTag == MKID_BE('raw ')) {
// Fortunately, most of the audio used in Myst videos is raw... // Fortunately, most of the audio used in Myst videos is raw...
@ -1381,7 +1387,7 @@ uint32 QuickTimeDecoder::getAudioChunkSampleCount(uint chunk) {
} }
void QuickTimeDecoder::readNextAudioChunk() { void QuickTimeDecoder::readNextAudioChunk() {
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0]; AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic(); Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
_fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]); _fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
@ -1430,7 +1436,7 @@ void QuickTimeDecoder::updateAudioBuffer() {
// If we're on the last frame, make sure all audio remaining is buffered // If we're on the last frame, make sure all audio remaining is buffered
numberOfChunksNeeded = _streams[_audioStreamIndex]->chunk_count; numberOfChunksNeeded = _streams[_audioStreamIndex]->chunk_count;
} else { } else {
STSDEntry *entry = &_streams[_audioStreamIndex]->stsdEntries[0]; AudioSampleDesc *entry = (AudioSampleDesc *)_streams[_audioStreamIndex]->sampleDescs[0];
// Calculate the amount of chunks we need in memory until the next frame // Calculate the amount of chunks we need in memory until the next frame
uint32 timeToNextFrame = getTimeToNextFrame(); uint32 timeToNextFrame = getTimeToNextFrame();
@ -1453,24 +1459,30 @@ void QuickTimeDecoder::updateAudioBuffer() {
readNextAudioChunk(); readNextAudioChunk();
} }
QuickTimeDecoder::STSDEntry::STSDEntry() { QuickTimeDecoder::SampleDesc::SampleDesc() {
codecTag = 0; codecTag = 0;
bitsPerSample = 0; bitsPerSample = 0;
}
QuickTimeDecoder::VideoSampleDesc::VideoSampleDesc() : SampleDesc() {
memset(codecName, 0, 32); memset(codecName, 0, 32);
colorTableId = 0; colorTableId = 0;
palette = 0; palette = 0;
videoCodec = 0; videoCodec = 0;
}
QuickTimeDecoder::VideoSampleDesc::~VideoSampleDesc() {
delete[] palette;
delete videoCodec;
}
QuickTimeDecoder::AudioSampleDesc::AudioSampleDesc() : SampleDesc() {
channels = 0; channels = 0;
sampleRate = 0; sampleRate = 0;
samplesPerFrame = 0; samplesPerFrame = 0;
bytesPerFrame = 0; bytesPerFrame = 0;
} }
QuickTimeDecoder::STSDEntry::~STSDEntry() {
delete[] palette;
delete videoCodec;
}
QuickTimeDecoder::MOVStreamContext::MOVStreamContext() { QuickTimeDecoder::MOVStreamContext::MOVStreamContext() {
chunk_count = 0; chunk_count = 0;
chunk_offsets = 0; chunk_offsets = 0;
@ -1488,8 +1500,6 @@ QuickTimeDecoder::MOVStreamContext::MOVStreamContext() {
width = 0; width = 0;
height = 0; height = 0;
codec_type = CODEC_TYPE_MOV_OTHER; codec_type = CODEC_TYPE_MOV_OTHER;
stsdEntryCount = 0;
stsdEntries = 0;
editCount = 0; editCount = 0;
editList = 0; editList = 0;
extradata = 0; extradata = 0;
@ -1504,9 +1514,11 @@ QuickTimeDecoder::MOVStreamContext::~MOVStreamContext() {
delete[] sample_to_chunk; delete[] sample_to_chunk;
delete[] sample_sizes; delete[] sample_sizes;
delete[] keyframes; delete[] keyframes;
delete[] stsdEntries;
delete[] editList; delete[] editList;
delete extradata; delete extradata;
for (uint32 i = 0; i < sampleDescs.size(); i++)
delete sampleDescs[i];
} }
} // End of namespace Video } // End of namespace Video

View File

@ -34,6 +34,7 @@
#ifndef VIDEO_QT_DECODER_H #ifndef VIDEO_QT_DECODER_H
#define VIDEO_QT_DECODER_H #define VIDEO_QT_DECODER_H
#include "common/array.h"
#include "common/scummsys.h" #include "common/scummsys.h"
#include "common/queue.h" #include "common/queue.h"
#include "common/rational.h" #include "common/rational.h"
@ -156,20 +157,27 @@ private:
Common::Rational mediaRate; Common::Rational mediaRate;
}; };
struct STSDEntry { struct SampleDesc {
STSDEntry(); SampleDesc();
~STSDEntry(); virtual ~SampleDesc() {}
uint32 codecTag; uint32 codecTag;
uint16 bitsPerSample; uint16 bitsPerSample;
};
struct VideoSampleDesc : public SampleDesc {
VideoSampleDesc();
~VideoSampleDesc();
// Video
char codecName[32]; char codecName[32];
uint16 colorTableId; uint16 colorTableId;
byte *palette; byte *palette;
Codec *videoCodec; Codec *videoCodec;
};
struct AudioSampleDesc : public SampleDesc {
AudioSampleDesc();
// Audio
uint16 channels; uint16 channels;
uint32 sampleRate; uint32 sampleRate;
uint32 samplesPerFrame; uint32 samplesPerFrame;
@ -204,8 +212,7 @@ private:
uint16 height; uint16 height;
CodecType codec_type; CodecType codec_type;
uint32 stsdEntryCount; Common::Array<SampleDesc *> sampleDescs;
STSDEntry *stsdEntries;
uint32 editCount; uint32 editCount;
EditListEntry *editList; EditListEntry *editList;