Linby
Linby

Reputation: 1

Gstreamer create RTP stream

I want to use gstreamer to package and stream h264 video frames. The udp method succeeds, but the tcp method does not work. What is my problem?

This is a rtp client program. The following is the code for the gstreamer setting part. It can send udp video stream to the server. The server cannot display when sending tcp video stream.

GstElement *pipeline, *appsrc, *h264parse, *mpegpsmux, *payloader, *sink, *queue;
User_RTP_Config main_rtp_config;

int RTP_Push_Stream(const unsigned char *frame, const int len)
{
    GstBuffer *buffer;
    GstFlowReturn ret;

    if(need_data == 1)
    {
        need_data = 0;
        buffer = gst_buffer_new_memdup(frame, len);
        g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
        if (ret != GST_FLOW_OK) {
            return -1;
        }
    }
    return 0;
}

int need_data = 0;
static void need_video_data_callback(GstElement *src) {
    need_data = 1;
}

static void enough_video_data_callback(GstElement *src) { 
    need_data = 0;    
}

int GST_RTP_Init(User_RTP_Config *config) {
    gst_init(NULL, NULL);
    gst_debug_set_default_threshold(GST_LEVEL_DEBUG);

    pipeline = gst_pipeline_new("rtp-pipeline");
    appsrc = gst_element_factory_make("appsrc", "source");
    queue = gst_element_factory_make("queue", "queue");

    if(config->rtp_type == RTP_TYPE_TCP_ACTIVE) {
        sink = gst_element_factory_make("tcpclientsink", "tcpclient-sink");
    }
//    else if(config->rtp_type == RTP_TYPE_TCP_PASSIVE) {
//        sink = gst_element_factory_make("tcpserversink", "tcpserver-sink");
//    }
    else {
        sink = gst_element_factory_make("udpsink", "udp-sink");
    }
    
    if (config->rtp_payload == RTP_PAYLOAD_PS) {
        h264parse = gst_element_factory_make("h264parse", "h264parser");
        mpegpsmux = gst_element_factory_make("mpegtsmux", "mpegpsmux");
        payloader = gst_element_factory_make("rtpmp2tpay", "ps-payloader");    
        if (!pipeline || !appsrc || !payloader || !sink || !queue || !mpegpsmux || !h264parse) {
            GST_ERROR("Failed to create elements");
            return -1;
        }
    }
    else if(config->rtp_payload == RTP_PAYLOAD_H264) {
        payloader = gst_element_factory_make("rtph264pay", "h264-payloader");
        if (!pipeline ||!appsrc ||!payloader ||!sink ||!queue) {
            GST_ERROR("Failed to create elements");
            return -1;
        }
    }

    g_object_set(sink, "host", config->rtp_ip, "port", config->rtp_port, NULL);

    if(config->rtp_payload == RTP_PAYLOAD_PS) {
        g_object_set(payloader, "pt", 96, NULL);
    }
    else if(config->rtp_payload == RTP_PAYLOAD_H264) {
        g_object_set(payloader, "pt", 98, NULL);
    }

    g_object_set(payloader, "ssrc", config->rtp_ssrc, NULL);
    // g_object_set(payloader, "config-interval", 1, NULL); 
    // g_object_set(G_OBJECT(sink), "max-bitrate", 900000, NULL);

    GstCaps *caps = gst_caps_new_simple("video/x-h264",
                                "stream-format", G_TYPE_STRING, "byte-stream",
                                "alignment", G_TYPE_STRING, "au", 
                                "width", G_TYPE_INT, 3840,
                                "height", G_TYPE_INT, 2160,       
                                "framerate", GST_TYPE_FRACTION, 30, 1, 
                                "encoding-name", G_TYPE_STRING, "H264",
                                NULL);
    g_object_set(appsrc,
                "caps", caps,
                "is-live", TRUE,
                "stream-type", 0,
                "format", GST_FORMAT_TIME,
                "do-timestamp", TRUE,
                NULL);

    g_signal_connect(appsrc, "need-data", G_CALLBACK(need_video_data_callback), NULL);
    g_signal_connect(appsrc, "enough-data", G_CALLBACK(enough_video_data_callback), NULL);    

    if(config->rtp_payload == RTP_PAYLOAD_PS) {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, h264parse, mpegpsmux, payloader, sink, NULL);
        if(!gst_element_link_many(appsrc, queue, h264parse, mpegpsmux, payloader, sink, NULL)) {
            printf("Error: Failed to link elements.\n");
            return -1;
        }
    }
    else if(config->rtp_payload == RTP_PAYLOAD_H264) {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, payloader, sink, NULL);
        if(!gst_element_link_many(appsrc, queue, payloader, sink, NULL)) {
            printf("Error: Failed to link elements.\n");
            return -1;
        }
    }

    GstStateChangeReturn ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        return -1;
    }
    config->rtp_switch = 2;
    return 0;
}

int GST_RTP_Deinit(User_RTP_Config *config) {
    if (config->rtp_switch == 0)
    {
        return -1;
    }
    gst_element_set_state(pipeline, GST_STATE_NULL);
    need_data = 0;
    gst_object_unref(GST_OBJECT(pipeline));
    
    deinit_socket(config);
    config->rtp_switch = 0;
    return 0;
}

After running the program, the following information is output enter image description here

Am I missing some tcpclientsink related settings?

Upvotes: 0

Views: 44

Answers (1)

SeB
SeB

Reputation: 1626

For RTP streaming over TCP with gstreamer, you would add rtpstreampay/rtpstreamdepay elements such as:

Sender:

gst-launch-1.0 videotestsrc ! x264enc key-int-max=30 insert-vui=1 tune=zerolatency ! h264parse ! rtph264pay ! rtpstreampay ! tcpserversink

Receiver:

gst-launch-1.0 tcpclientsrc ! application/x-rtp-stream,encoding-name=H264 ! rtpstreamdepay ! rtph264depay ! decodebin ! autovideoconvert ! autovideosink

Upvotes: 1

Related Questions