r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / indexthread.C
blobc00d74507e758351c58299b1e7aa8e3ba3ede997
1 #include "asset.h"
2 #include "condition.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "filexml.h"
6 #include "indexfile.h"
7 #include "indexthread.h"
8 #include "language.h"
9 #include "mwindow.h"
10 #include "mwindowgui.h"
11 #include "preferences.h"
12 #include "mainsession.h"
13 #include "trackcanvas.h"
14 #include "tracks.h"
16 // Read data from buffers and calculate peaks
18 IndexThread::IndexThread(MWindow *mwindow, 
19                                                 IndexFile *index_file,
20                                                 Asset *asset,
21                                                 char *index_filename,
22                                                 int64_t buffer_size, 
23                                                 int64_t length_source)
25         this->asset = asset;
26         this->buffer_size = buffer_size;
27         this->length_source = length_source;
28         this->mwindow = mwindow;
29         this->index_filename = index_filename;
30         this->index_file = index_file;
32 // initialize output data
33         int64_t index_size = mwindow->preferences->index_size / 
34                 sizeof(float) + 1;      // size of output file in floats
35         if(asset->index_buffer) delete [] asset->index_buffer;
36         if(asset->index_offsets) delete [] asset->index_offsets;
37 // buffer used for drawing during the build.  This is not deleted in the asset
38         asset->index_buffer = new float[index_size];  
39 // This is deleted in the asset's destructor
40         asset->index_offsets = new int64_t[asset->channels];
41         bzero(asset->index_buffer, index_size * sizeof(float));
42 //printf("IndexThread::IndexThread %d\n", index_size);
44 // initialization is completed in run
45         for(int i = 0; i < TOTAL_BUFFERS; i++)
46         {
47                 buffer_in[i] = new double*[asset->channels];
48                 output_lock[i] = new Condition(0, "IndexThread::output_lock");
49                 input_lock[i] = new Condition(1, "IndexThread::input_lock");
50                 for(int j = 0; j < asset->channels; j++)
51                 {
52                         buffer_in[i][j] = new double[buffer_size];
53                 }
54         }
56         interrupt_flag = 0;
59 IndexThread::~IndexThread()
61         for(int i = 0; i < TOTAL_BUFFERS; i++)
62         {
63                 for(int j = 0; j < asset->channels; j++)
64                 {
65                         delete [] buffer_in[i][j];
66                 }
67                 delete [] buffer_in[i];
68                 delete output_lock[i];
69                 delete input_lock[i];
70         }
71         
72         delete [] asset->index_buffer;
73         asset->index_buffer = 0;
76 int IndexThread::start_build()
78         set_synchronous(1);
79         interrupt_flag = 0;
80         current_buffer = 0;
81         for(int i = 0; i <  TOTAL_BUFFERS; i++) last_buffer[i] = 0;
82         start();
85 int IndexThread::stop_build()
87         join();
90 void IndexThread::run()
92         int done = 0;
94 // current high samples in index
95         int64_t *highpoint;            
96 // current low samples in the index
97         int64_t *lowpoint;             
98 // position in current indexframe
99         int64_t *frame_position;
100         int first_point = 1;
102         highpoint = new int64_t[asset->channels];
103         lowpoint = new int64_t[asset->channels];
104         frame_position = new int64_t[asset->channels];
106 // predict first highpoint for each channel plus padding and initialize it
107         for(int64_t channel = 0; channel < asset->channels; channel++)
108         {
109                 highpoint[channel] = 
110                         asset->index_offsets[channel] = 
111                         (length_source / asset->index_zoom * 2 + 1) * channel;
112                 lowpoint[channel] = highpoint[channel] + 1;
114 // Not effective when index_zoom == 1
115 // zero the first point
116 //              asset->index_buffer[highpoint[channel]] = 0;
117 //              asset->index_buffer[lowpoint[channel]] = 0;
118                 frame_position[channel] = 0;
119         }
121         int64_t index_start = 0;    // end of index during last edit update
122         asset->index_end = 0;      // samples in source completed
123         asset->old_index_end = 0;
124         asset->index_status = 2;
125         int64_t zoomx = asset->index_zoom;
126         float *index_buffer = asset->index_buffer;    // output of index build
128 //      index_file->redraw_edits();
130         while(!interrupt_flag && !done)
131         {
132                 output_lock[current_buffer]->lock("IndexThread::run");
134                 if(last_buffer[current_buffer]) done = 1;
135                 if(!interrupt_flag && !done)
136                 {
137 // process buffer
138                         int64_t fragment_size = input_len[current_buffer];
140 //printf("IndexThread::run 1\n");
141                         for(int channel = 0; channel < asset->channels; channel++)
142                         {
143                                 int64_t *highpoint_channel = &highpoint[channel];
144                                 int64_t *lowpoint_channel = &lowpoint[channel];
145                                 int64_t *frame_position_channel = &frame_position[channel];
146                                 double *buffer_source = buffer_in[current_buffer][channel];
148                                 for(int64_t i = 0; i < fragment_size; i++)
149                                 {
150                                         if(*frame_position_channel == zoomx)
151                                         {
152                                                 *highpoint_channel += 2;
153                                                 *lowpoint_channel += 2;
154                                                 *frame_position_channel = 0;
155 // store and reset output values
156                                                 index_buffer[*highpoint_channel] = index_buffer[*lowpoint_channel] = buffer_source[i];
157                                         }
158                                         else
159                                         {
160 // get high and low points
161                                                 if(first_point)
162                                                 {
163                                                         index_buffer[*highpoint_channel] = 
164                                                                 index_buffer[*lowpoint_channel] = buffer_source[i];
165                                                         first_point = 0;
166                                                 }
167                                                 else
168                                                 {
169                                                         if(buffer_source[i] > index_buffer[*highpoint_channel]) 
170                                                                 index_buffer[*highpoint_channel] = buffer_source[i];
171                                                         else 
172                                                         if(buffer_source[i] < index_buffer[*lowpoint_channel]) 
173                                                                 index_buffer[*lowpoint_channel] = buffer_source[i];
174                                                 }
175                                         }
176                                         (*frame_position_channel)++;
177                                 } // end index one buffer
178                         }
179 //printf("IndexThread::run 2\n");
181                         asset->index_end += fragment_size;
183 // draw simultaneously with build
184 //printf("IndexThread::run 2.1\n");
185                         index_file->redraw_edits(0);
186 //printf("IndexThread::run 2.2\n");
187                         index_start = asset->index_end;
188 //printf("IndexThread::run 2.3\n");
189 //printf("IndexThread::run 3\n");
190                 }
192 //printf("IndexThread::run %ld\n", lowpoint[asset->channels - 1] + 1);
193                 input_lock[current_buffer]->unlock();
194                 current_buffer++;
195                 if(current_buffer >= TOTAL_BUFFERS) current_buffer = 0;
196         }
198         index_file->redraw_edits(1);
200 // ================================== write the index file to disk
201         FILE *file;
202         if(!(file = fopen(index_filename, "wb")))
203         {
204 // failed to create it
205                 printf(_("IndexThread::run() Couldn't write index file %s to disk.\n"), index_filename);
206         }
207         else
208         {
209                 FileXML xml;
210                 fwrite((char*)&(asset->index_start), sizeof(int64_t), 1, file);
212                 asset->index_status = INDEX_READY;
213                 asset->write(mwindow->plugindb, 
214                         &xml, 
215                         1, 
216                         "");
217                 xml.write_to_file(file);
218                 asset->index_start = ftell(file);
219                 fseek(file, 0, SEEK_SET);
220                 fwrite((char*)&(asset->index_start), sizeof(int64_t), 1, file);
221                 fseek(file, asset->index_start, SEEK_SET);
222                 
223                 fwrite(asset->index_buffer, (lowpoint[asset->channels - 1] + 1) * sizeof(float), 1, file);
224                 fclose(file);
225         }
227 // done
228 // Force reread of header
229         asset->index_status = INDEX_NOTTESTED;
230 //      asset->index_status = INDEX_READY;
231         asset->index_end = length_source;
232         asset->old_index_end = 0;
233         asset->index_start = 0;
234         
235         delete [] highpoint;
236         delete [] lowpoint;
237         delete [] frame_position;