r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filelist.C
blobff4070da7cc8cb57fe9c1dbfa4442f96a0ec7c2d
1 #include "assets.h"
2 #include "file.h"
3 #include "filelist.h"
4 #include "guicast.h"
5 #include "mwindow.inc"
6 #include "render.h"
7 #include "renderfarmfsserver.inc"
8 #include "vframe.h"
10 #include <ctype.h>
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/stat.h>
17 FileList::FileList(Asset *asset, 
18         File *file, 
19         char *list_prefix,
20         char *file_extension, 
21         int frame_type,
22         int list_type)
23  : FileBase(asset, file)
25         reset_parameters();
26         asset->video_data = 1;
27         this->list_prefix = list_prefix;
28         this->file_extension = file_extension;
29         this->frame_type = frame_type;
30         this->list_type = list_type;
31         table_lock = new Mutex;
34 FileList::~FileList()
36         close_file();
37         delete table_lock;
40 int FileList::reset_parameters_derived()
42         data = 0;
43         writer = 0;
44         temp = 0;
45         first_number = 0;
48 int FileList::open_file(int rd, int wr)
50         this->rd = rd;
51         this->wr = wr;
52         int result = 0;
54 // skip header for write
55         if(wr)
56         {
57 // Frame files are created in write_frame and list index is created when
58 // file is closed.
59 // Look for the starting number in the path but ignore the starting character
60 // and total digits since these are used by the header.
61                 Render::get_starting_number(asset->path, 
62                         first_number,
63                         number_start, 
64                         number_digits);
65                 path_list.remove_all_objects();
66                 writer = new FrameWriter(this, 
67                         asset->format == list_type ? file->cpus : 1);
68         }
69         else
70         if(rd)
71         {
72 // Determine type of file.
73 // Header isn't used for background rendering, in which case everything known
74 // by the file encoder is known by the decoder.
75 //printf("FileList::open_file 1 %d\n", asset->use_header);
76                 if(asset->use_header)
77                 {
78                         FILE *stream = fopen(asset->path, "rb");
79                         if(stream)
80                         {
81                                 char string[BCTEXTLEN];
82                                 fread(string, strlen(list_prefix), 1, stream);
83                                 fclose(stream);
85                                 if(!strncasecmp(string, list_prefix, strlen(list_prefix)))
86                                 {
88                                         asset->format = list_type;
90 // Open index here or get frame size from file.
91                                         result = read_list_header();
92                                         if(!result) result = read_frame_header(path_list.values[0]);
93                                 }
94                                 else
95                                 {
96 //printf("FileList::open_file 2\n", asset->use_header);
97                                         asset->format = frame_type;
98                                         result = read_frame_header(asset->path);
99                                         asset->layers = 1;
100                                         if(!asset->frame_rate)
101                                                 asset->frame_rate = 1;
102                                         asset->video_length = -1;
103                                 }
104                         }
105                 }
106                 else
107                 {
108                         Render::get_starting_number(asset->path, 
109                                 first_number,
110                                 number_start, 
111                                 number_digits,
112                                 6);
113                 }
114         }
116         file->current_frame = 0;
117 // Compressed data storage
118         data = new VFrame;
120         return result;
124 int FileList::close_file()
126 //      path_list.total, asset->format, list_type, wr);
127         if(asset->format == list_type && path_list.total)
128         {
129 //printf("FileList::close_file 1 %d\n", asset->use_header);
130                 if(wr && asset->use_header) write_list_header();
131                 path_list.remove_all_objects();
132         }
133         if(data) delete data;
134         if(writer) delete writer;
135         if(temp) delete temp;
136         reset_parameters();
138         FileBase::close_file();
139         return 0;
142 int FileList::write_list_header()
144         FILE *stream = fopen(asset->path, "w");
145 // Use sprintf for VFS.
146         char string[BCTEXTLEN];
147         sprintf(string, "%s\n", list_prefix);
148         fwrite(string, strlen(string), 1, stream);
149         sprintf(string, "# First line is always %s\n", list_prefix);
150         fwrite(string, strlen(string), 1, stream);
151         sprintf(string, "# Frame rate:\n");
152         fwrite(string, strlen(string), 1, stream);
153         sprintf(string, "%f\n", asset->frame_rate);
154         fwrite(string, strlen(string), 1, stream);
155         sprintf(string, "# Width:\n");
156         fwrite(string, strlen(string), 1, stream);
157         sprintf(string, "%d\n", asset->width);
158         fwrite(string, strlen(string), 1, stream);
159         sprintf(string, "# Height:\n");
160         fwrite(string, strlen(string), 1, stream);
161         sprintf(string, "%d\n", asset->height);
162         fwrite(string, strlen(string), 1, stream);
163         sprintf(string, "# List of image files follows\n");
164         fwrite(string, strlen(string), 1, stream);
166         for(int i = 0; i < path_list.total; i++)
167         {
168 // Fix path for VFS
169                 if(!strncmp(path_list.values[i], RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
170                         sprintf(string, "%s", path_list.values[i] + strlen(RENDERFARM_FS_PREFIX) + 1);
171                 else
172                         sprintf(string, "%s\n", path_list.values[i]);
173         }
174         fclose(stream);
175         return 0;
178 int FileList::read_list_header()
180         char string[BCTEXTLEN], *new_entry;
182         FILE *stream = fopen(asset->path, "r");
183         
184         
185         if(stream)
186         {
187 // Get information about the frames
188                 do
189                 {
190                         fgets(string, BCTEXTLEN, stream);
191                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' ' || isalpha(string[0])));
193 // Don't want a user configured frame rate to get destroyed
194                 if(asset->frame_rate == 0)
195                         asset->frame_rate = atof(string);
197                 do
198                 {
199                         fgets(string, BCTEXTLEN, stream);
200                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
201                 asset->width = atol(string);
203                 do
204                 {
205                         fgets(string, BCTEXTLEN, stream);
206                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
207                 asset->height = atol(string);
209                 asset->layers = 1;
210                 asset->audio_data = 0;
211                 asset->video_data = 1;
213 // Get all the paths
214                 while(!feof(stream))
215                 {
216                         fgets(string, BCTEXTLEN, stream);
217                         if(strlen(string) && string[0] != '#' && string[0] != ' ' && !feof(stream))
218                         {
219                                 string[strlen(string) - 1] = 0;
220                                 path_list.append(new_entry = new char[strlen(string) + 1]);
221                                 strcpy(new_entry, string);
222                         }
223                 }
225 //for(int i = 0; i < path_list.total; i++) printf("%s\n", path_list.values[i]);
226                 fclose(stream);
227                 asset->video_length = path_list.total;
228         }
229         else
230                 return 1;
232         return 0;
235 int FileList::read_frame(VFrame *frame)
237         int result = 0;
238         if(file->current_frame < 0 || 
239                 (asset->use_header && file->current_frame >= path_list.total &&
240                         asset->format == list_type))
241                 return 1;
243         if(asset->format == list_type)
244         {
245                 char string[BCTEXTLEN];
246                 char *path;
247                 if(asset->use_header)
248                 {
249                         path = path_list.values[file->current_frame];
250                 }
251                 else
252                 {
253                         path = calculate_path(file->current_frame, string);
254                 }
255                 FILE *in;
258 // Fix path for VFS
259                 if(!strncmp(asset->path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
260                         sprintf(string, "%s%s", RENDERFARM_FS_PREFIX, path);
263                 if(!(in = fopen(string, "rb")))
264                 {
265                         fprintf(stderr, "FileList::read_frame %s: %s\n", string, strerror(errno));
266                 }
267                 else
268                 {
269                         struct stat ostat;
270                         stat(string, &ostat);
272                         switch(frame->get_color_model())
273                         {
274                                 case BC_COMPRESSED:
275                                         frame->allocate_compressed_data(ostat.st_size);
276                                         frame->set_compressed_size(ostat.st_size);
277                                         fread(frame->get_data(), ostat.st_size, 1, in);
278                                         break;
279                                 default:
280                                         data->allocate_compressed_data(ostat.st_size);
281                                         data->set_compressed_size(ostat.st_size);
282                                         fread(data->get_data(), ostat.st_size, 1, in);
283                                         result = read_frame(frame, data);
284                                         break;
285                         }
288                         fclose(in);
289                 }
290         }
291         else
292         {
294 //printf("FileList::read_frame 1\n");
295 // Allocate and decompress once into temporary
296                 if(!temp || temp->get_color_model() != frame->get_color_model())
297                 {
298                         if(temp) delete temp;
299                         temp = 0;
300                 
301 //printf("FileList::read_frame 2\n");
302                         FILE *fd = fopen(asset->path, "rb");
303                         if(fd)
304                         {
305                                 struct stat ostat;
306                                 stat(asset->path, &ostat);
308                                 switch(frame->get_color_model())
309                                 {
310                                         case BC_COMPRESSED:
311                                                 frame->allocate_compressed_data(ostat.st_size);
312                                                 frame->set_compressed_size(ostat.st_size);
313                                                 fread(frame->get_data(), ostat.st_size, 1, fd);
314                                                 break;
315                                         default:
316                                                 data->allocate_compressed_data(ostat.st_size);
317                                                 data->set_compressed_size(ostat.st_size);
318                                                 fread(data->get_data(), ostat.st_size, 1, fd);
319                                                 temp = new VFrame(0, 
320                                                         asset->width, 
321                                                         asset->height, 
322                                                         frame->get_color_model());
323                                                 read_frame(temp, data);
324                                                 break;
325                                 }
327 //printf("FileList::read_frame 3\n");
328                                 fclose(fd);
329                         }
330                         else
331                         {
332                                 fprintf(stderr, "FileList::read_frame %s: %s\n", asset->path, strerror(errno));
333                                 result = 1;
334                         }
335                 }
337 //printf("FileList::read_frame 4\n");
338                 if(!temp) return result;
340                 if(frame->get_color_model() == temp->get_color_model())
341                 {
342                         frame->copy_from(temp);
343                 }
344                 else
345                 {
346 // Never happens
347                         cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */
348                                 temp->get_rows(),
349                                 frame->get_y(), /* Leave NULL if non existent */
350                                 frame->get_u(),
351                                 frame->get_v(),
352                                 temp->get_y(), /* Leave NULL if non existent */
353                                 temp->get_u(),
354                                 temp->get_v(),
355                                 0,        /* Dimensions to capture from input frame */
356                                 0, 
357                                 asset->width, 
358                                 asset->height,
359                                 0,       /* Dimensions to project on output frame */
360                                 0, 
361                                 asset->width, 
362                                 asset->height,
363                                 temp->get_color_model(), 
364                                 frame->get_color_model(),
365                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
366                                 temp->get_w(),       /* For planar use the luma rowspan */
367                                 frame->get_w());
368                 }
369         }
372 //printf("FileList::read_frame 5 %d\n", result);
375         return result;
378 int FileList::write_frames(VFrame ***frames, int len)
380         return_value = 0;
382         if(frames[0][0]->get_color_model() == BC_COMPRESSED)
383         {
384                 for(int i = 0; i < asset->layers && !return_value; i++)
385                 {
386                         for(int j = 0; j < len && !return_value; j++)
387                         {
388                                 VFrame *frame = frames[i][j];
389                                 char *path = create_path(frame->get_number());
390                                 FILE *fd = fopen(path, "wb");
391                                 if(fd)
392                                 {
393                                         return_value = !fwrite(frames[i][j]->get_data(),
394                                                 frames[i][j]->get_compressed_size(),
395                                                 1,
396                                                 fd);
398                                         fclose(fd);
399                                 }
400                                 else
401                                 {
402                                         printf("FileList::write_frames %s: %s\n", path, strerror(errno));
403                                         return_value++;
404                                 }
405                         }
406                 }
407         }
408         else
409         {
410                 writer->write_frames(frames, len);
411         }
412         return return_value;
423 void FileList::add_return_value(int amount)
425         table_lock->lock();
426         return_value += amount;
427         table_lock->unlock();
430 char* FileList::calculate_path(int number, char *string)
432 // Synthesize filename.
433 // If a header is used, the filename number must be in a different location.
434         if(asset->use_header)
435         {
436                 int k;
437                 strcpy(string, asset->path);
438                 for(k = strlen(string) - 1; k > 0 && string[k] != '.'; k--)
439                         ;
440                 if(k <= 0) k = strlen(string);
442                 sprintf(&string[k], "%06d%s", 
443                         number, 
444                         file_extension);
445         }
446         else
447 // Without a header, the original filename can be altered.
448         {
449                 Render::create_filename(string, 
450                         asset->path, 
451                         number,
452                         number_digits,
453                         number_start);
454         }
456         return string;
459 char* FileList::create_path(int number_override)
461         if(asset->format != list_type) return asset->path;
463         table_lock->lock();
467         char *path = "";
468         char output[BCTEXTLEN];
469         if(file->current_frame >= path_list.total || !asset->use_header)
470         {
471                 int number;
472                 if(number_override < 0)
473                         number = file->current_frame++;
474                 else
475                         number = number_override;
477                 if(!asset->use_header)
478                 {
479                         number += first_number;
480                 }
482                 calculate_path(number, output);
484                 path = new char[strlen(output) + 1];
485                 strcpy(path, output);
486                 path_list.append(path);
487         }
488         else
489         {
490 // Overwrite an old path
491                 path = path_list.values[file->current_frame];
492         }
495         table_lock->unlock();
496         
497         return path;
500 FrameWriterUnit* FileList::new_writer_unit(FrameWriter *writer)
502         return new FrameWriterUnit(writer);
514 FrameWriterPackage::FrameWriterPackage()
518 FrameWriterPackage::~FrameWriterPackage()
532 FrameWriterUnit::FrameWriterUnit(FrameWriter *server)
533  : LoadClient(server)
535 // Don't use server here since subclasses call this with no server.
536         this->server = server;
537         output = new VFrame;
540 FrameWriterUnit::~FrameWriterUnit()
542         delete output;
545 void FrameWriterUnit::process_package(LoadPackage *package)
547         FrameWriterPackage *ptr = (FrameWriterPackage*)package;
549         FILE *file;
551 //printf("FrameWriterUnit::process_package 1 %s\n", ptr->path);
552         if(!(file = fopen(ptr->path, "wb")))
553         {
554                 printf("FrameWriterUnit::process_package %s: %s\n",
555                         ptr->path,
556                         strerror(errno));
557                 return;
558         }
559         
560         
561         int result = server->file->write_frame(ptr->input, output, this);
562         
563         if(!result) result = !fwrite(output->get_data(), output->get_compressed_size(), 1, file);
564         fclose(file);
565         
566         server->file->add_return_value(result);
579 FrameWriter::FrameWriter(FileList *file, int cpus)
580  : LoadServer(cpus, 0)
582         this->file = file;
586 FrameWriter::~FrameWriter()
590 void FrameWriter::init_packages()
592         for(int i = 0, layer = 0, number = 0; 
593                 i < get_total_packages(); 
594                 i++)
595         {
596                 FrameWriterPackage *package = (FrameWriterPackage*)get_package(i);
597                 package->input = frames[layer][number];
598                 package->path = file->create_path(package->input->get_number());
599 // printf("FrameWriter::init_packages 1 %d %s\n", 
600 // package->input->get_number(), 
601 // package->path);
602                 number++;
603                 if(number >= len)
604                 {
605                         layer++;
606                         number = 0;
607                 }
608         }
611 void FrameWriter::write_frames(VFrame ***frames, int len)
613         this->frames = frames;
614         this->len = len;
615         set_package_count(len * file->asset->layers);
616         
617         process_packages();
620 LoadClient* FrameWriter::new_client()
622         return file->new_writer_unit(this);
625 LoadPackage* FrameWriter::new_package()
627         return new FrameWriterPackage;