1 /*
2  *
3  *  lav2wav.c
4  *
5  *	Copyright (C) 2000 MSSG, Rainer Johanni, Aaron Holtzman, Andrew Stevens
6  *
7  *  This file is part of lav2wav,a component of the "MJPEG tools"
8  *  suite of open source tools for MJPEG and MPEG processing.
9  *
10  *  lav2wav is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  lav2wav is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with GNU Make; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include "lav_io.h"
31 #include "editlist.h"
32 #include "mjpeg_logging.h"
33 
34 struct	wave_header wave;
35 static	uint8_t audio_buff[2*256*1024]; /* Enough for 1fps, 48kHz ... */
36 	int verbose = 1;
37 	int big_endian; /* The endian detection */
38 	int silence_sr, silence_bs, silence_ch ;
39 	EditList el;
40 
41 void set_silence (char *);
42 int wav_header(unsigned int bits, unsigned int rate, unsigned int channels, int fd);
43 void Usage(char *str);
44 
45 /* Raw write does *not* guarantee to write the entire buffer load if it
46    becomes possible to do so.  This does...  */
do_write(int fd,void * buf,size_t count)47 static size_t do_write( int fd, void *buf, size_t count )
48 {
49 	char *cbuf = buf;
50 	size_t count_left = count;
51 	size_t written;
52 	while( count_left > 0 )
53 	{
54 		written = write( fd, cbuf, count_left );
55 		if( written < 0 )
56 			return count-count_left;
57 		count_left -= written;
58 		cbuf += written;
59 	}
60 	return count;
61 }
62 
wav_header(unsigned int bits,unsigned int rate,unsigned int channels,int fd)63 int wav_header( unsigned int bits, unsigned int rate, unsigned int channels, int fd )
64 {
65 	uint16_t temp_16; /* temp variables for swapping the bytes */
66 	uint32_t temp_32; /* temp variables for swapping the bytes */
67         uint32_t dummy_size = 0x7fffff00+sizeof(wave);
68 
69 	/* Write out a ZEROD wave header first */
70 	memset(&wave, 0, sizeof(wave));
71 
72 	strncpy((char*)wave.riff.id, "RIFF", 4);
73 	strncpy((char*)wave.riff.wave_id, "WAVE",4);
74 	dummy_size -=8;
75 	wave.riff.len = reorder_32(dummy_size, big_endian);
76 
77 	strncpy((char*)wave.format.id, "fmt ",4);
78         wave.format.len = reorder_32((uint32_t)sizeof(struct common_struct), big_endian);
79 
80 	/* Store information */
81         if (big_endian == 0)
82           {
83              wave.common.wFormatTag = WAVE_FORMAT_PCM;
84              wave.common.wChannels = channels;
85              wave.common.dwSamplesPerSec = rate;
86              wave.common.dwAvgBytesPerSec = channels*rate*bits/8;
87              wave.common.wBlockAlign = channels*bits/8;
88              wave.common.wBitsPerSample = bits;
89           }
90         else  /* We have a big endian machine and have to swap the bytes */
91           {
92              temp_16 = WAVE_FORMAT_PCM;
93              swab(&temp_16, &wave.common.wFormatTag,2);
94              temp_16 = channels;
95              swab(&temp_16, &wave.common.wChannels, 2);
96              temp_32 = rate;
97              wave.common.dwSamplesPerSec = reorder_32 (temp_32, big_endian);
98              temp_32 = channels*rate*bits/8;
99              wave.common.dwAvgBytesPerSec = reorder_32 (temp_32, big_endian);
100              temp_16 = channels*bits/8;
101              swab(&temp_16, &wave.common.wBlockAlign, 2);
102              temp_16 = bits;
103              swab(&temp_16, &wave.common.wBitsPerSample, 2);
104           }
105 
106 	strncpy((char*)wave.data.id, "data",4);
107 	dummy_size -= 20+sizeof(struct common_struct);
108 
109         wave.data.len = reorder_32 (dummy_size, big_endian);
110 	if (do_write(fd, &wave, sizeof(wave)) != sizeof(wave))
111 		return 1;
112 	return 0;
113 }
114 
wav_close(int fd)115 static void wav_close(int fd)
116 {
117         unsigned int size;
118 
119 	/* Find how long our file is in total, including header */
120 	size = lseek(fd, 0, SEEK_CUR);
121 
122 	if (size < 0 )
123 	{
124 		if( fd > 2 )
125 			mjpeg_error("lseek failed - wav-header is corrupt");
126 		goto EXIT;
127 	}
128 
129 	/* Rewind file */
130 	if (lseek(fd, 0, SEEK_SET) < 0)
131 	{
132 		mjpeg_error("rewind failed - wav-header is corrupt");
133 		goto EXIT;
134 	}
135 	mjpeg_debug("Writing WAV header");
136 
137 	/* Fill out our wav-header with some information.  */
138 	size -= 8;
139         wave.riff.len = reorder_32 ((uint32_t)size, big_endian);
140 
141 	size -= 20+sizeof(struct common_struct);
142 	wave.data.len = reorder_32 ((uint32_t)size, big_endian);
143 
144 	if (do_write(fd, &wave, sizeof(wave)) < sizeof(wave))
145 	{
146 		mjpeg_error("wav-header write failed -- file is corrupt");
147 		goto EXIT;
148 	}
149 	mjpeg_info("WAV done");
150 EXIT:
151 	close(fd);
152 }
153 
154 /* The typical help output */
Usage(char * str)155 void Usage(char *str)
156 {
157    fprintf(stderr, "Usage: %s [options] inputfiles\n",str);
158    fprintf(stderr, "where options are:\n");
159    fprintf(stderr, "-o num        Start extracting at video frame (num)\n");
160    fprintf(stderr, "-f num        Extract (num) frames of audio\n");
161    fprintf(stderr, "-s/-c         Backwards compatibility options for -o/-f\n");
162    fprintf(stderr, "-v num        verbose level [0..2]\n");
163    fprintf(stderr, "-I            Ignore unsupported bitrates/bits per sample\n");
164    fprintf(stderr, "-r sr,bs,ch   If the file does not contain any sound generate silence\n");
165    fprintf(stderr, "              sr samplerate 32000,44100,48000 bs bytesize 8,16, ch channes 1/2\n");
166    fprintf(stderr, "-R            The same as -r but now a silence with 44100, 16, 2 is created\n");
167 
168    exit(0);
169 }
170 
171 /* Setting the type of silence, samplerate, bitesize, chanels */
set_silence(char * optarg)172 void set_silence (char *optarg)
173 {
174 unsigned int u1, u2, u3;
175 int i;
176 
177 i = (sscanf (optarg, "%i,%i,%i", &u1, &u2, &u3));
178 
179 if (i != 3)
180     mjpeg_error_exit1("Wrong number of arguments given to the -r option");
181 else /*Setting user chosen values */
182   {
183     if ( (u1 == 32000) || (u1 == 44100) || (u1 == 48000) )
184         silence_sr = u1;
185     else
186         mjpeg_error_exit1("Wrong sampelrate use: 32000,44100,48000, exiting");
187 
188     if ( (u2 == 8) || (u2 == 16) )
189         silence_bs = u2;
190     else
191         mjpeg_error_exit1("Wrong audio bitsize use 8 or 16, exiting");
192 
193     if ( (u3 == 1) || (u3 == 2) )
194         silence_ch = u3;
195     else
196         mjpeg_error_exit1("Wrong number of chanels use 1 or 2, exiting");
197   }
198 
199 mjpeg_info("Setting silence to %i sampelrate, %i bitsize, %i chanels",
200      silence_sr, silence_bs, silence_ch);
201 }
202 
203 int
main(argc,argv)204 main(argc, argv)
205 int     argc;
206 char    **argv;
207 {
208 	int n,f,i;
209 	int res;
210 	int warned = 0;
211 	int start_frame = 0;
212 	int num_frames = -1;
213         int ignore_bitrate = 0;
214 	int fragments;
215 
216 silence_sr=0; /* silence_sr is use for detecting if the -r option is used */
217 silence_bs=0; silence_ch=0;
218 
219     while( (n=getopt(argc,argv,"v:s:r:Rc:o:f:I")) != EOF)
220     {
221         switch(n) {
222 
223 	   case 'v':
224 		verbose = atoi(optarg);
225 		if( verbose < 0 || verbose > 2 )
226 			Usage(argv[0]);
227 		break;
228            case 'o':
229 	   case 's':
230 		start_frame = atoi(optarg);
231 		break;
232 	   case 'r':
233                 set_silence(optarg);
234                 break;
235 	   case 'R':
236 		silence_sr=44100;
237 		silence_bs=16;
238 		silence_ch=2;
239                 break;
240            case 'f':
241 	   case 'c':
242 		num_frames = atoi(optarg);
243 		break;
244 	   case 'I':
245 		ignore_bitrate = 1;
246 		break;
247 	   case '?':
248 		Usage(argv[0]);
249         }
250     }
251 
252     big_endian = lav_detect_endian();
253     if (big_endian < 0)
254 	exit(1);
255 
256     /* Open editlist */
257 	if( argc-optind < 1)
258 		Usage(argv[0]);
259 
260 	(void)mjpeg_default_handler_verbosity(verbose);
261 
262     read_video_files(argv + optind, argc - optind, &el,0);
263 
264     if(!el.has_audio)
265     {
266       if (silence_sr == 0)
267           mjpeg_error_exit1("Input file(s) have no audio, use -r to generate silence");
268      else
269         {
270 
271   mjpeg_info("mjpeg_framerate %f ", el.video_fps);
272 
273 	/* Create wav header (skeleton) on stdout ... */
274         /* audio_bits, audio_rate, audio_chans */
275 	wav_header( silence_bs, silence_sr, silence_ch, 1);
276 	/* skip to the start frame if specified */
277         f = 0;
278 	if (start_frame != 0)
279 		f = start_frame;
280 	/* num_frames = -1, read em all, else read specified # */
281 	if ( num_frames == -1)
282 		num_frames = el.video_frames;
283 
284 	fragments = silence_sr / el.video_fps;
285 
286 	/* Here is a dirty hack for the number of fragments we put out
287 	   I dont know a other way how to put out a certain number of \x00
288            So we put always 4bytes of 00h out and reduce the number of
289 	   fragments. Works perfect for PAL framerate. But in NTSC there is
290 	   a round problem. At 44k1Hz, 16bs 2ch 0,47 samples/frame
291            That means that we have on second offset per hour of film  */
292         if (silence_bs == 8)
293           fragments = fragments / 2;
294         if (silence_ch == 1)
295           fragments = fragments / 2;
296 
297 	/* Stream out audio wav-style... in per-frame chunks */
298 	for( ; f < num_frames; ++f )
299 	  {
300 	    for ( i = 0; i < fragments ; i++)
301 	 	do_write (1, "\x0000000", 4);
302 	  }
303 
304         wav_close(1);
305         exit(0);
306         }
307     }
308 
309     if (!ignore_bitrate)
310       {
311         if (el.audio_bits!=16)
312 		  mjpeg_error_exit1("Input file(s) must have 16 bit audio!");
313 
314 	switch (el.audio_rate) {
315 		case 48000 :
316 		case 44100 :
317 		case 32000 :
318 			break;
319 		default:
320 			mjpeg_error_exit1("Audio rate is %ld Hz - must be 32000, 44100 or 48000!", el.audio_rate);
321 	}
322       }
323 
324     switch (el.audio_chans) {
325 	    case 1:
326 	    case 2:
327 		    break;
328 	    default:
329 		    mjpeg_error_exit1("Audio channels %d not allowed",el.audio_chans);
330     }
331 
332     /* Create wav header (skeleton) on stdout ... */
333     wav_header( el.audio_bits, el.audio_rate, el.audio_chans, 1);
334     /* skip to the start frame if specified */
335     f = 0;
336     if (start_frame != 0)
337 	    f = start_frame;
338     /* num_frames = -1, read em all, else read specified # */
339     if ( num_frames == -1)
340 	    num_frames = el.video_frames;
341 
342     /* Stream out audio wav-style... in per-frame chunks */
343     for( ; f < num_frames; ++f )
344     {
345 	    n = el_get_audio_data(audio_buff, f, &el, 0);
346 	    if (n < 0)
347 	       mjpeg_error_exit1( "Couldn't get audio for frame %d!", f);
348 	    if( n != 0 )
349 	    {
350 		    res = do_write( 1, audio_buff, n );
351 		    if (res != n)
352 		      mjpeg_error_exit1("Couldn't write audio for frame %d!",f);
353 	    }
354 
355 	    else if( f < num_frames && ! warned )
356 	    {
357 		    mjpeg_warn("audio ends early at frame %d", f);
358 		    warned = 1;
359 	    }
360     }
361 
362     wav_close(1);
363     exit(0);
364 }
365