int main(int argc, char ** argv) { try { const std::string description = "Parallel Empirical Variogram: A massively parallel solution " "for computing empirical variograms of large-scale data."; const std::string input_desc = "Path to input file"; const std::string output_desc = "Path to output file. Defaults to stdout."; const std::string timing_desc = "Path to timing file. " "Defaults to not writing timing information."; const std::string repl_desc = "Desired replication factor. Defaults to 1."; const std::string bins_desc = "Number of distance bins to use for empirical variogram. " "Defaults to 15."; const std::string format_desc = "Prints information about output formats instead of performing computations."; // TODO: Improve input file descriptions to describe output formats TCLAP::CmdLine cmd(description, ' ', "0.1"); TCLAP::ValueArg<std::string> input_file_arg("i", "input", input_desc, true, "", "path"); TCLAP::ValueArg<std::string> output_file_arg("o", "output", output_desc, false, "", "path"); TCLAP::ValueArg<std::string> timing_file_arg("t", "timing", timing_desc, false, "", "path"); // TCLAP::ValueArg<int> repl_factor_arg("c", "replication", repl_desc, // false, 1, &positive_constraint); TCLAP::ValueArg<int> num_bins_arg("b", "bins", bins_desc, false, 15, &positive_constraint); TCLAP::SwitchArg format_arg("p", "print-formats", format_desc, false); // We only want EITHER input file or format cmd.xorAdd(input_file_arg, format_arg); cmd.add(output_file_arg); cmd.add(timing_file_arg); // cmd.add(repl_factor_arg); cmd.add(num_bins_arg); cmd.parse(argc, argv); const int num_bins = num_bins_arg.getValue(); // const int replication_factor = repl_factor_arg.getValue(); const std::string input_path = input_file_arg.getValue(); const std::string output_path = output_file_arg.getValue(); const std::string timing_path = timing_file_arg.getValue(); MPI_Init(&argc, &argv); int rank, ranks; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &ranks); if (format_arg.isSet()) { if (rank == 0) print_formats(); MPI_Finalize(); return 0; } pev::parallel_options options(ranks, 1); if (rank == 0) { std::cout << "Using " << options.active_processor_count() << " of " << ranks << " processors with replication factor " << options.replication_factor() << std::endl; } pev::variogram_data variogram = pev::empirical_variogram_parallel(input_path, num_bins); if (rank == 0) { std::ofstream outfile; if (output_file_arg.isSet()) outfile.open(output_path); // Print to stdout if output file not supplied std::ostream & out = output_file_arg.isSet() ? outfile : std::cout; pev::print_variogram(out, variogram); if (timing_file_arg.isSet()) { std::ofstream outfile; // Append to timing file if path is given if (timing_path != "-") outfile.open(timing_path, std::ios_base::out | std::ios_base::app); std::ostream & out = timing_path == "-" ? std::cout : outfile; pev::print_timing_info(out, variogram); } } MPI_Finalize(); return 0; } catch (const TCLAP::ArgException & e) { std::cerr << "ERROR: " << e.what() << " for argument " << e.argId() << std::endl; return -1; } }
int main (int argc, char *argv[]) { /* Program Option parsing */ int num_frames = 1; int threads = 1; bool disable_output = false; bool colourise_quantiser = false; bool colourise_padding = false; bool colourise_unpadded = false; bool quartersize = false; bool verbose = false; std::string input_filename; std::string output_filename; try { TCLAP::CmdLine cmd("VC2 HQ profile Decoder Example\n" "All input files must be vc2 streams\n" "All output files will be yuv422p10le\n", '=', "0.1", true); TCLAP::SwitchArg verbose_arg ("v", "verbose", "verbose mode", cmd, false); TCLAP::ValueArg<int> num_frames_arg ("n", "num-frames", "Number of frames to decode", false, 1, "integer", cmd); TCLAP::ValueArg<int> num_threads_arg ("t", "threads", "Number of threads", false, 1, "integer", cmd); TCLAP::SwitchArg disable_output_args ("d", "disable-output", "disable output", cmd, false); TCLAP::SwitchArg colourise_quantiser_args("q", "colourise-quantiser", "colourise based on quantiser levels", cmd, false); TCLAP::SwitchArg colourise_padding_args ("p", "colourise-padding", "colourise based on padding levels", cmd, false); TCLAP::SwitchArg colourise_unpadded_args ("u", "colourise-unpadded", "colourise based on lack of padding", cmd, false); TCLAP::UnlabeledValueArg<std::string> input_file_arg("input_file", "encoded input file", true, "", "string", cmd); TCLAP::UnlabeledValueArg<std::string> output_file_arg("output_file", "output file (defaults to input file + .yuv)", false, "", "string", cmd); cmd.parse( argc, argv ); num_frames = num_frames_arg.getValue(); threads = num_threads_arg.getValue(); disable_output = disable_output_args.getValue(); colourise_quantiser = colourise_quantiser_args.getValue(); colourise_padding = colourise_padding_args.getValue(); colourise_unpadded = colourise_unpadded_args.getValue(); verbose = verbose_arg.getValue(); input_filename = input_file_arg.getValue(); output_filename = output_file_arg.getValue(); } catch (TCLAP::ArgException &e) { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; return 1; } if (output_filename == "") output_filename = input_filename + ".yuv"; /* Variables for storing input and output buffers */ char *idata; size_t input_length = 0; uint16_t **odata = new uint16_t*[num_frames]; // Output frame pointers uint16_t ***opics = new uint16_t**[num_frames*2]; // Output picture pointers (which may be different for interlaced sequences) for (int i = 0; i < num_frames * 2; i++) { opics[i] = new uint16_t*[3]; } int ostride[3]; int num_frames_decoded_from_sequence = 0; int total_frames_decoded = 0; /* Initialise decoder */ vc2decode_init(); VC2DecoderHandle decoder = vc2decode_create(); /* Configure decoder */ { VC2DecoderParamsUser params; memset((void *)¶ms, 0, sizeof(params)); params.threads = threads; params.colourise_quantiser = colourise_quantiser; params.colourise_padding = colourise_padding; params.colourise_unpadded = colourise_unpadded; /* QuarterSize is only really sensible for HD */ if (quartersize) { params.partial_decode = true; params.partial_decode_width = 1920/2; params.partial_decode_height = 1080/2; params.partial_decode_offset_x = 0; params.partial_decode_offset_y = 540; } { VC2DecoderResult r = vc2decode_set_parameters(decoder, params); if (r != VC2DECODER_OK) { printf("Parameter Error: %d\n", r); return 1; } } } /* Read input data */ { FILE *f = FOPEN(input_filename.c_str(), "rb"); if (!f) { fprintf(stderr, "Could not open: %s\n", input_filename.c_str()); perror("Invalid input file: "); return 1; } int r = fseek(f, 0L, SEEK_END); if (r < 0) { perror("Error seeking in input file"); return 1; } input_length = ftell(f); rewind(f); idata = (char *)malloc(input_length); size_t s = fread(idata, 1, input_length, f); if (s != input_length) { if (ferror(f)) fprintf(stderr, "Error reading file\n"); else fprintf(stderr, "Improper Length on Input File\n"); return 1; } fclose(f); printf("Read %lubytes of input data\n", input_length); } /* Set the output fmt to something invalid to start with */ VC2DecoderOutputFormat fmt; fmt.width = 0; fmt.height = 0; fmt.signal_range = 0; fmt.source_sampling = 0; fmt.frame_rate_numer = 0; fmt.frame_rate_denom = 0; fmt.interlaced = 0; ostride[0] = 0; ostride[1] = 0; ostride[2] = 0; for (int i = 0; i < num_frames; i++) { odata[i] = NULL; } /* Begin the main program loop */ int err = 0; uint64_t time_taken = 0; while (total_frames_decoded < num_frames) { VC2DecoderResult r; /* Reset to the start of the input data */ char *id = idata; char *iend = idata + input_length; /* We are at the start of a sequence, so synchronise */ r = vc2decode_synchronise(decoder, &id, iend - id, true); if (r != VC2DECODER_OK_RECONFIGURED) { fprintf(stderr, "Error synchronising to sequence"); err = 1; break; } /* We have synchronised, so get the output format */ VC2DecoderOutputFormat new_fmt; r = vc2decode_get_output_format(decoder, &new_fmt); if (r != VC2DECODER_OK) { fprintf(stderr, "Output format error: %d\n", r); err = 1; break; } /* Reconfigure output buffers if this format doesn't match the current one */ if (fmt.width != new_fmt.width || fmt.height != new_fmt.height || fmt.interlaced != new_fmt.interlaced) { fmt = new_fmt; for (int i = 0; i < num_frames; i++) { if (odata[i]) free(odata[i]); odata[i] = (uint16_t *)malloc(fmt.width*fmt.height*2*sizeof(uint16_t)); } if (fmt.interlaced) { ostride[0] = fmt.width*2; ostride[1] = fmt.width; ostride[2] = fmt.width; for (int i = 0; i < num_frames; i++) { opics[2*i + 0][0] = odata[i]; opics[2*i + 0][1] = odata[i] + fmt.width*fmt.height; opics[2*i + 0][2] = odata[i] + fmt.width*fmt.height + fmt.width*fmt.height/2; opics[2*i + 1][0] = odata[i] + fmt.width; opics[2*i + 1][1] = odata[i] + fmt.width*fmt.height + fmt.width/2; opics[2*i + 1][2] = odata[i] + fmt.width*fmt.height + fmt.width*fmt.height/2 + fmt.width/2; } } else { ostride[0] = fmt.width; ostride[1] = fmt.width/2; ostride[2] = fmt.width/2; for (int i = 0; i < num_frames; i++) { opics[i][0] = odata[i]; opics[i][1] = odata[i] + fmt.width*fmt.height; opics[i][2] = odata[i] + fmt.width*fmt.height + fmt.width*fmt.height/2; } } } /* Decode Pictures from stream */ int picture = 0; struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); while (total_frames_decoded < num_frames) { r = vc2decode_decode_one_picture(decoder, &id, iend - id, opics[picture], ostride, true); /* If End of Sequence break from loop */ if (r == VC2DECODER_OK_EOS) { break; } /* If a picture has been sucessfully decoded continue */ if (r == VC2DECODER_OK_PICTURE) { if (!fmt.interlaced || (picture%2)) total_frames_decoded++; picture++; if (id == NULL) { fprintf(stderr, "Premature end of stream\n"); break; } continue; } /* If a reconfiguration has been triggered this is an invalid sequence, flag that */ if (r == VC2DECODER_OK_RECONFIGURED) { fprintf(stderr, "Warning: this sequence changes parameters part way through\n"); break; } /* Otherwise we have an error */ if (r < 0) { fprintf(stderr, "Error decoding:\n"); fprintf(stderr, " %s\n", VC2DecoderErrorString[-r]); err=1; break; } fprintf(stderr, "Unknown Return value: %d\n", r); break; } clock_gettime(CLOCK_MONOTONIC, &end); /* We have reached the end of a sequence, or have decoded enough frames */ /*If an error has occurred bail */ if (err) break; /*If no pictures were decoded bail */ if (picture == 0) { fprintf(stderr, "No pictures in sequence!\n"); err = 1; break; } /* Otherwise update the record of how many decoded frames have been recorded */ int num_frames_decoded_from_this_sequence = (fmt.interlaced)?(picture/2):(picture); if (num_frames_decoded_from_this_sequence > num_frames_decoded_from_sequence) num_frames_decoded_from_sequence = num_frames_decoded_from_this_sequence; /* And update the record of time taken to decode */ time_taken += (end.tv_sec*1000000000 + end.tv_nsec) - (start.tv_sec*1000000000 + start.tv_nsec); } /* If there has been no error print the speed */ if (!err) { printf("--------------------------------------------------\n"); printf(" %d frames decoded in %5.3fs\n", total_frames_decoded, time_taken/1000000000.0); printf(" %5.3ffps\n", total_frames_decoded*1000000000.0/time_taken); printf("--------------------------------------------------\n"); } /* If there has been no error get decoder statistics */ if (!err) { VC2DecoderSequenceInfo info; vc2decode_sequence_info(decoder, &info); print_sequence_info(info, verbose); } /* If there is no error and output is enabled write the output to a file This code actually performs an endianess swap and some bit shifting on the output data to put it into the desired format (10-bit data in the high order bits of 16-bit words in network byte order). */ if (!err && !disable_output) { try { FILE *of = FOPEN(output_filename.c_str(), "wb"); for (int i = 0; i < num_frames_decoded_from_sequence; i++) { for (int y = 0; y < fmt.height; y++) { size_t s = fwrite(&odata[i][(y*fmt.width)], 1, fmt.width*sizeof(uint16_t), of); if (s != fmt.width*sizeof(uint16_t)) throw std::runtime_error("Writing Error"); } for (int y = 0; y < fmt.height*2; y++) { size_t s = fwrite(&odata[i][(fmt.height*fmt.width + y*fmt.width/2)], 1, fmt.width/2*sizeof(uint16_t), of); if (s != fmt.width/2*sizeof(uint16_t)) throw std::runtime_error("Writing Error"); } } printf("Wrote out %d frames\n", num_frames_decoded_from_sequence); fclose(of); } catch(...) { fprintf(stderr, "Error writing output\n"); err = 1; } } /* Destroy the decoder */ vc2decode_destroy(decoder); /* Deallocate buffers */ free(idata); for (int i = 0; i < num_frames; i++) if (odata[i]) free(odata[i]); delete[] odata; for (int i = 0; i < num_frames * 2; i++) delete[] opics[i]; delete[] opics; return err; }