]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - ffmpeg.c
test
[frescor/ffmpeg.git] / ffmpeg.c
1 /*
2  * Basic user interface for ffmpeg system
3  * Copyright (c) 2000 Gerard Lantau
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <netinet/in.h>
22 #include <linux/videodev.h>
23 #include <linux/soundcard.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/ioctl.h>
27 #include <sys/mman.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <getopt.h>
31
32 #include "mpegenc.h"
33 #include "mpegvideo.h"
34
35 static AVFormat *file_format;
36 static int frame_width  = 160;
37 static int frame_height = 128;
38 static int frame_rate = 25;
39 static int bit_rate = 200000;
40 static int video_disable = 0;
41
42 static const char *video_filename, *audio_filename;
43 static float recording_time = 10.0;
44 static int nb_frames;
45 static int gop_size = 12;
46 static int intra_only = 0;
47 static int audio_freq = 44100;
48 static int audio_bit_rate = 64000;
49 static int audio_disable = 0;
50 static int audio_channels = 1;
51
52 static long long time_start;
53
54
55 static int file_read_picture(AVEncodeContext *s, 
56                              UINT8 *picture[3],
57                              int width, int height,
58                              int picture_number)
59 {
60     FILE *f;
61     char buf[1024];
62     static int init = 0;
63     static UINT8 *pict[3];
64     if (!init) {
65         pict[0] = malloc(width * height);
66         pict[1] = malloc(width * height / 4);
67         pict[2] = malloc(width * height / 4);
68         init = 1;
69     }
70     
71     picture[0] = pict[0];
72     picture[1] = pict[1];
73     picture[2] = pict[2];
74
75     sprintf(buf, "%s%d.Y", video_filename, picture_number);
76     f=fopen(buf, "r");
77     if (!f) {
78         return -1;
79     }
80
81     fread(picture[0], 1, width * height, f);
82     fclose(f);
83
84     sprintf(buf, "%s%d.U", video_filename, picture_number);
85     f=fopen(buf, "r");
86     if (!f) {
87         perror(buf);
88         exit(1);
89     }
90     fread(picture[1], 1, width * height / 4, f);
91     fclose(f);
92     
93     sprintf(buf, "%s%d.V", video_filename, picture_number);
94     f=fopen(buf, "r");
95     if (!f) {
96         perror(buf);
97         exit(1);
98     }
99     fread(picture[2], 1, width * height / 4, f);
100     fclose(f);
101     return 0;
102 }
103
104 static void display_stats(AVEncodeContext *video_ctx, 
105                           AVEncodeContext *audio_ctx,
106                           int batch_mode, int the_end)
107 {
108     if (video_ctx && 
109         ((video_ctx->frame_number % video_ctx->rate) == 0 || 
110         the_end)) {
111         float ti;
112         
113         if (batch_mode) {
114             ti = (float)video_ctx->frame_number / video_ctx->rate;
115         } else {
116             ti = (gettime() - time_start) / 1000000.0;
117             if (ti < 0.1)
118                     ti = 0.1;
119         }
120         
121         fprintf(stderr,
122                 "frame=%5d size=%8dkB time=%0.1f fps=%4.1f bitrate=%6.1fkbits/s q=%2d\r", 
123                 video_ctx->frame_number,
124                 data_out_size / 1024,
125                 ti,
126                 video_ctx->frame_number / ti,
127                 (data_out_size * 8 / ti / 1000),
128                 ((MpegEncContext *)video_ctx->priv_data)->qscale);
129         if (the_end) {
130             fprintf(stderr,"\n");
131         }
132         fflush(stderr);
133     }
134 #if 0
135     if (the_end && batch_mode && audio_ctx) {
136         duration = (gettime() - ti) / 1000000.0;
137         factor = 0;
138         if (ti > 0) {
139             factor = (float)nb_samples / s->sample_rate / duration;
140         }
141         fprintf(stderr, "%0.1f seconds compressed in %0.1f seconds (speed factor: %0.1f)\n",
142                 (float)nb_samples / s->sample_rate, 
143                 duration,
144                 factor);
145     }
146 #endif
147 }
148
149 void raw_write_data(void *opaque, 
150                     unsigned char *buf, int size)
151 {
152     FILE *outfile = opaque;
153     fwrite(buf, 1, size, outfile);
154     data_out_size += size;
155 }
156
157 int raw_seek(void *opaque, long long offset, int whence)
158 {
159     FILE *outfile = opaque;
160     fseek(outfile, offset, whence);
161     return 0;
162 }
163
164 static void av_encode(AVFormatContext *ctx,
165                       const char *video_filename,
166                       const char *audio_filename)
167 {
168     UINT8 audio_buffer[4096];
169     UINT8 video_buffer[128*1024];
170     char buf[256];
171     short *samples;
172     int ret;
173     int audio_fd;
174     FILE *infile;
175     int sample_count;
176     int batch_mode;
177     AVEncodeContext *audio_enc, *video_enc;
178     int frame_size, frame_bytes;
179     AVEncoder *audio_encoder, *video_encoder;
180     UINT8 *picture[3];
181
182     /* audio */
183     audio_enc = ctx->audio_enc;
184     sample_count = 0;
185     infile = NULL;
186     frame_size = 0;
187     samples = NULL;
188     audio_fd = -1;
189     frame_bytes = 0;
190     batch_mode = 0;
191     if (audio_filename ||
192         video_filename)
193         batch_mode = 1;
194     
195     if (audio_enc) {
196         if (batch_mode) {
197             if (!audio_filename) {
198                 fprintf(stderr, "Must give audio input file\n");
199                 exit(1);
200             }
201             infile = fopen(audio_filename, "r");
202             if (!infile) {
203                 fprintf(stderr, "Could not open '%s'\n", audio_filename);
204                 exit(1);
205             }
206             audio_fd = -1;
207         } else {
208             audio_fd = audio_open(audio_enc->rate, audio_enc->channels);
209             if (audio_fd < 0) {
210                 fprintf(stderr, "Could not open audio device\n");
211                 exit(1);
212             }
213         }
214         
215         audio_encoder = avencoder_find(ctx->format->audio_codec);
216         if (avencoder_open(audio_enc, audio_encoder) < 0) {
217             fprintf(stderr, "Audio encoder: incorrect audio frequency or bitrate\n");
218             exit(1);
219         }
220         avencoder_string(buf, sizeof(buf), audio_enc);
221         fprintf(stderr, "  %s\n", buf);
222         
223         frame_size = audio_enc->frame_size;
224         
225         frame_bytes = frame_size * 2 * audio_enc->channels;
226         samples = malloc(frame_bytes);
227     }
228
229     /* video */
230     video_enc = ctx->video_enc;
231     if (video_enc) {
232         if (batch_mode) {
233             if (!video_filename) {
234                 fprintf(stderr, "Must give video input file\n");
235                 exit(1);
236             }
237         } else {
238             ret = v4l_init(video_enc->rate, video_enc->width, video_enc->height);
239             if (ret < 0) {
240                 fprintf(stderr,"Could not init video 4 linux capture\n");
241                 exit(1);
242             }
243         }
244         
245         video_encoder = avencoder_find(ctx->format->video_codec);
246         if (avencoder_open(video_enc, video_encoder) < 0) {
247             fprintf(stderr, "Error while initializing video codec\n");
248             exit(1);
249         }
250
251         avencoder_string(buf, sizeof(buf), video_enc);
252         fprintf(stderr, "  %s\n", buf);
253     }
254     
255     ctx->format->write_header(ctx);
256     time_start = gettime();
257
258     for(;;) {
259         /* read & compression audio frames */
260         if (audio_enc) {
261             if (!batch_mode) {
262                 for(;;) {
263                     ret = read(audio_fd, samples, frame_bytes);
264                     if (ret != frame_bytes)
265                         break;
266                     ret = avencoder_encode(audio_enc,
267                                            audio_buffer, sizeof(audio_buffer), samples);
268                     ctx->format->write_audio_frame(ctx, audio_buffer, ret);
269                 }
270             } else {
271                 if (video_enc)
272                     sample_count += audio_enc->rate / video_enc->rate;
273                 else
274                     sample_count += frame_size;
275                 while (sample_count > frame_size) {
276                     if (fread(samples, 1, frame_bytes, infile) == 0)
277                         goto the_end;
278                     
279                     ret = avencoder_encode(audio_enc,
280                                            audio_buffer, sizeof(audio_buffer), samples);
281                     ctx->format->write_audio_frame(ctx, audio_buffer, ret);
282
283                     sample_count -= frame_size;
284                 }
285             }
286         }
287
288         if (video_enc) {
289             /* read video image */
290             if (batch_mode) {
291                 ret = file_read_picture (video_enc, picture, 
292                                          video_enc->width, video_enc->height, 
293                                          video_enc->frame_number);
294             } else {
295                 ret = v4l_read_picture (picture, 
296                                         video_enc->width, video_enc->height, 
297                                         video_enc->frame_number);
298             }
299             if (ret < 0)
300                 break;
301             ret = avencoder_encode(video_enc, video_buffer, sizeof(video_buffer), picture);
302             ctx->format->write_video_picture(ctx, video_buffer, ret);
303         }
304         
305         display_stats(video_enc, NULL, batch_mode, 0);
306         if (video_enc && video_enc->frame_number >= nb_frames)
307             break;
308     }
309  the_end:
310     display_stats(video_enc, NULL, batch_mode, 1);
311
312     if (video_enc)
313         avencoder_close(video_enc);
314
315     if (audio_enc)
316         avencoder_close(audio_enc);
317     
318     ctx->format->write_trailer(ctx);
319
320     if (!infile) {
321         close(audio_fd);
322     } else {
323         fclose(infile);
324     }
325 }
326
327 typedef struct {
328     const char *str;
329     int width, height;
330 } SizeEntry;
331
332 SizeEntry sizes[] = {
333     { "sqcif", 128, 96 },
334     { "qcif", 176, 144 },
335     { "cif", 352, 288 },
336     { "4cif", 704, 576 },
337 };
338     
339 enum {
340     OPT_AR=256,
341     OPT_AB,
342     OPT_AN,
343     OPT_AC,
344     OPT_VN,
345 };
346
347 struct option long_options[] =
348 {
349     { "ar", required_argument, NULL, OPT_AR },
350     { "ab", required_argument, NULL, OPT_AB },
351     { "an", no_argument, NULL, OPT_AN },
352     { "ac", required_argument, NULL, OPT_AC },
353     { "vn", no_argument, NULL, OPT_VN },
354 };
355
356 enum {
357     OUT_FILE,
358     OUT_PIPE,
359     OUT_UDP,
360 };
361
362
363 void help(void)
364 {
365     AVFormat *f;
366
367     printf("ffmpeg version 1.0, Copyright (c) 2000 Gerard Lantau\n"
368            "usage: ffmpeg [options] outfile [video_infile] [audio_infile]\n"
369            "Hyper fast MPEG1 video/H263/RV and AC3/MPEG audio layer 2 encoder\n"
370            "\n"
371            "Main options are:\n"
372            "\n"
373            "-L           print the LICENSE\n"
374            "-s size      set frame size                   [%dx%d]\n"
375            "-f format    set encoding format              [%s]\n"
376            "-r fps       set frame rate                   [%d]\n"
377            "-b bitrate   set the total bitrate in kbit/s  [%d]\n"
378            "-t time      set recording time in seconds    [%0.1f]\n"
379            "-ar freq     set the audio sampling freq      [%d]\n"
380            "-ab bitrate  set the audio bitrate in kbit/s  [%d]\n"
381            "-ac channels set the number of audio channels [%d]\n"
382            "-an          disable audio recording          [%s]\n"
383            "-vn          disable video recording          [%s]\n"
384            "\n"
385            "Frame sizes abbreviations: sqcif qcif cif 4cif\n",
386            frame_width, frame_height,
387            file_format->name,
388            frame_rate,
389            bit_rate / 1000,
390            recording_time,
391            audio_freq,
392            audio_bit_rate / 1000,
393            audio_channels,
394            audio_disable ? "yes" : "no",
395            video_disable ? "yes" : "no");
396
397     printf("Encoding video formats:");
398     for(f = first_format; f != NULL; f = f->next)
399         printf(" %s", f->name);
400     printf("\n");
401
402     printf("outfile can be a file name, - (pipe) or 'udp:host:port'\n"
403            "\n"
404            "Advanced options are:\n"
405            "-d device    set video4linux device name\n"
406            "-g gop_size  set the group of picture size    [%d]\n"
407            "-i           use only intra frames            [%s]\n"
408            "-c comment   set the comment string\n"
409            "\n",
410            gop_size,
411            intra_only ? "yes" : "no");
412 }
413
414 void licence(void)
415 {
416     printf(
417     "ffmpeg version 1.0\n"
418     "Copyright (c) 2000 Gerard Lantau\n"
419     "This program is free software; you can redistribute it and/or modify\n"
420     "it under the terms of the GNU General Public License as published by\n"
421     "the Free Software Foundation; either version 2 of the License, or\n"
422     "(at your option) any later version.\n"
423     "\n"
424     "This program is distributed in the hope that it will be useful,\n"
425     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
426     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
427     "GNU General Public License for more details.\n"
428     "\n"
429     "You should have received a copy of the GNU General Public License\n"
430     "along with this program; if not, write to the Free Software\n"
431     "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
432     );
433 }
434
435 static unsigned char output_buffer[32768];
436
437 int main(int argc, char **argv)
438 {
439     AVEncodeContext video_enc1, *video_enc = &video_enc1;
440     AVEncodeContext audio_enc1, *audio_enc = &audio_enc1;
441     UDPContext udp_ctx1, *udp_ctx = &udp_ctx1;
442     AVFormatContext av_ctx1, *av_ctx = &av_ctx1;
443     FILE *outfile;
444     int i, c;
445     char *filename;
446     int output_type;
447     int use_video, use_audio;
448
449     register_avencoder(&ac3_encoder);
450     register_avencoder(&mp2_encoder);
451     register_avencoder(&mpeg1video_encoder);
452     register_avencoder(&h263_encoder);
453     register_avencoder(&rv10_encoder);
454     register_avencoder(&mjpeg_encoder);
455
456     register_avformat(&mp2_format);
457     register_avformat(&ac3_format);
458     register_avformat(&mpeg1video_format);
459     register_avformat(&h263_format);
460     register_avformat(&mpeg_mux_format);
461     register_avformat(&ra_format);
462     register_avformat(&rm_format);
463     register_avformat(&asf_format);
464     register_avformat(&mpjpeg_format);
465     register_avformat(&swf_format);
466
467     file_format = NULL;
468     
469     for(;;) {
470         c = getopt_long_only(argc, argv, "s:f:r:b:t:hd:g:ic:L", 
471                              long_options, NULL);
472         if (c == -1)
473             break;
474         switch(c) {
475         case 'L':
476             licence();
477             exit(1);
478         case 'h':
479             help();
480             exit(1);
481         case 's':
482             {
483                 int n = sizeof(sizes) / sizeof(SizeEntry);
484                 const char *p;
485
486                 for(i=0;i<n;i++) {
487                     if (!strcmp(sizes[i].str, optarg)) {
488                         frame_width = sizes[i].width;
489                         frame_height = sizes[i].height;
490                         break;
491                     }
492                 }
493                 if (i == n) {
494                     p = optarg;
495                     frame_width = strtol(p, (char **)&p, 10);
496                     if (*p)
497                         p++;
498                     frame_height = strtol(p, (char **)&p, 10);
499                 }
500             }
501             break;
502         case 'f':
503             {
504                 AVFormat *f;
505                 f = first_format;
506                 while (f != NULL && strcmp(f->name, optarg) != 0) f = f->next;
507                 if (f == NULL) {
508                     fprintf(stderr, "Invalid format: %s\n", optarg);
509                     exit(1);
510                 }
511                 file_format = f;
512             }
513             break;
514         case 'r':
515             {
516                 frame_rate = atoi(optarg);
517             }
518             break;
519         case 'b':
520             {
521                 bit_rate = atoi(optarg) * 1000;
522             }
523             break;
524         case 't':
525             {
526                 recording_time = atof(optarg);
527                 break;
528             }
529             /* audio specific */
530         case OPT_AR:
531             {
532                 audio_freq = atoi(optarg);
533                 break;
534             }
535         case OPT_AB:
536             {
537                 audio_bit_rate = atoi(optarg) * 1000;
538                 break;
539             }
540         case OPT_AN:
541             audio_disable = 1;
542             break;
543         case OPT_VN:
544             video_disable = 1;
545             break;
546         case OPT_AC:
547             {
548                 audio_channels = atoi(optarg);
549                 if (audio_channels != 1 && 
550                     audio_channels != 2) {
551                     fprintf(stderr, "Incorrect number of channels: %d\n", audio_channels);
552                     exit(1);
553                 }
554             }
555             break;
556             /* advanced options */
557         case 'd':
558             v4l_device = optarg;
559             break;
560         case 'g':
561             gop_size = atoi(optarg);
562             break;
563         case 'i':
564             intra_only = 1;
565             break;
566         case 'c':
567             comment_string = optarg;
568             break;
569         default:
570             exit(2);
571         }
572     }
573
574     if (optind >= argc) {
575         help();
576         exit(1);
577     }
578
579     filename = argv[optind++];
580     video_filename = NULL;
581     audio_filename = NULL;
582
583     /* auto detect format */
584     if (file_format == NULL)
585         file_format = guess_format(NULL, filename, NULL);
586
587     if (file_format == NULL)
588         file_format = &mpeg_mux_format;
589
590     /* check parameters */
591     if (frame_width <= 0 || frame_height <= 0) {
592         fprintf(stderr, "Incorrect frame size\n");
593         exit(1);
594     }
595     if ((frame_width % 16) != 0 || (frame_height % 16) != 0) {
596         fprintf(stderr, "Frame size must be a multiple of 16\n");
597         exit(1);
598     }
599     
600     if (bit_rate < 5000 || bit_rate >= 10000000) {
601         fprintf(stderr, "Invalid bit rate\n");
602         exit(1);
603     }
604
605     if (frame_rate < 1 || frame_rate >= 60) {
606         fprintf(stderr, "Invalid frame rate\n");
607         exit(1);
608     }
609
610     nb_frames = (int)(recording_time * frame_rate);
611     if (nb_frames < 1) {
612         fprintf(stderr, "Invalid recording time\n");
613         exit(1);
614     }
615
616     use_video = file_format->video_codec != CODEC_ID_NONE;
617     use_audio = file_format->audio_codec != CODEC_ID_NONE;
618     if (audio_disable) {
619         use_audio = 0;
620     }
621     if (video_disable) {
622         use_video = 0;
623     }
624         
625     if (use_video == 0 && use_audio == 0) {
626         fprintf(stderr, "No audio or video selected\n");
627         exit(1);
628     }
629
630     fprintf(stderr, "Recording: %s, %0.1f seconds\n",
631             file_format->name, 
632             recording_time);
633
634     /* open output media */
635
636     if (strstart(filename, "udp:", NULL)) {
637         output_type = OUT_UDP;
638         outfile = NULL;
639         memset(udp_ctx, 0, sizeof(*udp_ctx));
640         if (udp_tx_open(udp_ctx, filename, 0) < 0) {
641             fprintf(stderr, "Could not open UDP socket\n");
642             exit(1);
643         }
644     } else if (!strcmp(filename, "-")) {
645         output_type = OUT_PIPE;
646         outfile = stdout;
647     } else {
648         output_type = OUT_FILE;
649         outfile = fopen(filename, "w");
650         if (!outfile) {
651             perror(filename);
652             exit(1);
653         }
654     }
655
656     av_ctx->video_enc = NULL;
657     av_ctx->audio_enc = NULL;
658
659     if (output_type == OUT_UDP) {
660         init_put_byte(&av_ctx->pb, output_buffer, sizeof(output_buffer),
661                       udp_ctx, udp_write_data, NULL);
662     } else {
663         init_put_byte(&av_ctx->pb, output_buffer, sizeof(output_buffer),
664                       outfile, raw_write_data, raw_seek);
665     }
666
667     if (use_video) {
668         if (optind < argc) {
669             video_filename = argv[optind++];
670         }
671         /* init mpeg video encoding context */
672         memset(video_enc, 0, sizeof(*video_enc));
673         video_enc->bit_rate = bit_rate;
674         video_enc->rate = frame_rate; 
675
676         video_enc->width = frame_width;
677         video_enc->height = frame_height;
678         if (!intra_only)
679             video_enc->gop_size = gop_size;
680         else
681             video_enc->gop_size = 0;
682
683         av_ctx->video_enc = video_enc;
684         av_ctx->format = file_format;
685     }
686
687     if (use_audio) {
688         if (optind < argc) {
689             audio_filename = argv[optind++];
690         }
691         audio_enc->bit_rate = audio_bit_rate;
692         audio_enc->rate = audio_freq;
693         audio_enc->channels = audio_channels;
694         av_ctx->audio_enc = audio_enc;
695     }
696     av_ctx->format = file_format;
697     av_ctx->is_streamed = 0;
698
699     av_encode(av_ctx, video_filename, audio_filename);
700
701     /* close output media */
702
703     switch(output_type) {
704     case OUT_FILE:
705         fclose(outfile);
706         break;
707     case OUT_PIPE:
708         break;
709     case OUT_UDP:
710         udp_tx_close(udp_ctx);
711         break;
712     }
713     fprintf(stderr, "\n");
714     
715     return 0;
716 }
717