Almost working HTTP connector - mid-rewrite, running into some issues, sleepy, going to bed...
This commit is contained in:
parent
ae48440f4b
commit
63bf65952b
5 changed files with 296 additions and 17 deletions
|
@ -44,7 +44,7 @@ bool DTSC::Stream::parsePacket(std::string & buffer){
|
||||||
buffers.front() = DTSC::parseDTMI((unsigned char*)buffer.c_str() + 8, len);
|
buffers.front() = DTSC::parseDTMI((unsigned char*)buffer.c_str() + 8, len);
|
||||||
datapointertype = INVALID;
|
datapointertype = INVALID;
|
||||||
if (buffers.front().getContentP("data")){
|
if (buffers.front().getContentP("data")){
|
||||||
datapointer = buffers.front().getContentP("data")->StrValue().c_str();
|
datapointer = &(buffers.front().getContentP("data")->StrValue());
|
||||||
if (buffers.front().getContentP("datatype")){
|
if (buffers.front().getContentP("datatype")){
|
||||||
std::string tmp = buffers.front().getContentP("datatype")->StrValue();
|
std::string tmp = buffers.front().getContentP("datatype")->StrValue();
|
||||||
if (tmp == "video"){datapointertype = VIDEO;}
|
if (tmp == "video"){datapointertype = VIDEO;}
|
||||||
|
@ -68,8 +68,8 @@ bool DTSC::Stream::parsePacket(std::string & buffer){
|
||||||
|
|
||||||
/// Returns a direct pointer to the data attribute of the last received packet, if available.
|
/// Returns a direct pointer to the data attribute of the last received packet, if available.
|
||||||
/// Returns NULL if no valid pointer or packet is available.
|
/// Returns NULL if no valid pointer or packet is available.
|
||||||
const char * DTSC::Stream::lastData(){
|
std::string & DTSC::Stream::lastData(){
|
||||||
return datapointer;
|
return *datapointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the packed in this buffer number.
|
/// Returns the packed in this buffer number.
|
||||||
|
@ -177,11 +177,11 @@ DTSC::DTMItype DTSC::DTMI::GetType(){return myType;};
|
||||||
|
|
||||||
/// Returns the numeric value of this object, if available.
|
/// Returns the numeric value of this object, if available.
|
||||||
/// If this object holds no numeric value, 0 is returned.
|
/// If this object holds no numeric value, 0 is returned.
|
||||||
uint64_t DTSC::DTMI::NumValue(){return numval;};
|
uint64_t & DTSC::DTMI::NumValue(){return numval;};
|
||||||
|
|
||||||
/// Returns the std::string value of this object, if available.
|
/// Returns the std::string value of this object, if available.
|
||||||
/// If this object holds no string value, an empty string is returned.
|
/// If this object holds no string value, an empty string is returned.
|
||||||
std::string DTSC::DTMI::StrValue(){return strval;};
|
std::string & DTSC::DTMI::StrValue(){return strval;};
|
||||||
|
|
||||||
/// Returns the C-string value of this object, if available.
|
/// Returns the C-string value of this object, if available.
|
||||||
/// If this object holds no string value, an empty C-string is returned.
|
/// If this object holds no string value, an empty C-string is returned.
|
||||||
|
|
45
util/dtsc.h
45
util/dtsc.h
|
@ -9,16 +9,39 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
// video
|
|
||||||
// codec (string)
|
|
||||||
|
|
||||||
// audio
|
|
||||||
// codec (string)
|
|
||||||
// sampingrate (int, Hz)
|
|
||||||
// samplesize (int, bytesize)
|
|
||||||
// channels (int, channelcount)
|
|
||||||
|
|
||||||
/// Holds all DDVTECH Stream Container classes and parsers.
|
/// Holds all DDVTECH Stream Container classes and parsers.
|
||||||
|
///Video:
|
||||||
|
/// - codec (string: AAC, MP3)
|
||||||
|
/// - 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: H264, H263, VP6)
|
||||||
|
/// - 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{
|
namespace DTSC{
|
||||||
|
|
||||||
/// Enumerates all possible DTMI types.
|
/// Enumerates all possible DTMI types.
|
||||||
|
@ -35,8 +58,8 @@ namespace DTSC{
|
||||||
public:
|
public:
|
||||||
std::string Indice();
|
std::string Indice();
|
||||||
DTMItype GetType();
|
DTMItype GetType();
|
||||||
uint64_t NumValue();
|
uint64_t & NumValue();
|
||||||
std::string StrValue();
|
std::string & StrValue();
|
||||||
const char * Str();
|
const char * Str();
|
||||||
int hasContent();
|
int hasContent();
|
||||||
void addContent(DTMI c);
|
void addContent(DTMI c);
|
||||||
|
@ -99,7 +122,7 @@ namespace DTSC{
|
||||||
DTSC::DTMI metadata;
|
DTSC::DTMI metadata;
|
||||||
DTSC::DTMI & getPacket(unsigned int num = 0);
|
DTSC::DTMI & getPacket(unsigned int num = 0);
|
||||||
datatype lastType();
|
datatype lastType();
|
||||||
const char * lastData();
|
std::string & lastData();
|
||||||
bool hasVideo();
|
bool hasVideo();
|
||||||
bool hasAudio();
|
bool hasAudio();
|
||||||
bool parsePacket(std::string & buffer);
|
bool parsePacket(std::string & buffer);
|
||||||
|
@ -112,7 +135,7 @@ namespace DTSC{
|
||||||
std::set<DTSC::Ring *> rings;
|
std::set<DTSC::Ring *> rings;
|
||||||
std::deque<DTSC::Ring> keyframes;
|
std::deque<DTSC::Ring> keyframes;
|
||||||
void advanceRings();
|
void advanceRings();
|
||||||
const char * datapointer;
|
std::string * datapointer;
|
||||||
datatype datapointertype;
|
datatype datapointertype;
|
||||||
unsigned int buffercount;
|
unsigned int buffercount;
|
||||||
};
|
};
|
||||||
|
|
251
util/flv_tag.cpp
251
util/flv_tag.cpp
|
@ -2,6 +2,7 @@
|
||||||
/// Holds all code for the FLV namespace.
|
/// Holds all code for the FLV namespace.
|
||||||
|
|
||||||
#include "flv_tag.h"
|
#include "flv_tag.h"
|
||||||
|
#include "amf.h"
|
||||||
#include "rtmpchunks.h"
|
#include "rtmpchunks.h"
|
||||||
#include <stdio.h> //for Tag::FileLoader
|
#include <stdio.h> //for Tag::FileLoader
|
||||||
#include <unistd.h> //for Tag::FileLoader
|
#include <unistd.h> //for Tag::FileLoader
|
||||||
|
@ -245,6 +246,256 @@ FLV::Tag & FLV::Tag::operator= (const FLV::Tag& O){
|
||||||
return *this;
|
return *this;
|
||||||
}//assignment operator
|
}//assignment operator
|
||||||
|
|
||||||
|
/// FLV loader function from DTSC.
|
||||||
|
/// Takes the DTSC data and makes it into FLV.
|
||||||
|
bool FLV::Tag::DTSCLoader(DTSC::Stream & S){
|
||||||
|
switch (S.lastType()){
|
||||||
|
case DTSC::VIDEO:
|
||||||
|
len = S.lastData().length() + 16;
|
||||||
|
if (S.metadata.getContentP("video") && S.metadata.getContentP("video")->getContentP("codec")){
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H264"){len += 4;}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DTSC::AUDIO:
|
||||||
|
len = S.lastData().length() + 16;
|
||||||
|
if (S.metadata.getContentP("audio") && S.metadata.getContentP("audio")->getContentP("codec")){
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "AAC"){len += 1;}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DTSC::META:
|
||||||
|
len = S.lastData().length() + 15;
|
||||||
|
break;
|
||||||
|
default://ignore all other types (there are currently no other types...)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len > 0){
|
||||||
|
if (!data){
|
||||||
|
data = (char*)malloc(len);
|
||||||
|
buf = len;
|
||||||
|
}else{
|
||||||
|
if (buf < len){
|
||||||
|
data = (char*)realloc(data, len);
|
||||||
|
buf = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (S.lastType()){
|
||||||
|
case DTSC::VIDEO:
|
||||||
|
if ((unsigned int)len == S.lastData().length() + 16){
|
||||||
|
memcpy(data+12, S.lastData().c_str(), S.lastData().length());
|
||||||
|
}else{
|
||||||
|
memcpy(data+16, S.lastData().c_str(), S.lastData().length());
|
||||||
|
if (S.getPacket().getContentP("nalu")){data[12] = 1;}else{data[12] = 2;}
|
||||||
|
int offset = S.getPacket().getContentP("offset")->NumValue();
|
||||||
|
data[13] = (offset >> 16) & 0xFF;
|
||||||
|
data[14] = (offset >> 8) & 0XFF;
|
||||||
|
data[15] = offset & 0xFF;
|
||||||
|
}
|
||||||
|
data[11] = 0;
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H264"){data[11] += 7;}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H263"){data[11] += 2;}
|
||||||
|
if (S.getPacket().getContentP("keyframe")){data[11] += 0x10;}
|
||||||
|
if (S.getPacket().getContentP("interframe")){data[11] += 0x20;}
|
||||||
|
if (S.getPacket().getContentP("disposableframe")){data[11] += 0x30;}
|
||||||
|
break;
|
||||||
|
case DTSC::AUDIO:
|
||||||
|
if ((unsigned int)len == S.lastData().length() + 16){
|
||||||
|
memcpy(data+12, S.lastData().c_str(), S.lastData().length());
|
||||||
|
}else{
|
||||||
|
memcpy(data+13, S.lastData().c_str(), S.lastData().length());
|
||||||
|
data[12] = 1;//raw AAC data, not sequence header
|
||||||
|
}
|
||||||
|
data[11] = 0;
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "AAC"){data[11] += 0xA0;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "MP3"){data[11] += 0x20;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 11025){data[11] += 0x04;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 22050){data[11] += 0x08;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 44100){data[11] += 0x0C;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("size")->NumValue() == 16){data[11] += 0x02;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("channels")->NumValue() > 1){data[11] += 0x01;}
|
||||||
|
break;
|
||||||
|
case DTSC::META:
|
||||||
|
memcpy(data+11, S.lastData().c_str(), S.lastData().length());
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((unsigned int *)(data+len-4))[0] = len-15;
|
||||||
|
switch (S.lastType()){
|
||||||
|
case DTSC::VIDEO: data[0] = 0x09; break;
|
||||||
|
case DTSC::AUDIO: data[0] = 0x08; break;
|
||||||
|
case DTSC::META: data[0] = 0x12; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
data[1] = ((len-15) >> 16) & 0xFF;
|
||||||
|
data[2] = ((len-15) >> 8) & 0xFF;
|
||||||
|
data[3] = (len-15) & 0xFF;
|
||||||
|
tagTime(S.getPacket().getContentP("time")->NumValue());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FLV Video init data loader function from DTSC.
|
||||||
|
/// Takes the DTSC Video init data and makes it into FLV.
|
||||||
|
/// Assumes init data is available - so check before calling!
|
||||||
|
bool FLV::Tag::DTSCVideoInit(DTSC::Stream & S){
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H264"){
|
||||||
|
len = S.metadata.getContentP("video")->getContentP("init")->StrValue().length() + 20;
|
||||||
|
}
|
||||||
|
if (len > 0){
|
||||||
|
if (!data){
|
||||||
|
data = (char*)malloc(len);
|
||||||
|
buf = len;
|
||||||
|
}else{
|
||||||
|
if (buf < len){
|
||||||
|
data = (char*)realloc(data, len);
|
||||||
|
buf = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(data+16, S.metadata.getContentP("video")->getContentP("init")->StrValue().c_str(), len-20);
|
||||||
|
data[12] = 0;//H264 sequence header
|
||||||
|
data[13] = 0;
|
||||||
|
data[14] = 0;
|
||||||
|
data[15] = 0;
|
||||||
|
data[11] = 0x57;//H264 init data (0x07 & 0x50)
|
||||||
|
}
|
||||||
|
((unsigned int *)(data+len-4))[0] = len-15;
|
||||||
|
switch (S.lastType()){
|
||||||
|
case DTSC::VIDEO: data[0] = 0x09; break;
|
||||||
|
case DTSC::AUDIO: data[0] = 0x08; break;
|
||||||
|
case DTSC::META: data[0] = 0x12; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
data[1] = ((len-15) >> 16) & 0xFF;
|
||||||
|
data[2] = ((len-15) >> 8) & 0xFF;
|
||||||
|
data[3] = (len-15) & 0xFF;
|
||||||
|
tagTime(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FLV Audio init data loader function from DTSC.
|
||||||
|
/// Takes the DTSC Audio init data and makes it into FLV.
|
||||||
|
/// Assumes init data is available - so check before calling!
|
||||||
|
bool FLV::Tag::DTSCAudioInit(DTSC::Stream & S){
|
||||||
|
len = 0;
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "AAC"){
|
||||||
|
len = S.metadata.getContentP("audio")->getContentP("init")->StrValue().length() + 17;
|
||||||
|
}
|
||||||
|
if (len > 0){
|
||||||
|
if (!data){
|
||||||
|
data = (char*)malloc(len);
|
||||||
|
buf = len;
|
||||||
|
}else{
|
||||||
|
if (buf < len){
|
||||||
|
data = (char*)realloc(data, len);
|
||||||
|
buf = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(data+13, S.metadata.getContentP("audio")->getContentP("init")->StrValue().c_str(), len-17);
|
||||||
|
data[12] = 0;//AAC sequence header
|
||||||
|
data[11] = 0;
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "AAC"){data[11] += 0xA0;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "MP3"){data[11] += 0x20;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 11000){data[11] += 0x04;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 22000){data[11] += 0x08;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")->NumValue() == 44000){data[11] += 0x0C;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("size")->NumValue() == 16){data[11] += 0x02;}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("channels")->NumValue() > 1){data[11] += 0x01;}
|
||||||
|
}
|
||||||
|
((unsigned int *)(data+len-4))[0] = len-15;
|
||||||
|
switch (S.lastType()){
|
||||||
|
case DTSC::VIDEO: data[0] = 0x09; break;
|
||||||
|
case DTSC::AUDIO: data[0] = 0x08; break;
|
||||||
|
case DTSC::META: data[0] = 0x12; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
data[1] = ((len-15) >> 16) & 0xFF;
|
||||||
|
data[2] = ((len-15) >> 8) & 0xFF;
|
||||||
|
data[3] = (len-15) & 0xFF;
|
||||||
|
tagTime(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FLV metadata loader function from DTSC.
|
||||||
|
/// Takes the DTSC metadata and makes it into FLV.
|
||||||
|
/// Assumes metadata is available - so check before calling!
|
||||||
|
bool FLV::Tag::DTSCMetaInit(DTSC::Stream & S){
|
||||||
|
AMF::Object amfdata("root", AMF::AMF0_DDV_CONTAINER);
|
||||||
|
|
||||||
|
amfdata.addContent(AMF::Object("", "onMetaData"));
|
||||||
|
amfdata.addContent(AMF::Object("", AMF::AMF0_ECMA_ARRAY));
|
||||||
|
if (S.metadata.getContentP("video")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("hasVideo", 1, AMF::AMF0_BOOL));
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H264"){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 7, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "VP6"){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 4, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("codec")->StrValue() == "H263"){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 2, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("width")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("width", S.metadata.getContentP("video")->getContentP("width")->NumValue(), AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("height")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("height", S.metadata.getContentP("video")->getContentP("height")->NumValue(), AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("fpks")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("framerate", (double)S.metadata.getContentP("video")->getContentP("fpks")->NumValue() / 1000.0, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("video")->getContentP("bps")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("videodatarate", ((double)S.metadata.getContentP("video")->getContentP("bps")->NumValue() * 8.0) / 1024.0, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("hasAudio", 1, AMF::AMF0_BOOL));
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiodelay", 0, AMF::AMF0_NUMBER));
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "AAC"){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", 10, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("codec")->StrValue() == "MP3"){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", 2, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("channels")){
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("channels")->NumValue() > 1){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("stereo", 1, AMF::AMF0_BOOL));
|
||||||
|
}else{
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("stereo", 0, AMF::AMF0_BOOL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("rate")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplerate", S.metadata.getContentP("audio")->getContentP("rate")->NumValue(), AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("size")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplesize", S.metadata.getContentP("audio")->getContentP("size")->NumValue(), AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
if (S.metadata.getContentP("audio")->getContentP("bps")){
|
||||||
|
amfdata.getContentP(1)->addContent(AMF::Object("audiodatarate", ((double)S.metadata.getContentP("audio")->getContentP("bps")->NumValue() * 8.0) / 1024.0, AMF::AMF0_NUMBER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp = amfdata.Pack();
|
||||||
|
len = tmp.length() + 15;
|
||||||
|
if (len > 0){
|
||||||
|
if (!data){
|
||||||
|
data = (char*)malloc(len);
|
||||||
|
buf = len;
|
||||||
|
}else{
|
||||||
|
if (buf < len){
|
||||||
|
data = (char*)realloc(data, len);
|
||||||
|
buf = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(data+11, tmp.c_str(), len-15);
|
||||||
|
}
|
||||||
|
((unsigned int *)(data+len-4))[0] = len-15;
|
||||||
|
data[0] = 0x12;
|
||||||
|
data[1] = ((len-15) >> 16) & 0xFF;
|
||||||
|
data[2] = ((len-15) >> 8) & 0xFF;
|
||||||
|
data[3] = (len-15) & 0xFF;
|
||||||
|
tagTime(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// FLV loader function from chunk.
|
/// FLV loader function from chunk.
|
||||||
/// Copies the contents and wraps it in a FLV header.
|
/// Copies the contents and wraps it in a FLV header.
|
||||||
bool FLV::Tag::ChunkLoader(const RTMPStream::Chunk& O){
|
bool FLV::Tag::ChunkLoader(const RTMPStream::Chunk& O){
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include "dtsc.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//forward declaration of RTMPStream::Chunk to avoid circular dependencies.
|
//forward declaration of RTMPStream::Chunk to avoid circular dependencies.
|
||||||
|
@ -38,6 +39,10 @@ namespace FLV {
|
||||||
Tag(const RTMPStream::Chunk& O); ///<Copy constructor from a RTMP chunk.
|
Tag(const RTMPStream::Chunk& O); ///<Copy constructor from a RTMP chunk.
|
||||||
//loader functions
|
//loader functions
|
||||||
bool ChunkLoader(const RTMPStream::Chunk& O);
|
bool ChunkLoader(const RTMPStream::Chunk& O);
|
||||||
|
bool DTSCLoader(DTSC::Stream & S);
|
||||||
|
bool DTSCVideoInit(DTSC::Stream & S);
|
||||||
|
bool DTSCAudioInit(DTSC::Stream & S);
|
||||||
|
bool DTSCMetaInit(DTSC::Stream & S);
|
||||||
bool MemLoader(char * D, unsigned int S, unsigned int & P);
|
bool MemLoader(char * D, unsigned int S, unsigned int & P);
|
||||||
bool SockLoader(int sock);
|
bool SockLoader(int sock);
|
||||||
bool SockLoader(Socket::Connection sock);
|
bool SockLoader(Socket::Connection sock);
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace Socket{
|
||||||
int iwrite(const void * buffer, int len); ///< Incremental write call.
|
int iwrite(const void * buffer, int len); ///< Incremental write call.
|
||||||
int iread(void * buffer, int len); ///< Incremental read call.
|
int iread(void * buffer, int len); ///< Incremental read call.
|
||||||
bool read(std::string & buffer); ///< Read call that is compatible with std::string.
|
bool read(std::string & buffer); ///< Read call that is compatible with std::string.
|
||||||
bool swrite(std::string & buffer); ///< Read call that is compatible with std::string.
|
bool swrite(std::string & buffer); ///< Write call that is compatible with std::string.
|
||||||
bool iread(std::string & buffer); ///< Incremental write call that is compatible with std::string.
|
bool iread(std::string & buffer); ///< Incremental write call that is compatible with std::string.
|
||||||
bool iwrite(std::string & buffer); ///< Write call that is compatible with std::string.
|
bool iwrite(std::string & buffer); ///< Write call that is compatible with std::string.
|
||||||
void spool(); ///< Updates the downbuffer and upbuffer internal variables.
|
void spool(); ///< Updates the downbuffer and upbuffer internal variables.
|
||||||
|
|
Loading…
Add table
Reference in a new issue