shithub: libvpx

Download patch

ref: 34882b9bf538dc726fe9bec9dee2e45b8d8ea222
parent: 800ad0b886ce6776712c1835878e500ffd43af64
author: John Koleszar <jkoleszar@google.com>
date: Thu Mar 1 07:50:40 EST 2012

vpxenc: support scaling prior to encoding

Scales the input of the encoder using libyuv's "box filter". Each stream
may have a different width and height specified. If the width (or
height) parameter is missing (or is explicitly set to 0) then the value
will be calculated based on the specified height (or width) and the
input file's dimensions, preserving its aspect ratio. Leaving the height
unspecified behaves similarly.

Change-Id: Ic7026810b13be030826be80dc6f7fc4aaf0c35d0

--- a/examples.mk
+++ b/examples.mk
@@ -8,6 +8,12 @@
 ##  be found in the AUTHORS file in the root of the source tree.
 ##
 
+LIBYUV_SRCS +=  third_party/libyuv/include/libyuv/basic_types.h  \
+                third_party/libyuv/include/libyuv/cpu_id.h  \
+                third_party/libyuv/include/libyuv/scale.h  \
+                third_party/libyuv/source/row.h \
+                third_party/libyuv/source/scale.c  \
+                third_party/libyuv/source/cpu_id.c
 
 # List of examples to build. UTILS are files that are taken from the source
 # tree directly, and GEN_EXAMPLES are files that are created from the
@@ -36,6 +42,7 @@
 vpxenc.SRCS                 += libmkv/EbmlIDs.h
 vpxenc.SRCS                 += libmkv/EbmlWriter.c
 vpxenc.SRCS                 += libmkv/EbmlWriter.h
+vpxenc.SRCS                 += $(LIBYUV_SRCS)
 vpxenc.GUID                  = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
 vpxenc.DESCRIPTION           = Full featured encoder
 UTILS-$(CONFIG_VP8_ENCODER)    += vp8_scalable_patterns.c
@@ -99,13 +106,7 @@
 
 # C file is provided, not generated automatically.
 UTILS-$(CONFIG_MULTI_RES_ENCODING) += vp8_multi_resolution_encoder.c
-vp8_multi_resolution_encoder.SRCS  \
-                         += third_party/libyuv/include/libyuv/basic_types.h  \
-                            third_party/libyuv/include/libyuv/cpu_id.h  \
-                            third_party/libyuv/include/libyuv/scale.h  \
-                            third_party/libyuv/source/row.h \
-                            third_party/libyuv/source/scale.c  \
-                            third_party/libyuv/source/cpu_id.c
+vp8_multi_resolution_encoder.SRCS         += $(LIBYUV_SRCS)
 vp8_multi_resolution_encoder.GUID         = 04f8738e-63c8-423b-90fa-7c2703a374de
 vp8_multi_resolution_encoder.DESCRIPTION  = VP8 Multiple-resolution Encoding
 
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -47,6 +47,7 @@
 #include "y4minput.h"
 #include "libmkv/EbmlWriter.h"
 #include "libmkv/EbmlIDs.h"
+#include "third_party/libyuv/include/libyuv/scale.h"
 
 /* Need special handling of these functions on Windows */
 #if defined(_MSC_VER)
@@ -1642,6 +1643,7 @@
   uint64_t                  cx_time;
   size_t                    nbytes;
   stats_io_t                stats;
+  struct vpx_image         *img;
   vpx_codec_ctx_t           decoder;
   vpx_ref_frame_t           ref_enc;
   vpx_ref_frame_t           ref_dec;
@@ -2061,11 +2063,15 @@
 static void set_stream_dimensions(struct stream_state *stream,
                                   unsigned int w,
                                   unsigned int h) {
-  if ((stream->config.cfg.g_w && stream->config.cfg.g_w != w)
-      || (stream->config.cfg.g_h && stream->config.cfg.g_h != h))
-    fatal("Stream %d: Resizing not yet supported", stream->index);
-  stream->config.cfg.g_w = w;
-  stream->config.cfg.g_h = h;
+  if (!stream->config.cfg.g_w) {
+    if (!stream->config.cfg.g_h)
+      stream->config.cfg.g_w = w;
+    else
+      stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
+  }
+  if (!stream->config.cfg.g_h) {
+    stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
+  }
 }
 
 
@@ -2258,6 +2264,28 @@
   next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
                       * global->framerate.den)
                      / cfg->g_timebase.num / global->framerate.num;
+
+  /* Scale if necessary */
+  if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {
+    if (!stream->img)
+      stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420,
+                                  cfg->g_w, cfg->g_h, 16);
+    I420Scale(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
+              img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
+              img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
+              img->d_w, img->d_h,
+              stream->img->planes[VPX_PLANE_Y],
+              stream->img->stride[VPX_PLANE_Y],
+              stream->img->planes[VPX_PLANE_U],
+              stream->img->stride[VPX_PLANE_U],
+              stream->img->planes[VPX_PLANE_V],
+              stream->img->stride[VPX_PLANE_V],
+              stream->img->d_w, stream->img->d_h,
+              kFilterBox);
+
+    img = stream->img;
+  }
+
   vpx_usec_timer_start(&timer);
   vpx_codec_encode(&stream->encoder, img, frame_start,
                    (unsigned long)(next_frame_start - frame_start),
@@ -2518,6 +2546,9 @@
     });
 
     /* Update stream configurations from the input file's parameters */
+    if (!input.w || !input.h)
+      fatal("Specify stream dimensions with --width (-w) "
+            " and --height (-h)");
     FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
     FOREACH_STREAM(validate_stream_config(stream));