Advertisement
Guest User

gstreamer memory usage

a guest
Apr 2nd, 2013
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.32 KB | None | 0 0
  1. #include <gst/gst.h>
  2.  
  3. #include <cstdio>
  4.  
  5. #include <string>
  6. #include <sstream>
  7. #include <iostream>
  8.  
  9.  
  10. void log(const char * chaine,...) {
  11.     va_list ap;
  12.     va_start( ap, chaine );
  13.  
  14.     vfprintf( stdout, chaine, ap );
  15.    
  16.     va_end( ap );
  17. }
  18.  
  19. GstElement* _pipeline;
  20. GMainLoop*  _loop;
  21. GstBus* bus = NULL;
  22. guint _timeout = 0;
  23. guint _busWatchId = 0;
  24. bool _useAudio = false;
  25.  
  26. int _duration = 10;
  27.  
  28. std::string _filename = "test_04.mp4";
  29. std::string _rtmpLocation = "";
  30. std::string _login = "";
  31. std::string _password = "";
  32.  
  33. gboolean stop_encoding( void * data ) {
  34.     if( g_main_loop_is_running( _loop ) ) {
  35.         gst_element_send_event ( _pipeline, gst_event_new_eos() );
  36.     }
  37.  
  38.     return FALSE;
  39. }
  40.  
  41. gboolean bus_call ( GstBus* bus, GstMessage* msg, void* data ){
  42.  
  43.     switch ( GST_MESSAGE_TYPE ( msg ) ){
  44.     case GST_MESSAGE_EOS: {
  45.         log ( "bus_call: End of stream\n" );
  46.         g_main_loop_quit ( _loop );
  47.  
  48.        break;
  49.     }
  50.     case GST_MESSAGE_ERROR : {
  51.         gchar* debug;
  52.         GError* error;
  53.         gst_message_parse_error ( msg, &error, &debug );
  54.         g_free ( debug );
  55.  
  56.         log( "bus_call: Error: %s\n", error->message );
  57.         g_error_free ( error );
  58.         g_main_loop_quit ( _loop );
  59.  
  60.         break;
  61.     }
  62.     case GST_MESSAGE_STATE_CHANGED : {
  63.         GstObject * obj = GST_MESSAGE_SRC( msg );
  64.         if( GST_IS_PIPELINE( obj ) ) {
  65.             if( GST_ELEMENT( obj ) == _pipeline ) {
  66.                 GstState oldstate, newstate, pending;
  67.                 gst_message_parse_state_changed ( msg, &oldstate, &newstate, &pending );
  68.                 if( newstate == GST_STATE_PLAYING ) {
  69.                     if( _duration ) {
  70.                         log("bus_call: pipeline state changed to PLAYING, setting up timeout %ds\n", _duration );
  71.                         _timeout = g_timeout_add_seconds( _duration, (GSourceFunc)stop_encoding, NULL);
  72.                     }
  73.                     else {
  74.                         log("bus_call: pipeline state changed to PLAYING but no timeout needed (duration=0)\n");
  75.                     }
  76.                 }
  77.                 else if( newstate == GST_STATE_PAUSED ) {
  78.                     log("bus_call: pipeline state changed to PAUSED\n" );
  79.                 }
  80.             }
  81.         }
  82.         break;
  83.     }
  84.     default:
  85.         break;
  86.     }
  87.  
  88.     return true;
  89. }
  90.  
  91. void on_pad_added( GstElement *decoder, GstPad *pad, gpointer data ) {
  92.     GstCaps *caps = NULL;
  93. #if GST_CHECK_VERSION(1,0,0)
  94.     caps = gst_pad_query_caps( pad, NULL );
  95. #else
  96.     caps = gst_pad_get_caps( pad );
  97. #endif
  98.     GstBin *bin = (GstBin *) data;
  99.     GstStructure *structure = gst_caps_get_structure( caps, 0 );
  100.     int ret = 0;
  101.  
  102.     if(g_strrstr(gst_structure_get_string(structure,"media"), "video")) {
  103.         GstElement * element = gst_bin_get_by_name( bin,"rtph264depay");
  104.         if( element ) {
  105.             GstPad * targetsink = gst_element_get_static_pad(element,"sink");
  106.  
  107.             ret = gst_pad_link( pad, targetsink );
  108.             if( ret != GST_PAD_LINK_OK ) {
  109.                 GstCaps *sinkcaps = NULL;
  110. #if GST_CHECK_VERSION(1,0,0)
  111.                 sinkcaps = gst_pad_query_caps( targetsink, NULL );
  112. #else
  113.                 sinkcaps = gst_pad_get_caps( targetsink );
  114. #endif
  115.                 log("on_pad_added: %d LINKING RETURN: %d\n", __LINE__, ret );
  116.                 log("on_pad_added: Src Caps: %s\n", gst_caps_to_string( caps ) );
  117.                 log("on_pad_added: Target Caps: %s\n", gst_caps_to_string( sinkcaps ) );
  118.                 gst_caps_unref( sinkcaps );
  119.             }
  120.             else
  121.                 log("on_pad_added: linked video\n" );
  122.  
  123.             gst_object_unref( targetsink );
  124.             gst_object_unref( element );
  125.         }
  126.     }
  127.  
  128.     if( g_strrstr( gst_structure_get_string( structure, "media" ), "audio" ) ) {
  129.         GstElement * element = gst_bin_get_by_name( bin, "rtpmp4gdepay" );
  130.  
  131.         if( element ) {
  132.             GstPad * targetsink = gst_element_get_static_pad( element, "sink" );
  133.             ret = gst_pad_link( pad, targetsink );
  134.             if( ret != GST_PAD_LINK_OK ) {
  135.                 GstCaps *sinkcaps = NULL;
  136. #if GST_CHECK_VERSION(1,0,0)
  137.                 sinkcaps = gst_pad_query_caps( targetsink, NULL );
  138. #else
  139.                 sinkcaps = gst_pad_get_caps( targetsink );
  140. #endif
  141.                 log("on_pad_added: %d LINKING RETURN: %d\n", __LINE__, ret );
  142.                 log("on_pad_added: Src Caps: %s\n", gst_caps_to_string( caps ) );
  143.                 log("on_pad_added: Target Caps: %s\n", gst_caps_to_string( sinkcaps ) );
  144.                 gst_caps_unref( sinkcaps );
  145.             }
  146.             else
  147.                 log("on_pad_added: linked audio\n" );
  148.  
  149.             gst_object_unref( targetsink );
  150.             gst_object_unref( element );
  151.         }
  152.     }
  153.  
  154.     gst_caps_unref( caps );
  155.  
  156.     return;
  157. }
  158.  
  159. bool setState( GstState state ) {
  160.     GstStateChangeReturn sret;
  161.    
  162.     GstClockTime timeout = 10 * GST_SECOND; //10s
  163.    
  164.     log( "setState: Setting pipeline state to %s\n", gst_element_state_get_name( state ) );
  165.     sret = gst_element_set_state ( _pipeline, state );
  166.     if( sret == GST_STATE_CHANGE_ASYNC )
  167.         log( "setState: going to %s state is ASYNC\n", gst_element_state_get_name( state ) );
  168.  
  169.     log( "setState: getting state\n" );
  170.     sret = gst_element_get_state( _pipeline, NULL, NULL, timeout);
  171.    
  172.     if( sret != GST_STATE_CHANGE_SUCCESS && sret != GST_STATE_CHANGE_NO_PREROLL ) {
  173.         if( sret == GST_STATE_CHANGE_FAILURE )
  174.             log( "setState: failed to go into %s state (failure returned)\n", gst_element_state_get_name( state ) );
  175.         else //ASYNC
  176.             log( "setState: failed to go into %s state (async returned)\n", gst_element_state_get_name( state ) );
  177.  
  178.         if( state != GST_STATE_NULL ) {
  179.             log( "setState: fallback to pipeline NULL state\n");
  180.            
  181.             gst_element_set_state ( _pipeline, GST_STATE_NULL );
  182.  
  183.             /* wait until state change either completes or fails */
  184.             sret = gst_element_get_state( _pipeline, &state, NULL, timeout );
  185.             if( sret == GST_STATE_CHANGE_SUCCESS )
  186.                 log( "setState: fallback to pipeline NULL state succeed\n" );
  187.             if( sret == GST_STATE_CHANGE_FAILURE )
  188.                 log( "setState: fallback to pipeline NULL state failed (failure returned)\n" );
  189.             else //ASYNC
  190.                 log( "setState: fallback to pipeline NULL state failed (async returned)\n" );
  191.         }
  192.        
  193.         return false;
  194.     }
  195.    
  196.     log( "setState: Setting pipeline state to %s DONE successfully\n", gst_element_state_get_name( state ) );
  197.    
  198.     return true;
  199. }
  200.  
  201. /*
  202.  * pipeline without audio:
  203.  * rtspsrc location="..." ! rtph264depay ! h264parse ! mp4mux ! filesink location=".."
  204.  */
  205. bool init() {
  206.     GstBus* bus = NULL;
  207.     _loop = g_main_loop_new( NULL, false );
  208.  
  209.     if( _filename.empty( ) && _rtmpLocation.empty( ) ) {
  210.         log( "init: Can't init pipeline, no filename nor rtmpLocation provided\n");
  211.         return false;
  212.     }
  213.  
  214.     _pipeline = gst_pipeline_new( "mypipeline" );
  215.     gst_pipeline_set_auto_flush_bus( GST_PIPELINE( _pipeline ), false );
  216.  
  217.     if( !_pipeline ) {
  218.         log( "init: Failed to init pipeline\n");
  219.         return false;
  220.     }
  221.  
  222.     GstElement *rtspsrc = NULL,
  223.         *rtph264depay = NULL,
  224.         *h264parse = NULL,
  225.         *aacparse = NULL,
  226.         *rtpmp4gdepay = NULL,
  227.         *muxer = NULL,
  228.         *sink = NULL;
  229.  
  230.     bus = gst_pipeline_get_bus( GST_PIPELINE( _pipeline ) );
  231.     _busWatchId = gst_bus_add_watch( bus, bus_call, NULL );
  232.     gst_object_unref( bus );
  233.  
  234.     rtspsrc = gst_element_factory_make( "rtspsrc", "src" );
  235.     rtph264depay = gst_element_factory_make( "rtph264depay", "rtph264depay" );
  236.     h264parse = gst_element_factory_make( "h264parse", "h264parse" );
  237.  
  238.     if( !rtspsrc || !rtph264depay || !h264parse ) {
  239.         gst_object_unref( GST_OBJECT( _pipeline ) );
  240.         _pipeline = NULL;
  241.         g_main_loop_unref( _loop );
  242.         _loop = NULL;
  243.         log( "init: Failed to create element rtspsrc or rtph264depay or h264parse\n");
  244.         return false;
  245.     }
  246.    
  247.     //rtsp source
  248.     std::ostringstream rtspLocation;
  249.     rtspLocation << "rtsp://192.168.10.26/axis-media/media.amp?videocodec=h264&resolution=320x180";
  250.  
  251.     g_object_set( G_OBJECT( rtspsrc ), "location", rtspLocation.str( ).c_str( ), NULL );
  252.     if( !_login.empty( ) )
  253.         g_object_set( G_OBJECT( rtspsrc ), "user-id", _login.c_str( ), NULL );
  254.     if( !_password.empty( ) )
  255.         g_object_set( G_OBJECT( rtspsrc ), "user-pw", _password.c_str( ), NULL );
  256.    
  257.     if( !_filename.empty( ) ) {
  258.         muxer = gst_element_factory_make( "mp4mux", "mux" );
  259.         if( !muxer ) {
  260.             gst_object_unref( GST_OBJECT( _pipeline ) );
  261.             _pipeline = NULL;
  262.             g_main_loop_unref( _loop );
  263.             _loop = NULL;
  264.             log( "init: Failed to create element mp4mux\n" );
  265.             return false;
  266.         }
  267.        
  268.         if( !_filename.compare( "stdout" ) ) {
  269.             sink = gst_element_factory_make( "fdsink", NULL );
  270.             if( sink )
  271.                 g_object_set( G_OBJECT( sink ), "fd", 1, NULL );
  272.         }
  273.         else {
  274.             sink = gst_element_factory_make( "filesink", NULL );
  275.             if( sink )
  276.                 g_object_set( G_OBJECT( sink ), "location", _filename.c_str( ), NULL );
  277.         }
  278.        
  279.         if( !sink ) {
  280.             gst_object_unref( GST_OBJECT( _pipeline ) );
  281.             _pipeline = NULL;
  282.             g_main_loop_unref( _loop );
  283.             _loop = NULL;
  284.  
  285.             log( "init: Failed to create element fdsink/filesink\n");
  286.             return false;
  287.         }
  288.  
  289.         //gstreamer-1.0: no more available option
  290. #if ! GST_CHECK_VERSION(1,0,0)
  291.         g_object_set( G_OBJECT( rtph264depay ), "byte-stream", false, NULL );
  292. #endif
  293.     }
  294.     else {
  295.         muxer = gst_element_factory_make( "flvmux", "mux" );
  296.         sink = gst_element_factory_make( "rtmpsink", NULL );
  297.  
  298.         if( !muxer || !sink ) {
  299.             gst_object_unref( GST_OBJECT( _pipeline ) );
  300.             _pipeline = NULL;
  301.             g_main_loop_unref( _loop );
  302.             _loop = NULL;
  303.  
  304.             log( "init: Failed to create element rtmpsink or flvmux\n");
  305.             return false;
  306.         }
  307.  
  308.         g_object_set( G_OBJECT( muxer ), "streamable", true, NULL );
  309.  
  310.         //gstreamer-1.0: no more available option
  311. #if ! GST_CHECK_VERSION(1,0,0)
  312.         g_object_set( G_OBJECT( rtph264depay ), "byte-stream", true, NULL );
  313. #endif
  314.         std::string sinkLocation = _rtmpLocation + " live=1 timeout=10";
  315.  
  316.         g_object_set( G_OBJECT( sink ), "location", sinkLocation.c_str( ), NULL );
  317.         g_object_set( G_OBJECT( sink ), "max-lateness", (gint64)1000000000, NULL);
  318.  
  319.         if( _useAudio ) {
  320.             rtpmp4gdepay = gst_element_factory_make( "rtpmp4gdepay", "rtpmp4gdepay" );
  321.             aacparse = gst_element_factory_make( "aacparse", "aacparse" );
  322.             if( !rtpmp4gdepay || !aacparse ) {
  323.                 gst_object_unref( GST_OBJECT( _pipeline ) );
  324.                 _pipeline = NULL;
  325.                 g_main_loop_unref( _loop );
  326.                 _loop = NULL;
  327.  
  328.                 log( "init: Failed to create element rtmp4gdepay or aacparse\n" );
  329.                 return false;
  330.             }
  331.         }
  332.     }
  333.    
  334.     gst_bin_add_many( GST_BIN( _pipeline ), rtspsrc, rtph264depay, h264parse, muxer, sink, NULL );
  335.     if( ! gst_element_link_many( rtph264depay, h264parse, muxer, sink, NULL ) ) {
  336.         log( "init: Failed to link elements rtph264depay, h264parse, muxer, sink\n" );
  337.         gst_object_unref( GST_OBJECT( _pipeline ) );
  338.         _pipeline = NULL;
  339.         g_main_loop_unref( _loop );
  340.         _loop = NULL;
  341.  
  342.         return false;
  343.     }
  344.  
  345.     if( _useAudio && rtpmp4gdepay ) {
  346.         gst_bin_add_many( GST_BIN( _pipeline ), rtpmp4gdepay, aacparse, NULL );
  347.         if( ! gst_element_link_many( rtpmp4gdepay, aacparse, muxer, NULL ) ) {
  348.             log( "init: Failed to link elements rtpmp4gdepay, aacparse, muxer\n" );
  349.             gst_object_unref( GST_OBJECT( _pipeline ) );
  350.             _pipeline = NULL;
  351.             g_main_loop_unref( _loop );
  352.             _loop = NULL;
  353.  
  354.             return false;
  355.         }
  356.     }
  357.    
  358.     g_signal_connect( rtspsrc, "pad-added", G_CALLBACK( on_pad_added ), _pipeline );
  359.  
  360.     if( ! setState( GST_STATE_PAUSED ) ) {
  361.         GstMessage *msg;
  362.  
  363.         // check if there is an error message with details on the bus
  364.         msg = gst_bus_poll( bus, GST_MESSAGE_ERROR, 0 );
  365.         if( msg ) {
  366.             GError *err = NULL;
  367.  
  368.             gst_message_parse_error( msg, &err, NULL );
  369.             log( "init: setState to PAUSED failed, error message: %s\n", err->message );
  370.             g_error_free( err );
  371.             gst_message_unref( msg );
  372.         }
  373.        
  374.         gst_object_unref( GST_OBJECT( _pipeline ) );
  375.         _pipeline = NULL;
  376.         g_main_loop_unref( _loop );
  377.         _loop = NULL;
  378.  
  379.         return false;
  380.     }
  381.     log( "init: Pipeline state change to PAUSED succeed\n");
  382.  
  383.     return true;
  384. }
  385.  
  386. bool start() {
  387.     bool rv = setState( GST_STATE_PLAYING );
  388.    
  389.     if( rv ) {
  390.         log( "start: Running...\n" );
  391.         g_main_loop_run( _loop );
  392.  
  393.         /* Out of the main loop, clean up nicely */
  394.         log( "start: Returned, stopping playback, setting state to NULL\n" );
  395.         rv = setState( GST_STATE_NULL );
  396.     }
  397.  
  398.     log( "start: Deleting pipeline\n");
  399.     gst_object_unref ( GST_OBJECT( _pipeline ) );
  400.     _pipeline = NULL;
  401.     g_source_remove( _busWatchId );
  402.     _busWatchId = 0;
  403.     if( _timeout )
  404.         g_source_remove( _timeout );
  405.    
  406.     g_main_loop_unref( _loop );
  407.     _loop = NULL;
  408.  
  409.     return rv;
  410. }
  411.  
  412. bool die = false;
  413. static void theEnd( int signal ) {
  414.     log( "theEnd: end signal catched => %d\n", signal );
  415.     die = true;
  416. }
  417.  
  418. int main( int argc, char ** argv ) {
  419.     signal( SIGTERM, theEnd ); /* default signal sent with kill */
  420.     signal( SIGINT, theEnd ); /* Ctrl-C */
  421.     signal( SIGHUP, theEnd );
  422.  
  423.     {
  424.         gst_init_check(NULL, NULL, NULL);
  425.         gst_debug_set_active(false);
  426.         gst_debug_set_default_threshold(GST_LEVEL_NONE);
  427.     }
  428.  
  429.     int i=0;
  430.     while( ! die ) {
  431.         log("\n\n%d\n\n", i);
  432.         init();
  433.         start();
  434.         i++;
  435.     }
  436.    
  437.     gst_deinit();
  438.    
  439.     return 0;
  440. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement