2,543
社区成员
发帖
与我相关
我的任务
分享
/root/QtProgram/GStreamer/video_cut/video_cut 启动中...
STATE CHANGE: NAME: "mp4filesink" Old State: "NULL" New State: "READY"
STATE CHANGE: NAME: "mp4mux" Old State: "NULL" New State: "READY"
STATE CHANGE: NAME: "qtdemux" Old State: "NULL" New State: "READY"
STATE CHANGE: NAME: "mp4filesrc" Old State: "NULL" New State: "READY"
STATE CHANGE: NAME: "my-pipeline" Old State: "NULL" New State: "READY"
STATE CHANGE: NAME: "mp4mux" Old State: "READY" New State: "PAUSED"
STREAM_STATUS Element: "qtdemux" Status: "GST_STREAM_STATUS_TYPE_CREATE"
STATE CHANGE: NAME: "qtdemux" Old State: "READY" New State: "PAUSED"
STATE CHANGE: NAME: "mp4filesrc" Old State: "READY" New State: "PAUSED"
STREAM_STATUS Element: "qtdemux" Status: "GST_STREAM_STATUS_TYPE_ENTER"
In->S_CbPadAdded(...)
caps: "video/x-h264, stream-format=(string)avc, alignment=(string)au, level=(string)4, profile=(string)high, codec_data=(buffer)01640028ffe1001867640028acb402802dd808800000030080000019478c195001000568cf32c8b0, width=(int)1280, height=(int)720, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)1/1"
video/x-h264 padSink 0x10c0b20
pad link success
In->S_CbPadAdded(...)
caps: "audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, level=(string)2, base-profile=(string)lc, profile=(string)lc, codec_data=(buffer)1210, rate=(int)44100, channels=(int)2"
audio/mpeg padSink 0x10c0f80
pad link success
#include <gst/gst.h>
#include <glib.h>
#include <QDebug>
#include <QString>
#define IF_NULL_REUTRN(OBJECT) if (NULL == OBJECT) { qDebug() << "OBJECT==NULL"; return -1;}
/// help class
class CPipeElem
{
public:
GMainLoop* loop;
GstElement* elemPipeline;
GstBus* bus;
GstElement* elemFileSrc;
GstElement* elemQtDemux;
GstElement* elemMp4mux;
GstElement* elemFileSink;
public:
CPipeElem():loop(NULL), elemPipeline(NULL), bus(NULL),
elemFileSrc(NULL), elemQtDemux(NULL), elemMp4mux(NULL),elemFileSink(NULL)
{
}
};
/// function declaration
static void S_CallBackMessage(GstBus *bus, GstMessage *message, gpointer user_data);
static void S_CbPadAdded(GstElement *element, GstPad *pad, gpointer user_data);
/// main function
gint main (gint argc, gchar *argv[])
{
CPipeElem pipeElem;
/////////////////////////////////////////// init //////////////////////////////////////////////////
/// init gstreamer
gst_init (&argc, &argv);
/////////////////////////////////////////// init elem //////////////////////////////////////////////////
/// loop
pipeElem.loop = g_main_loop_new(NULL, FALSE);
IF_NULL_REUTRN(pipeElem.loop);
/// pipeline
pipeElem.elemPipeline = gst_pipeline_new("my-pipeline");
IF_NULL_REUTRN(pipeElem.elemPipeline);
/// bus
pipeElem.bus = gst_pipeline_get_bus (GST_PIPELINE (pipeElem.elemPipeline));
IF_NULL_REUTRN(pipeElem.bus);
gst_bus_add_signal_watch(pipeElem.bus);
g_signal_connect (pipeElem.bus, "message", (GCallback)S_CallBackMessage, &pipeElem); ///// pipeline的message
/// filesrc elem (mp4 file)
pipeElem.elemFileSrc = gst_element_factory_make("filesrc", "filesrc");
IF_NULL_REUTRN(pipeElem.elemFileSrc);
g_object_set (G_OBJECT(pipeElem.elemFileSrc), "name", "mp4filesrc", NULL);
g_object_set (G_OBJECT(pipeElem.elemFileSrc), "location", "/root/QtProgram/GStreamer/video_cut/wildlife_h264.mp4", NULL);
/// demux elem
pipeElem.elemQtDemux = gst_element_factory_make("qtdemux", "qtdemux");
IF_NULL_REUTRN(pipeElem.elemQtDemux);
g_object_set (G_OBJECT(pipeElem.elemQtDemux), "name", "qtdemux", NULL);
/// mux elem
pipeElem.elemMp4mux = gst_element_factory_make("mp4mux", "mp4mux");
IF_NULL_REUTRN(pipeElem.elemMp4mux);
g_object_set (G_OBJECT(pipeElem.elemMp4mux), "name", "mp4mux", NULL);
/// file sink elem
pipeElem.elemFileSink = gst_element_factory_make("filesink", "mp4filesink");
IF_NULL_REUTRN(pipeElem.elemFileSink);
g_object_set (G_OBJECT(pipeElem.elemFileSink), "name", "mp4filesink", NULL);
g_object_set (G_OBJECT(pipeElem.elemFileSink), "location", "/root/QtProgram/GStreamer/video_cut/cut.mp4", NULL);
/////////////////////////////////////////// create pipeline //////////////////////////////////////////////////
/// add to pipeline
gst_bin_add_many(GST_BIN (pipeElem.elemPipeline),
pipeElem.elemFileSrc, pipeElem.elemQtDemux,
pipeElem.elemMp4mux, pipeElem.elemFileSink,
NULL);
/// link in pipeline
gst_element_link_many(pipeElem.elemFileSrc, pipeElem.elemQtDemux, NULL);
gst_element_link_many(pipeElem.elemMp4mux, pipeElem.elemFileSink, NULL);
g_signal_connect(pipeElem.elemQtDemux, "pad-added", (GCallback)S_CbPadAdded, &pipeElem);
/////////////////////////////////////////// run pipeline //////////////////////////////////////////////////
int nRes = gst_element_set_state(pipeElem.elemPipeline, GST_STATE_PLAYING);
if (!(nRes == GST_STATE_CHANGE_ASYNC || nRes == GST_STATE_CHANGE_SUCCESS))
{
qDebug() << "Set State Error:" << nRes;
}
g_main_loop_run(pipeElem.loop);
/////////////////////////////////////////// uninit pipeline //////////////////////////////////////////////////
gst_element_set_state (pipeElem.elemPipeline, GST_STATE_NULL);
gst_object_unref(pipeElem.bus);
gst_object_unref(pipeElem.elemPipeline);
g_main_loop_unref(pipeElem.loop);
return 0;
}
static void S_CallBackMessage(GstBus *, GstMessage *message, gpointer user_data)
{
CPipeElem* pPipeElem = (CPipeElem*)user_data;
switch (GST_MESSAGE_TYPE (message))
{
case GST_MESSAGE_ERROR:
{
gchar *pDebug;
GError *pError;
gst_message_parse_error (message, &pError, &pDebug);
g_free (pDebug);
qDebug() << "Error: " << QString(pError->message);
g_error_free(pError);
g_main_loop_quit(pPipeElem->loop);
break;
}
case GST_MESSAGE_EOS:
{
qDebug() << "GST_MESSAGE_EOS";
g_main_loop_quit (pPipeElem->loop);
break;
}
case GST_MESSAGE_STATE_CHANGED:
{
GstState stateOld;
GstState stateNew;
gst_message_parse_state_changed(message, &stateOld, &stateNew, NULL);
qDebug() << "STATE CHANGE: "
<< "NAME: " << QString(GST_OBJECT_NAME (message->src))
<< " Old State: " << QString(gst_element_state_get_name (stateOld))
<< " New State: " << QString(gst_element_state_get_name (stateNew));
break;
}
case GST_MESSAGE_STREAM_STATUS:
{
QMap<GstStreamStatusType, QString> mapStreamStatus;
mapStreamStatus[GST_STREAM_STATUS_TYPE_CREATE] = "GST_STREAM_STATUS_TYPE_CREATE";
mapStreamStatus[GST_STREAM_STATUS_TYPE_ENTER] = "GST_STREAM_STATUS_TYPE_ENTER";
mapStreamStatus[GST_STREAM_STATUS_TYPE_LEAVE] = "GST_STREAM_STATUS_TYPE_LEAVE";
mapStreamStatus[GST_STREAM_STATUS_TYPE_DESTROY] = "GST_STREAM_STATUS_TYPE_DESTROY";
mapStreamStatus[GST_STREAM_STATUS_TYPE_START] = "GST_STREAM_STATUS_TYPE_START";
mapStreamStatus[GST_STREAM_STATUS_TYPE_PAUSE] = "GST_STREAM_STATUS_TYPE_PAUSE";
mapStreamStatus[GST_STREAM_STATUS_TYPE_STOP] = "GST_STREAM_STATUS_TYPE_STOP";
GstStreamStatusType statusType;
GstElement *elemOwner;
gst_message_parse_stream_status(message, &statusType, &elemOwner);
qDebug() << "STREAM_STATUS "
<< "Element:" << QString(gst_element_get_name(elemOwner))
<< " Status: " << mapStreamStatus[statusType];
break;
}
default:
break;
}
return;
}
static void S_CbPadAdded(GstElement *, GstPad *padSrc, gpointer user_data)
{
qDebug() << "In->S_CbPadAdded(...)";
CPipeElem* pPipeElem = (CPipeElem*) user_data;
//// Get the pads string
GstCaps *capsQuery = gst_pad_query_caps(padSrc, NULL);
gchar *cstrCaps = gst_caps_to_string(capsQuery);
QString strCaps(cstrCaps);
qDebug() << "caps:" << strCaps;
g_free(cstrCaps);
gst_caps_unref(capsQuery);
GstPad* padSink = NULL;
/// 视频处理
if(strCaps.contains("video/x-h264"))
{
padSink = gst_element_get_request_pad(pPipeElem->elemMp4mux, "video_%u");
qDebug() << "video/x-h264 padSink" << padSink;
}
/// 音频处理
else if(strCaps.contains("audio/mpeg"))
{
padSink = gst_element_get_request_pad(pPipeElem->elemMp4mux, "audio_%u");
qDebug() << "audio/mpeg padSink" << padSink;
}
int nRes = 500;
if (padSink != NULL)
{
nRes = gst_pad_link(padSrc, padSink);
}
if (nRes == 500)
{
qDebug() << "no pad to link";
}
else if (GST_PAD_LINK_OK != nRes)
{
qDebug() << "pad link error: " << nRes; /// GST_PAD_LINK_WAS_LINKED
}
else
{
qDebug() << "pad link success";
}
if (padSink != NULL)
{
gst_object_unref(padSink);
}
return;
}