nsresult WaveReader::ReadMetadata(nsVideoInfo* aInfo, MetadataTags** aTags) { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); bool loaded = LoadRIFFChunk() && LoadFormatChunk() && FindDataOffset(); if (!loaded) { return NS_ERROR_FAILURE; } mInfo.mHasAudio = true; mInfo.mHasVideo = false; mInfo.mAudioRate = mSampleRate; mInfo.mAudioChannels = mChannels; *aInfo = mInfo; *aTags = nullptr; ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mDecoder->GetStateMachine()->SetDuration( static_cast<int64_t>(BytesToTime(GetDataLength()) * USECS_PER_S)); return NS_OK; }
bool WaveReader::LoadAllChunks(nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags) { // Chunks are always word (two byte) aligned. MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0, "LoadAllChunks called with unaligned resource"); bool loadFormatChunk = false; bool findDataOffset = false; for (;;) { static const unsigned int CHUNK_HEADER_SIZE = 8; char chunkHeader[CHUNK_HEADER_SIZE]; const char* p = chunkHeader; if (!ReadAll(chunkHeader, sizeof(chunkHeader))) { return false; } static_assert(sizeof(uint32_t) * 2 <= CHUNK_HEADER_SIZE, "Reads would overflow chunkHeader buffer."); uint32_t magic = ReadUint32BE(&p); uint32_t chunkSize = ReadUint32LE(&p); int64_t chunkStart = GetPosition(); switch (magic) { case FRMT_CHUNK_MAGIC: loadFormatChunk = LoadFormatChunk(chunkSize); if (!loadFormatChunk) { return false; } break; case LIST_CHUNK_MAGIC: if (!aTags) { LoadListChunk(chunkSize, aTags); } break; case DATA_CHUNK_MAGIC: findDataOffset = FindDataOffset(chunkSize); return loadFormatChunk && findDataOffset; default: break; } // RIFF chunks are two-byte aligned, so round up if necessary. chunkSize += chunkSize % 2; // Move forward to next chunk CheckedInt64 forward = CheckedInt64(chunkStart) + chunkSize - GetPosition(); if (!forward.isValid() || forward.value() < 0) { return false; } static const int64_t MAX_CHUNK_SIZE = 1 << 16; static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char), "MAX_CHUNK_SIZE too large for enumerator."); nsAutoArrayPtr<char> chunk(new char[MAX_CHUNK_SIZE]); while (forward.value() > 0) { int64_t size = std::min(forward.value(), MAX_CHUNK_SIZE); if (!ReadAll(chunk.get(), size)) { return false; } forward -= size; } } return false; }