r851: Merge 2.1:
[cinelerra_cv.git] / cinelerra / filethread.C
blob78fc6cfc64419ece9a043e3d9aa9e2e55567b490
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "condition.h"
4 #include "file.h"
5 #include "filethread.h"
6 #include "mutex.h"
7 #include "vframe.h"
9 #include <string.h>
10 #include <unistd.h>
16 FileThread::FileThread(File *file, int do_audio, int do_video)
17  : Thread(1, 0, 0)
19         reset();
20         create_objects(file,
21                 do_audio,
22                 do_video);
25 FileThread::~FileThread()
27         delete_objects();
30         delete file_lock;
33 void FileThread::reset()
35         audio_buffer = 0;
36         video_buffer = 0;
37         output_size = 0;
38         input_lock = 0;
39         output_lock = 0;
40         last_buffer = 0;
44 void FileThread::create_objects(File *file, 
45                 int do_audio, 
46                 int do_video)
48         this->file = file;
49         this->do_audio = do_audio;
50         this->do_video = do_video;
51         file_lock = new Mutex("FileThread::file_lock");
55 void FileThread::delete_objects()
57         if(output_lock)
58         {
59                 for(int i = 0; i < ring_buffers; i++)
60                 {
61                         delete output_lock[i];
62                 }
63                 delete [] output_lock;
64         }
66         if(input_lock)
67         {
68                 for(int i = 0; i < ring_buffers; i++)
69                 {
70                         delete input_lock[i];
71                 }
72                 delete [] input_lock;
73         }
76         if(last_buffer)
77                 delete [] last_buffer;
80         delete [] output_size;
82         reset();
85 void FileThread::run()
87         int done = 0;
88         int i, j, result;
90         while(!done)
91         {
92                 output_lock[local_buffer]->lock("FileThread::run 1");
93                 return_value = 0;
96 // Timer timer;
97 // timer.update();
98                 if(!last_buffer[local_buffer])
99                 {
100                         if(output_size[local_buffer])
101                         {
102                                 file_lock->lock("FileThread::run 2");
103                                 if(do_audio)
104                                 {
105                                         result = file->write_samples(audio_buffer[local_buffer], 
106                                                 output_size[local_buffer]);
107                                 }
108                                 else
109                                 if(do_video)
110                                 {
111                                         result = 0;
112                                         if(compressed)
113                                         {
114                                                 for(j = 0; j < file->asset->layers && !result; j++)
115                                                         for(i = 0; i < output_size[local_buffer] && !result; i++)
116                                                                 result = file->write_compressed_frame(video_buffer[local_buffer][j][i]);
117                                         }
118                                         else
119                                         {
120                                                 result = file->write_frames(video_buffer[local_buffer], 
121                                                         output_size[local_buffer]);
122                                         }
123                                 }
125                                 file_lock->unlock();
126                                 return_value = result;
127                         }
128                         else
129                                 return_value = 0;
131                         output_size[local_buffer] = 0;
132                 }
133                 else
134                         done = 1;
136                 input_lock[local_buffer]->unlock();
137                 local_buffer++;
138                 if(local_buffer >= ring_buffers) local_buffer = 0;
139         }
144 int FileThread::stop_writing()
147         int i, buffer, layer, frame;
149         swap_buffer();
150         input_lock[current_buffer]->lock("FileThread::stop_writing 1");
152         last_buffer[current_buffer] = 1;
154         for(i = 0; i < ring_buffers; i++)
155                 output_lock[i]->unlock();
157         swap_buffer();
159 // wait for thread to finish
160         Thread::join();
162 // delete buffers
163         file_lock->lock("FileThread::stop_writing 2");
164         if(do_audio)
165         {
166                 for(buffer = 0; buffer < ring_buffers; buffer++)
167                 {
168                         for(i = 0; i < file->asset->channels; i++)
169                                 delete [] audio_buffer[buffer][i];
170                         delete [] audio_buffer[buffer];
171                 }
172                 delete [] audio_buffer;
173                 audio_buffer = 0;
174         }
176 // printf("FileThread::stop_writing %d %d %d %d\n", 
177 // do_video,
178 // ring_buffers,
179 // file->asset->layers,
180 // buffer_size);
181         if(do_video)
182         {
183                 for(buffer = 0; buffer < ring_buffers; buffer++)
184                 {
185                         for(layer = 0; layer < file->asset->layers; layer++)
186                         {
187                                 for(frame = 0; frame < buffer_size; frame++)
188                                 {
189                                         delete video_buffer[buffer][layer][frame];
190                                 }
191                                 delete [] video_buffer[buffer][layer];
192                         }
193                         delete [] video_buffer[buffer];
194                 }
195                 delete [] video_buffer;
196                 video_buffer = 0;
197         }
199         file_lock->unlock();
200         return 0;
203 int FileThread::start_writing(long buffer_size, 
204                 int color_model, 
205                 int ring_buffers, 
206                 int compressed)
208 // allocate buffers
209         int buffer, layer, frame;
210         long bytes_per_frame;
212         this->ring_buffers = ring_buffers;
213         this->buffer_size = buffer_size;
214         this->color_model = color_model;
215         this->compressed = compressed;
216         this->current_buffer = ring_buffers - 1;
217         return_value = 0;
218         local_buffer = 0;
220         file_lock->lock("FileThread::start_writing 1");
225 // Buffer is swapped before first get
226         last_buffer = new int[ring_buffers];
227         output_size = new long[ring_buffers];
230         output_lock = new Condition*[ring_buffers];
231         input_lock = new Condition*[ring_buffers];
232         for(int i = 0; i < ring_buffers; i++)
233         {
234                 output_lock[i] = new Condition(0, "FileThread::output_lock");
235                 input_lock[i] = new Condition(1, "FileThread::input_lock");
236                 last_buffer[i] = 0;
237                 output_size[i] = 0;
238         }
242         if(do_audio)
243         {
244                 audio_buffer = new double**[ring_buffers];
245                 for(buffer = 0; buffer < ring_buffers; buffer++)
246                 {
247                         audio_buffer[buffer] = new double*[file->asset->channels];
249                         for(int channel = 0; channel < file->asset->channels; channel++)
250                         {
251                                 audio_buffer[buffer][channel] = new double[buffer_size];
252                         }
253                 }
254         }
256         if(do_video)
257         {
258                 this->color_model = color_model;
259                 bytes_per_frame = VFrame::calculate_data_size(file->asset->width,
260                         file->asset->height,
261                         -1,
262                         color_model);
264                 video_buffer = new VFrame***[ring_buffers];
265 // printf("FileThread::start_writing 1 %d %d %d %p\n", 
266 // ring_buffers,
267 // file->asset->layers,
268 // buffer_size,
269 // video_buffer);
270                 for(buffer = 0; buffer < ring_buffers; buffer++)
271                 {
272                         video_buffer[buffer] = new VFrame**[file->asset->layers];
273                         for(layer = 0; layer < file->asset->layers; layer++)
274                         {
275                                 video_buffer[buffer][layer] = new VFrame*[buffer_size];
276                                 for(frame = 0; frame < buffer_size; frame++)
277                                 {
278                                         if(compressed)
279                                                 video_buffer[buffer][layer][frame] = new VFrame;
280                                         else
281                                         {
282                                                 video_buffer[buffer][layer][frame] = 
283                                                         new VFrame(0, 
284                                                                 file->asset->width, 
285                                                                 file->asset->height, 
286                                                                 color_model);
287 // printf("FileThread::start_writing 4 %d %d %d %p\n", 
288 // buffer, 
289 // layer, 
290 // frame, 
291 // video_buffer[buffer][layer]);
292                                         }
293                                 }
294                         }
295                 }
296         }
297         file_lock->unlock();
299         for(int i = 0; i < ring_buffers; i++)
300         {
301                 last_buffer[i] = 0;
302         }
305         start();
306         return 0;
310 int64_t FileThread::get_memory_usage()
312         frame_lock->lock("FileThread::get_memory_usage");
313         int64_t result = 0;
314 // 2.0 to 2.1 Dummy place-holder patch for until variables better implemented  
315         frame_lock->unlock();
316         return result;
320 double** FileThread::get_audio_buffer()
322         swap_buffer();
324         input_lock[current_buffer]->lock("FileThread::get_audio_buffer");
325         return audio_buffer[current_buffer];
328 VFrame*** FileThread::get_video_buffer()
330         swap_buffer();
332         input_lock[current_buffer]->lock("FileThread::get_video_buffer");
333         return video_buffer[current_buffer];
336 int FileThread::write_buffer(long size)
338         output_size[current_buffer] = size;
340 // unlock the output lock
341         output_lock[current_buffer]->unlock();
343         return return_value;
346 int FileThread::swap_buffer()
348         current_buffer++;
349         if(current_buffer >= ring_buffers) current_buffer = 0;