This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/AM5728:GStreamer 编码器内存泄漏

Guru**** 2546020 points
Other Parts Discussed in Thread: AM5728

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/618509/linux-am5728-gstreamer-encode-memory-leak

器件型号:AM5728

工具/软件:Linux

大家好  

 我有很大的问题。 我的板是   http://www.ti.com.cn/tool/cn/tmdsevm572x?keyMatch=am5728%20evm&tisearch=Search-CN-Everything am5728 EVM  

 我的 SDK 为  http://software-dl.ti.com/processor-sdk-linux/esd/AM57X/03_03_00_04/index_FDS.html  

我的主机 PC 是 Ubuntu 14.04

当我使用带有 ducatih264enc 的 gstreamer 对摄像机数据进行编码时,,很遗憾 发生了内存泄漏

/*

*
***编译命令 arm-linux-gnueabihf-gcc app-camera.c -o app `pkg-config --CFLAGS --libs gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0`
*
/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#define waylandsink
#define v4l2src


typedef struct _App;
struct _App
{
GstElement *管道;
GstElement *appsrc;
GstElement *编码;
GstElement *灌电流;

GstBus *总线;
GstMessage *msg;
GMainLoop *LOOP;
guint bus_watch_id;
};

应用 s_app;
int ret、idx、 fd;
#define NBUF 3
#define FRAME_SIZE 152064//352*288*1.5

int width = 352、height = 288;
void * buffer_addr[NBUF];
int size[NBUF];


static void
feed_data (GstElement * appsrc、guint size、App * app)
{
printf ("源数据...\n");
struct v4l2_buffer buf;
/*选择一个缓冲器*/
memset (&buf、0、sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO 捕捉;
buf.memory = V4L2_MEMORY_MMAP;

if (-1 = xioctl (FD、VIDIOC_DQBUF、&buf)){
Perror ("队列缓冲区");
返回 false;
}
IDX = buf.index;

GstBuffer *缓冲区;
GstFlowReturn;
Buffer = GST_Buffer_new_allocate (NULL、FRAME_SIZE、NULL);

GstMapInfo 信息;
GST_buffer_map (buffer、&info、GST_MAP_WRITE);

unsigned char * buff = info.data;
memcpy (buff、buffer_addr[idx]、frame_size);
GST_buffer_unmap (buffer、&info);

g_signal_emit_by_name (app->appsrc、"push-buffer"、buffer、&ret);
printf ("ret:%d\n"、ret);
if (ret!= GST_flow_OK){
/*一些错误,停止发送数据*/
printf ("推送错误...\n");
返回 false;
}
GST_buffer_UNREF (buffer);


memset (&buf、0、sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO 捕捉;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = idx;
if (-1 = xioctl (FD、VIDIOC_QBUF、&buf)){
Perror ("队列缓冲区");
返回 false;
}
返回 true;
}


int xioctl (int fd、int request、void *arg)
{
内部 r;
do r = ioctl (fd、request、arg);
while (-1 = r && EINTR => errno);
返回 r;
}

int init_device (int fd){
unsigned int i;
struct v4l2_capability;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;

/*检查捕获设备*/
memset (&cap、0、sizeof (cap));

if (-1 = xioctl (FD、VIDIOC_QUERYCAP、&cap)){
Perror ("设置像素格式");
返回1;
}

printf ("驱动程序:%s\ncap:%8x"、caps.driver、caps.capabilities);
if (~caps.capabilities & V4L2_CAP_VIDEO 捕捉){
printf ("不是捕获设备");
返回1;
}

/*将捕捉格式设置为 UYVY */
memset (&fmt、0、sizeof (fmt));
FMT.TYPE = V4L2_BUF_TYPE_VIDEO 捕捉;
fmt.fmt.pix.width =宽度;
fmt.fmt.pix.height =高度;
fmt.fmt.pix.pixelformat = V4L2_PI_FMT_NV12;
//fmt.fmt.pix.pixelformat = V4L2_PI_FMT_UYVY;
fmt.fmt.pix.field = V4L2_field_none;
if (-1 = xioctl (FD、VIDIOC_S_FMT、&fmt)){
Perror ("设置像素格式");
返回1;
}

printf ("选定的摄像机模式:\n"宽度:%d\n"高度:%d\n"字段:%d"、
fmt.fmt.pix.width、fmt.fmt.pix.height、fmt.fmt.pix.field);
printf (" PixFmt =%c%c%c%c%c\n"、
fmt.fmt.pix.pixelformat 和0xFF、(fmt.fmt.pix.pixelformat >> 8)& 0xFF、
(fmt.fmt.pix.pixelformat >> 16)& 0xFF、(fmt.fmt.pix.pixelformat >> 24)&0xFF);

/*当前驱动程序仅支持 mmap 缓冲区
*请求内存映射缓冲区*/
memset (&req、0、sizeof (req));
REQ.COUNT = NBUF;
REQ.TYPE = V4L2_BUF_TYPE_VIDEO_CAPTURE;
REQ.MEMORY = V4L2_MEMORY_MMAP;

if (-1 = xioctl (FD、VIDIOC_REQBUFS、&req)){
perror ("请求缓冲区");
返回1;
}

printf ("总缓冲区 num %d\n"、req.count);
对于(i = 0;i < req.count;i++){
memset (&buf、0、sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO 捕捉;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = I;
if (-1 = xioctl (FD、VIDIOC_QUERYBUF、&buf)){
perror ("查询缓冲区");
返回1;
}

/*内存映射所有缓冲区并保存地址*/
Buffer_addr[i]= mmap (NULL、buf.length、PROT_read | PROT_WRITE、
map_shared、fd、buf.m.offset);
//buffer_addr[i]=(void*) malloc (frame_size);
size]= buf.length;
printf ("地址%p、大小%d、图像大小:%d \n"、buffer_addr[i]、buf.length、buf.bytesused);

/*为捕捉队列缓冲区*/
memset (&buf、0、sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO 捕捉;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = I;
if (-1 = xioctl (FD、VIDIOC_QBUF、&buf)){
Perror ("队列缓冲区");
返回1;
}
printf ("12345\r\n");
}

if (-1 = xioctl (FD、VIDIOC_STREAMON、&buf.type)){
Perror ("开始捕获");
返回1;
}

返回0;
}

void release_device (int fd)
{
int 类型= V4L2_BUF_TYPE_VIDEO 捕捉;
xioctl (FD、VIDIOC_STREAMOFF、&TYPE);
close (fd);
}


gboolean bus_call (GstBus *总线、GstMessage * msg、gpointer 数据)
{
GMainLoop * loop =(GMainLoop *)数据;
开关(GST_MESSAGE_TYPE (消息))
{
案例 GST_MESSAGE_EOS:
fprintf (stderr、"流结束\n");
G_MAIN_LOOP_QUIT (LOOP);
中断;

案例 GST_MESSAGE_ERROR:
{
gchar *调试;
GError *错误;
GST_MESSAGE_PART_ERROR (msg、&error、&DEBUG);
G_FREE (调试);
G_printerr ("错误:%s\n"、错误->消息);
G_ERROR_FREE (错误);
G_MAIN_LOOP_QUIT (LOOP);
中断;
}
默认值:
中断;
}
返回 true;
}

int main (int argc、char ** argv)
{
应用程序*app =&s_app;
printf ("=========== \n");
char devnode[100]="/dev/video1;

FD =开路(devnode、O_RDWR);
if (fd =-1){
perror ("正在打开视频设备");
返回1;
}

RET = INIT_DEVICE (FD);
如果(0!= ret){
printf ("正在退出");
返回 ret;
}

GST_init (NULL、NULL);
app->pipeline = gst_pipeline_new ("encodepipeline");
g_assert (app->pipeline);

app->appsrc = gst_elem_factory_make ("appsrc"、"srcElement");
g_assert (app->appsrc);

app->encode = gst_elem_factory_make ("ducatih264enc"、"srcElement);
g_assert (app->encode);

app->sink = gst_elem_factory_make ("filesink"、"sinkElement);
g_assert (app->sink);

printf ("元素创建成功\n");
GstCaps * capsappsrc2H264enc;
capsappsrc2H264enc = gst_caps_new_Simple ("video/x-raw)、
"format"、G_TYPE_string、"NV12"、
"宽度"、G_TYPE_INT、352、
"高度"、G_TYPE_INT、288、
"帧速率"、GST_TYPE_FRATE、30、1、
null);

GST_APP_SRC_SET_CAPs (GST_APP_SRC (APP->APPsrc)、capsappssrc2H264encc);
g_object_set (app->sink、"location"、"/mnt/camera.yuv、NULL);


app->loop = g_main_loop_new (NULL、false);
app->bus = gst_pipel_get_bus (gst_pipeline (app->pipeline));
app->bus_watch_id = gst_bus_add_watch (app->bus、bus_call、app->loop);
GST_OBJECT_UNREF (应用->总线);

gboolean bLinkOk;


//appsrc ->文件链接 gst_bin_add_many (gst_bin (app->pipeline)、app->appsrc、app->sink、NULL); bLinkOk= GST_Element _link (app->appsrc、app->sink); if (!bLinkOk){ g_warning ("链接多个1\n"失败); 返回-5; } //appsrc -> ducatih264enc ->文件链接 // gst_bin_add_many (gst_bin (app->pipeline)、app->appsrc、app->encode、app->sink、NULL); // bLinkOk= GST_Element _link (app->appsrc、app->encode、app->sink); // if (!bLinkOk){ // g_warning ("链接多个1\n"失败); // 返回-5; //} g_signal_connect (app->appsrc、"need-data"、g_callback (feed_data)、app); GST_ELECK_SET_STATE (APP->管线、GST_STATE_Playing); printf ("run...1\n"); g_main_loop_run (app->loop); printf ("run...2\n"); APP->MSG = GST_BUST_TIME_POP_FILTERED (APP->BUS、GST_CLOCK _TIME_NONE、GST_MESSAGE_ERROR | GST_MESSAGE_EOS); if (app->msg!=空) GST_MESSAGE_UNREF (APP->msg); GST_OBJECT_UNREF (APP->bus); GST_ELECK_SET_STATE (APP->管线、GST_STATE_NULL); GST_OBJECT_UNREF (APP->管线); GST_object_UNREF (app->appsrc); GST_OBJECT_UNREF (APP->Sink); printf ("close...\n"); 返回0; }