| /* |
| * Copyright 2020 Google LLC |
| * |
| */ |
| |
| /* |
| * Copyright (c) 2020, Alliance for Open Media. All rights reserved |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <vector> |
| #include <list> |
| #include <string> |
| #include <fstream> |
| #include <sstream> |
| #include <chrono> |
| #include <thread> |
| #include <set> |
| |
| #include "common\log.h" |
| #include "cmd_parser.h" |
| #include "decoder.h" |
| #include "aom/aom.h" |
| #include "aom/aom_decoder.h" |
| |
| #include "common/stream_reader.h" |
| #include "decoder_creator.h" |
| |
| #if (WINAPI_FAMILY == WINAPI_FAMILY_APP) |
| using namespace Platform; |
| using namespace Windows::Foundation; |
| using namespace Windows::Foundation::Collections; |
| using namespace Windows::Storage::Streams; |
| |
| using namespace Windows::Storage; |
| using namespace Platform; |
| #endif |
| |
| extern "C" void usage_exit(void) { exit(EXIT_FAILURE); } |
| |
| #define ERR_DESC(x) \ |
| { x, #x } |
| struct error_decript { |
| int err; |
| const char* err_string; |
| }; |
| const error_decript error_decripts[] = {ERR_DESC(AOM_CODEC_OK), |
| ERR_DESC(AOM_CODEC_ERROR), |
| ERR_DESC(AOM_CODEC_MEM_ERROR), |
| ERR_DESC(AOM_CODEC_ABI_MISMATCH), |
| ERR_DESC(AOM_CODEC_INCAPABLE), |
| ERR_DESC(AOM_CODEC_UNSUP_BITSTREAM), |
| ERR_DESC(AOM_CODEC_CORRUPT_FRAME), |
| ERR_DESC(AOM_CODEC_INVALID_PARAM), |
| ERR_DESC(AOM_CODEC_UNSUP_FEATURE)}; |
| const int errors_size = sizeof(error_decripts) / sizeof(error_decript); |
| |
| #if (WINAPI_FAMILY == WINAPI_FAMILY_APP) |
| static std::string pstos(Platform::String ^ ps) { |
| std::string s; |
| std::wstring ws(ps->Data()); |
| s.assign(ws.begin(), ws.end()); |
| return s; |
| } |
| #endif |
| |
| const char* GetVpxErrorString(int err) { |
| for (int i = 0; i < errors_size; i++) { |
| if (error_decripts[i].err == err) return error_decripts[i].err_string; |
| } |
| return "Unspecified error"; |
| } |
| |
| static void parse_file(const std::string& str, std::vector<one_task>& list) { |
| std::ifstream input(str.c_str()); |
| if (input.is_open()) { |
| std::string line; |
| |
| while (std::getline(input, line)) { |
| if (line[0] == '#') continue; |
| std::string ss; |
| int brace_is_open = 0; |
| list.push_back(one_task(line)); |
| std::vector<std::string>& current = list.back(); |
| for (int i = 0; i < line.length(); i++) { |
| int s = line[i]; |
| if (s == '\"') { |
| if (brace_is_open) { |
| if (ss.length()) current.push_back(ss); |
| ss = ""; |
| brace_is_open = 0; |
| continue; |
| } else { |
| brace_is_open = 1; |
| continue; |
| } |
| } |
| if (isspace(s) && !brace_is_open) { |
| if (ss.length()) current.push_back(ss); |
| ss = ""; |
| continue; |
| } |
| ss += (char)s; |
| } |
| if (ss.length()) current.push_back(ss); |
| } |
| } else { |
| XB_LOGE << "Invalid file path '" << str.c_str() << "'"; |
| } |
| } |
| |
| int Decoders::process_directory(CParameters& params) { |
| XB_LOGI << "#######################################"; |
| XB_LOGI << "# Process directory " << params.GetParams().source_dir_; |
| XB_LOGI << "#######################################"; |
| std::vector<std::string> names; |
| std::string search_path = /*read_path_ + "\\" +*/ params.GetParams().source_dir_ + "\\*.*"; |
| WIN32_FIND_DATAA fd; |
| HANDLE hFind = ::FindFirstFileA(search_path.c_str(), &fd); |
| if (hFind != INVALID_HANDLE_VALUE) { |
| do { |
| // read all (real) files in current folder |
| // , delete '!' read other 2 default folder . and .. |
| if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { |
| std::string str(fd.cFileName); |
| if (str.substr(str.length() - 4, 4) == ".ivf" || str.substr(str.length() - 4, 4) == ".av1" || |
| str.substr(str.length() - 5, 5) == ".webm" || str.substr(str.length() - 4, 4) == ".obu" || |
| str.substr(str.length() - 4, 4) == ".mp4") |
| names.push_back(str); |
| } |
| } while (::FindNextFileA(hFind, &fd)); |
| ::FindClose(hFind); |
| } |
| for (std::vector<std::string>::iterator iter = names.begin(); iter != names.end() && !stop_; iter++) { |
| std::string path(params.GetParams().source_dir_); |
| if (path.substr(path.length() - 1, 1) != "\\" || path.substr(path.length() - 1, 1) != "/") path += "\\"; |
| params.GetParamsPtr()->bad_conform_file_ = params.GetParams().bad_conform_dir_ + *iter; |
| path += *iter; |
| XB_LOGD << "Create decoder for " << params.GetParams().source_file_.c_str(); |
| params.GetParamsPtr()->source_file_ = path; |
| decoder_->Start(¶ms); |
| decoder_->WaitForFinish(); |
| } |
| return 0; |
| } |
| |
| Decoders::Decoders(int is_xbox, d3d_resources dx_resources, DisplayCallbacks* display, const char* root_path) |
| : is_xbox_(is_xbox), dx_resources_(dx_resources), display_(display), root_path_(root_path ? root_path : "") {} |
| |
| void Decoders::GetAvailablePaths(std::string& read_path, std::string& write_path, std::string& root_path) { |
| #if (WINAPI_FAMILY == WINAPI_FAMILY_APP) |
| write_path = "..\\data"; |
| read_path = "..\\data"; |
| #else |
| read_path = write_path = root_path.empty() ? "./" : root_path; |
| #endif |
| } |
| |
| int Decoders::DecodeLoop() { |
| std::string err; |
| std::string args_path(_CONFIG_PATH_); |
| std::vector<one_task> arg_lists; |
| std::string write_path; |
| std::string read_path; |
| GetAvailablePaths(read_path, write_path, root_path_); |
| write_path_ = write_path; |
| read_path_ = read_path; |
| std::string full_args_path = read_path + args_path; |
| parse_file(full_args_path, arg_lists); |
| if (arg_lists.size() == 0) { |
| XB_LOGE << "No args were found"; |
| return -1; |
| } |
| dx_resources_.dx12_psos = |
| av1_create_pipeline_cache_handle(dx_resources_.dx12_device.Get(), CREATE_SHADERS_THREAD_CNT); |
| if (!dx_resources_.dx12_psos) { |
| XB_LOGE << "Unable to create compute shaders"; |
| return -1; |
| } |
| decoder_ = std::shared_ptr<AV1Decoder>(new AV1Decoder(dx_resources_, display_, &stop_decode_)); |
| for (std::vector<one_task>::iterator iter = arg_lists.begin(); iter != arg_lists.end() && !stop_; iter++) { |
| // check if line is not empty |
| if (iter->empty()) continue; |
| CParameters params(read_path.c_str(), write_path.c_str()); |
| int ret = params.Parse(*iter, err); |
| if (ret || !err.empty()) { |
| XB_LOGE << "Invalid arguments string. " << err; |
| continue; |
| } |
| if (params.GetParams().isDirectory_) { |
| if (params.GetParams().conformance_) { |
| params.GetParamsPtr()->bad_conform_dir_ = params.GetParamsPtr()->source_dir_ + "\\trg\\"; |
| params.GetParamsPtr()->source_dir_ += "\\src"; |
| } |
| process_directory(params); |
| } else { |
| XB_LOGD << "Run decoder for " << params.GetParams().source_file_.c_str(); |
| decoder_->Start(¶ms); |
| decoder_->WaitForFinish(); |
| int a = 0; |
| } |
| } |
| // finished all tasks |
| decoder_.reset(); |
| if (display_) display_->AllJobDoneNotify(); |
| av1_destroy_pipeline_cache_handle(dx_resources_.dx12_psos); |
| dx_resources_.dx12_psos = 0; |
| return 0; |
| } |