// Called periodically on every UI update JNIEXPORT void Java_com_superpowered_hlsexample_MainActivity_UpdateStatus(JNIEnv *javaEnvironment, jobject self) { jclass thisClass = javaEnvironment->GetObjectClass(self); //setFloatField(javaEnvironment, self, thisClass, "bufferStartPercent", player->bufferStartPercent); setFloatField(javaEnvironment, self, thisClass, "bufferEndPercent", player->bufferEndPercent); setLongField(javaEnvironment, self, thisClass, "durationSeconds", player->durationSeconds); setLongField(javaEnvironment, self, thisClass, "positionSeconds", player->positionSeconds); setFloatField(javaEnvironment, self, thisClass, "positionPercent", player->positionPercent); setBoolField(javaEnvironment, self, thisClass, "playing", player->playing); }
void MyFmsAuthorizeEvent::authorize() { bool bAuthorized = true; // default authorization state switch(m_pAev->getType()) { case IFmsAuthEvent::E_APPSTART: { // only E_APPSTART allows changes to the following fields: // F_APP_PRTMP // F_APP_PRTMP_COMMON_KEY_FILE // F_APP_PRTMP_VIDEO_ENC_LEVEL // F_APP_PRTMP_UPDATE_INTERVAL // F_APP_PRTMP_SWF_VERIFICATION // F_APP_PRTMP_SWF_WHITELIST_FOLDER bool bSet; I8 sValue; if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP, sValue)) { bSet = setI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP, sValue); } char* pCommonKeyPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_COMMON_KEY_FILE); if (pCommonKeyPath) { bSet = setStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_COMMON_KEY_FILE, pCommonKeyPath); } U32 uValue; if (getU32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_VIDEO_ENC_LEVEL, uValue)) { bSet = setU32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_VIDEO_ENC_LEVEL, uValue); } I32 iValue; if (getI32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_UPDATE_INTERVAL, iValue)) { bSet = setI32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_UPDATE_INTERVAL, iValue); } if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_VERIFICATION, sValue)) { bSet = setI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_VERIFICATION, sValue); } char* pWhiteListPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_WHITELIST_FOLDER); if (pWhiteListPath) { bSet = setStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_WHITELIST_FOLDER, pWhiteListPath); } bAuthorized = true; } break; case IFmsAuthEvent::E_CONNECT: { // only E_CONNECT allows changes to the following fields: // F_CLIENT_AUDIO_SAMPLE_ACCESS // F_CLIENT_AUDIO_SAMPLE_ACCESS_LOCK // F_CLIENT_READ_ACCESS // F_CLIENT_READ_ACCESS_LOCK // F_CLIENT_VIDEO_SAMPLE_ACCESS // F_CLIENT_VIDEO_SAMPLE_ACCESS_LOCK // F_CLIENT_WRITE_ACCESS_LOCK // F_CLIENT_WRITE_ACCESS I8 iValue; if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS, iValue)) { setI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS, iValue); } // redirect connection example char* pUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI); if (pUri && !strcmp(pUri, "rtmp://localhost/streamtest")) { setStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REDIRECT_URI, "rtmp://localhost:1935/streamtest"); bAuthorized = false; } // set DiffServ fields based on a client IP // char* pIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP); // if (pIp && !strcmp(pIp, "192.168.1.1")) { // set the DSCP bits and mask U8 m_diffServBits = 170; U8 m_diffServMask = 252; setU8Field(m_pAev, IFmsAuthEvent::F_CLIENT_DIFFSERV_BITS, m_diffServBits); setU8Field(m_pAev, IFmsAuthEvent::F_CLIENT_DIFFSERV_MASK, m_diffServMask); bAuthorized = true; } } break; case IFmsAuthEvent::E_PLAY: { char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); if (pStreamName) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName); } char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE); if (pStreamType) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType); } char* pStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY); if (pStreamQuery) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY, pStreamQuery); } m_pFmsAuthServerContext->log(pStreamName, IFmsServerContext::kInformation, false); m_pFmsAuthServerContext->log(pStreamType, IFmsServerContext::kInformation, false); m_pFmsAuthServerContext->log(pStreamQuery, IFmsServerContext::kInformation, false); I8 iValue; if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_RESET, iValue)) { // If iValue is 1 (true) the playlist will be reset and the // stream will be the only stream in the playlist; otherwise // 0 (false) means the stream will be added to the existing // playlist. setI8Field(m_pAev, IFmsAuthEvent::F_STREAM_RESET, iValue); } if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_IGNORE, iValue)) { // If iValue is 1 (true) the stream timestamps will be ignored; // otherwise 0 (false) means the timestamps will be handled. setI8Field(m_pAev, IFmsAuthEvent::F_STREAM_IGNORE, iValue); } char* pStreamTransition = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TRANSITION); if (pStreamTransition && strlen(pStreamTransition)) { // MBR transition example if (!strcmp(pStreamTransition, "switch") || !strcmp(pStreamTransition, "swap")) { // get the old stream's properties char* pOldStreamName = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_NAME); char* pOldStreamType = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_TYPE); char* pOldStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_QUERY); // if pOldStream is empty (optional for switch) current stream is in play // do we really want stream transition? { // no we do not allow transition // bAuthorized = false; // now transition will be turned off and old stream continue playing // break; } // doing nothing will execute transition mode as is // or you could modify transition by changing transition properties // set it to 1 to indicate they will be hooking up the stream, // but that it does not currently exist setI32Field(m_pAev, IFmsAuthEvent::F_STREAM_LIVE_PUBLISH_PENDING, 1); } // get the offset value if transition is set to offset mode for reconnect if (!strcmp(pStreamTransition, "resume")) { float fValue; if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_OFFSET, fValue)) { float offset = fValue; //offset value in seconds } } } else { // This is a regular play waiting for approval, which may be converted // into a play2 command by changing transition properties } } break; case IFmsAuthEvent::E_PUBLISH: { char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); if (pStreamName) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName); } char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE); if (pStreamType) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType); } I32 iValue; if (getI32Field(m_pAev, IFmsAuthEvent::F_STREAM_PUBLISH_TYPE, iValue)) { // publish types: // 0 : record // 1 : append // 2 : appendWithGap // -1 : live setI32Field(m_pAev, IFmsAuthEvent::F_STREAM_PUBLISH_TYPE, iValue); } } break; case IFmsAuthEvent::E_FILENAME_TRANSFORM: { I64 iValue; if (getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_ID, iValue)) { // some fields are not eligible to be modified. The return // value will be false when trying to modify the F_CLIENT_ID. bool bSet = setI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_ID, iValue); } char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); if (pStreamName) { // some fields are not eligible to be modified. The return // value will be false when trying to modify the F_STREAM_NAME. bool bSet = setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName); } char* pStreamPath = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH); if (pStreamPath) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH, pStreamPath); } char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE); if (pStreamType) { setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType); } } break; case IFmsAuthEvent::E_PAUSE: { bAuthorized = false; // block all E_PAUSE events. float fValue; if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE_TIME, fValue)) { float fPauseTime = fValue; // in seconds } I8 iValue; if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE, iValue)) { // 1 (true) means PAUSE // 0 (false) means UNPAUSE bool boolPause = iValue != 0; } if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE_TOGGLE, iValue)) { // 1 (true) means PAUSE_TOGGLE // 0 (false) means no PAUSE_TOGGLE was set bool boolPauseToggle = iValue != 0; } FmsVariant field; // Notify Action example: An IFmsNofifyAction is created to notify // server side action script (SSAS) of the E_PAUSE event by calling // the function name "method" in the script. In this example two // variables will be passed to "method" by calling addParam(field) // on the action. if (m_pAev->getField(IFmsAuthEvent::F_CLIENT_ID, field) == IFmsAuthEvent::S_SUCCESS) { I64 clientId = field.i64; IFmsNotifyAction* pAction = m_pAev->addNotifyAction("Notified by adaptor"); pAction->setClientId(field); const char mtd[] = "method"; field.setString(reinterpret_cast<I8*>(const_cast<char*>(mtd))); pAction->setMethodName(field); // create and insert a U16 "12345" as the first parameter field.setU16(12345); pAction->addParam(field); // create and insert clientId as a double as the second parameter field.setDouble((double)clientId); pAction->addParam(field); // Note: SSAS does not work with I64 or Buffer variants // field.setI64(clientId); // pAction->addParam(field); // incorrect } } break; case IFmsAuthEvent::E_SEEK: { bAuthorized = false; // block all E_SEEK events float fValue; if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_SEEK_POSITION, fValue)) { // Modification of the seek position example: // fValue + 3; will add 3 seconds to the initial seek posistion float fSeekTime = fValue; // value in seconds setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_SEEK_POSITION, fSeekTime); } } break; case IFmsAuthEvent::E_LOADSEGMENT: { // bAuthorized = false; // block all E_LOADSEGMENT events // E_LOADSEGMENT is a read only event that substitutes E_PLAY on // FMS Origin servers for recorded streams. I64 iValue; if (getI64Field(m_pAev, IFmsAuthEvent::F_SEGMENT_START, iValue)) { I64 iStart = iValue; // in bytes } if (getI64Field(m_pAev, IFmsAuthEvent::F_SEGMENT_END, iValue)) { I64 iEnd = iValue; // in bytes } } break; case IFmsAuthEvent::E_RECORD: { // bAuthorized = false; // block all E_RECORD events float fValue; if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXSIZE, fValue)) { float recMaxSize = fValue; // in kilobytes setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXSIZE, recMaxSize); } if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXDURATION, fValue)) { float recMaxDuration = fValue; // in seconds setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXDURATION, recMaxDuration); } } break; case IFmsAuthEvent::E_SWF_VERIFY: { // SWF Verification example: // kAuthorizeSwfVerification is assigned false by default. The // target SWF file must be updated for this to work. if(kAuthorizeSwfVerification) { I8 swfvVersion = 0; if(getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_VERSION, swfvVersion)) { std::stringstream stream; stream << "Swf verification version is " << static_cast<int>(swfvVersion); m_pFmsAuthServerContext->log(stream.str().c_str(), IFmsServerContext::kInformation, false); } I64 swfvDepth; if(getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_DEPTH, swfvDepth)) { I32 swfvTTL; if(getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_TTL, swfvTTL)) { swfvTTL /= 2; setI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_TTL, swfvTTL); } U8 digest[kSHA256DigestLen]; // Target a real SWF file instead of sample.swf hashSwfFileAtDepth("C:\\sample.swf", swfvDepth, digest); FmsVariant field; field.setBuffer(digest, kSHA256DigestLen); m_pAev->setField(IFmsAuthEvent::F_CLIENT_SWFV_DIGEST, field); } } } break; case IFmsAuthEvent::E_APPSTOP: case IFmsAuthEvent::E_DISCONNECT: case IFmsAuthEvent::E_STOP: case IFmsAuthEvent::E_UNPUBLISH: case IFmsAuthEvent::E_ACTION: case IFmsAuthEvent::E_CODEC_CHANGE: case IFmsAuthEvent::E_RECORD_STOP: case IFmsAuthEvent::E_CLIENT_PAUSE: case IFmsAuthEvent::E_SWF_VERIFY_COMPLETE: case IFmsAuthEvent::E_CLIENT_SEEK: case IFmsAuthEvent::E_START_TRANSMIT: case IFmsAuthEvent::E_STOP_TRANSMIT: case IFmsAuthEvent::E_MAXEVENT: break; } IFmsAuthServerContext2::AuthFailureDesc* desc = NULL; if(!bAuthorized) { desc = new IFmsAuthServerContext2::AuthFailureDesc("Blocked by auth adaptor", IFmsAuthServerContext2::kDefaultStatus, -1); } char buf[1024]; const char* const action = bAuthorized ? "approved" : "rejected"; sprintf(buf, "Received dddd authorization type=%d id=%p %s\n", m_pAev->getType(), m_pAev, action); char tlog[1024]; sprintf(tlog,"bb\n"); m_pFmsAuthServerContext->log(tlog, IFmsServerContext::kInformation, false) // log to the configured FMS log directory. If the third parameter is true, // also send the log to the system event log. m_pFmsAuthServerContext->log(buf, IFmsServerContext::kInformation, false); m_pFmsAuthServerContext->onAuthorize(m_pAev, bAuthorized, desc); delete desc; }