截取AVI格式的视频C语言代码
首先在阅读本代码之前百度一下avi,虽然经过我验证上面有部分错误,但是不影响阅读。因为有些变量的注释我没有写,所以请读者自行搜索吧。下面是c语言文件,编译之后能够直接运行,用来截取开始时间(单位s)后指定长度(单位s)的视频流。最后附上一部分视频文件的二进制,方便对照阅读。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#pragma pack(1)
/*
最开始的4个字节是一个四字符码‘RIFF’,表示这是一个RIFF文件;紧跟着后面用4个字节表示此RIFF文件的大小;
然后又是一个四字符码说明文件的具体类型(比如AVI、WAVE等);最后就是实际的数据。注意文件大小值的计算
方法为:实际数据长度 +4(文件类型域的大小);也就是说,文件大小的值不包括‘RIFF’域和“文件大小”域本身
的大小。
*/
typedef struct RIFF
{
char riff[4];
unsigned int size;
char type[4];
}RIFF;
/*
注意listSize值的计算方法为:实际的列表数据长度 +4(listType域的大小);也就是说listSize值不包括‘LIST’域和listSize域本身的大小。
*/
typedef struct list
{
char fcc[4];
unsigned int size;
char type[4];
}LIST;
/*************avih*********************/
typedef struct _avimainheader
{
char fcc[4];//'avih'
int size;// 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)
int dwMicroSecPerFrame;//视频帧间隔时间(以微秒为单位)
int dwMaxBytesPerSec;// 这个AVI文件的最大数据率
int dwPaddingGranularity;// 数据填充的粒度
int dwFlags;// AVI文件的全局标记,比如是否含有索引块等
int dwTotalFrames; // 总帧数
int dwInitialFrames; // 为交互格式指定初始帧数(非交互格式应该指定为0)
int dwStreams;// 本文件包含的流的个数
int dwSuggestedBufferSize; // 建议读取本文件的缓存大小(应能容纳最大的块)
int dwWidth;//视频图像的宽(以像素为单位)
int dwHeight;//视频图像的高(以像素为单位)
int dwReserved[4]; // 保留
}AVIMAINHEADER;
/********strh*******/
typedef struct
{
short int left;
short int top;
short int right;
short int bottom;
}RCFRAME;
typedef struct _avistreamheader
{
char fcc[4];// 必须为‘strh’
int size;
char fccType[4];// 流的类型:‘auds’(音频流)、‘vids’(视频流)、
char fccHandler[4];// 指定流的处理者,对于音视频来说就是解码器
int dwFlags;// 标记:是否允许这个流输出?调色板是否变化?
int wPriority;// 流的优先级(当有多个相同类型的流时优先级最高的为默认流)
int wLanguage;
int dwInitialFrames; // 为交互格式指定初始帧数
int dwScale;// 这个流使用的时间尺度
int dwRate;
int dwStart;// 流的开始时间
int dwLength;// 流的长度(单位与dwScale和dwRate的定义有关)
int dwQuality;// 流数据的质量指标(0 ~ 10,000)
int dwSampleSize;// Sample的大小
RCFRAME rcFrame;// 指定这个流(视频流或文字流)在视频主窗口中的显示位置
}AVISTREAMHEADER;
/**************strf_vids********************/
typedef struct tagBITMAPINFOHEADER
{
char fcc[4];
int biSize;
int biWidth;
int biHeight;
short int biPlanes;
short int biBitCount;
int biCompression;
int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
int biClrUsed;
int biClrImportant;
}BITMAPINFOHEADER;
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
int bimColors[1];
}BITMAPINFO;
/***************strf_auds*********************/
//#define WAVEFORMAT __attribute__((packed))
typedef struct
{
char fcc[4];
int size;
short int wFormatTag;
short int nChannels;
int nSamplesPerSec;
int nAvgBytesPerSec;
short int nBlockAlign;
short int wBitsPerSample;
short int biSize;
}WAVEFORMAT;
typedef struct strl_vids
{
LIST list;
AVISTREAMHEADER strh;
BITMAPINFO strf;
}STRL_VIDS;
typedef struct strl_auds
{
LIST list;
AVISTREAMHEADER strh;
WAVEFORMAT strf;
}STRL_AUDS;
typedef struct junk
{
char fcc[4];
int size;
}JUNK;
typedef struct HDRL
{
AVIMAINHEADER avih;
STRL_VIDS strl_vids;
STRL_AUDS strl_auds;
JUNK junk;
}HDRL;
typedef struct movi
{
char id[4];
int length;
}MOVI;
typedef struct data
{
LIST list;
MOVI chunk;
}DATA;
typedef struct aindex
{
char dwChunkId[4];
int dwFlags;
int dwOffset;
int dwSize;
}AINDEX;
typedef struct avi_idxl
{
char fcc[4];
AINDEX aindex[10];
}AVI_IDXL;
void print_avihead(RIFF riff,LIST list,HDRL hdrl)
{
printf("riff.size=%d\n",riff.size);
printf("list.size=%d\n",list.size);
printf("hdrl.avih.fcc=%s\n",hdrl.avih.fcc);
printf("hdrl.avih.dwTotalFrames=%d\n",hdrl.avih.dwTotalFrames);
printf("hdrl.avih.dwMicroSecPerFrame=%dms\n",hdrl.avih.dwMicroSecPerFrame/1000);
printf("hdrl.strl_vids.strh.fcc=%s\n",hdrl.strl_vids.strh.fcc);
printf("hdrl.strl_auds.strh.fcc=%s\n",hdrl.strl_auds.strh.fcc);
printf("hdrl.junk.fcc=%c\n",hdrl.junk.fcc[3]);
printf("hdrl.junk.size=%d\n",hdrl.junk.size);
}
void get_aviidxl(AVI_IDXL*idxl,char*src_buf,int off_set)
{
char*p;
p=src_buf+off_set;
memcpy(idxl,p,sizeof(AVI_IDXL));
printf("idxl.fcc:%s\n",idxl->fcc);
}
long get_file_size(const char *path)
{
unsigned long filesize = -1;
FILE*fp;
fp = fopen(path,"r");
if(fp==NULL)
{
return filesize;
}
fseek(fp,0,SEEK_END);
filesize = ftell(fp);
fclose(fp);
return filesize;
}
int main(int argc ,char*argv[])
{
unsigned long size;
int count=0,i;
int begin_s=60;//开始时间s
int t_s=20;//截取间隔s
int fd_src,fd_dst;
int off_set;
char*buf,*readbuf;
char*src_buf,*tmp;
RIFF riff;
LIST lhdrl;
HDRL hdrl;
LIST lmovi;
MOVI movi;
/*******************打开源文件与目的文件*****************************/
fd_src = open("H264.avi",O_RDONLY);
fd_dst = open("out.avi",O_CREAT|O_RDWR,0777);
/************将源文件内容读入缓存区***********************/
lseek(fd_src,0,SEEK_SET);
read(fd_src,&riff,sizeof(riff));
read(fd_src,&lhdrl,sizeof(lhdrl));
read(fd_src,&hdrl,lhdrl.size+4);
// print_avihead(riff,lhdrl,hdrl);
/*********建立JUNK缓存区存储0************/
buf=malloc(hdrl.junk.size);
memset(buf,0,hdrl.junk.size);
/**********将文件头与JUNK区写入目标文件***********/
lseek(fd_dst,sizeof(riff),SEEK_CUR);
lseek(fd_dst,sizeof(lhdrl),SEEK_CUR);
lseek(fd_dst,sizeof(hdrl),SEEK_CUR);
//write(fd_dst,&riff,sizeof(riff));
//write(fd_dst,&list,sizeof(list));
//write(fd_dst,&hdrl,sizeof(hdrl));
write(fd_dst,buf,hdrl.junk.size);
free(buf);
/***********偏移至movi区获取实际数据***************/
lseek(fd_src,hdrl.junk.size,SEEK_CUR);
read(fd_src,&lmovi,sizeof(lmovi));
write(fd_dst,&lmovi,sizeof(lmovi));
/******写数据*****/
while(1)//for(i =0 ;i < 20;i++)
{
read(fd_src,&movi,sizeof(movi));
if(movi.length%2!=0)
{
movi.length+=1;
}
buf = malloc(movi.length);
read(fd_src,buf,movi.length);
// printf("%d\tmovi.id=%s\n",count,movi.id);
if(((strncmp(movi.id+2,"db",2)==0)||(strncmp(movi.id+2,"dc",2)==0))&&(count<begin_s*25))//25帧是1秒
{
free(buf);
count++;
// printf("%d\tmovi.id=%s\n",count,movi.id);
continue;
}
if(((strncmp(movi.id+2,"pc",2)==0)||(strncmp(movi.id+2,"wb",2)==0))&&((count-1)<begin_s*25))//音频帧不计算在内,时间只用视频帧计算
{
free(buf);
continue;
}
if(((strncmp(movi.id+2,"db",2)==0)||(strncmp(movi.id+2,"dc",2)==0))&&(count>=begin_s*25))
{
count++;
printf("%d\tmovi.id=%s\tmovi.size=%x\n",count,movi.id,movi.length);
}
write(fd_dst,&movi,sizeof(movi));
write(fd_dst,buf,movi.length);
size=size+movi.length+8;
free(buf);
if(count>(begin_s+t_s)*25)
{
break;
}
//free(buf);
//size=size+movi.length+8;
}
riff.size=12+12+lhdrl.size+4+hdrl.junk.size+12+size;//计算数据大小,用来填充报头
hdrl.avih.dwTotalFrames=count;//大小字节
lseek(fd_dst,0,SEEK_SET);
write(fd_dst,&riff,sizeof(riff));
write(fd_dst,&lhdrl,sizeof(lhdrl));
write(fd_dst,&hdrl,sizeof(hdrl));
// off_set=off_set+8+data.list.size;
// get_aviidxl(&idxl,src_buf,off_set);
// write(fd_dst,src_buf,size);
close(fd_src);
close(fd_dst);
}
报头的图片
中间是JUNK的填充
这是一部分数据,都不到一帧,所以最好自己找个avi文件对照的我的代码看。
————————————————
版权声明:本文为CSDN博主「天晓-workspace」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38697824/article/details/85341049
截取AVI格式的视频C语言代码相关推荐
- AVI音视频封装格式学习(四)——linux系统C语言AVI格式音视频封装应用
拖了很久的AVI音视频封装实例,花了一天时间终于调完了,兼容性不是太好,但作为参考学习使用应该没有问题.RIFF和AVI以及WAV格式,可以参考前面的一些文章.这里详细介绍将一个H264视频流和一个2 ...
- IjkVideoView播放视频(支持avi格式的视频)
上一篇 Ijkplayer播放视频(支持AVI格式的视频) 讲了,Ijkplayer和SurfaceView结合,播放视频.这一篇我们把Ijkpayer和SurfaceView进行封装,封装成Ij ...
- Qt实现avi格式录制视频
声明:刚刚接触qt开发,觉得qt真的很强大,也正是因为它的强大,所以在这条路上还有很远很远的路要走,希望大家多多指教,多多交流共同进步.另外由于本人不是系统的从头开始学qt,主要是在实战需求中来实现功 ...
- 怎么把avi格式的视频转换成gif动态图
随着gif动态图越来越火爆,制作gif动态图的小伙伴也越来越多,在制作gif时我们经常会在互联网下载视频作为制作素材,而下载的诸多视频格式中avi格式作为流行的视频格式被大量下载.那怎么用迅捷视频转换 ...
- 如何使用JiaoZiVideoPlayer(饺子视频播放器)播放avi格式的视频
如何使用JiaoZiVideoPlayer(饺子视频播放器)播放avi等原生不支持的格式的视频 1.为什么使用JiaoZiVideoPlayer播放AVI格式的视频 有的同学可能会发现,部分.avi文 ...
- 如何将AVI格式的视频转换为MP4?用嗨格式试试看
如何将AVI格式的视频转换为MP4?MP4是目前最为常见且兼容性好的视频格式之一,但有时候遇到的视频格式是AVI的,怎么才能将其转换器MP4格式呢?下面就给你分享一个好用的方法. 首先在电脑上下载并运 ...
- MATLAB实现将图片转化为avi格式的视频
MATLAB实现将图片转化为avi格式的视频 视频就是将一系列连续的图片进行播放的效果.所以将图片转换为AVI格式的视频就是将一系列连续的图片保存到AVI格式的文件中. 转换的通用格式: %% 保 ...
- android flv格式的视频文件,android-如何运行mkv,flv,avi格式的视频文件?
我正在制作一个项目,使用使用videoview的简单代码,我可以播放3gp amd mp4格式的视频文件 vv = (VideoView) findViewById(R.id.videoView); ...
- html embed页面无法播放视频播放,用embed标签在网页中嵌入avi格式的视频不能播放...
制作HTML网页插入视频Mp 4格式可以播放,AVI格式不可以播放的原因是因为引入的参数错误,如下正确的使用方式: objecthttp://activex.microsoft.com/activex ...
最新文章
- K-Means算法理论及Python实现
- java 与c 运行效率_Java语言与C语言代码运行效率的比较
- 柯泰测试同步采集软件,上海近场测试设备_柯泰测试
- Vue.js 相关知识(动画)
- matlab robotics工具箱(3)逆运动学
- 判断用户用手机访问还是用电脑访问网页
- canvas 擦除动画_帧动画的多种实现方式与性能对比
- Mp3Play.ocx控件让音乐之声响起来
- atexit函数详解
- android mac 调试,Mac下使用Android studio真机调试
- 快来看!我把小时候最喜欢的连连看游戏源代码拿来了~
- QGIS数据分析入门——Qgis下载及界面介绍(一)
- Metasploit之——基本后渗透命令
- 分析功能强大的蛋白质结构预测软件Phyre2
- 取决于数学符号_科学发现的未来取决于开放
- 汽车之家APP车型口碑--参数分析
- word表格怎么缩小上下间距_word表格怎么调整行高间距拉不动
- 一行代码实现shell if else逻辑
- java 时间字符串比较大小_java中如何比较两个时间字符串的大小
- PSGAN(2019SIGIR)
热门文章
- react 项目总结
- hdu 1161 Eddy's mistakes
- DiscoveryService.getRemoteAdvertisements是否会获得本地通告?
- 配置SAMBA文件共享的基本方法
- 石头机器人红灯快闪_机器人集体“快闪”活动爆红网络 “我是AI”与您相约智能新时代...
- python 内置模块 subprocess
- Docker 精通之微服务
- html中怎么写多选框,如何在HTML中实现“选择所有”复选框?
- loading gif 透明_搞笑GIF:有这样的女朋友下班哪里都不想去
- 【教程分享】Jmeter入门教程