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
diff --git a/vp8_multi_resolution_encoder.c b/vp8_multi_resolution_encoder.c
index 11c33d6..633c039 100644
--- a/vp8_multi_resolution_encoder.c
+++ b/vp8_multi_resolution_encoder.c
@@ -212,7 +212,10 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
}
/* 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 @@
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 @@
/* 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]);
}