amlogic播放h264我一份代码
时间: 2023-06-11 10:07:05 浏览: 183
以下是使用Amlogic SoC播放H.264视频的示例代码:
```C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "amvideocap.h"
// 视频设备名称
#define DEVICE_NAME "/dev/video0"
int main(int argc, char *argv[])
{
int fd, ret;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
void *buffer_start[4];
size_t buffer_length[4];
size_t num_buffers;
int i, j;
char *filename = NULL;
int frame_count = 0;
if (argc < 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
filename = argv[1];
// 打开视频设备
fd = open(DEVICE_NAME, O_RDWR);
if (fd == -1) {
fprintf(stderr, "Failed to open device: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 查询设备能力
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret == -1) {
fprintf(stderr, "Failed to query capability: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 检查设备是否支持视频捕捉
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr, "Device does not support video capture\n");
exit(EXIT_FAILURE);
}
// 检查设备是否支持H.264编码
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
fprintf(stderr, "Device does not support multiplanar video capture\n");
exit(EXIT_FAILURE);
}
// 设置视频格式
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.width = 1920; // 视频宽度
fmt.fmt.pix_mp.height = 1080; // 视频高度
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; // 视频编码格式
fmt.fmt.pix_mp.num_planes = 1; // 每帧数据平面数
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret == -1) {
fprintf(stderr, "Failed to set format: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 请求视频缓冲区
memset(&req, 0, sizeof(req));
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
req.memory = V4L2_MEMORY_MMAP;
req.count = 4;
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
if (ret == -1) {
fprintf(stderr, "Failed to request buffers: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
num_buffers = req.count;
// 映射视频缓冲区
for (i = 0; i < num_buffers; i++) {
struct v4l2_plane planes[1];
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
memset(&planes, 0, sizeof(planes));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
buf.m.planes = planes;
buf.length = 1;
ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
if (ret == -1) {
fprintf(stderr, "Failed to query buffer %d: %s\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
buffer_length[i] = buf.m.planes[0].length;
buffer_start[i] = mmap(NULL, buffer_length[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[0].m.mem_offset);
if (buffer_start[i] == MAP_FAILED) {
fprintf(stderr, "Failed to mmap buffer %d: %s\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
}
// 将视频缓冲区入队
for (i = 0; i < num_buffers; i++) {
struct v4l2_plane planes[1];
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
memset(&planes, 0, sizeof(planes));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
buf.m.planes = planes;
buf.length = 1;
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if (ret == -1) {
fprintf(stderr, "Failed to queue buffer %d: %s\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
}
// 启动视频捕获
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
ret = ioctl(fd, VIDIOC_STREAMON, &type);
if (ret == -1) {
fprintf(stderr, "Failed to start streaming: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 打开输出文件
int output_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (output_fd == -1) {
fprintf(stderr, "Failed to open output file: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 循环获取视频帧数据并写入输出文件
while (frame_count < 100) {
// 从视频缓冲区取出一帧数据
memset(&buf, 0, sizeof(buf));
memset(&buf.m, 0, sizeof(buf.m));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if (ret == -1) {
fprintf(stderr, "Failed to dequeue buffer: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 将帧数据写入输出文件
size_t bytes_written = write(output_fd, buffer_start[buf.index], buffer_length[buf.index]);
if (bytes_written != buffer_length[buf.index]) {
fprintf(stderr, "Failed to write frame to output file: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 将视频缓冲区重新入队
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if (ret == -1) {
fprintf(stderr, "Failed to queue buffer: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
frame_count++;
}
// 停止视频捕获
ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
if (ret == -1) {
fprintf(stderr, "Failed to stop streaming: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 关闭视频设备
close(fd);
// 关闭输出文件
close(output_fd);
// 释放视频缓冲区
for (i = 0; i < num_buffers; i++) {
munmap(buffer_start[i], buffer_length[i]);
}
exit(EXIT_SUCCESS);
}
```
这段代码使用V4L2接口与Amlogic SoC的视频设备进行交互,从视频设备中获取H.264编码的视频帧数据,并将其写入文件中。
阅读全文