]> git.sesse.net Git - ffmpeg/blobdiff - ffmpeg.c
init has_b_frames for stream copy
[ffmpeg] / ffmpeg.c
index eabebb760d565ced32ce579dfa9480df79ffb877..1a63076c62a6fddf4c28e78b7e60f7b13bcb46a0 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -106,10 +106,13 @@ static int video_qmin = 2;
 static int video_qmax = 31;
 static int video_lmin = 2*FF_QP2LAMBDA;
 static int video_lmax = 31*FF_QP2LAMBDA;
-static int video_mb_qmin = 2;
-static int video_mb_qmax = 31;
+static int video_mb_lmin = 2*FF_QP2LAMBDA;
+static int video_mb_lmax = 31*FF_QP2LAMBDA;
 static int video_qdiff = 3;
+static int video_lelim = 0;
+static int video_celim = 0;
 static float video_qblur = 0.5;
+static float video_qsquish = 0.0;
 static float video_qcomp = 0.5;
 static uint16_t *intra_matrix = NULL;
 static uint16_t *inter_matrix = NULL;
@@ -133,6 +136,7 @@ static int video_intra_quant_bias= FF_DEFAULT_QUANT_BIAS;
 static int video_inter_quant_bias= FF_DEFAULT_QUANT_BIAS;
 static int me_method = ME_EPZS;
 static int video_disable = 0;
+static int video_discard = 0;
 static int video_codec_id = CODEC_ID_NONE;
 static int video_codec_tag = 0;
 static int same_quality = 0;
@@ -162,9 +166,12 @@ static int use_scan_offset = 0;
 static int use_qpel = 0;
 static int use_qprd = 0;
 static int use_cbprd = 0;
+static int use_mv0 = 0;
+static int do_normalize_aqp = 0;
 static int qns = 0;
 static int closed_gop = 0;
 static int strict_gop = 0;
+static int no_output = 0;
 static int do_deinterlace = 0;
 static int do_interlace_dct = 0;
 static int do_interlace_me = 0;
@@ -655,15 +662,15 @@ static void fill_pad_region(AVPicture* img, int height, int width,
             optr = img->data[i] + (img->linesize[i] * (padtop >> shift)) +
                 (img->linesize[i] - (padright >> shift));
 
-            for (y = 0; y < ((height - (padtop + padbottom)) >> shift); y++) {
+            for (y = 0; y < ((height - (padtop + padbottom) - 1) >> shift); y++) {
                 memset(optr, color[i], (padleft + padright) >> shift);
                 optr += img->linesize[i];
             }
         }
       
-        if (padbottom) {
-            optr = img->data[i] + (img->linesize[i] * ((height - padbottom) >> shift));
-            memset(optr, color[i], ((img->linesize[i] * padbottom) >> shift));
+        if (padbottom || padright) {
+            optr = img->data[i] + (((img->linesize[i] * (height - padbottom)) - padright) >> shift);
+            memset(optr, color[i], (((img->linesize[i] * padbottom) + padright) >> shift));
         }
     }
 }
@@ -899,7 +906,7 @@ static void do_video_out(AVFormatContext *s,
                                        bit_buffer, bit_buffer_size,
                                        &big_picture);
             //enc->frame_number = enc->real_pict_num;
