/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2023, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SubpicMergeMain.cpp \brief Subpicture merge main function and command line handling */ #include #include #include #include #include #include #include #include #include #include "Utilities/program_options_lite.h" #include "SubpicMergeApp.h" namespace po = df::program_options_lite; //! \ingroup SubpicMergeApp //! \{ /** - Parse file name of an input bitstream or a YUV file */ void getSubpicFilename(std::istringstream &iss, std::string &fname) { char currChar; while (iss.get(currChar) && isspace(currChar)) { } if (currChar == '\"') // Is file name delimited by quotes? { while (iss.get(currChar) && (currChar != '\"')) { fname.append((size_t)1, currChar); } } else // Nn quote found - assume no whitespaces in file name { do { fname.append((size_t)1, currChar); } while (iss.get(currChar) && !isspace(currChar)); } } /** - Parse subpic list file containing all subpictures to be merged */ bool parseSubpicListFile(const char *filename, std::vector &subpics) { std::ifstream confFile; confFile.open(filename); if (!confFile.is_open()) { std::cerr << "Error: cannot open subpic list file " << filename << " for reading" << std::endl; return false; } std::string line; while (std::getline(confFile, line)) { if (line.at(0) != '#') // Lines beginning with # are ignored { std::istringstream iss(line); std::string bitstreamFilename; subpics.emplace_back(); SubpicParams &sf = subpics.back(); if (!(iss >> sf.width >> sf.height >> sf.topLeftCornerX >> sf.topLeftCornerY)) { std::cerr << "Error: subpic list file has incorrect formatting" << std::endl; return false; } getSubpicFilename(iss, bitstreamFilename); sf.fp.open(bitstreamFilename, std::ios_base::binary); if (!sf.fp.is_open()) { std::cerr << "Error: cannot open input file " << bitstreamFilename << " for reading" << std::endl; return false; } } } return true; } /** - Parse command line parameters */ bool parseCmdLine(int argc, char* argv[], std::vector &subpics, std::ofstream &outputStream, bool &yuvMerge, int &yuvBitdepth, int &yuvChromaFormat, bool &mixedNaluFlag) { bool doHelp = false; std::string subpicListFile; std::string outFile; po::Options opts; opts.addOptions() ("-help", doHelp, false, "This help text") ("l", subpicListFile, std::string(""), "File containing list of input pictures to be merged") ("o", outFile, std::string(""), "Output file name") ("m", mixedNaluFlag, false, "Enable mixed NALU type bitstreams merging") ("-yuv", yuvMerge, false, "Perform YUV merging (instead of bitstream merging)") ("d", yuvBitdepth, 0, "Bitdepth for YUV merging") ("f", yuvChromaFormat, 420, "Chroma format for YUV merging, 420 (default), 400, 422 or 444") ; po::setDefaults(opts); po::ErrorReporter err; const std::list& argvUnhandled = po::scanArgv(opts, argc, (const char**) argv, err); if (argc == 1 || doHelp) { /* argc == 1: no options have been specified */ po::doHelp(std::cout, opts); std::cout << std::endl; std::cout << "Examples" << std::endl; std::cout << " Merge VVC bitstreams:" << std::endl; std::cout << " SubpicMergeApp -l subpic_list.txt -o merged_stream.bin" << std::endl; std::cout << " Merge YUV files (10-bit):" << std::endl; std::cout << " SubpicMergeApp -yuv 1 -d 10 -l subpic_list_yuv.txt -o merged_yuv.yuv" << std::endl; std::cout << std::endl; std::cout << "Subpic list file contains list of subpics to be merged, one line for each subpicture. Format of a line in subpic list file is given below. Unit of subpic dimensions is one luma sample. Input file is either bitstream file or YUV file depending on the -yuv option." << std::endl; std::cout << std::endl; std::cout << " subpic_width subpic_height subpic_x_pos subpic_y_pos subpic_input_file_name" << std::endl; std::cout << std::endl; return false; } if (yuvChromaFormat != 400 && yuvChromaFormat != 420 && yuvChromaFormat != 422 && yuvChromaFormat != 444 ) { std::cerr << "Illegal chroma format: " << yuvChromaFormat << std::endl; return false; } for (std::list::const_iterator it = argvUnhandled.begin(); it != argvUnhandled.end(); it++) { std::cerr << "Unhandled argument ignored: `" << *it << "'" << std::endl; } if (!parseSubpicListFile(subpicListFile.c_str(), subpics)) { return false; } if (subpics.empty()) { std::cerr << "Error: subpic list file does not define valid subpictures" << std::endl; return false; } outputStream.open(outFile, std::ios_base::binary); if (!outputStream.is_open()) { std::cerr << "Error: cannot open output file " << outFile << " for writing" << std::endl; return false; } return true; } /** - Subpicture merge main() */ int main(int argc, char* argv[]) { std::vector subpics; std::ofstream outputStream; bool yuvMerge = false; int yuvBitdepth = -1; int yuvChromaFormat = -1; bool mixedNaluFlag = false; if (!parseCmdLine(argc, argv, subpics, outputStream, yuvMerge, yuvBitdepth, yuvChromaFormat, mixedNaluFlag)) { return 1; } SubpicMergeApp *subpicMergeApp = new SubpicMergeApp(subpics, outputStream); if (!yuvMerge) { subpicMergeApp->mergeStreams(mixedNaluFlag); } else { subpicMergeApp->mergeYuvFiles(yuvBitdepth, yuvChromaFormat); } delete subpicMergeApp; return 0; } //! \}