shithub: libvpx

Download patch

ref: 3245d463c4a3e44185722c1e108d20576cd3f9f8
parent: db0f26c0e2ea0ee24a771105a04b833920c0c7dd
author: John Koleszar <jkoleszar@google.com>
date: Thu Jun 10 13:10:12 EDT 2010

ivfenc: support reading/writing from a pipe

Use - for the filename to use stdin/stdout. Update to avoid opening
the file multiple times.

Change-Id: I356356fa16bb334d4b22abc531dc03c0d95917a3

--- a/ivfenc.c
+++ b/ivfenc.c
@@ -1,10 +1,10 @@
 /*
  *  Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
  *
- *  Use of this source code is governed by a BSD-style license 
+ *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
  *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may 
+ *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
@@ -55,8 +55,8 @@
 {
     va_list ap;
     va_start(ap, fmt);
-    vprintf(fmt, ap);
-    printf("\n");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
     usage_exit();
 }
 
@@ -66,10 +66,10 @@
     {
         const char *detail = vpx_codec_error_detail(ctx);
 
-        printf("%s: %s\n", s, vpx_codec_error(ctx));
+        fprintf(stderr, "%s: %s\n", s, vpx_codec_error(ctx));
 
         if (detail)
-            printf("    %s\n", detail);
+            fprintf(stderr, "    %s\n", detail);
 
         exit(EXIT_FAILURE);
     }
@@ -226,9 +226,15 @@
     FILE_TYPE_Y4M
 };
 
+struct detect_buffer {
+    char buf[4];
+    int  valid;
+};
+
+
 #define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
 static int read_frame(FILE *f, vpx_image_t *img, unsigned int file_type,
-                      y4m_input *y4m)
+                      y4m_input *y4m, struct detect_buffer *detect)
 {
     int plane = 0;
 
@@ -275,7 +281,15 @@
 
             for (r = 0; r < h; r++)
             {
-                fread(ptr, 1, w, f);
+                if (detect->valid)
+                {
+                    memcpy(ptr, detect->buf, 4);
+                    fread(ptr+4, 1, w-4, f);
+                    detect->valid = 0;
+                }
+                else
+                    fread(ptr, 1, w, f);
+
                 ptr += img->stride[plane];
             }
         }
@@ -286,16 +300,14 @@
 
 
 unsigned int file_is_y4m(FILE *infile,
-                         y4m_input *y4m)
+                         y4m_input *y4m,
+                         char       detect[4])
 {
-    char raw_hdr[4];
-    if (fread(raw_hdr, 1, 4, infile) == 4 &&
-        memcmp(raw_hdr, "YUV4", 4) == 0 &&
-        y4m_input_open(y4m, infile, raw_hdr, 4) >= 0)
+    if(memcmp(detect, "YUV4", 4) == 0 &&
+        y4m_input_open(y4m, infile, detect, 4) >= 0)
     {
         return 1;
     }
-    rewind(infile);
     return 0;
 }
 
@@ -303,18 +315,21 @@
 unsigned int file_is_ivf(FILE *infile,
                          unsigned int *fourcc,
                          unsigned int *width,
-                         unsigned int *height)
+                         unsigned int *height,
+                         char          detect[4])
 {
     char raw_hdr[IVF_FILE_HDR_SZ];
     int is_ivf = 0;
 
+    if(memcmp(detect, "DKIF", 4) != 0)
+        return 0;
+
     /* See write_ivf_file_header() for more documentation on the file header
      * layout.
      */
-    if (fread(raw_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ)
+    if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
+        == IVF_FILE_HDR_SZ - 4)
     {
-        if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
-            && raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
         {
             is_ivf = 1;
 
@@ -331,8 +346,6 @@
         *width = mem_get_le16(raw_hdr + 12);
         *height = mem_get_le16(raw_hdr + 14);
     }
-    else
-        rewind(infile);
 
     return is_ivf;
 }
