I am writing my own network plugin that should transfer packets over SCTP.
I am passing the data into the SCTP socket from rtph264pay and on the receiver from the SCTP socket into rtph264depay but the stream cannot be decoded. I checked hex dumps of the data and the incoming packets (from rtppay) are equivalent to the once outgoing (into rtpdepay). The one message that really bothers me and I couldn't find any solution is: I don't have all the debug output enabled: sender: GST_DEBUG="4,basesink:4,sctpsink:6,gstutils:5,basesrc:4,pushsrc:5,sctpsrc:5,rtph264pay:5,rtpbasepayload:5" ./build/rtpsctp /rtpsctpsendsend.txt receiver: GST_DEBUG="4,basesink:4,sctpsink:6,gstutils:5,basesrc:4,pushsrc:5,sctpsrc:5,rtph264depay:8,rtpbasedepayload:8"recv.txt I am also dumpung the first 16bytes form the packet as a hex dump on every packet.. It seems like the RTP header starts at byte 3 -> what are the first 2 bytes? I create the pipelines like this: sender: GstElement *pipeline, *source, *sink, *encoder, *rtppay; /* create pipeline */ pipeline = gst_pipeline_new ("pipeline"); /* create element */ source = gst_element_factory_make("videotestsrc", "source"); if (!source) { /* g_print ("Failed to create element of type 'videotestsrc'\n"); */ g_print ("Failed to create element of type 'videotestsrc'\n"); /* return -1; */ } g_object_set(G_OBJECT(source), /* "pattern", GstVideoTestSrcPattern.GST_VIDEO_TEST_SRC_SNOW, */ "is-live", TRUE, NULL); gst_util_set_object_arg(G_OBJECT(source), "pattern", "snow"); GstCaps *src_caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, 1280, "height", G_TYPE_INT, 720, "framerate", GST_TYPE_FRACTION, 25, 1, NULL); encoder = gst_element_factory_make("x264enc", "encoder"); if (!encoder) { g_print ("failed to create element of type 'x264enc'\n"); /* return -1; */ } gst_util_set_object_arg(G_OBJECT(encoder), "tune", "zerolatency"); /* g_object_set(encoder, "tune", (GstX264EncTune)"zerolatency", NULL); */ rtppay = gst_element_factory_make("rtph264pay", "rtppay"); if (!rtppay) { g_print ("failed to create element of type 'rtph264pay'\n"); /* return -1; */ } receiver: GstElement *pipeline = gst_pipeline_new ("pipeline"); /* create element */ GstElement *source = gst_element_factory_make("sctpsrc", "source"); if (!source) { g_critical ("Failed to create element of type 'sctpsrc'\n"); /* return -1; */ } g_object_set(G_OBJECT(source), "port", 1117, NULL); GstCaps *src_caps = gst_caps_new_simple("application/x-rtp", "media", G_TYPE_STRING, "video", "clock-rate", G_TYPE_INT, 90000, "encoding-name", G_TYPE_STRING, "H264", "a-framerate", G_TYPE_STRING, "25", "packetization-mode", G_TYPE_STRING, "1", "payload", G_TYPE_INT, 96, NULL); GstElement *rtpdepay = gst_element_factory_make("rtph264depay", "rtpdepay"); if (!rtpdepay) { g_critical ("failed to create element of type 'rtph264depay'\n"); /* return -1; */ } GstElement *decoder = gst_element_factory_make("avdec_h264", "decoder"); if (!decoder) { g_critical ("failed to create element of type 'avdec_h264'\n"); /* return -1; */ } GstCaps *decode_caps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "avc", "alignment", G_TYPE_STRING, "au", "level", G_TYPE_STRING, "3.1", "width", G_TYPE_INT, 1280, "height", G_TYPE_INT, 720, "framerate", GST_TYPE_FRACTION, 25, 1, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); GstElement *videoconvert = gst_element_factory_make("videoconvert", "videoconvert"); if (!videoconvert) { g_critical ("failed to create element of type 'videoconvert'\n"); /* return -1; */ } GstElement *videosink = gst_element_factory_make("ximagesink", "videsink"); if (!videosink) { g_critical ("Failed to create element of type 'ximagesink'\n"); /* return -1; */ } /* add to pipeline */ gst_bin_add_many(GST_BIN(pipeline), source, rtpdepay, decoder, videoconvert, videosink, NULL); /* link */ /* rtpdepay, decoder, */ if (!gst_element_link_filtered(source, rtpdepay, src_caps)) { g_warning ("Failed to link filterd source and rtpdepay!\n"); } gst_caps_unref(src_caps); if (!gst_element_link_filtered(rtpdepay, decoder, decode_caps)) { g_critical ("Failed to link source and rtpdepay'\n"); } gst_caps_unref(decode_caps); if (!gst_element_link(decoder, videoconvert)) { g_critical ("Failed to link source and rtpdepay'\n"); } if (!gst_element_link(videoconvert, videosink)) { g_critical ("Failed to link source and rtpdepay'\n"); } I've implemented the .create() methos of PushSrc where I retrieve the data from the socket and store it into the give buffer: static GstFlowReturn gst_sctpsrc_create(GstPushSrc *src, GstBuffer **buf) { GstSctpSrc *sctpsrc = GST_SCTPSRC(src); ssize_t n; int flags; char name[INET6_ADDRSTRLEN]; /* char *buffer = g_malloc(BUFFER_SIZE); */ /* buf = g_malloc(BUFFER_SIZE); */ /* [BUFFER_SIZE]; // FIXME: change to a malloc! */ socklen_t infolen; struct sctp_rcvinfo rcv_info; unsigned int infotype; struct sockaddr_in6 from; socklen_t from_len; // allocate the buffer GstMapInfo map; *buf = gst_buffer_new_and_alloc (BUFFER_SIZE); gst_buffer_map (*buf, &map, GST_MAP_READWRITE); from_len = (socklen_t)sizeof(struct sockaddr_in6); flags = 0; infolen = (socklen_t)sizeof(struct sctp_rcvinfo); n = usrsctp_recvv(sctpsrc->sock, (void *)map.data, BUFFER_SIZE, (struct sockaddr *)&from, &from_len, (void *)&rcv_info, &infolen, &infotype, &flags); if (n > 0) { if (flags & MSG_NOTIFICATION) { union sctp_notification *sn=(union sctp_notification*)map.data; /* switch(sn->sn_header.sn_type) { */ /* case SCTP_COMM_UP: { */ GST_DEBUG_OBJECT(sctpsrc, "Notificatjion of type %u length %llu received.", sn->sn_header.sn_type, (unsigned long long)n); } else { if (infotype == SCTP_RECVV_RCVINFO) { GST_DEBUG_OBJECT(sctpsrc, "Msg len %4llu from [%s]:%u SID %d " "SSN %u TSN %u PPID %u contxt %u compl %d", (unsigned long long)n, inet_ntop(AF_INET6, &from.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(from.sin6_port), rcv_info.rcv_sid, rcv_info.rcv_ssn, rcv_info.rcv_tsn, ntohl(rcv_info.rcv_ppid), rcv_info.rcv_context, (flags & MSG_EOR) ? 1 : 0); } else { GST_DEBUG_OBJECT(sctpsrc, "Msg of length %llu received from %s:%u, complete %d.", (unsigned long long)n, inet_ntop(AF_INET6, &from.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(from.sin6_port), (flags & MSG_EOR) ? 1 : 0); } print_rtp_header(sctpsrc, map.data+2); hexDump(NULL, map.data, MIN(16, n)); /* hexDump(NULL, map.data, n); */ } } else { GST_WARNING_OBJECT(sctpsrc, "GST_FLOW_EOS"); return GST_FLOW_EOS; } gst_buffer_unmap (*buf, &map); /* *buf = buffer; */ return GST_FLOW_OK; } |
What I forgot to say.. The following line in the debug output bothers me:
ERROR rtpbasedepayload gstrtpbasedepayload.c:618:gst_rtp_base_depayload_handle_event:<rtpdepay> Non-TIME segments are not supported and will likely fail |
ok it seems really like it has something to do with the rtp header:
having a look at gstrtpbuffer.c DEBUG default gstrtpbuffer.c:463:gst_rtp_buffer_map: version check failed (64 != 2) I got it to work now.. on the render function in the sctpsink I took the GstBuffer and just sent it out to the socket.. I managed to make it work with using the proper mapping.. gst_buffer_map (buffer, &map, GST_MAP_READ); and map.data not really well documented to be honest... or did I miss that somewhere in the doc?..... |
Le samedi 18 mars 2017 à 14:12 -0700, stfl a écrit :
> ok it seems really like it has something to do with the rtp header: > > having a look at gstrtpbuffer.c > > > I got it to work now.. on the render function in the sctpsink I took > the > GstBuffer and just sent it out to the socket.. > I managed to make it work with using the proper mapping.. > > gst_buffer_map (buffer, &map, GST_MAP_READ); > and map.data > > not really well documented to be honest... or did I miss that > somewhere in > the doc?..... writers) https://gstreamer.freedesktop.org/documentation/application-development/basics/data.html#buffers The Plugin Writer explanation (with examples): https://gstreamer.freedesktop.org/documentation/plugin-development/advanced/allocation.html#memory-allocation A tutorial that map GstBuffer: https://gstreamer.freedesktop.org/documentation/tutorials/basic/short-cutting-the-pipeline.html The reference documentation for GstBuffer: https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstBuffer.html The reference documentation for GstMemory: https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstMemory.html And that without listing the countless existing example code through all the similar plugins, notably udpsink, tcpsink etc. regards, Nicolas _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel signature.asc (188 bytes) Download Attachment |
Free forum by Nabble | Edit this page |