Allow to skip highest-resolution encoding in multi-resolution encoder
Sometimes, a user doesn't have enough bandwidth to send high-resolution (i.e. HD) video even though the camera catches HD video. This change allowed users to skip highest-resolution encoding by setting that level's target bit rate to 0. To test it, modify the following line in vp8_multi_resolution_encoder.c. unsigned int target_bitrate[NUM_ENCODERS]={1400, 500, 100}; To skip the highest-resolution level, change it to unsigned int target_bitrate[NUM_ENCODERS]={0, 500, 100}; To skip the first and second highest resolution levels, change it to unsigned int target_bitrate[NUM_ENCODERS]={0, 0, 100}; This change also fixed a small problem in mapping, which slightly helped quality and performance. Change-Id: I977bae9a9fbfba85c8be4bd5af01539f2b84bc81
This commit is contained in:
parent
07c6eb18ad
commit
fa1a9290e6
@ -413,12 +413,11 @@ void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd, int *dissim,
|
||||
* such as 2, 4, 8. Will revisit it if needed.
|
||||
* Should also try using a look-up table to see if it helps
|
||||
* performance. */
|
||||
int round = cpi->oxcf.mr_down_sampling_factor.num/2;
|
||||
int parent_mb_row, parent_mb_col;
|
||||
|
||||
parent_mb_row = (mb_row*cpi->oxcf.mr_down_sampling_factor.den+round)
|
||||
parent_mb_row = mb_row*cpi->oxcf.mr_down_sampling_factor.den
|
||||
/cpi->oxcf.mr_down_sampling_factor.num;
|
||||
parent_mb_col = (mb_col*cpi->oxcf.mr_down_sampling_factor.den+round)
|
||||
parent_mb_col = mb_col*cpi->oxcf.mr_down_sampling_factor.den
|
||||
/cpi->oxcf.mr_down_sampling_factor.num;
|
||||
parent_mb_index = parent_mb_row*cpi->mr_low_res_mb_cols + parent_mb_col;
|
||||
}
|
||||
|
@ -212,7 +212,10 @@ int main(int argc, char **argv)
|
||||
double psnr_totals[NUM_ENCODERS][4] = {{0,0}};
|
||||
int psnr_count[NUM_ENCODERS] = {0};
|
||||
|
||||
/* Set the required target bitrates for each resolution level. */
|
||||
/* Set the required target bitrates for each resolution level.
|
||||
* If target bitrate for highest-resolution level is set to 0,
|
||||
* (i.e. target_bitrate[0]=0), we skip encoding at that level.
|
||||
*/
|
||||
unsigned int target_bitrate[NUM_ENCODERS]={1400, 500, 100};
|
||||
/* Enter the frame rate of the input video */
|
||||
int framerate = 30;
|
||||
@ -221,6 +224,9 @@ int main(int argc, char **argv)
|
||||
dsf[1] controls down sampling from level 1 to level 2;
|
||||
dsf[2] is not used. */
|
||||
vpx_rational_t dsf[NUM_ENCODERS] = {{2, 1}, {2, 1}, {1, 1}};
|
||||
/* Encode starting from which resolution level. Normally it is 0 that
|
||||
* means the original(highest) resolution. */
|
||||
int s_lvl = 0;
|
||||
|
||||
if(argc!= (5+NUM_ENCODERS))
|
||||
die("Usage: %s <width> <height> <infile> <outfile(s)> <output psnr?>\n",
|
||||
@ -234,6 +240,21 @@ int main(int argc, char **argv)
|
||||
if(width < 16 || width%2 || height <16 || height%2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
|
||||
/* Check to see if we need to encode all resolution levels */
|
||||
for (i=0; i<NUM_ENCODERS; i++)
|
||||
{
|
||||
if (target_bitrate[i])
|
||||
break;
|
||||
else
|
||||
s_lvl += 1;
|
||||
}
|
||||
|
||||
if (s_lvl >= NUM_ENCODERS)
|
||||
{
|
||||
printf("No encoding: total number of encoders is 0!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open input video file for encoding */
|
||||
if(!(infile = fopen(argv[3], "rb")))
|
||||
die("Failed to open %s for reading", argv[3]);
|
||||
@ -321,17 +342,15 @@ int main(int argc, char **argv)
|
||||
else
|
||||
read_frame_p = read_frame_by_row;
|
||||
|
||||
for (i=0; i< NUM_ENCODERS; i++)
|
||||
write_ivf_file_header(outfile[i], &cfg[i], 0);
|
||||
|
||||
/* Initialize multi-encoder */
|
||||
if(vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
|
||||
(show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
|
||||
die_codec(&codec[0], "Failed to initialize encoder");
|
||||
if(vpx_codec_enc_init_multi(&codec[s_lvl], interface, &cfg[s_lvl], s_lvl,
|
||||
NUM_ENCODERS,
|
||||
(show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[s_lvl]))
|
||||
die_codec(&codec[s_lvl], "Failed to initialize encoder");
|
||||
|
||||
/* The extra encoding configuration parameters can be set as follows. */
|
||||
/* Set encoding speed */
|
||||
for ( i=0; i<NUM_ENCODERS; i++)
|
||||
for ( i=s_lvl; i<NUM_ENCODERS; i++)
|
||||
{
|
||||
int speed = -6;
|
||||
if(vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
|
||||
@ -341,20 +360,25 @@ int main(int argc, char **argv)
|
||||
* better performance. */
|
||||
{
|
||||
unsigned int static_thresh = 1000;
|
||||
if(vpx_codec_control(&codec[0], VP8E_SET_STATIC_THRESHOLD, static_thresh))
|
||||
die_codec(&codec[0], "Failed to set static threshold");
|
||||
if(vpx_codec_control(&codec[s_lvl], VP8E_SET_STATIC_THRESHOLD,
|
||||
static_thresh))
|
||||
die_codec(&codec[s_lvl], "Failed to set static threshold");
|
||||
}
|
||||
/* Set static thresh = 0 for other encoders for better quality */
|
||||
for ( i=1; i<NUM_ENCODERS; i++)
|
||||
for ( i=s_lvl+1; i<NUM_ENCODERS; i++)
|
||||
{
|
||||
unsigned int static_thresh = 0;
|
||||
if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, static_thresh))
|
||||
if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD,
|
||||
static_thresh))
|
||||
die_codec(&codec[i], "Failed to set static threshold");
|
||||
}
|
||||
|
||||
frame_avail = 1;
|
||||
got_data = 0;
|
||||
|
||||
for (i=s_lvl ; i< NUM_ENCODERS; i++)
|
||||
write_ivf_file_header(outfile[i], &cfg[i], 0);
|
||||
|
||||
while(frame_avail || got_data)
|
||||
{
|
||||
vpx_codec_iter_t iter[NUM_ENCODERS]={NULL};
|
||||
@ -381,11 +405,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Encode each frame at multi-levels */
|
||||
if(vpx_codec_encode(&codec[0], frame_avail? &raw[0] : NULL,
|
||||
if(vpx_codec_encode(&codec[s_lvl], frame_avail? &raw[s_lvl] : NULL,
|
||||
frame_cnt, 1, flags, arg_deadline))
|
||||
die_codec(&codec[0], "Failed to encode frame");
|
||||
die_codec(&codec[s_lvl], "Failed to encode frame");
|
||||
|
||||
for (i=NUM_ENCODERS-1; i>=0 ; i--)
|
||||
for (i=NUM_ENCODERS-1; i>=s_lvl ; i--)
|
||||
{
|
||||
got_data = 0;
|
||||
|
||||
@ -428,7 +452,7 @@ int main(int argc, char **argv)
|
||||
|
||||
fclose(infile);
|
||||
|
||||
for (i=0; i< NUM_ENCODERS; i++)
|
||||
for (i=s_lvl; i< NUM_ENCODERS; i++)
|
||||
{
|
||||
printf("Processed %ld frames.\n",(long int)frame_cnt-1);
|
||||
|
||||
@ -454,8 +478,11 @@ int main(int argc, char **argv)
|
||||
/* Try to rewrite the file header with the actual frame count */
|
||||
if(!fseek(outfile[i], 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile[i], &cfg[i], frame_cnt-1);
|
||||
fclose(outfile[i]);
|
||||
}
|
||||
|
||||
for (i=0; i< NUM_ENCODERS; i++)
|
||||
{
|
||||
fclose(outfile[i]);
|
||||
vpx_img_free(&raw[i]);
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,7 @@ vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iface_t *iface,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int s_lvl,
|
||||
int num_enc,
|
||||
vpx_codec_flags_t flags,
|
||||
vpx_rational_t *dsf,
|
||||
@ -99,7 +100,7 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
|
||||
|
||||
if(!(res = iface->enc.mr_get_mem_loc(cfg, &mem_loc)))
|
||||
{
|
||||
for (i = 0; i < num_enc; i++)
|
||||
for (i = s_lvl; i < num_enc; i++)
|
||||
{
|
||||
vpx_codec_priv_enc_mr_cfg_t mr_cfg;
|
||||
|
||||
@ -112,7 +113,7 @@ vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
|
||||
}
|
||||
|
||||
mr_cfg.mr_low_res_mode_info = mem_loc;
|
||||
mr_cfg.mr_total_resolutions = num_enc;
|
||||
mr_cfg.mr_total_resolutions = num_enc - s_lvl;
|
||||
mr_cfg.mr_encoder_id = num_enc-1-i;
|
||||
mr_cfg.mr_down_sampling_factor.num = dsf->num;
|
||||
mr_cfg.mr_down_sampling_factor.den = dsf->den;
|
||||
|
@ -688,6 +688,7 @@ extern "C" {
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[in] iface Pointer to the algorithm interface to use.
|
||||
* \param[in] cfg Configuration to use, if known. May be NULL.
|
||||
* \param[in] s_lvl Starting encoder id. Normally it is 0.
|
||||
* \param[in] num_enc Total number of encoders.
|
||||
* \param[in] flags Bitfield of VPX_CODEC_USE_* flags
|
||||
* \param[in] dsf Pointer to down-sampling factors.
|
||||
@ -701,6 +702,7 @@ extern "C" {
|
||||
vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iface_t *iface,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int s_lvl,
|
||||
int num_enc,
|
||||
vpx_codec_flags_t flags,
|
||||
vpx_rational_t *dsf,
|
||||
@ -711,8 +713,8 @@ extern "C" {
|
||||
*
|
||||
* Ensures the ABI version parameter is properly set.
|
||||
*/
|
||||
#define vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf) \
|
||||
vpx_codec_enc_init_multi_ver(ctx, iface, cfg, num_enc, flags, dsf, \
|
||||
#define vpx_codec_enc_init_multi(ctx, iface, cfg, s_lvl, num_enc, flags, dsf) \
|
||||
vpx_codec_enc_init_multi_ver(ctx, iface, cfg, s_lvl, num_enc, flags, dsf, \
|
||||
VPX_ENCODER_ABI_VERSION)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user