@@ -546,28 +559,28 @@
 {
     int i;
 
-    printf("Usage: %s <options> src_filename dst_filename\n", exec_name);
+    fprintf(stderr, "Usage: %s <options> src_filename dst_filename\n", exec_name);
 
-    printf("\n_options:\n");
+    fprintf(stderr, "\n_options:\n");
     arg_show_usage(stdout, main_args);
-    printf("\n_encoder Global Options:\n");
+    fprintf(stderr, "\n_encoder Global Options:\n");
     arg_show_usage(stdout, global_args);
-    printf("\n_rate Control Options:\n");
+    fprintf(stderr, "\n_rate Control Options:\n");
     arg_show_usage(stdout, rc_args);
-    printf("\n_twopass Rate Control Options:\n");
+    fprintf(stderr, "\n_twopass Rate Control Options:\n");
     arg_show_usage(stdout, rc_twopass_args);
-    printf("\n_keyframe Placement Options:\n");
+    fprintf(stderr, "\n_keyframe Placement Options:\n");
     arg_show_usage(stdout, kf_args);
 #if CONFIG_VP8_ENCODER
-    printf("\n_vp8 Specific Options:\n");
+    fprintf(stderr, "\n_vp8 Specific Options:\n");
     arg_show_usage(stdout, vp8_args);
 #endif
-    printf("\n"
+    fprintf(stderr, "\n"
            "Included encoders:\n"
            "\n");
 
     for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
-        printf("    %-6s - %s\n",
+        fprintf(stderr, "    %-6s - %s\n",
                codecs[i].name,
                vpx_codec_iface_name(codecs[i].iface));
 
@@ -687,7 +700,7 @@
         /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
         if (one_pass_only > arg_passes)
         {
-            printf("Warning: Assuming --pass=%d implies --passes=%d\n",
+            fprintf(stderr, "Warning: Assuming --pass=%d implies --passes=%d\n",
                    one_pass_only, one_pass_only);
             arg_passes = one_pass_only;
         }
@@ -701,7 +714,8 @@
 
     if (res)
     {
-        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+        fprintf(stderr, "Failed to get config: %s\n",
+                vpx_codec_err_to_string(res));
         return EXIT_FAILURE;
     }
 
@@ -761,8 +775,9 @@
             cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
 
             if (arg_passes < 2)
-                printf("Warning: option %s ignored in one-pass mode.\n",
-                       arg.name);
+                fprintf(stderr,
+                        "Warning: option %s ignored in one-pass mode.\n",
+                        arg.name);
         }
         else if (arg_match(&arg, &minsection_pct, argi))
         {
@@ -769,8 +784,9 @@
             cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
 
             if (arg_passes < 2)
-                printf("Warning: option %s ignored in one-pass mode.\n",
-                       arg.name);
+                fprintf(stderr,
+                        "Warning: option %s ignored in one-pass mode.\n",
+                        arg.name);
         }
         else if (arg_match(&arg, &maxsection_pct, argi))
         {
@@ -777,8 +793,9 @@
             cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
 
             if (arg_passes < 2)
-                printf("Warning: option %s ignored in one-pass mode.\n",
-                       arg.name);
+                fprintf(stderr,
+                        "Warning: option %s ignored in one-pass mode.\n",
+                        arg.name);
         }
         else if (arg_match(&arg, &kf_min_dist, argi))
             cfg.kf_min_dist = arg_parse_uint(&arg);
@@ -826,7 +843,7 @@
 
     /* Check for unrecognized options */
     for (argi = argv; *argi; argi++)
-        if (argi[0][0] == '-')
+        if (argi[0][0] == '-' && argi[0][1])
             die("Error: Unrecognized option %s\n", *argi);
 
     /* Handle non-option arguments */
@@ -836,108 +853,6 @@
     if (!in_fn || !out_fn)
         usage_exit();
 
-    /* Parse certain options from the input file, if possible */
-    infile = fopen(in_fn, "rb");
-
-    if (!infile)
-    {
-        printf("Failed to open input file");
-        return EXIT_FAILURE;
-    }
-
-    if (file_is_y4m(infile, &y4m))
-    {
-        file_type = FILE_TYPE_Y4M;
-        cfg.g_w = y4m.pic_w;
-        cfg.g_h = y4m.pic_h;
-        /* Use the frame rate from the file only if none was specified on the
-         *  command-line.
-         */
-        if (!arg_have_timebase)
-        {
-            cfg.g_timebase.num = y4m.fps_d;
-            cfg.g_timebase.den = y4m.fps_n;
-        }
-        arg_use_i420 = 0;
-    }
-    else if (file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h))
-    {
-        file_type = FILE_TYPE_IVF;
-        switch (fourcc)
-        {
-        case 0x32315659:
-            arg_use_i420 = 0;
-            break;
-        case 0x30323449:
-            arg_use_i420 = 1;
-            break;
-        default:
-            printf("Unsupported fourcc (%08x) in IVF\n", fourcc);
-            return EXIT_FAILURE;
-        }
-    }
-    else
-        file_type = FILE_TYPE_RAW;
-
-    fclose(infile);
-
-
-#define SHOW(field) printf("    %-28s = %d\n", #field, cfg.field)
-
-    if (verbose)
-    {
-        printf("Codec: %s\n", vpx_codec_iface_name(codec->iface));
-        printf("Source file: %s Format: %s\n", in_fn, arg_use_i420 ? "I420" : "YV12");
-        printf("Destination file: %s\n", out_fn);
-        printf("Encoder parameters:\n");
-
-        SHOW(g_usage);
-        SHOW(g_threads);
-        SHOW(g_profile);
-        SHOW(g_w);
-        SHOW(g_h);
-        SHOW(g_timebase.num);
-        SHOW(g_timebase.den);
-        SHOW(g_error_resilient);
-        SHOW(g_pass);
-        SHOW(g_lag_in_frames);
-        SHOW(rc_dropframe_thresh);
-        SHOW(rc_resize_allowed);
-        SHOW(rc_resize_up_thresh);
-        SHOW(rc_resize_down_thresh);
-        SHOW(rc_end_usage);
-        SHOW(rc_target_bitrate);
-        SHOW(rc_min_quantizer);
-        SHOW(rc_max_quantizer);
-        SHOW(rc_undershoot_pct);
-        SHOW(rc_overshoot_pct);
-        SHOW(rc_buf_sz);
-        SHOW(rc_buf_initial_sz);
-        SHOW(rc_buf_optimal_sz);
-        SHOW(rc_2pass_vbr_bias_pct);
-        SHOW(rc_2pass_vbr_minsection_pct);
-        SHOW(rc_2pass_vbr_maxsection_pct);
-        SHOW(kf_mode);
-        SHOW(kf_min_dist);
-        SHOW(kf_max_dist);
-    }
-
-    if (file_type == FILE_TYPE_Y4M)
-        /*The Y4M reader does its own allocation.
-          Just initialize this here to avoid problems if we never read any
-           frames.*/
-        memset(&raw, 0, sizeof(raw));
-    else
-        vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
-                      cfg.g_w, cfg.g_h, 1);
-
-    // This was added so that ivfenc will create monotically increasing
-    // timestamps.  Since we create new timestamps for alt-reference frames
-    // we need to make room in the series of timestamps.  Since there can
-    // only be 1 alt-ref frame ( current bitstream) multiplying by 2
-    // gives us enough room.
-    cfg.g_timebase.den *= 2;
-
     memset(&stats, 0, sizeof(stats));
 
     for (pass = one_pass_only ? one_pass_only - 1 : 0; pass < arg_passes; pass++)
@@ -944,32 +859,120 @@
     {
         int frames_in = 0, frames_out = 0;
         unsigned long nbytes = 0;
+        struct detect_buffer detect;
 
-        infile = fopen(in_fn, "rb");
+        /* Parse certain options from the input file, if possible */
+        infile = strcmp(in_fn, "-") ? fopen(in_fn, "rb") : stdin;
 
         if (!infile)
         {
-            printf("Failed to open input file");
+            fprintf(stderr, "Failed to open input file\n");
             return EXIT_FAILURE;
         }
 
-        /*Skip the file header.*/
-        if (file_type == FILE_TYPE_IVF)
+        fread(detect.buf, 1, 4, infile);
+        detect.valid = 0;
+
+        if (file_is_y4m(infile, &y4m, detect.buf))
         {
-            char raw_hdr[IVF_FILE_HDR_SZ];
-            (void)fread(raw_hdr, 1, IVF_FILE_HDR_SZ, infile);
+            file_type = FILE_TYPE_Y4M;
+            cfg.g_w = y4m.pic_w;
+            cfg.g_h = y4m.pic_h;
+            /* Use the frame rate from the file only if none was specified on the
+             *  command-line.
+             */
+            if (!arg_have_timebase)
+            {
+                cfg.g_timebase.num = y4m.fps_d;
+                cfg.g_timebase.den = y4m.fps_n;
+            }
+            arg_use_i420 = 0;
         }
-        else if(file_type == FILE_TYPE_Y4M)
+        else if (file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h, detect.buf))
         {
-            char buffer[80];
-            (void)fgets(buffer, sizeof(buffer)/sizeof(*buffer) - 1, infile);
+            file_type = FILE_TYPE_IVF;
+            switch (fourcc)
+            {
+            case 0x32315659:
+                arg_use_i420 = 0;
+                break;
+            case 0x30323449:
+                arg_use_i420 = 1;
+                break;
+            default:
+                fprintf(stderr, "Unsupported fourcc (%08x) in IVF\n", fourcc);
+                return EXIT_FAILURE;
+            }
         }
+        else
+        {
+            file_type = FILE_TYPE_RAW;
+            detect.valid = 1;
+        }
+#define SHOW(field) fprintf(stderr, "    %-28s = %d\n", #field, cfg.field)
 
-        outfile = fopen(out_fn, "wb");
+        if (verbose && pass == 0)
+        {
+            fprintf(stderr, "Codec: %s\n", vpx_codec_iface_name(codec->iface));
+            fprintf(stderr, "Source file: %s Format: %s\n", in_fn,
+                    arg_use_i420 ? "I420" : "YV12");
+            fprintf(stderr, "Destination file: %s\n", out_fn);
+            fprintf(stderr, "Encoder parameters:\n");
 
+            SHOW(g_usage);
+            SHOW(g_threads);
+            SHOW(g_profile);
+            SHOW(g_w);
+            SHOW(g_h);
+            SHOW(g_timebase.num);
+            SHOW(g_timebase.den);
+            SHOW(g_error_resilient);
+            SHOW(g_pass);
+            SHOW(g_lag_in_frames);
+            SHOW(rc_dropframe_thresh);
+            SHOW(rc_resize_allowed);
+            SHOW(rc_resize_up_thresh);
+            SHOW(rc_resize_down_thresh);
+            SHOW(rc_end_usage);
+            SHOW(rc_target_bitrate);
+            SHOW(rc_min_quantizer);
+            SHOW(rc_max_quantizer);
+            SHOW(rc_undershoot_pct);
+            SHOW(rc_overshoot_pct);
+            SHOW(rc_buf_sz);
+            SHOW(rc_buf_initial_sz);
+            SHOW(rc_buf_optimal_sz);
+            SHOW(rc_2pass_vbr_bias_pct);
+            SHOW(rc_2pass_vbr_minsection_pct);
+            SHOW(rc_2pass_vbr_maxsection_pct);
+            SHOW(kf_mode);
+            SHOW(kf_min_dist);
+            SHOW(kf_max_dist);
+        }
+
+        if(pass == 0) {
+            if (file_type == FILE_TYPE_Y4M)
+                /*The Y4M reader does its own allocation.
+                  Just initialize this here to avoid problems if we never read any
+                   frames.*/
+                memset(&raw, 0, sizeof(raw));
+            else
+                vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
+                              cfg.g_w, cfg.g_h, 1);
+
+            // This was added so that ivfenc will create monotically increasing
+            // timestamps.  Since we create new timestamps for alt-reference frames
+            // we need to make room in the series of timestamps.  Since there can
+            // only be 1 alt-ref frame ( current bitstream) multiplying by 2
+            // gives us enough room.
+            cfg.g_timebase.den *= 2;
+        }
+
+        outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb") : stdout;
+
         if (!outfile)
         {
-            printf("Failed to open output file");
+            fprintf(stderr, "Failed to open output file\n");
             return EXIT_FAILURE;
         }
 
