Half-updated flv_tag with JSON metadata support.
This commit is contained in:
parent
75a420db2a
commit
48bf3d189a
2 changed files with 85 additions and 102 deletions
176
lib/flv_tag.cpp
176
lib/flv_tag.cpp
|
@ -772,8 +772,8 @@ bool FLV::Tag::FileLoader(FILE * f){
|
||||||
return false;
|
return false;
|
||||||
}//FLV_GetPacket
|
}//FLV_GetPacket
|
||||||
|
|
||||||
DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){
|
JSON::Value FLV::Tag::toJSON(JSON::Value & metadata){
|
||||||
DTSC::DTMI pack_out; // Storage for outgoing DTMI data.
|
JSON::Value pack_out; // Storage for outgoing metadata.
|
||||||
|
|
||||||
if (data[0] == 0x12){
|
if (data[0] == 0x12){
|
||||||
AMF::Object meta_in = AMF::parse((unsigned char*)data+11, len-15);
|
AMF::Object meta_in = AMF::parse((unsigned char*)data+11, len-15);
|
||||||
|
@ -781,45 +781,59 @@ DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){
|
||||||
AMF::Object * tmp = meta_in.getContentP(1);
|
AMF::Object * tmp = meta_in.getContentP(1);
|
||||||
if (tmp->getContentP("videocodecid")){
|
if (tmp->getContentP("videocodecid")){
|
||||||
switch ((unsigned int)tmp->getContentP("videocodecid")->NumValue()){
|
switch ((unsigned int)tmp->getContentP("videocodecid")->NumValue()){
|
||||||
case 2: Meta_Put(metadata, "video", "codec", "H263"); break;
|
case 2: metadata["video"]["codec"] = "H263"; break;
|
||||||
case 4: Meta_Put(metadata, "video", "codec", "VP6"); break;
|
case 4: metadata["video"]["codec"] = "VP6"; break;
|
||||||
case 7: Meta_Put(metadata, "video", "codec", "H264"); break;
|
case 7: metadata["video"]["codec"] = "H264"; break;
|
||||||
default: Meta_Put(metadata, "video", "codec", "?"); break;
|
default: metadata["video"]["codec"] = "?"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("audiocodecid")){
|
if (tmp->getContentP("audiocodecid")){
|
||||||
switch ((unsigned int)tmp->getContentP("audiocodecid")->NumValue()){
|
switch ((unsigned int)tmp->getContentP("audiocodecid")->NumValue()){
|
||||||
case 2: Meta_Put(metadata, "audio", "codec", "MP3"); break;
|
case 2: metadata["audio"]["codec"] = "MP3"; break;
|
||||||
case 10: Meta_Put(metadata, "audio", "codec", "AAC"); break;
|
case 10: metadata["audio"]["codec"] = "AAC"; break;
|
||||||
default: Meta_Put(metadata, "audio", "codec", "?"); break;
|
default: metadata["audio"]["codec"] = "?"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("width")){
|
if (tmp->getContentP("width")){
|
||||||
Meta_Put(metadata, "video", "width", (unsigned long long int)tmp->getContentP("width")->NumValue());
|
metadata["video"]["width"] = (long long int)tmp->getContentP("width")->NumValue();
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("height")){
|
if (tmp->getContentP("height")){
|
||||||
Meta_Put(metadata, "video", "height", (unsigned long long int)tmp->getContentP("height")->NumValue());
|
metadata["video"]["height"] = (long long int)tmp->getContentP("height")->NumValue();
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("framerate")){
|
if (tmp->getContentP("framerate")){
|
||||||
Meta_Put(metadata, "video", "fpks", (unsigned long long int)tmp->getContentP("framerate")->NumValue()*1000);
|
metadata["video"]["fpks"] = (long long int)tmp->getContentP("framerate")->NumValue()*1000;
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("videodatarate")){
|
if (tmp->getContentP("videodatarate")){
|
||||||
Meta_Put(metadata, "video", "bps", (unsigned long long int)(tmp->getContentP("videodatarate")->NumValue()*1024)/8);
|
metadata["video"]["bps"] = (long long int)(tmp->getContentP("videodatarate")->NumValue()*1024)/8;
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("audiodatarate")){
|
if (tmp->getContentP("audiodatarate")){
|
||||||
Meta_Put(metadata, "audio", "bps", (unsigned long long int)(tmp->getContentP("audiodatarate")->NumValue()*1024)/8);
|
metadata["audio"]["bps"] = (long long int)(tmp->getContentP("audiodatarate")->NumValue()*1024)/8;
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("audiosamplerate")){
|
if (tmp->getContentP("audiosamplerate")){
|
||||||
Meta_Put(metadata, "audio", "rate", (unsigned long long int)tmp->getContentP("audiosamplerate")->NumValue());
|
metadata["audio"]["rate"] = (long long int)tmp->getContentP("audiosamplerate")->NumValue();
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("audiosamplesize")){
|
if (tmp->getContentP("audiosamplesize")){
|
||||||
Meta_Put(metadata, "audio", "size", (unsigned long long int)tmp->getContentP("audiosamplesize")->NumValue());
|
metadata["audio"]["size"] = (long long int)tmp->getContentP("audiosamplesize")->NumValue();
|
||||||
}
|
}
|
||||||
if (tmp->getContentP("stereo")){
|
if (tmp->getContentP("stereo")){
|
||||||
if (tmp->getContentP("stereo")->NumValue() == 1){
|
if (tmp->getContentP("stereo")->NumValue() == 1){
|
||||||
Meta_Put(metadata, "audio", "channels", 2);
|
metadata["audio"]["channels"] = 2;
|
||||||
}else{
|
}else{
|
||||||
Meta_Put(metadata, "audio", "channels", 1);
|
metadata["audio"]["channels"] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!metadata.isMember("length")){metadata["length"] = 0;}
|
||||||
|
if (metadata.isMember("video")){
|
||||||
|
if (!metadata["video"].isMember("width")){metadata["video"]["width"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("height")){metadata["video"]["height"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("fpks")){metadata["video"]["fpks"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("bps")){metadata["video"]["bps"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("keyms")){metadata["video"]["keyms"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("keyvar")){metadata["video"]["keyvar"] = 0;}
|
||||||
|
if (!metadata["video"].isMember("keys")){
|
||||||
|
while (metadata["video"]["keys"].size() < 100){
|
||||||
|
metadata["video"]["keys"].append(JSON::Value((long long int)0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,48 +843,47 @@ DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){
|
||||||
char audiodata = data[11];
|
char audiodata = data[11];
|
||||||
if (needsInitData() && isInitData()){
|
if (needsInitData() && isInitData()){
|
||||||
if ((audiodata & 0xF0) == 0xA0){
|
if ((audiodata & 0xF0) == 0xA0){
|
||||||
Meta_Put(metadata, "audio", "init", std::string((char*)data+13, (size_t)len-17));
|
metadata["audio"]["init"] = std::string((char*)data+13, (size_t)len-17);
|
||||||
}else{
|
}else{
|
||||||
Meta_Put(metadata, "audio", "init", std::string((char*)data+12, (size_t)len-16));
|
metadata["audio"]["init"] = std::string((char*)data+12, (size_t)len-16);
|
||||||
}
|
}
|
||||||
return pack_out;//skip rest of parsing, get next tag.
|
return pack_out;//skip rest of parsing, get next tag.
|
||||||
}
|
}
|
||||||
pack_out = DTSC::DTMI("audio", DTSC::DTMI_ROOT);
|
pack_out["datatype"] = "audio";
|
||||||
pack_out.addContent(DTSC::DTMI("datatype", "audio"));
|
pack_out["time"] = tagTime();
|
||||||
pack_out.addContent(DTSC::DTMI("time", tagTime()));
|
if (!metadata["audio"].isMember("codec") || metadata["audio"]["size"].asString() == ""){
|
||||||
if (!Meta_Has(metadata, "audio", "codec")){
|
|
||||||
switch (audiodata & 0xF0){
|
switch (audiodata & 0xF0){
|
||||||
case 0x20: Meta_Put(metadata, "audio", "codec", "MP3"); break;
|
case 0x20: metadata["audio"]["codec"] = "MP3"; break;
|
||||||
case 0xA0: Meta_Put(metadata, "audio", "codec", "AAC"); break;
|
case 0xA0: metadata["audio"]["codec"] = "AAC"; break;
|
||||||
default: Meta_Put(metadata, "audio", "codec", "?"); break;
|
default: metadata["audio"]["codec"] = "?"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Meta_Has(metadata, "audio", "rate")){
|
if (!metadata["audio"].isMember("rate") || metadata["audio"]["rate"].asInt() < 1){
|
||||||
switch (audiodata & 0x0C){
|
switch (audiodata & 0x0C){
|
||||||
case 0x0: Meta_Put(metadata, "audio", "rate", 5512); break;
|
case 0x0: metadata["audio"]["rate"] = 5512; break;
|
||||||
case 0x4: Meta_Put(metadata, "audio", "rate", 11025); break;
|
case 0x4: metadata["audio"]["rate"] = 11025; break;
|
||||||
case 0x8: Meta_Put(metadata, "audio", "rate", 22050); break;
|
case 0x8: metadata["audio"]["rate"] = 22050; break;
|
||||||
case 0xC: Meta_Put(metadata, "audio", "rate", 44100); break;
|
case 0xC: metadata["audio"]["rate"] = 44100; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Meta_Has(metadata, "audio", "size")){
|
if (!metadata["audio"].isMember("size") || metadata["audio"]["size"].asInt() < 1){
|
||||||
switch (audiodata & 0x02){
|
switch (audiodata & 0x02){
|
||||||
case 0x0: Meta_Put(metadata, "audio", "size", 8); break;
|
case 0x0: metadata["audio"]["size"] = 8; break;
|
||||||
case 0x2: Meta_Put(metadata, "audio", "size", 16); break;
|
case 0x2: metadata["audio"]["size"] = 16; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Meta_Has(metadata, "audio", "channels")){
|
if (!metadata["audio"].isMember("channels") || metadata["audio"]["channels"].asInt() < 1){
|
||||||
switch (audiodata & 0x01){
|
switch (audiodata & 0x01){
|
||||||
case 0x0: Meta_Put(metadata, "audio", "channels", 1); break;
|
case 0x0: metadata["audio"]["channels"] = 1; break;
|
||||||
case 0x1: Meta_Put(metadata, "audio", "channels", 2); break;
|
case 0x1: metadata["audio"]["channels"] = 2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((audiodata & 0xF0) == 0xA0){
|
if ((audiodata & 0xF0) == 0xA0){
|
||||||
if (len < 18){return DTSC::DTMI();}
|
if (len < 18){return JSON::Value();}
|
||||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+13, (size_t)len-17)));
|
pack_out["data"] = std::string((char*)data+13, (size_t)len-17);
|
||||||
}else{
|
}else{
|
||||||
if (len < 17){return DTSC::DTMI();}
|
if (len < 17){return JSON::Value();}
|
||||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16)));
|
pack_out["data"] = std::string((char*)data+12, (size_t)len-16);
|
||||||
}
|
}
|
||||||
return pack_out;
|
return pack_out;
|
||||||
}
|
}
|
||||||
|
@ -878,77 +891,46 @@ DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){
|
||||||
char videodata = data[11];
|
char videodata = data[11];
|
||||||
if (needsInitData() && isInitData()){
|
if (needsInitData() && isInitData()){
|
||||||
if ((videodata & 0x0F) == 7){
|
if ((videodata & 0x0F) == 7){
|
||||||
if (len < 21){return DTSC::DTMI();}
|
if (len < 21){return JSON::Value();}
|
||||||
Meta_Put(metadata, "video", "init", std::string((char*)data+16, (size_t)len-20));
|
metadata["video"]["init"] = std::string((char*)data+16, (size_t)len-20);
|
||||||
}else{
|
}else{
|
||||||
if (len < 17){return DTSC::DTMI();}
|
if (len < 17){return JSON::Value();}
|
||||||
Meta_Put(metadata, "video", "init", std::string((char*)data+12, (size_t)len-16));
|
metadata["video"]["init"] = std::string((char*)data+12, (size_t)len-16);
|
||||||
}
|
}
|
||||||
return pack_out;//skip rest of parsing, get next tag.
|
return pack_out;//skip rest of parsing, get next tag.
|
||||||
}
|
}
|
||||||
if (!Meta_Has(metadata, "video", "codec")){
|
if (!metadata["video"].isMember("codec") || metadata["video"]["codec"].asString() == ""){
|
||||||
switch (videodata & 0x0F){
|
switch (videodata & 0x0F){
|
||||||
case 2: Meta_Put(metadata, "video", "codec", "H263"); break;
|
case 2: metadata["video"]["codec"] = "H263"; break;
|
||||||
case 4: Meta_Put(metadata, "video", "codec", "VP6"); break;
|
case 4: metadata["video"]["codec"] = "VP6"; break;
|
||||||
case 7: Meta_Put(metadata, "video", "codec", "H264"); break;
|
case 7: metadata["video"]["codec"] = "H264"; break;
|
||||||
default: Meta_Put(metadata, "video", "codec", "?"); break;
|
default: metadata["video"]["codec"] = "?"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pack_out = DTSC::DTMI("video", DTSC::DTMI_ROOT);
|
pack_out["datatype"] = "video";
|
||||||
pack_out.addContent(DTSC::DTMI("datatype", "video"));
|
|
||||||
switch (videodata & 0xF0){
|
switch (videodata & 0xF0){
|
||||||
case 0x10: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break;
|
case 0x10: pack_out["keyframe"] = 1; break;
|
||||||
case 0x20: pack_out.addContent(DTSC::DTMI("interframe", 1)); break;
|
case 0x20: pack_out["interframe"] = 1; break;
|
||||||
case 0x30: pack_out.addContent(DTSC::DTMI("disposableframe", 1)); break;
|
case 0x30: pack_out["disposableframe"] = 1; break;
|
||||||
case 0x40: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break;
|
case 0x40: pack_out["keyframe"] = 1; break;
|
||||||
case 0x50: return DTSC::DTMI(); break;//the video info byte we just throw away - useless to us...
|
case 0x50: return JSON::Value(); break;//the video info byte we just throw away - useless to us...
|
||||||
}
|
}
|
||||||
pack_out.addContent(DTSC::DTMI("time", tagTime()));
|
pack_out["time"] = tagTime();
|
||||||
if ((videodata & 0x0F) == 7){
|
if ((videodata & 0x0F) == 7){
|
||||||
switch (data[12]){
|
switch (data[12]){
|
||||||
case 1: pack_out.addContent(DTSC::DTMI("nalu", 1)); break;
|
case 1: pack_out["nalu"] = 1; break;
|
||||||
case 2: pack_out.addContent(DTSC::DTMI("nalu_end", 1)); break;
|
case 2: pack_out["nalu_end"] = 1; break;
|
||||||
}
|
}
|
||||||
int offset = (data[13] << 16) + (data[14] << 8) + data[15];
|
int offset = (data[13] << 16) + (data[14] << 8) + data[15];
|
||||||
offset = (offset << 8) >> 8;
|
offset = (offset << 8) >> 8;
|
||||||
pack_out.addContent(DTSC::DTMI("offset", offset));
|
pack_out["offset"] = offset;
|
||||||
if (len < 21){return DTSC::DTMI();}
|
if (len < 21){return JSON::Value();}
|
||||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+16, (size_t)len-20)));
|
pack_out["data"] = std::string((char*)data+16, (size_t)len-20);
|
||||||
}else{
|
}else{
|
||||||
if (len < 17){return DTSC::DTMI();}
|
if (len < 17){return JSON::Value();}
|
||||||
pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16)));
|
pack_out["data"] = std::string((char*)data+12, (size_t)len-16);
|
||||||
}
|
}
|
||||||
return pack_out;
|
return pack_out;
|
||||||
}
|
}
|
||||||
return pack_out;//should never get here
|
return pack_out;//should never get here
|
||||||
}//FLV::Tag::toDTSC
|
}//FLV::Tag::toJSON
|
||||||
|
|
||||||
/// 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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "dtsc.h"
|
#include "dtsc.h"
|
||||||
|
#include "json.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//forward declaration of RTMPStream::Chunk to avoid circular dependencies.
|
//forward declaration of RTMPStream::Chunk to avoid circular dependencies.
|
||||||
|
@ -43,7 +44,7 @@ namespace FLV {
|
||||||
bool DTSCVideoInit(DTSC::Stream & S);
|
bool DTSCVideoInit(DTSC::Stream & S);
|
||||||
bool DTSCAudioInit(DTSC::Stream & S);
|
bool DTSCAudioInit(DTSC::Stream & S);
|
||||||
bool DTSCMetaInit(DTSC::Stream & S);
|
bool DTSCMetaInit(DTSC::Stream & S);
|
||||||
DTSC::DTMI toDTSC(DTSC::DTMI & metadata);
|
JSON::Value toJSON(JSON::Value & metadata);
|
||||||
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);
|
||||||
|
@ -57,10 +58,10 @@ namespace FLV {
|
||||||
bool MemReadUntil(char * buffer, unsigned int count, unsigned int & sofar, char * D, unsigned int S, unsigned int & P);
|
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 SockReadUntil(char * buffer, unsigned int count, unsigned int & sofar, Socket::Connection & sock);
|
||||||
bool FileReadUntil(char * buffer, unsigned int count, unsigned int & sofar, FILE * f);
|
bool FileReadUntil(char * buffer, unsigned int count, unsigned int & sofar, FILE * f);
|
||||||
//DTSC writer helpers
|
//JSON writer helpers
|
||||||
void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val);
|
void Meta_Put(JSON::Value & 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);
|
void Meta_Put(JSON::Value & meta, std::string cat, std::string elem, uint64_t val);
|
||||||
bool Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem);
|
bool Meta_Has(JSON::Value & meta, std::string cat, std::string elem);
|
||||||
};//Tag
|
};//Tag
|
||||||
|
|
||||||
};//FLV namespace
|
};//FLV namespace
|
||||||
|
|
Loading…
Add table
Reference in a new issue