GStreamer 1.0 在 C 中将原始编码为 H.264

Posted

技术标签:

【中文标题】GStreamer 1.0 在 C 中将原始编码为 H.264【英文标题】:GStreamer 1.0 encode raw to H.264 in C 【发布时间】:2018-07-02 08:29:35 【问题描述】:

我正在使用 GStreamer-1.0 版本:1.10.4

我有一个原始视频文件,我想在 C 中使用 GStreamer 使用 h.264 对其进行编码。

我的管道如下所示:

gst-launch-1.0 文件rc location=myVideo.yuv blocksize=2073600 !视频解析宽度=1920 高度=1080 !解码器!视频转换! x264enc !队列 ! mp4mux 名称=mux !文件接收器位置=myFile.mp4

当我在终端中执行此管道时,它工作正常。但我想用 C-API 来做,所以我的源代码如下所示:

GstElement* pipeline;

GstElement* src;
GstElement* videoparse;
GstElement* decodebin;
GstElement* videoconvert;
GstElement* x264enc;
GstElement* queue;
GstElement* mp4mux;
GstElement* filesink;

pipeline = gst_pipeline_new("pipeline");

src = gst_element_factory_make("filesrc", NULL);
if(!src) 
    GST_WARNING("Error in: src");


g_object_set(G_OBJECT(src),"location","myVideo.yuv",NULL);
g_object_set(G_OBJECT(src),2073600,NULL);

videoparse = gst_element_factory_make("videoparse", NULL);
if(!videoparse) 
    GST_WARNING("Error in: videoparse");


g_object_set(G_OBJECT(videoparse),"width",1920,NULL);
g_object_set(G_OBJECT(videoparse),"height",1080,NULL);

decodebin = gst_element_factory_make("decodebin", NULL);
if(!decodebin) 
    GST_WARNING("Error in: decodebin");


videoconvert = gst_element_factory_make("videoconvert", NULL);
if(!videoconvert) 
    GST_WARNING("Error in: videoconvert");
   

x264enc = gst_element_factory_make("x264enc", NULL);
if(!x264enc) 
    GST_WARNING("Error in: x264enc");
    

queue = gst_element_factory_make("queue", NULL);
if(!queue) 
    GST_WARNING("Error in: queue");
     

mp4mux = gst_element_factory_make("mp4mux", NULL);
if(!mp4mux) 
    GST_WARNING("Error in: mp4mux");
     

g_object_set(G_OBJECT(mp4mux),"name","mux",NULL);

filesink = gst_element_factory_make("filesink", NULL);
if(!filesink) 
    GST_WARNING("Error in: filesink");
     

g_object_set(G_OBJECT(filesink),"location","myFile.mp4",NULL);

gst_bin_add_many(GST_BIN(pipeline),src,videoparse,decodebin,videoconvert,x264enc,queue,mp4mux,filesink, NULL);

gst_element_link(src, videoparse);
gst_element_link(videoparse, decodebin);
gst_element_link(decodebin, videoconvert);
gst_element_link(videoconvert, x264enc);
gst_element_link(x264enc, queue);
gst_element_link(queue, mp4mux);
gst_element_link(mp4mux, filesink);

gst_element_set_state(pipeline, GST_STATE_PLAYING);

sleep(40);

正如我所说,终端中的管道工作正常,但 C 实现只创建一个空的 mp4 文件。我不明白为什么。

以防万一:原始视频文件的录制也已使用 GStreamer 完成。用于此的管道是:

gst-launch-1.0 -e v4l2src device=/dev/video0 num-buffers=300 !队列 !图像/JPEG,宽度=1920,高度=1080,帧率=30/1! JPEG格式!视频/x-raw,格式=I420,宽度=1920,高度=1080,帧率=30/1!文件接收器位置=myVideo.yuv

我想知道是否有人能看到我犯的错误,或者是否有人遇到过类似的问题。

【问题讨论】:

g_object_set(G_OBJECT(src),"location",myVideo.yuv,NULL);你能解释一下 myVideo.yuv 的价值是什么吗?它应该是字符串。 对不起,这是我的错误。我用静态名称和数字替换了所有变量,以保持论坛的可读性。在这一点上,我还应该提到 gst_init(NULL,NULL);也已经被调用了。无论如何,这不是问题。我发现 videoparse 似乎是麻烦制造者。我试图用 rawvideoparse 替换它,但没有成功。我不知道我的实现可能有什么问题。 【参考方案1】:

您没有检查任何函数的返回值。例如,链接元素可能会失败,或者设置状态。

在您的情况下,问题是 a)将 decodebin 链接到 videoconvert(它有时有垫,您需要连接到“垫添加”信号并从那里链接,检查 GStreamer 文档),b)将队列链接到mp4mux(它有请求垫,你必须使用 gst_element_get_request_pad() 来获得正确的垫)。

或者,您可以使用 C 中的 gst_parse_launch() 并传入您的管道字符串。它将为您提供一个与 gst-launch-1.0 工具创建的管道等效的管道,并且它会在内部完成我上面提到的两件事,而您不必担心。

【讨论】:

以上是关于GStreamer 1.0 在 C 中将原始编码为 H.264的主要内容,如果未能解决你的问题,请参考以下文章

视频编码原理及Gstreamer 硬编码代码实现

如何在MATLAB中将原始Unicode十六进制转换为Unicode表示

Gstreamer 1.0 - 创建自定义消息/事件/信号

在python中将base64编码的图像解码为原始图像

在 C 中将 char* 转换为 wchar*

在 mp4 中使用 gstreamer h264 + aac 录制只会产生部分可播放的文件