www.pudn.com > mediator15src.zip > asyncstream.cpp
/* * asyncstream.cpp * Copyright (C) 2001-2002 Arno Hornberger* * This file is part of MPEG Mediator, a free MPEG stream converter. * * MPEG Mediator is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPEG Mediator is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "asyncstream.h" AsyncStream::AsyncStream() { bitbuffer = new unsigned char[BUFFERSIZE]; for (int i = 0; i < MAXFILES; i++) filehandles[i] = 0; nfiles = 0; } AsyncStream::~AsyncStream() { if (nfiles > 0) Close(); if (bitbuffer) delete []bitbuffer; } int AsyncStream::ReadBytes(unsigned char *buffer, int size, __int64 loc) { int bytes_read; int bytes_to_read = size; int file = WhichFile(loc); if (end_of_stream) return 0; while (bytes_to_read > 0) { // bytes_read = fread(buffer, sizeof(unsigned char), // bytes_to_read, filehandles[file]); bytes_read = _read(filehandles[file], buffer, bytes_to_read); if (bytes_read == bytes_to_read) return size; if (bytes_read < 0) bytes_read = 0; bytes_to_read -= bytes_read; if ((_eof(filehandles[file]) <= 0) || (file + 1 == nfiles)) { end_of_stream = true; // read error or end of stream return size - bytes_to_read; } buffer += bytes_read; file++; } return size; } int AsyncStream::ReadChunk() { int bytes; int buffer_offset; if (end_of_stream) return 0; if (stop - start + CHUNKSIZE > BUFFERSIZE) start += CHUNKSIZE; buffer_offset = (int)stop & BUFFERMASK; if (buffer_offset + CHUNKSIZE > BUFFERSIZE) { bytes = ReadBytes(&bitbuffer[buffer_offset], BUFFERSIZE - buffer_offset, stop); bytes += ReadBytes(&bitbuffer[0], CHUNKSIZE - (BUFFERSIZE - buffer_offset), stop + (BUFFERSIZE - buffer_offset)); } else bytes = ReadBytes(&bitbuffer[buffer_offset], CHUNKSIZE, stop); stop += bytes; return bytes; } void AsyncStream::Open(char **filenames, int count) { // fpos_t fpos; int error = 0; if (count > MAXFILES) throw DemuxExcept(DemuxExcept::TOO_MANY_FILES); nfiles = count; for (int i = 0; i < nfiles; i++) { // filehandles[i] = fopen(filenames[i], "rb"); filehandles[i] = _open(filenames[i], _O_BINARY | _O_RDONLY); if (filehandles[i] == -1) { error = DemuxExcept::FILE_OPEN_ERROR; break; } // fseek(filehandles[i], 0, SEEK_END); _lseeki64(filehandles[i], 0, SEEK_END); filesizes[i] = _telli64(filehandles[i]); if (filesizes[i] == -1) { error = DemuxExcept::FILE_ACCESS_ERROR; break; } /* if (fgetpos(filehandles[i], &fpos) == 0) filesizes[i] = fpos; else error = DemuxExcept::FILE_ACCESS_ERROR; rewind(filehandles[i]); */ _lseeki64(filehandles[i], 0, SEEK_SET); } if (error != 0) { Close(); throw DemuxExcept(error); } start = 0; stop = 0; pos = -1; pos_bit = 0; end_of_stream = false; } void AsyncStream::Close() { for (int i = 0; i < nfiles; i++) { if (filehandles[i] != -1) _close(filehandles[i]); // fclose(filehandles[i]); filehandles[i] = 0; } nfiles = 0; } __int64 AsyncStream::Size() { __int64 size = 0; for (int i = 0; i < nfiles; i++) size += filesizes[i]; return size; } void AsyncStream::Seek(__int64 loc) { // fpos_t fpos; int i = 0; pos = loc - 1; pos_bit = 0; if (loc < start || loc > stop) { end_of_stream = false; start = loc; stop = loc; while (i < nfiles) { if (loc < filesizes[i]) break; loc -= filesizes[i++]; } if (i == nfiles) throw DemuxExcept(DemuxExcept::END_OF_STREAM); // fpos = loc; // fsetpos(filehandles[i++], &fpos); _lseeki64(filehandles[i++], loc, SEEK_SET); while (i < nfiles) _lseeki64(filehandles[i++], 0, SEEK_SET); // rewind(filehandles[i++]); } } unsigned long AsyncStream::GetBits(int nbits) { unsigned long bits = 0; while (nbits > 0) { if (pos_bit == 0) { pos++; if (pos == stop) { if (end_of_stream) throw DemuxExcept(DemuxExcept::END_OF_STREAM); if (ReadChunk() == 0) throw DemuxExcept(DemuxExcept::END_OF_STREAM); } pos_bit = 8; } if (pos_bit >= nbits) { // all bits present in current byte? bits = (bits << nbits) | ((bitbuffer[(int)pos & BUFFERMASK] >> (pos_bit - nbits)) & ((1L << nbits) - 1)); pos_bit -= nbits; return bits; } else { bits = (bits << pos_bit) | (bitbuffer[(int)pos & BUFFERMASK] & ((1L << pos_bit) - 1)); nbits -= pos_bit; pos_bit = 0; } } return bits; } unsigned long AsyncStream::GetBit() { if (pos_bit == 0) { pos++; if (pos == stop) { if (end_of_stream) throw DemuxExcept(DemuxExcept::END_OF_STREAM); if (ReadChunk() == 0) throw DemuxExcept(DemuxExcept::END_OF_STREAM); } pos_bit = 8; } pos_bit--; return (bitbuffer[(int)pos & BUFFERMASK] >> pos_bit) & 1L; } void AsyncStream::CopyBlock(unsigned char *dest, int nbytes) { int remainder = 0; if (nbytes == 0) return; if (((int)(pos + nbytes - 1) & BUFFERMASK) < ((int)pos & BUFFERMASK)) { remainder = BUFFERSIZE - ((int)pos & BUFFERMASK); memcpy(dest, &bitbuffer[(int)pos & BUFFERMASK], remainder); dest += remainder; nbytes -= remainder; } if (nbytes) memcpy(dest, &bitbuffer[(int)(pos + remainder) & BUFFERMASK], nbytes); } void AsyncStream::GetBytes(unsigned char *dest, int nbytes) { int bytes_left; pos_bit = 0; while (nbytes > 0) { if (++pos == stop) { if (end_of_stream) throw DemuxExcept(DemuxExcept::END_OF_STREAM); ReadChunk(); } bytes_left = (int)(stop - pos); if (bytes_left >= nbytes) { CopyBlock(dest, nbytes); pos += nbytes - 1; return; } CopyBlock(dest, bytes_left); dest += bytes_left; nbytes -= bytes_left; pos = stop - 1; } } void AsyncStream::FlushBytes(int nbytes) { int bytes_left; pos_bit = 0; while (nbytes > 0) { if (++pos == stop) { if (end_of_stream) throw DemuxExcept(DemuxExcept::END_OF_STREAM); ReadChunk(); } bytes_left = (int)(stop - pos); if (bytes_left >= nbytes) { pos += nbytes - 1; return; } nbytes -= bytes_left; pos = stop - 1; } } unsigned long AsyncStream::LookAhead(int nbits) { unsigned long bits; __int64 pos_save; int pos_bit_save; pos_save = pos; pos_bit_save = pos_bit; bits = GetBits(nbits); pos = pos_save; pos_bit = pos_bit_save; return bits; }