diff options
author | Yunqing Wang <yunqingwang@google.com> | 2011-10-25 15:14:16 -0400 |
---|---|---|
committer | Yunqing Wang <yunqingwang@google.com> | 2011-12-05 17:59:42 -0500 |
commit | aa7335e610b961626f77130bc99b24de1031601d (patch) | |
tree | cfdd17dd049a005e30ec8d515fd6d303e035754c /vp8/vp8_cx_iface.c | |
parent | 6127af60c1eb4f20b03a4a34eb53704592194bed (diff) | |
download | libvpx-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.c | 60 |
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 */ }; |