From f2476d444b24f4776bd640a9aac6e6ab2786619c Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 30 Jan 2006 19:21:07 +0000 Subject: [PATCH] ext/theora/theoraenc.c (theora_enc_sink_setcaps) Original commit message from CVS: 2006-01-30 Andy Wingo * ext/theora/theoraenc.c (theora_enc_sink_setcaps) (gst_theora_enc_init): Pull the granule shift out of the encoder. (granulepos_add): New function, handles the messiness of adjusting granulepos values. (theora_buffer_from_packet): (theora_enc_chain): (theora_enc_sink_event): Use granulepos_add, not +. * tests/check/pipelines/theoraenc.c (check_buffer_granulepos_from_starttime): Just check the frame count, not the actual granulepos -- we can't dictate to the encoder when it should be placing keyframes. --- ChangeLog | 15 ++++++++++++ ext/theora/gsttheoraenc.h | 1 + ext/theora/theoraenc.c | 48 +++++++++++++++++++++++++++++++++++---- tests/check/pipelines/theoraenc.c | 13 +++++++---- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f23fe5..6a7afd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-01-30 Andy Wingo + + * ext/theora/theoraenc.c (theora_enc_sink_setcaps) + (gst_theora_enc_init): Pull the granule shift out of the encoder. + (granulepos_add): New function, handles the messiness of adjusting + granulepos values. + (theora_buffer_from_packet): + (theora_enc_chain): + (theora_enc_sink_event): Use granulepos_add, not +. + + * tests/check/pipelines/theoraenc.c + (check_buffer_granulepos_from_starttime): Just check the frame + count, not the actual granulepos -- we can't dictate to the + encoder when it should be placing keyframes. + 2006-01-30 Thomas Vander Stichele * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_start): diff --git a/ext/theora/gsttheoraenc.h b/ext/theora/gsttheoraenc.h index 55beb89..6483723 100644 --- a/ext/theora/gsttheoraenc.h +++ b/ext/theora/gsttheoraenc.h @@ -84,6 +84,7 @@ struct _GstTheoraEnc guint64 bytes_out; guint64 granulepos_offset; guint64 timestamp_offset; + gint granule_shift; }; struct _GstTheoraEncClass diff --git a/ext/theora/theoraenc.c b/ext/theora/theoraenc.c index 3f7c121..b236628 100644 --- a/ext/theora/theoraenc.c +++ b/ext/theora/theoraenc.c @@ -82,6 +82,19 @@ gst_border_mode_get_type (void) #define THEORA_DEF_NOISE_SENSITIVITY 1 #define THEORA_DEF_SHARPNESS 0 +/* taken from theora/lib/toplevel.c */ +static int +_ilog (unsigned int v) +{ + int ret = 0; + + while (v) { + ret++; + v >>= 1; + } + return (ret); +} + enum { ARG_0, @@ -236,6 +249,11 @@ gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class) enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE; enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY; enc->sharpness = THEORA_DEF_SHARPNESS; + + enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1); + GST_DEBUG_OBJECT (enc, + "keyframe_frequency_force is %d, granule shift is %d", + enc->info.keyframe_frequency_force, enc->granule_shift); } static gboolean @@ -298,11 +316,29 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps) enc->info.noise_sensitivity = enc->noise_sensitivity; enc->info.sharpness = enc->sharpness; + /* as done in theora */ + enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1); + GST_DEBUG_OBJECT (enc, + "keyframe_frequency_force is %d, granule shift is %d", + enc->info.keyframe_frequency_force, enc->granule_shift); + theora_encode_init (&enc->state, &enc->info); return TRUE; } +static guint64 +granulepos_add (guint64 granulepos, guint64 addend, gint shift) +{ + GstClockTime iframe, pframe; + + iframe = granulepos >> shift; + pframe = granulepos - (iframe << shift); + iframe += addend; + + return (iframe << shift) + pframe; +} + /* prepare a buffer for transmission by passing data through libtheora */ static GstFlowReturn theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet, @@ -318,7 +354,9 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet, memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes); GST_BUFFER_OFFSET (buf) = enc->bytes_out; - GST_BUFFER_OFFSET_END (buf) = packet->granulepos + enc->granulepos_offset; + GST_BUFFER_OFFSET_END (buf) = + granulepos_add (packet->granulepos, enc->granulepos_offset, + enc->granule_shift); GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset; GST_BUFFER_DURATION (buf) = duration; @@ -418,8 +456,8 @@ theora_enc_sink_event (GstPad * pad, GstEvent * event) /* push last packet with eos flag */ while (theora_encode_packetout (&enc->state, 1, &op)) { /* See comment in the chain function */ - GstClockTime next_time = - theora_granule_time (&enc->state, op.granulepos + 1) * GST_SECOND; + GstClockTime next_time = theora_granule_time (&enc->state, + granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND; theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts); enc->next_ts = next_time; @@ -675,8 +713,8 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer) theora starts with 0 instead of 1... */ GstClockTime next_time; - next_time = - theora_granule_time (&enc->state, op.granulepos + 1) * GST_SECOND; + next_time = theora_granule_time (&enc->state, + granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND; ret = theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts); enc->next_ts = next_time; diff --git a/tests/check/pipelines/theoraenc.c b/tests/check/pipelines/theoraenc.c index ad3293c..430225e 100644 --- a/tests/check/pipelines/theoraenc.c +++ b/tests/check/pipelines/theoraenc.c @@ -25,6 +25,9 @@ #define TIMESTAMP_OFFSET 3249870963 #define FRAMERATE 10 +/* I know all of these have a shift of 6 bits */ +#define GRANULEPOS_SHIFT 6 + static GCond *cond = NULL; static GMutex *lock = NULL; static GstBuffer *buf = NULL; @@ -143,15 +146,17 @@ static void check_buffer_granulepos_from_starttime (GstBuffer * buffer, GstClockTime starttime) { - GstClockTime granulepos, expected; + GstClockTime granulepos, expected, framecount; granulepos = GST_BUFFER_OFFSET_END (buffer); + framecount = granulepos >> GRANULEPOS_SHIFT; + framecount += granulepos & ((1 << GRANULEPOS_SHIFT) - 1); expected = gst_util_uint64_scale (starttime, FRAMERATE, GST_SECOND); - fail_unless (granulepos == expected || granulepos == expected + 1, - "expected granulepos %" G_GUINT64_FORMAT + fail_unless (framecount == expected || framecount == expected + 1, + "expected frame count %" G_GUINT64_FORMAT " or %" G_GUINT64_FORMAT - ", but got granulepos %" G_GUINT64_FORMAT, + ", but got frame count %" G_GUINT64_FORMAT, expected, expected + 1, granulepos); } -- 2.7.4