MistPlayer will now auto-run DTSCFix, updated connectors to use the now guaranteed consistent metadata.
This commit is contained in:
parent
e2ef8c45d8
commit
78886239e1
5 changed files with 32 additions and 79 deletions
|
@ -10,6 +10,7 @@
|
|||
#include <mist/config.h>
|
||||
#include <mist/socket.h>
|
||||
#include <mist/timing.h>
|
||||
#include <mist/procs.h>
|
||||
|
||||
//under cygwin, recv blocks for ~15ms if no data is available.
|
||||
//This is a hack to keep performance decent with that bug present.
|
||||
|
@ -70,9 +71,23 @@ int main(int argc, char** argv){
|
|||
conf.activate();
|
||||
int playing = 0;
|
||||
|
||||
DTSC::File source = DTSC::File(conf.getString("filename"));
|
||||
Socket::Connection in_out = Socket::Connection(fileno(stdout), fileno(stdin));
|
||||
|
||||
DTSC::File source = DTSC::File(conf.getString("filename"));
|
||||
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;
|
||||
pausemark["datatype"] = "pause_marker";
|
||||
pausemark["time"] = (long long int)0;
|
||||
|
@ -84,6 +99,8 @@ int main(int argc, char** argv){
|
|||
std::string meta_str = meta.toNetPacked();
|
||||
in_out.Send(meta_str);
|
||||
|
||||
if (meta.isMember("keytime"))
|
||||
|
||||
if (meta["video"]["keyms"].asInt() < 11){
|
||||
meta["video"]["keyms"] = (long long int)1000;
|
||||
}
|
||||
|
|
|
@ -62,18 +62,10 @@ namespace Connector_HTTP {
|
|||
afrt.setFragmentRun(afrtrun, count++);
|
||||
}
|
||||
}else{
|
||||
for (int i = 0; i < metadata["keytime"].size(); i++){
|
||||
afrtrun.firstFragment = i + 1;
|
||||
for (int i = 0; i < metadata["keynum"].size(); i++){
|
||||
afrtrun.firstFragment = metadata["keynum"][i].asInt();
|
||||
afrtrun.firstTimestamp = metadata["keytime"][i].asInt();
|
||||
if (i + 1 < metadata["keytime"].size()){
|
||||
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
|
||||
}
|
||||
}
|
||||
afrtrun.duration = metadata["keylen"][i].asInt();
|
||||
afrt.setFragmentRun(afrtrun, i);
|
||||
}
|
||||
}
|
||||
|
@ -92,23 +84,10 @@ namespace Connector_HTTP {
|
|||
abst.setUpdate(true);
|
||||
}
|
||||
abst.setTimeScale(1000);
|
||||
if (metadata.isMember("vod")){
|
||||
abst.setLive(false);
|
||||
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.setMovieIdentifier(MovieId);
|
||||
//abst.setServerEntry(empty, 0);
|
||||
//abst.setQualityEntry(empty, 0);
|
||||
//abst.setDrmData(empty);
|
||||
//abst.setMetaData(empty);
|
||||
abst.setSegmentRunTable(asrt, 0);
|
||||
abst.setFragmentRunTable(afrt, 0);
|
||||
|
||||
|
|
|
@ -25,52 +25,22 @@
|
|||
|
||||
/// Holds everything unique to HTTP Connectors.
|
||||
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
|
||||
std::string BuildIndex(std::string & MovieId, JSON::Value & metadata){
|
||||
std::stringstream Result;
|
||||
if ( !metadata.isMember("live")){
|
||||
std::vector<int> fragIndices = keyframesToFragments(metadata);
|
||||
int longestFragment = 0;
|
||||
for (int i = 1; i < fragIndices.size(); i++){
|
||||
int fragDuration = metadata["keytime"][fragIndices[i]].asInt() - metadata["keytime"][fragIndices[i - 1]].asInt();
|
||||
if (fragDuration > longestFragment){
|
||||
longestFragment = fragDuration;
|
||||
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"
|
||||
//"#EXT-X-VERSION: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-PLAYLIST-TYPE:VOD\r\n";
|
||||
int lastDuration = 0;
|
||||
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();
|
||||
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{
|
||||
|
|
|
@ -222,21 +222,8 @@ namespace Connector_HTTP {
|
|||
MP4::MFHD mfhd_box;
|
||||
for (int i = 0; i < Strm.metadata["keytime"].size(); i++){
|
||||
if (Strm.metadata["keytime"][i].asInt() >= (ReqFragment / 10000)){
|
||||
if (Strm.metadata.isMember("keynum")){
|
||||
mfhd_box.setSequenceNumber(Strm.metadata["keynum"][i].asInt());
|
||||
}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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace Converters {
|
|||
std::cout << std::string(DTSC::Magic_Header, 4) << std::string((char*) &size, 4) << packed_header;
|
||||
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;
|
||||
} //FLV2DTSC
|
||||
|
|
Loading…
Add table
Reference in a new issue