MP3 codec support in more protocols.
This commit is contained in:
parent
aedf06d3ef
commit
286d6cba5c
3 changed files with 92 additions and 41 deletions
|
@ -21,6 +21,7 @@ namespace Mist {
|
|||
capa["socket"] = "http_progressive_mp4";
|
||||
capa["codecs"][0u][0u].append("H264");
|
||||
capa["codecs"][0u][1u].append("AAC");
|
||||
capa["codecs"][0u][1u].append("MP3");
|
||||
capa["methods"][0u]["handler"] = "http";
|
||||
capa["methods"][0u]["type"] = "html5/video/mp4";
|
||||
capa["methods"][0u]["priority"] = 8ll;
|
||||
|
@ -113,6 +114,9 @@ namespace Mist {
|
|||
if (myMeta.tracks[*it].codec == "AAC"){
|
||||
ase.setCodec("mp4a");
|
||||
ase.setDataReferenceIndex(1);
|
||||
}else if (myMeta.tracks[*it].codec == "MP3"){
|
||||
ase.setCodec("mp4a");
|
||||
ase.setDataReferenceIndex(1);
|
||||
}
|
||||
ase.setSampleRate(myMeta.tracks[*it].rate);
|
||||
ase.setChannelCount(myMeta.tracks[*it].channels);
|
||||
|
@ -121,23 +125,37 @@ namespace Mist {
|
|||
MP4::ESDS esdsBox;
|
||||
|
||||
//outputting these values first, so malloc isn't called as often.
|
||||
esdsBox.setESHeaderStartCodes(myMeta.tracks[*it].init);
|
||||
esdsBox.setSLValue(2);
|
||||
|
||||
esdsBox.setESDescriptorTypeLength(32+myMeta.tracks[*it].init.size());
|
||||
if (myMeta.tracks[*it].codec == "MP3"){
|
||||
esdsBox.setESHeaderStartCodes("\002");
|
||||
esdsBox.setConfigDescriptorTypeLength(1);
|
||||
esdsBox.setSLConfigExtendedDescriptorTypeTag(0);
|
||||
esdsBox.setSLDescriptorTypeLength(0);
|
||||
esdsBox.setESDescriptorTypeLength(27);
|
||||
esdsBox.setSLConfigDescriptorTypeTag(0);
|
||||
esdsBox.setDecoderDescriptorTypeTag(0x06);
|
||||
esdsBox.setSLValue(0);
|
||||
//esdsBox.setBufferSize(0);
|
||||
esdsBox.setDecoderConfigDescriptorTypeLength(13);
|
||||
esdsBox.setByteObjectTypeID(0x6b);
|
||||
}else{
|
||||
//AAC
|
||||
esdsBox.setESHeaderStartCodes(myMeta.tracks[*it].init);
|
||||
esdsBox.setConfigDescriptorTypeLength(myMeta.tracks[*it].init.size());
|
||||
esdsBox.setSLConfigExtendedDescriptorTypeTag(0x808080);
|
||||
esdsBox.setSLDescriptorTypeLength(1);
|
||||
esdsBox.setESDescriptorTypeLength(32+myMeta.tracks[*it].init.size());
|
||||
esdsBox.setSLConfigDescriptorTypeTag(0x6);
|
||||
esdsBox.setSLValue(2);
|
||||
esdsBox.setDecoderConfigDescriptorTypeLength(18 + myMeta.tracks[*it].init.size());
|
||||
esdsBox.setByteObjectTypeID(0x40);
|
||||
}
|
||||
esdsBox.setESID(2);
|
||||
esdsBox.setStreamPriority(0);
|
||||
esdsBox.setDecoderConfigDescriptorTypeLength(18 + myMeta.tracks[*it].init.size());
|
||||
esdsBox.setByteObjectTypeID(0x40);
|
||||
esdsBox.setStreamType(5);
|
||||
esdsBox.setReservedFlag(1);
|
||||
esdsBox.setBufferSize(1250000);
|
||||
esdsBox.setMaximumBitRate(10000000);
|
||||
esdsBox.setAverageBitRate(myMeta.tracks[*it].bps * 8);
|
||||
esdsBox.setConfigDescriptorTypeLength(5);
|
||||
esdsBox.setSLConfigDescriptorTypeTag(0x6);
|
||||
esdsBox.setSLConfigExtendedDescriptorTypeTag(0x808080);
|
||||
esdsBox.setSLDescriptorTypeLength(1);
|
||||
esdsBox.setBufferSize(1250000);
|
||||
ase.setCodecBox(esdsBox);
|
||||
stsdBox.setEntry(ase,0);
|
||||
}
|
||||
|
|
|
@ -8,23 +8,6 @@ namespace Mist {
|
|||
AudioCounter = 0;
|
||||
VideoCounter = 0;
|
||||
std::string tracks = config->getString("tracks");
|
||||
unsigned int currTrack = 0;
|
||||
//loop over tracks, add any found track IDs to selectedTracks
|
||||
if (tracks != ""){
|
||||
for (unsigned int i = 0; i < tracks.size(); ++i){
|
||||
if (tracks[i] >= '0' && tracks[i] <= '9'){
|
||||
currTrack = currTrack*10 + (tracks[i] - '0');
|
||||
}else{
|
||||
if (currTrack > 0){
|
||||
selectedTracks.insert(currTrack);
|
||||
}
|
||||
currTrack = 0;
|
||||
}
|
||||
}
|
||||
if (currTrack > 0){
|
||||
selectedTracks.insert(currTrack);
|
||||
}
|
||||
}
|
||||
streamName = config->getString("streamname");
|
||||
parseData = true;
|
||||
wantRequest = false;
|
||||
|
@ -48,6 +31,7 @@ namespace Mist {
|
|||
capa["optional"]["tracks"]["option"] = "--tracks";
|
||||
capa["codecs"][0u][0u].append("H264");
|
||||
capa["codecs"][0u][1u].append("AAC");
|
||||
capa["codecs"][0u][1u].append("MP3");
|
||||
cfg->addOption("streamname",
|
||||
JSON::fromString("{\"arg\":\"string\",\"short\":\"s\",\"long\":\"stream\",\"help\":\"The name of the stream that this connector will transmit.\"}"));
|
||||
cfg->addOption("tracks",
|
||||
|
@ -91,8 +75,12 @@ namespace Mist {
|
|||
}
|
||||
ContCounter = &VideoCounter;
|
||||
}else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
|
||||
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90));
|
||||
ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init));
|
||||
if (myMeta.tracks[currentPacket.getTrackId()].codec == "AAC"){
|
||||
ToPack.append(TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90));
|
||||
ToPack.append(TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init));
|
||||
}else{
|
||||
ToPack.append(TS::Packet::getPESAudioLeadIn(dataLen, currentPacket.getTime() * 90));
|
||||
}
|
||||
ToPack.append(dataPointer, dataLen);
|
||||
ContCounter = &AudioCounter;
|
||||
}
|
||||
|
@ -101,17 +89,11 @@ namespace Mist {
|
|||
//send TS packets
|
||||
while (ToPack.size()){
|
||||
PackData.Clear();
|
||||
/// \todo Update according to sendHeader()'s generated data.
|
||||
//0x100 - 1 + currentPacket.getTrackId()
|
||||
if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
|
||||
PackData.PID(0x100);
|
||||
}else{
|
||||
PackData.PID(0x101);
|
||||
}
|
||||
PackData.PID(0x100 - 1 + currentPacket.getTrackId());
|
||||
PackData.ContinuityCounter((*ContCounter)++);
|
||||
if (first){
|
||||
PackData.UnitStart(1);
|
||||
if (IsKeyFrame){
|
||||
if (IsKeyFrame || myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
|
||||
PackData.RandomAccess(1);
|
||||
PackData.PCR(currentPacket.getTime() * 27000);
|
||||
}
|
||||
|
@ -124,11 +106,60 @@ namespace Mist {
|
|||
}
|
||||
}
|
||||
|
||||
///this function generates the PMT packet
|
||||
std::string OutTS::createPMT(){
|
||||
//0x02 = table ID = 2 = PMT
|
||||
//0xB017 = section syntax(1) = 1, 0(1)=0, reserved(2) = 3, section_len(12) = 23
|
||||
//0x0001 = ProgNo = 1
|
||||
//0xC1 = reserved(2) = 3, version(5)=0, curr_next_indi(1) = 1
|
||||
//0x00 = section_number = 0
|
||||
//0x00 = last_section_no = 0
|
||||
//0xE100 = reserved(3) = 7, PCR_PID(13) = 0x100
|
||||
//0xF000 = reserved(4) = 15, proginfolen = 0
|
||||
//0x1B = streamtype = 27 = H264
|
||||
//0xE100 = reserved(3) = 7, elem_ID(13) = 0x100
|
||||
//0xF000 = reserved(4) = 15, es_info_len = 0
|
||||
//0x0F = streamtype = 15 = audio with ADTS transport syntax
|
||||
//0xE101 = reserved(3) = 7, elem_ID(13) = 0x101
|
||||
//0xF000 = reserved(4) = 15, es_info_len = 0
|
||||
//0x2F44B99B = CRC32
|
||||
TS::ProgramMappingTable PMT;
|
||||
PMT.PID(4096);
|
||||
PMT.setTableId(2);
|
||||
PMT.setSectionLength(0xB017);
|
||||
PMT.setProgramNumber(1);
|
||||
PMT.setVersionNumber(0);
|
||||
PMT.setCurrentNextIndicator(0);
|
||||
PMT.setSectionNumber(0);
|
||||
PMT.setLastSectionNumber(0);
|
||||
PMT.setPCRPID(0x100 + (*(selectedTracks.begin())) - 1);
|
||||
PMT.setProgramInfoLength(0);
|
||||
short id = 0;
|
||||
//for all selected tracks
|
||||
for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
|
||||
if (myMeta.tracks[*it].codec == "H264"){
|
||||
PMT.setStreamType(0x1B,id);
|
||||
}else if (myMeta.tracks[*it].codec == "AAC"){
|
||||
PMT.setStreamType(0x0F,id);
|
||||
}else if (myMeta.tracks[*it].codec == "MP3"){
|
||||
PMT.setStreamType(0x03,id);
|
||||
}
|
||||
PMT.setElementaryPID(0x100 + (*it) - 1, id);
|
||||
PMT.setESInfoLength(0,id);
|
||||
id++;
|
||||
}
|
||||
PMT.calcCRC();
|
||||
INFO_MSG("stringsize: %d %s", PMT.getStrBuf().size(), PMT.toPrettyString(0).c_str());
|
||||
return PMT.getStrBuf();
|
||||
}
|
||||
|
||||
void OutTS::sendHeader(){
|
||||
/// \todo Update this to actually generate these from the selected tracks.
|
||||
/// \todo ts_packet.h contains all neccesary info for this
|
||||
/// \todo if --tracks is set, clear selected tracks and fill with --tracks tracks.
|
||||
myConn.SendNow(TS::PAT, 188);
|
||||
myConn.SendNow(TS::PMT, 188);
|
||||
/// \todo Find a nice way to not use strings in this case
|
||||
std::string pmt = createPMT();
|
||||
myConn.SendNow(pmt.c_str(), 188);
|
||||
//myConn.SendNow(TS::PMT, 188);
|
||||
sentHeader = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "output.h"
|
||||
#include <mist/mp4_generic.h>
|
||||
#include <mist/ts_packet.h>
|
||||
#include <string>
|
||||
|
||||
namespace Mist {
|
||||
class OutTS : public Output {
|
||||
|
@ -17,6 +18,7 @@ namespace Mist {
|
|||
char VideoCounter;
|
||||
char AudioCounter;
|
||||
MP4::AVCC avccbox;
|
||||
std::string createPMT();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue