blob: c382f293b8aa60766885de9d786137b9eca14b3b [file] [log] [blame]
/*
* 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(&params);
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(&params);
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;
}