/// \file dtsc.h /// Holds all headers for DDVTECH Stream Container parsing/generation. #pragma once #include #include #include //for uint64_t #include #include #include #include //for FILE /// Holds all DDVTECH Stream Container classes and parsers. ///length (int, length in seconds, if available) ///video: /// - codec (string: H264, H263, VP6) /// - width (int, pixels) /// - height (int, pixels) /// - fpks (int, frames per kilosecond (FPS * 1000)) /// - bps (int, bytes per second) /// - init (string, init data) /// - keyms (int, average ms per keyframe) /// - keyvar (int, max ms per keyframe variance) /// - keys (array of byte position ints - first is first keyframe, last is last keyframe, in between have ~equal spacing) /// ///audio: /// - codec (string: AAC, MP3) /// - rate (int, Hz) /// - size (int, bitsize) /// - bps (int, bytes per second) /// - channels (int, channelcount) /// - init (string, init data) /// ///All packets: /// - datatype (string: audio, video, meta (unused)) /// - data (string: data) /// - time (int: ms into video) /// ///Video packets: /// - keyframe (int, if set, is a seekable keyframe) /// - interframe (int, if set, is a non-seekable interframe) /// - disposableframe (int, if set, is a disposable interframe) /// ///H264 video packets: /// - nalu (int, if set, is a nalu) /// - nalu_end (int, if set, is a end-of-sequence) /// - offset (int, unsigned version of signed int! Holds the ms offset between timestamp and proper display time for B-frames) namespace DTSC{ /// Enumerates all possible DTMI types. enum DTMItype { DTMI_INT = 0x01, ///< Unsigned 64-bit integer. DTMI_STRING = 0x02, ///< String, equivalent to the AMF longstring type. DTMI_OBJECT = 0xE0, ///< Object, equivalent to the AMF object type. DTMI_OBJ_END = 0xEE, ///< End of object marker. DTMI_ROOT = 0xFF ///< Root node for all DTMI data. }; /// Recursive class that holds DDVTECH MediaInfo. class DTMI { public: std::string Indice(); DTMItype GetType(); uint64_t & NumValue(); std::string & StrValue(); const char * Str(); int hasContent(); bool isEmpty(); void addContent(DTMI c); DTMI* getContentP(int i); DTMI getContent(int i); DTMI* getContentP(std::string s); DTMI getContent(std::string s); DTMI(); DTMI(std::string indice, uint64_t val, DTMItype setType = DTMI_INT); DTMI(std::string indice, std::string val, DTMItype setType = DTMI_STRING); DTMI(std::string indice, DTMItype setType = DTMI_OBJECT); void Print(std::string indent = ""); std::string Pack(bool netpack = false); bool netpacked; std::string packed; protected: std::string myIndice; ///< Holds this objects indice, if any. DTMItype myType; ///< Holds this objects AMF0 type. std::string strval; ///< Holds this objects string value, if any. uint64_t numval; ///< Holds this objects numeric value, if any. std::vector contents; ///< Holds this objects contents, if any (for container types). };//AMFType /// Parses a C-string to a valid DTSC::DTMI. DTMI parseDTMI(const unsigned char * data, unsigned int len); /// Parses a std::string to a valid DTSC::DTMI. DTMI parseDTMI(std::string data); /// Parses a single DTMI type - used recursively by the DTSC::parseDTMI() functions. DTMI parseOneDTMI(const unsigned char *& data, unsigned int &len, unsigned int &i, std::string name); /// This enum holds all possible datatypes for DTSC packets. enum datatype { AUDIO, ///< Stream Audio data VIDEO, ///< Stream Video data META, ///< Stream Metadata 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 /// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it. class File{ public: File(std::string filename, bool create = false); ~File(); std::string & getHeader(); bool writeHeader(std::string & header, bool force = false); std::string & getPacket(); private: std::string strbuffer; FILE * F; long headerSize; char buffer[4]; };//FileWriter /// A part from the DTSC::Stream ringbuffer. /// Holds information about a buffer that will stay consistent class Ring { public: Ring(unsigned int v); volatile unsigned int b; ///< Holds current number of buffer. May and is intended to change unexpectedly! volatile bool waiting; ///< If true, this Ring is currently waiting for a buffer fill. volatile bool starved; ///< If true, this Ring can no longer receive valid data. }; /// Holds temporary data for a DTSC stream and provides functions to utilize it. /// Optionally also acts as a ring buffer of a certain requested size. /// If ring buffering mode is enabled, it will automatically grow in size to always contain at least one keyframe. class Stream { public: Stream(); ~Stream(); Stream(unsigned int buffers); DTSC::DTMI metadata; DTSC::DTMI & getPacket(unsigned int num = 0); datatype lastType(); std::string & lastData(); bool hasVideo(); bool hasAudio(); bool parsePacket(std::string & buffer); std::string & outPacket(unsigned int num); std::string & outHeader(); Ring * getRing(); unsigned int getTime(); void dropRing(Ring * ptr); private: std::deque buffers; std::set rings; std::deque keyframes; void advanceRings(); std::string * datapointer; datatype datapointertype; unsigned int buffercount; }; };