请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号: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;
}