From 4fe4fca0815c49508be613df57948d6d29fcefb0 Mon Sep 17 00:00:00 2001 From: Erik Zandvliet Date: Wed, 6 Mar 2013 11:53:31 +0100 Subject: [PATCH] Updated to allow for basic conversion. --- lib/converter.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++--- lib/converter.h | 7 ++ 2 files changed, 183 insertions(+), 9 deletions(-) diff --git a/lib/converter.cpp b/lib/converter.cpp index 65320ab1..5c6a5974 100644 --- a/lib/converter.cpp +++ b/lib/converter.cpp @@ -1,10 +1,15 @@ #include #include #include +#include +#include +#include +#include #include "timing.h" #include "converter.h" #include "procs.h" +#include "config.h" namespace Converter { @@ -12,13 +17,14 @@ namespace Converter { fillFFMpegEncoders(); } - void Converter::fillFFMpegEncoders(){ - char ** cmd = (char**)malloc(3*sizeof(char*)); - cmd[0] = "ffmpeg"; - cmd[1] = "-encoders"; - cmd[2] = NULL; + void Converter::fillFFMpegEncoders(){ + std::vector cmd; + cmd.reserve(3); + cmd.push_back((char*)"ffmpeg"); + cmd.push_back((char*)"-encoders"); + cmd.push_back(NULL); int outFD = -1; - Util::Procs::StartPiped("FFMpegInfo", cmd, 0, &outFD, 0); + Util::Procs::StartPiped("FFMpegInfo", &cmd[0], 0, &outFD, 0); while( Util::Procs::isActive("FFMpegInfo")){ Util::sleep(100); } FILE * outFile = fdopen( outFD, "r" ); char * fileBuf = 0; @@ -45,12 +51,173 @@ namespace Converter { } JSON::Value Converter::getEncoders(){ - JSON::Value Result; + JSON::Value result; for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){ for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++){ - Result[convIt->first][codIt->first] = codIt->second; + result[convIt->first][codIt->first] = codIt->second; } } - return Result; + return result; + } + + JSON::Value Converter::queryPath(std::string myPath){ + std::vector cmd; + cmd.reserve(3); + cmd.push_back((char*)"MistInfo"); + cmd.push_back(NULL); + cmd.push_back(NULL); + fprintf( stderr, "Querying %s\n", myPath.c_str()); + JSON::Value result; + DIR * Dirp = opendir(myPath.c_str()); + struct stat StatBuf; + if (Dirp){ + dirent * entry; + while ((entry = readdir(Dirp))){ + if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1){ + continue; + } + if ((StatBuf.st_mode & S_IFREG) == 0){ + continue; + } + std::string fileName = entry->d_name; + std::string myPath = std::string(myPath + (myPath[myPath.size()-1] == '/' ? "" : "/") + entry->d_name); + cmd[1] = (char*)myPath.c_str(); + int outFD = -1; + Util::Procs::StartPiped("MistInfo", &cmd[0], 0, &outFD, 0); + while( Util::Procs::isActive("MistInfo")){ Util::sleep(10); } + FILE * outFile = fdopen( outFD, "r" ); + char * fileBuf = 0; + size_t fileBufLen = 0; + getline(&fileBuf, &fileBufLen, outFile); + std::string line = fileBuf; + result[fileName] = JSON::fromString(std::string(fileBuf)); + if ( !result[fileName]){ + result.removeMember(fileName); + } + fclose( outFile ); + } + } + return result; + } + + void Converter::startConversion(std::string name, JSON::Value parameters) { + if ( !parameters.isMember("input")){ + statusHistory[name] = "No input file supplied"; + return; + } + if ( !parameters.isMember("output")){ + statusHistory[name] = "No output file supplied"; + return; + } + if ( !parameters.isMember("encoder")){ + statusHistory[name] = "No encoder specified"; + return; + } + if (allCodecs.find(parameters["encoder"]) == allCodecs.end()){ + statusHistory[name] = "Can not find encoder " + parameters["encoder"]; + return; + } + std::stringstream encoderCommand; + if (parameters["encoder"] == "ffmpeg"){ + encoderCommand << "ffmpeg -i "; + encoderCommand << parameters["input"].asString() << " "; + if (parameters.isMember("video")){ + if ( !parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy"){ + encoderCommand << "-vcodec copy "; + }else{ + codecInfo::iterator vidCodec = allCodecs["ffmpeg"].find(parameters["video"]["codec"]); + if (vidCodec == allCodecs["ffmpeg"].end()){ + statusHistory[name] = "Can not find video codec " + parameters["video"]["codec"].asString(); + return; + } + encoderCommand << "-vcodec " << vidCodec->first << " "; + if (parameters["video"].isMember("kfps")){ + encoderCommand << "-r " << parameters["video"]["kfps"].asInt() / 1000 << " "; + } + ///\todo Keyframe interval (different in older and newer versions of ffmpeg?) + } + }else{ + encoderCommand << "-vn "; + } + if (parameters.isMember("audio")){ + if ( !parameters["audio"].isMember("codec")){ + encoderCommand << "-acodec copy "; + }else{ + codecInfo::iterator audCodec = allCodecs["ffmpeg"].find(parameters["audio"]["codec"]); + if (audCodec == allCodecs["ffmpeg"].end()){ + statusHistory[name] = "Can not find audio codec " + parameters["audio"]["codec"].asString(); + return; + } + if (audCodec->second == "aac"){ + encoderCommand << "-strict -2 "; + } + encoderCommand << "-acodec " << audCodec->first << " "; + if (parameters["audio"].isMember("samplerate")){ + encoderCommand << "-ar " << parameters["audio"]["samplerate"].asInt() << " "; + } + } + }else{ + encoderCommand << "-an "; + } + encoderCommand << "-f flv -"; + } + Util::Procs::Start(name,encoderCommand.str(),Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString()); + allConversions[name] = parameters; + } + + void Converter::updateStatus(){ + if (allConversions.size()){ + std::map::iterator cIt; + bool hasChanged = true; + while (hasChanged && allConversions.size()){ + hasChanged = false; + for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){ + if (Util::Procs::isActive(cIt->first)){ + continue; + } + if (cIt->second["output"].asString().find(".dtsc") != std::string::npos){ + statusHistory[cIt->first] = "Conversion succesful, running DTSCFix"; + Util::Procs::Start(cIt->first+"DTSCFix",Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString()); + }else{ + statusHistory[cIt->first] = "Conversion succesful"; + } + allConversions.erase(cIt); + hasChanged = true; + break; + } + } + } + if(statusHistory.size()){ + std::map::iterator sIt; + for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){ + if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos){ + if (Util::Procs::isActive(sIt->first+"DTSCFIX")){ + continue; + } + statusHistory[sIt->first] = "Conversion succesful"; + } + } + } + } + + JSON::Value Converter::getStatus(){ + updateStatus(); + JSON::Value result; + if (allConversions.size()){ + for (std::map::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){ + result[cIt->first] = "Converting"; + } + } + if (statusHistory.size()){ + std::map::iterator sIt; + for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){ + result[sIt->first] = sIt->second; + } + } + return result; + } + + void Converter::clearStatus(){ + statusHistory.clear(); } } diff --git a/lib/converter.h b/lib/converter.h index b572e52e..9f3d4f28 100644 --- a/lib/converter.h +++ b/lib/converter.h @@ -12,8 +12,15 @@ namespace Converter { Converter(); converterInfo & getCodecs(); JSON::Value getEncoders(); + JSON::Value queryPath(std::string myPath); + void startConversion(std::string name, JSON::Value parameters); + void updateStatus(); + JSON::Value getStatus(); + void clearStatus(); private: void fillFFMpegEncoders(); converterInfo allCodecs; + std::map allConversions; + std::map statusHistory; }; }