Guest User

clientRTP

a guest
Nov 18th, 2020
38
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <gst/gst.h>
  3.  
  4. #include <gst/rtp/rtp.h>
  5. #include <sys/time.h>
  6. #include <unistd.h>
  7. using namespace std;
  8.  
  9. /*
  10.  * Receiver setup
  11.  *
  12.  *  receives H264 encoded RTP video on port 5000, RTCP is received on  port 5001.
  13.  *  the receiver RTCP reports are sent to port 5005
  14.  *
  15.  *             .-------.      .----------.     .---------.   .-------.   .-----------.
  16.  *  RTP        |udpsrc |      | rtpbin   |     |h264depay|   |h264dec|   |xvimagesink|
  17.  *  port=5000  |      src->recv_rtp recv_rtp->sink     src->sink   src->sink         |
  18.  *             '-------'      |          |     '---------'   '-------'   '-----------'
  19.  *                            |          |
  20.  *                            |          |     .-------.
  21.  *                            |          |     |udpsink|  RTCP
  22.  *                            |    send_rtcp->sink     | port=5005
  23.  *             .-------.      |          |     '-------' sync=false
  24.  *  RTCP       |udpsrc |      |          |               async=false
  25.  *  port=5001  |     src->recv_rtcp      |
  26.  *             '-------'      '----------'
  27.  */
  28. struct Data
  29. {
  30.     GstElement *rtpbin;
  31.     GstElement *rtpx264depay;
  32. };
  33. static gboolean bus_call (GstBus     *bus,
  34.                          GstMessage *msg,
  35.                          gpointer    data)
  36. {
  37.     GMainLoop *loop = (GMainLoop *)data;
  38.  
  39.     switch (GST_MESSAGE_TYPE (msg)) {
  40.     case GST_MESSAGE_EOS:
  41.         g_print ("End-of-stream\n");
  42.         g_main_loop_quit (loop);
  43.         break;
  44.     case GST_MESSAGE_ERROR: {
  45.         gchar *debug = NULL;
  46.         GError *err = NULL;
  47.  
  48.         gst_message_parse_error (msg, &err, &debug);
  49.  
  50.         g_print ("Error: %s\n", err->message);
  51.         g_error_free (err);
  52.  
  53.         if (debug) {
  54.             g_print ("Debug details: %s\n", debug);
  55.             g_free (debug);
  56.         }
  57.  
  58.  
  59.         g_main_loop_quit (loop);
  60.         break;
  61.     }
  62.     case GST_MESSAGE_INFO: {
  63.         gchar *debug = NULL;
  64.         GError *err = NULL;
  65.  
  66.         gst_message_parse_info(msg, &err, &debug);
  67.  
  68.         g_print ("INFO: %s\n", err->message);
  69.         g_error_free (err);
  70.  
  71.         if (debug) {
  72.             g_print ("Debug details: %s\n", debug);
  73.             g_free (debug);
  74.         }
  75.  
  76.  
  77.         break;
  78.     }
  79.     case GST_MESSAGE_WARNING: {
  80.         gchar *debug = NULL;
  81.         GError *err = NULL;
  82.  
  83.         gst_message_parse_warning(msg, &err, &debug);
  84.  
  85.         g_print ("WARNING: %s\n", err->message);
  86.         g_error_free (err);
  87.  
  88.         if (debug) {
  89.             g_print ("Debug details: %s\n", debug);
  90.             g_free (debug);
  91.         }
  92.  
  93.  
  94.         break;
  95.     }
  96.  
  97.  
  98.  
  99.     default:
  100.         break;
  101.     }
  102.  
  103.     return TRUE;
  104. }
  105.  
  106.  
  107.  
  108. static void cb_new_rtp_recv_src_pad (GstElement *element,
  109.                                     GstPad     *pad,
  110.                                     gpointer    data)
  111. {
  112.     //gchar *name;
  113.     Data *rtp = (Data *) data;
  114.     GstPad *sinkPad;
  115.  
  116.     //name = gst_pad_get_name (pad);
  117.     //g_debug ("A new pad %s was created\n", name);
  118.     //g_free (name);
  119.  
  120.  
  121.     sinkPad = gst_element_get_static_pad (rtp->rtpx264depay, "sink");
  122.  
  123.     gst_pad_link (pad, sinkPad);
  124.  
  125.     gst_pad_set_caps(pad,gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)103"));
  126.     gst_pad_set_caps(sinkPad,gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)103"));
  127.     GList *cur = rtp->rtpbin->pads;
  128.     while (cur != 0) {
  129.         GstPad *curPad = (GstPad *)(cur->data);
  130.         gchar *name = gst_pad_get_name(curPad);
  131.        // gchar *findName = "recv_rtp_sink_0";
  132.         if (memcmp("recv_rtp_sink_0",name,sizeof (name)) == 0)
  133.         {
  134.             gst_pad_set_caps(curPad,gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)103"));
  135.              break;
  136.         }
  137.         cur = cur->next;
  138.     }
  139.     //GstPad *rtpSinkPad = gst_element_get_request_pad(rtp->rtpbin,"recv_rtp_sink_0");
  140.   //  gst_pad_set_caps(rtpSinkPad,gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)103"));
  141.  
  142.    // gst_object_unref(rtpSinkPad);
  143.     gst_object_unref (sinkPad);
  144.  
  145. }
  146.  
  147. bool linkStaticAndRequestPad(GstElement *sourse,GstElement *sink,gchar *nameSrcPad,gchar *nameSinkPad)
  148. {
  149.  
  150.     GstPad *srcPad = gst_element_get_static_pad(sourse,nameSrcPad);
  151.     GstPad *sinkPad = gst_element_get_request_pad(sink,nameSinkPad);
  152.     GstPadLinkReturn ret_link = gst_pad_link(srcPad,sinkPad);
  153.     if (ret_link != GST_PAD_LINK_OK)
  154.     {
  155.         cerr << "Error create link, beetwen recvRtpSinkPad and udpSrcRtpPad\n";
  156.         return false;
  157.     }
  158.     gst_object_unref(GST_OBJECT(srcPad));
  159.     gst_object_unref(GST_OBJECT(sinkPad));
  160.     return true;
  161. }
  162. bool linkRequestAndStatic(GstElement *sourse,GstElement *sink,gchar *nameSrcPad,gchar *nameSinkPad)
  163. {
  164.  
  165.     GstPad *srcPad = gst_element_get_request_pad(sourse,nameSrcPad);
  166.     GstPad *sinkPad = gst_element_get_static_pad(sink,nameSinkPad);
  167.     GstPadLinkReturn ret_link = gst_pad_link(srcPad,sinkPad);
  168.     if (ret_link != GST_PAD_LINK_OK)
  169.     {
  170.         cerr << "Error create link, beetwen recvRtpSinkPad and udpSrcRtpPad\n";
  171.         return false;
  172.     }
  173.     gst_object_unref(GST_OBJECT(srcPad));
  174.     gst_object_unref(GST_OBJECT(sinkPad));
  175.     return true;
  176. }
  177.  
  178. static gboolean process_rtcp_packet(GstRTCPPacket *packet){
  179.     guint32 ssrc, rtptime, packet_count, octet_count;
  180.     guint64 ntptime;
  181.     guint count, i;
  182.  
  183.     count = gst_rtcp_packet_get_rb_count(packet);
  184.     cerr << "    count " << count;
  185.     for (i=0; i<count; i++) {
  186.         guint32 exthighestseq, jitter, lsr, dlsr;
  187.         guint8 fractionlost;
  188.         gint32 packetslost;
  189.  
  190.         gst_rtcp_packet_get_rb(packet, i, &ssrc, &fractionlost,
  191.                                &packetslost, &exthighestseq, &jitter, &lsr, &dlsr);
  192.  
  193.         cerr << "    block " << i;
  194.         cerr << "    ssrc " << ssrc;
  195.         cerr << "    highest seq " << exthighestseq;
  196.         cerr << "    jitter " << jitter;
  197.         cerr << "    fraction lost " << fractionlost;
  198.         cerr << "    packet lost " << packetslost;
  199.         cerr << "    lsr " << lsr;
  200.         cerr << "    dlsr " << dlsr;
  201.  
  202.         //        rtcp_pkt->fractionlost = fractionlost;
  203.         //        rtcp_pkt->jitter = jitter;
  204.         //        rtcp_pkt->packetslost = packetslost;
  205.     }
  206.  
  207.     //cerr << "Received rtcp packet");
  208.  
  209.     return TRUE;
  210. }
  211.  
  212.  
  213. static gboolean cb_receive_rtcp(GstElement *rtpsession, GstBuffer *buf, gpointer data){
  214.  
  215.     GstRTCPBuffer rtcpBuffer = GST_RTCP_BUFFER_INIT;
  216.     //    GstRTCPBuffer *rtcpBuffer = (GstRTCPBuffer*)malloc(sizeof(GstRTCPBuffer));
  217.     //    rtcpBuffer->buffer = nullptr;
  218.     GstRTCPPacket *rtcpPacket = (GstRTCPPacket*)malloc(sizeof(GstRTCPPacket));
  219.  
  220.  
  221.     if (!gst_rtcp_buffer_validate(buf))
  222.     {
  223.         cerr << "Received invalid RTCP packet" << endl;
  224.     }
  225.  
  226.     cerr << "Received rtcp packet" << "\n";
  227.  
  228.  
  229.     gst_rtcp_buffer_map (buf,(GstMapFlags)(GST_MAP_READ),&rtcpBuffer);
  230.     gboolean more = gst_rtcp_buffer_get_first_packet(&rtcpBuffer,rtcpPacket);
  231.     while (more) {
  232.         GstRTCPType type;
  233.  
  234.         type = gst_rtcp_packet_get_type(rtcpPacket);
  235.         switch (type) {
  236.         case GST_RTCP_TYPE_SR:
  237.             process_rtcp_packet(rtcpPacket);
  238.             //   gst_rtcp_buffer_unmap (&rtcpBuffer);
  239.             //g_debug("RR");
  240.             //send_event_to_encoder(venc, &rtcp_pkt);
  241.             break;
  242.         default:
  243.             cerr << "Other types" << endl;
  244.             break;
  245.         }
  246.         more = gst_rtcp_packet_move_to_next(rtcpPacket);
  247.     }
  248.  
  249.     free(rtcpPacket);
  250.     return TRUE;
  251. }
  252. //struct timespec ts;
  253. //        timespec_get(&ts, TIME_UTC);
  254. GstPadProbeReturn cb_read_timestamp_rtp_pakcet (GstPad *pad,
  255.                                                GstPadProbeInfo *info,gpointer *user_data)
  256. {
  257.  
  258.  
  259.  
  260.     GstBuffer *buffer;
  261.     //  RTPJitterBuffer *rtpjitterbuffer = (GstElement *)(user_data);
  262.     buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  263.     if (buffer == NULL)
  264.         return GST_PAD_PROBE_OK;
  265.     static struct timespec ts;
  266.     //timespec_get(&ts, TIME_UTC);
  267.     //gconstpointer nsec = &ts.tv_nsec;
  268.     //gconstpointer sec = &ts.tv_sec;
  269.     gpointer nsec = &ts.tv_nsec;
  270.     gpointer sec = &ts.tv_sec;
  271.     guint size = 8;
  272.     //*size = 8;
  273.     guint8 appbits;
  274.     GstRTPBuffer rtpBufer = GST_RTP_BUFFER_INIT;
  275.     gst_rtp_buffer_map(buffer,GST_MAP_READ,&rtpBufer);
  276.    // gst_rtp_buffer_get_extension_twobytes_header(&rtpBufer,&appbits,1,0,&nsec,&size);
  277.    // gst_rtp_buffer_get_extension_twobytes_header(&rtpBufer,&appbits,1,0,&sec,&size);
  278.     std::cout << "RECV time, sec: " << ts.tv_sec << " " << "nanosec: " << ts.tv_nsec <<  std::endl;
  279.  
  280.     gst_rtp_buffer_unmap(&rtpBufer);
  281.     return GST_PAD_PROBE_OK;
  282. }
  283.  
  284. GstElement *create_pipeline(){
  285.  
  286.     GstElement *pipeline,*udpSrcRtp,*videconverter,
  287.         *x264decoder,*rtph264depay,*xvimagesink,
  288.         *rtpbin,*udpSrcRtcp,*udpSinkRtcp;
  289.  
  290.     pipeline = gst_pipeline_new("rtpStreamerRecv");
  291.  
  292.     // Создаю udpsrc для приема rtp пакетов.
  293.     udpSrcRtp = gst_element_factory_make("udpsrc","source");
  294.     // Создаю элемент управющий rtp сесией
  295.     rtpbin = gst_element_factory_make("rtpbin","rtpbin");
  296.  
  297.     // Создаю udp сток для приема rtсp пакетов
  298.     udpSinkRtcp = gst_element_factory_make("udpsink","udpSinkRtcp");
  299.     // Создаю udp источник для отправки rtcp пакетов.
  300.     udpSrcRtcp = gst_element_factory_make("udpsrc","udpSrcRtcp");
  301.  
  302.     // Создаю элемент который распакуют данные из rtp пакетов.
  303.     rtph264depay = gst_element_factory_make("rtph264depay","rtpdepay");
  304.     // Создаю декодер
  305.     x264decoder = gst_element_factory_make("avdec_h264","decoder");
  306.  
  307.  
  308.  
  309.     // Создаю элелмент который преобразует данные с кодера для воспроизведения.
  310.     videconverter = gst_element_factory_make("videoconvert","converter");
  311.     // Создаю для показа видео входящего видео потока.
  312.     xvimagesink = gst_element_factory_make("xvimagesink","video");
  313.  
  314.  
  315.     if (!pipeline || !udpSrcRtp || !x264decoder || !rtph264depay || !rtpbin || !udpSrcRtp || !udpSinkRtcp || !udpSrcRtcp || !xvimagesink || !videconverter)
  316.     {
  317.         cerr << "Not all elements could be created.\n";
  318.         return NULL;
  319.     }
  320.     // Задаю свойство udpsrt для приема RTP пакетов с которог захватывать видео
  321.     g_object_set(G_OBJECT(udpSrcRtp),"caps",gst_caps_from_string("application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264,payload=(int)103"),NULL);
  322.     g_object_set(G_OBJECT(udpSrcRtp),"port",5000,NULL);
  323.  
  324.  
  325.     // Устанавливаю параметры для upd сойденений.
  326.     g_object_set(G_OBJECT(udpSrcRtcp),"address","127.0.0.1",NULL);
  327.     g_object_set(G_OBJECT(udpSrcRtcp),"port",5001,NULL);
  328.     g_object_set(G_OBJECT (udpSrcRtcp), "caps", gst_caps_from_string("application/x-rtcp"), NULL);
  329.  
  330.  
  331.     g_object_set(G_OBJECT(udpSinkRtcp),"host","127.0.0.1",NULL);
  332.     g_object_set(G_OBJECT(udpSinkRtcp),"port",5005,NULL);
  333.     g_object_set(G_OBJECT(udpSinkRtcp),"sync",FALSE,NULL);
  334.     g_object_set(G_OBJECT(udpSinkRtcp),"async",FALSE,NULL);
  335.  
  336.  
  337.     g_object_set(G_OBJECT (rtpbin), "latency", 500, NULL);
  338.     // Добавляю элементы в контейнер
  339.     gst_bin_add_many(GST_BIN(pipeline),udpSrcRtp,udpSrcRtcp,rtpbin,udpSinkRtcp,
  340.                      rtph264depay,x264decoder,videconverter,xvimagesink,NULL);
  341.  
  342.     // Сойденяю PADы.
  343.  
  344.     if (!linkStaticAndRequestPad(udpSrcRtp,rtpbin,"src","recv_rtp_sink_%u"))
  345.     {
  346.         cerr << "Error create link, beetwen udpSrcRtp and rtpbin\n";
  347.         return NULL;
  348.     }
  349.  
  350.  
  351.  
  352.     if (!linkStaticAndRequestPad(udpSrcRtcp,rtpbin,"src","recv_rtcp_sink_%u"))
  353.     {
  354.         cerr << "Error create link, beetwen udpSrcRtcp and rtpbin\n";
  355.         return NULL;
  356.     }
  357.  
  358.  
  359.  
  360.     if (!linkRequestAndStatic(rtpbin,udpSinkRtcp,"send_rtcp_src_%u","sink"))
  361.     {
  362.         cerr << "Error create link, beetwen rtpbin and udpSinkRtcp\n";
  363.         return NULL;
  364.     }
  365.  
  366.     // сойденяю остальные элементы
  367.     Data *data = new Data;
  368.     data->rtpbin = rtpbin;
  369.     data->rtpx264depay = rtph264depay;
  370.     g_signal_connect (rtpbin, "pad-added", G_CALLBACK (cb_new_rtp_recv_src_pad),data);
  371.  
  372.  
  373.     if (!gst_element_link_many(rtph264depay,x264decoder,videconverter,xvimagesink,NULL))
  374.     {
  375.         cerr << "Elements could not be linked other.\n";
  376.         return NULL;
  377.  
  378.     }
  379.  
  380.     // создаю капы для согласования
  381.     // Создаю caps для того, чтобы согласовать параметры захвата видео с камеры и кодировщика.
  382.    /* GstCaps *capVideoConverterToXvimagesink;
  383.     capVideoConverterToXvimagesink = gst_caps_new_simple ("video/x-raw",
  384.                                                          "format",G_TYPE_STRING,"YUY2",
  385.                                                          "framerate", GST_TYPE_FRACTION, 30, 1,
  386.                                                          NULL);
  387.     if (!capVideoConverterToXvimagesink){
  388.         cerr << "Error create caps\n";
  389.         return NULL;
  390.     }
  391.     GstCaps *capDecoderToVideoConverter;
  392.     capDecoderToVideoConverter  = gst_caps_new_simple ("video/x-raw",
  393.                                                      "format",G_TYPE_STRING,"I420",
  394.                                                      "framerate", GST_TYPE_FRACTION, 30, 1,
  395.                                                      NULL);
  396.     if (!capDecoderToVideoConverter){
  397.         cerr << "Error create caps\n";
  398.         return NULL;
  399.     }*/
  400.     // Связваю все элементы.
  401.   /*  if (!gst_element_link_filtered(x264decoder,videconverter,capDecoderToVideoConverter))
  402.     {
  403.         cerr << "Elements could not be linked x264decoder and videconverter.\n";
  404.         return NULL;
  405.     }
  406.  
  407.     if (!gst_element_link_filtered(videconverter,xvimagesink,capVideoConverterToXvimagesink))
  408.     {
  409.         cerr << "Elements could not be linked videoconv and x264.\n";
  410.         return NULL;
  411.     }*/
  412. /*
  413.  * /GstPipeline:pipeline0/GstRtpSession:r.GstPad:send_rtcp_src: caps = application/x-rtcp
  414.  * /GstPipeline:pipeline0/GstUDPSink:udpsink0.GstPad:sink: caps = application/x-rtcp
  415.  * /GstPipeline:pipeline0/GstRtpSession:r.GstPad:sync_src: caps = application/x-rtcp
  416. */
  417.    // GstPad *srcPad = gst_element_get_static_pad(sourse,nameSrcPad);
  418.   //  GstPad *sinkPad = gst_element_get_request_pad(sink,nameSinkPad);
  419.  
  420. //    GObject *session;
  421.  
  422.  
  423. //    g_signal_emit_by_name (rtpbin, "get-internal-session", 0, &session);
  424. //    g_signal_connect_after (session, "on-receiving-rtcp",
  425. //                           G_CALLBACK (cb_receive_rtcp), NULL);
  426. //    g_object_unref(session);
  427.  
  428.  
  429.     //    GstElement *rtpjiterbuffer;
  430.     //    g_signal_emit_by_name (rtpbin, "new-jitterbuffer", 0, &rtpjiterbuffer);
  431. //    GstPad *rtph264depayPad = gst_element_get_static_pad(rtph264depay,"sink");
  432. //    gst_pad_add_probe(rtph264depayPad,GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback)cb_read_timestamp_rtp_pakcet,NULL,NULL);
  433. //    gst_object_unref(GST_OBJECT(rtph264depayPad));
  434.     return pipeline;
  435.  
  436. }
  437. int main(int argc, char *argv[])
  438. {
  439.  
  440.     gst_init(&argc, &argv);
  441.   //  GST_LEVEL_DEBUG;
  442.  
  443.     GMainLoop *loop;
  444.     loop = g_main_loop_new(NULL,FALSE);
  445.     GstBus *bus;
  446.  
  447.     GstElement *pipeline = create_pipeline();
  448.     if (pipeline == NULL)
  449.     {
  450.         cerr << "Error create pipeline!" << endl;
  451.         return -1;
  452.     }
  453.  
  454.     guint watch_id;
  455.     bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  456.     watch_id = gst_bus_add_watch (bus, bus_call, loop);
  457.     gst_object_unref (bus);
  458.  
  459.  
  460.     GstStateChangeReturn ret;
  461.     ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
  462.  
  463.     g_main_loop_run (loop);
  464.  
  465.  
  466.  
  467.     /* clean up */
  468.     gst_element_set_state (pipeline, GST_STATE_NULL);
  469.     gst_object_unref (pipeline);
  470.     g_source_remove (watch_id);
  471.     g_main_loop_unref (loop);
  472.  
  473.     return 0;
  474. }
  475.  
RAW Paste Data