161 lines
5.4 KiB
C++
161 lines
5.4 KiB
C++
/// \file dtsc.h
|
|
/// Holds all headers for DDVTECH Stream Container parsing/generation.
|
|
|
|
#pragma once
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <stdint.h> //for uint64_t
|
|
#include <string>
|
|
#include <deque>
|
|
#include <set>
|
|
#include <stdio.h> //for FILE
|
|
|
|
|
|
|
|
/// Holds all DDVTECH Stream Container classes and parsers.
|
|
///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)
|
|
///
|
|
///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<DTMI> 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<DTSC::DTMI> buffers;
|
|
std::set<DTSC::Ring *> rings;
|
|
std::deque<DTSC::Ring> keyframes;
|
|
void advanceRings();
|
|
std::string * datapointer;
|
|
datatype datapointertype;
|
|
unsigned int buffercount;
|
|
};
|
|
};
|