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