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