加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
gstsave2mp4.cpp 6.21 KB
一键复制 编辑 原始数据 按行查看 历史
心尘 提交于 2018-10-09 20:11 . gst save rtsp to mp4 with h264 and aac ok
#include "gstsave2mp4.h"
#include "qdebug.h"
/*
* GStreamer 0.10 Core Reference Manual:
* https://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/gstreamer-0.10/
*
*
*
*/
GstSave2Mp4::GstSave2Mp4(QObject *parent) : QObject(parent)
{
}
void GstSave2Mp4::createPipeline()
{
/* Initialisation */
gst_init (NULL, NULL);
char uri[] = "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov";
char location[] = "./test.mp4";
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("rtsp-player");
source = gst_element_factory_make ("uridecodebin", "source");
audioEncoder = gst_element_factory_make("ffenc_aac", "audio-encoder");
videoEncoder = gst_element_factory_make("x264enc", "video-encoder");
muxer = gst_element_factory_make("mp4mux", "muxer");
sink = gst_element_factory_make ("filesink", "sink");
GstElement *queue1 = gst_element_factory_make ("queue", "queue1");
GstElement *queue2= gst_element_factory_make ("queue", "queue2");
if (!pipeline || !source || !audioEncoder || !videoEncoder || !muxer || !sink) {
g_printerr ("One element could not be created.\n");
}
/* Set up the pipeline */
/* we set the rtsp uri to the source element and set file path to the sink element. */
g_object_set (G_OBJECT (source), "uri", uri, NULL);
g_object_set (G_OBJECT (sink), "location", location, NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_object_unref (bus);
gst_bus_add_signal_watch (bus);
/* we add all elements into the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, queue1, audioEncoder, queue2, videoEncoder , muxer, sink, NULL);
g_signal_connect (bus, "message", G_CALLBACK (cb_message), this);
g_signal_connect (source, "pad-added", G_CALLBACK (on_pad_added), queue1);
g_signal_connect (source, "pad-added", G_CALLBACK (on_pad_added), queue2);
if(!gst_element_link(muxer, sink)){
g_warning("failed to link muxer and sink");
}
if(!gst_element_link(audioEncoder, muxer)){
g_warning("failed to link audioEncoder and muxer");
}
if(!gst_element_link(queue1, audioEncoder)){
g_warning("failed to link audioEncoder and queue1");
}
if(!gst_element_link(videoEncoder, muxer)){
g_warning("failed to link videoEncoder and muxer");
}
if(!gst_element_link(queue2, videoEncoder)){
g_warning("failed to link audioEncoder and queue2");
}
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", uri);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
}
void GstSave2Mp4::cb_message (GstBus *bus, GstMessage *msg, gpointer *data)
{
// qDebug() << "cb_message";
GstSave2Mp4 *gstSave2Mp4 = (GstSave2Mp4*)data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR: {
GError *err;
gchar *debug;
gst_message_parse_error (msg, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
gst_element_set_state (gstSave2Mp4->pipeline, GST_STATE_READY);
break;
}
case GST_MESSAGE_EOS:
qDebug()<<"EOS !!!!!!";
/* end-of-stream */
gst_element_set_state (gstSave2Mp4->pipeline, GST_STATE_READY);
break;
case GST_MESSAGE_BUFFERING: {
gint percent = 0;
/* If the stream is live, we do not care about buffering. */
// if (data->is_live) break;
gst_message_parse_buffering (msg, &percent);
g_print ("Buffering (%3d%%)\r", percent);
/* Wait until buffering is complete before start/resume playing */
// if (percent < 100)
// gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
// else
// gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
break;
}
case GST_MESSAGE_CLOCK_LOST:
/* Get a new clock */
gst_element_set_state (gstSave2Mp4->pipeline, GST_STATE_PAUSED);
gst_element_set_state (gstSave2Mp4->pipeline, GST_STATE_PLAYING);
break;
case GST_MESSAGE_STATE_CHANGED:
GstState stateOld;
GstState stateNew;
gst_message_parse_state_changed(msg, &stateOld, &stateNew, NULL);
qDebug() << "STATE CHANGE: "
<< "NAME: " << QString(GST_OBJECT_NAME (msg->src))
<< " Old State: " << QString(gst_element_state_get_name (stateOld))
<< " New State: " << QString(gst_element_state_get_name (stateNew));
break;
default:
/* Unhandled message */
break;
}
}
void GstSave2Mp4::on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad;
GstElement *encoder = (GstElement *) data;
gchar *name;
qDebug() << "on_pad_added";
// name = gst_pad_get_name (pad);
// GstCaps *caps = gst_pad_get_caps(pad);
// gchar *caps_string = gst_caps_to_string(caps);
// g_print ("A new pad %s was created\n", name);
// g_print("caps:%s\n", caps_string);
// g_free (name);
// g_free(caps_string);
/* We can now link this pad with the vorbis-decoder sink pad */
g_print ("Dynamic pad created, linking demuxer/decoder\n");
sinkpad = gst_element_get_static_pad (encoder, "sink");
GstPadLinkReturn lret = gst_pad_link (pad, sinkpad);
switch (lret) {
case GST_PAD_LINK_OK:
qDebug() << "on_pad_added GST_PAD_LINK_OK";
break;
case GST_PAD_LINK_WRONG_HIERARCHY:
qDebug() << "on_pad_added GST_PAD_LINK_WRONG_HIERARCHY";
break;
case GST_PAD_LINK_WAS_LINKED:
qDebug() << "on_pad_added GST_PAD_LINK_WAS_LINKED";
break;
case GST_PAD_LINK_WRONG_DIRECTION:
qDebug() << "on_pad_added GST_PAD_LINK_WRONG_DIRECTION";
break;
case GST_PAD_LINK_NOFORMAT:
qDebug() << "on_pad_added GST_PAD_LINK_NOFORMAT";
break;
case GST_PAD_LINK_NOSCHED:
qDebug() << "on_pad_added GST_PAD_LINK_NOSCHED";
break;
case GST_PAD_LINK_REFUSED:
qDebug() << "on_pad_added GST_PAD_LINK_REFUSED";
break;
}
gst_object_unref (sinkpad);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化