参考esp_video中的例程image_storage/usb_msc,实现2个功能,功能如下:
F1、H.264视频录取并封装成MP4文件
F2、抓拍照片生成JPG格式文件
参数:
camera sensor: OV5647
采集分辨率:1920x1080
帧率:30fps
问题描述:
1、在运行过程中动态切换F1和F2功能,当完成F2功能之后,启动F1时,会报错,报错位置:esp_h264_enc_hw_new_param->"No memory for handle",根据描述是无法申请内存
2、由于功能F1 和 F2分别使用H.264和MJPEG进行编码,2种编码器是否会占用很大资源
3、当一直执行同一个功能时,不会出现问题1的报错。
每次启动都会配置代码
Code: Select all
int type;
struct v4l2_buffer buf;
struct v4l2_format format;
struct v4l2_requestbuffers req;
uint32_t capture_fmt = 0;
ESP_LOGD(TAG, "video start");
if(video)
{
// init_h264_codec_video(cb_ctx);
cb_ctx->format = V4L2_PIX_FMT_H264;
}
else
{
// init_jpeg_codec_video(cb_ctx);
cb_ctx->format = V4L2_PIX_FMT_JPEG;
}
if (cb_ctx->format == V4L2_PIX_FMT_JPEG) {
int fmt_index = 0;
const uint32_t jpeg_input_formats[] = {
V4L2_PIX_FMT_RGB565,
V4L2_PIX_FMT_YUV422P,
V4L2_PIX_FMT_RGB24,
V4L2_PIX_FMT_GREY
};
int jpeg_input_formats_num = sizeof(jpeg_input_formats) / sizeof(jpeg_input_formats[0]);
while (!capture_fmt) {
struct v4l2_fmtdesc fmtdesc = {
.index = fmt_index++,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
};
if (ioctl(cb_ctx->cap_fd, VIDIOC_ENUM_FMT, &fmtdesc) != 0) {
break;
}
for (int i = 0; i < jpeg_input_formats_num; i++) {
if (jpeg_input_formats[i] == fmtdesc.pixelformat) {
capture_fmt = jpeg_input_formats[i];
break;
}
}
}
if (!capture_fmt) {
ESP_LOGI(TAG, "The camera sensor output pixel format is not supported by JPEG");
return ESP_ERR_NOT_SUPPORTED;
}
} else {
capture_fmt = V4L2_PIX_FMT_YUV420;
}
ESP_LOGI(TAG,"capture fmt :%x",capture_fmt);
/* Configure camera interface capture stream */
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = capture_fmt;
ESP_ERROR_CHECK(ioctl(cb_ctx->cap_fd, VIDIOC_S_FMT, &format));
memset(&req, 0, sizeof(req));
req.count = BUFFER_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ESP_ERROR_CHECK(ioctl(cb_ctx->cap_fd, VIDIOC_REQBUFS, &req));
for (int i = 0; i < BUFFER_COUNT; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ESP_ERROR_CHECK(ioctl(cb_ctx->cap_fd, VIDIOC_QUERYBUF, &buf));
cb_ctx->cap_buffer[i] = (uint8_t *) mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED, cb_ctx->cap_fd, buf.m.offset);
assert(cb_ctx->cap_buffer[i]);
ESP_ERROR_CHECK(ioctl(cb_ctx->cap_fd, VIDIOC_QBUF, &buf));
}
/* Configure codec output stream */
if(!video)
{
ESP_ERROR_CHECK(set_codec_control(cb_ctx->jpeg_fd,V4L2_CID_JPEG_CLASS, V4L2_CID_JPEG_COMPRESSION_QUALITY, compress));
}
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = capture_fmt;
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_S_FMT, &format));
memset(&req, 0, sizeof(req));
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
req.memory = V4L2_MEMORY_USERPTR;
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_REQBUFS, &req));
/* Configure codec capture stream */
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = width;
format.fmt.pix.height = height;
format.fmt.pix.pixelformat = cb_ctx->format;
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_S_FMT, &format));
memset(&req, 0, sizeof(req));
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_REQBUFS, &req));
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_QUERYBUF, &buf));
cb_ctx->m2m_cap_buffer = (uint8_t *) mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED, video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, buf.m.offset);
assert(cb_ctx->m2m_cap_buffer);
ESP_ERROR_CHECK(ioctl(video?cb_ctx->m2m_fd:cb_ctx->jpeg_fd, VIDIOC_QBUF, &buf));
1、反复切换不同编码器是否可行
2、如果都使用H.264编码器进行输出,如何将CAM采集的YUV420帧转换成MJPEG实现拍照(曾经将CAM采集的YUV420保存输出,发现无法在电脑端正确转换出图片,是否是其他格式)