r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filethread.C
blob1373e84cfca76950ab61f52ad0566fb31cf466da
1 #include "asset.h"
2 #include "condition.h"
3 #include "file.h"
4 #include "filethread.h"
5 #include "mutex.h"
6 #include "vframe.h"
8 #include <unistd.h>
10 FileThread::FileThread(File *file, int do_audio, int do_video)
11  : Thread(1, 0, 0)
13         create_objects(file,
14                 do_audio,
15                 do_video,
16                 0,
17                 0,
18                 0,
19                 0);
22 FileThread::FileThread(File *file, 
23                 int do_audio, 
24                 int do_video,
25                 long buffer_size, 
26                 int color_model, 
27                 int ring_buffers, 
28                 int compressed)
30         create_objects(file, 
31                 do_audio, 
32                 do_video,
33                 buffer_size, 
34                 color_model, 
35                 ring_buffers, 
36                 compressed);
39 void FileThread::create_objects(File *file, 
40                 int do_audio, 
41                 int do_video,
42                 long buffer_size, 
43                 int color_model, 
44                 int ring_buffers, 
45                 int compressed)
47         this->file = file;
48         this->do_audio = do_audio;
49         this->do_video = do_video;
50         file_lock = new Mutex("FileThread::file_lock");
51         for(int i = 0; i < RING_BUFFERS; i++)
52         {
53                 output_lock[i] = new Condition(0, "FileThread::output_lock");
54                 input_lock[i] = new Condition(1, "FileThread::input_lock");
55         }
56         this->ring_buffers = ring_buffers;
57         this->buffer_size = buffer_size;
58         this->color_model = color_model;
59         this->compressed = compressed;
60 // Buffer is swapped before first get
61         current_buffer = ring_buffers - 1;
62         return_value = 0;
63         local_buffer = 0;
66 FileThread::~FileThread()
68         delete file_lock;
69         for(int i = 0; i < RING_BUFFERS; i++)
70         {
71                 delete output_lock[i];
72                 delete input_lock[i];
73         }
76 void FileThread::run()
78         int done = 0;
79         int i, j, result;
81 //printf("FileThread::run 1 %d\n", getpid());
82         while(!done)
83         {
84                 output_lock[local_buffer]->lock("FileThread::run 1");
85                 return_value = 0;
87 // Timer timer;
88 // timer.update();
89                 if(!last_buffer[local_buffer])
90                 {
91                         if(output_size[local_buffer])
92                         {
93                                 file_lock->lock("FileThread::run 2");
94                                 if(do_audio)
95                                 {
96                                         result = file->write_samples(audio_buffer[local_buffer], 
97                                                 output_size[local_buffer]);
98                                 }
99                                 else
100                                 if(do_video)
101                                 {
102                                         result = 0;
103                                         if(compressed)
104                                         {
105                                                 for(j = 0; j < file->asset->layers && !result; j++)
106                                                         for(i = 0; i < output_size[local_buffer] && !result; i++)
107                                                                 result = file->write_compressed_frame(video_buffer[local_buffer][j][i]);
108                                         }
109                                         else
110                                         {
111                                                 result = file->write_frames(video_buffer[local_buffer], 
112                                                         output_size[local_buffer]);
113                                         }
114                                 }
116                                 file_lock->unlock();
117                                 return_value = result;
118                         }
119                         else
120                                 return_value = 0;
122                         output_size[local_buffer] = 0;
123                 }
124                 else
125                         done = 1;
127 //printf("FileThread::run %lld\n", timer.get_difference());
128                 input_lock[local_buffer]->unlock();
129                 local_buffer++;
130                 if(local_buffer >= ring_buffers) local_buffer = 0;
131         }
136 int FileThread::stop_writing()
138         int i, buffer, layer, frame;
140         swap_buffer();
141         input_lock[current_buffer]->lock("FileThread::stop_writing 1");
143         last_buffer[current_buffer] = 1;
145         for(i = 0; i < ring_buffers; i++)
146                 output_lock[i]->unlock();
148         swap_buffer();
150 // wait for thread to finish
151         join();
153 // delete buffers
154         file_lock->lock("FileThread::stop_writing 2");
155         if(do_audio)
156         {
157                 for(buffer = 0; buffer < ring_buffers; buffer++)
158                 {
159                         for(i = 0; i < file->asset->channels; i++)
160                                 delete [] audio_buffer[buffer][i];
161                         delete [] audio_buffer[buffer];
162                 }
163         }
165 // printf("FileThread::stop_writing %d %d %d %d\n", 
166 // do_video,
167 // ring_buffers,
168 // file->asset->layers,
169 // buffer_size);
170         if(do_video)
171         {
172                 for(buffer = 0; buffer < ring_buffers; buffer++)
173                 {
174                         for(layer = 0; layer < file->asset->layers; layer++)
175                         {
176                                 for(frame = 0; frame < buffer_size; frame++)
177                                 {
178                                         delete video_buffer[buffer][layer][frame];
179                                 }
180                                 delete [] video_buffer[buffer][layer];
181                         }
182                         delete [] video_buffer[buffer];
183                 }
184         }
185         file_lock->unlock();
186         return 0;
189 int FileThread::start_writing()
191         start_writing(buffer_size, 
192                 color_model, 
193                 ring_buffers, 
194                 compressed);
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;
210         file_lock->lock("FileThread::start_writing 1");
211         if(do_audio)
212         {
213                 for(buffer = 0; buffer < ring_buffers; buffer++)
214                 {
215                         audio_buffer[buffer] = new double*[file->asset->channels];
217                         for(int channel = 0; channel < file->asset->channels; channel++)
218                         {
219                                 audio_buffer[buffer][channel] = new double[buffer_size];
220                         }
221                 }
222         }
224         if(do_video)
225         {
226                 this->color_model = color_model;
227                 bytes_per_frame = VFrame::calculate_data_size(file->asset->width,
228                         file->asset->height,
229                         -1,
230                         color_model);
232                 for(buffer = 0; buffer < ring_buffers; buffer++)
233                 {
234                         video_buffer[buffer] = new VFrame**[file->asset->layers];
235                         for(layer = 0; layer < file->asset->layers; layer++)
236                         {
237                                 video_buffer[buffer][layer] = new VFrame*[buffer_size];
238                                 for(frame = 0; frame < buffer_size; frame++)
239                                 {
240                                         if(compressed)
241                                                 video_buffer[buffer][layer][frame] = new VFrame;
242                                         else
243                                         {
244                                                 video_buffer[buffer][layer][frame] = 
245                                                         new VFrame(0, 
246                                                                 file->asset->width, 
247                                                                 file->asset->height, 
248                                                                 color_model);
249                                         }
250                                 }
251                         }
252                 }
253         }
254 //printf("FileThread::start_writing 1\n");
255         file_lock->unlock();
257         for(int i = 0; i < ring_buffers; i++)
258         {
259                 last_buffer[i] = 0;
260         }
261 //printf("FileThread::start_writing 1\n");
264         start();
265         return 0;
268 double** FileThread::get_audio_buffer()
270         swap_buffer();
272         input_lock[current_buffer]->lock("FileThread::get_audio_buffer");
273         return audio_buffer[current_buffer];
276 VFrame*** FileThread::get_video_buffer()
278         swap_buffer();
280         input_lock[current_buffer]->lock("FileThread::get_video_buffer");
281         return video_buffer[current_buffer];
284 int FileThread::write_buffer(long size)
286         output_size[current_buffer] = size;
288 // unlock the output lock
289         output_lock[current_buffer]->unlock();
291         return return_value;
294 int FileThread::swap_buffer()
296         current_buffer++;
297         if(current_buffer >= ring_buffers) current_buffer = 0;