vp8enc: Add property to manually specify the timebase of the encoder

https://bugzilla.gnome.org/show_bug.cgi?id=695709
This commit is contained in:
Tom Greenwood 2013-03-06 13:17:54 +00:00 committed by Sebastian Dröge
parent 7a3df1ab31
commit 5532989728
2 changed files with 45 additions and 11 deletions

View file

@ -146,6 +146,8 @@ gst_vp8_enc_user_data_free (GstVP8EncUserData * user_data)
#define DEFAULT_TUNING VP8_TUNE_PSNR #define DEFAULT_TUNING VP8_TUNE_PSNR
#define DEFAULT_CQ_LEVEL 10 #define DEFAULT_CQ_LEVEL 10
#define DEFAULT_MAX_INTRA_BITRATE_PCT 0 #define DEFAULT_MAX_INTRA_BITRATE_PCT 0
#define DEFAULT_TIMEBASE_N 0
#define DEFAULT_TIMEBASE_D 1
enum enum
{ {
@ -192,7 +194,8 @@ enum
PROP_ARNR_TYPE, PROP_ARNR_TYPE,
PROP_TUNING, PROP_TUNING,
PROP_CQ_LEVEL, PROP_CQ_LEVEL,
PROP_MAX_INTRA_BITRATE_PCT PROP_MAX_INTRA_BITRATE_PCT,
PROP_TIMEBASE
}; };
#define GST_VP8_ENC_END_USAGE_TYPE (gst_vp8_enc_end_usage_get_type()) #define GST_VP8_ENC_END_USAGE_TYPE (gst_vp8_enc_end_usage_get_type())
@ -393,8 +396,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
#define parent_class gst_vp8_enc_parent_class #define parent_class gst_vp8_enc_parent_class
G_DEFINE_TYPE_WITH_CODE (GstVP8Enc, gst_vp8_enc, GST_TYPE_VIDEO_ENCODER, G_DEFINE_TYPE_WITH_CODE (GstVP8Enc, gst_vp8_enc, GST_TYPE_VIDEO_ENCODER,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL); G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL); G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL););
);
static void static void
gst_vp8_enc_class_init (GstVP8EncClass * klass) gst_vp8_enc_class_init (GstVP8EncClass * klass)
@ -700,6 +702,12 @@ gst_vp8_enc_class_init (GstVP8EncClass * klass)
0, G_MAXINT, DEFAULT_MAX_INTRA_BITRATE_PCT, 0, G_MAXINT, DEFAULT_MAX_INTRA_BITRATE_PCT,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_TIMEBASE,
gst_param_spec_fraction ("timebase", "Shortest interframe time",
"Fraction of one second that is the shortest interframe time - normally left as zero which will default to the framerate",
0, 1, G_MAXINT, 1, DEFAULT_TIMEBASE_N, DEFAULT_TIMEBASE_D,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
GST_DEBUG_CATEGORY_INIT (gst_vp8enc_debug, "vp8enc", 0, "VP8 Encoder"); GST_DEBUG_CATEGORY_INIT (gst_vp8enc_debug, "vp8enc", 0, "VP8 Encoder");
} }
@ -768,6 +776,8 @@ gst_vp8_enc_init (GstVP8Enc * gst_vp8_enc)
gst_vp8_enc->tuning = DEFAULT_TUNING; gst_vp8_enc->tuning = DEFAULT_TUNING;
gst_vp8_enc->cq_level = DEFAULT_CQ_LEVEL; gst_vp8_enc->cq_level = DEFAULT_CQ_LEVEL;
gst_vp8_enc->max_intra_bitrate_pct = DEFAULT_MAX_INTRA_BITRATE_PCT; gst_vp8_enc->max_intra_bitrate_pct = DEFAULT_MAX_INTRA_BITRATE_PCT;
gst_vp8_enc->timebase_n = DEFAULT_TIMEBASE_N;
gst_vp8_enc->timebase_d = DEFAULT_TIMEBASE_D;
gst_vp8_enc->cfg.g_profile = DEFAULT_PROFILE; gst_vp8_enc->cfg.g_profile = DEFAULT_PROFILE;
@ -1162,6 +1172,10 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
} }
} }
break; break;
case PROP_TIMEBASE:
gst_vp8_enc->timebase_n = gst_value_get_fraction_numerator (value);
gst_vp8_enc->timebase_d = gst_value_get_fraction_denominator (value);
break;
default: default:
break; break;
} }
@ -1379,6 +1393,10 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_MAX_INTRA_BITRATE_PCT: case PROP_MAX_INTRA_BITRATE_PCT:
g_value_set_int (value, gst_vp8_enc->max_intra_bitrate_pct); g_value_set_int (value, gst_vp8_enc->max_intra_bitrate_pct);
break; break;
case PROP_TIMEBASE:
gst_value_set_fraction (value, gst_vp8_enc->timebase_n,
gst_vp8_enc->timebase_d);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1508,16 +1526,29 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info); encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info); encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
if (GST_VIDEO_INFO_FPS_D (info) == 0 || GST_VIDEO_INFO_FPS_N (info) == 0) {
/* Zero framerate but still need to setup the timebase so we if (encoder->timebase_n != 0 && encoder->timebase_d != 0) {
* presume this is RTP - VP8 payload draft states clock rate of 90000 GST_DEBUG_OBJECT (video_encoder, "Using timebase configuration");
* see specification http://tools.ietf.org/html/draft-ietf-payload-vp8-01 encoder->cfg.g_timebase.num = encoder->timebase_n;
* section 6.3.1 */ encoder->cfg.g_timebase.den = encoder->timebase_d;
encoder->cfg.g_timebase.num = 1; } else if (GST_VIDEO_INFO_FPS_D (info) != 0
encoder->cfg.g_timebase.den = 90000; && GST_VIDEO_INFO_FPS_N (info) != 0) {
} else { /* GstVideoInfo holds either the framerate or max-framerate (if framerate
* is 0) in FPS so this will be used if max-framerate or framerate
* is set */
GST_DEBUG_OBJECT (video_encoder, "Setting timebase from framerate");
encoder->cfg.g_timebase.num = GST_VIDEO_INFO_FPS_D (info); encoder->cfg.g_timebase.num = GST_VIDEO_INFO_FPS_D (info);
encoder->cfg.g_timebase.den = GST_VIDEO_INFO_FPS_N (info); encoder->cfg.g_timebase.den = GST_VIDEO_INFO_FPS_N (info);
} else {
/* Zero framerate and max-framerate but still need to setup the timebase to avoid
* a divide by zero error. Presuming the lowest common denominator will be RTP -
* VP8 payload draft states clock rate of 90000 which should work for anyone where
* FPS < 90000 (shouldn't be too many cases where it's higher) though wouldn't be optimal. RTP specification
* http://tools.ietf.org/html/draft-ietf-payload-vp8-01 section 6.3.1 */
GST_WARNING_OBJECT (encoder,
"No timebase and zero framerate setting timebase to 1/90000");
encoder->cfg.g_timebase.num = 1;
encoder->cfg.g_timebase.den = 90000;
} }
if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) { if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {

View file

@ -87,6 +87,9 @@ struct _GstVP8Enc
vp8e_tuning tuning; vp8e_tuning tuning;
unsigned int cq_level; unsigned int cq_level;
unsigned int max_intra_bitrate_pct; unsigned int max_intra_bitrate_pct;
/* Timebase - a value of 0 will use the framerate */
unsigned int timebase_n;
unsigned int timebase_d;
/* state */ /* state */
gboolean inited; gboolean inited;