天天看點

OBS源碼分析之rtmp

rtmp推流過程如下:

1)啟動connect線程   

static void *connect_thread(void *data)

{

struct rtmp_stream *stream = data;//流資訊指派

int ret;

os_set_thread_name("rtmp-stream: connect_thread");

if (!init_connect(stream)) {//初始化流資訊

obs_output_signal_stop(stream->output, OBS_OUTPUT_BAD_PATH);

return NULL;

}

ret = try_connect(stream);//嘗試連接配接

if (ret != OBS_OUTPUT_SUCCESS) {

obs_output_signal_stop(stream->output, ret);//發送停止推流信号

info("Connection to %s failed: %d", stream->path.array, ret);

}

if (!stopping(stream))

pthread_detach(stream->connect_thread);

os_atomic_set_bool(&stream->connecting, false);

return NULL;

}

2)嘗試connect   

static int try_connect(struct rtmp_stream *stream)

{

if (dstr_is_empty(&stream->path)) {//推流位址不能為空

warn("URL is empty");

return OBS_OUTPUT_BAD_PATH;

}

info("Connecting to RTMP URL %s...", stream->path.array);

memset(&stream->rtmp.Link, 0, sizeof(stream->rtmp.Link));

if (!RTMP_SetupURL(&stream->rtmp, stream->path.array))

return OBS_OUTPUT_BAD_PATH;

RTMP_EnableWrite(&stream->rtmp);//寫權限

dstr_copy(&stream->encoder_name, "FMLE/3.0 (compatible; obs-studio/");

#ifdef HAVE_OBSCONFIG_H

dstr_cat(&stream->encoder_name, OBS_VERSION);

#else

dstr_catf(&stream->encoder_name, "%d.%d.%d",

LIBOBS_API_MAJOR_VER,

LIBOBS_API_MINOR_VER,

LIBOBS_API_PATCH_VER);

#endif

dstr_cat(&stream->encoder_name, "; FMSc/1.0)");

set_rtmp_dstr(&stream->rtmp.Link.pubUser,   &stream->username);

set_rtmp_dstr(&stream->rtmp.Link.pubPasswd, &stream->password);

set_rtmp_dstr(&stream->rtmp.Link.flashVer,  &stream->encoder_name);

stream->rtmp.Link.swfUrl = stream->rtmp.Link.tcUrl;

RTMP_AddStream(&stream->rtmp, stream->key.array);//key連接配接

for (size_t idx = 1;; idx++) {

obs_encoder_t *encoder = obs_output_get_audio_encoder(

stream->output, idx);

const char *encoder_name;

if (!encoder)

break;

encoder_name = obs_encoder_get_name(encoder);

RTMP_AddStream(&stream->rtmp, encoder_name);//編碼器

}

stream->rtmp.m_outChunkSize       = 4096;

stream->rtmp.m_bSendChunkSizeInfo = true;

stream->rtmp.m_bUseNagle          = true;

#ifdef _WIN32

win32_log_interface_type(stream);

#endif

if (!RTMP_Connect(&stream->rtmp, NULL))//推流伺服器連接配接

return OBS_OUTPUT_CONNECT_FAILED;

if (!RTMP_ConnectStream(&stream->rtmp, 0))//流連接配接

return OBS_OUTPUT_INVALID_STREAM;

info("Connection to %s successful", stream->path.array);

return init_send(stream);//推流線程

}

3) connect過程 

int

RTMP_Connect(RTMP *r, RTMPPacket *cp)

{

#ifdef _WIN32

    HOSTENT *h;

#endif

    struct sockaddr_storage service;

    socklen_t addrlen = 0;

    if (!r->Link.hostname.av_len)

        return FALSE;

#ifdef _WIN32

    //COMODO security software sandbox blocks all DNS by returning "host not found"

    h = gethostbyname("localhost");

    if (!h && GetLastError() == WSAHOST_NOT_FOUND)

    {

        RTMP_Log(RTMP_LOGERROR, "RTMP_Connect: Connection test failed. This error is likely caused by Comodo Internet Security running OBS in sandbox mode. Please add OBS to the Comodo automatic sandbox exclusion list, restart OBS and try again (11001).");

        return FALSE;

    }

#endif

    memset(&service, 0, sizeof(service));

    if (r->Link.socksport)

    {

        if (!add_addr_info(&service, &addrlen, &r->Link.sockshost, r->Link.socksport))

            return FALSE;

    }

    else

    {

        if (!add_addr_info(&service, &addrlen, &r->Link.hostname, r->Link.port))

            return FALSE;

    }

    if (!RTMP_Connect0(r, (struct sockaddr *)&service, addrlen))

        return FALSE;

    r->m_bSendCounter = TRUE;

    return RTMP_Connect1(r, cp);

}

RTMP_Connect0(RTMP *r, struct sockaddr * service, socklen_t addrlen)

RTMP_Connect1(RTMP *r, RTMPPacket *cp)

4)三次握手

static int

HandShake(RTMP *r, int FP9HandShake)

繼續閱讀