Commit eb9048b9 authored by Simon Morlat's avatar Simon Morlat
Browse files

make mediastreamer2 more clever while choosing best video configurations by...

make mediastreamer2 more clever while choosing best video configurations by putting the min number of cpu required into the table.
Simplifies greatly the code.
parent 4e131a18
......@@ -16,7 +16,7 @@ MEDIASTREAMER_MINOR_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f2)
MEDIASTREAMER_MICRO_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f3)
MEDIASTREAMER_EXTRA_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f4)
LIBMEDIASTREAMER_SO_CURRENT=3 dnl increment this number when you add/change/remove an interface
LIBMEDIASTREAMER_SO_CURRENT=4 dnl increment this number when you add/change/remove an interface
LIBMEDIASTREAMER_SO_REVISION=0 dnl increment this number when you change source code, without changing interfaces; set to 0 when incrementing CURRENT
LIBMEDIASTREAMER_SO_AGE=0 dnl increment this number when you add an interface, set to 0 if you remove an interface
......
......@@ -141,6 +141,7 @@ struct _MSVideoConfiguration {
int bitrate_limit; /**< The maximum bitrate to use when this video configuration is used. */
MSVideoSize vsize; /**< The video size that is used when using this video configuration. */
float fps; /**< The FPS that is used when using this video configuration. */
int mincpu; /**< The minimum cpu count necessary when this configuration is used */
void *extra; /**< A pointer to some extra parameters that may be used by the encoder when using this video configuration. */
};
......@@ -369,17 +370,19 @@ MS2_PUBLIC bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t curre
* Find the best video configuration from a list of configurations according to a given bitrate limit.
* @param[in] vconf_list The list of video configurations to choose from.
* @param[in] bitrate The maximum bitrate limit the chosen configuration is allowed to use.
* @param[in] cpucount the number of cpu that can be used for this encoding.
* @return The best video configuration found in the given list.
*/
MS2_PUBLIC MSVideoConfiguration ms_video_find_best_configuration_for_bitrate(const MSVideoConfiguration *vconf_list, int bitrate);
MS2_PUBLIC MSVideoConfiguration ms_video_find_best_configuration_for_bitrate(const MSVideoConfiguration *vconf_list, int bitrate, int cpucount);
/**
* Find the best video configuration from a list of configuration according to a given video size.
* @param[in] vconf_list The list of video configurations to choose from.
* @param[in] vsize The maximum video size the chosen configuration is allowed to use.
* @param[in] cpucount the number of cpu that can be used for this encoding.
* @return The best video configuration found in the given list.
*/
MS2_PUBLIC MSVideoConfiguration ms_video_find_best_configuration_for_size(const MSVideoConfiguration *vconf_list, MSVideoSize vsize);
MS2_PUBLIC MSVideoConfiguration ms_video_find_best_configuration_for_size(const MSVideoConfiguration *vconf_list, MSVideoSize vsize, int cpucount);
#ifdef __cplusplus
}
......
......@@ -38,8 +38,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define RATE_CONTROL_MARGIN 15000 /*bits/second*/
#define MS_VIDEOENC_CONF(required_bitrate, bitrate_limit, resolution, fps, qminvalue) \
{ required_bitrate, bitrate_limit, { MS_VIDEO_SIZE_ ## resolution ## _W, MS_VIDEO_SIZE_ ## resolution ## _H }, fps, (void *)&qmin ## qminvalue }
#define MS_VIDEOENC_CONF(required_bitrate, bitrate_limit, resolution, fps, cpu, qminvalue) \
{ required_bitrate, bitrate_limit, { MS_VIDEO_SIZE_ ## resolution ## _W, MS_VIDEO_SIZE_ ## resolution ## _H }, fps, cpu, (void *)&qmin ## qminvalue }
static bool_t avcodec_initialized=FALSE;
......@@ -51,55 +51,54 @@ static const int qmin4 = 4;
static const int qmin5 = 5;
static const MSVideoConfiguration h263_conf_list[] = {
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 3),
MS_VIDEOENC_CONF( 128000, 256000, QCIF, 10, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 5)
MS_VIDEOENC_CONF( 800000, 1024000, 4CIF, 25, 2, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 1, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 1, 3),
MS_VIDEOENC_CONF( 128000, 256000, QCIF, 10, 1, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 1, 5)
};
static const MSVideoConfiguration h263p_conf_list[] = {
MS_VIDEOENC_CONF(800000, 1024000, 4CIF, 25, 2),
MS_VIDEOENC_CONF(512000, 800000, CIF, 25, 2),
MS_VIDEOENC_CONF(256000, 512000, CIF, 17, 3),
MS_VIDEOENC_CONF(128000, 256000, QCIF, 10, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 5)
MS_VIDEOENC_CONF(800000, 1024000, 4CIF, 25, 2, 2),
MS_VIDEOENC_CONF(512000, 800000, CIF, 25, 1, 2),
MS_VIDEOENC_CONF(256000, 512000, CIF, 17, 1, 3),
MS_VIDEOENC_CONF(128000, 256000, QCIF, 10, 1, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 1, 5)
};
static const MSVideoConfiguration mjpeg_conf_list[] = {
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 5)
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 1, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 1, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 1, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 1, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 1, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 1, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 1, 5)
};
static const MSVideoConfiguration mpeg4_conf_list[] = {
MS_VIDEOENC_CONF(2048000, 2560000, SXGA_MINUS, 25, 2),
MS_VIDEOENC_CONF(2048000, 2560000, 720P, 25, 2),
MS_VIDEOENC_CONF(1536000, 2048000, XGA, 25, 2),
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 5)
MS_VIDEOENC_CONF(2048000, 2560000, SXGA_MINUS, 25, 4, 2),
MS_VIDEOENC_CONF(2048000, 2560000, 720P, 25, 4, 2),
MS_VIDEOENC_CONF(1536000, 2048000, XGA, 25, 4, 2),
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 1, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 1, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 1, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 1, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 1, 3),
MS_VIDEOENC_CONF( 0, 128000, QCIF, 5, 1, 5)
};
#if HAVE_AVCODEC_SNOW
static const MSVideoConfiguration snow_conf_list[] = {
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 3),
MS_VIDEOENC_CONF( 64000, 128000, QCIF, 7, 4),
MS_VIDEOENC_CONF( 0, 64000, QCIF, 5, 5)
MS_VIDEOENC_CONF(1024000, 1536000, SVGA, 25, 2, 2),
MS_VIDEOENC_CONF( 800000, 1024000, VGA, 25, 1, 2),
MS_VIDEOENC_CONF( 512000, 800000, CIF, 25, 1, 2),
MS_VIDEOENC_CONF( 256000, 512000, CIF, 17, 1, 3),
MS_VIDEOENC_CONF( 170000, 256000, QVGA, 15, 1, 3),
MS_VIDEOENC_CONF( 128000, 170000, QCIF, 10, 1, 3),
MS_VIDEOENC_CONF( 64000, 128000, QCIF, 7, 1, 4),
MS_VIDEOENC_CONF( 0, 64000, QCIF, 5, 1, 5)
};
#endif
......@@ -236,7 +235,7 @@ static void enc_init(MSFilter *f, enum CodecID codec)
s->framenum=0;
s->av_context.codec=NULL;
s->vconf_list = get_vconf_list(s);
s->vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, 500000);
s->vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, 500000, ms_get_cpu_count());
s->pict = av_frame_alloc();
}
......@@ -909,7 +908,7 @@ static int enc_set_vsize(MSFilter *f, void *arg) {
MSVideoConfiguration best_vconf;
MSVideoSize *vs = (MSVideoSize *)arg;
EncState *s=(EncState*)f->data;
best_vconf = ms_video_find_best_configuration_for_size(s->vconf_list, *vs);
best_vconf = ms_video_find_best_configuration_for_size(s->vconf_list, *vs, ms_get_cpu_count());
s->vconf.vsize = *vs;
s->vconf.fps = best_vconf.fps;
s->vconf.bitrate_limit = best_vconf.bitrate_limit;
......@@ -943,7 +942,7 @@ static int enc_set_br(MSFilter *f, void *arg) {
s->vconf.required_bitrate = br;
enc_set_configuration(f, &s->vconf);
} else {
MSVideoConfiguration best_vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, br);
MSVideoConfiguration best_vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, br, ms_get_cpu_count());
enc_set_configuration(f, &best_vconf);
}
return 0;
......
......@@ -33,47 +33,33 @@
#include <vpx/vp8cx.h>
#define MS_VP8_CONF(required_bitrate, bitrate_limit, resolution, fps) \
{ required_bitrate, bitrate_limit, { MS_VIDEO_SIZE_ ## resolution ## _W, MS_VIDEO_SIZE_ ## resolution ## _H }, fps, NULL }
#define MS_VP8_CONF(required_bitrate, bitrate_limit, resolution, fps, cpus) \
{ required_bitrate, bitrate_limit, { MS_VIDEO_SIZE_ ## resolution ## _W, MS_VIDEO_SIZE_ ## resolution ## _H }, fps, cpus, NULL }
static const MSVideoConfiguration vp8_conf_list[] = {
#if defined(ANDROID) || (TARGET_OS_IPHONE == 1) || defined(__arm__)
MS_VP8_CONF(300000, 600000, VGA, 12),
MS_VP8_CONF(100000, 300000, QVGA, 10),
MS_VP8_CONF( 64000, 100000, QCIF, 10),
MS_VP8_CONF( 0, 64000, QCIF, 5)
MS_VP8_CONF(2048000, 2560000, UXGA, 12, 2),
MS_VP8_CONF(1024000, 1536000, SXGA_MINUS, 12, 2),
MS_VP8_CONF( 750000, 1024000, XGA, 12, 2),
MS_VP8_CONF( 500000, 750000, SVGA, 12, 2),
MS_VP8_CONF( 300000, 500000, VGA, 15, 2),
MS_VP8_CONF( 100000, 300000, QVGA, 18, 2),
MS_VP8_CONF( 64000, 100000, QCIF, 12, 2),
MS_VP8_CONF(300000, 600000, VGA, 12, 1),
MS_VP8_CONF(100000, 300000, QVGA, 10, 1),
MS_VP8_CONF( 64000, 100000, QCIF, 10, 1),
MS_VP8_CONF( 0, 64000, QCIF, 5, 1)
#else
MS_VP8_CONF(1024000, 1536000, VGA, 25),
MS_VP8_CONF( 350000, 600000, VGA, 15),
MS_VP8_CONF( 200000, 350000, CIF, 15),
MS_VP8_CONF( 150000, 200000, QVGA, 15),
MS_VP8_CONF( 100000, 150000, QVGA, 10),
MS_VP8_CONF( 64000, 100000, QCIF, 12),
MS_VP8_CONF( 0, 64000, QCIF, 5)
#endif
};
static const MSVideoConfiguration multicore_vp8_conf_list[] = {
#if defined(ANDROID) || (TARGET_OS_IPHONE == 1) || defined(__arm__)
MS_VP8_CONF(2048000, 2560000, UXGA, 12),
MS_VP8_CONF(1024000, 1536000, SXGA_MINUS, 12),
MS_VP8_CONF( 750000, 1024000, XGA, 12),
MS_VP8_CONF( 500000, 750000, SVGA, 12),
MS_VP8_CONF( 300000, 500000, VGA, 15),
MS_VP8_CONF( 100000, 300000, QVGA, 18),
MS_VP8_CONF( 64000, 100000, QCIF, 12),
MS_VP8_CONF( 0, 64000, QCIF, 5)
#else
MS_VP8_CONF(1536000, 2560000, SXGA_MINUS, 15),
MS_VP8_CONF(1536000, 2560000, 720P, 15),
MS_VP8_CONF(1024000, 1536000, XGA, 15),
MS_VP8_CONF( 600000, 1024000, SVGA, 20),
MS_VP8_CONF( 350000, 600000, VGA, 20),
MS_VP8_CONF( 200000, 350000, CIF, 18),
MS_VP8_CONF( 150000, 200000, QVGA, 15),
MS_VP8_CONF( 100000, 150000, QVGA, 10),
MS_VP8_CONF( 64000, 100000, QCIF, 12),
MS_VP8_CONF( 0, 64000, QCIF, 5)
MS_VP8_CONF(1536000, 2560000, SXGA_MINUS, 20, 4),
MS_VP8_CONF(1536000, 2560000, 720P, 20, 4),
MS_VP8_CONF(1024000, 1536000, XGA, 20, 4),
MS_VP8_CONF( 600000, 1024000, SVGA, 20, 2),
MS_VP8_CONF( 350000, 600000, VGA, 20, 1),
MS_VP8_CONF( 200000, 350000, CIF, 18, 1),
MS_VP8_CONF( 150000, 200000, QVGA, 15, 1),
MS_VP8_CONF( 100000, 150000, QVGA, 10, 1),
MS_VP8_CONF( 64000, 100000, QCIF, 12, 1),
MS_VP8_CONF( 0, 64000, QCIF, 5 ,1)
#endif
};
......@@ -115,10 +101,9 @@ static void enc_init(MSFilter *f) {
s->iface = vpx_codec_vp8_cx();
ms_message("Using %s", vpx_codec_iface_name(s->iface));
if (ms_get_cpu_count() > 1) s->vconf_list = &multicore_vp8_conf_list[0];
else s->vconf_list = &vp8_conf_list[0];
s->vconf_list = &vp8_conf_list[0];
MS_VIDEO_SIZE_ASSIGN(vsize, CIF);
s->vconf = ms_video_find_best_configuration_for_size(s->vconf_list, vsize);
s->vconf = ms_video_find_best_configuration_for_size(s->vconf_list, vsize, ms_get_cpu_count());
s->frame_count = 0;
s->last_fir_seq_nr = -1;
#ifdef PICTURE_ID_ON_16_BITS
......@@ -513,7 +498,7 @@ static int enc_set_vsize(MSFilter *f, void *data) {
MSVideoConfiguration best_vconf;
MSVideoSize *vs = (MSVideoSize *)data;
EncState *s = (EncState *)f->data;
best_vconf = ms_video_find_best_configuration_for_size(s->vconf_list, *vs);
best_vconf = ms_video_find_best_configuration_for_size(s->vconf_list, *vs, ms_get_cpu_count());
s->vconf.vsize = *vs;
s->vconf.fps = best_vconf.fps;
s->vconf.bitrate_limit = best_vconf.bitrate_limit;
......@@ -557,7 +542,7 @@ static int enc_set_br(MSFilter *f, void *data) {
s->vconf.required_bitrate = br;
enc_set_configuration(f, &s->vconf);
} else {
MSVideoConfiguration best_vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, br);
MSVideoConfiguration best_vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, br, ms_get_cpu_count());
enc_set_configuration(f, &best_vconf);
}
return 0;
......
......@@ -830,36 +830,49 @@ float ms_average_fps_get(const MSAverageFPS* afps){
return afps->mean_inter_frame!=0 ? 1.0/afps->mean_inter_frame : 0.0;
}
MSVideoConfiguration ms_video_find_best_configuration_for_bitrate(const MSVideoConfiguration *vconf_list, int bitrate) {
const MSVideoConfiguration *current_vconf = vconf_list;
const MSVideoConfiguration *closer_to_best_vconf = NULL;
MSVideoConfiguration best_vconf;
while (closer_to_best_vconf == NULL) {
if ((bitrate >= current_vconf->required_bitrate) || (current_vconf->required_bitrate == 0)) {
closer_to_best_vconf = current_vconf;
} else {
current_vconf++;
}
}
MSVideoConfiguration ms_video_find_best_configuration_for_bitrate(const MSVideoConfiguration *vconf_list, int bitrate , int cpu_count) {
const MSVideoConfiguration *vconf_it = vconf_list;
MSVideoConfiguration best_vconf={0};
int max_pixels=0;
memcpy(&best_vconf, closer_to_best_vconf, sizeof(best_vconf));
best_vconf.required_bitrate = bitrate;
/* search for configuration that has compatible cpu count, compatible bitrate, biggest video size, and greater fps*/
do{
int pixels=vconf_it->vsize.width*vconf_it->vsize.height;
if ((cpu_count>=vconf_it->mincpu && bitrate>=vconf_it->required_bitrate) || vconf_it->required_bitrate==0){
if (pixels>max_pixels){
best_vconf=*vconf_it;
max_pixels=pixels;
}else if (pixels==max_pixels){
if (best_vconf.fps<vconf_it->fps){
best_vconf=*vconf_it;
}
}
}
vconf_it++;
}while(vconf_it->required_bitrate!=0);
return best_vconf;
}
MSVideoConfiguration ms_video_find_best_configuration_for_size(const MSVideoConfiguration *vconf_list, MSVideoSize vsize) {
MSVideoConfiguration ms_video_find_best_configuration_for_size(const MSVideoConfiguration *vconf_list, MSVideoSize vsize, int cpu_count) {
const MSVideoConfiguration *vconf_it = vconf_list;
MSVideoConfiguration best_vconf={0};
int min_score=INT32_MAX;
int ref_pixels=vsize.height*vsize.width;
/* search for configuration that is first nearest to target video size, then second has the greater fps,
* but any case making sure the the cpu count is sufficient*/
for(;vconf_it->required_bitrate!=0;vconf_it++){
int pixels=vconf_it->vsize.width*vconf_it->vsize.height;
int score=abs(pixels-ref_pixels);
if (score<min_score){
best_vconf=*vconf_it;
min_score=score;
if (cpu_count>=vconf_it->mincpu){
if (score<min_score){
best_vconf=*vconf_it;
min_score=score;
}else if (score==min_score){
if (best_vconf.fps<vconf_it->fps){
best_vconf=*vconf_it;
}
}
}
}
return best_vconf;
......
......@@ -582,7 +582,7 @@ int video_stream_start_with_source (VideoStream *stream, RtpProfile *profile, co
ms_message("Limiting bitrate of video encoder to %i bits/s for stream [%p]",pt->normal_bitrate,stream);
ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_GET_CONFIGURATION_LIST, &vconf_list);
if (vconf_list != NULL) {
MSVideoConfiguration vconf = ms_video_find_best_configuration_for_bitrate(vconf_list, pt->normal_bitrate);
MSVideoConfiguration vconf = ms_video_find_best_configuration_for_bitrate(vconf_list, pt->normal_bitrate, ms_get_cpu_count());
/* Adjust configuration video size to use the user preferred video size if it is lower that the configuration one. */
if ((stream->sent_vsize.height * stream->sent_vsize.width) < (vconf.vsize.height * vconf.vsize.width)) {
vconf.vsize = stream->sent_vsize;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment