mistserver/src/output/output_mp4.h
Thulinma 9953cd6ee2 Generic HTTP handler
# Conflicts:
#	src/output/output_mp4.cpp
#	src/output/output_mp4.h
2021-10-19 22:29:41 +02:00

157 lines
4.6 KiB
C++

#include "output_http.h"
#include <list>
#include <mist/http_parser.h>
namespace Mist{
class keyPart{
public:
bool operator<(const keyPart &rhs) const{
if (time < rhs.time){return true;}
if (time > rhs.time){return false;}
if (trackID < rhs.trackID){return true;}
return (trackID == rhs.trackID && index < rhs.index);
}
size_t trackID;
uint64_t time;
uint64_t byteOffset; // Stores relative bpos for fragmented MP4
uint64_t index;
size_t sampleSize;
uint16_t sampleDuration;
uint16_t sampleOffset;
};
class SortSet{
private:
Util::ResizeablePointer ptr;
Util::ResizeablePointer avail;
size_t entries;
size_t currBegin;
void findBegin();
bool hasBegin;
public:
SortSet();
const keyPart & begin();
void erase();
bool empty();
void insert(const keyPart & part);
};
/// Class that implements a tiny subset of std::map, optimized for speed for our type of usage.
template <class T> class QuickMap{
private:
Util::ResizeablePointer ptr;
size_t entries;
public:
QuickMap(){
entries = 0;
}
~QuickMap(){
size_t len = 8 + sizeof(T*);
for (size_t i = 0; i < entries; ++i){
delete *(T**)(void*)(ptr+len*i+8);
}
}
T & get(uint64_t idx){
static T blank;
size_t len = 8 + sizeof(T*);
for (size_t i = 0; i < entries; ++i){
if (*((uint64_t*)(void*)(ptr+len*i)) == idx){
return **(T**)(void*)(ptr+len*i+8);
}
}
return blank;
}
void insert(uint64_t idx, T elem){
size_t i = 0;
size_t len = 8 + sizeof(T*);
for (i = 0; i < entries; ++i){
if (*((uint64_t*)(void*)(ptr+len*i)) == idx){
*(T**)(void*)(ptr+len*i+8) = new T(elem);
return;
}
}
entries = i+1;
ptr.allocate(len*entries);
*(T**)(void*)(ptr+len*i+8) = new T(elem);
*((uint64_t*)(void*)(ptr+len*i)) = idx;
}
};
struct fragSet{
uint64_t firstPart;
uint64_t lastPart;
uint64_t firstTime;
uint64_t lastTime;
};
class OutMP4 : public HTTPOutput{
public:
OutMP4(Socket::Connection &conn);
~OutMP4();
static void init(Util::Config *cfg);
uint64_t mp4HeaderSize(uint64_t &fileSize, int fragmented = 0) const;
bool mp4Header(Util::ResizeablePointer & headOut, uint64_t &size, int fragmented = 0);
uint64_t mp4moofSize(uint64_t startFragmentTime, uint64_t endFragmentTime, uint64_t &mdatSize) const;
virtual void sendFragmentHeaderTime(uint64_t startFragmentTime,
uint64_t endFragmentTime); // this builds the moof box for fragmented MP4
void findSeekPoint(uint64_t byteStart, uint64_t &seekPoint, uint64_t headerSize);
void appendSinglePacketMoof(Util::ResizeablePointer& moofOut, size_t extraBytes = 0);
size_t fragmentHeaderSize(std::deque<size_t>& sortedTracks, std::set<keyPart>& trunOrder, uint64_t startFragmentTime, uint64_t endFragmentTime);
void respondHTTP(const HTTP::Parser & req, bool headersOnly);
void sendNext();
void sendHeader();
bool doesWebsockets() { return true; }
void onWebsocketConnect();
void onWebsocketFrame();
void onIdle();
virtual bool onFinish();
protected:
void sendWebsocketCodecData(const std::string& type);
bool handleWebsocketSeek(JSON::Value& command);
bool handleWebsocketSetSpeed(JSON::Value& command);
bool stayLive;
double target_rate; ///< Target playback speed rate (1.0 = normal, 0 = auto)
uint64_t fileSize;
uint64_t byteStart;
uint64_t byteEnd;
int64_t leftOver;
uint64_t currPos;
uint64_t seekPoint;
uint64_t forwardTo;
uint64_t nextHeaderTime;
uint64_t headerSize;
size_t prevVidTrack;
// variables for standard MP4
std::set<keyPart> sortSet; // needed for unfragmented MP4, remembers the order of keyparts
// variables for fragmented
size_t fragSeqNum; // the sequence number of the next keyframe/fragment when producing
// fragmented MP4's
size_t vidTrack; // the video track we use as fragmenting base
uint64_t realBaseOffset; // base offset for every moof packet
// from sendnext
bool sending3GP;
uint64_t startTime;
uint64_t endTime;
bool chromeWorkaround;
int keysOnly;
uint64_t estimateFileSize() const;
// This is a dirty solution... but it prevents copying and copying and copying again
std::map<size_t, fragSet> currentPartSet;
std::string protectionHeader(size_t idx);
Util::ResizeablePointer webBuf;
};
}// namespace Mist
typedef Mist::OutMP4 mistOut;