bool CUP_Player::parseNextHeaderTag(Common::SeekableReadStream &dataStream) { uint32 tag = dataStream.readUint32BE(); uint32 size = dataStream.readUint32BE() - 8; if (dataStream.eos()) return false; uint32 next = dataStream.pos() + size; debug(1, "New header tag %s %d dataSize %d", tag2str(tag), size, _dataSize); switch (tag) { case MKTAG('H','E','A','D'): handleHEAD(dataStream, size); break; case MKTAG('S','F','X','B'): handleSFXB(dataStream, size); break; case MKTAG('R','G','B','S'): handleRGBS(dataStream, size); break; case MKTAG('D','A','T','A'): _dataSize = size; return false; case MKTAG('G','F','X','B'): // this is never triggered default: warning("Unhandled tag %s", tag2str(tag)); break; } dataStream.seek(next); return true; }
byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) { uint32 curpos, totalsize, size; debugC(DEBUG_RESOURCE, "heFindResource(%s, %p)", tag2str(tag), (const void *)searchin); assert(searchin); searchin += 4; _resourceLastSearchSize = totalsize = READ_BE_UINT32(searchin); curpos = 8; searchin += 4; while (curpos < totalsize) { if (READ_BE_UINT32(searchin) == tag) { return searchin; } size = READ_BE_UINT32(searchin + 4); if ((int32)size <= 0) { error("(%s) Not found in %d... illegal block len %d", tag2str(tag), 0, size); return NULL; } curpos += size; searchin += size; } return NULL; }
void AVIDecoder::readNextPacket() { uint32 nextTag = _fileStream->readUint32BE(); uint32 size = _fileStream->readUint32LE(); if (_fileStream->eos()) return; if (nextTag == ID_LIST) { // A list of audio/video chunks int32 startPos = _fileStream->pos(); if (_fileStream->readUint32BE() != ID_REC) error("Expected 'rec ' LIST"); size -= 4; // subtract list type // Decode chunks in the list while (_fileStream->pos() < startPos + (int32)size) readNextPacket(); return; } else if (nextTag == ID_JUNK || nextTag == ID_IDX1) { skipChunk(size); return; } Track *track = getTrack(getStreamIndex(nextTag)); if (!track) error("Cannot get track from tag '%s'", tag2str(nextTag)); Common::SeekableReadStream *chunk = 0; if (size != 0) { chunk = _fileStream->readStream(size); _fileStream->skip(size & 1); } if (track->getTrackType() == Track::kTrackTypeAudio) { if (getStreamType(nextTag) != kStreamTypeAudio) error("Invalid audio track tag '%s'", tag2str(nextTag)); assert(chunk); ((AVIAudioTrack *)track)->queueSound(chunk); } else { AVIVideoTrack *videoTrack = (AVIVideoTrack *)track; if (getStreamType(nextTag) == kStreamTypePaletteChange) { // Palette Change videoTrack->loadPaletteFromChunk(chunk); } else if (getStreamType(nextTag) == kStreamTypeRawVideo) { // TODO: Check if this really is uncompressed. Many videos // falsely put compressed data in here. error("Uncompressed AVI frame found"); } else { // Otherwise, assume it's a compressed frame videoTrack->decodeFrame(chunk); } } }
void AviDecoder::runHandle(uint32 tag) { assert (_fileStream); if (_fileStream->eos()) return; debug (3, "Decoding tag %s", tag2str(tag)); switch (tag) { case ID_RIFF: /*_filesize = */_fileStream->readUint32LE(); if (_fileStream->readUint32BE() != ID_AVI) error("RIFF file is not an AVI video"); break; case ID_LIST: handleList(); break; case ID_AVIH: _header.size = _fileStream->readUint32LE(); _header.microSecondsPerFrame = _fileStream->readUint32LE(); _header.maxBytesPerSecond = _fileStream->readUint32LE(); _header.padding = _fileStream->readUint32LE(); _header.flags = _fileStream->readUint32LE(); _header.totalFrames = _fileStream->readUint32LE(); _header.initialFrames = _fileStream->readUint32LE(); _header.streams = _fileStream->readUint32LE(); _header.bufferSize = _fileStream->readUint32LE(); _header.width = _fileStream->readUint32LE(); _header.height = _fileStream->readUint32LE(); //Ignore 16 bytes of reserved data _fileStream->skip(16); break; case ID_STRH: handleStreamHeader(); break; case ID_STRD: // Extra stream info, safe to ignore case ID_VEDT: // Unknown, safe to ignore case ID_JUNK: // Alignment bytes, should be ignored { uint32 junkSize = _fileStream->readUint32LE(); _fileStream->skip(junkSize + (junkSize & 1)); // Alignment } break; case ID_IDX1: _ixInfo.size = _fileStream->readUint32LE(); _ixInfo.indices = new AVIOLDINDEX::Index[_ixInfo.size / 16]; debug (0, "%d Indices", (_ixInfo.size / 16)); for (uint32 i = 0; i < (_ixInfo.size / 16); i++) { _ixInfo.indices[i].id = _fileStream->readUint32BE(); _ixInfo.indices[i].flags = _fileStream->readUint32LE(); _ixInfo.indices[i].offset = _fileStream->readUint32LE(); _ixInfo.indices[i].size = _fileStream->readUint32LE(); debug (0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size); } break; default: error ("Unknown tag \'%s\' found", tag2str(tag)); } }
bool AVIDecoder::parseNextChunk() { uint32 tag = _fileStream->readUint32BE(); uint32 size = _fileStream->readUint32LE(); if (_fileStream->eos()) return false; debug(3, "Decoding tag %s", tag2str(tag)); switch (tag) { case ID_LIST: handleList(size); break; case ID_AVIH: _header.size = size; _header.microSecondsPerFrame = _fileStream->readUint32LE(); _header.maxBytesPerSecond = _fileStream->readUint32LE(); _header.padding = _fileStream->readUint32LE(); _header.flags = _fileStream->readUint32LE(); _header.totalFrames = _fileStream->readUint32LE(); _header.initialFrames = _fileStream->readUint32LE(); _header.streams = _fileStream->readUint32LE(); _header.bufferSize = _fileStream->readUint32LE(); _header.width = _fileStream->readUint32LE(); _header.height = _fileStream->readUint32LE(); // Ignore 16 bytes of reserved data _fileStream->skip(16); break; case ID_STRH: handleStreamHeader(size); break; case ID_STRD: // Extra stream info, safe to ignore case ID_VEDT: // Unknown, safe to ignore case ID_JUNK: // Alignment bytes, should be ignored case ID_ISFT: // Metadata, safe to ignore case ID_DISP: // Metadata, should be safe to ignore skipChunk(size); break; case ID_IDX1: debug(0, "%d Indices", size / 16); for (uint32 i = 0; i < size / 16; i++) { OldIndex indexEntry; indexEntry.id = _fileStream->readUint32BE(); indexEntry.flags = _fileStream->readUint32LE(); indexEntry.offset = _fileStream->readUint32LE() + _movieListStart - 4; // Adjust to absolute indexEntry.size = _fileStream->readUint32LE(); _indexEntries.push_back(indexEntry); debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags); } break; default: error("Unknown tag \'%s\' found", tag2str(tag)); } return true; }
Common::String Archive::getName(uint32 tag, uint16 id) const { if (!_types.contains(tag)) error("Archive does not contain '%s' %04x", tag2str(tag), id); const ResourceMap &resMap = _types[tag]; if (!resMap.contains(id)) error("Archive does not contain '%s' %04x", tag2str(tag), id); return resMap[id].name; }
uint32 Archive::getOffset(uint32 tag, uint16 id) const { if (!_types.contains(tag)) error("Archive does not contain '%s' %04x", tag2str(tag), id); const ResourceMap &resMap = _types[tag]; if (!resMap.contains(id)) error("Archive does not contain '%s' %04x", tag2str(tag), id); return resMap[id].offset; }
bool AVIDecoder::parseNextChunk() { uint32 tag = _fileStream->readUint32BE(); uint32 size = _fileStream->readUint32LE(); if (_fileStream->eos()) return false; debug(6, "Decoding tag %s", tag2str(tag)); switch (tag) { case ID_LIST: handleList(size); break; case ID_AVIH: _header.size = size; _header.microSecondsPerFrame = _fileStream->readUint32LE(); _header.maxBytesPerSecond = _fileStream->readUint32LE(); _header.padding = _fileStream->readUint32LE(); _header.flags = _fileStream->readUint32LE(); _header.totalFrames = _fileStream->readUint32LE(); _header.initialFrames = _fileStream->readUint32LE(); _header.streams = _fileStream->readUint32LE(); _header.bufferSize = _fileStream->readUint32LE(); _header.width = _fileStream->readUint32LE(); _header.height = _fileStream->readUint32LE(); // Ignore 16 bytes of reserved data _fileStream->skip(16); break; case ID_STRH: handleStreamHeader(size); break; case ID_STRD: // Extra stream info, safe to ignore case ID_VEDT: // Unknown, safe to ignore case ID_JUNK: // Alignment bytes, should be ignored case ID_JUNQ: // Same as JUNK, safe to ignore case ID_ISFT: // Metadata, safe to ignore case ID_DISP: // Metadata, should be safe to ignore case ID_DMLH: // OpenDML extension, contains an extra total frames field, safe to ignore skipChunk(size); break; case ID_STRN: // Metadata, safe to ignore readStreamName(size); break; case ID_IDX1: readOldIndex(size); break; default: error("Unknown tag \'%s\' found", tag2str(tag)); } return true; }
Common::SeekableSubReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) { if (!_types.contains(tag)) error("Archive does not contain '%s' %04x", tag2str(tag), id); const ResourceMap &resMap = _types[tag]; if (!resMap.contains(id)) error("Archive does not contain '%s' %04x", tag2str(tag), id); const Resource &res = resMap[id]; return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO); }
void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs, int &numMarkers) { uint32 tag; int32 size = 0; do { tag = READ_BE_UINT32(ptr); ptr += 4; switch (tag) { case MKTAG('S','T','O','P'): case MKTAG('F','R','M','T'): case MKTAG('D','A','T','A'): size = READ_BE_UINT32(ptr); ptr += size + 4; break; case MKTAG('T','E','X','T'): if (!scumm_stricmp((const char *)(ptr + 8), "exit")) numMarkers++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; case MKTAG('R','E','G','N'): numRegions++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; case MKTAG('J','U','M','P'): numJumps++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; case MKTAG('S','Y','N','C'): numSyncs++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; default: error("ImuseDigiSndMgr::countElements() Unknown sfx header '%s'", tag2str(tag)); } } while (tag != MKTAG('D','A','T','A')); }
Codec *createQuickTimeCodec(uint32 tag, int width, int height, int bitsPerPixel) { switch (tag) { case MKTAG('c','v','i','d'): // Cinepak: As used by most Myst and all Riven videos as well as some Myst ME videos. "The Chief" videos also use this. return new CinepakDecoder(bitsPerPixel); case MKTAG('r','p','z','a'): // Apple Video ("Road Pizza"): Used by some Myst videos. return new RPZADecoder(width, height); case MKTAG('r','l','e',' '): // QuickTime RLE: Used by some Myst ME videos. return new QTRLEDecoder(width, height, bitsPerPixel); case MKTAG('s','m','c',' '): // Apple SMC: Used by some Myst videos. return new SMCDecoder(width, height); case MKTAG('S','V','Q','1'): // Sorenson Video 1: Used by some Myst ME videos. return new SVQ1Decoder(width, height); case MKTAG('S','V','Q','3'): // Sorenson Video 3: Used by some Myst ME videos. warning("Sorenson Video 3 not yet supported"); break; case MKTAG('j','p','e','g'): // JPEG: Used by some Myst ME 10th Anniversary videos. return new JPEGDecoder(); case MKTAG('Q','k','B','k'): // CDToons: Used by most of the Broderbund games. return new CDToonsDecoder(width, height); default: warning("Unsupported QuickTime codec \'%s\'", tag2str(tag)); } return 0; }
void reportstats (void) { unsigned int grandcount = 1; unsigned int grandreachcount = 1; uint32_t grandspace = headspace; int k; for (k=0; k<MAX_TAG; k++) { grandcount += count[k]; grandreachcount += reachcount[k]; grandspace += space[k]; } if (rmode) printf("%7s", "% Reach"); printf("%10s %-20s%12s%10s\n\n", "Number", "Description", "Bytes", "% Space"); if (rmode) printf("%7.1f", pc(1,1)); printf("%10u %-20s%12u%10.1f\n", 1, "header", headspace, pc(headspace,grandspace)); for (k=0; k<=ListCons; (k==ExpDoStmt? k=AtomVariable: k++)) { if (rmode) printf("%7.1f", pc(reachcount[k], count[k])); printf("%10u %-20s%12u%10.1f\n", count[k], tag2str(k), space[k], pc(space[k],grandspace)); } { int w; putchar('\n'); if (rmode) for (w=0; w<7; w++) putchar(' '); for (w=0; w<55; w++) putchar(w<13 ? ' ' : '-'); putchar('\n'); } if (rmode) printf("%7.1f", pc(grandreachcount,grandcount)); printf("%10u %-20s%12u%10.1f\n", grandcount, "whole trace file", grandspace, pc(grandspace,grandspace)); }
bool BundleMgr::loadCompTable(int32 index) { _file->seek(_bundleTable[index].offset, SEEK_SET); uint32 tag = _file->readUint32BE(); _numCompItems = _file->readUint32BE(); assert(_numCompItems > 0); _file->seek(8, SEEK_CUR); if (tag != MKID_BE('COMP')) { error("BundleMgr::loadCompTable() Compressed sound %d invalid (%s)", index, tag2str(tag)); return false; } _compTable = (CompTable *)malloc(sizeof(CompTable) * _numCompItems); assert(_compTable); int32 maxSize = 0; for (int i = 0; i < _numCompItems; i++) { _compTable[i].offset = _file->readUint32BE(); _compTable[i].size = _file->readUint32BE(); _compTable[i].codec = _file->readUint32BE(); _file->seek(4, SEEK_CUR); if (_compTable[i].size > maxSize) maxSize = _compTable[i].size; } // CMI hack: one more byte at the end of input buffer _compInput = (byte *)malloc(maxSize + 1); assert(_compInput); return true; }
void AVIDecoder::handleList(uint32 listSize) { uint32 listType = _fileStream->readUint32BE(); listSize -= 4; // Subtract away listType's 4 bytes uint32 curPos = _fileStream->pos(); debug(0, "Found LIST of type %s", tag2str(listType)); switch (listType) { case ID_MOVI: // Movie List // We found the movie block _foundMovieList = true; _movieListStart = curPos; _fileStream->skip(listSize); return; case ID_HDRL: // Header List // Mark the header as decoded _decodedHeader = true; break; case ID_INFO: // Metadata case ID_PRMI: // Unknown metadata, should be safe to ignore // Ignore metadata _fileStream->skip(listSize); return; case ID_STRL: // Stream list default: // (Just hope we can parse it!) break; } while ((_fileStream->pos() - curPos) < listSize) parseNextChunk(); }
void QuickTimeDecoder::VideoSampleDesc::initCodec(Graphics::Surface &surface) { if (_codecTag == MKID_BE('mp4v')) { Common::UString videoType; // Parse the object type switch (_parentTrack->objectTypeMP4) { case 0x20: videoType = "h.263"; _videoCodec = new H263Codec(_parentTrack->width, _parentTrack->height); if (_parentTrack->extraData) _videoCodec->decodeFrame(surface, *_parentTrack->extraData); break; default: videoType = "Unknown"; break; } if (!_videoCodec) warning("MPEG-4 Video (%s) not yet supported", videoType.c_str()); } else if (_codecTag == MKID_BE('SVQ3')) { // TODO: Sorenson Video 3 warning("Sorenson Video 3 not yet supported"); } else { warning("Unsupported codec \'%s\'", tag2str(_codecTag)); } }
Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) { if (codecTag == MKID_BE('cvid')) { // Cinepak: As used by most Myst and all Riven videos as well as some Myst ME videos. "The Chief" videos also use this. return new CinepakDecoder(bitsPerPixel); } else if (codecTag == MKID_BE('rpza')) { // Apple Video ("Road Pizza"): Used by some Myst videos. return new RPZADecoder(getWidth(), getHeight()); } else if (codecTag == MKID_BE('rle ')) { // QuickTime RLE: Used by some Myst ME videos. return new QTRLEDecoder(getWidth(), getHeight(), bitsPerPixel); } else if (codecTag == MKID_BE('smc ')) { // Apple SMC: Used by some Myst videos. return new SMCDecoder(getWidth(), getHeight()); } else if (codecTag == MKID_BE('SVQ1')) { // Sorenson Video 1: Used by some Myst ME videos. warning("Sorenson Video 1 not yet supported"); } else if (codecTag == MKID_BE('SVQ3')) { // Sorenson Video 3: Used by some Myst ME videos. warning("Sorenson Video 3 not yet supported"); } else if (codecTag == MKID_BE('jpeg')) { // Motion JPEG: Used by some Myst ME 10th Anniversary videos. return new JPEGDecoder(); } else if (codecTag == MKID_BE('QkBk')) { // CDToons: Used by most of the Broderbund games. return new CDToonsDecoder(getWidth(), getHeight()); } else { warning("Unsupported codec \'%s\'", tag2str(codecTag)); } return NULL; }
Common::SeekableReadStream *ComposerEngine::getResource(uint32 tag, uint16 id) { for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++) if (i->_archive->hasResource(tag, id)) return i->_archive->getResource(tag, id); error("No loaded library contains '%s' %04x", tag2str(tag), id); }
Codec *AVIDecoder::AVIVideoTrack::createCodec() { switch (_vidsHeader.streamHandler) { case ID_CRAM: case ID_MSVC: case ID_WHAM: return new MSVideo1Decoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); case ID_RLE: return new MSRLEDecoder(_bmInfo.width, _bmInfo.height, _bmInfo.bitCount); case ID_CVID: return new CinepakDecoder(_bmInfo.bitCount); case ID_IV32: return new Indeo3Decoder(_bmInfo.width, _bmInfo.height); #ifdef VIDEO_CODECS_TRUEMOTION1_H case ID_DUCK: return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height); #endif #ifdef USE_MPEG2 case ID_MPG2: return new MPEGDecoder(); #endif default: warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler)); } return 0; }
Common::SeekableReadStream *MohawkEngine::getResource(uint32 tag, uint16 id) { for (uint32 i = 0; i < _mhk.size(); i++) if (_mhk[i]->hasResource(tag, id)) return _mhk[i]->getResource(tag, id); error("Could not find a '%s' resource with ID %04x", tag2str(tag), id); return NULL; }
uint16 MohawkEngine::findResourceID(uint32 tag, const Common::String &resName) { for (uint32 i = 0; i < _mhk.size(); i++) if (_mhk[i]->hasResource(tag, resName)) return _mhk[i]->findResourceID(tag, resName); error("Could not find a '%s' resource matching name '%s'", tag2str(tag), resName.c_str()); return 0xFFFF; }
uint32 MohawkEngine::getResourceOffset(uint32 tag, uint16 id) { for (uint32 i = 0; i < _mhk.size(); i++) if (_mhk[i]->hasResource(tag, id)) return _mhk[i]->getOffset(tag, id); error("Could not find a '%s' resource with ID %04x", tag2str(tag), id); return 0; }
void dopointer (int okzero, int requiretag, FileOffset requireoffset, int contexttag, FileOffset contextoffset, char *edgelabel) { if (vmode && ((okzero==NONZERO && requireoffset <= Interrupted) || (okzero==MAYBELAMBDA && requireoffset < Lambda))) { fprintf(stderr, "bad %s pointer in %s 0x%x\n" ,ref2str(requireoffset), tag2str(contexttag), contextoffset); } if (vmode && requireoffset>DoLambda) { int t = tagat(requireoffset); if (t != requiretag) { if ((requiretag==ANYEXP) && (ExpApp<=t) && (t<=ExpDoStmt)) ; else if ((requiretag==ANYATOM) && (AtomVariable<=t) && (t<=AtomAbstract)) ; else fprintf(stderr, "tag at 0x%x is %s, not %s as %s at 0x%x implies\n" , requireoffset, tag2str(t), tag2str(requiretag) , tag2str(contexttag), contextoffset); } } if (amode) { switch(requireoffset) { case Root: case Unevaluated: case Entered: case Interrupted: case Lambda: case DoLambda: printf("(%s)",ref2str(requireoffset)); break; default: printf("(%s 0x%x)", tag2str(requiretag), requireoffset); break; } } if (gmode && requireoffset!=0 && *edgelabel != '\0') if (strcmp(edgelabel,"p")==0) printf("%d -> %d [style=dashed]\n", contextoffset, requireoffset); else printf("%d -> %d [label=\"%s\"]\n", contextoffset, requireoffset, edgelabel); }
Common::String MohawkEngine::getResourceName(uint32 tag, uint16 id) { for (uint32 i = 0; i < _mhk.size(); i++) if (_mhk[i]->hasResource(tag, id)) { return _mhk[i]->getName(tag, id); } error("Could not find a \'%s\' resource with ID %04x", tag2str(tag), id); return 0; }
bool CUP_Player::parseNextBlockTag(Common::SeekableReadStream &dataStream) { uint32 tag = dataStream.readUint32BE(); uint32 size = dataStream.readUint32BE() - 8; uint32 next = dataStream.pos() + size; debug(1, "New block tag %s %d dataSize %d", tag2str(tag), size, _dataSize); switch (tag) { case MKTAG('F','R','A','M'): handleFRAM(dataStream, size); break; case MKTAG('L','Z','S','S'): if (handleLZSS(dataStream, size) && _outLzssBufSize != 0) { Common::MemoryReadStream memoryStream(_outLzssBufData, _outLzssBufSize); parseNextBlockTag(memoryStream); } break; case MKTAG('R','A','T','E'): handleRATE(dataStream, size); break; case MKTAG('R','G','B','S'): handleRGBS(dataStream, size); break; case MKTAG('S','N','D','E'): handleSNDE(dataStream, size); break; case MKTAG('T','O','I','L'): handleTOIL(dataStream, size); break; case MKTAG('S','R','L','E'): handleSRLE(dataStream, size); break; case MKTAG('B','L','O','K'): _dataSize -= size + 8; return false; case MKTAG('W','R','L','E'): // this is never triggered default: warning("Unhandled tag %s", tag2str(tag)); break; } dataStream.seek(next); return true; }
void AVIDecoder::readOldIndex(uint32 size) { uint32 entryCount = size / 16; debug(7, "Old Index: %d entries", entryCount); if (entryCount == 0) return; // Read the first index separately OldIndex firstEntry; firstEntry.id = _fileStream->readUint32BE(); firstEntry.flags = _fileStream->readUint32LE(); firstEntry.offset = _fileStream->readUint32LE(); firstEntry.size = _fileStream->readUint32LE(); // Check if the offset is already absolute // If it's absolute, the offset will equal the start of the movie list bool isAbsolute = firstEntry.offset == _movieListStart; debug(6, "Old index is %s", isAbsolute ? "absolute" : "relative"); if (!isAbsolute) firstEntry.offset += _movieListStart - 4; debug(7, "Index 0: Tag '%s', Offset = %d, Size = %d (Flags = %d)", tag2str(firstEntry.id), firstEntry.offset, firstEntry.size, firstEntry.flags); _indexEntries.push_back(firstEntry); for (uint32 i = 1; i < entryCount; i++) { OldIndex indexEntry; indexEntry.id = _fileStream->readUint32BE(); indexEntry.flags = _fileStream->readUint32LE(); indexEntry.offset = _fileStream->readUint32LE(); indexEntry.size = _fileStream->readUint32LE(); // Adjust to absolute, if necessary if (!isAbsolute) indexEntry.offset += _movieListStart - 4; _indexEntries.push_back(indexEntry); debug(7, "Index %d: Tag '%s', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags); } }
int QuickTimeDecoder::readHDLR(MOVatom atom) { MOVStreamContext *st = _streams[_numStreams - 1]; _fd->readByte(); // version _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags // component type uint32 ctype = _fd->readUint32LE(); uint32 type = _fd->readUint32BE(); // component subtype debug(0, "ctype= %s (0x%08lx)", tag2str(ctype), (long)ctype); debug(0, "stype= %s", tag2str(type)); if(ctype == MKTAG('m','h','l','r')) // MOV debug(0, "MOV detected"); else if(ctype == 0) { warning("MP4 streams are not supported"); return -1; } if (type == MKTAG('v','i','d','e')) st->codec_type = CODEC_TYPE_VIDEO; else if (type == MKTAG('s','o','u','n')) st->codec_type = CODEC_TYPE_AUDIO; _fd->readUint32BE(); // component manufacture _fd->readUint32BE(); // component flags _fd->readUint32BE(); // component flags mask if (atom.size <= 24) return 0; // nothing left to read // .mov: PASCAL string byte len = _fd->readByte(); _fd->seek(len, SEEK_CUR); _fd->seek(atom.size - (_fd->pos() - atom.offset), SEEK_CUR); return 0; }
int QuickTimeParser::readHDLR(Atom atom) { Track *track = _tracks.back(); _fd->readByte(); // version _fd->readByte(); _fd->readByte(); _fd->readByte(); // flags // component type uint32 ctype = _fd->readUint32BE(); uint32 type = _fd->readUint32BE(); // component subtype debug(0, "ctype= %s (0x%08lx)", tag2str(ctype), (long)ctype); debug(0, "stype= %s", tag2str(type)); if (ctype == MKTAG('m', 'h', 'l', 'r')) // MOV debug(0, "MOV detected"); else if (ctype == 0) debug(0, "MPEG-4 detected"); if (type == MKTAG('v', 'i', 'd', 'e')) track->codecType = CODEC_TYPE_VIDEO; else if (type == MKTAG('s', 'o', 'u', 'n')) track->codecType = CODEC_TYPE_AUDIO; else if (type == MKTAG('m', 'u', 's', 'i')) track->codecType = CODEC_TYPE_MIDI; _fd->readUint32BE(); // component manufacture _fd->readUint32BE(); // component flags _fd->readUint32BE(); // component flags mask if (atom.size <= 24) return 0; // nothing left to read // .mov: PASCAL string byte len = _fd->readByte(); _fd->seek(len, SEEK_CUR); _fd->seek(atom.size - (_fd->pos() - atom.offset), SEEK_CUR); return 0; }
void AviDecoder::handleList() { uint32 listSize = _fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes uint32 listType = _fileStream->readUint32BE(); uint32 curPos = _fileStream->pos(); debug (0, "Found LIST of type %s", tag2str(listType)); while ((_fileStream->pos() - curPos) < listSize) runHandle(_fileStream->readUint32BE()); // We now have all the header data if (listType == ID_HDRL) _decodedHeader = true; }
Common::QuickTimeParser::SampleDesc *QuickTimeAudioDecoder::readSampleDesc(Track *track, uint32 format) { if (track->codecType == CODEC_TYPE_AUDIO) { debug(0, "Audio Codec FourCC: \'%s\'", tag2str(format)); AudioSampleDesc *entry = new AudioSampleDesc(track, format); uint16 stsdVersion = _fd->readUint16BE(); _fd->readUint16BE(); // revision level _fd->readUint32BE(); // vendor entry->_channels = _fd->readUint16BE(); // channel count entry->_bitsPerSample = _fd->readUint16BE(); // sample size _fd->readUint16BE(); // compression id = 0 _fd->readUint16BE(); // packet size = 0 entry->_sampleRate = (_fd->readUint32BE() >> 16); debug(0, "stsd version =%d", stsdVersion); if (stsdVersion == 0) { // Not used, except in special cases. See below. entry->_samplesPerFrame = entry->_bytesPerFrame = 0; } else if (stsdVersion == 1) { // Read QT version 1 fields. In version 0 these dont exist. entry->_samplesPerFrame = _fd->readUint32BE(); debug(0, "stsd samples_per_frame =%d",entry->_samplesPerFrame); _fd->readUint32BE(); // bytes per packet entry->_bytesPerFrame = _fd->readUint32BE(); debug(0, "stsd bytes_per_frame =%d", entry->_bytesPerFrame); _fd->readUint32BE(); // bytes per sample } else { warning("Unsupported QuickTime STSD audio version %d", stsdVersion); delete entry; return 0; } // Version 0 videos (such as the Riven ones) don't have this set, // but we need it later on. Add it in here. if (format == MKTAG('i', 'm', 'a', '4')) { entry->_samplesPerFrame = 64; entry->_bytesPerFrame = 34 * entry->_channels; } if (entry->_sampleRate == 0 && track->timeScale > 1) entry->_sampleRate = track->timeScale; return entry; }
bool SaudChannel::handleSubTags(int32 &offset) { if (_tbufferSize - offset >= 8) { uint32 type = READ_BE_UINT32(_tbuffer + offset); uint32 size = READ_BE_UINT32(_tbuffer + offset + 4); uint32 available_size = _tbufferSize - offset; switch (type) { case MKID_BE('STRK'): _inData = false; if (available_size >= (size + 8)) { int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4); if (subSize != 14 && subSize != 10) { error("STRK has an invalid size : %d", subSize); } } else return false; break; case MKID_BE('SMRK'): _inData = false; if (available_size >= (size + 8)) _markReached = true; else return false; break; case MKID_BE('SHDR'): _inData = false; if (available_size >= (size + 8)) { int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4); if (subSize != 4) error("SHDR has an invalid size : %d", subSize); } else return false; break; case MKID_BE('SDAT'): _inData = true; _dataSize = size; offset += 8; return false; default: error("unknown Chunk in SAUD track : %s ", tag2str(type)); } offset += size + 8; return true; } return false; }