gstreamer1.0用appsrc元件抓取fb0节点RGB图像进行视频h264编码

最近接到的一个任务是,利用gstreamer1.0抓取framebuffer的fb0设备的RGB图像数据,进行h264编码,然后再转换为MP4视频;硬件平台式imx6qdl,内含IPU与VPU硬件,Linux内核版本是yocto project 4.1.15。

IPU:将RGB数据转为YUV格式,因为VPU只能接收YUV格式数据转换为H264

VPU:将YUV格式的数据转换为H264码流

关于gstreamer的概念,这里就不在详述,可以参考其开发手册与官网实例。尤其比较有用的工具是gst-inspect-1.0可以查看gstreamer所有的元件elements,或者gst-inspect-1.0 后跟元件名称,可以单独查看某一元件的详细信息。另外可以使用gst-lanuch-1.0工具,先进行测试,例如:

gst-launch-1.0ximagesrc remote=1 use-damage=0 ! video/x-raw,framerate=25/1 !videoconvert ! vp8enc ! matroskamux ! filesink location=/home/luke/test.mkv

可以实现在ubuntu16.04上进行录屏

根据应用需求,需要使用gstreamer1.0的appsrc、imxvideoconvert_ipu、vpuenc_h264、appsink、filesink、mp4mux共6个元件。现将RGB转为H264码,在PC上使用ffmpeg 工具进行转换测试;转换命令:ffmpeg -f h264 -i test_15x30.h264 -vcodec copy test_15x30.mp4代码如下:

#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <signal.h>

typedef struct _GstDataStruct{
    GstElement *pipeline;
    GstElement *app_source;
    GstElement *video_convert;
    GstElement *auto_video_convert;
    GstElement *h264_encoder;
    GstElement *jpgenc;
    GstElement *mp4mux;
    GstElement *file_sink;
    GstElement *app_sink;
    guint sourceid;        /* To control the GSource */
    guint app_src_index;
    guint app_sink_index;
    GMainLoop *loop;  /* GLib's Main Loop */
} GstDataStruct;

typedef struct
{
    struct fb_var_screeninfo vinfo;	        // 可变的显示屏幕信息
    int width;				// width 宽度
    int height;				// height 高度
    int bpp;				// bit per pixel 像素的位数
    int rowsize;				// 屏幕一行所占字节数
    int real_len;				// 实际显示区域的字节数
    int total_len;				// 显示区域总字节数,即长度
    int offset;				// 实际显示位置在总长度中的偏移量
    int fd;					// 打开fb节点时的文件句柄
    void* data;				// fb0 节点内存映射后数据指针
}FbInfoStruct;

static void new_h264_sample_on_appsink (GstElement *sink, GstDataStruct *pGstData);
static void eos_on_appsink (GstElement *sink, GstDataStruct *pGstData);
static gboolean read_data(GstDataStruct *pGstData);
static void start_feed (GstElement * pipeline, guint size, GstDataStruct *pGstData);
static void stop_feed (GstElement * pipeline, GstDataStruct *pGstData);
gboolean bus_msg_call(GstBus *bus, GstMessage *msg, GstDataStruct *pGstData);

static FILE *fp;			// 打开或保存文件的的指针
static GstBus *bus;
static GstDataStruct GstData;
static FbInfoStruct FbInfo;
int main(int argc, char *argv[])
{
    guint bus_watch_id;
    char file_name[32];
    int frame_rate = 10;
    int gop_size = 30;
    if(argc == 3)
    {
        frame_rate = atoi(argv[1]);
        gop_size = atoi(argv[2]);
    }
    memset (file_name, 0, sizeof(file_name));
    sprintf(file_name, "%s", "/home/root/test_");
    file_name[16] = frame_rate/10 + 0x30;
    file_name[17] = frame_rate%10 + 0x30;
    file_name[18] = 'x';
    file_name[19] = gop_size/10 + 0x30;
    file_name[20] = gop_size%10 + 0x30;
    file_name[21] = '.';
    file_name[22] = 'h';
    file_name[23] = '2';
    file_name[24] = '6';
    file_name[25] = '4';
    printf("file name is :%s\n", file_name);
    printf("frame_rate:%d gop-size:%d\n", frame_rate, gop_size);
    fp = fopen(file_name, "wb");
    if(!fp)
    {
        printf("can not open file %s", file_name);
        return -1;
    }
    printf("================ imx60 360 main start ==============\n");
    memset (&GstData, 0, sizeof (GstDataStruct));
    memset (&FbInfo, 0, sizeof (FbInfoStruct));
    printf("=========== imx60 360 get fb0 info start ===========\n");
    FbInfo.fd = open("/dev/fb0", O_RDWR);
    ioctl(FbInfo.fd, FBIOGET_VSCREENINFO, &FbInfo.vinfo);

    FbInfo.width = FbInfo.vinfo.xres;
    FbInfo.height = FbInfo.vinfo.yres;
    FbInfo.bpp = FbInfo.vinfo.bits_per_pixel;
    FbInfo.rowsize = FbInfo.width * (FbInfo.bpp >> 3);
    FbInfo.offset = FbInfo.rowsize * FbInfo.vinfo.yoffset;
    FbInfo.total_len = FbInfo.vinfo.xres_virtual * FbInfo.vinfo.yres_virtual * (FbInfo.bpp >> 3);
    FbInfo.real_len = FbInfo.width * FbInfo.height * (FbInfo.bpp >> 3);
    FbInfo.data = mmap (NULL, FbInfo.total_len, PROT_READ | PROT_WRITE, MAP_SHARED, FbInfo.fd, 0);
    printf("================= var screen info =================\n");
    printf("  sz  [%d x %d] %d\n", FbInfo.width, FbInfo.height, FbInfo.bpp);
    printf("  vsz [%d x %d]\n", FbInfo.vinfo.xres_virtual, FbInfo.vinfo.yres_virtual);
    printf("  pan     : (%d, %d)\n", FbInfo.vinfo.xoffset, FbInfo.vinfo.yoffset);
    printf("  off     : %d\n", FbInfo.offset);
    printf("  map     : %p\n", FbInfo.data);
    printf("============ imx60 360 get fb0 info end ===========\n");

    /* Initialize cumstom data structure
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值