A few bugfixes and improvements in the FLV2DTSC code. Also, moved conversion logic to flv_tag.cpp/h instead of keeping it inside the conversion tool itself.
This commit is contained in:
parent
8294656515
commit
f615427c95
4 changed files with 193 additions and 2 deletions
|
@ -198,6 +198,13 @@ const char * DTSC::DTMI::Str(){return strval.c_str();};
|
|||
/// If this object is not a container type, this function will always return 0.
|
||||
int DTSC::DTMI::hasContent(){return contents.size();};
|
||||
|
||||
/// Returns true if this DTSC::DTMI value is non-default.
|
||||
/// Non-default means it is either not a root element or has content.
|
||||
bool DTSC::DTMI::isEmpty(){
|
||||
if (myType != DTMI_ROOT){return false;}
|
||||
return (hasContent() == 0);
|
||||
};
|
||||
|
||||
/// Adds an DTSC::DTMI to this object. Works for all types, but only makes sense for container types.
|
||||
/// This function resets DTMI::packed to an empty string, forcing a repack on the next call to DTMI::Pack.
|
||||
/// If the indice name already exists, replaces the indice.
|
||||
|
@ -213,9 +220,12 @@ void DTSC::DTMI::addContent(DTSC::DTMI c){
|
|||
};
|
||||
|
||||
/// Returns a pointer to the object held at indice i.
|
||||
/// Returns AMF::AMF0_DDV_CONTAINER of indice "error" if no object is held at this indice.
|
||||
/// Returns null pointer if no object is held at this indice.
|
||||
/// \param i The indice of the object in this container.
|
||||
DTSC::DTMI* DTSC::DTMI::getContentP(int i){return &contents.at(i);};
|
||||
DTSC::DTMI* DTSC::DTMI::getContentP(int i){
|
||||
if (contents.size() <= (unsigned int)i){return 0;}
|
||||
return &contents.at(i);
|
||||
};
|
||||
|
||||
/// Returns a copy of the object held at indice i.
|
||||
/// Returns a AMF::AMF0_DDV_CONTAINER of indice "error" if no object is held at this indice.
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace DTSC{
|
|||
std::string & StrValue();
|
||||
const char * Str();
|
||||
int hasContent();
|
||||
bool isEmpty();
|
||||
void addContent(DTMI c);
|
||||
DTMI* getContentP(int i);
|
||||
DTMI getContent(int i);
|
||||
|
|
175
util/flv_tag.cpp
175
util/flv_tag.cpp
|
@ -771,3 +771,178 @@ bool FLV::Tag::FileLoader(FILE * f){
|
|||
fcntl(fileno(f), F_SETFL, preflags);
|
||||
return false;
|
||||
}//FLV_GetPacket
|
||||
|
||||
DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){
|
||||
DTSC::DTMI pack_out; // Storage for outgoing DTMI data.
|
||||
|
||||
if (data[0] == 0x12){
|
||||
AMF::Object meta_in = AMF::parse((unsigned char*)data+11, len-15);
|
||||
if (meta_in.getContentP(0) && (meta_in.getContentP(0)->StrValue() == "onMetaData") && meta_in.getContentP(1)){
|
||||
AMF::Object * tmp = meta_in.getContentP(1);
|
||||
if (tmp->getContentP("videocodecid")){
|
||||
switch ((unsigned int)tmp->getContentP("videocodecid")->NumValue()){
|
||||
case 2: Meta_Put(metadata, "video", "codec", "H263"); break;
|
||||
case 4: Meta_Put(metadata, "video", "codec", "VP6"); break;
|
||||
case 7: Meta_Put(metadata, "video", "codec", "H264"); break;
|
||||
default: Meta_Put(metadata, "video", "codec", "?"); break;
|
||||
}
|
||||
}
|
||||
if (tmp->getContentP("audiocodecid")){
|
||||
switch ((unsigned int)tmp->getContentP("audiocodecid")->NumValue()){
|
||||
case 2: Meta_Put(metadata, "audio", "codec", "MP3"); break;
|
||||
case 10: Meta_Put(metadata, "audio", "codec", "AAC"); break;
|
||||
default: Meta_Put(metadata, "audio", "codec", "?"); break;
|
||||
}
|
||||
}
|
||||
if (tmp->getContentP("width")){
|
||||
Meta_Put(metadata, "video", "width", tmp->getContentP("width")->NumValue());
|
||||
}
|
||||
if (tmp->getContentP("height")){
|
||||
Meta_Put(metadata, "video", "height", tmp->getContentP("height")->NumValue());
|
||||
}
|
||||
if (tmp->getContentP("framerate")){
|
||||
Meta_Put(metadata, "video", "fpks", tmp->getContentP("framerate")->NumValue()*1000);
|
||||
}
|
||||
if (tmp->getContentP("videodatarate")){
|
||||
Meta_Put(metadata, "video", "bps", (tmp->getContentP("videodatarate")->NumValue()*1024)/8);
|
||||
}
|
||||
if (tmp->getContentP("audiodatarate")){
|
||||
Meta_Put(metadata, "audio", "bps", (tmp->getContentP("audiodatarate")->NumValue()*1024)/8);
|
||||
}
|
||||
if (tmp->getContentP("audiosamplerate")){
|
||||
Meta_Put(metadata, "audio", "rate", tmp->getContentP("audiosamplerate")->NumValue());
|
||||
}
|
||||
if (tmp->getContentP("audiosamplesize")){
|
||||
Meta_Put(metadata, "audio", "size", tmp->getContentP("audiosamplesize")->NumValue());
|
||||
}
|
||||
if (tmp->getContentP("stereo")){
|
||||
if (tmp->getContentP("stereo")->NumValue() == 1){
|
||||
Meta_Put(metadata, "audio", "channels", 2);
|
||||
}else{
|
||||
Meta_Put(metadata, "audio", "channels", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pack_out;//empty
|
||||
}
|
||||
if (data[0] == 0x08){
|
||||
char audiodata = data[11];
|
||||
if (needsInitData() && isInitData()){
|
||||
if ((audiodata & 0xF0) == 0xA0){
|
||||
Meta_Put(metadata, "audio", "init", std::string((char*)data+13, (size_t)len-17));
|
||||
}else{
|
||||
Meta_Put(metadata, "audio", "init", std::string((char*)data+12, (size_t)len-16));
|
||||
}
|
||||
return pack_out;//skip rest of parsing, get next tag.
|
||||
}
|
||||
pack_out = DTSC::DTMI("audio", DTSC::DTMI_ROOT);
|
||||
pack_out.addContent(DTSC::DTMI("datatype", "audio"));
|
||||
pack_out.addContent(DTSC::DTMI("time", tagTime()));
|
||||
if (!Meta_Has(metadata, "audio", "codec")){
|
||||
switch (audiodata & 0xF0){
|
||||
case 0x20: Meta_Put(metadata, "audio", "codec", "MP3"); break;
|
||||
case 0xA0: Meta_Put(metadata, "audio", "codec", "AAC"); break;
|
||||
default: Meta_Put(metadata, "audio", "codec", "?"); break;
|
||||
}
|
||||
}
|
||||
if (!Meta_Has(metadata, "audio", "rate")){
|
||||
switch (audiodata & 0x0C){
|
||||
case 0x0: Meta_Put(metadata, "audio", "rate", 5512); break;
|
||||
case 0x4: Meta_Put(metadata, "audio", "rate", 11025); break;
|
||||
case 0x8: Meta_Put(metadata, "audio", "rate", 22050); break;
|
||||
case 0xC: Meta_Put(metadata, "audio", "rate", 44100); break;
|
||||
}
|
||||
}
|
||||
if (!Meta_Has(metadata, "audio", "size")){
|
||||
switch (audiodata & 0x02){
|
||||
case 0x0: Meta_Put(metadata, "audio", "size", 8); break;
|
||||
case 0x2: Meta_Put(metadata, "audio", "size", 16); break;
|
||||
}
|
||||
}
|
||||
if (!Meta_Has(metadata, "audio", "channels")){
|
||||
switch (audiodata & 0x01){
|
||||
case 0x0: Meta_Put(metadata, "audio", "channels", 1); break;
|
||||
case 0x1: Meta_Put(metadata, "audio", "channels", 2); break;
|
||||
}
|
||||
}
|
||||
if ((audiodata & 0xF0) == 0xA0){
|
||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+13, (size_t)len-17)));
|
||||
}else{
|
||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16)));
|
||||
}
|
||||
return pack_out;
|
||||
}
|
||||
if (data[0] == 0x09){
|
||||
char videodata = data[11];
|
||||
if (needsInitData() && isInitData()){
|
||||
if ((videodata & 0x0F) == 7){
|
||||
Meta_Put(metadata, "video", "init", std::string((char*)data+16, (size_t)len-20));
|
||||
}else{
|
||||
Meta_Put(metadata, "video", "init", std::string((char*)data+12, (size_t)len-16));
|
||||
}
|
||||
return pack_out;//skip rest of parsing, get next tag.
|
||||
}
|
||||
if (!Meta_Has(metadata, "video", "codec")){
|
||||
switch (videodata & 0x0F){
|
||||
case 2: Meta_Put(metadata, "video", "codec", "H263"); break;
|
||||
case 4: Meta_Put(metadata, "video", "codec", "VP6"); break;
|
||||
case 7: Meta_Put(metadata, "video", "codec", "H264"); break;
|
||||
default: Meta_Put(metadata, "video", "codec", "?"); break;
|
||||
}
|
||||
}
|
||||
pack_out = DTSC::DTMI("video", DTSC::DTMI_ROOT);
|
||||
pack_out.addContent(DTSC::DTMI("datatype", "video"));
|
||||
switch (videodata & 0xF0){
|
||||
case 0x10: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break;
|
||||
case 0x20: pack_out.addContent(DTSC::DTMI("interframe", 1)); break;
|
||||
case 0x30: pack_out.addContent(DTSC::DTMI("disposableframe", 1)); break;
|
||||
case 0x40: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break;
|
||||
case 0x50: return DTSC::DTMI(); break;//the video info byte we just throw away - useless to us...
|
||||
}
|
||||
pack_out.addContent(DTSC::DTMI("time", tagTime()));
|
||||
if ((videodata & 0x0F) == 7){
|
||||
switch (data[12]){
|
||||
case 1: pack_out.addContent(DTSC::DTMI("nalu", 1)); break;
|
||||
case 2: pack_out.addContent(DTSC::DTMI("nalu_end", 1)); break;
|
||||
}
|
||||
int offset = (data[13] << 16) + (data[14] << 8) + data[15];
|
||||
offset = (offset << 8) >> 8;
|
||||
pack_out.addContent(DTSC::DTMI("offset", offset));
|
||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+16, (size_t)len-20)));
|
||||
}else{
|
||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16)));
|
||||
}
|
||||
return pack_out;
|
||||
}
|
||||
return pack_out;//should never get here
|
||||
}//FLV::Tag::toDTSC
|
||||
|
||||
/// Inserts std::string type metadata into the passed DTMI object.
|
||||
/// \arg meta The DTMI object to put the metadata into.
|
||||
/// \arg cat Metadata category to insert into.
|
||||
/// \arg elem Element name to put into the category.
|
||||
/// \arg val Value to put into the element name.
|
||||
void FLV::Tag::Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val){
|
||||
if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));}
|
||||
meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val));
|
||||
}
|
||||
|
||||
/// Inserts uint64_t type metadata into the passed DTMI object.
|
||||
/// \arg meta The DTMI object to put the metadata into.
|
||||
/// \arg cat Metadata category to insert into.
|
||||
/// \arg elem Element name to put into the category.
|
||||
/// \arg val Value to put into the element name.
|
||||
void FLV::Tag::Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, uint64_t val){
|
||||
if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));}
|
||||
meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val));
|
||||
}
|
||||
|
||||
/// Returns true if the named category and elementname are available in the metadata.
|
||||
/// \arg meta The DTMI object to check.
|
||||
/// \arg cat Metadata category to check.
|
||||
/// \arg elem Element name to check.
|
||||
bool FLV::Tag::Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem){
|
||||
if (meta.getContentP(cat) == 0){return false;}
|
||||
if (meta.getContentP(cat)->getContentP(elem) == 0){return false;}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace FLV {
|
|||
bool DTSCVideoInit(DTSC::Stream & S);
|
||||
bool DTSCAudioInit(DTSC::Stream & S);
|
||||
bool DTSCMetaInit(DTSC::Stream & S);
|
||||
DTSC::DTMI toDTSC(DTSC::DTMI & metadata);
|
||||
bool MemLoader(char * D, unsigned int S, unsigned int & P);
|
||||
bool SockLoader(int sock);
|
||||
bool SockLoader(Socket::Connection sock);
|
||||
|
@ -56,6 +57,10 @@ namespace FLV {
|
|||
bool MemReadUntil(char * buffer, unsigned int count, unsigned int & sofar, char * D, unsigned int S, unsigned int & P);
|
||||
bool SockReadUntil(char * buffer, unsigned int count, unsigned int & sofar, Socket::Connection & sock);
|
||||
bool FileReadUntil(char * buffer, unsigned int count, unsigned int & sofar, FILE * f);
|
||||
//DTSC writer helpers
|
||||
void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val);
|
||||
void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, uint64_t val);
|
||||
bool Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem);
|
||||
};//Tag
|
||||
|
||||
};//FLV namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue