当前位置: 首页 > news >繁体>v4l2解码调用流程

v4l2解码调用流程

最近在学习v4l2codec,下面把学习心得总结一下,说明一点,这里不讲解v4l2,主要介绍应用层如何调用写案例,相关v4l2请看:
1、深入理解v4l2buf
2、V4L2学习资料收集
3、V4L2学习笔记

这个案例中,是V4L2_MEMORY_MMAP方式分配内存。

流程:

  • 设置输入端口的格式
  • 设置输出端口的格式
  • 枚举输入端口buf数量
  • map输入端口的buf(while循环)
  • 枚举输出端口的buf数量
  • map输出端口的buf(while循环)
  • 输出端口buf入队
  • stream on(输入和输出)
  • 输入数据入队
  • 循环从v4l2中取出已经解码后的数据,并且把空的buf送入v4l2(输出端口)
  • 循环从v4l2中取出已经消耗的buf,重新填充buf后送入v4l2

说明,下面代码是一次性把输入读取完,送入到了v4l2,实际情况下,我们并不是这样,而是循环送入,具体可以看这个案例:
入口
具体代码如下:

// #include <linux/videodev2.h>
// #include <cstdint>
#include "common.h"//
// ======== comm =======
int mem_type = V4L2_MEMORY_MMAP;
#define INPUT_BUF_NUM (2)
#define OUTPUT_BUF_NUM (5)
#define BS_BUF_SIZE (1 << 20)// ======== in =======
int                in_fourcc   = V4L2_PIX_FMT_H264;
enum v4l2_buf_type in_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;struct v4l2_format in_format;
struct v4l2_buffer in_buffer_arr[INPUT_BUF_NUM];
struct v4l2_plane  in_buf_planes[INPUT_BUF_NUM][VIDEO_MAX_PLANES];
char *             in_user_ptr[INPUT_BUF_NUM][8];// ======== out =======
int                out_fourcc   = V4L2_PIX_FMT_YUV420M;
enum v4l2_buf_type out_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;struct v4l2_format out_format;
struct v4l2_buffer out_buffer_arr[OUTPUT_BUF_NUM];
struct v4l2_plane  out_buf_planes[OUTPUT_BUF_NUM][VIDEO_MAX_PLANES];
char *             out_user_ptr[OUTPUT_BUF_NUM][8];// =============================================int ioctl_handler(int fd, int req, void *data) {DBG_SHOW_FUNC;int ret = ioctl(fd, req, data);if (0 != ret) {LOG("=====> IOCTL ERROR, req = %08x\n", req);}return ret;
}int ioc_set_ctrl(int fd, int id, int val) {DBG_SHOW_FUNC;int                 ret = 0;struct v4l2_control ctrl;memset(&ctrl, 0, sizeof(ctrl));ctrl.id    = id;ctrl.value = val;ret = ioctl_handler(fd, VIDIOC_S_CTRL, &ctrl);return ret;
}int get_format(int fd, struct v4l2_format *fmt, enum v4l2_buf_type buf_type) {DBG_SHOW_FUNC;fmt->type = buf_type;return ioctl_handler(fd, VIDIOC_G_FMT, fmt);
}int set_format(int fd, struct v4l2_format *fmt) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_S_FMT, fmt);
}int try_format(int fd, struct v4l2_format *fmt) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_TRY_FMT, fmt);
}int req_buffers(int fd, struct v4l2_requestbuffers *reqbuf) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_REQBUFS, reqbuf);
}int query_buffer(int fd, struct v4l2_buffer *buf) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_QUERYBUF, buf);
}int queue_buffer(int fd, struct v4l2_buffer *buf) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_QBUF, buf);
}int dequeue_buffer(int fd, struct v4l2_buffer *buf) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_DQBUF, buf);
}int stream_on(int fd, enum v4l2_buf_type *type) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_STREAMON, type);
}int stream_off(int fd, enum v4l2_buf_type *type) {DBG_SHOW_FUNC;return ioctl_handler(fd, VIDIOC_STREAMOFF, type);
}int get_output_picture(int fd, int pic_idx) {DBG_SHOW_FUNC;int ret = 0;struct v4l2_buffer buf;struct v4l2_plane  planes[8];buf.m.planes = planes;buf.type     = out_buf_type;buf.memory   = mem_type;buf.length   = 3;ret = dequeue_buffer(fd, &buf);if (0 != ret) {LOG("ERROR: no more output picture\n");return -1;}out_buffer_arr[buf.index] = buf;if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) {out_buffer_arr[buf.index].m.planes = out_buf_planes[buf.index];for (size_t i = 0; i < out_buffer_arr[buf.index].length; ++i) {out_buffer_arr[buf.index].m.planes[i] = buf.m.planes[i];}}return buf.index;
}int map_memory(int fd, struct v4l2_buffer *buf, void *user_ptr[8]) {if (V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {for (int i = 0; i < buf->length; ++i) {struct v4l2_plane *p = &buf->m.planes[i];if (p->length > 0) {user_ptr[i] = mmap(NULL, p->length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, p->m.mem_offset);if (user_ptr[i] == MAP_FAILED) {LOG("====== Failed to mmap multi plane memory");return -1;}}}} else {if (buf->length > 0) {user_ptr[0] =mmap(NULL, buf->length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf->m.offset);if (user_ptr[0] == MAP_FAILED) {LOG("============= Failed to mmap single plane memory");return -2;}}}
}void show_buffer_info(struct v4l2_buffer *p) {LOG("======= v4l2_buffer =====\n");LOG("index:             %d\n", p->index);LOG("type:              %d\n", p->type);LOG("bytesused:         %d\n", p->bytesused);LOG("flags:             0x%08x\n", p->flags);LOG("timeval sec:       %ld\n", p->timestamp.tv_sec);LOG("timeval usec:      %ld\n", p->timestamp.tv_usec);LOG("timecode type:     %d\n", p->timecode.type);LOG("timecode flags:    0x%08x\n", p->timecode.flags);LOG("timecode frames:   %d\n", p->timecode.frames);LOG("timecode seconds:  %d\n", p->timecode.seconds);LOG("timecode minutes:  %d\n", p->timecode.minutes);LOG("timecode hours:    %d\n", p->timecode.hours);LOG("timecode userbits: %d\n", (uint32_t)p->timecode.userbits);LOG("sequence:          %d\n", p->sequence);LOG("length:            %d\n", p->length);LOG("reserved2:         %08x\n", p->reserved2);
}int init_decoder(int fd) {int ret = 0;DBG_SHOW_FUNC;//// set naul formatioc_set_ctrl(fd, V4L2_CID_MVE_VIDEO_NALU_FORMAT, V4L2_OPT_NALU_FORMAT_START_CODES);// set format{LOG("=========== H264 format ============\n");int w = 0, h = 0;ret = get_format(fd, &in_format, in_buf_type);struct v4l2_pix_format *f = &in_format.fmt.pix;f->pixelformat  = in_fourcc;f->width        = w;f->height       = h;f->bytesperline = 0;f->sizeimage    = (1 << 20);f->field        = V4L2_FIELD_NONE;ret = try_format(fd, &in_format);w   = f->width;h   = f->height;LOG("After try_format, w = %d, h = %d\n", w, h);ret = set_format(fd, &in_format);}{LOG("============YUV420 format ==========\n");int w = 0, h = 0;ret = get_format(fd, &out_format, out_buf_type);struct v4l2_pix_format_mplane *f = &out_format.fmt.pix_mp;f->pixelformat = out_fourcc;f->width       = w;f->height      = h;f->num_planes  = 3;f->field       = V4L2_FIELD_NONE;ret = try_format(fd, &out_format);w   = f->width;h   = f->height;LOG("After try_format, w = %d, h = %d\n", w, h);ret = set_format(fd, &out_format);}// enum frame sizes{// alloc buffersstruct v4l2_requestbuffers reqbuf;reqbuf.count  = 1;reqbuf.type   = in_buf_type;reqbuf.memory = mem_type;ret = req_buffers(fd, &reqbuf);LOG("=======> bitstream buffer count : %d\n", reqbuf.count);for (int i = 0; i < reqbuf.count; ++i) {in_buffer_arr[i].type     = in_buf_type;in_buffer_arr[i].memory   = mem_type;in_buffer_arr[i].m.planes = in_buf_planes[i];in_buffer_arr[i].index    = i;in_buffer_arr[i].length   = 3;ret = query_buffer(fd, &in_buffer_arr[i]);if (V4L2_MEMORY_MMAP == mem_type) {ret = map_memory(fd, &in_buffer_arr[i], in_user_ptr[i]);}}struct v4l2_requestbuffers reqbuf_out;reqbuf_out.count  = OUTPUT_BUF_NUM;reqbuf_out.type   = out_buf_type;reqbuf_out.memory = mem_type;ret = req_buffers(fd, &reqbuf_out);LOG("=======> output yuv buffer count : %d\n", reqbuf.count);for (int i = 0; i < reqbuf_out.count; ++i) {out_buffer_arr[i].type     = out_buf_type;out_buffer_arr[i].memory   = mem_type;out_buffer_arr[i].m.planes = out_buf_planes[i];out_buffer_arr[i].index    = i;out_buffer_arr[i].length   = 3;ret = query_buffer(fd, &out_buffer_arr[i]);if (V4L2_MEMORY_MMAP == mem_type) {ret = map_memory(fd, &out_buffer_arr[i], out_user_ptr[i]);}}}// queue bufferfor (int i = 0; i < OUTPUT_BUF_NUM; ++i) {// remove vendor custom flags.out_buffer_arr[i].flags &= ~V4L2_BUF_FLAG_MVX_MASK;// mask buffer offsetif (!V4L2_TYPE_IS_MULTIPLANAR(out_buffer_arr[i].type) &&V4L2_MEMORY_MMAP == out_buffer_arr[i].memory) {out_buffer_arr[i].m.offset &= ~((1 << 12) - 1);}ret = queue_buffer(fd, &out_buffer_arr[i]);}// stream onstream_on(fd, &in_buf_type);stream_on(fd, &out_buf_type);return ret;
}int decode_file(int fd, const char *bs_filename) {DBG_SHOW_FUNC;int ret = 0;// init decoderret = init_decoder(fd);// input bs data{FILE *pbs_file = fopen(bs_filename, "wb");if (!pbs_file) {LOG("ERROR: can not open bs file: %s\n", bs_filename);}// read datafseek(pbs_file, 0, SEEK_END);int bs_len = ftell(pbs_file);fseek(pbs_file, 0, SEEK_SET);// char *bs_data  = malloc(bs_len * sizeof(char));//in_buffer_arr[0].flags = 0;LOG("bs data len: %d, bs_buf size: %d", bs_len, in_buffer_arr[0].length);int read_len = fread(in_user_ptr[0], sizeof(char), bs_len, pbs_file);LOG("read bs len : %d, bs buf size: %d\n", read_len, in_buffer_arr[0].length);//in_buffer_arr[0].bytesused = read_len;in_buffer_arr[0].flags |= V4L2_BUF_FLAG_LAST;if (pbs_file) {fclose(pbs_file);}// queueret = queue_buffer(fd, &in_buffer_arr[0]);}// get output picture{//int   buf_idx = 0;  // out_buffer_arr indexint   pic_idx = 0;FILE *out_pic = fopen("out.yuv", "wb");do {buf_idx = get_output_picture(fd, pic_idx);// handle output picturestruct v4l2_buffer *p        = &out_buffer_arr[buf_idx];char *              user_ptr = out_user_ptr[buf_idx];show_buffer_info(p);for (int i = 0; i < p->length; ++i) {struct v4l2_plane *plane = &p->m.planes;char *pl     = user_ptr[i] + plane->data_offset;int   len    = plane->bytesused - plane->data_offset;int   wr_len = fwrite(pl, 1, len, out_pic);}pic_idx++;// check last output picture} while (-1 != buf_idx);if (out_pic) {fclose(out_pic);}}// stream offstream_off(fd, &in_buf_type);stream_off(fd, &out_buf_type);return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-4.html

如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网进行投诉反馈,一经查实,立即删除!


相关文章:

  • 【算法】妙不可言---贪心算法
  • linux下使用apache+svn+ssl配置安全版本控制平台
  • JVM-内存结构