MistPlayer will now auto-run DTSCFix, updated connectors to use the now guaranteed consistent metadata.

This commit is contained in:
Thulinma 2013-03-21 14:22:22 +01:00
parent e2ef8c45d8
commit 78886239e1
5 changed files with 32 additions and 79 deletions

View file

@ -10,6 +10,7 @@
#include <mist/config.h> #include <mist/config.h>
#include <mist/socket.h> #include <mist/socket.h>
#include <mist/timing.h> #include <mist/timing.h>
#include <mist/procs.h>
//under cygwin, recv blocks for ~15ms if no data is available. //under cygwin, recv blocks for ~15ms if no data is available.
//This is a hack to keep performance decent with that bug present. //This is a hack to keep performance decent with that bug present.
@ -70,9 +71,23 @@ int main(int argc, char** argv){
conf.activate(); conf.activate();
int playing = 0; int playing = 0;
DTSC::File source = DTSC::File(conf.getString("filename"));
Socket::Connection in_out = Socket::Connection(fileno(stdout), fileno(stdin)); Socket::Connection in_out = Socket::Connection(fileno(stdout), fileno(stdin));
DTSC::File source = DTSC::File(conf.getString("filename"));
JSON::Value meta = source.getMeta(); JSON::Value meta = source.getMeta();
if ( !(meta.isMember("keytime") && meta.isMember("keybpos") && meta.isMember("keynum") && meta.isMember("keylen") && meta.isMember("frags")) && meta.isMember("video")){
//file needs to be DTSCFix'ed! Run MistDTSCFix executable on it first
std::cerr << "Calculating / writing / updating VoD metadata..." << std::endl;
Util::Procs::Start("Fixer", Util::getMyPath() + "MistDTSCFix "+conf.getString("filename"));
while (Util::Procs::isActive("Fixer")){
Util::sleep(5000);
}
std::cerr << "Done!" << std::endl;
source = DTSC::File(conf.getString("filename"));
meta = source.getMeta();
}
JSON::Value pausemark; JSON::Value pausemark;
pausemark["datatype"] = "pause_marker"; pausemark["datatype"] = "pause_marker";
pausemark["time"] = (long long int)0; pausemark["time"] = (long long int)0;
@ -83,6 +98,8 @@ int main(int argc, char** argv){
//send the header //send the header
std::string meta_str = meta.toNetPacked(); std::string meta_str = meta.toNetPacked();
in_out.Send(meta_str); in_out.Send(meta_str);
if (meta.isMember("keytime"))
if (meta["video"]["keyms"].asInt() < 11){ if (meta["video"]["keyms"].asInt() < 11){
meta["video"]["keyms"] = (long long int)1000; meta["video"]["keyms"] = (long long int)1000;

View file

@ -62,18 +62,10 @@ namespace Connector_HTTP {
afrt.setFragmentRun(afrtrun, count++); afrt.setFragmentRun(afrtrun, count++);
} }
}else{ }else{
for (int i = 0; i < metadata["keytime"].size(); i++){ for (int i = 0; i < metadata["keynum"].size(); i++){
afrtrun.firstFragment = i + 1; afrtrun.firstFragment = metadata["keynum"][i].asInt();
afrtrun.firstTimestamp = metadata["keytime"][i].asInt(); afrtrun.firstTimestamp = metadata["keytime"][i].asInt();
if (i + 1 < metadata["keytime"].size()){ afrtrun.duration = metadata["keylen"][i].asInt();
afrtrun.duration = metadata["keytime"][i + 1].asInt() - metadata["keytime"][i].asInt();
}else{
if (metadata["lastms"].asInt()){
afrtrun.duration = metadata["lastms"].asInt() - metadata["keytime"][i].asInt();
}else{
afrtrun.duration = 3000; //guess 3 seconds if unknown
}
}
afrt.setFragmentRun(afrtrun, i); afrt.setFragmentRun(afrtrun, i);
} }
} }
@ -92,23 +84,10 @@ namespace Connector_HTTP {
abst.setUpdate(true); abst.setUpdate(true);
} }
abst.setTimeScale(1000); abst.setTimeScale(1000);
if (metadata.isMember("vod")){ abst.setLive(false);
abst.setLive(false); abst.setCurrentMediaTime(metadata["lastms"].asInt());
if (metadata["lastms"].asInt()){
abst.setCurrentMediaTime(metadata["lastms"].asInt());
}else{
abst.setCurrentMediaTime(1000 * metadata["length"].asInt());
}
}else{
abst.setLive(false);
abst.setCurrentMediaTime(metadata["lastms"].asInt());
}
abst.setSmpteTimeCodeOffset(0); abst.setSmpteTimeCodeOffset(0);
abst.setMovieIdentifier(MovieId); abst.setMovieIdentifier(MovieId);
//abst.setServerEntry(empty, 0);
//abst.setQualityEntry(empty, 0);
//abst.setDrmData(empty);
//abst.setMetaData(empty);
abst.setSegmentRunTable(asrt, 0); abst.setSegmentRunTable(asrt, 0);
abst.setFragmentRunTable(afrt, 0); abst.setFragmentRunTable(afrt, 0);

View file

