Allow target autodetection to work when cross-compiling.
[profile/ivi/libvpx.git] / vpxenc.c
index 7d6758a..d32b21b 100644 (file)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -489,6 +489,13 @@ static void write_ivf_frame_header(FILE *outfile,
     if(fwrite(header, 1, 12, outfile));
 }
 
+static void write_ivf_frame_size(FILE *outfile, size_t size)
+{
+    char             header[4];
+    mem_put_le32(header, size);
+    fwrite(header, 1, 4, outfile);
+}
+
 
 typedef off_t EbmlLoc;
 
@@ -945,7 +952,6 @@ static double vp8_mse2psnr(double Samples, double Peak, double Mse)
 
 
 #include "args.h"
-
 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
         "Debug mode (makes output deterministic)");
 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
@@ -980,6 +986,8 @@ static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
         "Stream frame rate (rate/scale)");
 static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
         "Output IVF (default is WebM)");
+static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
+        "Makes encoder output partitions. Requires IVF output!");
 static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
         "Show quantizer histogram (n-buckets)");
 static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
@@ -989,7 +997,7 @@ static const arg_def_t *main_args[] =
     &debugmode,
     &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
     &best_dl, &good_dl, &rt_dl,
-    &verbosearg, &psnrarg, &use_ivf, &q_hist_n, &rate_hist_n,
+    &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
     NULL
 };
 
@@ -1492,6 +1500,7 @@ struct global_config
     int                       show_psnr;
     int                       have_framerate;
     struct vpx_rational       framerate;
+    int                       out_part;
     int                       debug;
     int                       show_q_hist_buckets;
     int                       show_rate_hist_buckets;
@@ -1508,6 +1517,7 @@ struct stream_config
     int                       arg_ctrls[ARG_CTRL_CNT_MAX][2];
     int                       arg_ctrl_cnt;
     int                       write_webm;
+    int                       have_kf_max_dist;
 };
 
 
@@ -1533,6 +1543,23 @@ struct stream_state
 };
 
 
