Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / filebase.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "asset.h"
23 #include "assets.h"
24 #include "byteorder.h"
25 #include "bccmodels.h"
26 #include "file.h"
27 #include "filebase.h"
28 #include "overlayframe.h"
29 #include "sizes.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 FileBase::FileBase(Asset *asset, File *file)
35 {
36         this->file = file;
37         this->asset = asset;
38         internal_byte_order = get_byte_order();
39         reset_parameters();
40         overlayer = new OverlayFrame;
41 }
42
43 FileBase::~FileBase()
44 {
45         close_file();
46         if(row_pointers_in) delete [] row_pointers_in;
47         if(row_pointers_out) delete [] row_pointers_out;
48         if(float_buffer) delete [] float_buffer;
49         delete overlayer;
50 }
51
52 int FileBase::close_file()
53 {
54         if(row_pointers_in) delete [] row_pointers_in;
55         if(row_pointers_out) delete [] row_pointers_out;
56         if(float_buffer) delete [] float_buffer;
57
58
59         if(pcm_history)
60         {
61                 for(int i = 0; i < history_channels; i++)
62                         delete [] pcm_history[i];
63                 delete [] pcm_history;
64         }
65
66
67         close_file_derived();
68         reset_parameters();
69         return 0;
70 }
71
72 void FileBase::update_pcm_history(int64_t len)
73 {
74         decode_start = 0;
75         decode_len = 0;
76
77         if(!pcm_history)
78         {
79                 history_channels = asset->channels;
80                 pcm_history = new double*[history_channels];
81                 for(int i = 0; i < history_channels; i++)
82                         pcm_history[i] = new double[HISTORY_MAX];
83                 history_start = 0;
84                 history_size = 0;
85                 history_allocated = HISTORY_MAX;
86         }
87
88
89 //printf("FileBase::update_pcm_history current_sample=%jd history_start=%jd history_size=%jd\n",
90 //file->current_sample,
91 //history_start,
92 //history_size);
93 // Restart history.  Don't bother shifting history back.
94         if(file->current_sample < history_start ||
95                 file->current_sample > history_start + history_size)
96         {
97                 history_size = 0;
98                 history_start = file->current_sample;
99                 decode_start = file->current_sample;
100                 decode_len = len;
101         }
102         else
103 // Shift history forward to make room for new samples
104         if(file->current_sample > history_start + HISTORY_MAX)
105         {
106                 int diff = file->current_sample - (history_start + HISTORY_MAX);
107                 for(int i = 0; i < asset->channels; i++)
108                 {
109                         double *temp = pcm_history[i];
110                         memcpy(temp, temp + diff, (history_size - diff) * sizeof(double));
111                 }
112
113                 history_start += diff;
114                 history_size -= diff;
115
116 // Decode more data
117                 decode_start = history_start + history_size;
118                 decode_len = file->current_sample + len - (history_start + history_size);
119         }
120         else
121 // Starting somewhere in the buffer
122         {
123                 decode_start = history_start + history_size;
124                 decode_len = file->current_sample + len - (history_start + history_size);
125         }
126 }
127
128 void FileBase::append_history(float **new_data, int len)
129 {
130         allocate_history(len);
131
132         for(int i = 0; i < history_channels; i++)
133         {
134                 double *output = pcm_history[i] + history_size;
135                 float *input = new_data[i];
136                 for(int j = 0; j < len; j++)
137                         *output++ = *input++;
138         }
139
140         history_size += len;
141         decode_end += len;
142 }
143
144 void FileBase::append_history(short *new_data, int len)
145 {
146         allocate_history(len);
147
148         for(int i = 0; i < history_channels; i++)
149         {
150                 double *output = pcm_history[i] + history_size;
151                 short *input = new_data + i;
152                 for(int j = 0; j < len; j++)
153                 {
154                         *output++ = (double)*input / 32768;
155                         input += history_channels;
156                 }
157         }
158
159         history_size += len;
160         decode_end += len;
161 }
162
163 void FileBase::read_history(double *dst,
164         int64_t start_sample,
165         int channel,
166         int64_t len)
167 {
168         if(start_sample - history_start + len > history_size)
169                 len = history_size - (start_sample - history_start);
170 //printf("FileBase::read_history start_sample=%jd history_start=%jd history_size=%jd len=%jd\n",
171 //start_sample, history_start, history_size, len);
172         double *input = pcm_history[channel] + start_sample - history_start;
173         for(int i = 0; i < len; i++)
174         {
175                 *dst++ = *input++;
176         }
177 }
178
179 void FileBase::allocate_history(int len)
180 {
181         if(history_size + len > history_allocated)
182         {
183                 double **temp = new double*[history_channels];
184
185                 for(int i = 0; i < history_channels; i++)
186                 {
187                         temp[i] = new double[history_size + len];
188                         memcpy(temp[i], pcm_history[i], history_size * sizeof(double));
189                         delete [] pcm_history[i];
190                 }
191
192                 delete [] pcm_history;
193                 pcm_history = temp;
194                 history_allocated = history_size + len;
195         }
196 }
197
198 int64_t FileBase::get_history_sample()
199 {
200         return history_start + history_size;
201 }
202
203 int FileBase::set_dither()
204 {
205         dither = 1;
206         return 0;
207 }
208
209 void FileBase::reset_parameters()
210 {
211         dither = 0;
212         float_buffer = 0;
213         row_pointers_in = 0;
214         row_pointers_out = 0;
215         prev_buffer_position = -1;
216         prev_frame_position = -1;
217         prev_len = 0;
218         prev_bytes = 0;
219         prev_track = -1;
220         prev_layer = -1;
221         ulawtofloat_table = 0;
222         floattoulaw_table = 0;
223         rd = wr = 0;
224         pcm_history = 0;
225         history_start = 0;
226         history_size = 0;
227         history_allocated = 0;
228         history_channels = 0;
229         decode_end = 0;
230
231         delete_ulaw_tables();
232         reset_parameters_derived();
233 }
234
235 void FileBase::get_mode(char *mode, int rd, int wr)
236 {
237         if(rd && !wr) sprintf(mode, "rb");
238         else if(!rd && wr) sprintf(mode, "wb");
239         else if(rd && wr) {
240                 int exists = 0;
241                 FILE *stream = fopen(asset->path, "rb");
242                 if( stream ) {
243                         exists = 1;
244                         fclose(stream);
245                 }
246                 sprintf(mode, exists ? "rb+" : "wb+");
247         }
248 }
249
250
251 // ======================================= audio codecs
252
253 int FileBase::get_video_buffer(unsigned char **buffer, int depth)
254 {
255 // get a raw video buffer for writing or compression by a library
256         if(!*buffer)
257         {
258 // Video compression is entirely done in the library.
259                 int64_t bytes = asset->width * asset->height * depth;
260                 *buffer = new unsigned char[bytes];
261         }
262         return 0;
263 }
264
265 int FileBase::get_row_pointers(unsigned char *buffer, unsigned char ***pointers, int depth)
266 {
267 // This might be fooled if a new VFrame is created at the same address with a different height.
268         if(*pointers && (*pointers)[0] != &buffer[0])
269         {
270                 delete [] *pointers;
271                 *pointers = 0;
272         }
273
274         if(!*pointers)
275         {
276                 *pointers = new unsigned char*[asset->height];
277                 for(int i = 0; i < asset->height; i++)
278                 {
279                         (*pointers)[i] = &buffer[i * asset->width * depth / 8];
280                 }
281         }
282         return 0;
283 }
284
285 int FileBase::match4(const char *in, const char *out)
286 {
287         return  in[0] == out[0] && in[1] == out[1] &&
288                 in[2] == out[2] && in[3] == out[3] ? 1 : 0;
289 }
290
291 int FileBase::search_render_strategies(ArrayList<int>* render_strategies, int render_strategy)
292 {
293         for(int i = 0; i < render_strategies->total; i++)
294                 if(render_strategies->values[i] == render_strategy) return 1;
295         return 0;
296 }
297
298
299 int64_t FileBase::base_memory_usage()
300 {
301 //printf("FileBase::base_memory_usage %d\n", __LINE__);
302         return !pcm_history ? 0 :
303                 history_allocated * history_channels * sizeof(double);
304 }
305
306