📄 lavtrans.c
字号:
/* lavtrans - takes file arguments like lavplay (AVI/Quicktime files and Edit Lists) and produces a new file or a bunch of JPEG images from that. Mostly intended to flaten the content of Edit Lists Copyright (C) 2000 Rainer Johanni <Rainer@Johanni.de> Additions by Gernot Ziegler <gz@lysator.liu.se> Usage: lavtrans [options] filename [filename ...] <-i num> where options are as follows: -o name Write output to file "name". Output must fit into 1 file (2 GB limit!!!) unless single images are produced. -f [amqiw] Format of output a: AVI (no selection of bottom/top frame first possible) q: Quicktime (if the input is interlaced, then all input files must be Quicktime, too) i: single images, "name" in the -o option must be a vaild format string for sprintf! w: WAV file (of sound only) Both options are mandatory! -i num Grab a single frame (num) from the input to the outputfile (you need -f i for this!) Filename options like in lavplay (optional +p/+n followed by an arbitrary number of AVI / Quicktime files or edit lists). This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include "lav_io.h"#include "editlist.h"#include "mjpeg_logging.h"static EditList el;static char *outfile=0;static char format=0;static int process_image_frame = -1; /* All, >-1 means not all */#define FOURCC(a,b,c,d) ( (d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff) )#define FOURCC_RIFF FOURCC ('R', 'I', 'F', 'F')#define FOURCC_WAVE FOURCC ('W', 'A', 'V', 'E')#define FOURCC_FMT FOURCC ('f', 'm', 't', ' ')#define FOURCC_DATA FOURCC ('d', 'a', 't', 'a')static struct{ uint32_t rifftag; uint32_t rifflen; uint32_t wavetag; uint32_t fmt_tag; uint32_t fmt_len; uint16_t wFormatTag; uint16_t nChannels; uint32_t nSamplesPerSec; uint32_t nAvgBytesPerSec; uint16_t nBlockAlign; uint16_t wBitsPerSample; uint32_t datatag; uint32_t datalen;} wave_hdr;static uint8_t abuff[16384];unsigned int fred; /* needed for endian detection */char *pfred; /* needed for endian detection */int big_endian; /* and that too ;) */int verbose = 1;/* Prototype definitions */void Usage(char *str);void system_error(const char *str1, const char *str2);void detect_endian (void);void initwav_hdr(void);/* The rest of the code */void detect_endian (){ /* The endian detection copied from mp2enc */ fred = 2 | (1 << (sizeof(int)*8-8)); pfred = (char *)&fred; if(*pfred == 1) { big_endian = 1; mjpeg_info("System is big endian"); } else if(*pfred == 2) { big_endian = 0; mjpeg_info("System is little endian"); } else { mjpeg_error("Can not determine if system is big/lttle endian"); mjpeg_error_exit1("Are you running on a Cray - or what?"); }}void initwav_hdr(){wave_hdr.rifflen = 0; /* to be filled later */wave_hdr.datalen = 0; /* to be filled later */wave_hdr.wFormatTag = 1; /* PCM */ wave_hdr.rifftag = reorder_32(FOURCC_RIFF, big_endian); wave_hdr.wavetag = reorder_32(FOURCC_WAVE, big_endian); wave_hdr.fmt_tag = reorder_32(FOURCC_FMT, big_endian); wave_hdr.fmt_len = reorder_32(16, big_endian); wave_hdr.datatag = reorder_32(FOURCC_DATA, big_endian); swab(&wave_hdr.wFormatTag, &wave_hdr.wFormatTag ,2);}void Usage(char *str){ fprintf(stderr,"Usage: %s -o <outputfile> -f [aqiw] filenames [<-i num>]\n",str); fprintf(stderr," -f a output AVI file\n"); fprintf(stderr," -f q output Quicktime file\n"); fprintf(stderr," -f i output single JPEG images, " "-o option mut be a valid format string\n"); fprintf(stderr," -f w output WAV file (sound only!)\n"); fprintf(stderr," -i num convert single frame to JPEG\n"); exit(1);}void system_error(const char *str1, const char *str2){ mjpeg_error_exit1("%s: %s: %s",str1, str2, strerror(errno));}int main(int argc, char ** argv){ lav_file_t *outfd = NULL; FILE *wavfd = NULL; FILE *imgfd = NULL; uint8_t *vbuff; char *dotptr; char imgfname[4096]; long audio_bytes_out = 0; int res, n, nv = 0, na = 0, nframe; int forcestereo = 0; while( (n=getopt(argc,argv,"o:f:i:v:")) != EOF) { switch(n) { case 'o': outfile = optarg; break; case 'f': format = optarg[0]; break; case 'i': process_image_frame = atoi(optarg); break; case 'v': verbose = atoi (optarg); if( verbose < 0 || verbose >2 ) { Usage (argv[0]); exit (1); } break; case '?': Usage(argv[0]); exit(1); } } (void)mjpeg_default_handler_verbosity(verbose); detect_endian(); if(outfile==0) Usage(argv[0]); if(optind>=argc) Usage(argv[0]); if(outfile != 0 && format == 0) { if((dotptr = strrchr(outfile, '.'))) {#ifdef HAVE_LIBQUICKTIME if(!strcasecmp(dotptr+1, "mov") || !strcasecmp(dotptr+1, "qt") || !strcasecmp(dotptr+1, "moov")) format = 'q';#endif if(!strcasecmp(dotptr+1, "avi")) format = 'a'; if(!strcasecmp(dotptr+1, "wav")) format = 'w'; } if(format == '\0') format = 'a'; } if(format!='a' && format!='q' && format!='i' && format!='w' && format!='A' && format!='W') Usage(argv[0]); if (process_image_frame != -1 && format!='i') { mjpeg_error_exit1("If you specify \'-i <num>\', you must use jpg (\'-f i\') as output:" " lavtrans -o image.jpg -f i movie.avi -i <frame_num>"); } /* Get and open input files */ read_video_files(argv + optind, argc - optind, &el,0); if(format == 'a' && el.video_inter == LAV_INTER_BOTTOM_FIRST) format = 'A'; if((format == 'q') && el.video_inter == LAV_INTER_BOTTOM_FIRST) { mjpeg_error_exit1("Output is Quicktime - wrong interlacing order"); } if(format == 'q' || format == 'a' || format == 'A') { outfd = lav_open_output_file(outfile,format, el.video_width,el.video_height,el.video_inter, el.video_fps /* was:video_norm=='n' ? 30000.0/1001.0 : 25.0*/ , el.audio_bits,el.audio_chans,el.audio_rate); if(!outfd) { mjpeg_error_exit1("Opening output file %s: %s", outfile,lav_strerror()); } } if(format == 'w' || format == 'W') { if(!el.has_audio) { mjpeg_error_exit1("WAV output requested but no audio present"); } if( format == 'W' ) { if( el.audio_bits == 16 && el.audio_chans == 1 ) forcestereo = 1; else { mjpeg_error_exit1("STEREOFIED WAV output request but non mono 16-bit audio present"); } } initwav_hdr(); wave_hdr.nChannels = forcestereo ? 2 : el.audio_chans; wave_hdr.nBlockAlign = el.audio_bps; wave_hdr.wBitsPerSample = el.audio_bits; wave_hdr.nSamplesPerSec = reorder_32(el.audio_rate, big_endian); wave_hdr.nAvgBytesPerSec = reorder_32(el.audio_rate*el.audio_bps, big_endian); if (big_endian) { swab(&wave_hdr.nChannels, &wave_hdr.nChannels, 2); swab(&wave_hdr.nBlockAlign, &wave_hdr.nBlockAlign, 2); swab(&wave_hdr.wBitsPerSample, &wave_hdr.wBitsPerSample, 2); } wavfd = fopen(outfile,"wb"); if(wavfd==0) system_error("opening WAV file","fopen"); res = fwrite(&wave_hdr,sizeof(wave_hdr),1,wavfd); if(res!=1) system_error("writing WAV file","fwrite"); } vbuff = (uint8_t*) malloc(el.max_frame_size); if(vbuff==0) { mjpeg_error_exit1("malloc failed"); } /* Quick hack by Ronald to enable one-frame picture grabbing */ if (process_image_frame != -1) { nv = el_get_video_frame(vbuff, process_image_frame, &el); sprintf(imgfname,outfile); imgfd = fopen(imgfname,"wb"); if(imgfd==0) system_error("opening image file","fopen"); res = fwrite(vbuff,nv,1,imgfd); if(res!=1) system_error("writing image","fwrite"); fclose(imgfd); mjpeg_info("Frame %d grabbed", process_image_frame); exit(1); } for(nframe=0;nframe<el.video_frames;nframe++) { if (format!='w') nv = el_get_video_frame(vbuff, nframe, &el); if (el.has_audio && format!='i') na = el_get_audio_data(abuff, nframe, &el, 0); switch(format) { case 'a': case 'A': case 'q': res = lav_write_frame(outfd,vbuff,nv,1); if(el.has_audio && res==0) res = lav_write_audio(outfd,abuff,na/el.audio_bps); if(res) { mjpeg_error_exit1("Error writing output: %s",lav_strerror()); } break; case 'i': sprintf(imgfname,outfile,nframe); imgfd = fopen(imgfname,"wb"); if(imgfd==0) system_error("opening image file","fopen"); res = fwrite(vbuff,nv,1,imgfd); if(res!=1) system_error("writing image","fwrite"); fclose(imgfd); break; case 'w': case 'W': if( forcestereo ) { /* Double up the samples */ int i; short *sbuff = (short *)abuff; for( i = na-1; i >= 0; --i ) { sbuff[i+i+1]=sbuff[i+i]=sbuff[i]; } na = na + na; res = fwrite(abuff,na,1,wavfd); } else { res = fwrite(abuff,na,1,wavfd); } if(res!=1) system_error("writing WAV file","fwrite"); audio_bytes_out += na; break; } } if(format == 'q' || format == 'a' || format == 'A') { res = lav_close(outfd); if(res) { mjpeg_error_exit1("Closing output file: %s",lav_strerror()); } } if(format == 'w' || format == 'W') { wave_hdr.rifflen = reorder_32(sizeof(wave_hdr) -8+ audio_bytes_out, big_endian); wave_hdr.datalen = reorder_32(audio_bytes_out, big_endian); res = fseek(wavfd,0,SEEK_SET); if(res) system_error("writing WAV file","fseek"); res = fwrite(&wave_hdr,sizeof(wave_hdr),1,wavfd); if(res!=1) system_error("writing WAV file","fwrite"); fclose(wavfd); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -