PCM support in Flash-based protocols

This commit is contained in:
Thulinma 2017-06-19 12:38:35 +02:00
parent bb5d0dda11
commit cef78b7d08
5 changed files with 138 additions and 72 deletions

View file

@ -182,7 +182,11 @@ const char * FLV::Tag::getVideoCodec() {
const char * FLV::Tag::getAudioCodec() { const char * FLV::Tag::getAudioCodec() {
switch (data[11] & 0xF0) { switch (data[11] & 0xF0) {
case 0x00: case 0x00:
return "PCMPE"; if (data[11] & 0x02){
return "PCMPE";//unknown endianness
}else{
return "PCM";//8 bit is always regular PCM
}
case 0x10: case 0x10:
return "ADPCM"; return "ADPCM";
case 0x20: case 0x20:

View file

@ -132,6 +132,18 @@ namespace Mist {
return getNext(); 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
DTSC::Track & trk = myMeta.tracks[tmpTag.getTrackID()];
if (trk.codec == "PCM" && trk.size == 16){
char * ptr = 0;
uint32_t ptrSize = 0;
thisPacket.getString("data", ptr, ptrSize);
for (uint32_t i = 0; i < ptrSize; i+=2){
char tmpchar = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = tmpchar;
}
}
} }
void inputFLV::seek(int seekTime) { void inputFLV::seek(int seekTime) {

View file

@ -172,7 +172,17 @@ namespace Mist {
H.Chunkify("", 0, myConn); H.Chunkify("", 0, myConn);
return; return;
} }
tag.DTSCLoader(thisPacket, myMeta.tracks[thisPacket.getTrackId()]); DTSC::Track & trk = myMeta.tracks[thisPacket.getTrackId()];
tag.DTSCLoader(thisPacket, trk);
if (trk.codec == "PCM" && trk.size == 16){
char * ptr = tag.getData();
uint32_t ptrSize = tag.getDataLen();
for (uint32_t i = 0; i < ptrSize; i+=2){
char tmpchar = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = tmpchar;
}
}
if (tag.len){ if (tag.len){
H.Chunkify(tag.data, tag.len, myConn); H.Chunkify(tag.data, tag.len, myConn);
} }

View file

@ -31,7 +31,17 @@ namespace Mist {
} }
void OutProgressiveFLV::sendNext(){ void OutProgressiveFLV::sendNext(){
tag.DTSCLoader(thisPacket, myMeta.tracks[thisPacket.getTrackId()]); DTSC::Track & trk = myMeta.tracks[thisPacket.getTrackId()];
tag.DTSCLoader(thisPacket, trk);
if (trk.codec == "PCM" && trk.size == 16){
char * ptr = tag.getData();
uint32_t ptrSize = tag.getDataLen();
for (uint32_t i = 0; i < ptrSize; i+=2){
char tmpchar = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = tmpchar;
}
}
myConn.SendNow(tag.data, tag.len); myConn.SendNow(tag.data, tag.len);
} }

View file

@ -181,6 +181,8 @@ namespace Mist {
0, 0, 0, 0}; //bytes 12-15 = extended timestamp 0, 0, 0, 0}; //bytes 12-15 = extended timestamp
char dataheader[] ={0, 0, 0, 0, 0}; char dataheader[] ={0, 0, 0, 0, 0};
unsigned int dheader_len = 1; unsigned int dheader_len = 1;
static char * swappyPointer = 0;
static uint32_t swappySize = 0;
char * tmpData = 0;//pointer to raw media data char * tmpData = 0;//pointer to raw media data
unsigned int data_len = 0;//length of processed media data unsigned int data_len = 0;//length of processed media data
thisPacket.getString("data", tmpData, data_len); thisPacket.getString("data", tmpData, data_len);
@ -232,6 +234,22 @@ namespace Mist {
dataheader[0] |= 0x10; dataheader[0] |= 0x10;
} }
if (track.codec == "PCM"){ if (track.codec == "PCM"){
if (track.size == 16){
if (swappySize < data_len){
char * tmp = (char*)realloc(swappyPointer, data_len);
if (!tmp){
FAIL_MSG("Could not allocate data for PCM endianness swap!");
return;
}
swappyPointer = tmp;
swappySize = data_len;
}
for (uint32_t i = 0; i < data_len; i+=2){
swappyPointer[i] = tmpData[i+1];
swappyPointer[i+1] = tmpData[i];
}
tmpData = swappyPointer;
}
dataheader[0] |= 0x30; dataheader[0] |= 0x30;
} }
if (track.codec == "Nellymoser"){ if (track.codec == "Nellymoser"){
@ -607,6 +625,9 @@ namespace Mist {
sendCommand(amfReply, messageType, streamId); sendCommand(amfReply, messageType, streamId);
return; return;
}//checkBandwidth }//checkBandwidth
if (amfData.getContentP(0)->StrValue() == "onBWDone"){
return;
}
if ((amfData.getContentP(0)->StrValue() == "play") || (amfData.getContentP(0)->StrValue() == "play2")){ if ((amfData.getContentP(0)->StrValue() == "play") || (amfData.getContentP(0)->StrValue() == "play2")){
//set reply number and stream name, actual reply is sent up in the ss.spool() handler //set reply number and stream name, actual reply is sent up in the ss.spool() handler
int playTransaction = amfData.getContentP(1)->NumValue(); int playTransaction = amfData.getContentP(1)->NumValue();
@ -773,7 +794,7 @@ namespace Mist {
return; return;
} }
if ((amfData.getContentP(0)->StrValue() == "_result") || (amfData.getContentP(0)->StrValue() == "onFCPublish") || (amfData.getContentP(0)->StrValue() == "onStatus")){ if ((amfData.getContentP(0)->StrValue() == "_result") || (amfData.getContentP(0)->StrValue() == "onFCPublish") || (amfData.getContentP(0)->StrValue() == "onStatus")){
//Results are ignored. We don't really care. //Other results are ignored. We don't really care.
return; return;
} }
@ -920,6 +941,15 @@ namespace Mist {
onFinish(); onFinish();
break; break;
} }
if (myMeta.tracks[reTrack].codec == "PCM" && myMeta.tracks[reTrack].size == 16){
char * ptr = F.getData();
uint32_t ptrSize = F.getDataLen();
for (uint32_t i = 0; i < ptrSize; i+=2){
char tmpchar = ptr[i];
ptr[i] = ptr[i+1];
ptr[i+1] = tmpchar;
}
}
thisPacket.genericFill(tagTime, F.offset(), reTrack, F.getData(), F.getDataLen(), 0, F.isKeyframe); thisPacket.genericFill(tagTime, F.offset(), reTrack, F.getData(), F.getDataLen(), 0, F.isKeyframe);
ltt = tagTime; ltt = tagTime;
if (!nProxy.userClient.getData()){ if (!nProxy.userClient.getData()){