Working HLS

This commit is contained in:
Erik Zandvliet 2013-01-08 14:31:09 +01:00
parent ade1518f3d
commit f9876c7548
3 changed files with 50 additions and 62 deletions

View file

@ -57,22 +57,18 @@ namespace Connector_HTTP {
if (metadata.isMember("length") && metadata["length"].asInt() > 0){ if (metadata.isMember("length") && metadata["length"].asInt() > 0){
Result << Result <<
"#EXTM3U\r\n" "#EXTM3U\r\n"
"#EXT-X-VERSION:3\r\n" //"#EXT-X-VERSION:1\r\n"
"#EXT-X-MEDIA-SEQUENCE:1\r\n" "#EXT-X-MEDIA-SEQUENCE:1\r\n"
//"#EXT-X-ALLOW-CACHE:YES\r\n" //"#EXT-X-ALLOW-CACHE:YES\r\n"
"#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n" "#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n";
"#EXT-X-PLAYLIST-TYPE:VOD\r\n"; //"#EXT-X-PLAYLIST-TYPE:VOD\r\n";
int lastDuration = 0; int lastDuration = 0;
int lastBytePos = 0;
bool writeOffset = true; bool writeOffset = true;
int j = 0; fragIndices.push_back( metadata["keytime"][metadata["keytime"].size()-1].asInt() + 1 );
for (int i = 0; i < fragIndices.size(); i++) { for (int i = 0; i < fragIndices.size() - 1; i++) {
if (lastDuration != 0){ Result << "#EXTINF:" << (metadata["keytime"][fragIndices[i]].asInt() - lastDuration) / 1000 << "." << std::setw(3) << std::setfill('0') << ((metadata["keytime"][fragIndices[i]].asInt() - lastDuration) % 1000) << ",\r\n"
Result << "#EXTINF:" << (metadata["keytime"][fragIndices[i]].asInt() - lastDuration) / 1000 << "." << std::setw(3) << std::setfill('0') << ((metadata["keytime"][fragIndices[i]].asInt() - lastDuration) % 1000) << ",\r\n" << fragIndices[i] << "_" << fragIndices[i+1] - fragIndices[i] << ".ts\r\n";
<< ++j << ".ts\r\n";
}
lastDuration = metadata["keytime"][fragIndices[i]].asInt(); lastDuration = metadata["keytime"][fragIndices[i]].asInt();
lastBytePos = metadata["keybpos"][fragIndices[i]].asInt();
} }
Result << "#EXT-X-ENDLIST"; Result << "#EXT-X-ENDLIST";
}else{ }else{
@ -152,7 +148,6 @@ namespace Connector_HTTP {
#if DEBUG >= 1 #if DEBUG >= 1
fprintf(stderr, "Could not connect to server!\n"); fprintf(stderr, "Could not connect to server!\n");
#endif #endif
ss.close();
HTTP_S.Clean(); HTTP_S.Clean();
HTTP_S.SetBody("No such stream is available on the system. Please try again.\n"); HTTP_S.SetBody("No such stream is available on the system. Please try again.\n");
conn.SendNow(HTTP_S.BuildResponse("404", "Not found")); conn.SendNow(HTTP_S.BuildResponse("404", "Not found"));
@ -163,28 +158,23 @@ namespace Connector_HTTP {
inited = true; inited = true;
} }
temp = HTTP_R.url.find("/", 5) + 1; temp = HTTP_R.url.find("/", 5) + 1;
Segment = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find(".ts", temp) - temp).c_str()); Segment = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find("_", temp) - temp).c_str());
if( !fragIndices.size() ) { temp = HTTP_R.url.find("_", temp) + 1;
fragIndices = keyframesToFragments( Strm.metadata ); int frameCount = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find(".ts", temp) - temp).c_str());
} //if( !fragIndices.size() ) {
//fragIndices = keyframesToFragments( Strm.metadata );
//}
#if DEBUG >= 4 #if DEBUG >= 4
fprintf( stderr, "Fragment number %d\n", Segment); fprintf( stderr, "Fragment number %d\n", Segment);
fprintf( stderr, "Fragment indices %d\n", fragIndices.size() ); //fprintf( stderr, "Fragment indices %d\n", fragIndices.size() );
fprintf( stderr, "Seeking to fragment %d\n", fragIndices[Segment-1] + 1 ); //fprintf( stderr, "Seeking to fragment %d\n", fragIndices[Segment-1] + 1 );
#endif #endif
std::stringstream sstream; std::stringstream sstream;
sstream << "f " << fragIndices[Segment-1] + 1 << "\n"; sstream << "f " << Segment + 1 + frameCount << "\n";
int frameCount; sstream << "f " << Segment + 1 << "\n";
if (Segment == fragIndices.size() - 1){
fprintf( stderr, "Last Fragment\n" );
frameCount = Strm.metadata["keytime"].size() - fragIndices[Segment];
}else{
fprintf( stderr, "Not Last Fragment\n" );
frameCount = fragIndices[Segment+1] - fragIndices[Segment];
}
#if DEBUG >= 4 #if DEBUG >= 4
fprintf( stderr, "Frame count %d\n", frameCount); fprintf( stderr, "Frame count %d\n", frameCount);
#endif #endif
@ -288,21 +278,23 @@ fprintf( stderr, "Not Last Fragment\n" );
receive_marks = true; receive_marks = true;
} }
if ((Strm.getPacket(0).isMember("keyframe") && !receive_marks) || Strm.lastType() == DTSC::PAUSEMARK){ if ((Strm.getPacket(0).isMember("keyframe") && !receive_marks) || Strm.lastType() == DTSC::PAUSEMARK){
TSBuf.flush();
#if DEBUG >= 4 #if DEBUG >= 4
fprintf(stderr, "Received a %s fragment of %i bytes.\n", Strm.getPacket(0)["datatype"].asString().c_str(), TSBuf.rdbuf()->in_avail()); fprintf(stderr, "Received a %s fragment of %i bytes.\n", Strm.getPacket(0)["datatype"].asString().c_str(), TSBuf.str().size());
#endif #endif
if (Flash_RequestPending > 0 && TSBuf.rdbuf()->in_avail()){ if (Flash_RequestPending > 0 && TSBuf.str().size()){
#if DEBUG >= 3 #if DEBUG >= 3
fprintf(stderr, "Sending a fragment..."); fprintf(stderr, "Sending a fragment...");
#endif #endif
HTTP_S.Clean(); HTTP_S.Clean();
HTTP_S.SetHeader("Content-Type", "video/MP2T"); HTTP_S.SetHeader("Content-Type", "video/MP2T");
HTTP_S.SetBody(""); HTTP_S.SetBody("");
HTTP_S.SetHeader("Content-Length", TSBuf.rdbuf()->in_avail()); HTTP_S.SetHeader("Content-Length", TSBuf.str().size());
conn.SendNow(HTTP_S.BuildResponse("200", "OK")); conn.SendNow(HTTP_S.BuildResponse("200", "OK"));
conn.SendNow(TSBuf.str().c_str(),TSBuf.rdbuf()->in_avail()); conn.SendNow(TSBuf.str().c_str(),TSBuf.str().size());
TSBuf.str(""); TSBuf.str("");
Flash_RequestPending--; Flash_RequestPending--;
fprintf( stderr, "Sent %d packets\n", PacketNumber );
PacketNumber = 0; PacketNumber = 0;
#if DEBUG >= 3 #if DEBUG >= 3
fprintf(stderr, "Done\n"); fprintf(stderr, "Done\n");
@ -330,41 +322,38 @@ fprintf( stderr, " Received Keyframe of size %d\n", Strm.lastData().size() );
} }
int TSType; int TSType;
bool FirstPic = true; bool FirstPic = true;
std::string videoBuffer;
while( DTMIData.size() ) { while( DTMIData.size() ) {
ThisNaluSize = (DTMIData[0] << 24) + (DTMIData[1] << 16) + ThisNaluSize = (DTMIData[0] << 24) + (DTMIData[1] << 16) +
(DTMIData[2] << 8) + DTMIData[3]; (DTMIData[2] << 8) + DTMIData[3];
DTMIData.erase(0,4);//Erase the first four characters; DTMIData.erase(0,4);//Erase the first four characters;
TSType = (int)DTMIData[0] & 0x1F; TSType = (int)DTMIData[0] & 0x1F;
if( !( TSType == 0x09 ) ) { if( TSType == 0x05 ) {
if( TSType == 0x05 ) { if( FirstPic ) {
if( FirstPic ) { ToPack += avccbox.asAnnexB( );
ToPack += avccbox.asAnnexB( ); FirstPic = false;
FirstPic = false; }
} if( IsKeyFrame ) {
if( IsKeyFrame ) { //if( !FirstKeyFrame && FirstIDRInKeyFrame ) {
if( !FirstKeyFrame && FirstIDRInKeyFrame ) { // ToPack += (char)0x00;
ToPack += (char)0x00; // FirstIDRInKeyFrame = false;
FirstIDRInKeyFrame = false; //}
}
ToPack.append(TS::ShortNalHeader,3);
}
} else if ( TSType == 0x01 ) {
if( FirstPic ) {
ToPack += (char)0x00;
FirstPic = false;
}
ToPack.append(TS::ShortNalHeader,3);
} else {
ToPack.append(TS::NalHeader,4); ToPack.append(TS::NalHeader,4);
} }
ToPack.append(DTMIData,0,ThisNaluSize); } else if ( TSType == 0x01 ) {
if( FirstPic ) {
//ToPack += (char)0x00;
FirstPic = false;
}
ToPack.append(TS::NalHeader,4);
} else {
ToPack.append(TS::NalHeader,4);
} }
ToPack.append(DTMIData,0,ThisNaluSize);
DTMIData.erase(0,ThisNaluSize); DTMIData.erase(0,ThisNaluSize);
} }
WritePesHeader = true; WritePesHeader = true;
while( ToPack.size() ) { while( ToPack.size() ) {
if (PacketNumber == 0) { if ((PacketNumber % 42) == 0) {
PackData.DefaultPAT(); PackData.DefaultPAT();
TSBuf.write(PackData.ToString(), 188); TSBuf.write(PackData.ToString(), 188);
PackData.DefaultPMT(); PackData.DefaultPMT();
@ -399,9 +388,8 @@ fprintf( stderr, " Received Keyframe of size %d\n", Strm.lastData().size() );
DTMIData = Strm.lastData(); DTMIData = Strm.lastData();
ToPack = TS::GetAudioHeader( DTMIData.size(), Strm.metadata["audio"]["init"].asString() ); ToPack = TS::GetAudioHeader( DTMIData.size(), Strm.metadata["audio"]["init"].asString() );
ToPack += DTMIData; ToPack += DTMIData;
TimeStamp = Strm.getPacket(0)["time"].asInt() * 81000;
while( ToPack.size() ) { while( ToPack.size() ) {
if ( ( PacketNumber == 0 ) ) { if ((PacketNumber % 42) == 0){
PackData.DefaultPAT(); PackData.DefaultPAT();
TSBuf.write(PackData.ToString(), 188); TSBuf.write(PackData.ToString(), 188);
PackData.DefaultPMT(); PackData.DefaultPMT();
@ -415,7 +403,7 @@ fprintf( stderr, " Received Keyframe of size %d\n", Strm.lastData().size() );
if( WritePesHeader ) { if( WritePesHeader ) {
PackData.UnitStart( 1 ); PackData.UnitStart( 1 );
PackData.AddStuffing( 184 - (14 + ToPack.size()) ); PackData.AddStuffing( 184 - (14 + ToPack.size()) );
PackData.PESAudioLeadIn( ToPack.size(), TimeStamp ); PackData.PESAudioLeadIn( ToPack.size(), Strm.getPacket(0)["time"].asInt() * 90 );
WritePesHeader = false; WritePesHeader = false;
} else { } else {
PackData.AdaptationField( 1 ); PackData.AdaptationField( 1 );

View file

@ -148,7 +148,6 @@ int TS_Handler( Socket::Connection conn, std::string streamname ) {
DTMIData = Strm.lastData(); DTMIData = Strm.lastData();
ToPack = TS::GetAudioHeader( DTMIData.size(), Strm.metadata["audio"]["init"].asString() ); ToPack = TS::GetAudioHeader( DTMIData.size(), Strm.metadata["audio"]["init"].asString() );
ToPack += DTMIData; ToPack += DTMIData;
TimeStamp = Strm.getPacket(0)["time"].asInt() * 81000;
while( ToPack.size() ) { while( ToPack.size() ) {
if ( ( PacketNumber % 42 ) == 0 ) { if ( ( PacketNumber % 42 ) == 0 ) {
PackData.DefaultPAT(); PackData.DefaultPAT();
@ -163,9 +162,8 @@ int TS_Handler( Socket::Connection conn, std::string streamname ) {
AudioCounter ++; AudioCounter ++;
if( WritePesHeader ) { if( WritePesHeader ) {
PackData.UnitStart( 1 ); PackData.UnitStart( 1 );
PackData.RandomAccess( 0 );
PackData.AddStuffing( 184 - (14 + ToPack.size()) ); PackData.AddStuffing( 184 - (14 + ToPack.size()) );
PackData.PESAudioLeadIn( ToPack.size(), TimeStamp ); PackData.PESAudioLeadIn( ToPack.size(), Strm.getPacket(0)["time"].asInt() * 90 );
WritePesHeader = false; WritePesHeader = false;
} else { } else {
PackData.AdaptationField( 1 ); PackData.AdaptationField( 1 );

View file

@ -11,6 +11,9 @@
#include <mist/dtsc.h> //DTSC support #include <mist/dtsc.h> //DTSC support
#include <mist/mp4.h> //For initdata conversion #include <mist/mp4.h> //For initdata conversion
#define VIDEO_SCALING ( 27000000.0 / (double)DTSCStream.metadata["video"]["fpks"].asInt())
#define AUDIO_SCALING ( 27000000.0 / (double)DTSCStream.metadata["audio"]["rate"].asInt())
int main( ) { int main( ) {
char charBuffer[1024*10]; char charBuffer[1024*10];
unsigned int charCount; unsigned int charCount;
@ -122,7 +125,6 @@ int main( ) {
DTMIData = DTSCStream.lastData(); DTMIData = DTSCStream.lastData();
ToPack = TS::GetAudioHeader( DTMIData.size(), DTSCStream.metadata["audio"]["init"].asString() ); ToPack = TS::GetAudioHeader( DTMIData.size(), DTSCStream.metadata["audio"]["init"].asString() );
ToPack += DTMIData; ToPack += DTMIData;
TimeStamp = DTSCStream.getPacket(0)["time"].asInt() * 81000;
while( ToPack.size() ) { while( ToPack.size() ) {
if ( ( PacketNumber % 42 ) == 0 ) { if ( ( PacketNumber % 42 ) == 0 ) {
PackData.DefaultPAT(); PackData.DefaultPAT();
@ -138,7 +140,7 @@ int main( ) {
if( WritePesHeader ) { if( WritePesHeader ) {
PackData.UnitStart( 1 ); PackData.UnitStart( 1 );
PackData.AddStuffing( 184 - (14 + ToPack.size()) ); PackData.AddStuffing( 184 - (14 + ToPack.size()) );
PackData.PESAudioLeadIn( ToPack.size(), TimeStamp ); PackData.PESAudioLeadIn( ToPack.size(), DTSCStream.getPacket(0)["time"].asInt() * 90 );
WritePesHeader = false; WritePesHeader = false;
} else { } else {
PackData.AdaptationField( 1 ); PackData.AdaptationField( 1 );