IController::ApplicatorList Controller::removeStreamApplicators(const String& streamName) { auto context = getStreamContext(streamName); auto applicators = context->applicators; context->applicators = ApplicatorList(); return applicators; }
void Controller::setStreamApplicators(const String& streamName, const ApplicatorList& applicators) { auto context = getStreamContext(streamName); context->applicators = applicators; }
RtmpMsgHeaderPtr RtmpParser::parseMsgHeaderOnly() { RtmpMsgHeaderPtr mh(new RtmpMsgHeader()); //Utility::dumpData(rb_->getUnReadBufferNoCopy(), // rb_->getUnReadSize(), "/tmp/xg"); uint8_t firstByte = rb_->readByte(); mh->chunkType = firstByte >> 6; mh->chunkStreamId = firstByte & ((1 << 6) - 1); if(mh->chunkType != 0 && mh->chunkType != 1 && mh->chunkType != 2 && mh->chunkType != 3) { throw RtmpBadProtocalData("chunkType should be 0, 1, 2 or 3"); } if(mh->chunkStreamId == 0) { mh->chunkStreamId = rb_->readByte() + 64; } else if(mh->chunkStreamId == 1) { // third * 256 + second + 64 mh->chunkStreamId = rb_->read<uint16_t>(ReadBuffer::LITTLE) + 64; } StreamContext* sc = NULL; switch(mh->chunkType) { case 0: mh->timestamp = rb_->read<uint32_t>(ReadBuffer::BIG, 3); mh->length = rb_->read<uint32_t>(ReadBuffer::BIG, 3); mh->typeId = rb_->readByte(); mh->streamId = rb_->read<uint32_t>(ReadBuffer::LITTLE); break; case 1: mh->timestamp = rb_->read<uint32_t>(ReadBuffer::BIG, 3); mh->length = rb_->read<uint32_t>(ReadBuffer::BIG, 3); mh->typeId = rb_->readByte(); break; case 2: mh->timestamp = rb_->read<uint32_t>(ReadBuffer::BIG, 3); break; case 3: sc = getStreamContext(mh->chunkStreamId); if(sc != NULL) { if(sc->prevMsg->extendtedTimestamp != -1 && sc->prevMsg->extendtedTimestamp == rb_->peek<uint32_t>(ReadBuffer::BIG)) { // RTMP spec says: (Extended Timestamp, Type 3 chunks MUST NOT have this field) // BUT FMLE sends this!! // mh->timestamp = 0x00ffffff; } } // no header break; default: throw RtmpBadProtocalData("chunk type should be 0, 1, 2, or 3"); } if(mh->timestamp == 0x00ffffff) { mh->extendtedTimestamp = rb_->read<uint32_t>(ReadBuffer::BIG); mh->timestamp = (uint64_t)0x00ffffff + mh->extendtedTimestamp; } return mh; }
void Controller::addStreamApplicator(const String& streamName, IApplicator* applicator) { auto context = getStreamContext(streamName); context->applicators.push_back(applicator); }
void RtmpParser::onMsgHeaderParsed(RtmpMsgHeaderPtr& mh) { if(mh->typeId == MST_Audio || mh->typeId == MST_Video || mh->chunkType == 2 || mh->chunkType == 3 || mh->typeId == MST_DataAMF0) { StreamContext* sc = getStreamContext(mh->chunkStreamId); if(sc == NULL) { pair<int, StreamContext*> p(mh->chunkStreamId, new StreamContext()); sc = p.second; sc->prevMsg = mh; streamContexts_.push_back(p); } // Determin timedelta // 3 after 0, then timedelta should be type 0's timestamp if(sc->prevMsg->chunkType == 0 && mh->chunkType == 3) { sc->timestampDelta = sc->prevMsg->timestamp; } else if(mh->chunkType == 1 || mh->chunkType == 2) { sc->timestampDelta = mh->timestamp; } else { //throw RtmpBadProtocalData("can't determin timedelta"); } // 2. determin timestamp // if not type 0, then determin other parameter if(mh->chunkType == 0) { sc->timestamp = mh->timestamp; } else { sc->timestamp += sc->timestampDelta; mh->timestamp = sc->timestamp; mh->streamId = sc->prevMsg->streamId; if(mh->extendtedTimestamp == -1 && mh->chunkType == 3) { mh->extendtedTimestamp = sc->prevMsg->extendtedTimestamp; } // type 1 has message length and typeId if(mh->chunkType != 1) { mh->length = sc->prevMsg->length; mh->typeId = sc->prevMsg->typeId; } } sc->prevMsg = mh; } mh->unParsedSize = mh->length; }