Changeset 898

Show
Ignore:
Timestamp:
05/24/08 13:43:22 (6 months ago)
Author:
gbooker
Message:

Better frame buffer interface. Less memory, better memory allocation mechanism, less memcpy on expansion

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/FFusionCodec.c

    r882 r898  
    252252static void DumpFrameDropStats(FFusionGlobals glob) 
    253253{ 
     254#ifdef DEBUG_BUILD 
    254255        static const char types[4] = {'?', 'I', 'P', 'B'}; 
     256#endif 
    255257        int i; 
    256258         
     
    260262         
    261263        for (i = 0; i < 4; i++) { 
     264#ifdef DEBUG_BUILD 
    262265                struct per_frame_decode_stats *f = &glob->stats.type[i]; 
     266#endif 
    263267                                 
    264268                Codecprintf(glob->fileLog, "%c\t| %d\t\t| %d\t\t| %d\t\t| %d/%f%%\t\t| %d/%f%%\n", types[i], f->begin_calls, f->decode_calls, f->draw_calls, 
     
    358362                // we allocate some space for copying the frame data since we need some padding at the end 
    359363                // for ffmpeg's optimized bitstream readers. Size doesn't really matter, it'll grow if need be 
    360                 FFusionDataSetup(&(glob->data), 256, 64*1024); 
     364                FFusionDataSetup(&(glob->data), 256, 1024*1024); 
    361365        FFusionRunUpdateCheck(); 
    362366    } 
     
    977981                        /* Reset context, safe marking in such a case */ 
    978982                        glob->begin.lastFrameType = FF_I_TYPE; 
    979                         glob->data.unparsedFrames.dataSize = 0
     983                        FFusionDataReadUnparsed(&(glob->data))
    980984                        glob->begin.lastPFrameData = NULL; 
    981985                        redisplayFirstFrame = 1; 
     
    10191023                                glob->packedType = PACKED_DELAY_BY_ONE_FRAME; 
    10201024                         
    1021                         if(FFusionCreateDataBuffer(&(glob->data), (uint8_t *)drp->codecData, parsedBufSize)) 
    1022                                 myDrp->frameData = FFusionDataAppend(&(glob->data), parsedBufSize, type); 
     1025                        myDrp->frameData = FFusionDataAppend(&(glob->data), (uint8_t *)drp->codecData, parsedBufSize, type); 
    10231026                        if(type != FF_I_TYPE) 
    10241027                                myDrp->frameData->prereqFrame = glob->begin.lastPFrameData; 
     
    10651068                                                glob->begin.lastPFrameData->nextFrame = myDrp->frameData; 
    10661069                                        glob->begin.lastPFrameData = myDrp->frameData; 
    1067                                         if(FFusionCreateDataBuffer(&(glob->data), buffer, parsedBufSize)) 
    1068                                                 myDrp->frameData = FFusionDataAppend(&(glob->data), parsedBufSize, type); 
     1070                                        myDrp->frameData = FFusionDataAppend(&(glob->data), buffer, parsedBufSize, type); 
    10691071                                        myDrp->frameData->prereqFrame = glob->begin.lastPFrameData; 
    10701072                                        buffer += parsedBufSize; 
     
    10741076                                        FFusionDataSetUnparsed(&(glob->data), buffer, bufferSize); 
    10751077                                else 
    1076                                         glob->data.unparsedFrames.dataSize = 0
     1078                                        FFusionDataReadUnparsed(&(glob->data))
    10771079                        } 
    10781080                        else 
    1079                                 glob->data.unparsedFrames.dataSize = 0
     1081                                FFusionDataReadUnparsed(&(glob->data))
    10801082                        myDrp->bufferSize = 0; 
    10811083                } 
     
    11691171#endif 
    11701172                        glob->decode.futureBuffer = NULL; 
    1171                 FFusionDataMarkRead(&(glob->data), myDrp->frameData); 
     1173                FFusionDataMarkRead(myDrp->frameData); 
    11721174                glob->decode.lastFrame = myDrp->frameNumber; 
    11731175                return err; 
     
    12001202                /* data is already set up properly for us */ 
    12011203                dataSize = myDrp->bufferSize; 
    1202                 FFusionCreateDataBuffer(&(glob->data), (uint8_t *)drp->codecData, dataSize); 
    1203                 dataPtr = glob->data.buffer; 
     1204                dataPtr = FFusionCreateEntireDataBuffer(&(glob->data), (uint8_t *)drp->codecData, dataSize); 
    12041205        } 
    12051206        ICMDataProcRecordPtr dataProc = drp->dataProcRecord.dataProc ? &drp->dataProcRecord : NULL; 
     
    12271228        if (myDrp->buffer) myDrp->buffer->returnedFrame = tempFrame; 
    12281229         
    1229         FFusionDataMarkRead(&(glob->data), frameData); 
     1230        FFusionDataMarkRead(frameData); 
    12301231         
    12311232        FFusionDebugPrint("%p DecodeBand decoded #%d.\n", glob, glob->decode.lastFrame); 
     
    13671368pascal ComponentResult FFusionCodecEndBand(FFusionGlobals glob, ImageSubCodecDecompressRecord *drp, OSErr result, long flags) 
    13681369{ 
     1370#ifdef DEBUG_BUILD 
    13691371        FFusionDecompressRecord *myDrp = (FFusionDecompressRecord *)drp->userDecompressRecord; 
     1372#endif 
    13701373        glob->stats.type[drp->frameType].end_calls++; 
    13711374        FFusionDebugPrint("%p EndBand #%d.\n", glob, myDrp->frameNumber); 
  • trunk/FrameBuffer.c

    r806 r898  
    1010#include "FrameBuffer.h" 
    1111#include "avcodec.h" 
     12#include <sys/param.h> 
    1213 
    1314void FFusionDataSetup(FFusionData *data, int dataSize, int bufferSize) 
    1415{ 
    15         data->read = 0; 
    16         data->write = 0; 
    17         data->frames = malloc(sizeof(FrameData *) * dataSize); 
     16        memset(data, 0, sizeof(FFusionData)); 
     17        int framesSize = sizeof(FrameData) * dataSize; 
     18        data->frames = malloc(framesSize); 
     19        memset(data->frames, 0, framesSize); 
    1820         
    1921        int i; 
    2022        for(i=0; i<dataSize; i++) 
    2123        { 
    22                 FrameData *fdata = malloc(sizeof(FrameData)); 
    23                 data->frames[i] = fdata; 
    24                 fdata->buffer = av_malloc(bufferSize); 
    25                 fdata->bufferSize = bufferSize; 
     24                FrameData *fdata = data->frames + i; 
     25                fdata->buffer = NULL; 
     26                fdata->data = data; 
    2627        } 
    27         data->size = dataSize; 
    28         data->buffer = av_malloc(bufferSize); 
    29         data->bufferSize = bufferSize
    30         data->startBufferSize = bufferSize; 
     28        data->frameSize = dataSize; 
     29 
     30        data->ringBuffer = av_malloc(bufferSize)
     31        data->ringSize = bufferSize; 
    3132} 
    3233 
    3334void FFusionDataFree(FFusionData *data) 
    3435{ 
    35         int i
    36         for(i=0; i<data->size; i++
     36        free(data->frames)
     37        if(data->previousData != NULL
    3738        { 
    38                 av_free(data->frames[i]->buffer); 
    39                 free(data->frames[i]); 
     39                FFusionDataFree(data->previousData); 
     40                free(data->previousData); 
    4041        } 
    41         free(data->frames); 
    42         av_free(data->buffer); 
    4342} 
    4443 
    45 int FFusionCreateDataBuffer(FFusionData *data, uint8_t *buffer, int bufferSize) 
     44static void expansion(FFusionData *data, int dataSize) 
    4645{ 
    47         data->buffer = av_fast_realloc(data->buffer, &data->bufferSize, bufferSize + FF_INPUT_BUFFER_PADDING_SIZE); 
    48         if (data->buffer) { 
    49                 uint8_t *dataPtr = data->buffer; 
     46        FFusionData *prev = malloc(sizeof(FFusionData)); 
     47        memcpy(prev, data, sizeof(FFusionData)); 
     48        int i; 
     49        for(i=0; i<data->frameSize; i++) 
     50                data->frames[i].data = prev; 
     51         
     52        int newRingSize = MAX(dataSize * 10, data->ringSize * 2); 
     53        FFusionDataSetup(data, data->frameSize * 2, newRingSize); 
     54        data->previousData = prev; 
     55
     56 
     57uint8_t *FFusionCreateEntireDataBuffer(FFusionData *data, uint8_t *buffer, int bufferSize) 
     58
     59        data->ringBuffer = av_fast_realloc(data->ringBuffer, &(data->ringSize), bufferSize + FF_INPUT_BUFFER_PADDING_SIZE); 
     60        if (data->ringBuffer) { 
     61                uint8_t *dataPtr = data->ringBuffer; 
    5062                memcpy(dataPtr, buffer, bufferSize); 
    5163                memset(dataPtr + bufferSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); 
    5264        } 
    53         return data->buffer != NULL
     65        return data->ringBuffer
    5466} 
    5567 
    56 FrameData *FFusionDataAppend(FFusionData *data, int dataSize, int type) 
     68static uint8_t *createBuffer(FFusionData *data, int dataSize) 
    5769{ 
    58         if((data->write + 1) % data->size == data->read) 
     70        if(data->ringWrite >= data->ringRead) 
    5971        { 
    60                 int newSize = data->size * 2; 
    61                 FrameData * *newData = malloc(sizeof(FrameData *) * newSize); 
    62                 memcpy(newData, data->frames + data->read, (data->size - data->read) * sizeof(FrameData)); 
    63                 if(data->read != 0) 
    64                         memcpy(newData + (data->size - data->read), data->frames, data->read * sizeof(FrameData)); 
    65                  
    66                 int i; 
    67                 for(i=data->size; i<newSize; i++) 
     72                //Write is after read 
     73                if(data->ringWrite + dataSize + FF_INPUT_BUFFER_PADDING_SIZE < data->ringSize) 
    6874                { 
    69                         FrameData *newFrame = malloc(sizeof(FrameData)); 
    70                         newData[i] = newFrame; 
    71                         newFrame->buffer = av_malloc(data->startBufferSize)
    72                         newFrame->bufferSize = data->startBufferSize
     75                        //Found at end 
     76                        int offset = data->ringWrite; 
     77                        data->ringWrite = offset + dataSize
     78                        return data->ringBuffer + offset
    7379                } 
    74                 data->read = 0; 
    75                 data->write = data->size; 
    76                 data->size = newSize; 
    77                 free(data->frames); 
    78                 data->frames = newData; 
     80                else 
     81                        //Can't fit at end, loop 
     82                        data->ringWrite = 0; 
     83        } 
     84        if(data->ringWrite + dataSize + FF_INPUT_BUFFER_PADDING_SIZE < data->ringRead) 
     85        { 
     86                //Found at write 
     87                int offset = data->ringWrite; 
     88                data->ringWrite = offset + dataSize; 
     89                return data->ringBuffer + offset; 
     90        } 
     91        else 
     92        { 
     93                expansion(data, dataSize); 
     94                return data->ringBuffer; 
     95        } 
     96
     97 
     98static uint8_t *insertIntoBuffer(FFusionData *data, uint8_t *buffer, int dataSize) 
     99
     100        uint8_t *ret = createBuffer(data, dataSize); 
     101        memcpy(ret, buffer, dataSize); 
     102        memset(ret + dataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); 
     103        return ret; 
     104
     105 
     106FrameData *FFusionDataAppend(FFusionData *data, uint8_t *buffer, int dataSize, int type) 
     107
     108        if((data->frameWrite + 1) % data->frameSize == data->frameRead) 
     109        { 
     110                expansion(data, dataSize); 
    79111        } 
    80112         
    81         FrameData *dest = data->frames[data->write]; 
    82         uint8_t *tbuff = dest->buffer; 
    83         dest->buffer = data->buffer; 
    84         data->buffer = tbuff; 
     113        FrameData *dest = data->frames + data->frameWrite; 
    85114         
    86         unsigned int tsize = dest->bufferSize; 
    87         dest->bufferSize = data->bufferSize; 
    88         data->bufferSize = tsize; 
    89          
     115        uint8_t *saveBuffer = insertIntoBuffer(data, buffer, dataSize); 
     116        dest->buffer = saveBuffer; 
    90117        dest->dataSize = dataSize; 
    91118        dest->type = type; 
     
    94121        dest->nextFrame = NULL; 
    95122         
    96         data->write = (data->write + 1) % data->size; 
     123        data->frameWrite = (data->frameWrite + 1) % data->frameSize; 
    97124        return dest; 
    98125} 
     
    102129        FrameData *unparsed = &(data->unparsedFrames); 
    103130         
    104         unparsed->buffer = av_fast_realloc(unparsed->buffer, &unparsed->bufferSize, bufferSize); 
     131        unparsed->buffer = insertIntoBuffer(data, buffer, bufferSize); 
    105132        if (unparsed->buffer) { 
    106133                memcpy(unparsed->buffer, buffer, bufferSize); 
    107134                unparsed->dataSize = bufferSize; 
    108135        } 
     136} 
     137 
     138void FFusionDataReadUnparsed(FFusionData *data) 
     139{ 
     140        data->ringWrite -= data->unparsedFrames.dataSize; 
     141        data->unparsedFrames.dataSize = 0; 
    109142} 
    110143 
     
    117150} 
    118151 
    119 void FFusionDataMarkRead(FFusionData *data, FrameData *toData) 
     152void FFusionDataMarkRead(FrameData *toData) 
    120153{ 
    121154        if(toData == NULL) 
     
    125158                return; 
    126159         
    127         int i; 
    128         for(i=data->read; i!=data->write; i = (i + 1) % data->size) 
     160        FFusionData *data = toData->data; 
     161        data->frameRead = toData - data->frames + 1; 
     162        data->ringRead = toData->buffer + toData->dataSize - data->ringBuffer; 
     163        if(data->previousData != NULL) 
    129164        { 
    130                 if(data->frames[i] == toData) 
    131                 { 
    132                         data->read = (i + 1) % data->size; 
    133                         break; 
    134                 }                
     165                FFusionDataFree(data->previousData); 
     166                data->previousData = NULL; 
    135167        } 
    136168} 
     
    139171{ 
    140172        int i; 
    141         for(i=data->read; i!=data->write; i = (i + 1) % data->size) 
     173        for(i=data->frameRead; i!=data->frameWrite; i = (i + 1) % data->frameSize) 
    142174        { 
    143                 if(data->frames[i]->frameNumber == frameNumber) 
    144                         return data->frames[i]
     175                if(data->frames[i].frameNumber == frameNumber) 
     176                        return data->frames + i
    145177        } 
     178        if(data->previousData != NULL) 
     179                return FFusionDataFind(data->previousData, frameNumber); 
     180         
    146181        return NULL; 
    147182} 
  • trunk/FrameBuffer.h

    r641 r898  
    99 
    1010typedef struct FrameData_s FrameData; 
     11typedef struct FFusionData_s FFusionData; 
     12 
    1113struct FrameData_s 
    1214{ 
     
    2022        FrameData               *prereqFrame;  /* This is the frame's data which must be decoded to fully display this frame */ 
    2123        FrameData               *nextFrame; /* This is the next frame to decode if this one is already decoded.  This is for predictive decoding */ 
    22         /* private */ 
    23         unsigned int    bufferSize; 
     24        FFusionData             *data; 
    2425}; 
    2526 
    26 typedef struct 
     27typedef struct DataRingBuffer_s { 
     28} DataRingBuffer; 
     29 
     30struct FFusionData_s 
    2731{ 
    28         uint8_t                 *buffer; 
    29         unsigned int    bufferSize; 
    3032        FrameData               unparsedFrames; 
    3133        /* private */ 
    32         unsigned int    size; 
    33         unsigned int    read; 
    34         unsigned int    write; 
    35         unsigned int    startBufferSize; 
    36         FrameData               * *frames; 
    37 } FFusionData; 
     34        unsigned int    frameSize; 
     35        unsigned int    frameRead; 
     36        unsigned int    frameWrite; 
     37        FrameData               *frames; 
     38        unsigned int    ringSize; 
     39        unsigned int    ringRead; 
     40        unsigned int    ringWrite; 
     41        uint8_t                 *ringBuffer; 
     42        FFusionData             *previousData; 
     43}; 
    3844 
    3945void FFusionDataSetup(FFusionData *data, int dataSize, int bufferSize); 
    4046void FFusionDataFree(FFusionData *data); 
    41 int FFusionCreateDataBuffer(FFusionData *data, uint8_t *buffer, int bufferSize); 
    42 FrameData *FFusionDataAppend(FFusionData *data, int dataSize, int type); 
     47uint8_t *FFusionCreateEntireDataBuffer(FFusionData *data, uint8_t *buffer, int bufferSize); 
     48FrameData *FFusionDataAppend(FFusionData *data, uint8_t *buffer, int dataSize, int type); 
    4349void FFusionDataSetUnparsed(FFusionData *data, uint8_t *buffer, int bufferSize); 
    44 void FFusionDataMarkRead(FFusionData *data, FrameData *toData); 
     50void FFusionDataMarkRead(FrameData *toData); 
    4551FrameData *FFusionDataFind(FFusionData *data, int frameNumber); 
    4652