summaryrefslogtreecommitdiff
path: root/vp8/vp8_cx_iface.c
diff options
context:
space:
mode:
authorYunqing Wang <yunqingwang@google.com>2011-10-25 15:14:16 -0400
committerYunqing Wang <yunqingwang@google.com>2011-12-05 17:59:42 -0500
commitaa7335e610b961626f77130bc99b24de1031601d (patch)
treecfdd17dd049a005e30ec8d515fd6d303e035754c /vp8/vp8_cx_iface.c
parent6127af60c1eb4f20b03a4a34eb53704592194bed (diff)
downloadlibvpx-aa7335e610b961626f77130bc99b24de1031601d.tar
libvpx-aa7335e610b961626f77130bc99b24de1031601d.tar.gz
libvpx-aa7335e610b961626f77130bc99b24de1031601d.tar.bz2
libvpx-aa7335e610b961626f77130bc99b24de1031601d.zip
Multiple-resolution encoder
The example encoder down-samples the input video frames a number of times with a down-sampling factor, and then encodes and outputs bitstreams with different resolutions. Support arbitrary down-sampling factor, and down-sampling factor can be different for each encoding level. For example, the encoder can be tested as follows. 1. Configure with multi-resolution encoding enabled: ../libvpx/configure --target=x86-linux-gcc --disable-codecs --enable-vp8 --enable-runtime_cpu_detect --enable-debug --disable-install-docs --enable-error-concealment --enable-multi-res-encoding 2. Run make 3. Encode: If input video is 1280x720, run: ./vp8_multi_resolution_encoder 1280 720 input.yuv 1.ivf 2.ivf 3.ivf 1 (output: 1.ivf(1280x720); 2.ivf(640x360); 3.ivf(320x180). The last parameter is set to 1/0 to show/not show PSNR.) 4. Decode: ./simple_decoder 1.ivf 1.yuv ./simple_decoder 2.ivf 2.yuv ./simple_decoder 3.ivf 3.yuv 5. View video: mplayer 1.yuv -demuxer rawvideo -rawvideo w=1280:h=720 -loop 0 -fps 30 mplayer 2.yuv -demuxer rawvideo -rawvideo w=640:h=360 -loop 0 -fps 30 mplayer 3.yuv -demuxer rawvideo -rawvideo w=320:h=180 -loop 0 -fps 30 The encoding parameters can be modified in vp8_multi_resolution_encoder.c, for example, target bitrate, frame rate... Modified API. John helped a lot with that. Thanks! Change-Id: I03be9a51167eddf94399f92d269599fb3f3d54f5
Diffstat (limited to 'vp8/vp8_cx_iface.c')
-rw-r--r--vp8/vp8_cx_iface.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index 4f21e1456..5bb6b4099 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -264,7 +264,8 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
vpx_codec_enc_cfg_t cfg,
- struct vp8_extracfg vp8_cfg)
+ struct vp8_extracfg vp8_cfg,
+ vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
{
oxcf->multi_threaded = cfg.g_threads;
oxcf->Version = cfg.g_profile;
@@ -355,6 +356,17 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
}
+#if CONFIG_MULTI_RES_ENCODING
+ if(mr_cfg)
+ {
+ oxcf->mr_total_resolutions = mr_cfg->mr_total_resolutions;
+ oxcf->mr_encoder_id = mr_cfg->mr_encoder_id;
+ oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num;
+ oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den;
+ oxcf->mr_low_res_mode_info = mr_cfg->mr_low_res_mode_info;
+ }
+#endif
+
//oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
//strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
@@ -432,7 +444,7 @@ static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx,
if (!res)
{
ctx->cfg = *cfg;
- set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
+ set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
vp8_change_config(ctx->cpi, &ctx->oxcf);
}
@@ -498,14 +510,38 @@ static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
if (!res)
{
ctx->vp8_cfg = xcfg;
- set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
+ set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
vp8_change_config(ctx->cpi, &ctx->oxcf);
}
return res;
#undef MAP
}
-static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
+
+static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
+ void **mem_loc)
+{
+ vpx_codec_err_t res = 0;
+
+#if CONFIG_MULTI_RES_ENCODING
+ int mb_rows = ((cfg->g_w + 15) >>4);
+ int mb_cols = ((cfg->g_h + 15) >>4);
+
+ *mem_loc = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_INFO));
+ if(!(*mem_loc))
+ {
+ free(*mem_loc);
+ res = VPX_CODEC_MEM_ERROR;
+ }
+ else
+ res = VPX_CODEC_OK;
+#endif
+
+ return res;
+}
+
+static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
+ vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
{
vpx_codec_err_t res = VPX_DEC_OK;
struct vpx_codec_alg_priv *priv;
@@ -570,9 +606,16 @@ static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
if (!res)
{
+ if(mr_cfg)
+ ctx->priv->enc.total_encoders = mr_cfg->mr_total_resolutions;
+ else
+ ctx->priv->enc.total_encoders = 1;
+
set_vp8e_config(&ctx->priv->alg_priv->oxcf,
ctx->priv->alg_priv->cfg,
- ctx->priv->alg_priv->vp8_cfg);
+ ctx->priv->alg_priv->vp8_cfg,
+ mr_cfg);
+
optr = vp8_create_compressor(&ctx->priv->alg_priv->oxcf);
if (!optr)
@@ -587,6 +630,11 @@ static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
{
+#if CONFIG_MULTI_RES_ENCODING
+ /* Free multi-encoder shared memory */
+ if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1))
+ free(ctx->oxcf.mr_low_res_mode_info);
+#endif
free(ctx->cx_data);
vp8_remove_compressor(&ctx->cpi);
@@ -1223,6 +1271,7 @@ CODEC_INTERFACE(vpx_codec_vp8_cx) =
vp8e_set_config,
NOT_IMPLEMENTED,
vp8e_get_preview,
+ vp8e_mr_alloc_mem,
} /* encoder functions */
};
@@ -1307,5 +1356,6 @@ vpx_codec_iface_t vpx_enc_vp8_algo =
vp8e_set_config,
NOT_IMPLEMENTED,
vp8e_get_preview,
+ vp8e_mr_alloc_mem,
} /* encoder functions */
};