Changeset 395

Show
Ignore:
Timestamp:
03/30/07 01:44:02 (2 years ago)
Author:
dconrad
Message:

Use simple buffered read for Matroska. 20-30% faster import.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/DataHandlerCallback.cpp

    r322 r395  
    4343} 
    4444 
     45 
     46DataHBuffer::DataHBuffer(size_t bufferSize) 
     47{ 
     48        buffer = new uint8_t[bufferSize]; 
     49        allocatedSize = bufferSize; 
     50        fileOffset = -1; 
     51        dataSize = 0; 
     52} 
     53 
     54DataHBuffer::~DataHBuffer() 
     55{ 
     56        if (buffer) 
     57                delete[] buffer; 
     58} 
     59 
     60void DataHBuffer::Realloc(size_t bufferSize) 
     61{ 
     62        if (buffer) 
     63                delete[] buffer; 
     64         
     65        buffer = new uint8_t[bufferSize]; 
     66        allocatedSize = bufferSize; 
     67        fileOffset = -1; 
     68        dataSize = 0; 
     69} 
     70 
     71bool DataHBuffer::ContainsOffset(uint64_t offset) 
     72{ 
     73        return offset >= fileOffset && offset < fileOffset + dataSize; 
     74} 
     75 
     76uint8_t * DataHBuffer::GetBuffer(uint64_t offset, size_t size) 
     77{ 
     78        if (size > allocatedSize) 
     79                Realloc(size); 
     80         
     81        fileOffset = offset; 
     82        dataSize = size; 
     83        return buffer; 
     84} 
     85 
     86size_t DataHBuffer::Read(uint64_t offset, size_t size, uint8_t *store) 
     87{ 
     88        if (!ContainsOffset(offset)) 
     89                return 0; 
     90         
     91        uint8_t *dataStart = buffer + (offset - fileOffset); 
     92        size_t amountToRead = MIN(fileOffset + dataSize - offset, size); 
     93        memcpy(store, dataStart, amountToRead); 
     94        return amountToRead; 
     95} 
     96 
     97 
    4598DataHandlerCallback::DataHandlerCallback(ComponentInstance dataHandler, const open_mode aMode) 
    4699{        
    47         closeHandler = false; 
    48         supportsWideOffsets = true; 
    49         this->dataHandler = NULL; 
    50         mCurrentPosition = 0; 
    51         filesize = 0; 
    52         this->aMode = aMode; 
     100        Initialize(aMode); 
    53101         
    54102        switch (aMode) 
     
    71119{ 
    72120    ComponentResult err = noErr; 
    73     Component dataHComponent = NULL; 
    74          
    75         closeHandler = true; 
    76         supportsWideOffsets = true; 
    77         dataHComponent = NULL; 
    78         mCurrentPosition = 0; 
    79         filesize = 0; 
    80         this->aMode = aMode; 
     121        Component dataHComponent = NULL; 
     122         
     123        Initialize(aMode); 
    81124         
    82125        if (aMode == MODE_READ) 
     
    111154        } 
    112155         
     156        closeHandler = true; 
     157         
    113158        // figure out if we support wide offesets 
    114159        getFileSize(); 
    115160} 
    116161 
     162void DataHandlerCallback::Initialize(const open_mode aMode) 
     163{ 
     164        closeHandler = false; 
     165        supportsWideOffsets = true; 
     166        this->dataHandler = NULL; 
     167        mCurrentPosition = 0; 
     168        filesize = 0; 
     169        this->aMode = aMode; 
     170} 
    117171 
    118172DataHandlerCallback::~DataHandlerCallback() throw() 
     
    121175} 
    122176 
    123  
    124  
    125 uint32 DataHandlerCallback::read(void *Buffer, size_t Size) 
     177uint32 DataHandlerCallback::read(void *buffer, size_t size) 
    126178{ 
    127179        ComponentResult err = noErr; 
    128          
    129     if (Size < 1 || mCurrentPosition > filesize) 
     180        size_t amountRead = 0; 
     181        uint64_t oldPos = mCurrentPosition; 
     182        uint8_t *internalBuffer, *myBuffer = (uint8_t *)buffer; 
     183         
     184    if (size < 1 || mCurrentPosition > filesize) 
    130185        return 0; 
    131186         
    132         if (mCurrentPosition + Size > filesize) 
    133                 Size = filesize - mCurrentPosition; 
    134          
    135         if (supportsWideOffsets) { 
    136                 wide wideOffset = SInt64ToWide(mCurrentPosition); 
    137                  
    138                 err = DataHScheduleData64(dataHandler, (Ptr)Buffer, &wideOffset, Size, 0, NULL, NULL); 
    139         } else { 
    140                 err = DataHScheduleData(dataHandler, (Ptr)Buffer, mCurrentPosition, Size, 0, NULL, NULL); 
    141         } 
    142          
    143         if (err) { 
    144                 throw CRTError("Error reading data", err); 
    145         } 
    146         mCurrentPosition += Size; 
    147          
    148         // does QuickTime tell us how much it's read? 
    149         return Size; 
    150 
    151  
    152 void DataHandlerCallback::setFilePointer(int64 Offset, LIBEBML_NAMESPACE::seek_mode Mode) 
     187        if (mCurrentPosition + size > filesize) 
     188                size = filesize - mCurrentPosition; 
     189         
     190        while (size > 0) { 
     191                if (dataBuffer.ContainsOffset(mCurrentPosition)) { 
     192                        amountRead = dataBuffer.Read(mCurrentPosition, size, myBuffer); 
     193                        myBuffer += amountRead; 
     194                        mCurrentPosition += amountRead; 
     195                        size -= amountRead; 
     196                } 
     197                 
     198                if (size <= 0) 
     199                        break; 
     200                 
     201                internalBuffer = dataBuffer.GetBuffer(mCurrentPosition, READ_SIZE); 
     202                 
     203                if (supportsWideOffsets) { 
     204                        wide wideOffset = SInt64ToWide(mCurrentPosition); 
     205                         
     206                        err = DataHScheduleData64(dataHandler, (Ptr)internalBuffer, &wideOffset,  
     207                                                                          READ_SIZE, 0, NULL, NULL); 
     208                } else { 
     209                        err = DataHScheduleData(dataHandler, (Ptr)internalBuffer, mCurrentPosition,  
     210                                                                        READ_SIZE, 0, NULL, NULL); 
     211                } 
     212         
     213                if (err) { 
     214                        throw CRTError("Error reading data", err); 
     215                } 
     216        } 
     217         
     218        return mCurrentPosition - oldPos; 
     219
     220 
     221void DataHandlerCallback::setFilePointer(int64 Offset, seek_mode Mode) 
    153222{ 
    154223        switch ( Mode ) 
  • trunk/DataHandlerCallback.h

    r242 r395  
    3131#include <stdexcept> 
    3232#include <cerrno> 
     33#include <sys/param.h> 
    3334 
    34        // ------------------------------------------------ 
     35using namespace std; 
     36using namespace libebml; 
     37 
     38#define READ_SIZE 32*1024 
    3539 
    3640class CRTError:public std::runtime_error 
     
    4852}; 
    4953 
     54class DataHBuffer { 
     55private: 
     56        uint8_t *buffer; 
     57        size_t allocatedSize; 
     58        int64_t fileOffset; 
     59        size_t dataSize; 
     60         
     61        // this clears the buffer 
     62        void Realloc(size_t bufferSize); 
     63         
     64public: 
     65        DataHBuffer(size_t bufferSize = READ_SIZE); 
     66         
     67        ~DataHBuffer(); 
     68         
     69        bool ContainsOffset(uint64_t offset); 
     70         
     71        // this returns a pointer to a buffer at least as big as size, and saves 
     72        // the given offset and size of data that will be stored 
     73        uint8_t * GetBuffer(uint64_t offset, size_t size); 
     74         
     75        // this copies as much data from the buffer as possible from the given file offset, 
     76        // returning the number of bytes actually copied. 
     77        size_t Read(uint64_t offset, size_t size, uint8_t *store); 
     78}; 
    5079 
    5180// QuickTime Data Handler callback for libmatroska 
    52 class DataHandlerCallback:public LIBEBML_NAMESPACE::IOCallback 
     81class DataHandlerCallback:public IOCallback 
    5382{ 
    5483private: 
     
    5988        open_mode aMode; 
    6089        SInt64 filesize; 
     90        DataHBuffer dataBuffer; 
     91         
     92        void Initialize(const open_mode aMode); 
    6193     
    6294public: 
    63         DataHandlerCallback::DataHandlerCallback(ComponentInstance dataHandler, const open_mode aMode); 
    64     DataHandlerCallback::DataHandlerCallback(Handle dataRef, OSType dataRefType, const open_mode aMode); 
     95        DataHandlerCallback(ComponentInstance dataHandler, const open_mode aMode); 
     96       DataHandlerCallback(Handle dataRef, OSType dataRefType, const open_mode aMode); 
    6597        virtual ~DataHandlerCallback() throw(); 
    6698     
     
    70102        // or SEEK_END. The callback should return true(1) if the seek operation succeeded 
    71103        // or false (0), when the seek fails. 
    72         virtual void setFilePointer(int64 Offset, LIBEBML_NAMESPACE::seek_mode Mode=LIBEBML_NAMESPACE::seek_beginning); 
     104        virtual void setFilePointer(int64 Offset, seek_mode Mode=seek_beginning); 
    73105     
    74106        // This callback just works like its read pendant. It returns the number of bytes written.