r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filethread.C
blob43268a078f8687d0b0aa560ba10f10636eb7c2ac
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 <unistd.h>
11 FileThread::FileThread(File *file, int do_audio, int do_video)
12  : Thread(1, 0, 0)
14         reset();
15         create_objects(file,
16                 do_audio,
17                 do_video);
20 FileThread::~FileThread()
22         delete_objects();
26         delete file_lock;
29 void FileThread::reset()
31         audio_buffer = 0;
32         video_buffer = 0;
33         output_size = 0;
34         input_lock = 0;
35         output_lock = 0;
36         last_buffer = 0;
40 void FileThread::create_objects(File *file, 
41                 int do_audio, 
42                 int do_video)
44         this->file = file;
45         this->do_audio = do_audio;
46         this->do_video = do_video;
47         file_lock = new Mutex("FileThread::file_lock");
51 void FileThread::delete_objects()
53         if(output_lock)
54         {
55                 for(int i = 0; i < ring_buffers; i++)
56                 {
57                         delete output_lock[i];
58                 }
59                 delete [] output_lock;
60         }
62         if(input_lock)
63         {
64                 for(int i = 0; i < ring_buffers; i++)
65                 {
66                         delete input_lock[i];
67                 }
68                 delete [] input_lock;
69         }
72         if(last_buffer)
73                 delete [] last_buffer;
76         reset();
79 void FileThread::run()
81         int done = 0;
82         int i, j, result;
84 //printf("FileThread::run 1 %d\n", getpid());
85         while(!done)
86         {
87                 output_lock[local_buffer]->lock("FileThread::run 1");
88                 return_value = 0;
91 // Timer timer;
92 // timer.update();
93                 if(!last_buffer[local_buffer])
94                 {
95                         if(output_size[local_buffer])
96                         {
97                                 file_lock->lock("FileThread::run 2");
98                                 if(do_audio)
99                                 {
100 TRACE("FileThread::run 4");
101                                         result = file->write_samples(audio_buffer[local_buffer], 
102                                                 output_size[local_buffer]);
103 TRACE("FileThread::run 5");
104                                 }
105                                 else
106                                 if(do_video)
107                                 {
108                                         result = 0;
109                                         if(compressed)
110                                         {
111                                                 for(j = 0; j < file->asset->layers && !result; j++)
112                                                         for(i = 0; i < output_size[local_buffer] && !result; i++)
113                                                                 result = file->write_compressed_frame(video_buffer[local_buffer][j][i]);
114                                         }
115                                         else
116                                         {
117                                                 result = file->write_frames(video_buffer[local_buffer], 
118                                                         output_size[local_buffer]);
119                                         }
120                                 }
122                                 file_lock->unlock();
123                                 return_value = result;
124                         }
125                         else
126                                 return_value = 0;
128                         output_size[local_buffer] = 0;
129                 }
130                 else
131                         done = 1;
133                 input_lock[local_buffer]->unlock();
134                 local_buffer++;
135                 if(local_buffer >= ring_buffers) local_buffer = 0;
136         }
141 int FileThread::stop_writing()
143         int i, buffer, layer, frame;
145         swap_buffer();
146         input_lock[current_buffer]->lock("FileThread::stop_writing 1");
148         last_buffer[current_buffer] = 1;
150         for(i = 0; i < ring_buffers; i++)
151                 output_lock[i]->unlock();
153         swap_buffer();
155 // wait for thread to finish
156         Thread::join();
158 // delete buffers
159         file_lock->lock("FileThread::stop_writing 2");
160         if(do_audio)
161         {
162                 for(buffer = 0; buffer < ring_buffers; buffer++)
163                 {
164                         for(i = 0; i < file->asset->channels; i++)
165                                 delete [] audio_buffer[buffer][i];
166                         delete [] audio_buffer[buffer];
167                 }
168                 delete [] audio_buffer;
169                 audio_buffer = 0;
170         }
172 // printf("FileThread::stop_writing %d %d %d %d\n", 
173 // do_video,
174 // ring_buffers,
175 // file->asset->layers,
176 // buffer_size);
177         if(do_video)
178         {
179                 for(buffer = 0; buffer < ring_buffers; buffer++)
180                 {
181                         for(layer = 0; layer < file->asset->layers; layer++)
182                         {
183                                 for(frame = 0; frame < buffer_size; frame++)
184                                 {
185                                         delete video_buffer[buffer][layer][frame];
186                                 }
187                                 delete [] video_buffer[buffer][layer];
188                         }
189                         delete [] video_buffer[buffer];
190                 }
191                 delete [] video_buffer;
192                 video_buffer = 0;
193         }
194         file_lock->unlock();
195         return 0;
198 int FileThread::start_writing(long buffer_size, 
199                 int color_model, 
200                 int ring_buffers, 
201                 int compressed)
203 // allocate buffers
204         int buffer, layer, frame;
205         long bytes_per_frame;
207         this->ring_buffers = ring_buffers;
208         this->buffer_size = buffer_size;
209         this->color_model = color_model;
210         this->compressed = compressed;
211         this->current_buffer = ring_buffers - 1;
212         return_value = 0;
213         local_buffer = 0;
215         file_lock->lock("FileThread::start_writing 1");
220 // Buffer is swapped before first get
221         last_buffer = new int[ring_buffers];
222         output_size = new long[ring_buffers];
225         output_lock = new Condition*[ring_buffers];
226         input_lock = new Condition*[ring_buffers];
227         for(int i = 0; i < ring_buffers; i++)
228         {
229                 output_lock[i] = new Condition(0, "FileThread::output_lock");
230                 input_lock[i] = new Condition(1, "FileThread::input_lock");
231                 last_buffer[i] = 0;
232                 output_size[i] = 0;
233         }
237         if(do_audio)
238         {
239                 audio_buffer = new double**[ring_buffers];
240                 for(buffer = 0; buffer < ring_buffers; buffer++)
241                 {
242                         audio_buffer[buffer] = new double*[file->asset->channels];
244                         for(int channel = 0; channel < file->asset->channels; channel++)
245                         {
246                                 audio_buffer[buffer][channel] = new double[buffer_size];
247                         }
248                 }
249         }
251         if(do_video)
252         {
253                 this->color_model = color_model;
254                 bytes_per_frame = VFrame::calculate_data_size(file->asset->width,
255                         file->asset->height,
256                         -1,
257                         color_model);
259                 video_buffer = new VFrame***[ring_buffers];
260 // printf("FileThread::start_writing 1 %d %d %d %p\n", 
261 // ring_buffers,
262 // file->asset->layers,
263 // buffer_size,
264 // video_buffer);
265                 for(buffer = 0; buffer < ring_buffers; buffer++)
266                 {
267                         video_buffer[buffer] = new VFrame**[file->asset->layers];
268                         for(layer = 0; layer < file->asset->layers; layer++)
269                         {
270                                 video_buffer[buffer][layer] = new VFrame*[buffer_size];
271                                 for(frame = 0; frame < buffer_size; frame++)
272                                 {
273                                         if(compressed)
274                                                 video_buffer[buffer][layer][frame] = new VFrame;
275                                         else
276                                         {
277                                                 video_buffer[buffer][layer][frame] = 
278                                                         new VFrame(0, 
279                                                                 file->asset->width, 
280                                                                 file->asset->height, 
281                                                                 color_model);
282 // printf("FileThread::start_writing 4 %d %d %d %p\n", 
283 // buffer, 
284 // layer, 
285 // frame, 
286 // video_buffer[buffer][layer]);
287                                         }
288                                 }
289                         }
290                 }
291         }
292         file_lock->unlock();
294         for(int i = 0; i < ring_buffers; i++)
295         {
296                 last_buffer[i] = 0;
297         }
300         start();
301         return 0;
304 double** FileThread::get_audio_buffer()
306         swap_buffer();
308         input_lock[current_buffer]->lock("FileThread::get_audio_buffer");
309         return audio_buffer[current_buffer];
312 VFrame*** FileThread::get_video_buffer()
314         swap_buffer();
316         input_lock[current_buffer]->lock("FileThread::get_video_buffer");
317         return video_buffer[current_buffer];
320 int FileThread::write_buffer(long size)
322         output_size[current_buffer] = size;
324 // unlock the output lock
325         output_lock[current_buffer]->unlock();
327         return return_value;
330 int FileThread::swap_buffer()
332         current_buffer++;
333         if(current_buffer >= ring_buffers) current_buffer = 0;