@@ -977,7 +980,7 @@
         {
             if (!stats_open_file(&stats, stats_fn, pass))
             {
-                printf("Failed to open statistics store\n");
+                fprintf(stderr, "Failed to open statistics store\n");
                 return EXIT_FAILURE;
             }
         }
@@ -985,7 +988,7 @@
         {
             if (!stats_open_mem(&stats, pass))
             {
-                printf("Failed to open statistics store\n");
+                fprintf(stderr, "Failed to open statistics store\n");
                 return EXIT_FAILURE;
             }
         }
@@ -1020,8 +1023,8 @@
         for (i = 0; i < arg_ctrl_cnt; i++)
         {
             if (vpx_codec_control_(&encoder, arg_ctrls[i][0], arg_ctrls[i][1]))
-                printf("Error: Tried to set control %d = %d\n",
-                       arg_ctrls[i][0], arg_ctrls[i][1]);
+                fprintf(stderr, "Error: Tried to set control %d = %d\n",
+                        arg_ctrls[i][0], arg_ctrls[i][1]);
 
             ctx_exit_on_error(&encoder, "Failed to control codec");
         }
@@ -1037,13 +1040,15 @@
 
             if (!arg_limit || frames_in < arg_limit)
             {
-                frame_avail = read_frame(infile, &raw, file_type, &y4m);
+                frame_avail = read_frame(infile, &raw, file_type, &y4m,
+                                         &detect);
 
                 if (frame_avail)
                     frames_in++;
 
-                printf("\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
-                       arg_passes, frames_in, frames_out, nbytes);
+                fprintf(stderr,
+                        "\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
+                        arg_passes, frames_in, frames_out, nbytes);
             }
             else
                 frame_avail = 0;
