Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

filelist.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "file.h"
00004 #include "filelist.h"
00005 #include "guicast.h"
00006 #include "interlacemodes.h"
00007 #include "mwindow.inc"
00008 #include "render.h"
00009 #include "renderfarmfsserver.inc"
00010 #include "vframe.h"
00011 
00012 #include <ctype.h>
00013 #include <errno.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <sys/stat.h>
00017 
00018 
00019 FileList::FileList(Asset *asset, 
00020         File *file, 
00021         char *list_prefix,
00022         char *file_extension, 
00023         int frame_type,
00024         int list_type)
00025  : FileBase(asset, file)
00026 {
00027         reset_parameters();
00028         asset->video_data = 1;
00029         this->list_prefix = list_prefix;
00030         this->file_extension = file_extension;
00031         this->frame_type = frame_type;
00032         this->list_type = list_type;
00033         table_lock = new Mutex("FileList::table_lock");
00034 }
00035 
00036 FileList::~FileList()
00037 {
00038         close_file();
00039         delete table_lock;
00040 }
00041 
00042 int FileList::reset_parameters_derived()
00043 {
00044         data = 0;
00045         writer = 0;
00046         temp = 0;
00047         first_number = 0;
00048 }
00049 
00050 int FileList::open_file(int rd, int wr)
00051 {
00052         this->rd = rd;
00053         this->wr = wr;
00054         int result = 0;
00055 
00056 // skip header for write
00057         if(wr)
00058         {
00059 // Frame files are created in write_frame and list index is created when
00060 // file is closed.
00061 // Look for the starting number in the path but ignore the starting character
00062 // and total digits since these are used by the header.
00063                 Render::get_starting_number(asset->path, 
00064                         first_number,
00065                         number_start, 
00066                         number_digits);
00067                 path_list.remove_all_objects();
00068                 writer = new FrameWriter(this, 
00069                         asset->format == list_type ? file->cpus : 1);
00070         }
00071         else
00072         if(rd)
00073         {
00074 // Determine type of file.
00075 // Header isn't used for background rendering, in which case everything known
00076 // by the file encoder is known by the decoder.
00077 //printf("FileList::open_file 1 %d\n", asset->use_header);
00078                 if(asset->use_header)
00079                 {
00080                         FILE *stream = fopen(asset->path, "rb");
00081                         if(stream)
00082                         {
00083                                 char string[BCTEXTLEN];
00084                                 fread(string, strlen(list_prefix), 1, stream);
00085                                 fclose(stream);
00086 
00087                                 if(!strncasecmp(string, list_prefix, strlen(list_prefix)))
00088                                 {
00089 
00090                                         asset->format = list_type;
00091 
00092 // Open index here or get frame size from file.
00093                                         result = read_list_header();
00094                                         if(!result) result = read_frame_header(path_list.values[0]);
00095                                 }
00096                                 else
00097                                 {
00098 //printf("FileList::open_file 2\n", asset->use_header);
00099                                         asset->format = frame_type;
00100                                         result = read_frame_header(asset->path);
00101                                         asset->layers = 1;
00102                                         if(!asset->frame_rate)
00103                                                 asset->frame_rate = 1;
00104                                         asset->video_length = -1;
00105                                 }
00106                         }
00107                 }
00108                 else
00109                 {
00110                         Render::get_starting_number(asset->path, 
00111                                 first_number,
00112                                 number_start, 
00113                                 number_digits,
00114                                 6);
00115                 }
00116         }
00117 
00118         file->current_frame = 0;
00119 // Compressed data storage
00120         data = new VFrame;
00121 
00122         return result;
00123 }
00124 
00125 
00126 int FileList::close_file()
00127 {
00128 //      path_list.total, asset->format, list_type, wr);
00129         if(asset->format == list_type && path_list.total)
00130         {
00131                 if(wr && asset->use_header) write_list_header();
00132                 path_list.remove_all_objects();
00133         }
00134         if(data) delete data;
00135         if(writer) delete writer;
00136         if(temp) delete temp;
00137         reset_parameters();
00138 
00139         FileBase::close_file();
00140         return 0;
00141 }
00142 
00143 int FileList::write_list_header()
00144 {
00145         FILE *stream = fopen(asset->path, "w");
00146 // Use sprintf instead of fprintf for VFS.
00147         char string[BCTEXTLEN];
00148         sprintf(string, "%s\n", list_prefix);
00149         fwrite(string, strlen(string), 1, stream);
00150         sprintf(string, "# First line is always %s\n", list_prefix);
00151         fwrite(string, strlen(string), 1, stream);
00152         sprintf(string, "# Frame rate:\n");
00153         fwrite(string, strlen(string), 1, stream);
00154         sprintf(string, "%f\n", asset->frame_rate);
00155         fwrite(string, strlen(string), 1, stream);
00156         sprintf(string, "# Width:\n");
00157         fwrite(string, strlen(string), 1, stream);
00158         sprintf(string, "%d\n", asset->width);
00159         fwrite(string, strlen(string), 1, stream);
00160         sprintf(string, "# Height:\n");
00161         fwrite(string, strlen(string), 1, stream);
00162         sprintf(string, "%d\n", asset->height);
00163         fwrite(string, strlen(string), 1, stream);
00164         sprintf(string, "# List of image files follows\n");
00165         fwrite(string, strlen(string), 1, stream);
00166 
00167         for(int i = 0; i < path_list.total; i++)
00168         {
00169 // Fix path for VFS but leave leading slash
00170                 if(!strncmp(path_list.values[i], RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
00171                         sprintf(string, "%s\n", path_list.values[i] + strlen(RENDERFARM_FS_PREFIX));
00172                 else
00173                         sprintf(string, "%s\n", path_list.values[i]);
00174                 fwrite(string, strlen(string), 1, stream);
00175         }
00176         fclose(stream);
00177         return 0;
00178 }
00179 
00180 int FileList::read_list_header()
00181 {
00182         char string[BCTEXTLEN], *new_entry;
00183 
00184         FILE *stream = fopen(asset->path, "r");
00185         
00186         
00187         if(stream)
00188         {
00189 // Get information about the frames
00190                 do
00191                 {
00192                         fgets(string, BCTEXTLEN, stream);
00193                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' ' || isalpha(string[0])));
00194 
00195 // Don't want a user configured frame rate to get destroyed
00196                 if(asset->frame_rate == 0)
00197                         asset->frame_rate = atof(string);
00198 
00199                 do
00200                 {
00201                         fgets(string, BCTEXTLEN, stream);
00202                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
00203                 asset->width = atol(string);
00204 
00205                 do
00206                 {
00207                         fgets(string, BCTEXTLEN, stream);
00208                 }while(!feof(stream) && (string[0] == '#' || string[0] == ' '));
00209                 asset->height = atol(string);
00210 
00211                 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED;  // May be good to store the info in the list?
00212                 asset->layers = 1;
00213                 asset->audio_data = 0;
00214                 asset->video_data = 1;
00215 
00216 // Get all the paths
00217                 while(!feof(stream))
00218                 {
00219                         fgets(string, BCTEXTLEN, stream);
00220                         if(strlen(string) && string[0] != '#' && string[0] != ' ' && !feof(stream))
00221                         {
00222                                 string[strlen(string) - 1] = 0;
00223                                 path_list.append(new_entry = new char[strlen(string) + 1]);
00224                                 strcpy(new_entry, string);
00225                         }
00226                 }
00227 
00228 //for(int i = 0; i < path_list.total; i++) printf("%s\n", path_list.values[i]);
00229                 fclose(stream);
00230                 asset->video_length = path_list.total;
00231         }
00232         else
00233                 return 1;
00234 
00235         return 0;
00236 }
00237 
00238 int FileList::read_frame(VFrame *frame)
00239 {
00240         int result = 0;
00241         if(file->current_frame < 0 || 
00242                 (asset->use_header && file->current_frame >= path_list.total &&
00243                         asset->format == list_type))
00244                 return 1;
00245 
00246         if(asset->format == list_type)
00247         {
00248                 char string[BCTEXTLEN];
00249                 char *path;
00250                 if(asset->use_header)
00251                 {
00252                         path = path_list.values[file->current_frame];
00253                 }
00254                 else
00255                 {
00256                         path = calculate_path(file->current_frame, string);
00257                 }
00258                 FILE *in;
00259 
00260 
00261 // Fix path for VFS
00262                 if(!strncmp(asset->path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
00263                         sprintf(string, "%s%s", RENDERFARM_FS_PREFIX, path);
00264                 else
00265                         strcpy(string, path);
00266 
00267                 if(!(in = fopen(string, "rb")))
00268                 {
00269                         fprintf(stderr, "FileList::read_frame %s: %s\n", string, strerror(errno));
00270                 }
00271                 else
00272                 {
00273                         struct stat ostat;
00274                         stat(string, &ostat);
00275 
00276                         switch(frame->get_color_model())
00277                         {
00278                                 case BC_COMPRESSED:
00279                                         frame->allocate_compressed_data(ostat.st_size);
00280                                         frame->set_compressed_size(ostat.st_size);
00281                                         fread(frame->get_data(), ostat.st_size, 1, in);
00282                                         break;
00283                                 default:
00284                                         data->allocate_compressed_data(ostat.st_size);
00285                                         data->set_compressed_size(ostat.st_size);
00286                                         fread(data->get_data(), ostat.st_size, 1, in);
00287                                         result = read_frame(frame, data);
00288                                         break;
00289                         }
00290 
00291 
00292                         fclose(in);
00293                 }
00294         }
00295         else
00296         {
00297 
00298 // Allocate and decompress once into temporary
00299                 if(!temp || temp->get_color_model() != frame->get_color_model())
00300                 {
00301                         if(temp) delete temp;
00302                         temp = 0;
00303                 
00304                         FILE *fd = fopen(asset->path, "rb");
00305                         if(fd)
00306                         {
00307                                 struct stat ostat;
00308                                 stat(asset->path, &ostat);
00309 
00310                                 switch(frame->get_color_model())
00311                                 {
00312                                         case BC_COMPRESSED:
00313                                                 frame->allocate_compressed_data(ostat.st_size);
00314                                                 frame->set_compressed_size(ostat.st_size);
00315                                                 fread(frame->get_data(), ostat.st_size, 1, fd);
00316                                                 break;
00317                                         default:
00318                                                 data->allocate_compressed_data(ostat.st_size);
00319                                                 data->set_compressed_size(ostat.st_size);
00320                                                 fread(data->get_data(), ostat.st_size, 1, fd);
00321                                                 temp = new VFrame(0, 
00322                                                         asset->width, 
00323                                                         asset->height, 
00324                                                         frame->get_color_model());
00325                                                 read_frame(temp, data);
00326                                                 break;
00327                                 }
00328 
00329                                 fclose(fd);
00330                         }
00331                         else
00332                         {
00333                                 fprintf(stderr, "FileList::read_frame %s: %s\n", asset->path, strerror(errno));
00334                                 result = 1;
00335                         }
00336                 }
00337 
00338                 if(!temp) return result;
00339 
00340                 if(frame->get_color_model() == temp->get_color_model())
00341                 {
00342                         frame->copy_from(temp);
00343                 }
00344                 else
00345                 {
00346 // Never happens
00347                         cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */
00348                                 temp->get_rows(),
00349                                 frame->get_y(), /* Leave NULL if non existent */
00350                                 frame->get_u(),
00351                                 frame->get_v(),
00352                                 temp->get_y(), /* Leave NULL if non existent */
00353                                 temp->get_u(),
00354                                 temp->get_v(),
00355                                 0,        /* Dimensions to capture from input frame */
00356                                 0, 
00357                                 asset->width, 
00358                                 asset->height,
00359                                 0,       /* Dimensions to project on output frame */
00360                                 0, 
00361                                 asset->width, 
00362                                 asset->height,
00363                                 temp->get_color_model(), 
00364                                 frame->get_color_model(),
00365                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
00366                                 temp->get_w(),       /* For planar use the luma rowspan */
00367                                 frame->get_w());
00368                 }
00369         }
00370 
00371 
00372 //printf("FileList::read_frame 5 %d\n", result);
00373 
00374 
00375         return result;
00376 }
00377 
00378 int FileList::write_frames(VFrame ***frames, int len)
00379 {
00380         return_value = 0;
00381 
00382 //printf("FileList::write_frames 1\n");
00383         if(frames[0][0]->get_color_model() == BC_COMPRESSED)
00384         {
00385                 for(int i = 0; i < asset->layers && !return_value; i++)
00386                 {
00387                         for(int j = 0; j < len && !return_value; j++)
00388                         {
00389                                 VFrame *frame = frames[i][j];
00390                                 char *path = create_path(frame->get_number());
00391 
00392                                 FILE *fd = fopen(path, "wb");
00393                                 if(fd)
00394                                 {
00395                                         return_value = !fwrite(frames[i][j]->get_data(),
00396                                                 frames[i][j]->get_compressed_size(),
00397                                                 1,
00398                                                 fd);
00399 
00400                                         fclose(fd);
00401                                 }
00402                                 else
00403                                 {
00404                                         printf("FileList::write_frames %s: %s\n", path, strerror(errno));
00405                                         return_value++;
00406                                 }
00407                         }
00408                 }
00409         }
00410         else
00411         {
00412 //printf("FileList::write_frames 2\n");
00413                 writer->write_frames(frames, len);
00414 //printf("FileList::write_frames 100\n");
00415         }
00416         return return_value;
00417 }
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 void FileList::add_return_value(int amount)
00428 {
00429         table_lock->lock("FileList::add_return_value");
00430         return_value += amount;
00431         table_lock->unlock();
00432 }
00433 
00434 char* FileList::calculate_path(int number, char *string)
00435 {
00436 // Synthesize filename.
00437 // If a header is used, the filename number must be in a different location.
00438         if(asset->use_header)
00439         {
00440                 int k;
00441                 strcpy(string, asset->path);
00442                 for(k = strlen(string) - 1; k > 0 && string[k] != '.'; k--)
00443                         ;
00444                 if(k <= 0) k = strlen(string);
00445 
00446                 sprintf(&string[k], "%06d%s", 
00447                         number, 
00448                         file_extension);
00449         }
00450         else
00451 // Without a header, the original filename can be altered.
00452         {
00453                 Render::create_filename(string, 
00454                         asset->path, 
00455                         number,
00456                         number_digits,
00457                         number_start);
00458         }
00459 
00460         return string;
00461 }
00462 
00463 char* FileList::create_path(int number_override)
00464 {
00465         if(asset->format != list_type) return asset->path;
00466 
00467         table_lock->lock("FileList::create_path");
00468 
00469 
00470 
00471         char *path = "";
00472         char output[BCTEXTLEN];
00473         if(file->current_frame >= path_list.total || !asset->use_header)
00474         {
00475                 int number;
00476                 if(number_override < 0)
00477                         number = file->current_frame++;
00478                 else
00479                 {
00480                         number = number_override;
00481                         file->current_frame++;
00482                 }
00483 
00484                 if(!asset->use_header)
00485                 {
00486                         number += first_number;
00487                 }
00488 
00489                 calculate_path(number, output);
00490 
00491                 path = new char[strlen(output) + 1];
00492                 strcpy(path, output);
00493                 path_list.append(path);
00494         }
00495         else
00496         {
00497 // Overwrite an old path
00498                 path = path_list.values[file->current_frame];
00499         }
00500 
00501 
00502         table_lock->unlock();
00503         
00504         return path;
00505 }
00506 
00507 FrameWriterUnit* FileList::new_writer_unit(FrameWriter *writer)
00508 {
00509         return new FrameWriterUnit(writer);
00510 }
00511 
00512 int FileList::get_memory_usage()
00513 {
00514         int result = 0;
00515         if(data) result += data->get_compressed_allocated();
00516         if(temp) result += temp->get_data_size();
00517         return result;
00518 }
00519 
00520 int FileList::get_units()
00521 {
00522         if(writer) return writer->get_total_clients();
00523         return 0;
00524 }
00525 
00526 FrameWriterUnit* FileList::get_unit(int number)
00527 {
00528         if(writer) return (FrameWriterUnit*)writer->get_client(number);
00529 }
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 FrameWriterPackage::FrameWriterPackage()
00538 {
00539 }
00540 
00541 FrameWriterPackage::~FrameWriterPackage()
00542 {
00543 }
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 FrameWriterUnit::FrameWriterUnit(FrameWriter *server)
00556  : LoadClient(server)
00557 {
00558 // Don't use server here since subclasses call this with no server.
00559         this->server = server;
00560         output = new VFrame;
00561 }
00562 
00563 FrameWriterUnit::~FrameWriterUnit()
00564 {
00565         delete output;
00566 }
00567 
00568 void FrameWriterUnit::process_package(LoadPackage *package)
00569 {
00570 //printf("FrameWriterUnit::process_package 1\n");
00571         FrameWriterPackage *ptr = (FrameWriterPackage*)package;
00572 
00573         FILE *file;
00574 
00575 //printf("FrameWriterUnit::process_package 2 %s\n", ptr->path);
00576         if(!(file = fopen(ptr->path, "wb")))
00577         {
00578                 printf("FrameWriterUnit::process_package %s: %s\n",
00579                         ptr->path,
00580                         strerror(errno));
00581                 return;
00582         }
00583 //printf("FrameWriterUnit::process_package 3");
00584 
00585 
00586         int result = server->file->write_frame(ptr->input, output, this);
00587         
00588 //printf("FrameWriterUnit::process_package 4");
00589         if(!result) result = !fwrite(output->get_data(), output->get_compressed_size(), 1, file);
00590 //TRACE("FrameWriterUnit::process_package 4");
00591         fclose(file);
00592 //TRACE("FrameWriterUnit::process_package 5");
00593 
00594         server->file->add_return_value(result);
00595 //TRACE("FrameWriterUnit::process_package 6");
00596 }
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 FrameWriter::FrameWriter(FileList *file, int cpus)
00609  : LoadServer(cpus, 0)
00610 {
00611         this->file = file;
00612 }
00613 
00614 
00615 FrameWriter::~FrameWriter()
00616 {
00617 }
00618 
00619 void FrameWriter::init_packages()
00620 {
00621         for(int i = 0, layer = 0, number = 0; 
00622                 i < get_total_packages(); 
00623                 i++)
00624         {
00625                 FrameWriterPackage *package = (FrameWriterPackage*)get_package(i);
00626                 package->input = frames[layer][number];
00627                 package->path = file->create_path(package->input->get_number());
00628 // printf("FrameWriter::init_packages 1 %p %d %s\n", 
00629 // package->input,
00630 // package->input->get_number(), 
00631 // package->path);
00632                 number++;
00633                 if(number >= len)
00634                 {
00635                         layer++;
00636                         number = 0;
00637                 }
00638         }
00639 }
00640 
00641 void FrameWriter::write_frames(VFrame ***frames, int len)
00642 {
00643         this->frames = frames;
00644         this->len = len;
00645         set_package_count(len * file->asset->layers);
00646         
00647         process_packages();
00648 }
00649 
00650 LoadClient* FrameWriter::new_client()
00651 {
00652         return file->new_writer_unit(this);
00653 }
00654 
00655 LoadPackage* FrameWriter::new_package()
00656 {
00657         return new FrameWriterPackage;
00658 }
00659 
00660 
00661 

Generated on Sun Jan 8 13:38:54 2006 for Cinelerra-svn by  doxygen 1.4.4