Fixes FLV/RTMP compatibility issues with corrupted RTMP streams, fixes various flash-codecs through RTMP.

This commit is contained in:
Thulinma 2016-06-23 20:13:38 +02:00
parent 29949eb56e
commit ba044b4470
3 changed files with 42 additions and 7 deletions

View file

@ -933,11 +933,14 @@ char * FLV::Tag::getData(){
/// Returns the length of the raw media data for this packet. /// Returns the length of the raw media data for this packet.
unsigned int FLV::Tag::getDataLen(){ unsigned int FLV::Tag::getDataLen(){
if (data[0] == 0x08 && (data[11] & 0xF0) == 0xA0) { if (data[0] == 0x08 && (data[11] & 0xF0) == 0xA0) {
if (len < 17){return 0;}
return len - 17; return len - 17;
} }
if (data[0] == 0x09 && (data[11] & 0x0F) == 7) { if (data[0] == 0x09 && (data[11] & 0x0F) == 7) {
if (len < 20){return 0;}
return len - 20; return len - 20;
} }
if (len < 16){return 0;}
return len - 16; return len - 16;
} }
@ -993,10 +996,8 @@ JSON::Value FLV::Tag::toJSON(DTSC::Meta & metadata, AMF::Object & amf_storage, u
char audiodata = data[11]; char audiodata = data[11];
metadata.tracks[reTrack].trackID = reTrack; metadata.tracks[reTrack].trackID = reTrack;
metadata.tracks[reTrack].type = "audio"; metadata.tracks[reTrack].type = "audio";
if (metadata.tracks[reTrack].codec == "") { if (metadata.tracks[reTrack].codec == "" || metadata.tracks[reTrack].codec != getAudioCodec()) {
metadata.tracks[reTrack].codec = getAudioCodec(); metadata.tracks[reTrack].codec = getAudioCodec();
}
if (!metadata.tracks[reTrack].rate) {
switch (audiodata & 0x0C) { switch (audiodata & 0x0C) {
case 0x0: case 0x0:
metadata.tracks[reTrack].rate = 5512; metadata.tracks[reTrack].rate = 5512;
@ -1014,8 +1015,6 @@ JSON::Value FLV::Tag::toJSON(DTSC::Meta & metadata, AMF::Object & amf_storage, u
if (amf_storage.getContentP("audiosamplerate")) { if (amf_storage.getContentP("audiosamplerate")) {
metadata.tracks[reTrack].rate = (long long int)amf_storage.getContentP("audiosamplerate")->NumValue(); metadata.tracks[reTrack].rate = (long long int)amf_storage.getContentP("audiosamplerate")->NumValue();
} }
}
if (!metadata.tracks[reTrack].size) {
switch (audiodata & 0x02) { switch (audiodata & 0x02) {
case 0x0: case 0x0:
metadata.tracks[reTrack].size = 8; metadata.tracks[reTrack].size = 8;
@ -1027,8 +1026,6 @@ JSON::Value FLV::Tag::toJSON(DTSC::Meta & metadata, AMF::Object & amf_storage, u
if (amf_storage.getContentP("audiosamplesize")) { if (amf_storage.getContentP("audiosamplesize")) {
metadata.tracks[reTrack].size = (long long int)amf_storage.getContentP("audiosamplesize")->NumValue(); metadata.tracks[reTrack].size = (long long int)amf_storage.getContentP("audiosamplesize")->NumValue();
} }
}
if (!metadata.tracks[reTrack].channels) {
switch (audiodata & 0x01) { switch (audiodata & 0x01) {
case 0x0: case 0x0:
metadata.tracks[reTrack].channels = 1; metadata.tracks[reTrack].channels = 1;
@ -1124,6 +1121,11 @@ JSON::Value FLV::Tag::toJSON(DTSC::Meta & metadata, AMF::Object & amf_storage, u
break; //the video info byte we just throw away - useless to us... break; //the video info byte we just throw away - useless to us...
} }
pack_out["time"] = tagTime(); pack_out["time"] = tagTime();
if (!getDataLen()){
//empty packet
pack_out["data"] = "";
return pack_out;
}
if ((videodata & 0x0F) == 7) { if ((videodata & 0x0F) == 7) {
switch (data[12]) { switch (data[12]) {
case 1: case 1:

View file

@ -105,6 +105,9 @@ namespace Mist {
thisPacket.null(); thisPacket.null();
return; return;
} }
if (!tmpTag.getDataLen()){
return getNext();
}
thisPacket.genericFill(tmpTag.tagTime(), tmpTag.offset(), tmpTag.getTrackID(), tmpTag.getData(), tmpTag.getDataLen(), lastBytePos, tmpTag.isKeyframe); //init packet from tmpTags data thisPacket.genericFill(tmpTag.tagTime(), tmpTag.offset(), tmpTag.getTrackID(), tmpTag.getData(), tmpTag.getDataLen(), lastBytePos, tmpTag.isKeyframe); //init packet from tmpTags data
} }

View file

@ -198,6 +198,35 @@ namespace Mist {
} }
if (track.codec == "MP3"){ if (track.codec == "MP3"){
dataheader[0] += 0x20; dataheader[0] += 0x20;
if (track.rate == 8000){
dataheader[0] |= 0xE0;
}else{
dataheader[0] |= 0x20;
}
}
if (track.codec == "ADPCM") {
dataheader[0] |= 0x10;
}
if (track.codec == "PCM") {
dataheader[0] |= 0x30;
}
if (track.codec == "Nellymoser") {
if (track.rate == 8000){
dataheader[0] |= 0x50;
}else if(track.rate == 16000){
dataheader[0] |= 0x40;
}else{
dataheader[0] |= 0x60;
}
}
if (track.codec == "G711a") {
dataheader[0] |= 0x70;
}
if (track.codec == "G711mu") {
dataheader[0] |= 0x80;
}
if (track.codec == "Speex") {
dataheader[0] |= 0xB0;
} }
if (track.rate >= 44100){ if (track.rate >= 44100){
dataheader[0] |= 0x0C; dataheader[0] |= 0x0C;
@ -824,6 +853,7 @@ namespace Mist {
break; break;
} }
F.ChunkLoader(next); F.ChunkLoader(next);
if (!F.getDataLen()){break;}//ignore empty packets
AMF::Object * amf_storage = 0; AMF::Object * amf_storage = 0;
if (F.data[0] == 0x12 || pushMeta.count(next.cs_id) || !pushMeta.size()){ if (F.data[0] == 0x12 || pushMeta.count(next.cs_id) || !pushMeta.size()){
amf_storage = &(pushMeta[next.cs_id]); amf_storage = &(pushMeta[next.cs_id]);