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