日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

截取AVI格式的视频C语言代码

發布時間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 截取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语言代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。