📄 lavaddwav.c
字号:
/* lavaddwav: Add a WAV file as soundtrack to an AVI or QT file Usage: lavaddwav AVI_or_QT_file WAV_file Output_file Multiple output file version by Nicholas Redgrave <baron@bologrew.demon.co.uk> 8th January 2005 Use "%02d" style output filenames for multiple files. Parameter options added by Nicholas Redgrave <baron@bologrew.demon.co.uk> 15th January 2005 Major rewrite to add lists of AVI/QT and WAV files by Nicholas Redgrave <baron@bologrew.demon.co.uk> 2nd February 2005 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.*/#include <config.h>#include <stdio.h>#include <fcntl.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include "lav_io.h"#include "mjpeg_logging.h"#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')#define MAX_MBYTES_PER_FILE_32 ((0x7fffffff >> 20) * 85/100)/* Is less than 2^31 and 2*10^9 */#define MAX_FILE_NAME 127/* Structures */typedef struct{ char chFileName[MAX_FILE_NAME+1]; long video_frames; int width; int height; int interlacing; double fps; double time_length; int format; long max_frame_size;}videoparams;typedef struct{ char chFileName[MAX_FILE_NAME+1]; long data_length; long audio_samps; long audio_rate; int audio_chans; int audio_bits; int audio_bps; double time_length;}audioparams;/* Prototypes */static void usage(void);void handle_args(int argc, char **argv);int main(int argc, char **argv);int open_lav_file(lav_file_t **lav_fd, char *chLavFile, int ientry, int iscan);int open_wav_file(int *wav_fd, char *chWavFile, int ientry, int iscan);int count_list_entries(char *chFile);int fill_video_list_entries(char *chFile);int fill_audio_list_entries(char *chFile);void display_video_params(int ientry);void display_audio_params(int ientry);int allocate_video_memory(int ientries);int allocate_audio_memory(int ientries);void free_video_memory(int ientries);void free_audio_memory(int ientries);int compare_input_files(int iVidEntries, int iAudEntries);long find_max_frame_size(int ientries);int detect_endian(void);/* Global variables */int verbose = 1;static int big_endian = 0;static int param_maxfilesize = MAX_MBYTES_PER_FILE_32;static int list_mode = 0;static videoparams **vp = NULL;static audioparams **ap = NULL;static void usage(void) { fprintf(stderr, "Usage: lavaddwav [params] <AVI_or_QT_file> <WAV_file> <Output_file>\n" " where possible params are:\n" " -m num maximum size per file [%d MB]\n" " -l list mode (input files are text lists of AVI//QT and WAV files)\n", param_maxfilesize); fprintf(stderr," If the output file is too large for one AVI use %%0xd in\n"); fprintf(stderr," the output filename so that lavaddwav creates several files.\n"); fprintf(stderr," e.g. lavaddwav video.avi sound.wav output%%02d.avi\n");}/********************************************************************/void handle_args(int argc, char **argv){ int p; /* disable error messages from getopt */ opterr = 0; /* Parse options */ while( (p = getopt(argc, argv, "lm:")) != -1 ) { switch(p) { case 'l': { list_mode = 1; break; } case 'm': { param_maxfilesize = atoi(optarg); break; } default: { usage(); exit(1); } } } /* check validity of options */ if( (param_maxfilesize <= 0) || (param_maxfilesize > MAX_MBYTES_PER_FILE_32) ) { param_maxfilesize = MAX_MBYTES_PER_FILE_32; fprintf(stderr,"Maximum size per file out of range - resetting to maximum\n"); }}/********************************************************************/int main(int argc, char **argv){ int n; int wav_fd; long i, res, frame_size, max_frame_size; long absize, lRemBytes; uint8_t *vbuff = NULL; uint8_t *abuff = NULL; lav_file_t *lav_fd = NULL; lav_file_t *lav_out = NULL; char *dotptr; unsigned long ulOutputBytes; int iLavFiles, iWavFiles; int iTotBytes; char chOutFile[128] = "\0"; int iOutNum = 1; int iCurLav = 0; int iCurWav = 0; int imulti_out = 0; double total_video_duration = 0.0; double total_audio_duration = 0.0; if(argc < 4) { /* Show usage */ usage(); exit(1); } /* Handle command line arguments */ handle_args(argc, argv); /* Are we big or little endian? */ big_endian = detect_endian(); if( big_endian < 0 ) { exit(1); } /* Check for enough string space for output filename */ if( strlen(argv[optind+2]) > (sizeof(chOutFile)-2) ) { mjpeg_error("Insufficient string space to create output filename"); exit(1); } /* Process according to mode */ if( list_mode ) { /* Open and count file entries in lav list file */ iLavFiles = count_list_entries(argv[optind]); if( !iLavFiles ) { mjpeg_error("No entries found in video list file %s", argv[optind]); exit(1); } /* Open and count file entries in wav list file */ iWavFiles = count_list_entries(argv[optind+1]); if( !iWavFiles ) { mjpeg_error("No entries found in audio list file %s", argv[optind+1]); exit(1); } } else { iLavFiles = 1; iWavFiles = 1; } /* Allocate memory for list entry structures */ if( !allocate_video_memory(iLavFiles) ) { mjpeg_error("Unable to allocate memory for video file list structures"); exit(1); } if( !allocate_audio_memory(iWavFiles) ) { mjpeg_error("Unable to allocate memory for audio file list structures"); free_video_memory(iLavFiles); exit(1); } /* Fill structures with data */ if( list_mode ) { if( !fill_video_list_entries(argv[optind]) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill video file list structures"); exit(1); } if( !fill_audio_list_entries(argv[optind+1]) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill audio file list structures"); exit(1); } } else { if( !open_lav_file(&lav_fd, argv[optind], 0, 1) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill video file structure"); exit(1); } lav_close(lav_fd); display_video_params(0); if( !open_wav_file(&wav_fd, argv[optind+1], 0, 1) ) { free_audio_memory(iWavFiles); free_video_memory(iLavFiles); mjpeg_error("Unable to fill audio file structure"); exit(1); } close(wav_fd); display_audio_params(0); } /* Check that input files are compatible */ if( list_mode ) { if( !compare_input_files(iLavFiles, iWavFiles) ) { mjpeg_error("Input files are not compatible"); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } } /* Find largest frame size */ max_frame_size = find_max_frame_size(iLavFiles); mjpeg_debug(" Max frame size: %ld", max_frame_size); /* Check the output file format makes sense */ if( (dotptr = strrchr(argv[3], '.')) ) { if( !strcasecmp(dotptr+1, "mov") || !strcasecmp(dotptr+1, "qt") || !strcasecmp(dotptr+1, "moov") ) { if( vp[0]->format != 113 ) { mjpeg_error("Output file looks like QT but input files are not QT"); mjpeg_error("Please choose another extension to avoid confusion"); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } } } /* Rough check for "%d" style output filename */ if( strchr(argv[optind+2], 37) != NULL ) { imulti_out = 1; } else { /* Copy output filename for non-%d style names */ strncpy(chOutFile, argv[optind+2], sizeof(chOutFile)-1); chOutFile[sizeof(chOutFile)-1] = 0; } /* Allocate video and audio buffers */ vbuff = (uint8_t*) malloc(max_frame_size); absize = (ap[0]->audio_rate / vp[0]->fps) + 0.5; absize *= ap[0]->audio_bps; abuff = (uint8_t*) malloc(absize); if( (vbuff == NULL) || (abuff == NULL) ) { mjpeg_error("Out of Memory - malloc failed"); if( vbuff != NULL ){ free(vbuff); } if( abuff != NULL ){ free(abuff); } free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } /* Open first video and audio file */ if( !open_lav_file(&lav_fd, vp[iCurLav]->chFileName, iCurLav, 0) ) { mjpeg_error("Error opening %s", vp[iCurLav]->chFileName); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_video_duration += vp[iCurLav]->time_length; if( !open_wav_file(&wav_fd, ap[iCurWav]->chFileName, iCurWav, 0) ) { mjpeg_error("Error opening %s", ap[iCurWav]->chFileName); free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } total_audio_duration += ap[iCurWav]->time_length; /* (First) video and audio file are open - we are ready to multiplex */ ulOutputBytes = 0; i = 0; /* Outer loop */ while( iCurLav < iLavFiles ) { if( imulti_out ) { /* build output filename */ sprintf(chOutFile, argv[optind+2], iOutNum++); } /* Create output file */ lav_out = lav_open_output_file(chOutFile, vp[0]->format, vp[0]->width, vp[0]->height, vp[0]->interlacing, vp[0]->fps, ap[0]->audio_bits, ap[0]->audio_chans, ap[0]->audio_rate); if(!lav_out) { mjpeg_error("Error creating %s: %s", chOutFile, lav_strerror()); lav_close(lav_fd); if( wav_fd >= 0 ) { close(wav_fd); } free(abuff); free(vbuff); free_audio_memory(iWavFiles); free_video_memory(iLavFiles); exit(1); } /* Loop reading and writing video and audio */ while(1) { /* Video loop */ while( i < vp[iCurLav]->video_frames ) { /* read video frame */ res = lav_read_frame(lav_fd,vbuff); if( res < 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -