GStreamer的AppSrc的使用(续2)

前面俩篇文章中,记录了使用AppSrc的情况下,如何注入数据与自动探测数据类型及解码,但Sink部分只强制指定了使用alsasink来输出声音。对于同时输出声音与图像的场景,GStreamer提供了playsink组件,用于自动选择合适的video与audio sink。
playsink同样也是playbin的后端组件,如下的代码实现了playsink的配置:

#include <stdio.h>
#include <stdlib.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>

static FILE * fp;
static GstPad * audioPad;

void _needData( GstAppSrc * src, guint arg1, gpointer user_data )
{
    GstBuffer * _buf;
    GstFlowReturn _ret;
    int _size;

    arg1    *=  4;

    _buf    =   gst_buffer_new_and_alloc( arg1 );

    GST_BUFFER_OFFSET( _buf )   =   ftell( fp );

    _size   =   fread( GST_BUFFER_DATA( _buf ), 1, arg1, fp );

    GST_BUFFER_SIZE( _buf ) =   _size;
    GST_BUFFER_OFFSET_END( _buf )   =   GST_BUFFER_OFFSET( _buf ) + _size;

    if( feof( fp ))
    {
        g_message( "rewind to head" );
        fseek( fp, 0, SEEK_SET );
    }

    g_signal_emit_by_name( src, "push-buffer", _buf, &_ret );

    gst_buffer_unref( _buf );
}

void _enoughData( GstElement * src, gpointer user_data )
{
    g_message( "%s", __func__ );
}

    GstElement * _pipeline, * _src, * _codec, * _sink;
/*
 * ===  FUNCTION  ======================================================================
 *         Name:  _decNewPad
 *  Description:
 * =====================================================================================
 */

static void _decNewPad( GstElement * decodebin, GstPad * pad, gpointer user_data )
{
    GstCaps * _caps;
    GstStructure * _str;
    const gchar * _name;
    GstPadTemplate * _tpl   =   NULL;
    GstElementClass * _klass;
    gboolean _ret;

    _caps   =   gst_pad_get_caps_reffed( pad );
    _str    =   gst_caps_get_structure( _caps, 0 );
    _name   =   gst_structure_get_name( _str );

    _klass  =   GST_ELEMENT_GET_CLASS( _sink );

    if( g_str_has_prefix( _name, "audio" ))
    {
        _tpl    =   gst_element_class_get_pad_template( _klass, "audio_sink" );
    }

    if( _tpl != NULL )
    {
        GstPad * _sinkPad;

        _sinkPad    =   gst_element_request_pad( _sink, _tpl, NULL, NULL );

        if( !gst_pad_is_linked( _sinkPad ))
        {
            gst_pad_link( pad, _sinkPad );
        }

        g_object_unref( _sinkPad );
    }

    g_signal_emit_by_name( _sink, "reconfigure", &_ret );
//gst_pad_link( pad, audioPad );
}       /* -----  end of static function _decNewPad  ----- */

/*
 * ===  FUNCTION  ======================================================================
 *         Name:  main
 *  Description:
 * =====================================================================================
 */
int main ( int argc, char *argv[] )
{

    fp  =   fopen( argv[1], "r" );

    g_assert( fp != NULL );

    gst_init( &argc, &argv );

    g_assert( _src  =   gst_element_factory_make( "appsrc", "source" ));

    g_assert( _codec    =   gst_element_factory_make( "decodebin", "codec" ));
    g_signal_connect( _codec, "pad-added", G_CALLBACK( _decNewPad ), NULL );

    g_assert( _sink =   gst_element_factory_make( "playsink", "sink" ));
    gst_util_set_object_arg (G_OBJECT (_sink), "flags",
            "audio+video");
//  g_assert( _sink =   gst_element_factory_make( "pulsesink", "sink" ));
//   g_assert( audioPad  =   gst_element_get_static_pad( _sink, "sink" ));
    _pipeline   =   gst_pipeline_new( "pipeline" );

    gst_bin_add_many( GST_BIN( _pipeline ), _src, _codec, _sink, NULL );

    gst_element_link_many( _src, _codec, NULL );

    g_signal_connect ( _src, "need-data", G_CALLBACK( _needData ), NULL );
    g_signal_connect ( _src, "enough-data", G_CALLBACK( _enoughData ), NULL );

    gst_element_set_state( _pipeline, GST_STATE_PLAYING );

    sleep(1);
    GST_DEBUG_BIN_TO_DOT_FILE( _pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "pipeline" );
    pause();

    return 0;
}               /* ----------  end of function main  ---------- */

你可能感兴趣的:(gstreamer,playsink)