Exemple #1
0
  int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int* gotFrame) {

    if (videoUnpackager == 0) {
      ELOG_DEBUG("Unpackager not correctly initialized");
      return -1;
    }

    int inBuffOffset = 0;
    *gotFrame = 0;
    RtpHeader* head = reinterpret_cast<RtpHeader*>(inBuff);
    if (head->getPayloadType() != 100) {
      return -1;
    }

    int l = inBuffLen - head->getHeaderLength();
    inBuffOffset+=head->getHeaderLength();

    erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) &inBuff[inBuffOffset], l);
    memcpy(outBuff, parsed->data, parsed->dataLength);
    if (head->getMarker()) {
      *gotFrame = 1;
    }
    int ret = parsed->dataLength;
    delete parsed;
    return ret;
  }
Exemple #2
0
int main(int argc, const char * argv[]) {

    // data setup
    uint32_t first = 0xFFFF | 0x1FFFFFFF;
    uint32_t timestamp = 0x0128;
    uint32_t ssrc = 0x01 | 0x02 | 0x04 | 0x08 | 0x256;

    
    int somedata[4];
    //    The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.
    // on the other side:
    //    The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.
    somedata[0] = htonl(first);
    somedata[1] = htonl(timestamp);
    somedata[2] = htonl(ssrc);
    somedata[2] = htonl(ssrc);
    somedata[3] = htonl(ssrc);
    
    RtpHeader* head = reinterpret_cast<RtpHeader*>(somedata);
    
    printf("version: %" PRIu8 "\n", head->getVersion());
    printf("padding: %" PRIu8 "\n", head->hasPadding());
    printf("extension: %" PRIu8 "\n", head->getExtension());
    printf("marker: %" PRIu8 "\n", head->getMarker());
    printf("payload type: %" PRIu8 "\n", head->getPayloadType());
    printf("sequence number: %" PRIu16 "\n", head->getSeqNumber());
    printf("timestamp %" PRIu32 "\n", head->getTimestamp());
    printf("ssrc %" PRIu32 "\n", head->getSSRC());
    printf("header length: %u\n", head->getHeaderLength());
    
    return 0;
}
Exemple #3
0
void ExternalOutput::writeVideoData(char* buf, int len){
    RtpHeader* head = reinterpret_cast<RtpHeader*>(buf);

    uint16_t currentVideoSeqNumber = head->getSeqNumber();
    if (currentVideoSeqNumber != lastVideoSequenceNumber_ + 1) {
        // Something screwy.  We should always see sequence numbers incrementing monotonically.
        ELOG_DEBUG("Unexpected video sequence number; current %d, previous %d", currentVideoSeqNumber, lastVideoSequenceNumber_);
        // Set our search state to look for the start of a frame, and discard what we currently have (if anything).  it's now worthless.
        vp8SearchState_ = lookingForStart;
        unpackagedSize_ = 0;
        unpackagedBufferpart_ = unpackagedBuffer_;
    }

    lastVideoSequenceNumber_ = currentVideoSeqNumber;

    if (firstVideoTimestamp_ == -1) {
        firstVideoTimestamp_ = head->getTimestamp();
    }

    // TODO we should be tearing off RTP padding here, if it exists.  But WebRTC currently does not use padding.

    RtpVP8Parser parser;
    erizo::RTPPayloadVP8* payload = parser.parseVP8(reinterpret_cast<unsigned char*>(buf + head->getHeaderLength()), len - head->getHeaderLength());

    bool endOfFrame = (head->getMarker() > 0);
    bool startOfFrame = payload->beginningOfPartition;

    bool deliver = false;
    switch(vp8SearchState_) {
    case lookingForStart:
        if(startOfFrame && endOfFrame) {
            // This packet is a standalone frame.  Send it on.  Look for start.
            unpackagedSize_ = 0;
            unpackagedBufferpart_ = unpackagedBuffer_;
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
            deliver = true;
        } else if (!startOfFrame && !endOfFrame) {
            // This is neither the start nor the end of a frame.  Reset our buffers.  Look for start.
            unpackagedSize_ = 0;
            unpackagedBufferpart_ = unpackagedBuffer_;
        } else if (startOfFrame && !endOfFrame) {
            // Found start frame.  Copy to buffers.  Look for our end.
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
            vp8SearchState_ = lookingForEnd;
        } else { // (!startOfFrame && endOfFrame)
            // We got the end of a frame.  Reset our buffers.
            unpackagedSize_ = 0;
            unpackagedBufferpart_ = unpackagedBuffer_;
        }
        break;
    case lookingForEnd:
        if(startOfFrame && endOfFrame) {
            // Unexpected.  We were looking for the end of a frame, and got a whole new frame.
            // Reset our buffers, send this frame on, and go to the looking for start state.
            vp8SearchState_ = lookingForStart;
            unpackagedSize_ = 0;
            unpackagedBufferpart_ = unpackagedBuffer_;
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
            deliver = true;
        } else if (!startOfFrame && !endOfFrame) {
            // This is neither the start nor the end.  Add it to our unpackage buffer.
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
        } else if (startOfFrame && !endOfFrame) {
            // Unexpected.  We got the start of a frame.  Clear out our buffer, toss this payload in, and continue looking for the end.
            unpackagedSize_ = 0;
            unpackagedBufferpart_ = unpackagedBuffer_;
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
        } else { // (!startOfFrame && endOfFrame)
            // Got the end of a frame.  Let's deliver and start looking for the start of a frame.
            vp8SearchState_ = lookingForStart;
            memcpy(unpackagedBufferpart_, payload->data, payload->dataLength);
            unpackagedSize_ += payload->dataLength;
            unpackagedBufferpart_ += payload->dataLength;
            deliver = true;
        }
        break;
    }

    delete payload;

    //ELOG_DEBUG("Parsed VP8 payload, endOfFrame: %d, startOfFrame: %d, partitionId: %d", endOfFrame, startOfFrame, partitionId);

    this->initContext();
    if (video_stream_ == NULL) {
        // could not init our context yet.
        return;
    }

    if (deliver) {
        unpackagedBufferpart_ -= unpackagedSize_;

        long long currentTimestamp = head->getTimestamp();
        if (currentTimestamp - firstVideoTimestamp_ < 0) {
            // we wrapped.  add 2^32 to correct this.  We only handle a single wrap around since that's ~13 hours of recording, minimum.
            currentTimestamp += 0xFFFFFFFF;
        }

        long long timestampToWrite = (currentTimestamp - firstVideoTimestamp_) / (90000 / video_stream_->time_base.den);  // All of our video offerings are using a 90khz clock.

        // Adjust for our start time offset
        timestampToWrite += videoOffsetMsec_ / (1000 / video_stream_->time_base.den);   // in practice, our timebase den is 1000, so this operation is a no-op.

        /* ELOG_DEBUG("Writing video frame %d with timestamp %u, normalized timestamp %u, video offset msec %u, length %d, input timebase: %d/%d, target timebase: %d/%d", */
        /*            head->getSeqNumber(), head->getTimestamp(), timestampToWrite, videoOffsetMsec_, unpackagedSize_, */
        /*            video_stream_->codec->time_base.num, video_stream_->codec->time_base.den,    // timebase we requested */
        /*            video_stream_->time_base.num, video_stream_->time_base.den);                 // actual timebase */

        AVPacket avpkt;
        av_init_packet(&avpkt);
        avpkt.data = unpackagedBufferpart_;
        avpkt.size = unpackagedSize_;
        avpkt.pts = timestampToWrite;
        avpkt.stream_index = 0;
        av_write_frame(context_, &avpkt);
        av_free_packet(&avpkt);
        unpackagedSize_ = 0;
        unpackagedBufferpart_ = unpackagedBuffer_;
    }
}