ext/theora/theoraenc.c (theora_enc_sink_setcaps)

Original commit message from CVS:
2006-01-30  Andy Wingo  <wingo@pobox.com>

* 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.
This commit is contained in:
Andy Wingo 2006-01-30 19:21:07 +00:00
parent 3f905bd710
commit f2476d444b
4 changed files with 68 additions and 9 deletions

View file

@ -1,3 +1,18 @@
2006-01-30 Andy Wingo <wingo@pobox.com>
* 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 <thomas at apestaart dot org>
* ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_start):

View file

@ -84,6 +84,7 @@ struct _GstTheoraEnc
guint64 bytes_out;
guint64 granulepos_offset;
guint64 timestamp_offset;
gint granule_shift;
};
struct _GstTheoraEncClass

View file

@ -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;

View file

@ -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);
}