@@ -1067,8 +1072,8 @@
                 {
                 case VPX_CODEC_CX_FRAME_PKT:
                     frames_out++;
-                    printf(" %6luF",
-                           (unsigned long)pkt->data.frame.sz);
+                    fprintf(stderr, " %6luF",
+                            (unsigned long)pkt->data.frame.sz);
                     write_ivf_frame_header(outfile, pkt);
                     fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile);
                     nbytes += pkt->data.raw.sz;
@@ -1075,7 +1080,7 @@
                     break;
                 case VPX_CODEC_STATS_PKT:
                     frames_out++;
-                    printf(" %6luS",
+                    fprintf(stderr, " %6luS",
                            (unsigned long)pkt->data.twopass_stats.sz);
                     stats_write(&stats,
                                 pkt->data.twopass_stats.buf,
@@ -1089,7 +1094,7 @@
                         int i;
 
                         for (i = 0; i < 4; i++)
-                            printf("%.3lf ", pkt->data.psnr.psnr[i]);
+                            fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]);
                     }
 
                     break;
@@ -1104,7 +1109,8 @@
         /* this bitrate calc is simplified and relies on the fact that this
          * application uses 1/timebase for framerate.
          */
-        printf("\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
+        fprintf(stderr,
+               "\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
                " %7lu %s (%.2f fps)\033[K", pass + 1,
                arg_passes, frames_in, frames_out, nbytes, nbytes * 8 / frames_in,
                nbytes * 8 *(int64_t)cfg.g_timebase.den/2/ cfg.g_timebase.num / frames_in,
@@ -1121,7 +1127,7 @@
 
         fclose(outfile);
         stats_close(&stats);
-        printf("\n");
+        fprintf(stderr, "\n");
 
         if (one_pass_only)
             break;