diff --git a/CMakeLists.txt b/CMakeLists.txt index 27958d23..85be13eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -479,6 +479,7 @@ makeOutput(OGG ogg http) makeOutput(FLV flv http) makeOutput(HTTPMinimalServer http_minimalserver http) makeOutput(MP4 mp4 http) +makeOutput(AAC aac http) makeOutput(MP3 mp3 http) makeOutput(H264 h264 http) makeOutput(HDS hds http) diff --git a/src/output/output_aac.cpp b/src/output/output_aac.cpp new file mode 100644 index 00000000..bd04b0ad --- /dev/null +++ b/src/output/output_aac.cpp @@ -0,0 +1,81 @@ +#include "output_aac.h" +#include + +namespace Mist{ + OutAAC::OutAAC(Socket::Connection &conn) : HTTPOutput(conn){} + + void OutAAC::init(Util::Config *cfg){ + HTTPOutput::init(cfg); + capa["name"] = "AAC"; + capa["friendly"] = "AAC over HTTP"; + capa["desc"] = "Pseudostreaming in AAC format over HTTP"; + capa["url_rel"] = "/$.aac"; + capa["url_match"] = "/$.aac"; + capa["codecs"][0u][0u].append("AAC"); + capa["methods"][0u]["handler"] = "http"; + capa["methods"][0u]["type"] = "html5/audio/aac"; + capa["methods"][0u]["priority"] = 8; + + JSON::Value opt; + opt["arg"] = "string"; + opt["default"] = ""; + opt["arg_num"] = 1; + opt["help"] = "Target filename to store AAC file as, or - for stdout."; + cfg->addOption("target", opt); + } + + bool OutAAC::isRecording(){return config->getString("target").size();} + + void OutAAC::initialSeek(){ + if (!meta){return;} + maxSkipAhead = 30000; + if (targetParams.count("buffer")){ + maxSkipAhead = atof(targetParams["buffer"].c_str())*1000; + } + Output::initialSeek(); + uint64_t cTime = currentTime(); + if (M.getLive() && cTime > maxSkipAhead){ + seek(cTime-maxSkipAhead); + } + } + + void OutAAC::sendNext(){ + char *dataPointer = 0; + size_t len = 0; + + thisPacket.getString("data", dataPointer, len); + std::string head = TS::getAudioHeader(len, M.getInit(thisIdx)); + myConn.SendNow(head); + myConn.SendNow(dataPointer, len); + } + + void OutAAC::sendHeader(){ + if (!isRecording()){ + H.Clean(); + H.SetHeader("Content-Type", "audio/aac"); + H.SetHeader("Accept-Ranges", "none"); + H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); + H.SendResponse("200", "OK", myConn); + } + sentHeader = true; + } + + void OutAAC::onHTTP(){ + std::string method = H.method; + if (method == "OPTIONS" || method == "HEAD"){ + H.Clean(); + H.SetHeader("Content-Type", "audio/aac"); + H.SetHeader("Accept-Ranges", "none"); + H.protocol = "HTTP/1.0"; + H.setCORSHeaders(); + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; + } + + parseData = true; + wantRequest = false; + } + +}// namespace Mist diff --git a/src/output/output_aac.h b/src/output/output_aac.h new file mode 100644 index 00000000..7bb52672 --- /dev/null +++ b/src/output/output_aac.h @@ -0,0 +1,19 @@ +#include "output_http.h" + +namespace Mist{ + class OutAAC : public HTTPOutput{ + public: + OutAAC(Socket::Connection &conn); + static void init(Util::Config *cfg); + void onHTTP(); + void sendNext(); + void sendHeader(); + void initialSeek(); + + private: + bool isRecording(); + bool isFileTarget(){return isRecording();} + }; +}// namespace Mist + +typedef Mist::OutAAC mistOut; diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index bb6ee04d..1adc6af2 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -253,6 +253,7 @@ namespace Mist{ if (H.GetVar("stop") != ""){targetParams["stop"] = H.GetVar("stop");} if (H.GetVar("startunix") != ""){targetParams["startunix"] = H.GetVar("startunix");} if (H.GetVar("stopunix") != ""){targetParams["stopunix"] = H.GetVar("stopunix");} + if (H.GetVar("buffer") != ""){targetParams["buffer"] = H.GetVar("buffer");} // allow setting of play back rate through buffer variable. // play back rate is set in MS per second, but the variable is a simple multiplier. if (H.GetVar("rate") != ""){