Metadata upgrades.
This commit is contained in:
parent
071cba94f9
commit
79b4772c3d
7 changed files with 1116 additions and 343 deletions
165
lib/flv_tag.cpp
165
lib/flv_tag.cpp
|
@ -364,22 +364,18 @@ FLV::Tag & FLV::Tag::operator=(const FLV::Tag& O){
|
|||
/// Takes the DTSC data and makes it into FLV.
|
||||
bool FLV::Tag::DTSCLoader(DTSC::Stream & S){
|
||||
std::string meta_str;
|
||||
JSON::Value & track = S.getTrackById(S.getPacket()["trackid"].asInt());
|
||||
DTSC::Track & track = S.metadata.tracks[S.getPacket()["trackid"].asInt()];
|
||||
switch (S.lastType()){
|
||||
case DTSC::VIDEO:
|
||||
len = S.lastData().length() + 16;
|
||||
if (track && track.isMember("codec")){
|
||||
if (track["codec"].asStringRef() == "H264"){
|
||||
len += 4;
|
||||
}
|
||||
if (track.codec == "H264"){
|
||||
len += 4;
|
||||
}
|
||||
break;
|
||||
case DTSC::AUDIO:
|
||||
len = S.lastData().length() + 16;
|
||||
if (track && track.isMember("codec")){
|
||||
if (track["codec"].asStringRef() == "AAC"){
|
||||
len += 1;
|
||||
}
|
||||
if (track.codec == "AAC"){
|
||||
len += 1;
|
||||
}
|
||||
break;
|
||||
case DTSC::META:{
|
||||
|
@ -418,10 +414,10 @@ bool FLV::Tag::DTSCLoader(DTSC::Stream & S){
|
|||
offset(S.getPacket()["offset"].asInt());
|
||||
}
|
||||
data[11] = 0;
|
||||
if (track.isMember("codec") && track["codec"].asStringRef() == "H264"){
|
||||
if (track.codec == "H264"){
|
||||
data[11] += 7;
|
||||
}
|
||||
if (track.isMember("codec") && track["codec"].asStringRef() == "H263"){
|
||||
if (track.codec == "H263"){
|
||||
data[11] += 2;
|
||||
}
|
||||
if (S.getPacket().isMember("keyframe")){
|
||||
|
@ -442,13 +438,13 @@ bool FLV::Tag::DTSCLoader(DTSC::Stream & S){
|
|||
data[12] = 1; //raw AAC data, not sequence header
|
||||
}
|
||||
data[11] = 0;
|
||||
if (track.isMember("codec") && track["codec"].asString() == "AAC"){
|
||||
if (track.codec == "AAC"){
|
||||
data[11] += 0xA0;
|
||||
}
|
||||
if (track.isMember("codec") && track["codec"].asString() == "MP3"){
|
||||
if (track.codec == "MP3"){
|
||||
data[11] += 0x20;
|
||||
}
|
||||
unsigned int datarate = track["rate"].asInt();
|
||||
unsigned int datarate = track.rate;
|
||||
if (datarate >= 44100){
|
||||
data[11] += 0x0C;
|
||||
}else if (datarate >= 22050){
|
||||
|
@ -456,10 +452,10 @@ bool FLV::Tag::DTSCLoader(DTSC::Stream & S){
|
|||
}else if (datarate >= 11025){
|
||||
data[11] += 0x04;
|
||||
}
|
||||
if (track["size"].asInt() == 16){
|
||||
if (track.size == 16){
|
||||
data[11] += 0x02;
|
||||
}
|
||||
if (track["channels"].asInt() > 1){
|
||||
if (track.channels > 1){
|
||||
data[11] += 0x01;
|
||||
}
|
||||
break;
|
||||
|
@ -508,26 +504,20 @@ void FLV::Tag::setLen(){
|
|||
data[ --i] = (len4) & 0xFF;
|
||||
}
|
||||
|
||||
/// 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){
|
||||
return DTSCVideoInit(S.metadata["video"]);
|
||||
}
|
||||
|
||||
bool FLV::Tag::DTSCVideoInit(JSON::Value & video){
|
||||
/// FLV Video init data loader function from JSON.
|
||||
bool FLV::Tag::DTSCVideoInit(DTSC::Track & video){
|
||||
//Unknown? Assume H264.
|
||||
if (video["codec"].asString() == "?"){
|
||||
video["codec"] = "H264";
|
||||
if (video.codec == "?"){
|
||||
video.codec = "H264";
|
||||
}
|
||||
if (video["codec"].asString() == "H264"){
|
||||
len = video["init"].asString().length() + 20;
|
||||
if (video.codec == "H264"){
|
||||
len = video.init.size() + 20;
|
||||
}
|
||||
if (len > 0){
|
||||
if ( !checkBufferSize()){
|
||||
return false;
|
||||
}
|
||||
memcpy(data + 16, video["init"].asString().c_str(), len - 20);
|
||||
memcpy(data + 16, video.init.c_str(), len - 20);
|
||||
data[12] = 0; //H264 sequence header
|
||||
data[13] = 0;
|
||||
data[14] = 0;
|
||||
|
@ -546,36 +536,30 @@ bool FLV::Tag::DTSCVideoInit(JSON::Value & video){
|
|||
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){
|
||||
return DTSCAudioInit(S.metadata["audio"]);
|
||||
}
|
||||
|
||||
bool FLV::Tag::DTSCAudioInit(JSON::Value & audio){
|
||||
/// FLV Audio init data loader function from JSON.
|
||||
bool FLV::Tag::DTSCAudioInit(DTSC::Track & audio){
|
||||
len = 0;
|
||||
//Unknown? Assume AAC.
|
||||
if (audio["codec"].asString() == "?"){
|
||||
audio["codec"] = "AAC";
|
||||
if (audio.codec == "?"){
|
||||
audio.codec = "AAC";
|
||||
}
|
||||
if (audio["codec"].asString() == "AAC"){
|
||||
len = audio["init"].asString().length() + 17;
|
||||
if (audio.codec == "AAC"){
|
||||
len = audio.init.size() + 17;
|
||||
}
|
||||
if (len > 0){
|
||||
if ( !checkBufferSize()){
|
||||
return false;
|
||||
}
|
||||
memcpy(data + 13, audio["init"].asString().c_str(), len - 17);
|
||||
memcpy(data + 13, audio.init.c_str(), len - 17);
|
||||
data[12] = 0; //AAC sequence header
|
||||
data[11] = 0;
|
||||
if (audio["codec"].asString() == "AAC"){
|
||||
if (audio.codec == "AAC"){
|
||||
data[11] += 0xA0;
|
||||
}
|
||||
if (audio["codec"].asString() == "MP3"){
|
||||
if (audio.codec == "MP3"){
|
||||
data[11] += 0x20;
|
||||
}
|
||||
unsigned int datarate = audio["rate"].asInt();
|
||||
unsigned int datarate = audio.rate;
|
||||
if (datarate >= 44100){
|
||||
data[11] += 0x0C;
|
||||
}else if (datarate >= 22050){
|
||||
|
@ -583,10 +567,10 @@ bool FLV::Tag::DTSCAudioInit(JSON::Value & audio){
|
|||
}else if (datarate >= 11025){
|
||||
data[11] += 0x04;
|
||||
}
|
||||
if (audio["size"].asInt() == 16){
|
||||
if (audio.size == 16){
|
||||
data[11] += 0x02;
|
||||
}
|
||||
if (audio["channels"].asInt() > 1){
|
||||
if (audio.channels > 1){
|
||||
data[11] += 0x01;
|
||||
|
||||
}
|
||||
|
@ -606,34 +590,34 @@ bool FLV::Tag::DTSCAudioInit(JSON::Value & audio){
|
|||
/// 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, JSON::Value & videoRef, JSON::Value & audioRef){
|
||||
bool FLV::Tag::DTSCMetaInit(DTSC::Stream & S, DTSC::Track & videoRef, DTSC::Track & audioRef){
|
||||
//Unknown? Assume AAC.
|
||||
if (audioRef["codec"].asString() == "?"){
|
||||
audioRef["codec"] = "AAC";
|
||||
if (audioRef.codec == "?"){
|
||||
audioRef.codec = "AAC";
|
||||
}
|
||||
//Unknown? Assume H264.
|
||||
if (videoRef["codec"].asString() == "?"){
|
||||
videoRef["codec"] = "H264";
|
||||
if (videoRef.codec == "?"){
|
||||
videoRef.codec = "H264";
|
||||
}
|
||||
|
||||
AMF::Object amfdata("root", AMF::AMF0_DDV_CONTAINER);
|
||||
|
||||
amfdata.addContent(AMF::Object("", "onMetaData"));
|
||||
amfdata.addContent(AMF::Object("", AMF::AMF0_ECMA_ARRAY));
|
||||
if (S.metadata.isMember("length")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("duration", S.metadata["length"].asInt(), AMF::AMF0_NUMBER));
|
||||
if (S.metadata.vod){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("duration", videoRef.lastms / 1000, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("moovPosition", 40, AMF::AMF0_NUMBER));
|
||||
AMF::Object keys("keyframes", AMF::AMF0_OBJECT);
|
||||
keys.addContent(AMF::Object("filepositions", AMF::AMF0_STRICT_ARRAY));
|
||||
keys.addContent(AMF::Object("times", AMF::AMF0_STRICT_ARRAY));
|
||||
int total_byterate = 0;
|
||||
if (videoRef){
|
||||
total_byterate += videoRef["bps"].asInt();
|
||||
total_byterate += videoRef.bps;
|
||||
}
|
||||
if (audioRef){
|
||||
total_byterate += audioRef["bps"].asInt();
|
||||
total_byterate += audioRef.bps;
|
||||
}
|
||||
for (int i = 0; i < S.metadata["length"].asInt(); ++i){ //for each second in the file
|
||||
for (int i = 0; i < videoRef.lastms / 1000; ++i){ //for each second in the file
|
||||
keys.getContentP(0)->addContent(AMF::Object("", i * total_byterate, AMF::AMF0_NUMBER)); //multiply by byterate for fake byte positions
|
||||
keys.getContentP(1)->addContent(AMF::Object("", i, AMF::AMF0_NUMBER)); //seconds
|
||||
}
|
||||
|
@ -641,62 +625,45 @@ bool FLV::Tag::DTSCMetaInit(DTSC::Stream & S, JSON::Value & videoRef, JSON::Valu
|
|||
}
|
||||
if (videoRef){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("hasVideo", 1, AMF::AMF0_BOOL));
|
||||
if (videoRef["codec"].asString() == "H264"){
|
||||
if (videoRef.codec == "H264"){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", (std::string)"avc1"));
|
||||
}
|
||||
if (videoRef["codec"].asString() == "VP6"){
|
||||
if (videoRef.codec == "VP6"){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 4, AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (videoRef["codec"].asString() == "H263"){
|
||||
if (videoRef.codec == "H263"){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 2, AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (videoRef.isMember("width")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("width", videoRef["width"].asInt(), AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (videoRef.isMember("height")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("height", videoRef["height"].asInt(), AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (videoRef.isMember("fpks")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videoframerate", (double)videoRef["fpks"].asInt() / 1000.0, AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (videoRef.isMember("bps")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videodatarate", (double)videoRef["bps"].asInt() * 128.0, AMF::AMF0_NUMBER));
|
||||
}
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("width", videoRef.width, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("height", videoRef.height, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videoframerate", (double)videoRef.fpks / 1000.0, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("videodatarate", (double)videoRef.bps * 128.0, AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (audioRef){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("hasAudio", 1, AMF::AMF0_BOOL));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiodelay", 0, AMF::AMF0_NUMBER));
|
||||
if (audioRef["codec"].asString() == "AAC"){
|
||||
if (audioRef.codec == "AAC"){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string)"mp4a"));
|
||||
}
|
||||
if (audioRef["codec"].asString() == "MP3"){
|
||||
if (audioRef.codec == "MP3"){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string)"mp3"));
|
||||
}
|
||||
if (audioRef.isMember("channels")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiochannels", audioRef["channels"].asInt(), AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (audioRef.isMember("rate")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplerate", audioRef["rate"].asInt(), AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (audioRef.isMember("size")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplesize", audioRef["size"].asInt(), AMF::AMF0_NUMBER));
|
||||
}
|
||||
if (audioRef.isMember("bps")){
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiodatarate", (double)audioRef["bps"].asInt() * 128.0, AMF::AMF0_NUMBER));
|
||||
}
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiochannels", audioRef.channels, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplerate", audioRef.rate, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiosamplesize", audioRef.size, AMF::AMF0_NUMBER));
|
||||
amfdata.getContentP(1)->addContent(AMF::Object("audiodatarate", (double)audioRef.bps * 128.0, AMF::AMF0_NUMBER));
|
||||
}
|
||||
AMF::Object trinfo = AMF::Object("trackinfo", AMF::AMF0_STRICT_ARRAY);
|
||||
int i = 0;
|
||||
if (audioRef){
|
||||
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
|
||||
trinfo.getContentP(i)->addContent(
|
||||
AMF::Object("length", ((double)S.metadata["length"].asInt()) * ((double)audioRef["rate"].asInt()), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("timescale", audioRef["rate"].asInt(), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("length", ((double)S.metadata.length) * ((double)audioRef.rate), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("timescale", audioRef.rate, AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY));
|
||||
if (audioRef["codec"].asString() == "AAC"){
|
||||
if (audioRef.codec == "AAC"){
|
||||
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string)"mp4a"));
|
||||
}
|
||||
if (audioRef["codec"].asString() == "MP3"){
|
||||
if (audioRef.codec == "MP3"){
|
||||
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string)"mp3"));
|
||||
}
|
||||
++i;
|
||||
|
@ -704,16 +671,16 @@ bool FLV::Tag::DTSCMetaInit(DTSC::Stream & S, JSON::Value & videoRef, JSON::Valu
|
|||
if (videoRef){
|
||||
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
|
||||
trinfo.getContentP(i)->addContent(
|
||||
AMF::Object("length", ((double)S.metadata["length"].asInt()) * ((double)videoRef["fkps"].asInt() / 1000.0), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("timescale", ((double)videoRef["fkps"].asInt() / 1000.0), AMF::AMF0_NUMBER));
|
||||
AMF::Object("length", ((double)videoRef.lastms / 1000) * ((double)videoRef.fpks / 1000.0), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("timescale", ((double)videoRef.fpks / 1000.0), AMF::AMF0_NUMBER));
|
||||
trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY));
|
||||
if (videoRef["codec"].asString() == "H264"){
|
||||
if (videoRef.codec == "H264"){
|
||||
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string)"avc1"));
|
||||
}
|
||||
if (videoRef["codec"].asString() == "VP6"){
|
||||
if (videoRef.codec == "VP6"){
|
||||
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string)"vp6"));
|
||||
}
|
||||
if (videoRef["codec"].asString() == "H263"){
|
||||
if (videoRef.codec == "H263"){
|
||||
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string)"h263"));
|
||||
}
|
||||
++i;
|
||||
|
@ -1061,12 +1028,6 @@ JSON::Value FLV::Tag::toJSON(JSON::Value & metadata){
|
|||
if ( !metadata["tracks"]["track1"].isMember("bps")){
|
||||
metadata["tracks"]["track1"]["bps"] = 0;
|
||||
}
|
||||
if ( !metadata["tracks"]["track1"].isMember("keyms")){
|
||||
metadata["tracks"]["track1"]["keyms"] = 0;
|
||||
}
|
||||
if ( !metadata["tracks"]["track1"].isMember("keyvar")){
|
||||
metadata["tracks"]["track1"]["keyvar"] = 0;
|
||||
}
|
||||
}
|
||||
return pack_out; //empty
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue