]> git.sesse.net Git - ffmpeg/blobdiff - ffmpeg.c
* fixing bug that prevented resampling the picture and
[ffmpeg] / ffmpeg.c
index 47fc9ff69d60fa7f4eb193159af0e0f8ac715b91..697005458921bc963a614f60034e9361eb8666f1 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #define HAVE_AV_CONFIG_H
-#include "common.h"
 #include "avformat.h"
 #include "framehook.h"
-/* usleep() */
-#include "os_support.h"
 
 #ifndef CONFIG_WIN32
 #include <unistd.h>
@@ -38,7 +35,6 @@
 #include <stdlib.h>
 #endif
 #include <time.h>
-#include <ctype.h>
 
 #include "cmdutils.h"
 
@@ -114,10 +110,8 @@ static int same_quality = 0;
 static int b_frames = 0;
 static int mb_decision = FF_MB_DECISION_SIMPLE;
 static int use_4mv = 0;
-/* Fx */
 static int use_aic = 0;
 static int use_umv = 0;
-/* /Fx */
 static int do_deinterlace = 0;
 static int workaround_bugs = FF_BUG_AUTODETECT;
 static int error_resilience = 2;
@@ -128,6 +122,7 @@ static int use_part = 0;
 static int packet_size = 0;
 static int strict = 0;
 static int debug = 0;
+extern int loop_input; /* currently a hack */
 
 static int gop_size = 12;
 static int intra_only = 0;
@@ -163,6 +158,10 @@ static char *video_standard = "ntsc";
 static char *audio_grab_format = "audio_device";
 static char *audio_device = NULL;
 
+static int using_stdin = 0;
+static int using_vhook = 0;
+static int verbose = 1;
+
 #define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
 
 typedef struct AVOutputStream {
@@ -293,6 +292,8 @@ static int read_key(void)
 
 #else
 
+static volatile int received_sigterm = 0;
+
 /* no interactive support */
 static void term_exit(void)
 {
@@ -411,7 +412,7 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void
     dec = &ist->st->codec;
 
     /* deinterlace : must be done before any resize */
-    if (do_deinterlace) {
+    if (do_deinterlace || using_vhook) {
         int size;
 
         /* create temporary picture */
@@ -423,12 +424,22 @@ static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void
         picture2 = &picture_tmp;
         avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
 
-        if (avpicture_deinterlace(picture2, picture, 
-                                  dec->pix_fmt, dec->width, dec->height) < 0) {
-            /* if error, do not deinterlace */
-            av_free(buf);
-            buf = NULL;
-            picture2 = picture;
+        if (do_deinterlace){
+            if(avpicture_deinterlace(picture2, picture, 
+                                     dec->pix_fmt, dec->width, dec->height) < 0) {
+                /* if error, do not deinterlace */
+                av_free(buf);
+                buf = NULL;
+                picture2 = picture;
+            }
+        } else {
+            if (img_convert(picture2, dec->pix_fmt, picture, 
+                            dec->pix_fmt, dec->width, dec->height) < 0) {
+                /* if error, do not copy */
+                av_free(buf);
+                buf = NULL;
+                picture2 = picture;
+            }
         }
     } else {
         picture2 = picture;
@@ -456,6 +467,7 @@ static void do_video_out(AVFormatContext *s,
     static uint8_t *video_buffer;
     uint8_t *buf = NULL, *buf1 = NULL;
     AVCodecContext *enc, *dec;
+    enum PixelFormat target_pixfmt;
 
 #define VIDEO_BUFFER_SIZE (1024*1024)
 
@@ -523,7 +535,8 @@ static void do_video_out(AVFormatContext *s,
         return;
 
     /* convert pixel format if needed */
-    if (enc->pix_fmt != dec->pix_fmt) {
+    target_pixfmt = ost->video_resample ? PIX_FMT_YUV420P : enc->pix_fmt;
+    if (dec->pix_fmt != target_pixfmt) {
         int size;
 
         /* create temporary picture */
@@ -534,7 +547,7 @@ static void do_video_out(AVFormatContext *s,
         formatted_picture = &picture_format_temp;
         avpicture_fill(formatted_picture, buf, enc->pix_fmt, dec->width, dec->height);
         
-        if (img_convert(formatted_picture, enc->pix_fmt, 
+        if (img_convert(formatted_picture, target_pixfmt, 
                         in_picture, dec->pix_fmt, 
                         dec->width, dec->height) < 0) {
             fprintf(stderr, "pixel format conversion not handled\n");
@@ -550,6 +563,25 @@ static void do_video_out(AVFormatContext *s,
     if (ost->video_resample) {
         final_picture = &ost->pict_tmp;
         img_resample(ost->img_resample_ctx, final_picture, formatted_picture);
+       if (enc->pix_fmt != PIX_FMT_YUV420P) {
+            int size;
+           
+           av_free(buf);
+            /* create temporary picture */
+            size = avpicture_get_size(enc->pix_fmt, enc->width, enc->height);
+            buf = av_malloc(size);
+            if (!buf)
+                return;
+            final_picture = &picture_format_temp;
+            avpicture_fill(final_picture, buf, enc->pix_fmt, enc->width, enc->height);
+        
+            if (img_convert(final_picture, enc->pix_fmt, 
+                            &ost->pict_tmp, PIX_FMT_YUV420P, 
+                            enc->width, enc->height) < 0) {
+                fprintf(stderr, "pixel format conversion not handled\n");
+                goto the_end;
+            }
+       }
     } else if (ost->video_crop) {
         picture_crop_temp.data[0] = formatted_picture->data[0] +
                 (ost->topBand * formatted_picture->linesize[0]) + ost->leftBand;
@@ -723,20 +755,20 @@ static void print_report(AVFormatContext **output_files,
     }
     if (ti1 < 0.01)
         ti1 = 0.01;
-    bitrate = (double)(total_size * 8) / ti1 / 1000.0;
     
-    sprintf(buf + strlen(buf), 
+    if (verbose || is_last_report) {
+        bitrate = (double)(total_size * 8) / ti1 / 1000.0;
+        
+        sprintf(buf + strlen(buf), 
             "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
             (double)total_size / 1024, ti1, bitrate);
-    
-    fprintf(stderr, "%s   ", buf);
-    
-    if (is_last_report) {
-        fprintf(stderr, "\n");
-    } else {
-        fprintf(stderr, "\r");
+        
+        fprintf(stderr, "%s    \r", buf);
         fflush(stderr);
     }
+        
+    if (is_last_report)
+        fprintf(stderr, "\n");
 }
 
 /*
@@ -1110,18 +1142,20 @@ static int av_encode(AVFormatContext **output_files,
         ist = ist_table[i];
        is = input_files[ist->file_index];
         ist->pts = 0;
-        switch (ist->st->codec.codec_type) {
-        case CODEC_TYPE_AUDIO:
-           av_frac_init(&ist->next_pts, 
-                        0, 0, is->pts_num * ist->st->codec.sample_rate);
-            break;
-        case CODEC_TYPE_VIDEO:
-            av_frac_init(&ist->next_pts, 
-                        0, 0, is->pts_num * ist->st->codec.frame_rate);
-            break;
-        default:
-            break;
-       }
+        if (ist->decoding_needed) {
+            switch (ist->st->codec.codec_type) {
+            case CODEC_TYPE_AUDIO:
+                av_frac_init(&ist->next_pts, 
+                             0, 0, (uint64_t)is->pts_num * ist->st->codec.sample_rate);
+                break;
+            case CODEC_TYPE_VIDEO:
+                av_frac_init(&ist->next_pts, 
+                             0, 0, (uint64_t)is->pts_num * ist->st->codec.frame_rate);
+                break;
+            default:
+                break;
+            }
+        }
     }
     
     /* compute buffer size max (should use a complete heuristic) */
@@ -1140,14 +1174,15 @@ static int av_encode(AVFormatContext **output_files,
     }
 
 #ifndef CONFIG_WIN32
-    fprintf(stderr, "Press [q] to stop encoding\n");
+    if ( !using_stdin )
+        fprintf(stderr, "Press [q] to stop encoding\n");
 #endif
     term_init();
 
     stream_no_data = 0;
     key = -1;
 
-    for(;;) {
+    for(; received_sigterm == 0;) {
         int file_index, ist_index;
         AVPacket pkt;
         uint8_t *ptr;
@@ -1161,7 +1196,7 @@ static int av_encode(AVFormatContext **output_files,
         
     redo:
         /* if 'q' pressed, exits */
-        if (key) {
+        if (!using_stdin) {
             /* read_key() returns 0 on EOF */
             key = read_key();
             if (key == 'q')
@@ -1261,7 +1296,7 @@ static int av_encode(AVFormatContext **output_files,
                     }
                     data_buf = (uint8_t *)samples;
                    av_frac_add(&ist->next_pts, 
-                               is->pts_den * data_size / (2 * ist->st->codec.channels));
+                               (uint64_t)is->pts_den * data_size / (2 * ist->st->codec.channels));
                     break;
                 case CODEC_TYPE_VIDEO:
                     {
@@ -1286,7 +1321,7 @@ static int av_encode(AVFormatContext **output_files,
                             continue;
                         }
                         av_frac_add(&ist->next_pts, 
-                                   is->pts_den * ist->st->codec.frame_rate_base);          
+                                   (uint64_t)is->pts_den * ist->st->codec.frame_rate_base);          
                     }
                     break;
                 default:
@@ -1590,6 +1625,11 @@ static void opt_debug(const char *arg)
     debug = atoi(arg);
 }
 
+static void opt_verbose(const char *arg)
+{
+    verbose = atoi(arg);
+}
+
 static void opt_frame_rate(const char *arg)
 {
     if (parse_frame_rate(&frame_rate, &frame_rate_base, arg) < 0) {
@@ -1903,6 +1943,8 @@ static void add_frame_hooker(const char *arg)
     int i;
     char *args = av_strdup(arg);
 
+    using_vhook = 1;
+
     argv[0] = strtok(args, " ");
     while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
     }
@@ -1992,6 +2034,9 @@ static void opt_input_file(const char *filename)
     if (!strcmp(filename, "-"))
         filename = "pipe:";
 
+    using_stdin |= !strcmp(filename, "pipe:" ) || 
+                   !strcmp( filename, "/dev/stdin" );
+
     /* get default parameters from command line */
     memset(ap, 0, sizeof(*ap));
     ap->sample_rate = audio_sample_rate;
@@ -2168,6 +2213,9 @@ static void opt_output_file(const char *filename)
             avcodec_get_context_defaults(&st->codec);
 
             video_enc = &st->codec;
+            
+            if(!strcmp(file_oformat->name, "mp4") || !strcmp(file_oformat->name, "mov") || !strcmp(file_oformat->name, "3gp"))
+                video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
             if (video_stream_copy) {
                 st->stream_copy = 1;
                 video_enc->codec_type = CODEC_TYPE_VIDEO;
@@ -2205,14 +2253,12 @@ static void opt_output_file(const char *filename)
 
                 video_enc->mb_decision = mb_decision;
                 
-               /* Fx */ 
                 if (use_umv) {
                     video_enc->flags |= CODEC_FLAG_H263P_UMV;
                 }
                if (use_aic) {
                     video_enc->flags |= CODEC_FLAG_H263P_AIC;
                 }
-               /* /Fx */ 
                 if (use_4mv) {
                     video_enc->mb_decision = FF_MB_DECISION_BITS; //FIXME remove
                     video_enc->flags |= CODEC_FLAG_4MV;
@@ -2369,13 +2415,19 @@ static void opt_output_file(const char *filename)
             if (url_exist(filename)) {
                 int c;
                 
-                printf("File '%s' already exists. Overwrite ? [y/N] ", filename);
-                fflush(stdout);
-                c = getchar();
-                if (toupper(c) != 'Y') {
-                    fprintf(stderr, "Not overwriting - exiting\n");
+                if ( !using_stdin ) {
+                    fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
+                    fflush(stderr);
+                    c = getchar();
+                    if (toupper(c) != 'Y') {
+                        fprintf(stderr, "Not overwriting - exiting\n");
+                        exit(1);
+                    }
+                               }
+                               else {
+                    fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
                     exit(1);
-                }
+                               }
             }
         }
         
@@ -2580,7 +2632,7 @@ static void show_formats(void)
         printf(" %s:", up->name);
     printf("\n");
     
-    printf("Frame size, frame rate abbreviations: ntsc pal film ntsc-film sqcif qcif cif 4cif\n");
+    printf("Frame size, frame rate abbreviations: ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n");
     printf("Motion estimation methods:");
     pp = motion_str;
     while (*pp) {
@@ -2618,12 +2670,13 @@ const OptionDef options[] = {
     { "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump}, 
       "dump each input packet" },
     { "bitexact", OPT_EXPERT, {(void*)opt_bitexact}, "only use bit exact algorithms (for codec testing)" }, 
-
+    { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" },
+    { "loop", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" },
+    { "v", HAS_ARG, {(void*)opt_verbose}, "control amount of logging", "verbose" },
 
     /* video options */
     { "b", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" },
     { "r", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_rate}, "set frame rate (Hz value, fraction or abbreviation)", "rate" },
-    { "re", OPT_BOOL|OPT_EXPERT | OPT_VIDEO, {(void*)&rate_emu}, "read input at native frame rate" },
     { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
     { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
     { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
@@ -2649,7 +2702,7 @@ const OptionDef options[] = {
     { "i_qoffset", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_i_qoffset}, "qp offset between p and i frames", "offset" },
 //    { "b_strategy", HAS_ARG | OPT_EXPERT, {(void*)opt_b_strategy}, "dynamic b frame selection strategy", "strategy" },
     { "rc_eq", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_eq}, "set rate control equation", "equation" },
-    { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific internals", "override_string" },
+    { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
     { "bt", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_tolerance}, "set video bitrate tolerance (in kbit/s)", "tolerance" },
     { "maxrate", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_max}, "set max video bitrate tolerance (in kbit/s)", "bitrate" },
     { "minrate", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_min}, "set min video bitrate tolerance (in kbit/s)", "bitrate" },
@@ -2660,8 +2713,8 @@ const OptionDef options[] = {
     { "dct_algo", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_dct_algo}, "set dct algo",  "algo" },
     { "idct_algo", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_idct_algo}, "set idct algo",  "algo" },
     { "er", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_error_resilience}, "set error resilience",  "n" },
-    { "ec", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_error_concealment}, "set error concealment",  "n" },
-    { "bf", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" },
+    { "ec", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_error_concealment}, "set error concealment",  "bit_mask" },
+    { "bf", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_frames}, "use 'frames' B frames", "frames" },
     { "hq", OPT_BOOL, {(void*)&mb_decision}, "activate high quality settings" },
     { "mbd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_decision}, "macroblock decision", "mode" },
     { "4mv", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" },
@@ -2678,10 +2731,8 @@ const OptionDef options[] = {
     { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
     { "vstats", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_vstats}, "dump video coding statistics to file" }, 
     { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
-    /* Fx */
     { "aic", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_aic}, "enable Advanced intra coding (h263+)" },
     { "umv", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_umv}, "enable Unlimited Motion Vector (h263+)" },
-    /* /Fx */
 
     /* audio options */
     { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },