📄 write-avi.c
字号:
#include "config.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <sys/param.h>#include <sys/uio.h>#include "riff.h"#include "grab-ng.h"#if 0 /* debugging */# define LIMIT_OPENDML (1024*1024) #else# define LIMIT_OPENDML (2000*1024*1024)#endif/* * M$ vidcap avi video+audio layout * * riff avi * list hdrl header * avih avi header * list strl video stream header * strh * strf * list strl audio stream header * strh * strf * istf ??? software * idit ??? timestamp * yunk ??? 4k page pad * list movi data * 00db video data * yunk ??? 4k page pad * [ ... ] * 01wb audio data * [ ... ] * idx1 video frame index * *//* ----------------------------------------------------------------------- */#define TRAP(txt) fprintf(stderr,"%s:%d:%s\n",__FILE__,__LINE__,txt);exit(1);#define size_strl_vids (sizeof(struct RIFF_strh) + \ sizeof(struct RIFF_strf_vids) + \ 4*5)#define size_strl_auds (sizeof(struct RIFF_strh) + \ sizeof(struct RIFF_strf_auds) + \ 4*5)static const struct AVI_HDR avi_hdr = { {'R','I','F','F'}, 0, {'A','V','I',' '}, {'L','I','S','T'}, 0, {'h','d','r','l'}, {'a','v','i','h'}, AVI_SWAP4(sizeof(struct RIFF_avih)), {}};static const struct AVIX_HDR avix_hdr = { {'R','I','F','F'}, 0, {'A','V','I','X'}, {'L','I','S','T'}, 0, {'m','o','v','i'},};static const struct AVI_HDR_VIDEO avi_hdr_video = { {'L','I','S','T'}, AVI_SWAP4(size_strl_vids), {'s','t','r','l'}, {'s','t','r','h'}, AVI_SWAP4(sizeof(struct RIFF_strh)), {{'v','i','d','s'}}, {'s','t','r','f'}, AVI_SWAP4(sizeof(struct RIFF_strf_vids)), {}};static const struct AVI_HDR_AUDIO avi_hdr_audio = { {'L','I','S','T'}, AVI_SWAP4(size_strl_auds), {'s','t','r','l'}, {'s','t','r','h'}, AVI_SWAP4(sizeof(struct RIFF_strh)), {{'a','u','d','s'}}, {'s','t','r','f'}, AVI_SWAP4(sizeof(struct RIFF_strf_auds)), {}};static const struct AVI_HDR_ODML avi_hdr_odml = { {'L','I','S','T'}, AVI_SWAP4(sizeof(uint32_t) + 4*3), {'o','d','m','l'}, {'d','m','l','h'}, AVI_SWAP4(sizeof(uint32_t)),};static const struct AVI_DATA avi_data = { {'L','I','S','T'}, 0, {'m','o','v','i'},};static const struct CHUNK_HDR frame_hdr = { {'0','0','d','b'}, 0};static const struct CHUNK_HDR sound_hdr = { {'0','1','w','b'}, 0};static const struct CHUNK_HDR idx_hdr = { {'i','d','x','1'}, 0};/* ----------------------------------------------------------------------- */struct avi_video_priv { const char handler[4]; const char compress[4]; const int bytesperpixel;};struct avi_handle { /* file name+handle */ char file[MAXPATHLEN]; int fd; struct iovec *vec; /* format */ struct ng_video_fmt video; struct ng_audio_fmt audio; /* headers */ struct AVI_HDR avi_hdr; struct AVIX_HDR avix_hdr; struct AVI_HDR_ODML avi_hdr_odml; struct AVI_HDR_AUDIO avi_hdr_audio; struct AVI_HDR_VIDEO avi_hdr_video; struct AVI_DATA avi_data; struct CHUNK_HDR frame_hdr; struct CHUNK_HDR sound_hdr; struct CHUNK_HDR idx_hdr; /* statistics -- first chunk */ int frames; off_t hdr_size; off_t audio_size; off_t data_size; /* statistics -- current chunk */ int bigfile; int framesx; off_t avix_start; off_t datax_size; /* statistics -- total */ int frames_total; /* frame index */ struct IDX_RECORD *idx_array; int idx_index, idx_count; off_t idx_offset; off_t idx_size;};/* ----------------------------------------------------------------------- *//* idx1 frame index */static voidavi_addindex(struct avi_handle *h, char *fourcc,int flags,int chunksize){ if (h->idx_index == h->idx_count) { h->idx_count += 256; h->idx_array = realloc(h->idx_array,h->idx_count*sizeof(struct IDX_RECORD)); } memcpy(h->idx_array[h->idx_index].id,fourcc,4); h->idx_array[h->idx_index].flags=AVI_SWAP4(flags); h->idx_array[h->idx_index].offset=AVI_SWAP4(h->idx_offset-h->hdr_size-8); h->idx_array[h->idx_index].size=AVI_SWAP4(chunksize); h->idx_index++; h->idx_offset += chunksize + sizeof(struct CHUNK_HDR);}static voidavi_writeindex(struct avi_handle *h){ /* write frame index */ h->idx_hdr.size = AVI_SWAP4(h->idx_index * sizeof(struct IDX_RECORD)); write(h->fd,&h->idx_hdr,sizeof(struct CHUNK_HDR)); write(h->fd,h->idx_array,h->idx_index*sizeof(struct IDX_RECORD)); h->idx_size += h->idx_index * sizeof(struct IDX_RECORD) + sizeof(struct CHUNK_HDR); /* update header */ h->avi_hdr.avih.flags |= AVI_SWAP4(AVIF_HASINDEX);} static voidavi_bigfile(struct avi_handle *h, int last){ off_t avix_end; if (h->bigfile) { /* finish this chunk */ avix_end = lseek(h->fd,0,SEEK_CUR); lseek(h->fd,h->avix_start,SEEK_SET); h->avix_hdr.riff_size = h->datax_size + 4*4; h->avix_hdr.data_size = h->datax_size + 4; write(h->fd,&h->avix_hdr,sizeof(struct AVIX_HDR)); lseek(h->fd,avix_end,SEEK_SET); h->avix_start = avix_end; } else { h->avix_start = lseek(h->fd,0,SEEK_CUR); } if (last) return; h->bigfile++; h->framesx = 0; h->datax_size = 0; write(h->fd,&h->avix_hdr,sizeof(struct AVIX_HDR)); if (ng_debug) fprintf(stderr,"avi bigfile #%d\n",h->bigfile);}/* ----------------------------------------------------------------------- */static voidavi_write_header(struct avi_handle *h){ off_t curpos; /* fill in some statistic values ... */ h->avi_hdr.riff_size = AVI_SWAP4(h->hdr_size+h->data_size+h->idx_size); h->avi_hdr.hdrl_size = AVI_SWAP4(h->hdr_size - 4*5); h->avi_hdr.avih.frames = AVI_SWAP4(h->frames); if (h->video.fmtid != VIDEO_NONE) h->avi_hdr_video.strh.length = AVI_SWAP4(h->frames); if (h->audio.fmtid != AUDIO_NONE) h->avi_hdr_audio.strh.length = AVI_SWAP4(h->audio_size/h->avi_hdr_audio.strh.scale); h->avi_data.data_size = AVI_SWAP4(h->data_size); /* ... and write header again */ curpos = lseek(h->fd,0,SEEK_CUR); lseek(h->fd,0,SEEK_SET); write(h->fd,&h->avi_hdr,sizeof(struct AVI_HDR)); if (h->video.fmtid != VIDEO_NONE) write(h->fd,&h->avi_hdr_video,sizeof(struct AVI_HDR_VIDEO)); if (h->audio.fmtid != AUDIO_NONE) write(h->fd,&h->avi_hdr_audio,sizeof(struct AVI_HDR_AUDIO)); if (h->video.fmtid != VIDEO_NONE) { h->avi_hdr_odml.total_frames = h->frames_total; write(h->fd,&h->avi_hdr_odml,sizeof(struct AVI_HDR_ODML)); } write(h->fd,&h->avi_data,sizeof(struct AVI_DATA)); lseek(h->fd,curpos,SEEK_SET);}static void*avi_open(char *filename, char *dummy, struct ng_video_fmt *video, const void *priv_video, int fps, struct ng_audio_fmt *audio, const void *priv_audio){ const struct avi_video_priv *pvideo = priv_video; struct avi_handle *h; int i,frame_bytes,depth,streams,rate,us_frame; if (NULL == (h = malloc(sizeof(*h)))) return NULL; if (NULL == filename) return NULL; /* init */ memset(h,0,sizeof(*h)); h->video = *video; h->audio = *audio; h->avi_hdr = avi_hdr; h->avix_hdr = avix_hdr; h->avi_hdr_odml = avi_hdr_odml; h->avi_hdr_video = avi_hdr_video; h->avi_hdr_audio = avi_hdr_audio; h->avi_data = avi_data; h->frame_hdr = frame_hdr; h->sound_hdr = sound_hdr; h->idx_hdr = idx_hdr; h->vec = malloc(sizeof(struct iovec) * video->height);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -