Updated MistConnHTTPLive for DTSC2, fixed a bug in fragmentizing.

This commit is contained in:
Erik Zandvliet 2013-06-06 14:52:55 +02:00
parent 0d5011a89a
commit c6aabfa4bf
3 changed files with 81 additions and 26 deletions

View file

@ -111,8 +111,10 @@ int main(int argc, char** argv){
JSON::Value last_pack;
bool meta_sent = false;
int playUntil = -1;
long long now, lastTime = 0; //for timing of sending packets
long long bench = 0; //for benchmarking
std::set<int> newSelect;
Stats sts;
CYG_DEFI
@ -182,6 +184,11 @@ int main(int argc, char** argv){
playing = -1;
lastTime = 0;
in_out.setBlocking(false);
if (in_out.Received().get().size() >= 2){
playUntil = atoi(in_out.Received().get().substr(2).c_str());
}else{
playUntil = 0;
}
break;
}
case 'o': { //once-play
@ -199,7 +206,7 @@ int main(int argc, char** argv){
break;
}
case 't': {
std::set<int> newSelect;
newSelect.clear();
std::string tmp = in_out.Received().get().substr(2);
while (tmp != ""){
newSelect.insert(atoi(tmp.substr(0,tmp.find(' ')).c_str()));
@ -239,6 +246,9 @@ int main(int argc, char** argv){
--playing;
}
}
if ( playUntil && playUntil < source.getJSON()["time"].asInt()){
playing = 0;
}
if (playing == 0){
#if DEBUG >= 4
std::cerr << "Completed VoD request in MistPlayer (" << (Util::getMS() - bench) << "ms)" << std::endl;

View file

@ -29,36 +29,54 @@ namespace Connector_HTTP {
///\param metadata The current metadata, used to generate the index.
///\return The index file for HTTP Live Streaming.
std::string liveIndex(JSON::Value & metadata){
std::stringstream Result;
if ( !metadata.isMember("live")){
std::stringstream result;
if (metadata.isMember("tracks")){
result << "#EXTM3U\r\n";
int audioId = -1;
std::string audioName;
bool defAudio = false;//set default audio track;
for (JSON::ObjIter trackIt = metadata["tracks"].ObjBegin(); trackIt != metadata["tracks"].ObjEnd(); trackIt++){
if (trackIt->second["type"].asString() == "audio"){
audioId = trackIt->second["trackid"].asInt();
audioName = trackIt->first;
break;
}
}
for (JSON::ObjIter trackIt = metadata["tracks"].ObjBegin(); trackIt != metadata["tracks"].ObjEnd(); trackIt++){
if (trackIt->second["type"].asString() == "video"){
int bWidth = trackIt->second["maxbps"].asInt();
if (audioId != -1){
bWidth += (metadata["tracks"][audioName]["maxbps"].asInt() * 2);
}
result << "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" << bWidth * 8 << "\r\n";
result << trackIt->second["trackid"].asInt();
if (audioId != -1){
result << "_" << audioId;
}
result << "/index.m3u8\r\n";
}
}
}else{
//parse single track
int longestFragment = 0;
for (JSON::ArrIter ai = metadata["frags"].ArrBegin(); ai != metadata["frags"].ArrEnd(); ai++){
if ((*ai)["dur"].asInt() > longestFragment){
longestFragment = (*ai)["dur"].asInt();
}
}
Result << "#EXTM3U\r\n"
result << "#EXTM3U\r\n"
"#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n"
"#EXT-X-MEDIA-SEQUENCE:0\r\n";
"#EXT-X-MEDIA-SEQUENCE:" << metadata["trackid"].asInt() << "\r\n";
for (JSON::ArrIter ai = metadata["frags"].ArrBegin(); ai != metadata["frags"].ArrEnd(); ai++){
Result << "#EXTINF:" << (*ai)["dur"].asInt() / 1000 << ", no desc\r\n" << (*ai)["num"].asInt() << "_" << (*ai)["len"].asInt() << ".ts\r\n";
}
Result << "#EXT-X-ENDLIST";
}else{
if (metadata["missed_frags"].asInt() < 0){
metadata["missed_frags"] = 0ll;
}
Result << "#EXTM3U\r\n"
"#EXT-X-MEDIA-SEQUENCE:" << metadata["missed_frags"].asInt() <<"\r\n"
"#EXT-X-TARGETDURATION:30\r\n";
for (JSON::ArrIter ai = metadata["frags"].ArrBegin(); ai != metadata["frags"].ArrEnd(); ai++){
Result << "#EXTINF:" << (*ai)["dur"].asInt() / 1000 << ", no desc\r\n" << (*ai)["num"].asInt() << "_" << (*ai)["len"].asInt() << ".ts\r\n";
result << "#EXTINF:" << (*ai)["dur"].asInt() / 1000 << ", no desc\r\n"
<< metadata["keys"][(*ai)["num"].asInt() - 1]["time"].asInt() << "_" << (*ai)["dur"].asInt() + metadata["keys"][(*ai)["num"].asInt() - 1]["time"].asInt() << ".ts\r\n";
}
result << "#EXT-X-ENDLIST";
}
#if DEBUG >= 8
std::cerr << "Sending this index:" << std::endl << Result.str() << std::endl;
#endif
return Result.str();
return result.str();
} //liveIndex
///\brief Main function for the HTTP Live Connector
@ -92,6 +110,8 @@ namespace Connector_HTTP {
int Segment = -1;
int temp;
int trackID = 0;
int audioTrackID = 0;
unsigned int lastStats = 0;
conn.setBlocking(false); //do not block on conn.spool() when no data is available
@ -137,6 +157,10 @@ namespace Connector_HTTP {
}
if (HTTP_R.url.find(".m3u") == std::string::npos){
temp = HTTP_R.url.find("/", 5) + 1;
std::string allTracks = HTTP_R.url.substr(temp, HTTP_R.url.find("/", temp) - temp);
trackID = atoi(allTracks.c_str());
audioTrackID = atoi(allTracks.substr(allTracks.find("_")+1).c_str());
temp = HTTP_R.url.find("/", temp) + 1;
Segment = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find("_", temp) - temp).c_str());
temp = HTTP_R.url.find("_", temp) + 1;
int frameCount = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find(".ts", temp) - temp).c_str());
@ -159,13 +183,19 @@ namespace Connector_HTTP {
continue;
}
}
std::stringstream sstream;
sstream << "f " << Segment << "\n";
for (int i = 0; i < frameCount; i++){
sstream << "o \n";
for (int i = 0; i < allTracks.size(); i++){
if (allTracks[i] == '_'){
allTracks[i] = ' ';
}
}
std::stringstream sstream;
sstream << "t " << allTracks << "\n";
sstream << "s " << Segment << "\n";
sstream << "p " << frameCount << "\n";
ss.SendNow(sstream.str().c_str());
fprintf(stderr,"Sending %s to player\n", sstream.str().c_str());
}else{
std::string request = HTTP_R.url.substr(HTTP_R.url.find("/", 5) + 1);
if (HTTP_R.url.find(".m3u8") != std::string::npos){
manifestType = "audio/x-mpegurl";
}else{
@ -174,7 +204,13 @@ namespace Connector_HTTP {
HTTP_S.Clean();
HTTP_S.SetHeader("Content-Type", manifestType);
HTTP_S.SetHeader("Cache-Control", "no-cache");
std::string manifest = liveIndex(Strm.metadata);
std::string manifest;
if (request.find("/") == std::string::npos){
manifest = liveIndex(Strm.metadata);
}else{
int selectId = atoi(request.substr(0,request.find("/")).c_str());
manifest = liveIndex(Strm.getTrackById(selectId));
}
HTTP_S.SetBody(manifest);
conn.SendNow(HTTP_S.BuildResponse("200", "OK"));
}
@ -209,7 +245,7 @@ namespace Connector_HTTP {
TSBuf.str("");
}
if ( !haveAvcc){
avccbox.setPayload(Strm.metadata["video"]["init"].asString());
avccbox.setPayload(Strm.getTrackById(trackID)["init"].asString());
haveAvcc = true;
}
if (Strm.lastType() == DTSC::VIDEO || Strm.lastType() == DTSC::AUDIO){
@ -246,7 +282,7 @@ namespace Connector_HTTP {
PIDno = 0x100;
ContCounter = &VideoCounter;
}else if (Strm.lastType() == DTSC::AUDIO){
ToPack.append(TS::GetAudioHeader(Strm.lastData().size(), Strm.metadata["audio"]["init"].asString()));
ToPack.append(TS::GetAudioHeader(Strm.lastData().size(), Strm.getTrackById(audioTrackID)["init"].asString()));
ToPack.append(Strm.lastData());
ToPack.prepend(TS::Packet::getPESAudioLeadIn(ToPack.bytes(1073741824ul), Strm.getPacket(0)["time"].asInt() * 90));
PIDno = 0x101;

View file

@ -216,25 +216,34 @@ namespace Converters {
//calculate fragments
meta["tracks"][it->first]["frags"].null();
long long int currFrag = -1;
long long int maxBps = 0;
for (JSON::ArrIter arrIt = meta["tracks"][it->first]["keys"].ArrBegin(); arrIt != meta["tracks"][it->first]["keys"].ArrEnd(); arrIt++) {
if ((*arrIt)["time"].asInt() / 10000 > currFrag){
currFrag = (*arrIt)["time"].asInt() / 10000;
long long int fragLen = 1;
long long int fragDur = (*arrIt)["len"].asInt();
for (JSON::ArrIter it2 = arrIt; it2 != meta["tracks"][it->first]["keys"].ArrEnd(); it2++){
long long int fragSize = (*arrIt)["size"].asInt();
for (JSON::ArrIter it2 = arrIt + 1; it2 != meta["tracks"][it->first]["keys"].ArrEnd(); it2++){
if ((*it2)["time"].asInt() / 10000 > currFrag || (it2 + 1) == meta["tracks"][it->first]["keys"].ArrEnd()){
JSON::Value thisFrag;
thisFrag["num"] = (*arrIt)["num"].asInt();
thisFrag["len"] = fragLen;
thisFrag["dur"] = fragDur;
thisFrag["size"] = fragSize;
thisFrag["bps"] = fragSize / (fragDur / 1000);
if (maxBps < (fragSize / (fragDur / 1000))){
maxBps = (fragSize / (fragDur / 1000));
}
meta["tracks"][it->first]["frags"].append(thisFrag);
break;
}
fragLen ++;
fragDur += (*it2)["len"].asInt();
fragSize += (*it2)["size"].asInt();
}
}
}
meta["tracks"][it->first]["maxbps"] = maxBps;
}
meta["firstms"] = firstms;