@ -25,52 +25,22 @@
/// Holds everything unique to HTTP Connectors. /// Holds everything unique to HTTP Connectors.
namespace Connector_HTTP { namespace Connector_HTTP {
/// Parses the list of keyframes into 10 second fragments
std::vector<int> keyframesToFragments(JSON::Value & metadata){
std::vector<int> result;
if (metadata.isNull()){
return result;
}
if (metadata.isMember("keynum")){
for (int i = 0; i < metadata["keynum"].size(); i++){
result.push_back(metadata["keynum"][i].asInt());
}
}else{
result.push_back(0);
int currentBase = metadata["keytime"][0u].asInt();
for (int i = 0; i < metadata["keytime"].size(); i++){
if ((metadata["keytime"][i].asInt() - currentBase) > 10000){
currentBase = metadata["keytime"][i].asInt();
result.push_back(i);
}
}
}
return result;
}
/// Returns a m3u or m3u8 index file /// Returns a m3u or m3u8 index file
std::string BuildIndex(std::string & MovieId, JSON::Value & metadata){ std::string BuildIndex(std::string & MovieId, JSON::Value & metadata){
std::stringstream Result; std::stringstream Result;
if ( !metadata.isMember("live")){ if ( !metadata.isMember("live")){
std::vector<int> fragIndices = keyframesToFragments(metadata);
int longestFragment = 0; int longestFragment = 0;
for (int i = 1; i < fragIndices.size(); i++){ for (JSON::ArrIter ai = metadata["frags"].ArrBegin(); ai != metadata["frags"].ArrEnd(); ai++){
int fragDuration = metadata["keytime"][fragIndices[i]].asInt() - metadata["keytime"][fragIndices[i - 1]].asInt(); if ((*ai)["dur"].asInt() > longestFragment){
if (fragDuration > longestFragment){ longestFragment = (*ai)["dur"].asInt();
longestFragment = fragDuration;
} }
} }
Result << "#EXTM3U\r\n" Result << "#EXTM3U\r\n"
//"#EXT-X-VERSION:1\r\n" "#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n"
//"#EXT-X-ALLOW-CACHE:YES\r\n"
"#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n"
"#EXT-X-MEDIA-SEQUENCE:0\r\n"; "#EXT-X-MEDIA-SEQUENCE:0\r\n";
//"#EXT-X-PLAYLIST-TYPE:VOD\r\n"; for (JSON::ArrIter ai = metadata["frags"].ArrBegin(); ai != metadata["frags"].ArrEnd(); ai++){
int lastDuration = 0; Result << "#EXTINF:" << (*ai)["dur"].asInt() / 1000 << ", no desc\r\n" << (*ai)["num"].asInt() << "_" << (*ai)["len"].asInt() << ".ts\r\n";
for (int i = 0; i < fragIndices.size() - 1; i++){
Result << "#EXTINF:" << (metadata["keytime"][fragIndices[i + 1]].asInt() - lastDuration) / 1000 << ", no desc\r\n" << fragIndices[i] + 1
<< "_" << fragIndices[i + 1] - fragIndices[i] << ".ts\r\n";
lastDuration = metadata["keytime"][fragIndices[i + 1]].asInt();
} }
Result << "#EXT-X-ENDLIST"; Result << "#EXT-X-ENDLIST";
}else{ }else{

View file

@ -222,21 +222,8 @@ namespace Connector_HTTP {
MP4::MFHD mfhd_box; MP4::MFHD mfhd_box;
for (int i = 0; i < Strm.metadata["keytime"].size(); i++){ for (int i = 0; i < Strm.metadata["keytime"].size(); i++){
if (Strm.metadata["keytime"][i].asInt() >= (ReqFragment / 10000)){ if (Strm.metadata["keytime"][i].asInt() >= (ReqFragment / 10000)){
if (Strm.metadata.isMember("keynum")){ mfhd_box.setSequenceNumber(Strm.metadata["keynum"][i].asInt());
mfhd_box.setSequenceNumber(Strm.metadata["keynum"][i].asInt()); myDuration = Strm.metadata["keylen"][i].asInt() * 10000;
}else{
mfhd_box.setSequenceNumber(i + 1);
}
if (Strm.metadata.isMember("keylen")){
myDuration = Strm.metadata["keylen"][i].asInt() * 10000;
}else{
if (i != Strm.metadata["keytime"].size()){
myDuration = Strm.metadata["keytime"][i + 1].asInt() - Strm.metadata["keytime"][i].asInt();
}else{
myDuration = Strm.metadata["lastms"].asInt() - Strm.metadata["keytime"][i].asInt();
}
myDuration = myDuration * 10000;
}
break; break;
} }
} }

View file

@ -68,7 +68,7 @@ namespace Converters {
std::cout << std::string(DTSC::Magic_Header, 4) << std::string((char*) &size, 4) << packed_header; std::cout << std::string(DTSC::Magic_Header, 4) << std::string((char*) &size, 4) << packed_header;
std::cout << prebuffer.rdbuf(); std::cout << prebuffer.rdbuf();
} }
std::cerr << "Done! If you output this data to a file, don't forget to run MistDTSCFix next." << std::endl; std::cerr << "Done!" << std::endl;
return 0; return 0;
} //FLV2DTSC } //FLV2DTSC