gstreamer -- appsrc 到 rtsp推流

经常用到将appsrc中填充数据后,以rtsp流的形式推出。和rtmp不同的是,rtmp需要用ngnix做为server,而rtsp就是通过代码自己搭建一个server,代码如下

static int need_data_rtsp (GstElement * appsrc, guint unused, data * ptr)
{


if(*(ptr->Stop))
{
cout<<"stop pushing"<return 0;
}
  GstBuffer *buffer;
  guint size;
  GstFlowReturn ret =GST_FLOW_OK;


  size = (ptr->Input->size().width) * (ptr->Input->size().height) * 3;
   
  buffer = gst_buffer_new_allocate (NULL, size, NULL);
  
  GstMapInfo map;
  
  gst_buffer_map(buffer,&map,GST_MAP_READ);

  ptr->Mux->lock();
  memcpy(map.data,ptr->Input->data,size);
  ptr->Mux->unlock();
 
  guint64 s = ( getTickCount() - ptr->t) * GST_SECOND / getTickFrequency();
  
  ptr->t = getTickCount();


  GST_BUFFER_PTS (buffer) = ptr->Timestamp;

  GST_BUFFER_DURATION (buffer) = s;
 
  ptr->Timestamp += GST_BUFFER_DURATION (buffer) ;

  g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
  
  gst_buffer_unmap(buffer,&map);
  std::cout<<"pushing"<  
  gst_buffer_unref (buffer);


   if ( *(ptr->Stop)  ) {
    /* something wrong, stop pushing */
    g_main_loop_quit (ptr->Loop);
  } 


  return 1;
 
}




static void media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media, push_stream *ptr)
{
  GstElement *element, *appsrc;




//  GMainLoop *loop = g_main_loop_new (NULL, FALSE);
  data *ctx = new data(ptr->input,ptr->mux,&(ptr->stop),ptr->loop);


  /* get the element used for providing the streams of the media */
  element = gst_rtsp_media_get_element (media);


  /* get our appsrc, we named it 'mysrc' with the name property */
  appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc");


  /* this instructs appsrc that we will be dealing with timed buffer */
  gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
  /* configure the caps of the video */
  g_object_set (G_OBJECT (appsrc), "caps",
      gst_caps_new_simple ("video/x-raw",
          "format", G_TYPE_STRING, "BGR",
 "width", G_TYPE_INT, ptr->width,
 "height", G_TYPE_INT, ptr->height,
          "framerate", GST_TYPE_FRACTION, 2, 1, NULL), NULL);


  /* make sure ther datais freed when the media is gone */
  //g_object_set_data_full (G_OBJECT (media), "my-extra-data", ctx,
  //    (GDestroyNotify) g_free);


  /* install the callback that will be called when a buffer is needed */


  g_signal_connect (appsrc, "need-data", (GCallback) need_data_rtsp, ctx);
//  g_main_loop_run (loop);

  gst_object_unref (appsrc);
  gst_object_unref (element);
  cout<<"new a client"<

}




  void push_stream:: push_rtsp()
  {


  gst_init (NULL, NULL);


  loop = g_main_loop_new (NULL, FALSE);
  


  /* create a server instance */
  server = gst_rtsp_server_new ();
  gst_rtsp_server_set_service (server,"8556");
//  gst_rtsp_server_set_address (server,"192.168.1.164");


  /* get the mount points for this server, every server has a default object
   * that be used to map uri mount points to media factories */
  mounts = gst_rtsp_server_get_mount_points (server);
 
  /* make a media factory for a test stream. The default media factory can use
   * gst-launch syntax to create pipelines.
   * any launch line works as long as it contains elements named pay%d. Each
   * element with pay%d names will be a stream */
  factory = gst_rtsp_media_factory_new ();


  gst_rtsp_media_factory_set_launch (factory,
      "( appsrc name=mysrc ! videoconvert ! x264enc  ! rtph264pay name=pay0 pt=96 )");


  /* notify when our media is ready, This is called whenever someone asks for
   * the media and a new pipeline with our appsrc is created */


  g_signal_connect (factory, "media-configure", (GCallback) media_configure,this);




  /* attach the test factory to the /test url */
  gst_rtsp_mount_points_add_factory (mounts, “/test"”, factory);


  /* don't need the ref to the mounts anymore */
  g_object_unref (mounts);


  /* attach the server to the default maincontext */
  gst_rtsp_server_attach (server, NULL);
  /* start serving */
  g_print ("stream ready at rtsp://127.0.0.1:8554/test\n");
  g_main_loop_run (loop);

}

程序的流程是调用push_rtsp()函数后,进入主循环中,当有一个client请求连接时,就会触发 g_signal_connect (factory, "media-configure", (GCallback) media_configure,this)这句,调用media-configure()函数,当数据写入appsrc时触发  g_signal_connect (appsrc, "need-data", (GCallback) need_data_rtsp, ctx);回调 need-data()这个函数。因为项目的要求,我用到了data 和 push_stream 这两个类,push_rtsp()就是push_stream 中的一个方法。

类的具体定义:

class data
{
public:
data(Mat* _Input,mutex* _Mux, int* _Stop ,GMainLoop* _Loop);
~data();
Mat * Input;
mutex * Mux;
int * Stop;
GMainLoop *Loop;
       GstClockTime Timestamp;
int64 t;
};

class push_stream
{
private:

GstElement *pipeline;
    GstElement *appsrc;
    GstElement *conv;
GstElement *videosink; 
GstElement *h264enc;
GstElement *flvmux;
String location;
GstRTSPServer *server;
    GstRTSPMountPoints *mounts;
    GstRTSPMediaFactory *factory;


   


public:


int stop;
int width;
    int height;
GMainLoop *loop;
Mat *input;
mutex *mux;


void stop_stream();


push_stream();
push_stream(String _location ,Mat* _input, mutex *_mux);
void continue_stream();
void push_rtmp ();
void push_rtsp ();
void init (String _location, Mat* _input, mutex *_mux);


~push_stream();

};

https://github.com/GStreamer/gst-rtsp-server/tree/master/examples这个链接中有一些rtsp的有用的代码,测试过部分,可用。


你可能感兴趣的:(gstreamer)