void ClientSideResponse::DebugPrintRequest() { XString method = GetHeader(XString("method")); XString response_code = GetHeader(XString("response_code")); XString http_version = GetHeader(XString("http_version")); printf("method = %s\n", method.c_str()); printf("response_code = %s\n", response_code.c_str()); printf("http_version = %s\n", http_version.c_str()); fflush(stdout); }
bool createdirs(const char* _dir) { assert(_dir); if(!_dir) return false; XString dir(_dir); Trim(dir); if(dir.empty()) return false; std::replace(dir.begin(),dir.end(),'\\','/'); while('/' == *dir.rbegin()) dir.erase(dir.end() -1); XString::size_type pos = dir.find('/'); if(XString::npos == pos) return false; XString path; while (true) { pos = dir.find('/', pos + 1); if (pos == XString::npos) { path = dir; #if _WIN32 _mkdir(path.c_str()); #else mkdir(path.c_str(), S_IRWXU); #endif break; } path = dir.substr(0, pos); #if _WIN32 _mkdir(path.c_str()); #else mkdir(path.c_str(), S_IRWXU); #endif if (pos >= dir.size()) break; } return true; }
XIRef<XTimeZone> XSimpleTimeZone::FromISOString(const XString& isoString) { if(isoString[0] != '-' && isoString[0] != '+') X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); const int sign = isoString[0] == '-' ? -1 : 1; const XString str = isoString.substr(1); if(str.empty()) X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); const size_t colonDex = str.find(':'); XString hoursStr; XString minutesStr; if(colonDex != string::npos) { hoursStr = str.substr(0, colonDex); minutesStr = str.substr(colonDex + 1); if(minutesStr.size() != 2) X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); } else hoursStr = str; if(count_if(hoursStr.begin(), hoursStr.end(), verifyDigit) != (int)hoursStr.size() || count_if(minutesStr.begin(), minutesStr.end(), verifyDigit) != (int)minutesStr.size()) { X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); } const int hours = hoursStr.ToInt(); const int minutes = minutesStr.empty() ? 0 : minutesStr.ToInt(); return new XSimpleTimeZone(sign * (int)(convert(HOURS, MINUTES, hours) + minutes)); }
XString TranscodeExport::_GetTMPName( const XString& fileName ) const { if( !fileName.Contains(".") ) X_THROW(("No extension in file name!")); if( !fileName.Contains(PATH_SLASH) ) X_THROW(("Need full path to file for export.")); vector<XString> parts; fileName.Split( PATH_SLASH, parts ); if( parts.size() < 2 ) X_THROW(("Invalid export path: %s",fileName.c_str()));; XString path; for( int i = 0; i < ((int)parts.size() - 1); i++ ) path += XString::Format( "%s%s", PATH_SLASH, parts[i].c_str() ); XString mediaFileName = parts[parts.size()-1]; XString fileBaseName = mediaFileName.substr(0, mediaFileName.find(".")); XString extension = mediaFileName.substr(mediaFileName.find(".")+1); XMD5 hash; hash.Update( (uint8_t*)fileBaseName.c_str(), fileBaseName.length() ); hash.Finalize(); XString fileBaseNameHash = hash.GetAsString(); return XString::Format( "%s%sexport-tmp-%s.%s", path.c_str(), PATH_SLASH, fileBaseNameHash.c_str(), extension.c_str() ); }
XIRef<XDomParserNode> SoapArgs::_GetNode( const XString& path, XIRef<XDomParserNode> parent ) { const size_t dot = path.find('.'); XString front = path.substr(0, dot); XString rest = dot == string::npos ? "" : path.substr(dot + 1); const list<XIRef<XDomParserNode> >::const_iterator end = parent->GetChildren().end(); list<XIRef<XDomParserNode> >::const_iterator found = end; for(list<XIRef<XDomParserNode> >::const_iterator iter = parent->GetChildren().begin(); iter != end; ++iter) { if((*iter)->GetTagName() == front) { found = iter; break; } } if(found != end) return rest.empty() ? *found : _GetNode(rest, *found); XIRef<XDomParserNode> node(new XDomParserNode(XString::Format("<%s>", front.c_str()))); parent->AppendChild(node); if(!rest.empty()) return _GetNode(rest, node); return node; /* // Key - "foo.bar.alpha" // In this case, foo and bar are CONTAINER_TYPE and alpha is a VALUE_TYPE SoapArgs* existingNode = current->Find( path); if(existingNode) { } vector<XString> parts; key.Split( ".", parts ); XHash<SoapArgsNode>* current = &_complex; if( !parts.empty() ) { XString currPath = parts[0]; size_t limit = parts.size() - 1; // Loop over all the CONTAINER_TYPE parts of the path... for( size_t i = 0; i < limit; ++i ) { SoapArgsNode* found = current->Find( currPath ); if( found ) { current = &found->_children; } else { SoapArgsNode node; node._nodeType = CONTAINER_TYPE; node._name = parts[i]; current->Add( currPath, node ); SoapArgsNode* foundNode = current->Find( currPath ); current = &foundNode->_children; } currPath += "." + parts[i]; } SoapArgsNode* found == current->Find( path ); if(found) { SoapArgs node = *found; current->Remove( parts[i] ); return found; } } SoapArgsNode node; node._nodeType = VALUE_TYPE; node._name = !parts.empty() ? parts[i] : key; */ }
void TranscodeExport::Create( XIRef<XMemory> output ) { XString tempFileName = _GetTMPName( _fileName ); // If their is only 1 export in progress (us), but the temp file exists then it means we were interrupted // (either a power issue, or a segfault) and we should delete the temporary. if( _exportsInProgress == 1 ) { if( XPath::Exists(tempFileName) ) unlink(tempFileName.c_str()); } if( XPath::Exists(tempFileName) ) X_THROW(("Export in progress exception: %s", tempFileName.c_str())); bool outputToFile = (output.IsEmpty()) ? true : false; H264Decoder decoder( GetFastH264DecoderOptions() ); XRef<YUV420PToARGB24> yuvToARGB = new YUV420PToARGB24; XRef<ARGB24ToYUV420P> argbToYUV = new ARGB24ToYUV420P; XRef<H264Transcoder> transcoder; XRef<H264Encoder> encoder; XRef<AVMuxer> muxer; XRef<ExportOverlay> ov; bool wroteToContainer = false; auto lastProgressTime = steady_clock::now(); // We are going to count how many decoding or encoding exceptions we get... If it // ever exceeds some large threshold, we bail on this export. int64_t codingExceptions = 0; XString recorderURI; while( _recorderURLS.GetNextURL( recorderURI ) ) { auto now = steady_clock::now(); if( wroteToContainer && duration_cast<seconds>(now-lastProgressTime).count() > 2 ) { _progress( _recorderURLS.PercentComplete() ); lastProgressTime = now; } try { XIRef<XMemory> responseBuffer = FRAME_STORE_CLIENT::FetchMedia( _config->GetRecorderIP(), _config->GetRecorderPort(), recorderURI ); ResultParser resultParser; resultParser.Parse( responseBuffer ); FRAME_STORE_CLIENT::ResultStatistics stats = resultParser.GetStatistics(); // If we are not provided with a bit rate or a frame rate, we use the sources values. if( _bitRate == 0 ) _bitRate = stats.averageBitRate; if( _maxRate == 0 ) _maxRate = 2 * stats.averageBitRate; if( _bufSize == 0 ) _bufSize = 2 * stats.averageBitRate; if( _frameRate == 0.0 ) _frameRate = stats.frameRate; // Fix for ffmpeg's inability to make files with fps < 6.0. Don't believe me? Try these 2 commands and play // output in vlc: // // # generate a test movie of the game of life in life.mp4 // ffmpeg -f lavfi -i life -frames:v 1000 life.mp4 // # transcode and drop framerate of life.mp4 to 1 fps. output.mp4 won't play in vlc and will have a weird // # pause at the beginning for other players. // ffmpeg -i life.mp4 -vf fps=fps=1/1 -vcodec h264 output.mp4 // if( _frameRate < 6.0 ) _frameRate = 6.0; int outputTimeBaseNum = 0; int outputTimeBaseDen = 0; int inputTimeBaseNum = 0; int inputTimeBaseDen = 0; AVKit::DToQ( (1/stats.frameRate), inputTimeBaseNum, inputTimeBaseDen ); AVKit::DToQ( (1/_frameRate), outputTimeBaseNum, outputTimeBaseDen ); if( transcoder.IsEmpty() ) { transcoder = new H264Transcoder( inputTimeBaseNum, inputTimeBaseDen, outputTimeBaseNum, outputTimeBaseDen, _speed, // if our input is key only, enable decode skipping... _recorderURLS.KeyFrameOnly() ); } double secondsPer = AVKit::QToD(inputTimeBaseNum, inputTimeBaseDen) / (AVKit::QToD(inputTimeBaseNum, inputTimeBaseDen) / (AVKit::QToD(outputTimeBaseNum, outputTimeBaseDen) * _speed)); int traversalNum = 0; int traversalDen = 0; AVKit::DToQ( secondsPer, traversalNum, traversalDen ); while( !resultParser.EndOfFile() ) { try { if( transcoder->Decode( resultParser, decoder ) ) { if( encoder.IsEmpty() ) _FinishInit( encoder, muxer, decoder, tempFileName, outputToFile, traversalNum, traversalDen ); if( ov.IsEmpty() ) ov = new ExportOverlay( _msg, _withTime, _hAlign, _vAlign, decoder.GetOutputWidth(), decoder.GetOutputHeight(), traversalNum, traversalDen ); yuvToARGB->Transform( decoder.Get(), decoder.GetOutputWidth(), decoder.GetOutputHeight() ); XIRef<Packet> rgb = yuvToARGB->Get(); XIRef<Packet> withOverlay = ov->Process( rgb, resultParser.GetFrameTS() ); argbToYUV->Transform( withOverlay, decoder.GetOutputWidth(), decoder.GetOutputHeight() ); transcoder->EncodeYUV420PAndMux( *encoder, *muxer, argbToYUV->Get() ); wroteToContainer = true; } } catch(XException& ex) { X_LOG_NOTICE("Coding exception: %s",ex.what()); ++codingExceptions; // If we have had a LOT of decoding or encoding exceptions, just give up. if( codingExceptions > 100000 ) throw ex; } } } catch( XException& ex ) { X_LOG_NOTICE("Exception thrown while processing export. Continuing: %s",ex.what()); } } if( wroteToContainer ) _progress( 1.0 ); else X_STHROW( HTTP404Exception, ("No video was found during entire export.")); if( outputToFile ) { muxer->FinalizeFile(); rename( tempFileName.c_str(), _fileName.c_str() ); } else muxer->FinalizeBuffer( output ); }