mistserver/src/input/input_hls.h

174 lines
5.8 KiB
C++

#pragma once
#include "input.h"
#include <mist/dtsc.h>
#include <mist/nal.h>
#include <mist/segmentreader.h>
#define BUFFERTIME 10
namespace Mist{
extern bool streamIsLive; //< Playlist can be sliding window or get new segments appended
extern bool streamIsVOD; //< Playlist segments do not disappear
extern uint32_t globalWaitTime; // largest waitTime for any playlist we're loading - used to update minKeepAway
void parseKey(std::string key, char *newKey, unsigned int len);
struct playListEntries{
std::string filename;
std::string relative_filename;
std::string mapName;
uint64_t startAtByte; ///< Byte position inside filename where to start reading
uint64_t stopAtByte; ///< Byte position inside filename where to stop sending
uint64_t bytePos;
uint64_t mUTC; ///< UTC unix millis timestamp of first packet, if known
float duration; ///< Duration of entry in seconds
uint64_t timestamp; ///< zUTC-based timestamp for this entry
int64_t timeOffset; ///< Value timestamps in the media are shifted by to get zUTC-based timestamps
uint64_t wait;
char ivec[16];
char keyAES[16];
playListEntries(){
bytePos = 0;
mUTC = 0;
duration = 0;
timestamp = 0;
timeOffset = 0;
wait = 0;
startAtByte = 0;
stopAtByte = 0;
for (size_t i = 0; i < 16; ++i){
ivec[i] = 0;
keyAES[i] = 0;
}
}
std::string shortName() const{
if (!startAtByte && !stopAtByte){return filename;}
std::string ret = filename;
ret += " (";
ret += JSON::Value(startAtByte).asString();
ret += "-";
ret += JSON::Value(stopAtByte).asString();
ret += ")";
return ret;
}
};
inline bool operator< (const playListEntries a, const playListEntries b){
return a.filename < b.filename || (a.filename == b.filename && a.startAtByte < b.startAtByte);
}
inline bool operator== (const playListEntries a, const playListEntries b){
return a.filename == b.filename && a.startAtByte == b.startAtByte;
}
/// Keeps the segment entry list by playlist ID
extern std::map<uint32_t, std::deque<playListEntries> > listEntries;
class Playlist{
public:
Playlist(const std::string &uriSrc = "");
bool isUrl() const;
bool reload();
void addEntry(const std::string & absolute_filename, const std::string &filename, float duration, uint64_t &bpos,
const std::string &key, const std::string &keyIV, const std::string mapName, uint64_t startByte, uint64_t lenByte);
std::string uri; // link to the current playlistfile
HTTP::URL root;
std::string relurl;
uint64_t reloadNext;
uint32_t id;
bool playlistEnd;
int noChangeCount;
uint64_t waitTime;
uint64_t lastTimestamp;
uint64_t startTime;
int64_t oUTC;
uint64_t nextUTC; ///< If non-zero, the UTC timestamp of the next segment on this playlist
char keyAES[16];
std::map<std::string, std::string> keys;
std::map<std::string, std::string> maps;
uint64_t firstIndex; //< the index of the first segment in the playlist
uint64_t lastSegment;
std::map<size_t, bool> tracks;
};
void playlistRunner(void *ptr);
class InputHLS : public Input{
public:
InputHLS(Util::Config *cfg);
~InputHLS(){}
bool needsLock(){return !config->getBool("realtime");}
bool openStreamSource();
bool callback();
protected:
uint64_t zUTC; ///< Zero point in local millis, as UTC unix time millis
uint64_t nUTC; ///< Next packet timestamp in UTC unix time millis
int64_t streamOffset; ///< bootMsOffset we need to set once we have parsed the header
unsigned int startTime;
SegmentReader segDowner;
int version;
int targetDuration;
bool endPlaylist;
uint64_t currentPlaylist;
bool allowRemap; ///< True if the next packet may remap the timestamps
std::map<uint64_t, uint64_t> pidMapping;
std::map<uint64_t, uint64_t> pidMappingR;
std::map<int, int64_t> plsTimeOffset;
std::map<int, int64_t> DVRTimeOffsets;
std::map<int, uint64_t> plsLastTime;
std::map<int, uint64_t> plsInterval;
size_t currentIndex;
std::string currentFile;
// Used to map packetId of packets in pidMapping
int pidCounter;
// Override userLeadOut to buffer new data as live packets
void userLeadOut();
// Removes any metadata which is no longer and the playlist or buffered in memory
void updateMeta();
/// Tries to add as much live packets from a TS file at the given location
bool parseSegmentAsLive(uint64_t segmentIndex);
// index of last playlist entry finished parsing
long previousSegmentIndex;
size_t firstSegment();
void waitForNextSegment();
void readPMT();
bool checkArguments();
bool preSetup();
bool readHeader();
bool readExistingHeader();
void getNext(size_t idx = INVALID_TRACK_ID);
void seek(uint64_t seekTime, size_t idx = INVALID_TRACK_ID);
bool readIndex();
bool initPlaylist(const std::string &uri, bool fullInit = true);
bool readPlaylist(const HTTP::URL &uri, const std::string & relurl, bool fullInit = true);
bool readNextFile();
void parseStreamHeader();
void parseLivePoint();
void streamMainLoop();
uint32_t getMappedTrackId(uint64_t id);
uint32_t getMappedTrackPlaylist(uint64_t id);
uint64_t getOriginalTrackId(uint32_t playlistId, uint32_t id);
uint64_t getPacketTime(uint64_t packetTime, uint64_t tid, uint64_t currentPlaylist, uint64_t nUTC = 0);
uint64_t getPacketID(uint64_t currentPlaylist, uint64_t trackId);
virtual void finish();
void injectLocalVars();
virtual void checkHeaderTimes(const HTTP::URL & streamFile);
// Used to immediately mark pages for removal when we're bursting through segments on initial boot
bool isInitialRun;
};
}// namespace Mist
typedef Mist::InputHLS mistIn;