mistserver/lib/dtsc.h
2021-10-19 22:29:40 +02:00

498 lines
17 KiB
C++

/// \file dtsc.h
/// Holds all headers for DDVTECH Stream Container parsing/generation.
#pragma once
#include "defines.h"
#include "json.h"
#include "shared_memory.h"
#include "socket.h"
#include "timing.h"
#include "util.h"
#include <deque>
#include <iostream>
#include <set>
#include <stdint.h> //for uint64_t
#include <stdio.h> //for FILE
#include <string>
#include <vector>
#define DTSC_INT 0x01
#define DTSC_STR 0x02
#define DTSC_OBJ 0xE0
#define DTSC_ARR 0x0A
#define DTSC_CON 0xFF
// Increase this value every time the DTSH file format changes in an incompatible way
// Changelog:
// Version 0-2: Undocumented changes
// Version 3: switched to bigMeta-style by default, Parts layout switched from 3/2/4 to 3/3/3 bytes
// Version 4: renamed bps to maxbps (peak bit rate) and added new value bps (average bit rate)
#define DTSH_VERSION 4
namespace DTSC{
extern uint64_t veryUglyJitterOverride;
///\brief This enum holds all possible datatypes for DTSC packets.
enum datatype{
AUDIO, ///< Stream Audio data
VIDEO, ///< Stream Video data
META, ///< Stream Metadata
PAUSEMARK, ///< Pause marker
MODIFIEDHEADER, ///< Modified header data.
INVALID ///< Anything else or no data available.
};
extern char Magic_Header[]; ///< The magic bytes for a DTSC header
extern char Magic_Packet[]; ///< The magic bytes for a DTSC packet
extern char Magic_Packet2[]; ///< The magic bytes for a DTSC packet version 2
extern char Magic_Command[]; ///< The magic bytes for a DTCM packet
enum packType{DTSC_INVALID, DTSC_HEAD, DTSC_V1, DTSC_V2, DTCM};
/// This class allows scanning through raw binary format DTSC data.
/// It can be used as an iterator or as a direct accessor.
class Scan{
public:
Scan();
Scan(char *pointer, size_t len);
operator bool() const;
std::string toPrettyString(size_t indent = 0) const;
bool hasMember(const std::string &indice) const;
bool hasMember(const char *indice, size_t ind_len) const;
Scan getMember(const std::string &indice) const;
Scan getMember(const char *indice) const;
Scan getMember(const char *indice, size_t ind_len) const;
Scan getIndice(size_t num) const;
std::string getIndiceName(size_t num) const;
size_t getSize() const;
char getType() const;
bool asBool() const;
int64_t asInt() const;
std::string asString() const;
void getString(char *&result, size_t &len) const;
JSON::Value asJSON() const;
private:
char *p;
size_t len;
};
/// DTSC::Packets can currently be three types:
/// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content.
/// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content.
/// DTSC_V2 packets are "DTP2", followed by 4 bytes len, 4 bytes trackID, 8 bytes time, and packed
/// content. The len is always without the first 8 bytes counted.
class Packet{
public:
Packet();
Packet(const Packet &rhs, size_t idx = INVALID_TRACK_ID);
Packet(const char *data_, unsigned int len, bool noCopy = false);
virtual ~Packet();
void null();
void operator=(const Packet &rhs);
operator bool() const;
packType getVersion() const;
void reInit(Socket::Connection &src);
void reInit(const char *data_, unsigned int len, bool noCopy = false);
void genericFill(uint64_t packTime, int64_t packOffset, uint32_t packTrack, const char *packData,
size_t packDataSize, uint64_t packBytePos, bool isKeyframe);
void appendData(const char *appendData, uint32_t appendLen);
void getString(const char *identifier, char *&result, size_t &len) const;
void getString(const char *identifier, std::string &result) const;
void getInt(const char *identifier, uint64_t &result) const;
uint64_t getInt(const char *identifier) const;
void getFlag(const char *identifier, bool &result) const;
bool getFlag(const char *identifier) const;
bool hasMember(const char *identifier) const;
void appendNal(const char *appendData, uint32_t appendLen);
void upgradeNal(const char *appendData, uint32_t appendLen);
void setKeyFrame(bool kf);
virtual uint64_t getTime() const;
void setTime(uint64_t _time);
size_t getTrackId() const;
char *getData() const;
size_t getDataLen() const;
size_t getPayloadLen() const;
size_t getDataStringLen();
size_t getDataStringLenOffset();
JSON::Value toJSON() const;
std::string toSummary() const;
Scan getScan() const;
protected:
bool master;
packType version;
void resize(size_t size);
char *data;
size_t bufferLen;
size_t dataLen;
uint64_t prevNalSize;
};
/// A child class of DTSC::Packet, which allows overriding the packet time efficiently.
class RetimedPacket : public Packet{
public:
RetimedPacket(uint64_t reTime){timeOverride = reTime;}
RetimedPacket(uint64_t reTime, const Packet &rhs) : Packet(rhs){timeOverride = reTime;}
RetimedPacket(uint64_t reTime, const char *data_, unsigned int len, bool noCopy = false)
: Packet(data_, len, noCopy){
timeOverride = reTime;
}
~RetimedPacket(){}
virtual uint64_t getTime() const{return timeOverride;}
protected:
uint64_t timeOverride;
};
class Parts{
public:
Parts(const Util::RelAccX &_parts);
size_t getFirstValid() const;
size_t getEndValid() const;
size_t getValidCount() const;
size_t getSize(size_t idx) const;
uint64_t getDuration(size_t idx) const;
int64_t getOffset(size_t idx) const;
private:
const Util::RelAccX &parts;
Util::RelAccXFieldData sizeField;
Util::RelAccXFieldData durationField;
Util::RelAccXFieldData offsetField;
};
class Keys{
public:
Keys(Util::RelAccX &_keys);
Keys(const Util::RelAccX &_keys);
size_t getFirstValid() const;
size_t getEndValid() const;
size_t getValidCount() const;
size_t getFirstPart(size_t idx) const;
size_t getBpos(size_t idx) const;
uint64_t getDuration(size_t idx) const;
size_t getNumber(size_t idx) const;
size_t getParts(size_t idx) const;
uint64_t getTime(size_t idx) const;
void setSize(size_t idx, size_t _size);
size_t getSize(size_t idx) const;
size_t getNumForTime(uint64_t time) const;
private:
bool isConst;
Util::RelAccX empty;
Util::RelAccX &keys;
const Util::RelAccX &cKeys;
Util::RelAccXFieldData firstPartField;
Util::RelAccXFieldData bposField;
Util::RelAccXFieldData durationField;
Util::RelAccXFieldData numberField;
Util::RelAccXFieldData partsField;
Util::RelAccXFieldData timeField;
Util::RelAccXFieldData sizeField;
};
class Fragments{
public:
Fragments(const Util::RelAccX &_fragments);
size_t getFirstValid() const;
size_t getEndValid() const;
size_t getValidCount() const;
uint64_t getDuration(size_t idx) const;
size_t getKeycount(size_t idx) const;
size_t getFirstKey(size_t idx) const;
size_t getSize(size_t idx) const;
private:
const Util::RelAccX &fragments;
};
class Track{
public:
Util::RelAccX parts;
Util::RelAccX keys;
Util::RelAccX fragments;
Util::RelAccX pages;
Util::RelAccX track;
// Internal buffers so we don't always need to search for everything
Util::RelAccXFieldData trackIdField;
Util::RelAccXFieldData trackTypeField;
Util::RelAccXFieldData trackCodecField;
Util::RelAccXFieldData trackFirstmsField;
Util::RelAccXFieldData trackLastmsField;
Util::RelAccXFieldData trackBpsField;
Util::RelAccXFieldData trackMaxbpsField;
Util::RelAccXFieldData trackLangField;
Util::RelAccXFieldData trackInitField;
Util::RelAccXFieldData trackRateField;
Util::RelAccXFieldData trackSizeField;
Util::RelAccXFieldData trackChannelsField;
Util::RelAccXFieldData trackWidthField;
Util::RelAccXFieldData trackHeightField;
Util::RelAccXFieldData trackFpksField;
Util::RelAccXFieldData trackMissedFragsField;
Util::RelAccXFieldData partSizeField;
Util::RelAccXFieldData partDurationField;
Util::RelAccXFieldData partOffsetField;
Util::RelAccXFieldData keyFirstPartField;
Util::RelAccXFieldData keyBposField;
Util::RelAccXFieldData keyDurationField;
Util::RelAccXFieldData keyNumberField;
Util::RelAccXFieldData keyPartsField;
Util::RelAccXFieldData keyTimeField;
Util::RelAccXFieldData keySizeField;
Util::RelAccXFieldData fragmentDurationField;
Util::RelAccXFieldData fragmentKeysField;
Util::RelAccXFieldData fragmentFirstKeyField;
Util::RelAccXFieldData fragmentSizeField;
};
class Meta{
public:
Meta(const std::string &_streamName, const DTSC::Scan &src);
Meta(const std::string &_streamName = "", bool master = true);
Meta(const std::string &_streamName, const std::string &fileName);
~Meta();
void reInit(const std::string &_streamName, bool master = true);
void reInit(const std::string &_streamName, const std::string &fileName);
void reInit(const std::string &_streamName, const DTSC::Scan &src);
void refresh();
operator bool() const;
void setMaster(bool _master);
bool getMaster() const;
void clear();
void minimalFrom(const Meta &src);
bool trackLoaded(size_t idx) const;
bool trackValid(size_t idx) const;
size_t trackCount() const;
size_t addCopy(size_t source);
size_t addDelayedTrack(size_t fragCount = DEFAULT_FRAGMENT_COUNT, size_t keyCount = DEFAULT_KEY_COUNT,
size_t partCount = DEFAULT_PART_COUNT, size_t pageCount = DEFAULT_PAGE_COUNT);
size_t addTrack(size_t fragCount = DEFAULT_FRAGMENT_COUNT, size_t keyCount = DEFAULT_KEY_COUNT,
size_t partCount = DEFAULT_PART_COUNT, size_t pageCount = DEFAULT_PAGE_COUNT,
bool setValid = true);
void resizeTrack(size_t source, size_t fragCount = DEFAULT_FRAGMENT_COUNT, size_t keyCount = DEFAULT_KEY_COUNT,
size_t partCount = DEFAULT_PART_COUNT, size_t pageCount = DEFAULT_PAGE_COUNT);
void initializeTrack(Track &t, size_t fragCount = DEFAULT_FRAGMENT_COUNT, size_t keyCount = DEFAULT_KEY_COUNT,
size_t parCount = DEFAULT_PART_COUNT, size_t pageCount = DEFAULT_PAGE_COUNT);
void merge(const DTSC::Meta &M, bool deleteTracks = true, bool copyData = true);
void updatePosOverride(DTSC::Packet &pack, uint64_t bpos);
void update(const DTSC::Packet &pack);
void update(uint64_t packTime, int64_t packOffset, uint32_t packTrack, uint64_t packDataSize,
uint64_t packBytePos, bool isKeyframe, uint64_t packSendSize = 0);
size_t trackIDToIndex(size_t trackID, size_t pid = 0) const;
std::string getTrackIdentifier(size_t idx, bool unique = false) const;
void setInit(size_t trackIdx, const std::string &init);
void setInit(size_t trackIdx, const char *init, size_t initLen);
std::string getInit(size_t idx) const;
void setSource(const std::string &src);
std::string getSource() const;
void setID(size_t trackIdx, size_t id);
size_t getID(size_t trackIdx) const;
void markUpdated(size_t trackIdx);
uint64_t getLastUpdated(size_t trackIdx) const;
uint64_t getLastUpdated() const;
void setChannels(size_t trackIdx, uint16_t channels);
uint16_t getChannels(size_t trackIdx) const;
void setRate(size_t trackIdx, uint32_t rate);
uint32_t getRate(size_t trackIdx) const;
void setWidth(size_t trackIdx, uint32_t width);
uint32_t getWidth(size_t trackIdx) const;
void setHeight(size_t trackIdx, uint32_t height);
uint32_t getHeight(size_t trackIdx) const;
void setSize(size_t trackIdx, uint16_t size);
uint16_t getSize(size_t trackIdx) const;
void setType(size_t trackIdx, const std::string &type);
std::string getType(size_t trackIdx) const;
void setCodec(size_t trackIdx, const std::string &codec);
std::string getCodec(size_t trackIdx) const;
void setLang(size_t trackIdx, const std::string &lang);
std::string getLang(size_t trackIdx) const;
void setFirstms(size_t trackIdx, uint64_t firstms);
uint64_t getFirstms(size_t trackIdx) const;
void setLastms(size_t trackIdx, uint64_t lastms);
uint64_t getLastms(size_t trackIdx) const;
uint64_t getDuration(size_t trackIdx) const;
void setBps(size_t trackIdx, uint64_t bps);
uint64_t getBps(size_t trackIdx) const;
void setMaxBps(size_t trackIdx, uint64_t bps);
uint64_t getMaxBps(size_t trackIdx) const;
void setFpks(size_t trackIdx, uint64_t bps);
uint64_t getFpks(size_t trackIdx) const;
void setMissedFragments(size_t trackIdx, uint32_t missedFragments);
uint32_t getMissedFragments(size_t trackIdx) const;
void setMinKeepAway(size_t trackIdx, uint64_t minKeepAway);
uint64_t getMinKeepAway(size_t trackIdx) const;
/*LTS-START*/
void setSourceTrack(size_t trackIdx, size_t sourceTrack);
uint64_t getSourceTrack(size_t trackIdx) const;
void setEncryption(size_t trackIdx, const std::string &encryption);
std::string getEncryption(size_t trackIdx) const;
void setPlayReady(size_t trackIdx, const std::string &playReady);
std::string getPlayReady(size_t trackIdx) const;
void setWidevine(size_t trackIdx, const std::string &widevine);
std::string getWidevine(size_t trackIdx) const;
void setIvec(size_t trackIdx, uint64_t ivec);
uint64_t getIvec(size_t trackIdx) const;
void setMinimumFragmentDuration(uint64_t newFragmentDuration = DEFAULT_FRAGMENT_DURATION);
uint64_t getMinimumFragmentDuration() const;
/*LTS-END*/
/*LTS-START
uint64_t getFragmentDuration() const{return DEFAULT_FRAGMENT_DURATION;}
LTS-END*/
void setVod(bool vod = true);
bool getVod() const;
void setLive(bool live = true);
bool getLive() const;
bool hasBFrames(size_t idx = INVALID_TRACK_ID) const;
void setBufferWindow(uint64_t bufferWindow);
uint64_t getBufferWindow() const;
void setBootMsOffset(uint64_t bootMsOffset);
uint64_t getBootMsOffset() const;
std::set<size_t> getValidTracks(bool skipEmpty = false) const;
std::set<size_t> getMySourceTracks(size_t pid) const;
void validateTrack(size_t trackIdx);
void removeEmptyTracks();
void removeTrack(size_t trackIdx);
void removeFirstKey(size_t trackIdx);
size_t mainTrack() const;
uint32_t biggestFragment(uint32_t idx = INVALID_TRACK_ID) const;
bool tracksAlign(size_t idx1, size_t idx2) const;
uint64_t getTimeForFragmentIndex(uint32_t idx, uint32_t fragmentIdx) const;
uint32_t getFragmentIndexForTime(uint32_t idx, uint64_t timestamp) const;
uint64_t getTimeForKeyIndex(uint32_t idx, uint32_t keyIdx) const;
uint32_t getKeyIndexForTime(uint32_t idx, uint64_t timestamp) const;
uint32_t getPartIndex(const DTSC::Packet &pack, size_t idx) const;
bool nextPageAvailable(uint32_t idx, size_t currentPage) const;
size_t getPageNumberForTime(uint32_t idx, uint64_t time) const;
size_t getPageNumberForKey(uint32_t idx, uint64_t keynumber) const;
const Util::RelAccX &parts(size_t idx) const;
Util::RelAccX &keys(size_t idx);
const Util::RelAccX &keys(size_t idx) const;
const Util::RelAccX &fragments(size_t idx) const;
Util::RelAccX &pages(size_t idx);
const Util::RelAccX &pages(size_t idx) const;
std::string toPrettyString() const;
void remap(const std::string &_streamName = "");
uint64_t getSendLen(bool skipDynamic = false, std::set<size_t> selectedTracks = std::set<size_t>()) const;
void toFile(const std::string &fName) const;
void send(Socket::Connection &conn, bool skypDynamic = false,
std::set<size_t> selectedTracks = std::set<size_t>(), bool reID = false) const;
void toJSON(JSON::Value &res, bool skipDynamic = true, bool tracksOnly = false) const;
std::string getStreamName() const{return streamName;}
JSON::Value inputLocalVars;
uint8_t version;
protected:
void sBufMem(size_t trackCount = DEFAULT_TRACK_COUNT);
void sBufShm(const std::string &_streamName, size_t trackCount = DEFAULT_TRACK_COUNT, bool master = true);
void streamInit(size_t trackCount = DEFAULT_TRACK_COUNT);
std::string streamName;
IPC::sharedPage streamPage;
Util::RelAccX stream;
Util::RelAccX trackList;
std::map<size_t, Track> tracks;
std::map<size_t, IPC::sharedPage> tM;
bool isMaster;
char *streamMemBuf;
bool isMemBuf;
std::map<size_t, char *> tMemBuf;
std::map<size_t, size_t> sizeMemBuf;
private:
// Internal buffers so we don't always need to search for everything
Util::RelAccXFieldData streamVodField;
Util::RelAccXFieldData streamLiveField;
Util::RelAccXFieldData streamSourceField;
Util::RelAccXFieldData streamBufferWindowField;
Util::RelAccXFieldData streamBootMsOffsetField;
Util::RelAccXFieldData streamMinimumFragmentDurationField;
Util::RelAccXFieldData trackValidField;
Util::RelAccXFieldData trackIdField;
Util::RelAccXFieldData trackTypeField;
Util::RelAccXFieldData trackCodecField;
Util::RelAccXFieldData trackPageField;
Util::RelAccXFieldData trackLastUpdateField;
Util::RelAccXFieldData trackPidField;
Util::RelAccXFieldData trackMinKeepAwayField;
Util::RelAccXFieldData trackSourceTidField;
Util::RelAccXFieldData trackEncryptionField;
Util::RelAccXFieldData trackIvecField;
Util::RelAccXFieldData trackWidevineField;
Util::RelAccXFieldData trackPlayreadyField;
};
}// namespace DTSC