source: trunk/FrameBuffer.c @ 1472

Revision 1472, 5.9 KB checked in by astrange, 3 years ago (diff)

Xcode project cleanup and Lion SDK updates

  • Update ACPublic/PublicUtility to Lion version.

API changed in various ways. Rather than copy the files
I've just included them from the Developer directory,
which may turn out to be a bad idea.
Removed use of ACSimpleCodec along the way.

  • Stop including ffmpeg/, which will improve compilation speed.
  • Some other changes to better use Xcode 4 schemes
Line 
1/*
2 * FrameBuffer.c
3 * Created by Graham Booker on 1/30/07.
4 *
5 * This file is part of Perian.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <libavcodec/avcodec.h>
23#include <sys/param.h>
24
25#include "FrameBuffer.h"
26#include "CommonUtils.h"
27
28void FFusionDataSetup(FFusionData *data, int dataSize, int bufferSize)
29{
30        memset(data, 0, sizeof(FFusionData));
31        int framesSize = sizeof(FrameData) * dataSize;
32        data->frames = malloc(framesSize);
33        memset(data->frames, 0, framesSize);
34       
35        int i;
36        for(i=0; i<dataSize; i++)
37        {
38                FrameData *fdata = data->frames + i;
39                fdata->buffer = NULL;
40                fdata->data = data;
41        }
42        data->frameSize = dataSize;
43
44        data->ringBuffer = av_malloc(bufferSize);
45        data->ringSize = bufferSize;
46}
47
48void FFusionDataFree(FFusionData *data)
49{
50        free(data->frames);
51        if(data->previousData != NULL)
52        {
53                FFusionDataFree(data->previousData);
54                free(data->previousData);
55        }
56        av_free(data->ringBuffer);
57}
58
59//Expands both the frame array and the ring buffer.
60//Old data is kept in the previousData pointer to be dealloced when done
61static void expansion(FFusionData *data, int dataSize)
62{
63        //Create the prev structure to hold all existing frames
64        FFusionData *prev = malloc(sizeof(FFusionData));
65        //Move all frames to prev
66        memcpy(prev, data, sizeof(FFusionData));
67        int i;
68        for(i=0; i<data->frameSize; i++)
69                data->frames[i].data = prev;
70       
71        //Create new data
72        int newRingSize = MAX(dataSize * 10, data->ringSize * 2);
73        FFusionDataSetup(data, data->frameSize * 2, newRingSize);
74        //Preserve pointer to old data
75        data->previousData = prev;
76}
77
78uint8_t *FFusionCreateEntireDataBuffer(FFusionData *data, uint8_t *buffer, int bufferSize)
79{
80        data->ringBuffer = fast_realloc_with_padding(data->ringBuffer, &data->ringSize, bufferSize);
81        if (data->ringBuffer) {
82                memcpy(data->ringBuffer, buffer, bufferSize);
83        }
84        return data->ringBuffer;
85}
86
87//Find dataSize bytes in ringbuffer, expand if none available
88static uint8_t *createBuffer(FFusionData *data, int dataSize)
89{
90        if(data->ringWrite >= data->ringRead)
91        {
92                //Write is after read
93                if(data->ringWrite + dataSize + FF_INPUT_BUFFER_PADDING_SIZE < data->ringSize)
94                {
95                        //Found at end
96                        int offset = data->ringWrite;
97                        data->ringWrite = offset + dataSize;
98                        return data->ringBuffer + offset;
99                }
100                else
101                        //Can't fit at end, loop
102                        data->ringWrite = 0;
103        }
104        if(data->ringWrite + dataSize + FF_INPUT_BUFFER_PADDING_SIZE < data->ringRead)
105        {
106                //Found at write
107                int offset = data->ringWrite;
108                data->ringWrite = offset + dataSize;
109                return data->ringBuffer + offset;
110        }
111        else
112        {
113                expansion(data, dataSize);
114                data->ringWrite = dataSize;
115                return data->ringBuffer;
116        }
117}
118
119//Insert buffer into ring buffer
120static uint8_t *insertIntoBuffer(FFusionData *data, uint8_t *buffer, int dataSize)
121{
122        uint8_t *ret = createBuffer(data, dataSize);
123        memcpy(ret, buffer, dataSize);
124        memset(ret + dataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
125        return ret;
126}
127
128FrameData *FFusionDataAppend(FFusionData *data, uint8_t *buffer, int dataSize, int type)
129{
130        //Find an available frame
131        if((data->frameWrite + 1) % data->frameSize == data->frameRead)
132        {
133                expansion(data, dataSize);
134        }
135       
136        FrameData *dest = data->frames + data->frameWrite;
137       
138        if(data->unparsedFrames.buffer == buffer)
139        {               
140                //This was an unparsed frame, don't memcpy; it's already in the correct place.
141                dest->buffer = buffer;
142                data->unparsedFrames.buffer += dataSize;
143                data->unparsedFrames.dataSize -= dataSize;
144        }
145        else
146        {
147                uint8_t *saveBuffer = insertIntoBuffer(data, buffer, dataSize);
148                dest->buffer = saveBuffer;
149        }
150        dest->dataSize = dataSize;
151        dest->type = type;
152        dest->prereqFrame = NULL;
153        dest->decoded = FALSE;
154        dest->nextFrame = NULL;
155       
156        data->frameWrite = (data->frameWrite + 1) % data->frameSize;
157        return dest;
158}
159
160void FFusionDataSetUnparsed(FFusionData *data, uint8_t *buffer, int bufferSize)
161{
162        FrameData *unparsed = &(data->unparsedFrames);
163       
164        if(unparsed->buffer == buffer)
165        {
166                //This part was already unparsed; don't memcpy again
167                unparsed->dataSize = bufferSize;
168        }
169        else
170        {
171                unparsed->buffer = insertIntoBuffer(data, buffer, bufferSize);
172                if (unparsed->buffer) {
173                        unparsed->dataSize = bufferSize;
174                }               
175        }
176}
177
178//Seems to be unused
179void FFusionDataReadUnparsed(FFusionData *data)
180{
181        data->ringWrite -= data->unparsedFrames.dataSize;
182        data->unparsedFrames.dataSize = 0;
183}
184
185FrameData *FrameDataCheckPrereq(FrameData * toData)
186{
187        FrameData *prereq = toData->prereqFrame;
188        if(prereq && prereq->decoded)
189                return NULL;
190        return prereq;
191}
192
193void FFusionDataMarkRead(FrameData *toData)
194{
195        if(toData == NULL)
196                return;
197       
198        if(toData->prereqFrame != NULL)
199                return;
200       
201        FFusionData *data = toData->data;
202        data->frameRead = toData - data->frames + 1;
203        data->ringRead = toData->buffer + toData->dataSize - data->ringBuffer;
204        if(data->previousData != NULL)
205        {
206                //If there's previous data, free it since we are now done with it
207                FFusionDataFree(data->previousData);
208                free(data->previousData);
209                data->previousData = NULL;
210        }
211}
212
213FrameData *FFusionDataFind(FFusionData *data, int frameNumber)
214{
215        int i;
216        for(i=data->frameRead; i!=data->frameWrite; i = (i + 1) % data->frameSize)
217        {
218                if(data->frames[i].frameNumber == frameNumber)
219                        return data->frames + i;
220        }
221        if(data->previousData != NULL)
222                //Check previous data as well
223                return FFusionDataFind(data->previousData, frameNumber);
224       
225        return NULL;
226}
Note: See TracBrowser for help on using the repository browser.