Exemple #1
0
static unsigned int guessTabMultiplier(IFile &pckFile, IFile &tabFile)
{
	// This tries to guess if the tab file contains (offset) or (offset/4) based on the last entry,
	// if multiplying it by 4 is greater than the pck file size it's (offset), otherwise (offset/4)
	auto pckSize = pckFile.size();
	auto tabSize = tabFile.size();
	if (tabSize < 4)
	{
		LogWarning("Tab size %zu too small for a single entry?", tabSize);
		return 0;
	}

	// Store the tab offset so we can restore the file state
	auto tabOffset = tabFile.tellg();
	tabFile.seekg(tabSize - 4);
	uint32_t lastOffset;
	tabFile.read(reinterpret_cast<char *>(&lastOffset), sizeof(lastOffset));
	if (!tabFile)
	{
		LogWarning("Failed to read last tab offset");
		return 0;
	}
	tabFile.seekg(tabOffset);
	if (lastOffset * 4 >= pckSize)
	{
		return 1;
	}
	else
	{
		return 4;
	}
}
Exemple #2
0
	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;
	}