r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filelist.C
blob60914db3eeada2870fa69f61d9cce80acf144e97
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "file.h"
4 #include "filelist.h"
5 #include "guicast.h"
6 #include "mwindow.inc"
7 #include "render.h"
8 #include "renderfarmfsserver.inc"
9 #include "vframe.h"
11 #include <ctype.h>
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
18 FileList::FileList(Asset *asset, 
19         File *file, 
20         char *list_prefix,
21         char *file_extension, 
22         int frame_type,
23         int list_type)
24  : FileBase(asset, file)
26         reset_parameters();
27         asset->video_data = 1;
28         this->list_prefix = list_prefix;
29         this->file_extension = file_extension;
30         this->frame_type = frame_type;
31         this->list_type = list_type;
32         table_lock = new Mutex("FileList::table_lock");
35 FileList::~FileList()
37         close_file();
38         delete table_lock;
41 int FileList::reset_parameters_derived()
43         data = 0;
44         writer = 0;
45         temp = 0;
46         first_number = 0;
49 int FileList::open_file(int rd, int wr)
51         this->rd = rd;
52         this->wr = wr;
53         int result = 0;
55 // skip header for write
56         if(wr)
57         {
58 // Frame files are created in write_frame and list index is created when
59 // file is closed.
60 // Look for the starting number in the path but ignore the starting character
61 // and total digits since these are used by the header.
62                 Render::get_starting_number(asset->path, 
63                         first_number,
64                         number_start, 
65                         number_digits);
66                 path_list.remove_all_objects();
67                 writer = new FrameWriter(this, 
68                         asset->format == list_type ? file->cpus : 1);
69         }
70         else
71         if(rd)
72         {
73 // Determine type of file.
74 // Header isn't used for background rendering, in which case everything known
75 // by the file encoder is known by the decoder.
76 //printf("FileList::open_file 1 %d\n", asset->use_header);
77                 if(asset->use_header)
78                 {
79                         FILE *stream = fopen(asset->path, "rb");
80                         if(stream)
81                         {
82                                 char string[BCTEXTLEN];
83                                 fread(string, strlen(list_prefix), 1, stream);
84                                 fclose(stream);
86                                 if(!strncasecmp(string, list_prefix, strlen(list_prefix)))
87                                 {
89                                         asset->format = list_type;
91 // Open index here or get frame size from file.
92                                         result = read_list_header();
93                                         if(!result) result = read_frame_header(path_list.values[0]);
94                                 }
95                                 else
96                                 {
97 //printf("FileList::open_file 2\n", asset->use_header);
98                                         asset->format = frame_type;
99                                         result = read_frame_header(asset->path);
100                                         asset->layers = 1;
101                                         if(!asset->frame_rate)
102                                                 asset->frame_rate = 1;
103                                         asset->video_length = -1;
104                                 }
105                         }
106                 }
107                 else
108                 {
109                         Render::get_starting_number(asset->path, 
110                                 first_number,
111                                 number_start, 
112                                 number_digits,
113                                 6);
114                 }
115         }
117         file->current_frame = 0;
118 // Compressed data storage
119         data = new VFrame;
121         return result;
125 int FileList::close_file()
127 //      path_list.total, asset->format, list_type, wr);
128         if(asset->format == list_type && path_list.total)
129         {
130 //printf("FileList::close_file 1 %d\n", asset->use_header);
131                 if(wr && asset->use_header) write_list_header();
132                 path_list.remove_all_objects();
133         }
134         if(data) delete data;
135         if(writer) delete writer;
136         if(temp) delete temp;
137         reset_parameters();
139         FileBase::close_file();
140         return 0;
143 int FileList::write_list_header()
145         FILE *stream = fopen(asset->path, "w");
146 // Use sprintf for VFS.
147         char string[BCTEXTLEN];
148         sprintf(string, "%s\n", list_prefix);
149         fwrite(string, strlen(string), 1, stream);
150         sprintf(string, "# First line is always %s\n", list_prefix);
151         fwrite(string, strlen(string), 1, stream);
152         sprintf(string, "# Frame rate:\n");
153         fwrite(string, strlen(string), 1, stream);
154         sprintf(string, "%f\n", asset->frame_rate);
155         fwrite(string, strlen(string), 1, stream);
156         sprintf(string, "# Width:\n");
157         fwrite(string, strlen(string), 1, stream);
158         sprintf(string, "%d\n", asset->width);
159         fwrite(string, strlen(string), 1, stream);
160         sprintf(string, "# Height:\n");
161         fwrite(string, strlen(string), 1, stream);
162         sprintf(string, "%d\n", asset->height);
163         fwrite(string, strlen(string), 1, stream);
164         sprintf(string, "# List of image files follows\n");
165         fwrite(string, strlen(string), 1, stream);
167         for(int i = 0; i < path_list.total; i++)
168         {
169 // Fix path for VFS
170                 if(!strncmp(path_list.values[i], RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
171                         sprintf(string, "%s", path_list.values[i] + strlen(RENDERFARM_FS_PREFIX) + 1);
172                 else
173                         sprintf(string, "%s\n", path_list.values[i]);
174         }
175         fclose(stream);
176         return 0;
179 int FileList::read_list_header()
181         char string[BCTEXTLEN], *new_entry;
183         FILE *stream = fopen(asset->path, "r");
184         
185         
186         if(stream)
187         {
188 // Get information about the frames
189                 do
190                 {
191                         fgets(string, BCTEXTLEN, stream);
192                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' ' || isalpha(string[0])));
194 // Don't want a user configured frame rate to get destroyed
195                 if(asset->frame_rate == 0)
196                         asset->frame_rate = atof(string);
198                 do
199                 {
200                         fgets(string, BCTEXTLEN, stream);
201                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
202                 asset->width = atol(string);
204                 do
205                 {
206                         fgets(string, BCTEXTLEN, stream);
207                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
208                 asset->height = atol(string);
210                 asset->layers = 1;
211                 asset->audio_data = 0;
212                 asset->video_data = 1;
214 // Get all the paths
215                 while(!feof(stream))
216                 {
217                         fgets(string, BCTEXTLEN, stream);
218                         if(strlen(string) && string[0] != '#' && string[0] != ' ' && !feof(stream))
219                         {
220                                 string[strlen(string) - 1] = 0;
221                                 path_list.append(new_entry = new char[strlen(string) + 1]);
222                                 strcpy(new_entry, string);
223                         }
224                 }
226 //for(int i = 0; i < path_list.total; i++) printf("%s\n", path_list.values[i]);
227                 fclose(stream);
228                 asset->video_length = path_list.total;
229         }
230         else
231                 return 1;
233         return 0;
236 int FileList::read_frame(VFrame *frame)
238         int result = 0;
239         if(file->current_frame < 0 || 
240                 (asset->use_header && file->current_frame >= path_list.total &&
241                         asset->format == list_type))
242                 return 1;
244         if(asset->format == list_type)
245         {
246                 char string[BCTEXTLEN];
247                 char *path;
248                 if(asset->use_header)
249                 {
250                         path = path_list.values[file->current_frame];
251                 }
252                 else
253                 {
254                         path = calculate_path(file->current_frame, string);
255                 }
256                 FILE *in;
259 // Fix path for VFS
260                 if(!strncmp(asset->path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
261                         sprintf(string, "%s%s", RENDERFARM_FS_PREFIX, path);
262                 else
263                         strcpy(string, path);
265                 if(!(in = fopen(string, "rb")))
266                 {
267                         fprintf(stderr, "FileList::read_frame %s: %s\n", string, strerror(errno));
268                 }
269                 else
270                 {
271                         struct stat ostat;
272                         stat(string, &ostat);
274                         switch(frame->get_color_model())
275                         {
276                                 case BC_COMPRESSED:
277                                         frame->allocate_compressed_data(ostat.st_size);
278                                         frame->set_compressed_size(ostat.st_size);
279                                         fread(frame->get_data(), ostat.st_size, 1, in);
280                                         break;
281                                 default:
282                                         data->allocate_compressed_data(ostat.st_size);
283                                         data->set_compressed_size(ostat.st_size);
284                                         fread(data->get_data(), ostat.st_size, 1, in);
285                                         result = read_frame(frame, data);
286                                         break;
287                         }
290                         fclose(in);
291                 }
292         }
293         else
294         {
296 // Allocate and decompress once into temporary
297                 if(!temp || temp->get_color_model() != frame->get_color_model())
298                 {
299                         if(temp) delete temp;
300                         temp = 0;
301                 
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                                 fclose(fd);
328                         }
329                         else
330                         {
331                                 fprintf(stderr, "FileList::read_frame %s: %s\n", asset->path, strerror(errno));
332                                 result = 1;
333                         }
334                 }
336                 if(!temp) return result;
338                 if(frame->get_color_model() == temp->get_color_model())
339                 {
340                         frame->copy_from(temp);
341                 }
342                 else
343                 {
344 // Never happens
345                         cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */
346                                 temp->get_rows(),
347                                 frame->get_y(), /* Leave NULL if non existent */
348                                 frame->get_u(),
349                                 frame->get_v(),
350                                 temp->get_y(), /* Leave NULL if non existent */
351                                 temp->get_u(),
352                                 temp->get_v(),
353                                 0,        /* Dimensions to capture from input frame */
354                                 0, 
355                                 asset->width, 
356                                 asset->height,
357                                 0,       /* Dimensions to project on output frame */
358                                 0, 
359                                 asset->width, 
360                                 asset->height,
361                                 temp->get_color_model(), 
362                                 frame->get_color_model(),
363                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
364                                 temp->get_w(),       /* For planar use the luma rowspan */
365                                 frame->get_w());
366                 }
367         }
370 //printf("FileList::read_frame 5 %d\n", result);
373         return result;
376 int FileList::write_frames(VFrame ***frames, int len)
378         return_value = 0;
380 //printf("FileList::write_frames 1\n");
381         if(frames[0][0]->get_color_model() == BC_COMPRESSED)
382         {
383                 for(int i = 0; i < asset->layers && !return_value; i++)
384                 {
385                         for(int j = 0; j < len && !return_value; j++)
386                         {
387                                 VFrame *frame = frames[i][j];
388                                 char *path = create_path(frame->get_number());
389                                 FILE *fd = fopen(path, "wb");
390                                 if(fd)
391                                 {
392                                         return_value = !fwrite(frames[i][j]->get_data(),
393                                                 frames[i][j]->get_compressed_size(),
394                                                 1,
395                                                 fd);
397                                         fclose(fd);
398                                 }
399                                 else
400                                 {
401                                         printf("FileList::write_frames %s: %s\n", path, strerror(errno));
402                                         return_value++;
403                                 }
404                         }
405                 }
406         }
407         else
408         {
409 //printf("FileList::write_frames 2\n");
410                 writer->write_frames(frames, len);
411 //printf("FileList::write_frames 100\n");
412         }
413         return return_value;
424 void FileList::add_return_value(int amount)
426         table_lock->lock("FileList::add_return_value");
427         return_value += amount;
428         table_lock->unlock();
431 char* FileList::calculate_path(int number, char *string)
433 // Synthesize filename.
434 // If a header is used, the filename number must be in a different location.
435         if(asset->use_header)
436         {
437                 int k;
438                 strcpy(string, asset->path);
439                 for(k = strlen(string) - 1; k > 0 && string[k] != '.'; k--)
440                         ;
441                 if(k <= 0) k = strlen(string);
443                 sprintf(&string[k], "%06d%s", 
444                         number, 
445                         file_extension);
446         }
447         else
448 // Without a header, the original filename can be altered.
449         {
450                 Render::create_filename(string, 
451                         asset->path, 
452                         number,
453                         number_digits,
454                         number_start);
455         }
457         return string;
460 char* FileList::create_path(int number_override)
462         if(asset->format != list_type) return asset->path;
464         table_lock->lock("FileList::create_path");
468         char *path = "";
469         char output[BCTEXTLEN];
470         if(file->current_frame >= path_list.total || !asset->use_header)
471         {
472                 int number;
473                 if(number_override < 0)
474                         number = file->current_frame++;
475                 else
476                         number = number_override;
478                 if(!asset->use_header)
479                 {
480                         number += first_number;
481                 }
483                 calculate_path(number, output);
485                 path = new char[strlen(output) + 1];
486                 strcpy(path, output);
487                 path_list.append(path);
488         }
489         else
490         {
491 // Overwrite an old path
492                 path = path_list.values[file->current_frame];
493         }
496         table_lock->unlock();
497         
498         return path;
501 FrameWriterUnit* FileList::new_writer_unit(FrameWriter *writer)
503         return new FrameWriterUnit(writer);
506 int FileList::get_memory_usage()
508         int result = 0;
509         if(data) result += data->get_compressed_allocated();
510         if(temp) result += temp->get_data_size();
511         return result;
514 int FileList::get_units()
516         if(writer) return writer->get_total_clients();
517         return 0;
520 FrameWriterUnit* FileList::get_unit(int number)
522         if(writer) return (FrameWriterUnit*)writer->get_client(number);
531 FrameWriterPackage::FrameWriterPackage()
535 FrameWriterPackage::~FrameWriterPackage()
549 FrameWriterUnit::FrameWriterUnit(FrameWriter *server)
550  : LoadClient(server)
552 // Don't use server here since subclasses call this with no server.
553         this->server = server;
554         output = new VFrame;
557 FrameWriterUnit::~FrameWriterUnit()
559         delete output;
562 void FrameWriterUnit::process_package(LoadPackage *package)
564 //printf("FrameWriterUnit::process_package 1\n");
565         FrameWriterPackage *ptr = (FrameWriterPackage*)package;
567         FILE *file;
569 //printf("FrameWriterUnit::process_package 2 %s\n", ptr->path);
570         if(!(file = fopen(ptr->path, "wb")))
571         {
572                 printf("FrameWriterUnit::process_package %s: %s\n",
573                         ptr->path,
574                         strerror(errno));
575                 return;
576         }
577 //printf("FrameWriterUnit::process_package 3");
580         int result = server->file->write_frame(ptr->input, output, this);
581         
582 //printf("FrameWriterUnit::process_package 4");
583         if(!result) result = !fwrite(output->get_data(), output->get_compressed_size(), 1, file);
584 //TRACE("FrameWriterUnit::process_package 4");
585         fclose(file);
586 //TRACE("FrameWriterUnit::process_package 5");
588         server->file->add_return_value(result);
589 //TRACE("FrameWriterUnit::process_package 6");
602 FrameWriter::FrameWriter(FileList *file, int cpus)
603  : LoadServer(cpus, 0)
605         this->file = file;
609 FrameWriter::~FrameWriter()
613 void FrameWriter::init_packages()
615         for(int i = 0, layer = 0, number = 0; 
616                 i < get_total_packages(); 
617                 i++)
618         {
619                 FrameWriterPackage *package = (FrameWriterPackage*)get_package(i);
620                 package->input = frames[layer][number];
621                 package->path = file->create_path(package->input->get_number());
622 // printf("FrameWriter::init_packages 1 %d %s\n", 
623 // package->input->get_number(), 
624 // package->path);
625                 number++;
626                 if(number >= len)
627                 {
628                         layer++;
629                         number = 0;
630                 }
631         }
634 void FrameWriter::write_frames(VFrame ***frames, int len)
636         this->frames = frames;
637         this->len = len;
638         set_package_count(len * file->asset->layers);
639         
640         process_packages();
643 LoadClient* FrameWriter::new_client()
645         return file->new_writer_unit(this);
648 LoadPackage* FrameWriter::new_package()
650         return new FrameWriterPackage;