dav文件用什么播放器可以打开软件能打开H.264

本文讲述如何在linux下,使用ffmpeg采集视频数据,并编码成h264文件。打算分成3部分讲解:需要具备的软硬件环境ffmpeg命令采集摄像头数据并编码成h264文件ffmpeg代码采集摄像头数据并编码成h264文件需要具备的软硬件环境需要具备的硬件环境,摄像头。我这里是一个usb 摄像头。需要具备的软件环境,ffmpeg,并且启用了libx264编码的ffmpeg。假如是自己编译的ffmpeg,在configure 的时候,需要添加上参数“–enable-libx264”,我在这中间遇到了一些问题,老是找不到libx264编码器。后面做了2个操作,才完成的。删除了原来老的ffmpeg(自己通过apt install安装的),及其相关的库(libavcodec等)。自己安装了libx264-dev。然后configure 的时候加上了"–enable-libx264"参数,最后编译安装完成的。ffmpeg命令采集摄像头数据并编码成h264文件ffmpeg -f video4linux2 -i "/dev/video0" -vcodec libx264 -pix_fmt yuv420p mycamera.h264
使用上述命令,可以采集摄像头数据,并编码成h264文件。下面详细讲解一下这些参数。-f video4linux2,表示采用video4linux2驱动程序。-i “/dev/video0”,表示输入数据的地址是“/dev/video0”,这个设备地址,就是我们的摄像头设备地址。-vcodec libx264,表示采用libx264编解码器。-pix_fmt yuv420p,表示编码的数据采用yuv420p。mycamera.h264,这个就是我们最终的编码好的h264数据。然后使用命令播放一下,看看效果,没问题。ffplay mycamera.h264
ffmpeg代码采集摄像头数据并编码成h264文件分成几个部分,说明采集摄像头并编码成h264文件的过程。打开设备打开编码器采集摄像头数据,为yuyv422格式转换摄像头数据,从yuyv422转成yuv420p编码yuv420p数据为h264数据,并写成文件打开设备
// ctx
AVFormatContext *fmt_ctx = NULL;
AVDictionary *options = NULL;
char *devicename = "/dev/video0";
// register audio device
avdevice_register_all();
// get format
AVInputFormat *iformat = av_find_input_format("video4linux2");
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "pixel_format", "yuyv422", 0);
// open device
avformat_open_input(&fmt_ctx, devicename, iformat, &options);
这个,我们做了3件事,来打开设备:使用video4linux2这个驱动指定了设备路径为/dev/video0指定了一些参数,video_size, framerate, pixel_format最后,使用avformat_open_input来打开设备。打开编码器
AVCodec *codec = NULL;
codec = avcodec_find_encoder_by_name("libx264");
AVCodecContext **enc_ctx = NULL;
*enc_ctx = avcodec_alloc_context3(codec);
// SPS/PPS
(*enc_ctx)->profile = FF_PROFILE_H264_HIGH_444;
(*enc_ctx)->level = 50; //表示LEVEL是5.0
//设置分辫率
(*enc_ctx)->width = width;
// 640
(*enc_ctx)->height = height; // 480
// GOP
(*enc_ctx)->gop_size = 250;
(*enc_ctx)->keyint_min = 25; // option
//设置B帧数据
(*enc_ctx)->max_b_frames = 3; // option
(*enc_ctx)->has_b_frames = 1; // option
//参考帧的数量
(*enc_ctx)->refs = 3; // option
//设置输入YUV格式
(*enc_ctx)->pix_fmt = AV_PIX_FMT_YUV420P;
//设置码率
(*enc_ctx)->bit_rate = 600000; // 600kbps
//设置帧率
(*enc_ctx)->time_base = (AVRational){1, 30}; //帧与帧之间的间隔是time_base
(*enc_ctx)->framerate = (AVRational){30, 1}; //帧率,每秒 30帧
avcodec_open2((*enc_ctx), codec, NULL);
这里,也主要做了3件事:avcodec_find_encoder_by_name找到libx264这个编码器。给编码器开辟了一个 编码器上下文,avcodec_alloc_context3,并对这个上下文设置了一些参数。这都是我们编码需要使用的参数。使用avcodec_open2打开了编码器。采集摄像头数据
AVPacket pkt;
while ( av_read_frame(fmt_ctx, &pkt) == 0) {
int i = 0;
av_log(NULL, AV_LOG_INFO, "packet size is %d(%p)\n", pkt.size,
pkt.data);
}
这个采集数据,只需要拿着第一步打开的设备上下文,传递给av_read_frame进行数据读取,就可以了。转换摄像头数据,从yuyv422转成yuv420void yuyv422ToYuv420p(AVFrame *frame, AVPacket *pkt) {
int i = 0;
int yuv422_length = V_WIDTH * V_HEIGHT * 2;
int y_index = 0;
// copy all y
for (i = 0; i < yuv422_length; i += 2) {
frame->data[0][y_index] = pkt->data[i];
y_index++;
}
// copy u and v
int line_start = 0;
int is_u = 1;
int u_index = 0;
int v_index = 0;
// copy u, v per line. skip a line once
for (i = 0; i < V_HEIGHT; i += 2) {
// line i offset
line_start = i * V_WIDTH * 2;
for (int j = line_start + 1; j < line_start + V_WIDTH * 2; j += 4) {
frame->data[1][u_index] = pkt->data[j];
u_index++;
frame->data[2][v_index] = pkt->data[j + 2];
v_index++;
}
}
}
我这里,摄像头读取的yuyv422存储在AVPacket中,然后将他转换成yuv420p,存放到AVFrame中。其中AVFrame的data[0]存放y数据,data[1]存放u数据,data[2]存放v数据。至于yuyv422和yuv420的存储方式,这里就不讲了,网上能搜索到的。编码并保存为文件static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *newpkt,
FILE *outfile) {
int ret = 0;
if (frame) {
printf("send frame to encoder, pts=%lld", frame->pts);
}
//送原始数据给编码器进行编码
ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
printf("Error, Failed to send a frame for enconding!\n");
exit(1);
}
//从编码器获取编码好的数据
while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, newpkt);
//如果编码器数据不足时会返回
EAGAIN,或者到数据尾时会返回 AVERROR_EOF
if (ret == AVERROR(EAGAIN)
ret == AVERROR_EOF) {
return;
} else if (ret < 0) {
printf("Error, Failed to encode!\n");
exit(1);
}
fwrite(newpkt->data, 1, newpkt->size, outfile);
fflush(outfile);
av_packet_unref(newpkt);
}
}
编码的话,主要通过2个步骤完成:avcodec_send_frame,将需要编码的AVFrame数据(就是上一步骤拿到的yuv420p的AVFrame数据),送给编码器。avcodec_receive_packet,将编码好的AVPacket数据,读取出来,并保存文件。全部代码#include <string.h>
#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#define V_WIDTH 640
#define V_HEIGHT 480
//@brief
// return
static AVFormatContext *open_dev() {
int ret = 0;
char errors[1024] = {
0,
};
// ctx
AVFormatContext *fmt_ctx = NULL;
AVDictionary *options = NULL;
//摄像头的设备文件
char *devicename = "/dev/video0";
// register video device
avdevice_register_all();
// get format
AVInputFormat *iformat = av_find_input_format("video4linux2");
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "pixel_format", "yuyv422", 0);
// open device
ret = avformat_open_input(&fmt_ctx, devicename, iformat, &options);
if (ret < 0) {
av_strerror(ret, errors, 1024);
fprintf(stderr, "Failed to open video device, [%d]%s\n", ret, errors);
return NULL;
}
return fmt_ctx;
}
static void open_encoder(int width, int height, AVCodecContext **enc_ctx) {
int ret = 0;
AVCodec *codec = NULL;
avcodec_register_all();
codec = avcodec_find_encoder_by_name("libx264");
if (!codec) {
printf("Codec libx264 not found\n");
exit(1);
}
*enc_ctx = avcodec_alloc_context3(codec);
if (!enc_ctx) {
printf("Could not allocate video codec context!\n");
exit(1);
}
// SPS/PPS
(*enc_ctx)->profile = FF_PROFILE_H264_HIGH_444;
(*enc_ctx)->level = 50; //表示LEVEL是5.0
//设置分辫率
(*enc_ctx)->width = width;
// 640
(*enc_ctx)->height = height; // 480
// GOP
(*enc_ctx)->gop_size = 250;
(*enc_ctx)->keyint_min = 25; // option
//设置B帧数据
(*enc_ctx)->max_b_frames = 3; // option
(*enc_ctx)->has_b_frames = 1; // option
//参考帧的数量
(*enc_ctx)->refs = 3; // option
//设置输入YUV格式
(*enc_ctx)->pix_fmt = AV_PIX_FMT_YUV420P;
//设置码率
(*enc_ctx)->bit_rate = 600000; // 600kbps
//设置帧率
(*enc_ctx)->time_base = (AVRational){1, 30}; //帧与帧之间的间隔是time_base
(*enc_ctx)->framerate = (AVRational){30, 1}; //帧率,每秒 30帧
ret = avcodec_open2((*enc_ctx), codec, NULL);
if (ret < 0) {
printf("Could not open codec: %s!\n", av_err2str(ret));
exit(1);
}
}
static AVFrame *create_frame(int width, int height) {
int ret = 0;
AVFrame *frame = NULL;
frame = av_frame_alloc();
if (!frame) {
printf("Error, No Memory!\n");
goto __ERROR;
}
//设置参数
frame->width = width;
frame->height = height;
frame->format = AV_PIX_FMT_YUV420P;
// alloc inner memory
ret = av_frame_get_buffer(frame, 32); //按 32 位对齐
if (ret < 0) {
printf("Error, Failed to alloc buffer for frame!\n");
goto __ERROR;
}
return frame;
__ERROR:
if (frame) {
av_frame_free(&frame);
}
return NULL;
}
static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *newpkt,
FILE *outfile) {
int ret = 0;
if (frame) {
printf("send frame to encoder, pts=%lld", frame->pts);
}
//送原始数据给编码器进行编码
ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
printf("Error, Failed to send a frame for enconding!\n");
exit(1);
}
//从编码器获取编码好的数据
while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, newpkt);
//如果编码器数据不足时会返回
EAGAIN,或者到数据尾时会返回 AVERROR_EOF
if (ret == AVERROR(EAGAIN)
ret == AVERROR_EOF) {
return;
} else if (ret < 0) {
printf("Error, Failed to encode!\n");
exit(1);
}
fwrite(newpkt->data, 1, newpkt->size, outfile);
fflush(outfile);
av_packet_unref(newpkt);
}
}
void yuyv422ToYuv420p(AVFrame *frame, AVPacket *pkt) {
int i = 0;
int yuv422_length = V_WIDTH * V_HEIGHT * 2;
int y_index = 0;
// copy all y
for (i = 0; i < yuv422_length; i += 2) {
frame->data[0][y_index] = pkt->data[i];
y_index++;
}
// copy u and v
int line_start = 0;
int is_u = 1;
int u_index = 0;
int v_index = 0;
// copy u, v per line. skip a line once
for (i = 0; i < V_HEIGHT; i += 2) {
// line i offset
line_start = i * V_WIDTH * 2;
for (int j = line_start + 1; j < line_start + V_WIDTH * 2; j += 4) {
frame->data[1][u_index] = pkt->data[j];
u_index++;
frame->data[2][v_index] = pkt->data[j + 2];
v_index++;
}
}
}
void rec_video() {
int ret = 0;
int base = 0;
int count = 0;
// pakcet
AVPacket pkt;
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *enc_ctx = NULL;
// set log level
av_log_set_level(AV_LOG_DEBUG);
// create file
char *yuvout = "./video.yuv";
char *out = "./video.h264";
FILE *yuvoutfile = fopen(yuvout, "wb+");
FILE *outfile = fopen(out, "wb+");
//打开设备
fmt_ctx = open_dev();
//打开编码器
open_encoder(V_WIDTH, V_HEIGHT, &enc_ctx);
//创建 AVFrame
AVFrame *frame = create_frame(V_WIDTH, V_HEIGHT);
//创建编码后输出的Packet
AVPacket *newpkt = av_packet_alloc();
if (!newpkt) {
printf("Error, Failed to alloc avpacket!\n");
goto __ERROR;
}
// read data from device
while (((ret = av_read_frame(fmt_ctx, &pkt)) == 0) && (count++ < 100)) {
int i = 0;
av_log(NULL, AV_LOG_INFO, "packet size is %d(%p)\n", pkt.size,
pkt.data);
// YUYVYUYVYUYVYUYV
YUYV422
// YYYYYYYYUUVV YUV420
yuyv422ToYuv420p(frame, &pkt);
fwrite(frame->data[0], 1, 307200, yuvoutfile);
fwrite(frame->data[1], 1, 307200 / 4, yuvoutfile);
fwrite(frame->data[2], 1, 307200 / 4, yuvoutfile);
frame->pts = base++;
encode(enc_ctx, frame, newpkt, outfile);
//
av_packet_unref(&pkt); // release pkt
}
encode(enc_ctx, NULL, newpkt, outfile);
__ERROR:
if (yuvoutfile) {
// close file
fclose(yuvoutfile);
}
// close device and release ctx
if (fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
av_log(NULL, AV_LOG_DEBUG, "finish!\n");
return;
}
int main(int argc, char *argv[]) {
rec_video();
return 0;
}
全部代码,我这里命名为encode_video.c,然后使用命令gcc -g -O0 encode_video.c -lavformat -lavutil -lavdevice
-lavcodec -o encode_video
进行编译。然后运行./encode_video,录制视频,录制完的视频保存在video.h264中。最后播放一下,看看效果ffplay video.h264
可以看到视频播放正常。
有些网站下载的视频播放的时候,不支持MP4视频格式,导致视频不能使用,那么有什么解决办法呢?方法1、嗨格式视频转换器推荐指数:☆☆☆☆☆详细操作步骤1、选择功能将嗨格式视频转换器安装在电脑端,将安装好的软件打开,点击选择【视频转换】功能按键,开始进入到将视频格式转换成mp4格式的操作界面。详细操作步骤2、上传文件选择界面上方展示的【添加文件】紫色功能按钮,将需要上传的所有视频格式文件和文件夹上传至软件中。通过进度条,查看文件的进度和判断文件是否传输故障和传输成功。详细操作步骤3、调整参数在底部的功能项里面设置输出目录文件,保存转换成功额mp4视频格式文件,设置分辨率从等参数,提高视频输出画质。详细操作步骤4、全部转换,打开文件前期操作步骤的工作做好后,可以直接点击【全部转换】紫色按钮,开始进行转mp4的操作。最后直接打开转换成功的mp4视频格式文件。方法2、Tinywow推荐指数:☆☆☆详细操作步骤1、在Tinywow展示的功能项里面,包含很多功能选项,大家可以选择视频或者【免费在线转换工具】页面下的相应功能。详细操作步骤2、添加文件,将需要转换的视频格式文件上传至软件中央,或者直接点击图标,从pc端选择文件或文件夹导入。文件导入成功后,软件即可自动开启转码操作,无需进行多余的功能按键操作。详细操作步骤3、文件转换成功后,点击【Download】按钮,下载保存转换成功的mp4视频格式文件。方法3、XMedia Recode推荐指数:☆☆☆1、在XMedia Recode转码软件中上传需要转换的视频素材,然后点击文件,调出输出格式设置窗口。将格式调成mp4。2、依次点击视频>常规>模式>复制。将视频流成功复制出来。3、通过【添加队列】按钮,查看视频自动转码的开始和结束时间,以及持续时间和相应的输出格式。4、当转码的界面显示总计处理时间为0.01的时候,即代表转码成功,此时点击ok按钮即可。想要转换视频的小伙伴,赶快行动起来叭~分享2个视频转换软件+1个在线转换网站,都可以将视频变成格式为mp4 编码为H.264,不仅能够快速的将视频转换完成,转换后的视频画质还很清晰,特别是第一个,还可以导出4K画质,刚需的朋友快去试试~口袋视频转换器,直达网址:https://download2.huduntech.comConvertio,戳一戳网站:https://convertio.co/zh/视频转换器,直达官网:https://www.xunjieshipin.com/1、口袋视频转换器(PC)一个功能强大的专业视频文件转换器,涵盖了多种视频文件编辑功能,包括视频格式转换,视频压缩,视频合并,视频分割和音频格式转换等功能,几乎日常需要的视频转换功能在这里都能找到打开软件,选择【视频格式转换】,上传需要转换的文件,支持批量转换以及上传文件夹,可以一次上传多个视频文件,这样能够大幅度提高效率点击下方的【输出格式】,选择视频中的MP4,点击下方的【添加自定义参数模板】接着点击【视频编码】,选择“H264”,在设置一下转换质量、分辨率、帧数等,点击【创建】,之后在出现的页面中选中自己创建好的模板,点击它,最后选择【全部转换】即可~2、Convertio(web)一个在线转换工具,支持视频、文本、图像等多种文件格式的转换,不注册登录的话一次最多可以同时转换2个文件,转换文件需要在100M以内,超过的需要付费,对于日常较小的视频来说是可以用的上传需要转换的文件之后,选择转换为【视频】中的“MP4”接着再右侧的设置中选择编解码器中的“H.264”,点击“OK”,再将视频转换即可3、视频转换器(PC)一个用起来很不错的视频转换器,支持多种视频文件的格式转换,例如MP4、MOV、AVI等格式同时也支持音频转换、视频合并和分割、视频配乐和截图等,一整个就是方便又好用!超级nice~选择首页的【视频转换】,上传需要转换的视频文件,支持批量转换点击【输出格式】中的【视频】,点击需要转换的【MP4】,接着在右侧选择输出后画质,并且点击它右侧的编辑图标将【视频编码】选择为“H264”,再对模板名称、转换质量和比特率等进行设置,点击【创建】在列表中选择刚刚设置好的模板,最后点击【全部转换】即可以上就是今天的分享内容了喜欢的话记得点个赞告诉我哦~我是卷心派不是卷心菜,想看更多干货分享在这里~ @卷心派的打工日记

选择擅长的领域继续答题?
{@each tagList as item}
${item.tagName}
{@/each}
手机回答更方便,互动更有趣,下载APP
提交成功是否继续回答问题?
手机回答更方便,互动更有趣,下载APP
展开全部你说的这个是录像的的压缩格式,看不出品牌和型号,建议把录像机的前后外观拍上图片,还有录像机的显示的画面都拍张图片上传到上面让大家看一下。已赞过已踩过你对这个回答的评价是?评论
收起
展开全部准确的说是监控录像H264格式的
你可以到拍拍网主页搜索下
监控录像转换软件
一会能找到你要的答案
收起
2条折叠回答
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
为你推荐:
下载百度知道APP,抢鲜体验使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。扫描二维码下载
×个人、企业类侵权投诉
违法有害信息,请在下方选择后提交
类别色情低俗
涉嫌违法犯罪
时政信息不实
垃圾广告
低质灌水
我们会通过消息、邮箱等方式尽快将举报结果通知您。说明
做任务开宝箱累计完成0
个任务
10任务
50任务
100任务
200任务
任务列表加载中...

我要回帖

更多关于 dav文件用什么播放器可以打开 的文章

 

随机推荐