-            if(ret){
+            if(ret>0){
                 pkt.data= bit_buffer;
                 pkt.size= ret;
                 if(enc->coded_frame)
@@ -949,7 +956,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
     if (!fvstats) {
         today2 = time(NULL);
         today = localtime(&today2);
-        sprintf(filename, "vstats_%02d%02d%02d.log", today->tm_hour,
+        snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour,
                                                today->tm_min,
                                                today->tm_sec);
         fvstats = fopen(filename,"w");
@@ -1020,21 +1027,21 @@ static void print_report(AVFormatContext **output_files,
         os = output_files[ost->file_index];
         enc = &ost->st->codec;
         if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
-            sprintf(buf + strlen(buf), "q=%2.1f ",
+            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
                     enc->coded_frame->quality/(float)FF_QP2LAMBDA);
         }
         if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
             frame_number = ost->frame_number;
-            sprintf(buf + strlen(buf), "frame=%5d q=%2.1f ",
+            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d q=%2.1f ",
                     frame_number, enc->coded_frame ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : 0);
             if(is_last_report)
-                sprintf(buf + strlen(buf), "L");
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
             if (enc->flags&CODEC_FLAG_PSNR){
                 int j;
                 double error, error_sum=0;
                 double scale, scale_sum=0;
                 char type[3]= {'Y','U','V'};
-                sprintf(buf + strlen(buf), "PSNR=");
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
                 for(j=0; j<3; j++){
                     if(is_last_report){
                         error= enc->error[j];
@@ -1046,9 +1053,9 @@ static void print_report(AVFormatContext **output_files,
                     if(j) scale/=4;
                     error_sum += error;
                     scale_sum += scale;
-                    sprintf(buf + strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
+                    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
                 }
-                sprintf(buf + strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
+                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
             }
             vid = 1;
         }
@@ -1063,12 +1070,12 @@ static void print_report(AVFormatContext **output_files,
     if (verbose || is_last_report) {
         bitrate = (double)(total_size * 8) / ti1 / 1000.0;
         
-        sprintf(buf + strlen(buf), 
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 
             "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
             (double)total_size / 1024, ti1, bitrate);
 
        if (verbose > 1)
-         sprintf(buf + strlen(buf), " dup=%d drop=%d",
+         snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
                  nb_frames_dup, nb_frames_drop);
         
         if (verbose >= 0)
@@ -1110,7 +1117,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
     } else if (pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
         ist->next_pts = ist->pts = pkt->dts;
     } else {
-        assert(ist->pts == ist->next_pts);
+//        assert(ist->pts == ist->next_pts);
     }
     
     if (pkt == NULL) {
@@ -1526,6 +1533,7 @@ static int av_encode(AVFormatContext **output_files,
                 codec->frame_rate_base = icodec->frame_rate_base;
                 codec->width = icodec->width;
                 codec->height = icodec->height;
+                codec->has_b_frames = icodec->has_b_frames;
                 break;
             default:
                 av_abort();
@@ -1719,7 +1727,7 @@ static int av_encode(AVFormatContext **output_files,
                 exit(1);
             }
             if (avcodec_open(&ost->st->codec, codec) < 0) {
-                fprintf(stderr, "Error while opening codec for stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n", 
+                fprintf(stderr, "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n", 
                         ost->file_index, ost->index);
                 exit(1);
             }
@@ -1756,6 +1764,8 @@ static int av_encode(AVFormatContext **output_files,
         ist->next_pts = ist->st->start_time;
         if(ist->next_pts == AV_NOPTS_VALUE) 
             ist->next_pts=0;
+        if(input_files_ts_offset[ist->file_index])
+            ist->next_pts= AV_NOPTS_VALUE;
         ist->is_start = 1;
     }
 
@@ -1897,7 +1907,7 @@ static int av_encode(AVFormatContext **output_files,
             goto discard_packet;
 
 //        fprintf(stderr, "next:%lld dts:%lld off:%lld %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec.codec_type);
-        if (pkt.dts != AV_NOPTS_VALUE) {
+        if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE) {
             int64_t delta= pkt.dts - ist->next_pts;
             if(ABS(delta) > 10LL*AV_TIME_BASE && !copy_ts){
                 input_files_ts_offset[ist->file_index]-= delta;
@@ -1969,6 +1979,7 @@ static int av_encode(AVFormatContext **output_files,
     
     ret = 0;
  fail1:
+    av_freep(&bit_buffer);
     av_free(file_table);
 
     if (ist_table) {
@@ -2439,6 +2450,36 @@ static void opt_qscale(const char *arg)
     }
 }
 
+static void opt_qsquish(const char *arg)
+{
+    video_qsquish = atof(arg);
+    if (video_qsquish < 0.0 ||
+        video_qsquish > 99.0) {
+        fprintf(stderr, "qsquish must be >= 0.0 and <= 99.0\n");
+        exit(1);
+    }
+}
+
+static void opt_lelim(const char *arg)
+{
+    video_lelim = atoi(arg);
+    if (video_lelim < -99 ||
+        video_lelim > 99) {
+        fprintf(stderr, "lelim must be >= -99 and <= 99\n");
+        exit(1);
+    }
+}
+
+static void opt_celim(const char *arg)
+{
+    video_celim = atoi(arg);
+    if (video_celim < -99 ||
+        video_celim > 99) {
+        fprintf(stderr, "celim must be >= -99 and <= 99\n");
+        exit(1);
+    }
+}
+
 static void opt_lmax(const char *arg)
 {
     video_lmax = atof(arg)*FF_QP2LAMBDA;
@@ -2452,7 +2493,7 @@ static void opt_lmin(const char *arg)
 static void opt_qmin(const char *arg)
 {
     video_qmin = atoi(arg);
-    if (video_qmin < 0 ||
+    if (video_qmin < 1 ||
         video_qmin > 31) {
         fprintf(stderr, "qmin must be >= 1 and <= 31\n");
         exit(1);
@@ -2462,29 +2503,29 @@ static void opt_qmin(const char *arg)
 static void opt_qmax(const char *arg)
 {
     video_qmax = atoi(arg);
-    if (video_qmax < 0 ||
+    if (video_qmax < 1 ||
         video_qmax > 31) {
         fprintf(stderr, "qmax must be >= 1 and <= 31\n");
         exit(1);
     }
 }
 
-static void opt_mb_qmin(const char *arg)
+static void opt_mb_lmin(const char *arg)
 {
-    video_mb_qmin = atoi(arg);
-    if (video_mb_qmin < 0 ||
-        video_mb_qmin > 31) {
-        fprintf(stderr, "qmin must be >= 1 and <= 31\n");
+    video_mb_lmin = atof(arg)*FF_QP2LAMBDA;
+    if (video_mb_lmin < 1 ||
+        video_mb_lmin > FF_LAMBDA_MAX) {
+        fprintf(stderr, "mblmin must be >= 1 and <= %d\n", FF_LAMBDA_MAX / FF_QP2LAMBDA);
         exit(1);
     }
 }
 
-static void opt_mb_qmax(const char *arg)
+static void opt_mb_lmax(const char *arg)
 {
-    video_mb_qmax = atoi(arg);
-    if (video_mb_qmax < 0 ||
-        video_mb_qmax > 31) {
-        fprintf(stderr, "qmax must be >= 1 and <= 31\n");
+    video_mb_lmax = atof(arg)*FF_QP2LAMBDA;
+    if (video_mb_lmax < 1 ||
+        video_mb_lmax > FF_LAMBDA_MAX) {
+        fprintf(stderr, "mblmax must be >= 1 and <= %d\n", FF_LAMBDA_MAX / FF_QP2LAMBDA);
         exit(1);
     }
 }
@@ -2862,6 +2903,8 @@ static void opt_input_file(const char *filename)
             //fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
             audio_channels = enc->channels;
             audio_sample_rate = enc->sample_rate;
+            if(audio_disable)
+                ic->streams[i]->discard= AVDISCARD_ALL;
             break;
         case CODEC_TYPE_VIDEO:
             frame_height = enc->height;
@@ -2895,6 +2938,10 @@ static void opt_input_file(const char *filename)
             frame_rate_base = rfps_base;
 
             enc->rate_emu = rate_emu;
+            if(video_disable)
+                ic->streams[i]->discard= AVDISCARD_ALL;
+            else if(video_discard)
+                ic->streams[i]->discard= video_discard;
             break;
         case CODEC_TYPE_DATA:
             break;
@@ -3087,6 +3134,7 @@ static void opt_output_file(const char *filename)
                     video_enc->gop_size = 0;
                 if (video_qscale || same_quality) {
                     video_enc->flags |= CODEC_FLAG_QSCALE;
+                    video_enc->global_quality= 
                     st->quality = FF_QP2LAMBDA * video_qscale;
                 }
 
@@ -3142,6 +3190,12 @@ static void opt_output_file(const char *filename)
                 }
                if (use_trell) {
                     video_enc->flags |= CODEC_FLAG_TRELLIS_QUANT;
+                }
+                   if (use_mv0) {
+                    video_enc->flags |= CODEC_FLAG_MV0;
+                }
+                   if (do_normalize_aqp) {
+                    video_enc->flags |= CODEC_FLAG_NORMALIZE_AQP;
                 }
                if (use_scan_offset) {
                     video_enc->flags |= CODEC_FLAG_SVCD_SCAN_OFFSET;
@@ -3172,12 +3226,18 @@ static void opt_output_file(const char *filename)
                 if (do_interlace_me) {
                     video_enc->flags |= CODEC_FLAG_INTERLACED_ME;
                 }
+                if (no_output) {
+                    video_enc->flags2 |= CODEC_FLAG2_NO_OUTPUT;
+                }
                 video_enc->qmin = video_qmin;
                 video_enc->qmax = video_qmax;
                 video_enc->lmin = video_lmin;
                 video_enc->lmax = video_lmax;
-                video_enc->mb_qmin = video_mb_qmin;
-                video_enc->mb_qmax = video_mb_qmax;
+                video_enc->rc_qsquish = video_qsquish;
+                video_enc->luma_elim_threshold = video_lelim;
+                video_enc->chroma_elim_threshold = video_celim;
+                video_enc->mb_lmin = video_mb_lmin;
+                video_enc->mb_lmax = video_mb_lmax;
                 video_enc->max_qdiff = video_qdiff;
                 video_enc->qblur = video_qblur;
                 video_enc->qcompress = video_qcomp;
@@ -3331,7 +3391,7 @@ static void opt_output_file(const char *filename)
 
     output_files[nb_output_files++] = oc;
 
-    strcpy(oc->filename, filename);
+    pstrcpy(oc->filename, sizeof(oc->filename), filename);
 
     /* check filename in case of an image number is expected */
     if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
@@ -3685,7 +3745,7 @@ void opt_intra_matrix(const char *arg)
 static void opt_target(const char *arg)
 {
     int norm = -1;
-    static const char const *frame_rates[] = {"25", "30000/1001", "24000/1001"};
+    static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
 
     if(!strncmp(arg, "pal-", 4)) {
         norm = 0;
@@ -3728,7 +3788,7 @@ static void opt_target(const char *arg)
             }
         }
         if(verbose && norm >= 0)
-            printf("Assuming %s for target.\n", norm ? "NTSC" : "PAL");
+            fprintf(stderr, "Assuming %s for target.\n", norm ? "NTSC" : "PAL");
     }
 
     if(norm < 0) {
@@ -3825,7 +3885,7 @@ static void opt_target(const char *arg)
 
 static void show_version(void)
 {
-    printf("ffmpeg      " FFMPEG_VERSION "\n"
+    fprintf(stderr, "ffmpeg      " FFMPEG_VERSION "\n"
            "libavcodec  %d\n"
            "libavformat %d\n", 
            avcodec_build(), LIBAVFORMAT_BUILD);
@@ -3891,15 +3951,17 @@ const OptionDef options[] = {
     { "g", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" },
     { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
     { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
+    { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
     { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantiser scale (VBR)", "q" },
     { "qmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qmin}, "min video quantiser scale (VBR)", "q" },
     { "qmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qmax}, "max video quantiser scale (VBR)", "q" },
     { "lmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_lmin}, "min video lagrange factor (VBR)", "lambda" },
     { "lmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_lmax}, "max video lagrange factor (VBR)", "lambda" },
-    { "mbqmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_qmin}, "min macroblock quantiser scale (VBR)", "q" },
-    { "mbqmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_qmax}, "max macroblock quantiser scale (VBR)", "q" },
+    { "mblmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_lmin}, "min macroblock quantiser scale (VBR)", "q" },
+    { "mblmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_lmax}, "max macroblock quantiser scale (VBR)", "q" },
     { "qdiff", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qdiff}, "max difference between the quantiser scale (VBR)", "q" },
     { "qblur", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qblur}, "video quantiser scale blur (VBR)", "blur" },
+    { "qsquish", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qsquish}, "how to keep quantiser between qmin and qmax (0 = clip, 1 = use differentiable function)", "squish" },
     { "qcomp", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qcomp}, "video quantiser scale compression (VBR)", "compression" },
     { "rc_init_cplx", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_rc_initial_cplx}, "initial complexity for 1-pass encoding", "complexity" },
     { "b_qfactor", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_qfactor}, "qp factor between p and b frames", "factor" },
@@ -3933,6 +3995,8 @@ const OptionDef options[] = {
     { "cmp", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_cmp}, "fullpel compare function", "cmp function" },
     { "precmp", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_pre_cmp}, "pre motion estimation compare function", "cmp function" },
     { "preme", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_pre_me}, "pre motion estimation", "" },
+    { "lelim", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_lelim}, "single coefficient elimination threshold for luminance (negative values also consider DC coefficient)", "elim" },
+    { "celim", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_celim}, "single coefficient elimination threshold for chrominance (negative values also consider DC coefficient)", "elim" },
     { "lumi_mask", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_lumi_mask}, "luminance masking", "" },
     { "dark_mask", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_dark_mask}, "darkness masking", "" },
     { "scplx_mask", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_scplx_mask}, "spatial complexity masking", "" },
@@ -3967,8 +4031,11 @@ const OptionDef options[] = {
     { "qprd", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_qprd}, "" },
     { "cbp", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_cbprd}, "" },
     { "trell", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_trell}, "enable trellis quantization" },
+    { "mv0", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_mv0}, "try to encode each MB with MV=<0,0> and choose the better one (has no effect if mbd=0)" },
+    { "naq", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_normalize_aqp}, "normalize adaptive quantization" },
     { "cgop", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&closed_gop}, "closed gop" },
     { "sgop", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&strict_gop}, "strict gop" },
+    { "noout", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&no_output}, "skip bitstream encoding" },
     { "scan_offset", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_scan_offset}, "enable SVCD Scan Offset placeholder" },
     { "qpel", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_qpel}, "enable 1/4-pel" },
     { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
@@ -4021,14 +4088,14 @@ const OptionDef options[] = {
 
 static void show_banner(void)
 {
-    printf("ffmpeg version " FFMPEG_VERSION ", build %d, Copyright (c) 2000-2004 Fabrice Bellard\n",
+    fprintf(stderr, "ffmpeg version " FFMPEG_VERSION ", build %d, Copyright (c) 2000-2004 Fabrice Bellard\n",
         LIBAVCODEC_BUILD);
-    printf("  configuration: %s\n", FFMPEG_CONFIGURATION);
-    printf("  built on " __DATE__ " " __TIME__);
+    fprintf(stderr, "  configuration: %s\n", FFMPEG_CONFIGURATION);
+    fprintf(stderr, "  built on " __DATE__ " " __TIME__);
 #ifdef __GNUC__
-    printf(", gcc: %s\n", __VERSION__);
+    fprintf(stderr, ", gcc: %s\n", __VERSION__);
 #else
-    printf(", using a non-gcc compiler\n");
+    fprintf(stderr, ", using a non-gcc compiler\n");
 #endif
 }