0

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?

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer, but I need to use MPEG Program Stream (PS). H264 direct packaging rtp can already run
I might advise for RTPMP2T but I cannot for MP2PS over RTP, sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.