Exemplo n.º 1
0
int do_proxy(srs_flv_t flv, srs_rtmp_t ortmp, int64_t re, int32_t *pstarttime, u_int32_t *ptimestamp) {
    int ret = 0;

    // packet data
    char type;
    int size;
    char *data = NULL;

    srs_human_trace("start ingest flv to RTMP stream");
    for (; ;) {
        // tag header
        if ((ret = srs_flv_read_tag_header(flv, &type, &size, ptimestamp)) != 0) {
            if (srs_flv_is_eof(ret)) {
                srs_human_trace("parse completed.");
                return 0;
            }
            srs_human_trace("flv get packet failed. ret=%d", ret);
            return ret;
        }

        if (size <= 0) {
            srs_human_trace("invalid size=%d", size);
            break;
        }

        // TODO: FIXME: mem leak when error.
        data = (char *) malloc(size);
        if ((ret = srs_flv_read_tag_data(flv, data, size)) != 0) {
            return ret;
        }

        u_int32_t timestamp = *ptimestamp;

        if ((ret = srs_human_print_rtmp_packet(type, timestamp, data, size)) != 0) {
            srs_human_trace("print packet failed. ret=%d", ret);
            return ret;
        }

        if ((ret = srs_rtmp_write_packet(ortmp, type, *ptimestamp, data, size)) != 0) {
            srs_human_trace("irtmp get packet failed. ret=%d", ret);
            return ret;
        }

        if (*pstarttime < 0) {
            *pstarttime = *ptimestamp;
        }

        re_update(re, *pstarttime, *ptimestamp);
    }

    return ret;
}
Exemplo n.º 2
0
void PushEngine::run(){
    while(1){
        int64_t currentTime = srs_utils_time_ms();
        
        if(currentTime - m_timeTick > 1000){
            m_timeTick = currentTime;
#if 0
            for(std::list<OneStream*>::iterator it = m_streamList.begin(); it != m_streamList.end(); it++){
                m_logger.information("==> current publish [rtmp://%s/live/%s%d] size[%d]", (*it)->ipPort, \
                            (*it)->prefixName, (*it)->randNum, (*it)->receiveSize/1000);
                (*it)->receiveSize = 0;
            }
#endif
        }
        
        if(m_jobQueue.size() > 0){
            OneStreamSharePtr node = m_jobQueue.get();
            if(node.get() != NULL){
                node->setExpiredTime(currentTime);
                node->m_sendIndex = 0;
                m_streamList.push_back(node);
            }
            
            std::string url = node->getURL();
            node->rtmp = srs_rtmp_create(url.c_str());
            m_logger.information("begin publish to [%s].", url);

            if (srs_rtmp_handshake(node->rtmp) != 0) {
                srs_rtmp_destroy(node->rtmp);       // 析构rtmp
                m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent(node, currentTime, HANDSHAKE_FAIL)));    // 发送握手失败事件
                m_logger.error("simple handshake to [%s] failed.", url);
            }
                
            if (srs_rtmp_connect_app(node->rtmp) != 0) {
                srs_rtmp_destroy(node->rtmp);       // 析构rtmp
                m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent(node, currentTime, CONNECT_FAIL)));      // 发送连接失败事件
                m_logger.error("connect [%s] vhost/app failed.", url);
                continue;
            }

            if (srs_rtmp_publish_stream(node->rtmp) != 0) {
                srs_rtmp_destroy(node->rtmp);       // 析构rtmp
                m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent(node, currentTime, PUBLIC_FAIL)));       // 发送public失败事件
                m_logger.error("publish stream [%s] failed.", url);
                continue;
            }

            m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent(node, currentTime, START_STREAM)));          // 发送开始推流事件
        }
        
        //  发送当前时间片的帧到所有链接
        for(std::list<OneStreamSharePtr>::iterator it = m_streamList.begin(); it != m_streamList.end(); ){
            bool endThisStream = false;
            if((*it)->m_sendIndex == 0 || (*it)->m_sendIndex + 1 > m_flvFrame.size()){
                (*it)->m_baseTimestamp = currentTime;
                (*it)->m_sendIndex = 0;
            }
            
            if(((*it)->m_baseTimestamp + m_flvFrame[(*it)->m_sendIndex].timestamp) <= currentTime){
                Frame f = m_flvFrame[((*it)->m_sendIndex)++];
                char* data = (char*)malloc(f.size);
                memcpy(data, f.data, f.size);
                if (srs_rtmp_write_packet((*it)->rtmp, f.type, ((*it)->m_baseTimestamp + f.timestamp) % 10000000, data, f.size) != 0) {
                    endThisStream = true;
                    m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent((*it), currentTime, PUSH_STREAM_FAIL)));       // 发送推流失败事件
                    m_logger.error("error to publish [%s].", (*it)->getURL());                    
                }
                (*it)->addReceiveSize(f.size);
            }
            
            // 推流时间到
            if(currentTime > (*it)->getExpiredTime()){
                endThisStream = true;
                m_streamEventQueue.put(StreamEventSharePtr(new StreamEvent((*it), currentTime, END_STREAM)));            // 发送推流结束事件
                m_logger.information("stop to publish [%s].", (*it)->getURL());
            }
            
            if(endThisStream){
                srs_rtmp_destroy((*it)->rtmp);      // 析构rtmp
                it = m_streamList.erase(it);        // 从链表中删除
                continue;
            }
            else{
                it++;
            }
        }

        usleep(10 * 1000);
    }
}
Exemplo n.º 3
0
int main(int argc, char **argv) {
    printf("publish rtmp stream to server like FMLE/FFMPEG/Encoder\n");
    printf("srs(simple-rtmp-server) client librtmp library.\n");
    printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());

    if (argc <= 1) {
        printf("Usage: %s <rtmp_url>\n"
                       "   rtmp_url     RTMP stream url to publish\n"
                       "For example:\n"
                       "   %s rtmp://127.0.0.1:1935/live/livestream\n",
               argv[0], argv[0]);
        exit(-1);
    }

    // warn it .
    // @see: https://github.com/winlinvip/simple-rtmp-server/issues/126
    srs_human_trace("\033[33m%s\033[0m",
                    "[warning] it's only a sample to use librtmp. "
                            "please never use it to publish and test forward/transcode/edge/HLS whatever. "
                            "you should refer to this tool to use the srs-librtmp to publish the real media stream."
                            "read about: https://github.com/winlinvip/simple-rtmp-server/issues/126");
    srs_human_trace("rtmp url: %s", argv[1]);
    srs_rtmp_t rtmp = srs_rtmp_create(argv[1]);

    if (srs_rtmp_handshake(rtmp) != 0) {
        srs_human_trace("simple handshake failed.");
        goto rtmp_destroy;
    }
    srs_human_trace("simple handshake success");

    if (srs_rtmp_connect_app(rtmp) != 0) {
        srs_human_trace("connect vhost/app failed.");
        goto rtmp_destroy;
    }
    srs_human_trace("connect vhost/app success");

    if (srs_rtmp_publish_stream(rtmp) != 0) {
        srs_human_trace("publish stream failed.");
        goto rtmp_destroy;
    }
    srs_human_trace("publish stream success");

    u_int32_t timestamp = 0;
    for (; ;) {
        char type = SRS_RTMP_TYPE_VIDEO;
        int size = 4096;
        char *data = (char *) malloc(4096);

        timestamp += 40;

        if (srs_rtmp_write_packet(rtmp, type, timestamp, data, size) != 0) {
            goto rtmp_destroy;
        }
        srs_human_trace("sent packet: type=%s, time=%d, size=%d",
                        srs_human_flv_tag_type2string(type), timestamp, size);

        usleep(40 * 1000);
    }

    rtmp_destroy:
    srs_rtmp_destroy(rtmp);

    return 0;
}