public override void Close() { base.Close(); _audioTrack = null; _videoTrack = null; _frameCount = 0; if (_stream != null) { _stream.Dispose(); _stream = null; } }
protected override void ReadNextPacket() { Stream sector = null; BinaryReader br = null; byte[] partialFrame = null; int sectorsRead = 0; while (_stream.Position < _stream.Length) { sector = ReadSector(); sectorsRead++; if (sector == null) throw new InvalidOperationException("Corrupt PSX stream sector"); br = new BinaryReader(sector); sector.Seek(0x11, SeekOrigin.Begin); byte track = (byte)sector.ReadByte(); if (track >= 32) throw new InvalidOperationException("Bad PSX stream track"); byte sectorType = (byte)(br.ReadByte() & CDXA_TYPE_MASK); switch (sectorType) { case CDXA_TYPE_DATA: case CDXA_TYPE_VIDEO: if (track == 1) { if (_videoTrack == null) { _videoTrack = new PsxVideoTrack(sector, _speed, _frameCount, _screenFormat); AddTrack(_videoTrack); } sector.Seek(28, SeekOrigin.Begin); ushort curSector = br.ReadUInt16(); ushort sectorCount = br.ReadUInt16(); br.ReadUInt32(); ushort frameSize = (ushort)br.ReadUInt32(); if (curSector >= sectorCount) throw new InvalidOperationException("Bad sector"); if (partialFrame == null) partialFrame = new byte[sectorCount * VIDEO_DATA_CHUNK_SIZE]; sector.Seek(VIDEO_DATA_HEADER_SIZE, SeekOrigin.Begin); sector.Read(partialFrame, curSector * VIDEO_DATA_CHUNK_SIZE, VIDEO_DATA_CHUNK_SIZE); if (curSector == sectorCount - 1) { // Done assembling the frame using (var frame = new MemoryStream(partialFrame, 0, frameSize)) { _videoTrack.DecodeFrame(frame, sectorsRead); } sector.Dispose(); return; } } else throw new InvalidOperationException("Unhandled multi-track video"); break; case CDXA_TYPE_AUDIO: // We only handle one audio channel so far if (track == 1) { if (_audioTrack == null) { _audioTrack = new PsxAudioTrack(_mixer, sector); AddTrack(_audioTrack); } _audioTrack.QueueAudioFromSector(sector); } else { // TODO: warning("Unhandled multi-track audio"); } break; default: // This shows up way too often, but the other sectors // are safe to ignore //TODO: warning("Unknown PSX sector type 0x%x", sectorType); break; } sector.Dispose(); sector = null; } if (_stream.Position >= _stream.Length) { if (_videoTrack != null) _videoTrack.SetEndOfTrack(); if (_audioTrack != null) _audioTrack.SetEndOfTrack(); } }
protected override void ReadNextPacket() { Stream sector = null; BinaryReader br = null; byte[] partialFrame = null; int sectorsRead = 0; while (_stream.Position < _stream.Length) { sector = ReadSector(); sectorsRead++; if (sector == null) { throw new InvalidOperationException("Corrupt PSX stream sector"); } br = new BinaryReader(sector); sector.Seek(0x11, SeekOrigin.Begin); byte track = (byte)sector.ReadByte(); if (track >= 32) { throw new InvalidOperationException("Bad PSX stream track"); } byte sectorType = (byte)(br.ReadByte() & CDXA_TYPE_MASK); switch (sectorType) { case CDXA_TYPE_DATA: case CDXA_TYPE_VIDEO: if (track == 1) { if (_videoTrack == null) { _videoTrack = new PsxVideoTrack(sector, _speed, _frameCount, _screenFormat); AddTrack(_videoTrack); } sector.Seek(28, SeekOrigin.Begin); ushort curSector = br.ReadUInt16(); ushort sectorCount = br.ReadUInt16(); br.ReadUInt32(); ushort frameSize = (ushort)br.ReadUInt32(); if (curSector >= sectorCount) { throw new InvalidOperationException("Bad sector"); } if (partialFrame == null) { partialFrame = new byte[sectorCount * VIDEO_DATA_CHUNK_SIZE]; } sector.Seek(VIDEO_DATA_HEADER_SIZE, SeekOrigin.Begin); sector.Read(partialFrame, curSector * VIDEO_DATA_CHUNK_SIZE, VIDEO_DATA_CHUNK_SIZE); if (curSector == sectorCount - 1) { // Done assembling the frame using (var frame = new MemoryStream(partialFrame, 0, frameSize)) { _videoTrack.DecodeFrame(frame, sectorsRead); } sector.Dispose(); return; } } else { throw new InvalidOperationException("Unhandled multi-track video"); } break; case CDXA_TYPE_AUDIO: // We only handle one audio channel so far if (track == 1) { if (_audioTrack == null) { _audioTrack = new PsxAudioTrack(_mixer, sector); AddTrack(_audioTrack); } _audioTrack.QueueAudioFromSector(sector); } else { // TODO: warning("Unhandled multi-track audio"); } break; default: // This shows up way too often, but the other sectors // are safe to ignore //TODO: warning("Unknown PSX sector type 0x%x", sectorType); break; } sector.Dispose(); sector = null; } if (_stream.Position >= _stream.Length) { if (_videoTrack != null) { _videoTrack.SetEndOfTrack(); } if (_audioTrack != null) { _audioTrack.SetEndOfTrack(); } } }