+void validate_positive_rational(const char          *msg,
+                                struct vpx_rational *rat)
+{
+    if (rat->den < 0)
+    {
+        rat->num *= -1;
+        rat->den *= -1;
+    }
+
+    if (rat->num < 0)
+        die("Error: %s must be positive\n", msg);
+
+    if (!rat->den)
+        die("Error: %s has zero denominator\n", msg);
+}
+
+
 static void parse_global_config(struct global_config *global, char **argv)
 {
     char       **argi, **argj;
@@ -1601,8 +1628,11 @@ static void parse_global_config(struct global_config *global, char **argv)
         else if (arg_match(&arg, &framerate, argi))
         {
             global->framerate = arg_parse_rational(&arg);
+            validate_positive_rational(arg.name, &global->framerate);
             global->have_framerate = 1;
         }
+        else if (arg_match(&arg,&out_part, argi))
+            global->out_part = 1;
         else if (arg_match(&arg, &debugmode, argi))
             global->debug = 1;
         else if (arg_match(&arg, &q_hist_n, argi))
@@ -1729,6 +1759,9 @@ static struct stream_state *new_stream(struct global_config *global,
         stream->config.stereo_fmt = STEREO_FORMAT_MONO;
         stream->config.write_webm = 1;
         stream->ebml.last_pts_ms = -1;
+
+        /* Allows removal of the application version from the EBML tags */
+        stream->ebml.debug = global->debug;
     }
 
     /* Output files must be specified for each stream */
@@ -1793,7 +1826,10 @@ static int parse_stream_params(struct global_config *global,
         else if (arg_match(&arg, &stereo_mode, argi))
             config->stereo_fmt = arg_parse_enum_or_int(&arg);
         else if (arg_match(&arg, &timebase, argi))
+        {
             config->cfg.g_timebase = arg_parse_rational(&arg);
+            validate_positive_rational(arg.name, &config->cfg.g_timebase);
+        }
         else if (arg_match(&arg, &error_resilient, argi))
             config->cfg.g_error_resilient = arg_parse_uint(&arg);
         else if (arg_match(&arg, &lag_in_frames, argi))
@@ -1848,7 +1884,10 @@ static int parse_stream_params(struct global_config *global,
         else if (arg_match(&arg, &kf_min_dist, argi))
             config->cfg.kf_min_dist = arg_parse_uint(&arg);
         else if (arg_match(&arg, &kf_max_dist, argi))
+        {
             config->cfg.kf_max_dist = arg_parse_uint(&arg);
+            config->have_kf_max_dist = 1;
+        }
         else if (arg_match(&arg, &kf_disabled, argi))
             config->cfg.kf_mode = VPX_KF_DISABLED;
         else
@@ -1951,6 +1990,21 @@ static void set_stream_dimensions(struct stream_state *stream,
 }
 
 
+static void set_default_kf_interval(struct stream_state  *stream,
+                                    struct global_config *global)
+{
+    /* Use a max keyframe interval of 5 seconds, if none was
+     * specified on the command line.
+     */
+    if (!stream->config.have_kf_max_dist)
+    {
+        double framerate = (double)global->framerate.num/global->framerate.den;
+        if (framerate > 0.0)
+            stream->config.cfg.kf_max_dist = 5.0*framerate;
+    }
+}
+
+
 static void show_stream_config(struct stream_state  *stream,
                                struct global_config *global,
                                struct input_state   *input)
@@ -2071,6 +2125,10 @@ static void setup_pass(struct stream_state  *stream,
         : VPX_RC_ONE_PASS;
     if (pass)
         stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
+
+    stream->cx_time = 0;
+    stream->nbytes = 0;
+    stream->frames_out = 0;
 }
 
 
@@ -2078,11 +2136,14 @@ static void initialize_encoder(struct stream_state  *stream,
                                struct global_config *global)
 {
     int i;
+    int flags = 0;
+
+    flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
+    flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
 
     /* Construct Encoder Context */
     vpx_codec_enc_init(&stream->encoder, global->codec->iface,
-                       &stream->config.cfg,
-                       global->show_psnr ? VPX_CODEC_USE_PSNR : 0);
+                        &stream->config.cfg, flags);
     ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
 
     /* Note that we bypass the vpx_codec_control wrapper macro because
@@ -2151,12 +2212,18 @@ static void get_cx_data(struct stream_state  *stream,
 
     while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
     {
+        static size_t fsize = 0;
+        static off_t ivf_header_pos = 0;
+
         *got_data = 1;
 
         switch (pkt->kind)
         {
         case VPX_CODEC_CX_FRAME_PKT:
-            stream->frames_out++;
+            if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+            {
+                stream->frames_out++;
+            }
             fprintf(stderr, " %6luF",
                     (unsigned long)pkt->data.frame.sz);
 
@@ -2172,9 +2239,28 @@ static void get_cx_data(struct stream_state  *stream,
             }
             else
             {
-                write_ivf_frame_header(stream->file, pkt);
-                if(fwrite(pkt->data.frame.buf, 1,
-                          pkt->data.frame.sz, stream->file));
+                if (pkt->data.frame.partition_id <= 0)
+                {
+                    ivf_header_pos = ftello(stream->file);
+                    fsize = pkt->data.frame.sz;
+
+                    write_ivf_frame_header(stream->file, pkt);
+                }
+                else
+                {
+                    fsize += pkt->data.frame.sz;
+
+                    if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+                    {
+                        off_t currpos = ftello(stream->file);
+                        fseeko(stream->file, ivf_header_pos, SEEK_SET);
+                        write_ivf_frame_size(stream->file, fsize);
+                        fseeko(stream->file, currpos, SEEK_SET);
+                    }
+                }
+
+                fwrite(pkt->data.frame.buf, 1,
+                       pkt->data.frame.sz, stream->file);
             }
             stream->nbytes += pkt->data.raw.sz;
             break;
@@ -2335,6 +2421,8 @@ int main(int argc, const char **argv_)
         if (!global.have_framerate)
             global.framerate = input.framerate;
 
+        FOREACH_STREAM(set_default_kf_interval(stream, &global));
+
         /* Show configuration */
         if (global.verbose && pass == 0)
             FOREACH_STREAM(show_stream_config(stream, &global, &input));
@@ -2378,7 +2466,7 @@ int main(int argc, const char **argv_)
                     fprintf(stderr,
                             "\rPass %d/%d frame %4d/%-4d %7"PRId64"B \033[K",
                             pass + 1, global.passes, frames_in,
-                            streams->frames_out, streams->nbytes);
+                            streams->frames_out, (int64_t)streams->nbytes);
                 else
                     fprintf(stderr,
                             "\rPass %d/%d frame %4d %7lu %s (%.2f fps)\033[K",
@@ -2412,10 +2500,10 @@ int main(int argc, const char **argv_)
         FOREACH_STREAM(fprintf(
             stderr,
             "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
-            " %7lu %s (%.2f fps)\033[K\n", pass + 1,
-            global.passes, frames_in, stream->frames_out, stream->nbytes,
+            " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
+            global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
             frames_in ? (unsigned long)(stream->nbytes * 8 / frames_in) : 0,
-            frames_in ? stream->nbytes * 8
+            frames_in ? (int64_t)stream->nbytes * 8
                         * (int64_t)global.framerate.num / global.framerate.den
                         / frames_in
                       : 0,
@@ -2451,5 +2539,6 @@ int main(int argc, const char **argv_)
 
     vpx_img_free(&raw);
     free(argv);
+    free(streams);
     return EXIT_SUCCESS;
 }