IFile Data::load_file(const UString &path, Data::FileMode mode) { IFile f; if (mode != Data::FileMode::Read) { LogError("Invalid FileMode set for \"%s\"", path.c_str()); return f; } UString foundPath = GetCorrectCaseFilename(path); if (foundPath == "") { LogInfo("Failed to find \"%s\"", path.c_str()); assert(!f); return f; } f.f.reset(new PhysfsIFileImpl(foundPath, path)); f.rdbuf(dynamic_cast<PhysfsIFileImpl *>(f.f.get())); LogInfo("Loading \"%s\" from \"%s\"", path.c_str(), f.systemPath().c_str()); return f; }
IFile FileSystem::open(const UString &path) { TRACE_FN_ARGS1("PATH", path); IFile f; auto lowerPath = path.toLower(); if (path != lowerPath) { LogError("Path \"%s\" contains CAPITAL - cut it out!", path); } if (!PHYSFS_exists(path.cStr())) { LogInfo("Failed to find \"%s\"", path); LogAssert(!f); return f; } f.f.reset(new PhysfsIFileImpl(path)); f.rdbuf(dynamic_cast<PhysfsIFileImpl *>(f.f.get())); LogInfo("Loading \"%s\" from \"%s\"", path, f.systemPath()); return f; }
bool load(IFile &file) { TRACE_FN; double usf; // uSeconds per frame this->video_data = file.readAll(); this->video_data_size = file.size(); auto video_path = file.systemPath(); this->file_path = video_path; LogInfo("Read %llu bytes from video", static_cast<unsigned long long>(this->video_data_size)); this->smk_ctx = smk_open_memory(reinterpret_cast<unsigned char *>(this->video_data.get()), static_cast<unsigned long>(this->video_data_size)); if (!this->smk_ctx) { LogWarning("Failed to read SMK file \"%s\"", video_path.cStr()); this->video_data.reset(); return false; } LogInfo("Successfully created SMK context"); if (smk_info_all(this->smk_ctx, nullptr, &this->frame_count, &usf)) { LogWarning("Failed to read SMK file info from \"%s\"", video_path.cStr()); this->video_data.reset(); smk_close(this->smk_ctx); this->smk_ctx = nullptr; return false; } this->frame_time = std::chrono::nanoseconds((unsigned int)(usf * 1000)); LogInfo("Video frame count %lu, ns per frame = %u (USF: %f)", this->frame_count, this->frame_time.count(), usf); unsigned long height, width; if (smk_info_video(this->smk_ctx, &width, &height, nullptr)) { LogWarning("Failed to read SMK video info from \"%s\"", video_path.cStr()); this->video_data.reset(); smk_close(this->smk_ctx); this->smk_ctx = nullptr; return false; } this->frame_size = {width, height}; LogInfo("Video frame size {%u,%u}", this->frame_size.x, this->frame_size.y); auto ret = smk_enable_video(this->smk_ctx, 1); if (ret == SMK_ERROR) { LogWarning("Error enabling video for \"%s\"", video_path.cStr()); return false; } unsigned char audio_track_mask; unsigned char channels[7]; unsigned char bitdepth[7]; unsigned long audio_rate[7]; ret = smk_info_audio(this->smk_ctx, &audio_track_mask, channels, bitdepth, audio_rate); if (ret == SMK_ERROR) { LogWarning("Error reading audio info for \"%s\"", video_path.cStr()); return false; } if (audio_track_mask & SMK_AUDIO_TRACK_0) { // WE only support a single track LogInfo("Audio track: channels %u depth %u rate %lu", (unsigned)channels[0], (unsigned)bitdepth[0], audio_rate[0]); } else { LogWarning("Unsupported audio track mask 0x%02x for \"%s\"", (unsigned)audio_track_mask, video_path.cStr()); return false; } switch (channels[0]) { case 1: // Mono this->audio_format.channels = 1; break; case 2: // Stereo this->audio_format.channels = 2; break; default: LogWarning("Unsupported audio channel count %u for \"%s\"", (unsigned)channels[0], video_path.cStr()); return false; } switch (bitdepth[0]) { case 8: this->audio_format.format = AudioFormat::SampleFormat::PCM_UINT8; this->audio_bytes_per_sample = 1; break; case 16: this->audio_format.format = AudioFormat::SampleFormat::PCM_SINT16; this->audio_bytes_per_sample = 2; break; default: LogWarning("Unsupported audio bit depth %u for \"%s\"", (unsigned)bitdepth[0], video_path.cStr()); return false; } this->audio_format.frequency = audio_rate[0]; ret = smk_enable_audio(this->smk_ctx, 0, 1); if (ret == SMK_ERROR) { LogWarning("Error enabling audio track 0 for \"%s\"", video_path.cStr()); } // Everything looks good return true; }