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