4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "byteorder.h"
25 #include "colormodels.h"
29 #include "overlayframe.h"
35 FileBase::FileBase(Asset *asset, File *file)
39 internal_byte_order = get_byte_order();
42 overlayer = new OverlayFrame;
48 if(row_pointers_in) delete [] row_pointers_in;
49 if(row_pointers_out) delete [] row_pointers_out;
50 if(float_buffer) delete [] float_buffer;
55 int FileBase::close_file()
57 if(row_pointers_in) delete [] row_pointers_in;
58 if(row_pointers_out) delete [] row_pointers_out;
59 if(float_buffer) delete [] float_buffer;
64 for(int i = 0; i < history_channels; i++)
65 delete [] pcm_history[i];
66 delete [] pcm_history;
76 void FileBase::update_pcm_history(int64_t len)
83 history_channels = asset->channels;
84 pcm_history = new double*[history_channels];
85 for(int i = 0; i < history_channels; i++)
86 pcm_history[i] = new double[HISTORY_MAX];
89 history_allocated = HISTORY_MAX;
93 //printf("FileBase::update_pcm_history current_sample=" _LD " history_start=" _LD " history_size=" _LD "\n",
94 //file->current_sample,
97 // Restart history. Don't bother shifting history back.
98 if(file->current_sample < history_start ||
99 file->current_sample > history_start + history_size)
102 history_start = file->current_sample;
103 decode_start = file->current_sample;
107 // Shift history forward to make room for new samples
108 if(file->current_sample > history_start + HISTORY_MAX)
110 int diff = file->current_sample - (history_start + HISTORY_MAX);
111 for(int i = 0; i < asset->channels; i++)
113 double *temp = pcm_history[i];
114 memcpy(temp, temp + diff, (history_size - diff) * sizeof(double));
117 history_start += diff;
118 history_size -= diff;
121 decode_start = history_start + history_size;
122 decode_len = file->current_sample + len - (history_start + history_size);
125 // Starting somewhere in the buffer
127 decode_start = history_start + history_size;
128 decode_len = file->current_sample + len - (history_start + history_size);
132 void FileBase::append_history(float **new_data, int len)
134 allocate_history(len);
136 for(int i = 0; i < history_channels; i++)
138 double *output = pcm_history[i] + history_size;
139 float *input = new_data[i];
140 for(int j = 0; j < len; j++)
141 *output++ = *input++;
148 void FileBase::append_history(short *new_data, int len)
150 allocate_history(len);
152 for(int i = 0; i < history_channels; i++)
154 double *output = pcm_history[i] + history_size;
155 short *input = new_data + i;
156 for(int j = 0; j < len; j++)
158 *output++ = (double)*input / 32768;
159 input += history_channels;
167 void FileBase::read_history(double *dst,
168 int64_t start_sample,
172 if(start_sample - history_start + len > history_size)
173 len = history_size - (start_sample - history_start);
174 //printf("FileBase::read_history start_sample=" _LD " history_start=" _LD " history_size=" _LD " len=" _LD "\n",
175 //start_sample, history_start, history_size, len);
176 double *input = pcm_history[channel] + start_sample - history_start;
177 for(int i = 0; i < len; i++)
183 void FileBase::allocate_history(int len)
185 if(history_size + len > history_allocated)
187 double **temp = new double*[history_channels];
189 for(int i = 0; i < history_channels; i++)
191 temp[i] = new double[history_size + len];
192 memcpy(temp[i], pcm_history[i], history_size * sizeof(double));
193 delete [] pcm_history[i];
196 delete [] pcm_history;
198 history_allocated = history_size + len;
202 int64_t FileBase::get_history_sample()
204 return history_start + history_size;
207 int FileBase::set_dither()
213 int FileBase::reset_parameters()
218 row_pointers_out = 0;
219 prev_buffer_position = -1;
220 prev_frame_position = -1;
225 ulawtofloat_table = 0;
226 floattoulaw_table = 0;
231 history_allocated = 0;
232 history_channels = 0;
235 delete_ulaw_tables();
236 reset_parameters_derived();
240 int FileBase::get_mode(char *mode, int rd, int wr)
242 if(rd && !wr) sprintf(mode, "rb");
243 else if(!rd && wr) sprintf(mode, "wb");
246 FILE *stream = fopen(asset->path, "rb");
251 sprintf(mode, exists ? "rb+" : "wb+");
257 // ======================================= audio codecs
259 int FileBase::get_video_buffer(unsigned char **buffer, int depth)
261 // get a raw video buffer for writing or compression by a library
264 // Video compression is entirely done in the library.
265 int64_t bytes = asset->width * asset->height * depth;
266 *buffer = new unsigned char[bytes];
271 int FileBase::get_row_pointers(unsigned char *buffer, unsigned char ***pointers, int depth)
273 // This might be fooled if a new VFrame is created at the same address with a different height.
274 if(*pointers && (*pointers)[0] != &buffer[0])
282 *pointers = new unsigned char*[asset->height];
283 for(int i = 0; i < asset->height; i++)
285 (*pointers)[i] = &buffer[i * asset->width * depth / 8];
291 int FileBase::match4(const char *in, const char *out)
293 return in[0] == out[0] && in[1] == out[1] &&
294 in[2] == out[2] && in[3] == out[3] ? 1 : 0;
297 int FileBase::search_render_strategies(ArrayList<int>* render_strategies, int render_strategy)
299 for(int i = 0; i < render_strategies->total; i++)
300 if(render_strategies->values[i] == render_strategy) return 1;
305 int64_t FileBase::base_memory_usage()
307 //printf("FileBase::base_memory_usage %d\n", __LINE__);
308 return !pcm_history ? 0 :
309 history_allocated * history_channels * sizeof(double);