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
00057 if(wr)
00058 {
00059
00060
00061
00062
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
00075
00076
00077
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
00093 result = read_list_header();
00094 if(!result) result = read_frame_header(path_list.values[0]);
00095 }
00096 else
00097 {
00098
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
00120 data = new VFrame;
00121
00122 return result;
00123 }
00124
00125
00126 int FileList::close_file()
00127 {
00128
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
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
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
00190 do
00191 {
00192 fgets(string, BCTEXTLEN, stream);
00193 }while(!feof(stream) && (string[0] == '#' || string[0] == ' ' || isalpha(string[0])));
00194
00195
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;
00212 asset->layers = 1;
00213 asset->audio_data = 0;
00214 asset->video_data = 1;
00215
00216
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
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
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
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
00347 cmodel_transfer(frame->get_rows(),
00348 temp->get_rows(),
00349 frame->get_y(),
00350 frame->get_u(),
00351 frame->get_v(),
00352 temp->get_y(),
00353 temp->get_u(),
00354 temp->get_v(),
00355 0,
00356 0,
00357 asset->width,
00358 asset->height,
00359 0,
00360 0,
00361 asset->width,
00362 asset->height,
00363 temp->get_color_model(),
00364 frame->get_color_model(),
00365 0,
00366 temp->get_w(),
00367 frame->get_w());
00368 }
00369 }
00370
00371
00372
00373
00374
00375 return result;
00376 }
00377
00378 int FileList::write_frames(VFrame ***frames, int len)
00379 {
00380 return_value = 0;
00381
00382
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
00413 writer->write_frames(frames, len);
00414
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
00437
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
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
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
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
00571 FrameWriterPackage *ptr = (FrameWriterPackage*)package;
00572
00573 FILE *file;
00574
00575
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
00584
00585
00586 int result = server->file->write_frame(ptr->input, output, this);
00587
00588
00589 if(!result) result = !fwrite(output->get_data(), output->get_compressed_size(), 1, file);
00590
00591 fclose(file);
00592
00593
00594 server->file->add_return_value(result);
00595
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
00629
00630
00631
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