mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-28 15:02:24 +00:00
213 lines
6.3 KiB
C++
213 lines
6.3 KiB
C++
/*
|
|
* InterplayDecoder
|
|
* Copyright (C) 2020 sirlemonhead
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/* This code is based on interplayvideo.c, dpcm.c and ipmovie.c from the FFmpeg project which can be obtained
|
|
* from http://www.ffmpeg.org/. Below is the license from interplayvideo.c
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Interplay MVE Video Decoder
|
|
* Copyright (C) 2003 The FFmpeg project
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <deque>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
#include "files.h"
|
|
#include "animtexture.h"
|
|
#include "s_music.h"
|
|
|
|
#ifndef playmve_h_
|
|
#define playmve_h_
|
|
|
|
class InterplayDecoder
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
CHUNK_PREAMBLE_SIZE = 4,
|
|
OPCODE_PREAMBLE_SIZE = 4,
|
|
|
|
CHUNK_INIT_AUDIO = 0x0000,
|
|
CHUNK_AUDIO_ONLY = 0x0001,
|
|
CHUNK_INIT_VIDEO = 0x0002,
|
|
CHUNK_VIDEO = 0x0003,
|
|
CHUNK_SHUTDOWN = 0x0004,
|
|
CHUNK_END = 0x0005,
|
|
/* these last types are used internally */
|
|
CHUNK_DONE = 0xFFFC,
|
|
CHUNK_NOMEM = 0xFFFD,
|
|
CHUNK_EOF = 0xFFFE,
|
|
CHUNK_BAD = 0xFFFF,
|
|
|
|
OPCODE_END_OF_STREAM = 0x00,
|
|
OPCODE_END_OF_CHUNK = 0x01,
|
|
OPCODE_CREATE_TIMER = 0x02,
|
|
OPCODE_INIT_AUDIO_BUFFERS = 0x03,
|
|
OPCODE_START_STOP_AUDIO = 0x04,
|
|
OPCODE_INIT_VIDEO_BUFFERS = 0x05,
|
|
OPCODE_UNKNOWN_06 = 0x06,
|
|
OPCODE_SEND_BUFFER = 0x07,
|
|
OPCODE_AUDIO_FRAME = 0x08,
|
|
OPCODE_SILENCE_FRAME = 0x09,
|
|
OPCODE_INIT_VIDEO_MODE = 0x0A,
|
|
OPCODE_CREATE_GRADIENT = 0x0B,
|
|
OPCODE_SET_PALETTE = 0x0C,
|
|
OPCODE_SET_PALETTE_COMPRESSED = 0x0D,
|
|
OPCODE_UNKNOWN_0E = 0x0E,
|
|
OPCODE_SET_DECODING_MAP = 0x0F,
|
|
OPCODE_UNKNOWN_10 = 0x10,
|
|
OPCODE_VIDEO_DATA = 0x11,
|
|
OPCODE_UNKNOWN_12 = 0x12,
|
|
OPCODE_UNKNOWN_13 = 0x13,
|
|
OPCODE_UNKNOWN_14 = 0x14,
|
|
OPCODE_UNKNOWN_15 = 0x15,
|
|
|
|
PALETTE_COUNT = 256,
|
|
kAudioBlocks = 20 // alloc a lot of blocks - need to store lots of audio data before video frames start.
|
|
};
|
|
|
|
InterplayDecoder(bool soundenabled);
|
|
~InterplayDecoder();
|
|
|
|
bool Open(FileReader &fr);
|
|
void Close();
|
|
|
|
bool RunFrame(uint64_t clock);
|
|
|
|
bool FillSamples(void *buff, int len);
|
|
|
|
bool HasAudio() const noexcept { return bAudioEnabled; }
|
|
int NumChannels() const noexcept { return audio.nChannels; }
|
|
int GetSampleRate() const noexcept { return audio.nSampleRate; }
|
|
void DisableAudio();
|
|
|
|
AnimTextures& animTex() { return animtex; }
|
|
|
|
private:
|
|
struct AudioPacket
|
|
{
|
|
size_t nSize = 0;
|
|
std::unique_ptr<uint8_t[]> pData;
|
|
};
|
|
|
|
struct VideoPacket
|
|
{
|
|
uint16_t nPalStart=0, nPalCount=0;
|
|
uint32_t nDecodeMapSize = 0;
|
|
uint32_t nVideoDataSize = 0;
|
|
bool bSendFlag = false;
|
|
std::unique_ptr<uint8_t[]> pData;
|
|
};
|
|
|
|
struct AudioData
|
|
{
|
|
int nChannels = 0;
|
|
uint16_t nSampleRate = 0;
|
|
uint8_t nBitDepth = 0;
|
|
bool bCompressed = false;
|
|
|
|
std::unique_ptr<int16_t[]> samples;
|
|
int nWrite = 0;
|
|
int nRead = 0;
|
|
|
|
std::deque<AudioPacket> Packets;
|
|
};
|
|
AudioData audio;
|
|
|
|
struct DecodeMap
|
|
{
|
|
uint8_t* pData;
|
|
uint32_t nSize;
|
|
};
|
|
|
|
struct Palette
|
|
{
|
|
uint8_t r;
|
|
uint8_t g;
|
|
uint8_t b;
|
|
};
|
|
|
|
uint8_t* GetCurrentFrame();
|
|
uint8_t* GetPreviousFrame();
|
|
void SwapFrames();
|
|
void CopyBlock(uint8_t* pDest, uint8_t* pSrc);
|
|
void DecodeBlock0(int32_t offset);
|
|
void DecodeBlock1(int32_t offset);
|
|
void DecodeBlock2(int32_t offset);
|
|
void DecodeBlock3(int32_t offset);
|
|
void DecodeBlock4(int32_t offset);
|
|
void DecodeBlock5(int32_t offset);
|
|
void DecodeBlock7(int32_t offset);
|
|
void DecodeBlock8(int32_t offset);
|
|
void DecodeBlock9(int32_t offset);
|
|
void DecodeBlock10(int32_t offset);
|
|
void DecodeBlock11(int32_t offset);
|
|
void DecodeBlock12(int32_t offset);
|
|
void DecodeBlock13(int32_t offset);
|
|
void DecodeBlock14(int32_t offset);
|
|
void DecodeBlock15(int32_t offset);
|
|
|
|
std::mutex PacketMutex;
|
|
FileReader fr;
|
|
|
|
bool bIsPlaying, bAudioEnabled;
|
|
|
|
uint32_t nTimerRate, nTimerDiv;
|
|
uint32_t nWidth, nHeight, nFrame;
|
|
double nFps;
|
|
uint64_t nFrameDuration;
|
|
|
|
std::vector<uint8_t> ChunkData;
|
|
int ProcessNextChunk();
|
|
|
|
std::deque<VideoPacket> VideoPackets;
|
|
uint8_t* pVideoBuffers[2];
|
|
uint32_t nCurrentVideoBuffer, nPreviousVideoBuffer;
|
|
int32_t videoStride;
|
|
|
|
const uint8_t *ChunkPtr = nullptr;
|
|
DecodeMap decodeMap;
|
|
|
|
AnimTextures animtex;
|
|
Palette palette[256];
|
|
uint64_t nNextFrameTime = 0;
|
|
};
|
|
|
|
#endif
|