GStreamer设置pipeline的状态返回GST_STATE_CHANGE_ASYNC。

neicole 2014-04-01 05:34:10
GStreamer设置pipeline的状态返回GST_STATE_CHANGE_ASYNC。
程序一直在loop运行(不结束),但是却在bus上最后的消息是元素的状态改为PAUSED。

本来想实现mp4的截取功能,filesrc->qtdemux->mp4mux->filesink
打算下一步是通过seek实现(不确定可以不可以)控制qtdemux的时间。

本程序运行后,不能自动结束,按理来说,当文件完全读取完毕后,能自动结束程序。
以下是Debug信息:
/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;
}


...全文
1738 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