void BaseOutRecording::SignalAudioStreamCapabilitiesChanged( StreamCapabilities *pCapabilities, AudioCodecInfo *pOld, AudioCodecInfo *pNew) { if ((pOld == NULL)&&(pNew != NULL)) return; WARN("Codecs changed and the recordings does not support it. Closing recording"); if (pOld != NULL) FINEST("pOld: %s", STR(*pOld)); if (pNew != NULL) FINEST("pNew: %s", STR(*pNew)); else FINEST("pNew: NULL"); EnqueueForDelete(); }
bool BaseVariantProtocol::SignalInputData(IOBuffer &buffer) { if (_pProtocolHandler == NULL) { FATAL("This protocol is not registered to any application yet"); return false; } if (_pFarProtocol->GetType() == PT_OUTBOUND_HTTP || _pFarProtocol->GetType() == PT_INBOUND_HTTP) { #ifdef HAS_PROTOCOL_HTTP //1. This is a HTTP based transfer. We only start doing stuff //after a complete request is made. BaseHTTPProtocol *pHTTPProtocol = (BaseHTTPProtocol *) _pFarProtocol; if (!pHTTPProtocol->TransferCompleted()) return true; if (!Deserialize(GETIBPOINTER(buffer), pHTTPProtocol->GetContentLength(), _lastReceived)) { FATAL("Unable to deserialize content"); return false; } buffer.Ignore(pHTTPProtocol->GetContentLength()); _lastReceived.Compact(); return _pProtocolHandler->ProcessMessage(this, _lastSent, _lastReceived); #else FATAL("HTTP protocol not supported"); return false; #endif /* HAS_PROTOCOL_HTTP */ } else if (_pFarProtocol->GetType() == PT_TCP) { while (GETAVAILABLEBYTESCOUNT(buffer) > 4) { uint32_t size = ENTOHLP(GETIBPOINTER(buffer)); if (size > 4 * 1024 * 1024) { FATAL("Size too big: %u", size); return false; } if (GETAVAILABLEBYTESCOUNT(buffer) < size + 4) { FINEST("Need more data"); return true; } if (!Deserialize(GETIBPOINTER(buffer) + 4, size, _lastReceived)) { FATAL("Unable to deserialize variant"); return false; } buffer.Ignore(size + 4); _lastReceived.Compact(); if (!_pProtocolHandler->ProcessMessage(this, _lastSent, _lastReceived)) { FATAL("Unable to process message"); return false; } } return true; } else { FATAL("Invalid protocol stack"); return false; } }
bool HTTP4CLIProtocol::SignalInputData(IOBuffer &buffer) { //1. Get the HTTP protocol. We are sure is a PT_INBOUND_HTTP //because we return true inside AllowFarProtocol only when type == PT_INBOUND_HTTP InboundHTTPProtocol *pHTTP = (InboundHTTPProtocol *) GetFarProtocol(); //2. Get the request headers Variant headers = pHTTP->GetHeaders(); //3. Populate the input buffer for the next protocol in the stack (PT_INBOUND_JSONCLI) //with the data we just found out inside the headers URI uri; string dummy = "http://localhost" + (string) headers[HTTP_FIRST_LINE][HTTP_URL]; FINEST("dummy: %s",STR(dummy)); if (!URI::FromString(dummy, false, uri)) { FATAL("Invalid request"); return false; } string fullCommand=uri.document; fullCommand+=" "; if(uri.parameters.size()!=0){ fullCommand+=unb64(MAP_VAL(uri.parameters.begin())); } fullCommand+="\n"; _localInputBuffer.ReadFromString(fullCommand); //4. Call the next protocol with the new buffer return GetNearProtocol()->SignalInputData(_localInputBuffer); }
void ProtocolManager::EnqueueForDelete(BaseProtocol *pProtocol) { if (pProtocol->GetNearProtocol() == NULL) { FINEST("Enqueue for delete for protocol %s", STR(*pProtocol)); } pProtocol->SetApplication(NULL); if (MAP_HAS1(_activeProtocols, pProtocol->GetId())) _activeProtocols.erase(pProtocol->GetId()); if (!MAP_HAS1(_deadProtocols, pProtocol->GetId())) _deadProtocols[pProtocol->GetId()] = pProtocol; }
void BaseLiveFLVAppProtocolHandler::UnRegisterProtocol(BaseProtocol *pProtocol) { if (!MAP_HAS1(_protocols, pProtocol->GetId())) { ASSERT("Protocol ID %u not registered", pProtocol->GetId()); return; } if (pProtocol->GetType() != PT_INBOUND_LIVE_FLV) { ASSERT("This protocol can't be unregistered here"); return; } _protocols.erase(pProtocol->GetId()); FINEST("protocol %s unregistered from app %s", STR(*pProtocol), STR(GetApplication()->GetName())); }
void BaseLiveFLVAppProtocolHandler::RegisterProtocol(BaseProtocol *pProtocol) { if (MAP_HAS1(_protocols, pProtocol->GetId())) { ASSERT("Protocol ID %u already registered", pProtocol->GetId()); return; } if (pProtocol->GetType() != PT_INBOUND_LIVE_FLV) { ASSERT("This protocol can't be registered here"); return; } _protocols[pProtocol->GetId()] = (InboundLiveFLVProtocol *) pProtocol; FINEST("protocol %s registered to app %s", STR(*pProtocol), STR(GetApplication()->GetName())); }
bool InNetLiveFLVStream::FeedData(uint8_t *pData, uint32_t dataLength, uint32_t processedLength, uint32_t totalLength, double pts, double dts, bool isAudio) { if (isAudio) { _stats.audio.packetsCount++; _stats.audio.bytesCount += dataLength; if ((!_audioCapabilitiesInitialized) && (processedLength == 0)) { if (!InNetRTMPStream::InitializeAudioCapabilities(this, _streamCapabilities, _audioCapabilitiesInitialized, pData, dataLength)) { FATAL("Unable to initialize audio capabilities"); return false; } } _lastAudioTime = pts; } else { _stats.video.packetsCount++; _stats.video.bytesCount += dataLength; if ((!_videoCapabilitiesInitialized) && (processedLength == 0)) { if (!InNetRTMPStream::InitializeVideoCapabilities(this, _streamCapabilities, _videoCapabilitiesInitialized, pData, dataLength)) { FATAL("Unable to initialize audio capabilities"); return false; } } _lastVideoPts = pts; _lastVideoDts = dts; } LinkedListNode<BaseOutStream *> *pTemp = _pOutStreams; while (pTemp != NULL) { if (!pTemp->info->IsEnqueueForDelete()) { if (!pTemp->info->FeedData(pData, dataLength, processedLength, totalLength, pts, dts, isAudio)) { FINEST("Unable to feed OS: %p", pTemp->info); pTemp->info->EnqueueForDelete(); if (GetProtocol() == pTemp->info->GetProtocol()) { return false; } } } pTemp = pTemp->pPrev; } return true; }
bool BaseInFileStream::SignalPlay(double &absoluteTimestamp, double &length) { INFO("signal play"); //0. fix absoluteTimestamp and length absoluteTimestamp = absoluteTimestamp < 0 ? 0 : absoluteTimestamp; _playLimit = length; FINEST("absoluteTimestamp: %.2f; _playLimit: %.2f", absoluteTimestamp, _playLimit); //TODO: implement the limit playback //1. Seek to the correct point if (!InternalSeek(absoluteTimestamp)) { FATAL("Unable to seek to %.02f", absoluteTimestamp); return false; } //2. Put the stream in active mode _streamingState = FILE_STREAMING_STATE_PLAYING; //3. Start the feed reaction ReadyForSend(); //4. Done return true; }
void InFileRTMPStream::SignalOutStreamDetached(BaseOutStream *pOutStream) { FINEST("outbound stream %u detached from inbound stream %u", pOutStream->GetUniqueId(), GetUniqueId()); }
bool BaseVariantAppProtocolHandler::ProcessMessage(BaseVariantProtocol *pProtocol, Variant &lastSent, Variant &lastReceived) { FINEST("lastSent:\n%s", STR(lastSent.ToString())); FINEST("lastReceived:\n%s", STR(lastReceived.ToString())); return true; }
bool Initialize() { Logger::Init(); if ((bool)gRs.commandLine["arguments"]["--use-implicit-console-appender"]) { Variant dummy; dummy[CONF_LOG_APPENDER_NAME] = "implicit console appender"; dummy[CONF_LOG_APPENDER_TYPE] = CONF_LOG_APPENDER_TYPE_CONSOLE; dummy[CONF_LOG_APPENDER_COLORED] = (bool)true; dummy[CONF_LOG_APPENDER_LEVEL] = (uint32_t) 6; ConsoleLogLocation * pLogLocation = new ConsoleLogLocation(dummy); pLogLocation->SetLevel(_FINEST_); Logger::AddLogLocation(pLogLocation); } INFO("Reading configuration from %s", STR(gRs.commandLine["arguments"]["configFile"])); #ifdef COMPILE_STATIC gRs.pConfigFile = new ConfigFile(SpawnApplication, SpawnFactory); #else gRs.pConfigFile = new ConfigFile(NULL, NULL); #endif string configFilePath = gRs.commandLine["arguments"]["configFile"]; string fileName; string extension; splitFileName(configFilePath, fileName, extension); if (lowerCase(extension) == "xml") { if (!gRs.pConfigFile->LoadXmlFile(configFilePath, (bool)gRs.commandLine["arguments"]["--daemon"])) { FATAL("Unable to load file %s", STR(configFilePath)); return false; } } else if (lowerCase(extension) == "lua") { #ifdef HAS_LUA if (!gRs.pConfigFile->LoadLuaFile(configFilePath, (bool)gRs.commandLine["arguments"]["--daemon"])) { FATAL("Unable to load file %s", STR(configFilePath)); return false; } #else fprintf(stdout, "Lua is not supported by the current build of the server\n"); ASSERT("Lua is not supported by the current build of the server"); return false; #endif /* HAS_LUA */ } else { FATAL("Invalid file format: %s", STR(configFilePath)); return false; } #ifndef WIN32 if (gRs.pConfigFile->IsDaemon()) { if (!gRs.daemon) { INFO("Daemonize..."); pid_t pid = fork(); if (pid < 0) { FATAL("Unable to start as daemon. fork() failed"); return false; } if (pid > 0) { if (gRs.commandLine["arguments"].HasKey("--pid")) WritePidFile(pid); return false; } FINEST("Create a new SID for the daemon"); pid_t sid = setsid(); if (sid < 0) { FATAL("Unable to start as daemon. setsid() failed"); return false; } int fd = open("/dev/null", O_RDWR, 0); if (fd < 0) { FATAL("Unable to start as daemon. open(/dev/null) failed"); return false; } (void) dup2(fd, STDIN_FILENO); (void) dup2(fd, STDOUT_FILENO); (void) dup2(fd, STDERR_FILENO); if (fd > 2) { (void) close(fd); } gRs.daemon = true; Logger::SignalFork(); } } #endif /* WIN32 */ INFO("Configure logger"); if (!gRs.pConfigFile->ConfigLogAppenders()) { FATAL("Unable to configure log appenders"); return false; } INFO("%s", STR(Version::GetBanner())); INFO("Initialize I/O handlers manager: %s", NETWORK_REACTOR); IOHandlerManager::Initialize(); INFO("Configure modules"); if (!gRs.pConfigFile->ConfigModules()) { FATAL("Unable to configure modules"); return false; } INFO("Plug in the default protocol factory"); gRs.pProtocolFactory = new DefaultProtocolFactory(); if (!ProtocolFactoryManager::RegisterProtocolFactory(gRs.pProtocolFactory)) { FATAL("Unable to register default protocols factory"); return false; } INFO("Configure factories"); if (!gRs.pConfigFile->ConfigFactories()) { FATAL("Unable to configure factories"); return false; } INFO("Configure acceptors"); if (!gRs.pConfigFile->ConfigAcceptors()) { FATAL("Unable to configure acceptors"); return false; } INFO("Configure instances"); if (!gRs.pConfigFile->ConfigInstances()) { FATAL("Unable to configure instances"); return false; } INFO("Start I/O handlers manager: %s", NETWORK_REACTOR); IOHandlerManager::Start(); INFO("Configure applications"); if (!gRs.pConfigFile->ConfigApplications()) { FATAL("Unable to configure applications"); return false; } INFO("Install the quit signal"); installQuitSignal(QuitSignalHandler); return true; }
bool InboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) { switch (_rtmpState) { case RTMP_STATE_NOT_INITIALIZED: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1537) { return true; } uint8_t handshakeType = GETIBPOINTER(buffer)[0]; if (!buffer.Ignore(1)) { FATAL("Unable to ignore one byte"); return false; } _currentFPVersion = ENTOHLP(GETIBPOINTER(buffer) + 4); switch (handshakeType) { case 3: //plain { return PerformHandshake(buffer, false); } case 6: //encrypted { return PerformHandshake(buffer, true); } default: { FATAL("Handshake type not implemented: %hhu", handshakeType); return false; } } } case RTMP_STATE_SERVER_RESPONSE_SENT: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1536) { return true; } else { //ignore the client's last handshake part if (!buffer.Ignore(1536)) { FATAL("Unable to ignore inbound data"); return false; } _handshakeCompleted = true; _rtmpState = RTMP_STATE_DONE; if (_pKeyIn != NULL && _pKeyOut != NULL) { //insert the RTMPE protocol in the current protocol stack BaseProtocol *pFarProtocol = GetFarProtocol(); RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); ResetFarProtocol(); pFarProtocol->SetNearProtocol(pRTMPE); pRTMPE->SetNearProtocol(this); FINEST("New protocol chain: %s", STR(*pFarProtocol)); //decrypt the leftovers RC4(_pKeyIn, GETAVAILABLEBYTESCOUNT(buffer), GETIBPOINTER(buffer), GETIBPOINTER(buffer)); } return true; } } default: { FATAL("Invalid RTMP state: %d", _rtmpState); return false; } } }
bool MonitorRTMPProtocol::ProcessBytes(IOBuffer &buffer) { while (true) { uint32_t availableBytesCount = GETAVAILABLEBYTESCOUNT(buffer); if (_selectedChannel < 0) { if (availableBytesCount < 1) { return true; } else { switch (GETIBPOINTER(buffer)[0]&0x3f) { case 0: { if (availableBytesCount < 2) { FINEST("Not enough data"); return true; } _selectedChannel = 64 + GETIBPOINTER(buffer)[1]; _channels[_selectedChannel].lastInHeaderType = GETIBPOINTER(buffer)[0] >> 6; buffer.Ignore(2); availableBytesCount -= 2; break; } case 1: { // if (availableBytesCount < 3) { // FINEST("Not enough data"); // return true; // } // _selectedChannel = GETIBPOINTER(buffer)[2]*256 + GETIBPOINTER(buffer)[1] + 64; // _channels[_selectedChannel].lastInHeaderType = GETIBPOINTER(buffer)[0] >> 6; // buffer.Ignore(3); // availableBytesCount -= 3; // break; FATAL("The server doesn't support channel ids bigger than 319"); return false; }; default: { _selectedChannel = GETIBPOINTER(buffer)[0]&0x3f; _channels[_selectedChannel].lastInHeaderType = GETIBPOINTER(buffer)[0] >> 6; buffer.Ignore(1); availableBytesCount -= 1; break; } } } } Channel &channel = _channels[_selectedChannel]; Header &header = channel.lastInHeader; FINEST("header: %s", STR(header)); if (channel.state == CS_HEADER) { if (!header.Read(_selectedChannel, channel.lastInHeaderType, buffer, availableBytesCount)) { FATAL("Unable to read header"); return false; } else { if (!header.readCompleted) return true; if (H_SI(header) >= _maxStreamCount) { FATAL("%s", STR(header)); FATAL("buffer:\n%s", STR(buffer)); ASSERT("invalid stream index"); } if (H_CI(header) >= _maxChannelsCount) { FATAL("%s", STR(header)); FATAL("buffer:\n%s", STR(buffer)); ASSERT("invalid channel index"); } switch ((uint8_t) H_MT(header)) { case RM_HEADER_MESSAGETYPE_ABORTMESSAGE: case RM_HEADER_MESSAGETYPE_ACK: case RM_HEADER_MESSAGETYPE_AGGREGATE: case RM_HEADER_MESSAGETYPE_AUDIODATA: case RM_HEADER_MESSAGETYPE_CHUNKSIZE: case RM_HEADER_MESSAGETYPE_FLEX: case RM_HEADER_MESSAGETYPE_FLEXSHAREDOBJECT: case RM_HEADER_MESSAGETYPE_FLEXSTREAMSEND: case RM_HEADER_MESSAGETYPE_INVOKE: case RM_HEADER_MESSAGETYPE_NOTIFY: case RM_HEADER_MESSAGETYPE_PEERBW: case RM_HEADER_MESSAGETYPE_SHAREDOBJECT: case RM_HEADER_MESSAGETYPE_USRCTRL: case RM_HEADER_MESSAGETYPE_VIDEODATA: case RM_HEADER_MESSAGETYPE_WINACKSIZE: { break; } default: { FATAL("%s", STR(header)); FATAL("buffer:\n%s", STR(buffer)); ASSERT("invalid message type"); } } channel.state = CS_PAYLOAD; switch (channel.lastInHeaderType) { case HT_FULL: { channel.lastInAbsTs = H_TS(header); break; } case HT_SAME_STREAM: case HT_SAME_LENGTH_AND_STREAM: { channel.lastInAbsTs += H_TS(header); break; } case HT_CONTINUATION: { if (channel.lastInProcBytes == 0) { channel.lastInAbsTs += H_TS(header); } break; } } } } if (channel.state == CS_PAYLOAD) { uint32_t tempSize = H_ML(header) - channel.lastInProcBytes; tempSize = (tempSize >= _inboundChunkSize) ? _inboundChunkSize : tempSize; uint32_t availableBytes = GETAVAILABLEBYTESCOUNT(buffer); if (tempSize > availableBytes) return true; channel.state = CS_HEADER; _selectedChannel = -1; switch (H_MT(header)) { case RM_HEADER_MESSAGETYPE_VIDEODATA: { if (H_SI(header) >= _maxStreamCount) { FATAL("Incorrect stream index"); return false; } //FINEST("Video data"); channel.lastInProcBytes += tempSize; if (H_ML(header) == channel.lastInProcBytes) { channel.lastInProcBytes = 0; } if (!buffer.Ignore(tempSize)) { FATAL("V: Unable to ignore %u bytes", tempSize); return false; } break; } case RM_HEADER_MESSAGETYPE_AUDIODATA: { if (H_SI(header) >= _maxStreamCount) { FATAL("Incorrect stream index"); return false; } //FINEST("Audio data"); channel.lastInProcBytes += tempSize; if (H_ML(header) == channel.lastInProcBytes) { channel.lastInProcBytes = 0; } if (!buffer.Ignore(tempSize)) { FATAL("A: Unable to ignore %u bytes", tempSize); return false; } break; } default: { channel.inputData.ReadFromInputBuffer(buffer, tempSize); channel.lastInProcBytes += tempSize; if (!buffer.Ignore(tempSize)) { FATAL("Unable to ignore %u bytes", tempSize); return false; } if (H_ML(header) == channel.lastInProcBytes) { channel.lastInProcBytes = 0; Variant msg; if (!_rtmpProtocolSerializer.Deserialize(header, channel.inputData, msg)) { FATAL("Unable to deserialize message"); return false; } if ((uint8_t) VH_MT(msg) == RM_HEADER_MESSAGETYPE_CHUNKSIZE) { _inboundChunkSize = (uint32_t) msg[RM_CHUNKSIZE]; } if ((uint8_t) VH_MT(msg) == RM_HEADER_MESSAGETYPE_ABORTMESSAGE) { uint32_t channelId = (uint32_t) msg[RM_ABORTMESSAGE]; if (channelId >= _maxChannelsCount) { FATAL("Invalid channel id in reset message: %" PRIu32, channelId); return false; } o_assert(_channels[channelId].id == channelId); _channels[channelId].Reset(); } if (GETAVAILABLEBYTESCOUNT(channel.inputData) != 0) { FATAL("Invalid message! We have leftovers: %u bytes", GETAVAILABLEBYTESCOUNT(channel.inputData)); return false; } } break; } } } } }
bool PushVariant(lua_State *pLuaState, Variant &variant, bool substituteNullables) { switch ((VariantType) variant) { case V_UNDEFINED: case V_NULL: { if (substituteNullables) lua_pushstring(pLuaState, VAR_NULL_VALUE); else lua_pushnil(pLuaState); return true; break; } case V_STRING: { lua_pushstring(pLuaState, STR(variant)); return true; break; } case V_INT8: case V_INT16: case V_INT32: case V_INT64: case V_UINT8: case V_UINT16: case V_UINT32: case V_UINT64: case V_DOUBLE: { lua_pushnumber(pLuaState, (double) variant); return true; break; } case V_BOOL: { lua_pushboolean(pLuaState, (bool)variant); return true; break; } case V_TIMESTAMP: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_TIMESTAMP); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, tempTm.tm_year + 1900); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, tempTm.tm_mon+1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, tempTm.tm_mday); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_HOUR); lua_pushnumber(pLuaState, tempTm.tm_hour); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MIN); lua_pushnumber(pLuaState, tempTm.tm_min); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_SEC); lua_pushnumber(pLuaState, tempTm.tm_sec); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_ISDST); lua_pushboolean(pLuaState, false); lua_settable(pLuaState, -3); return true; break; } case V_DATE: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_DATE); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, tempTm.tm_year + 1900); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, tempTm.tm_mon); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, tempTm.tm_mday); lua_settable(pLuaState, -3); return true; break; } case V_TIME: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_TIME); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, 1970); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_HOUR); lua_pushnumber(pLuaState, tempTm.tm_hour); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MIN); lua_pushnumber(pLuaState, tempTm.tm_min); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_SEC); lua_pushnumber(pLuaState, tempTm.tm_sec); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_ISDST); lua_pushboolean(pLuaState, false); lua_settable(pLuaState, -3); return true; break; } case V_TYPED_MAP: case V_MAP: { lua_createtable(pLuaState, 0, 0); if ((VariantType) variant == V_TYPED_MAP) { lua_pushstring(pLuaState, VAR_MAP_NAME); lua_pushstring(pLuaState, STR(variant.GetTypeName())); lua_settable(pLuaState, -3); } FOR_MAP(variant, string, Variant, i) { if (MAP_KEY(i).find(VAR_INDEX_VALUE) == 0) { string temp = MAP_KEY(i).substr(VAR_INDEX_VALUE_LEN, string::npos); char *error = NULL; double index = strtod(STR(temp), &error); if (error == STR(temp) + temp.size()) { lua_pushnumber(pLuaState, index); } else { lua_pushstring(pLuaState, STR(MAP_KEY(i))); } } else { lua_pushstring(pLuaState, STR(MAP_KEY(i))); } if (!PushVariant(pLuaState, MAP_VAL(i), true)) { FINEST("Unable to push primitive"); return false; } lua_settable(pLuaState, -3); } return true; break; } default: { FATAL("Unknown type %hhu", (VariantType) variant); return false; break; } } return true; }
bool BaseInFileStream::ResolveCompleteMetadata(Variant &metaData) { if ((bool)metaData[CONF_APPLICATION_EXTERNSEEKGENERATOR]) return false; //1. Create the document BaseMediaDocument *pDocument = NULL; if (false) { } #ifdef HAS_MEDIA_FLV else if (metaData[META_MEDIA_TYPE] == MEDIA_TYPE_FLV || metaData[META_MEDIA_TYPE] == MEDIA_TYPE_LIVE_OR_FLV) { pDocument = new FLVDocument(metaData); } #endif /* HAS_MEDIA_FLV */ #ifdef HAS_MEDIA_MP3 else if (metaData[META_MEDIA_TYPE] == MEDIA_TYPE_MP3) { pDocument = new MP3Document(metaData); } #endif /* HAS_MEDIA_MP3 */ #ifdef HAS_MEDIA_MP4 else if (metaData[META_MEDIA_TYPE] == MEDIA_TYPE_MP4 || metaData[META_MEDIA_TYPE] == MEDIA_TYPE_M4A || metaData[META_MEDIA_TYPE] == MEDIA_TYPE_M4V || metaData[META_MEDIA_TYPE] == MEDIA_TYPE_MOV || metaData[META_MEDIA_TYPE] == MEDIA_TYPE_F4V) { pDocument = new MP4Document(metaData); } #endif /* HAS_MEDIA_MP4 */ #ifdef HAS_MEDIA_NSV else if (metaData[META_MEDIA_TYPE] == MEDIA_TYPE_NSV) { pDocument = new NSVDocument(metaData); } #endif /* HAS_MEDIA_NSV */ else { FATAL("File type not supported yet. Partial metadata:\n%s", STR(metaData.ToString())); return false; } //2. Process the document FINEST("Processing file %s", STR(metaData[META_SERVER_FULL_PATH])); if (!pDocument->Process()) { FATAL("Unable to process document"); delete pDocument; if ((bool)metaData[CONF_APPLICATION_RENAMEBADFILES]) { moveFile(metaData[META_SERVER_FULL_PATH], (string) metaData[META_SERVER_FULL_PATH] + ".bad"); } else { WARN("File %s will not be renamed", STR(metaData[META_SERVER_FULL_PATH])); } return false; } //3. Get the medatada metaData = pDocument->GetMetadata(); //4. cleanup delete pDocument; //5. Done return true; }
bool BaseInFileStream::Feed() { //1. Are we in paused state? if (_paused) return true; //2. First, send audio and video codecs if (!_audioVideoCodecsSent) { if (!SendCodecs()) { FATAL("Unable to send audio codec"); return false; } } //2. Determine if the client has enough data on the buffer and continue //or stay put uint32_t elapsedTime = (uint32_t) (time(NULL) - _startFeedingTime); if ((int32_t) _totalSentTime - (int32_t) elapsedTime >= _clientSideBufferLength) { return true; } //3. Test to see if we have sent the last frame if (_currentFrameIndex >= _totalFrames) { FINEST("Done streaming file"); _pOutStreams->info->SignalStreamCompleted(); _paused = true; return true; } //FINEST("_totalSentTime: %.2f; _playLimit: %.2f", (double) _totalSentTime, _playLimit); if (_playLimit >= 0) { if (_playLimit < (double) _totalSentTime) { FINEST("Done streaming file"); _pOutStreams->info->SignalStreamCompleted(); _paused = true; return true; } } //4. Read the current frame from the seeking file if (!_pSeekFile->SeekTo(_framesBaseOffset + _currentFrameIndex * sizeof (MediaFrame))) { FATAL("Unablt to seek inside seek file"); return false; } if (!_pSeekFile->ReadBuffer((uint8_t *) & _currentFrame, sizeof (_currentFrame))) { FATAL("Unable to read frame from seeking file"); return false; } //5. Take care of metadata if (_currentFrame.type == MEDIAFRAME_TYPE_DATA) { _currentFrameIndex++; if (!FeedMetaData(_pFile, _currentFrame)) { FATAL("Unable to feed metadata"); return false; } return Feed(); } //6. get our hands on the correct buffer, depending on the frame type: audio or video IOBuffer &buffer = _currentFrame.type == MEDIAFRAME_TYPE_AUDIO ? _audioBuffer : _videoBuffer; //7. Build the frame if (!BuildFrame(_pFile, _currentFrame, buffer)) { FATAL("Unable to build the frame"); return false; } //8. Compute the timestamp _totalSentTime = (uint32_t) (_currentFrame.absoluteTime / 1000) - _totalSentTimeBase; //9. Do the feedeng if (!_pOutStreams->info->FeedData( GETIBPOINTER(buffer), //pData GETAVAILABLEBYTESCOUNT(buffer), //dataLength 0, //processedLength GETAVAILABLEBYTESCOUNT(buffer), //totalLength (uint32_t) _currentFrame.absoluteTime, //absoluteTimestamp _currentFrame.type == MEDIAFRAME_TYPE_AUDIO //isAudio )) { FATAL("Unable to feed audio data"); return false; } //10. Discard the data buffer.IgnoreAll(); //11. Increment the frame index _currentFrameIndex++; //12. Done. We either feed again if frame length was 0 //or just return true if (_currentFrame.length == 0) { return Feed(); } else { return true; } }
bool PushVariant(lua_State *pLuaState, Variant &variant, bool substituteNullables) { switch ((VariantType) variant) { case V_UNDEFINED: case V_NULL: { if (substituteNullables) lua_pushstring(pLuaState, VAR_NULL_VALUE); else lua_pushnil(pLuaState); return true; break; } case V_STRING: { lua_pushstring(pLuaState, STR(variant)); return true; break; } case V_INT8: case V_INT16: case V_INT32: case V_INT64: case V_UINT8: case V_UINT16: case V_UINT32: case V_UINT64: case V_DOUBLE: { lua_pushnumber(pLuaState, (double) variant); return true; break; } case V_BOOL: { lua_pushboolean(pLuaState, (bool)variant); return true; break; } case V_TIMESTAMP: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_TIMESTAMP); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, tempTm.tm_year + 1900); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, tempTm.tm_mon + 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, tempTm.tm_mday); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_HOUR); lua_pushnumber(pLuaState, tempTm.tm_hour + 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MIN); lua_pushnumber(pLuaState, tempTm.tm_min); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_SEC); lua_pushnumber(pLuaState, tempTm.tm_sec); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_ISDST); lua_pushboolean(pLuaState, false); lua_settable(pLuaState, -3); return true; break; } case V_DATE: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_DATE); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, tempTm.tm_year + 1900); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, tempTm.tm_mon + 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, tempTm.tm_mday); lua_settable(pLuaState, -3); return true; break; } case V_TIME: { struct tm tempTm = (struct tm) variant; lua_createtable(pLuaState, 0, 0); lua_pushstring(pLuaState, VAR_TYPE); lua_pushstring(pLuaState, VAR_TIME); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_YEAR); lua_pushnumber(pLuaState, 1970); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MONTH); lua_pushnumber(pLuaState, 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_DAY); lua_pushnumber(pLuaState, 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_HOUR); lua_pushnumber(pLuaState, tempTm.tm_hour + 1); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_MIN); lua_pushnumber(pLuaState, tempTm.tm_min); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_SEC); lua_pushnumber(pLuaState, tempTm.tm_sec); lua_settable(pLuaState, -3); lua_pushstring(pLuaState, VAR_ISDST); lua_pushboolean(pLuaState, false); lua_settable(pLuaState, -3); return true; break; } case V_TYPED_MAP: case V_MAP: { lua_createtable(pLuaState, 0, 0); if ((VariantType) variant == V_TYPED_MAP) { lua_pushstring(pLuaState, VAR_MAP_NAME); lua_pushstring(pLuaState, STR(variant.GetTypeName())); lua_settable(pLuaState, -3); } FOR_MAP(variant, string, Variant, i) { const char *pKey = MAP_KEY(i).c_str(); if ((MAP_KEY(i).length() == 10) && (pKey[0] == '0') && (pKey[1] == 'x')) { uint32_t index = (uint32_t) strtol(pKey, NULL, 16); lua_pushnumber(pLuaState, index); } else { lua_pushstring(pLuaState, pKey); } if (!PushVariant(pLuaState, MAP_VAL(i), true)) { FINEST("Unable to push primitive"); return false; } lua_settable(pLuaState, -3); } return true; break; } default: { FATAL("Unknown type %d", (VariantType) variant); return false; break; } } }