OBS-rtmp源码剖析之rtmp发送音频和视频数据(七)

这里主要讲解了音频、视频包的发送,包括函数init_send()、send_thread()
1、初始化发送

static int init_send(struct rtmp_stream *stream)
{
    int ret;
    size_t idx = 0;
    bool next = true;

#if defined(_WIN32)
    adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE);
#endif

    reset_semaphore(stream);

    ret = pthread_create(&stream->send_thread, NULL, send_thread, stream);
    if (ret != 0) {
        RTMP_Close(&stream->rtmp);
        warn("Failed to create send thread");
        return OBS_OUTPUT_ERROR;
    }

    if (stream->new_socket_loop) {
        int one = 1;
#ifdef _WIN32
        if (ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
            stream->rtmp.last_error_code = WSAGetLastError();
#else
        if (ioctl(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
            stream->rtmp.last_error_code = errno;
#endif
            warn("Failed to set non-blocking socket");
            return OBS_OUTPUT_ERROR;
        }

        os_event_reset(stream->send_thread_signaled_exit);

        info("New socket loop enabled by user");
        if (stream->low_latency_mode)
            info("Low latency mode enabled by user");

        if (stream->write_buf)
            bfree(stream->write_buf);

        int total_bitrate = 0;
        obs_output_t  *context  = stream->output;

        obs_encoder_t *vencoder = obs_output_get_video_encoder(context);
        if (vencoder) {
            obs_data_t *params = obs_encoder_get_settings(vencoder);
            if (params) {
                int bitrate = obs_data_get_int(params, "bitrate");
                if (!bitrate) {
                    warn ("Video encoder didn't return a "
                        "valid bitrate, new network "
                        "code may function poorly. "
                        "Low latency mode disabled.");
                    stream->low_latency_mode = false;
                    bitrate = 10000;
                }
                total_bitrate += bitrate;
                obs_data_release(params);
            }
        }

        obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, 0);
        if (aencoder) {
            obs_data_t *params = obs_encoder_get_settings(aencoder);
            if (params) {
                int bitrate = obs_data_get_int(params, "bitrate");
                if (!bitrate)
                    bitrate = 160;
                total_bitrate += bitrate;
                obs_data_release(params);
            }
        }

        // to bytes/sec
        int ideal_buffer_size = total_bitrate * 128;

        if (ideal_buffer_size < 131072)
            ideal_buffer_size = 131072;

        stream->write_buf_size = ideal_buffer_size;
        stream->write_buf = bmalloc(ideal_buffer_size);

#ifdef _WIN32
        ret = pthread_create(&stream->socket_thread, NULL,
                socket_thread_windows, stream);
#else
        warn("New socket loop not supported on this platform");
        return OBS_OUTPUT_ERROR;
#endif

        if (ret != 0) {
            RTMP_Close(&stream->rtmp);
            warn("Failed to create socket thread");
            return OBS_OUTPUT_ERROR;
        }

        stream->socket_thread_active = true;
        stream->rtmp.m_bCustomSend = true;
        stream->rtmp.m_customSendFunc = socket_queue_data;
        stream->rtmp.m_customSendParam = stream;
    }

    os_atomic_set_bool(&stream->active, true);
    while (next) {
        if (!send_meta_data(stream, idx++, &next)) {
            warn("Disconnected while attempting to connect to "
                 "server.");
            set_output_error(stream);
            return OBS_OUTPUT_DISCONNECTED;
        }
    }
    obs_output_begin_data_capture(stream->output, 0);

    return OBS_OUTPUT_SUCCESS;
}

2、发送线程

static void *send_thread(void *data)
{
    struct rtmp_stream *stream = data;

    os_set_thread_name("rtmp-stream: send_thread");

    while (os_sem_wait(stream->send_sem) == 0) {
        struct encoder_packet packet;

        if (stopping(stream) && stream->stop_ts == 0) {
            break;
        }

        if (!get_next_packet(stream, &packet))
            continue;

        if (stopping(stream)) {
            if (can_shutdown_stream(stream, &packet)) {
                obs_encoder_packet_release(&packet);
                break;
            }
        }

        if (!stream->sent_headers) {
            if (!send_headers(stream)) {
                os_atomic_set_bool(&stream->disconnected, true);
                break;
            }
        }

        if (send_packet(stream, &packet, false, packet.track_idx) < 0) {
            os_atomic_set_bool(&stream->disconnected, true);
            break;
        }
    }

    if (disconnected(stream)) {
        info("Disconnected from %s", stream->path.array);
    } else {
        info("User stopped the stream");
    }

    if (stream->new_socket_loop) {
        os_event_signal(stream->send_thread_signaled_exit);
        os_event_signal(stream->buffer_has_data_event);
        pthread_join(stream->socket_thread, NULL);
        stream->socket_thread_active = false;
        stream->rtmp.m_bCustomSend = false;
    }

    set_output_error(stream);
    RTMP_Close(&stream->rtmp);

    if (!stopping(stream)) {
        pthread_detach(stream->send_thread);
        obs_output_signal_stop(stream->output, OBS_OUTPUT_DISCONNECTED);
    } else {
        obs_output_end_data_capture(stream->output);
    }

    free_packets(stream);
    os_event_reset(stream->stop_event);
    os_atomic_set_bool(&stream->active, false);
    stream->sent_headers = false;
    return NULL;
}

猜你喜欢

转载自blog.csdn.net/tong5956/article/details/81503141