Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <gst/gst.h>
- #include <cstdio>
- #include <string>
- #include <sstream>
- #include <iostream>
- void log(const char * chaine,...) {
- va_list ap;
- va_start( ap, chaine );
- vfprintf( stdout, chaine, ap );
- va_end( ap );
- }
- GstElement* _pipeline;
- GMainLoop* _loop;
- GstBus* bus = NULL;
- guint _timeout = 0;
- guint _busWatchId = 0;
- bool _useAudio = false;
- int _duration = 10;
- std::string _filename = "test_04.mp4";
- std::string _rtmpLocation = "";
- std::string _login = "";
- std::string _password = "";
- gboolean stop_encoding( void * data ) {
- if( g_main_loop_is_running( _loop ) ) {
- gst_element_send_event ( _pipeline, gst_event_new_eos() );
- }
- return FALSE;
- }
- gboolean bus_call ( GstBus* bus, GstMessage* msg, void* data ){
- switch ( GST_MESSAGE_TYPE ( msg ) ){
- case GST_MESSAGE_EOS: {
- log ( "bus_call: End of stream\n" );
- g_main_loop_quit ( _loop );
- break;
- }
- case GST_MESSAGE_ERROR : {
- gchar* debug;
- GError* error;
- gst_message_parse_error ( msg, &error, &debug );
- g_free ( debug );
- log( "bus_call: Error: %s\n", error->message );
- g_error_free ( error );
- g_main_loop_quit ( _loop );
- break;
- }
- case GST_MESSAGE_STATE_CHANGED : {
- GstObject * obj = GST_MESSAGE_SRC( msg );
- if( GST_IS_PIPELINE( obj ) ) {
- if( GST_ELEMENT( obj ) == _pipeline ) {
- GstState oldstate, newstate, pending;
- gst_message_parse_state_changed ( msg, &oldstate, &newstate, &pending );
- if( newstate == GST_STATE_PLAYING ) {
- if( _duration ) {
- log("bus_call: pipeline state changed to PLAYING, setting up timeout %ds\n", _duration );
- _timeout = g_timeout_add_seconds( _duration, (GSourceFunc)stop_encoding, NULL);
- }
- else {
- log("bus_call: pipeline state changed to PLAYING but no timeout needed (duration=0)\n");
- }
- }
- else if( newstate == GST_STATE_PAUSED ) {
- log("bus_call: pipeline state changed to PAUSED\n" );
- }
- }
- }
- break;
- }
- default:
- break;
- }
- return true;
- }
- void on_pad_added( GstElement *decoder, GstPad *pad, gpointer data ) {
- GstCaps *caps = NULL;
- #if GST_CHECK_VERSION(1,0,0)
- caps = gst_pad_query_caps( pad, NULL );
- #else
- caps = gst_pad_get_caps( pad );
- #endif
- GstBin *bin = (GstBin *) data;
- GstStructure *structure = gst_caps_get_structure( caps, 0 );
- int ret = 0;
- if(g_strrstr(gst_structure_get_string(structure,"media"), "video")) {
- GstElement * element = gst_bin_get_by_name( bin,"rtph264depay");
- if( element ) {
- GstPad * targetsink = gst_element_get_static_pad(element,"sink");
- ret = gst_pad_link( pad, targetsink );
- if( ret != GST_PAD_LINK_OK ) {
- GstCaps *sinkcaps = NULL;
- #if GST_CHECK_VERSION(1,0,0)
- sinkcaps = gst_pad_query_caps( targetsink, NULL );
- #else
- sinkcaps = gst_pad_get_caps( targetsink );
- #endif
- log("on_pad_added: %d LINKING RETURN: %d\n", __LINE__, ret );
- log("on_pad_added: Src Caps: %s\n", gst_caps_to_string( caps ) );
- log("on_pad_added: Target Caps: %s\n", gst_caps_to_string( sinkcaps ) );
- gst_caps_unref( sinkcaps );
- }
- else
- log("on_pad_added: linked video\n" );
- gst_object_unref( targetsink );
- gst_object_unref( element );
- }
- }
- if( g_strrstr( gst_structure_get_string( structure, "media" ), "audio" ) ) {
- GstElement * element = gst_bin_get_by_name( bin, "rtpmp4gdepay" );
- if( element ) {
- GstPad * targetsink = gst_element_get_static_pad( element, "sink" );
- ret = gst_pad_link( pad, targetsink );
- if( ret != GST_PAD_LINK_OK ) {
- GstCaps *sinkcaps = NULL;
- #if GST_CHECK_VERSION(1,0,0)
- sinkcaps = gst_pad_query_caps( targetsink, NULL );
- #else
- sinkcaps = gst_pad_get_caps( targetsink );
- #endif
- log("on_pad_added: %d LINKING RETURN: %d\n", __LINE__, ret );
- log("on_pad_added: Src Caps: %s\n", gst_caps_to_string( caps ) );
- log("on_pad_added: Target Caps: %s\n", gst_caps_to_string( sinkcaps ) );
- gst_caps_unref( sinkcaps );
- }
- else
- log("on_pad_added: linked audio\n" );
- gst_object_unref( targetsink );
- gst_object_unref( element );
- }
- }
- gst_caps_unref( caps );
- return;
- }
- bool setState( GstState state ) {
- GstStateChangeReturn sret;
- GstClockTime timeout = 10 * GST_SECOND; //10s
- log( "setState: Setting pipeline state to %s\n", gst_element_state_get_name( state ) );
- sret = gst_element_set_state ( _pipeline, state );
- if( sret == GST_STATE_CHANGE_ASYNC )
- log( "setState: going to %s state is ASYNC\n", gst_element_state_get_name( state ) );
- log( "setState: getting state\n" );
- sret = gst_element_get_state( _pipeline, NULL, NULL, timeout);
- if( sret != GST_STATE_CHANGE_SUCCESS && sret != GST_STATE_CHANGE_NO_PREROLL ) {
- if( sret == GST_STATE_CHANGE_FAILURE )
- log( "setState: failed to go into %s state (failure returned)\n", gst_element_state_get_name( state ) );
- else //ASYNC
- log( "setState: failed to go into %s state (async returned)\n", gst_element_state_get_name( state ) );
- if( state != GST_STATE_NULL ) {
- log( "setState: fallback to pipeline NULL state\n");
- gst_element_set_state ( _pipeline, GST_STATE_NULL );
- /* wait until state change either completes or fails */
- sret = gst_element_get_state( _pipeline, &state, NULL, timeout );
- if( sret == GST_STATE_CHANGE_SUCCESS )
- log( "setState: fallback to pipeline NULL state succeed\n" );
- if( sret == GST_STATE_CHANGE_FAILURE )
- log( "setState: fallback to pipeline NULL state failed (failure returned)\n" );
- else //ASYNC
- log( "setState: fallback to pipeline NULL state failed (async returned)\n" );
- }
- return false;
- }
- log( "setState: Setting pipeline state to %s DONE successfully\n", gst_element_state_get_name( state ) );
- return true;
- }
- /*
- * pipeline without audio:
- * rtspsrc location="..." ! rtph264depay ! h264parse ! mp4mux ! filesink location=".."
- */
- bool init() {
- GstBus* bus = NULL;
- _loop = g_main_loop_new( NULL, false );
- if( _filename.empty( ) && _rtmpLocation.empty( ) ) {
- log( "init: Can't init pipeline, no filename nor rtmpLocation provided\n");
- return false;
- }
- _pipeline = gst_pipeline_new( "mypipeline" );
- gst_pipeline_set_auto_flush_bus( GST_PIPELINE( _pipeline ), false );
- if( !_pipeline ) {
- log( "init: Failed to init pipeline\n");
- return false;
- }
- GstElement *rtspsrc = NULL,
- *rtph264depay = NULL,
- *h264parse = NULL,
- *aacparse = NULL,
- *rtpmp4gdepay = NULL,
- *muxer = NULL,
- *sink = NULL;
- bus = gst_pipeline_get_bus( GST_PIPELINE( _pipeline ) );
- _busWatchId = gst_bus_add_watch( bus, bus_call, NULL );
- gst_object_unref( bus );
- rtspsrc = gst_element_factory_make( "rtspsrc", "src" );
- rtph264depay = gst_element_factory_make( "rtph264depay", "rtph264depay" );
- h264parse = gst_element_factory_make( "h264parse", "h264parse" );
- if( !rtspsrc || !rtph264depay || !h264parse ) {
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- log( "init: Failed to create element rtspsrc or rtph264depay or h264parse\n");
- return false;
- }
- //rtsp source
- std::ostringstream rtspLocation;
- rtspLocation << "rtsp://192.168.10.26/axis-media/media.amp?videocodec=h264&resolution=320x180";
- g_object_set( G_OBJECT( rtspsrc ), "location", rtspLocation.str( ).c_str( ), NULL );
- if( !_login.empty( ) )
- g_object_set( G_OBJECT( rtspsrc ), "user-id", _login.c_str( ), NULL );
- if( !_password.empty( ) )
- g_object_set( G_OBJECT( rtspsrc ), "user-pw", _password.c_str( ), NULL );
- if( !_filename.empty( ) ) {
- muxer = gst_element_factory_make( "mp4mux", "mux" );
- if( !muxer ) {
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- log( "init: Failed to create element mp4mux\n" );
- return false;
- }
- if( !_filename.compare( "stdout" ) ) {
- sink = gst_element_factory_make( "fdsink", NULL );
- if( sink )
- g_object_set( G_OBJECT( sink ), "fd", 1, NULL );
- }
- else {
- sink = gst_element_factory_make( "filesink", NULL );
- if( sink )
- g_object_set( G_OBJECT( sink ), "location", _filename.c_str( ), NULL );
- }
- if( !sink ) {
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- log( "init: Failed to create element fdsink/filesink\n");
- return false;
- }
- //gstreamer-1.0: no more available option
- #if ! GST_CHECK_VERSION(1,0,0)
- g_object_set( G_OBJECT( rtph264depay ), "byte-stream", false, NULL );
- #endif
- }
- else {
- muxer = gst_element_factory_make( "flvmux", "mux" );
- sink = gst_element_factory_make( "rtmpsink", NULL );
- if( !muxer || !sink ) {
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- log( "init: Failed to create element rtmpsink or flvmux\n");
- return false;
- }
- g_object_set( G_OBJECT( muxer ), "streamable", true, NULL );
- //gstreamer-1.0: no more available option
- #if ! GST_CHECK_VERSION(1,0,0)
- g_object_set( G_OBJECT( rtph264depay ), "byte-stream", true, NULL );
- #endif
- std::string sinkLocation = _rtmpLocation + " live=1 timeout=10";
- g_object_set( G_OBJECT( sink ), "location", sinkLocation.c_str( ), NULL );
- g_object_set( G_OBJECT( sink ), "max-lateness", (gint64)1000000000, NULL);
- if( _useAudio ) {
- rtpmp4gdepay = gst_element_factory_make( "rtpmp4gdepay", "rtpmp4gdepay" );
- aacparse = gst_element_factory_make( "aacparse", "aacparse" );
- if( !rtpmp4gdepay || !aacparse ) {
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- log( "init: Failed to create element rtmp4gdepay or aacparse\n" );
- return false;
- }
- }
- }
- gst_bin_add_many( GST_BIN( _pipeline ), rtspsrc, rtph264depay, h264parse, muxer, sink, NULL );
- if( ! gst_element_link_many( rtph264depay, h264parse, muxer, sink, NULL ) ) {
- log( "init: Failed to link elements rtph264depay, h264parse, muxer, sink\n" );
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- return false;
- }
- if( _useAudio && rtpmp4gdepay ) {
- gst_bin_add_many( GST_BIN( _pipeline ), rtpmp4gdepay, aacparse, NULL );
- if( ! gst_element_link_many( rtpmp4gdepay, aacparse, muxer, NULL ) ) {
- log( "init: Failed to link elements rtpmp4gdepay, aacparse, muxer\n" );
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- return false;
- }
- }
- g_signal_connect( rtspsrc, "pad-added", G_CALLBACK( on_pad_added ), _pipeline );
- if( ! setState( GST_STATE_PAUSED ) ) {
- GstMessage *msg;
- // check if there is an error message with details on the bus
- msg = gst_bus_poll( bus, GST_MESSAGE_ERROR, 0 );
- if( msg ) {
- GError *err = NULL;
- gst_message_parse_error( msg, &err, NULL );
- log( "init: setState to PAUSED failed, error message: %s\n", err->message );
- g_error_free( err );
- gst_message_unref( msg );
- }
- gst_object_unref( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_main_loop_unref( _loop );
- _loop = NULL;
- return false;
- }
- log( "init: Pipeline state change to PAUSED succeed\n");
- return true;
- }
- bool start() {
- bool rv = setState( GST_STATE_PLAYING );
- if( rv ) {
- log( "start: Running...\n" );
- g_main_loop_run( _loop );
- /* Out of the main loop, clean up nicely */
- log( "start: Returned, stopping playback, setting state to NULL\n" );
- rv = setState( GST_STATE_NULL );
- }
- log( "start: Deleting pipeline\n");
- gst_object_unref ( GST_OBJECT( _pipeline ) );
- _pipeline = NULL;
- g_source_remove( _busWatchId );
- _busWatchId = 0;
- if( _timeout )
- g_source_remove( _timeout );
- g_main_loop_unref( _loop );
- _loop = NULL;
- return rv;
- }
- bool die = false;
- static void theEnd( int signal ) {
- log( "theEnd: end signal catched => %d\n", signal );
- die = true;
- }
- int main( int argc, char ** argv ) {
- signal( SIGTERM, theEnd ); /* default signal sent with kill */
- signal( SIGINT, theEnd ); /* Ctrl-C */
- signal( SIGHUP, theEnd );
- {
- gst_init_check(NULL, NULL, NULL);
- gst_debug_set_active(false);
- gst_debug_set_default_threshold(GST_LEVEL_NONE);
- }
- int i=0;
- while( ! die ) {
- log("\n\n%d\n\n", i);
- init();
- start();
- i++;
- }
- gst_deinit();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement