ext/theora/theoradec.c: Adapt for post-alpha meaning of granulepos, when we have a newer version of libtheora.

Original commit message from CVS:
* ext/theora/theoradec.c: (gst_theora_dec_class_init),
(_theora_granule_frame), (_theora_granule_start_time),
(theora_dec_sink_convert), (theora_dec_decode_buffer):
Adapt for post-alpha meaning of granulepos, when we
have a newer version of libtheora.
* ext/theora/theoraenc.c: (gst_theora_enc_class_init),
(theora_enc_get_ogg_packet_end_time), (theora_enc_sink_event),
(theora_enc_is_discontinuous), (theora_enc_chain):
Likewise.
* tests/check/Makefile.am:
Link libtheora into theoraenc test so we can check which version of
libtheora we're testing against.
* tests/check/pipelines/theoraenc.c: (check_libtheora),
(check_buffer_granulepos),
(check_buffer_granulepos_from_starttime), (GST_START_TEST),
(theoraenc_suite):
Adapt tests to check the values that are now defined for theora; make
the tests backwards-adapt the passed values if we're running against an
old libtheora.
Fixes #497964
This commit is contained in:
Michael Smith 2008-01-11 15:48:11 +00:00
parent 3feb4bc8c5
commit 57fab036b1
6 changed files with 125 additions and 29 deletions

View file

@ -1,3 +1,26 @@
2008-01-11 Michael Smith <msmith@fluendo.com>
* ext/theora/theoradec.c: (gst_theora_dec_class_init),
(_theora_granule_frame), (_theora_granule_start_time),
(theora_dec_sink_convert), (theora_dec_decode_buffer):
Adapt for post-alpha meaning of granulepos, when we
have a newer version of libtheora.
* ext/theora/theoraenc.c: (gst_theora_enc_class_init),
(theora_enc_get_ogg_packet_end_time), (theora_enc_sink_event),
(theora_enc_is_discontinuous), (theora_enc_chain):
Likewise.
* tests/check/Makefile.am:
Link libtheora into theoraenc test so we can check which version of
libtheora we're testing against.
* tests/check/pipelines/theoraenc.c: (check_libtheora),
(check_buffer_granulepos),
(check_buffer_granulepos_from_starttime), (GST_START_TEST),
(theoraenc_suite):
Adapt tests to check the values that are now defined for theora; make
the tests backwards-adapt the passed values if we're running against an
old libtheora.
Fixes #497964
2008-01-10 Tim-Philipp Müller <tim at centricular dot net>
* gst-libs/gst/audio/gstbaseaudiosink.c:

2
common

@ -1 +1 @@
Subproject commit 49c2fc5c9bff0e9858e89978bd98164a386de51d
Subproject commit bd02d788384b40ff511cac0e32aa77f51a68912d

View file

@ -51,6 +51,15 @@
#define GST_CAT_DEFAULT theoradec_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
/* With libtheora-1.0beta1 the granulepos scheme was changed:
* where earlier the granulepos refered to the index/beginning
* of a frame, it now refers to the end, which matches the use
* in vorbis/speex. There don't seem to be defines for the
* theora version we're compiling against, so we'll just use
* a run-time check for now. See theora_enc_get_ogg_packet_end_time().
*/
static gboolean use_old_granulepos;
#define THEORA_DEF_CROP TRUE
enum
{
@ -141,6 +150,8 @@ gst_theora_dec_class_init (GstTheoraDecClass * klass)
gstelement_class->change_state = theora_dec_change_state;
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
use_old_granulepos = (theora_version_number () <= 0x00030200);
}
static void
@ -212,11 +223,13 @@ _theora_ilog (unsigned int v)
return (ret);
}
/* Return the frame number (starting from zero) corresponding to this
* granulepos */
static gint64
_theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
{
guint ilog;
gint framecount;
gint framenum;
if (granulepos == -1)
return -1;
@ -225,16 +238,21 @@ _theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
/* granulepos is last ilog bits for counting pframes since last iframe and
* bits in front of that for the framenumber of the last iframe. */
framecount = granulepos >> ilog;
framecount += granulepos - (framecount << ilog);
framenum = granulepos >> ilog;
framenum += granulepos - (framenum << ilog);
GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framecount, ilog);
/* This is 1-based for current libtheora, 0 based for old. Fix up. */
if (!use_old_granulepos)
framenum -= 1;
return framecount;
GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
return framenum;
}
/* Return the frame start time corresponding to this granulepos */
static GstClockTime
_theora_granule_time (GstTheoraDec * dec, gint64 granulepos)
_theora_granule_start_time (GstTheoraDec * dec, gint64 granulepos)
{
gint64 framecount;
@ -407,7 +425,7 @@ theora_dec_sink_convert (GstPad * pad,
case GST_FORMAT_DEFAULT:
switch (*dest_format) {
case GST_FORMAT_TIME:
*dest_value = _theora_granule_time (dec, src_value);
*dest_value = _theora_granule_start_time (dec, src_value);
break;
default:
res = FALSE;
@ -1224,9 +1242,9 @@ theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf)
if (dec->have_header) {
if (packet.granulepos != -1) {
dec->granulepos = packet.granulepos;
dec->last_timestamp = _theora_granule_time (dec, packet.granulepos);
dec->last_timestamp = _theora_granule_start_time (dec, packet.granulepos);
} else if (dec->last_timestamp != -1) {
dec->last_timestamp = _theora_granule_time (dec, dec->granulepos);
dec->last_timestamp = _theora_granule_start_time (dec, dec->granulepos);
}
if (dec->last_timestamp == -1 && GST_BUFFER_TIMESTAMP_IS_VALID (buf))
dec->last_timestamp = GST_BUFFER_TIMESTAMP (buf);

View file

@ -69,6 +69,15 @@
#define GST_CAT_DEFAULT theoraenc_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
/* With libtheora-1.0beta1 the granulepos scheme was changed:
* where earlier the granulepos refered to the index/beginning
* of a frame, it now refers to the end, which matches the use
* in vorbis/speex. There don't seem to be defines for the
* theora version we're compiling against, so we'll just use
* a run-time check for now. See theora_enc_get_ogg_packet_end_time().
*/
static gboolean use_old_granulepos;
#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
static GType
gst_border_mode_get_type (void)
@ -258,6 +267,8 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
gstelement_class->change_state = theora_enc_change_state;
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
use_old_granulepos = (theora_version_number () <= 0x00030200);
}
static void
@ -540,6 +551,25 @@ theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
return caps;
}
static GstClockTime
theora_enc_get_ogg_packet_end_time (GstTheoraEnc * enc, ogg_packet * op)
{
ogg_int64_t end_granule;
/* FIXME: remove this hack once we depend on libtheora >= 1.0beta1 */
if (G_UNLIKELY (use_old_granulepos)) {
/* This is where we hack around theora's broken idea of what granulepos
* is -- normally we wouldn't need to add the 1, because granulepos
* should be the presentation time of the last sample in the packet, but
* theora starts with 0 instead of 1... (update: this only applies to old
* bitstream/theora versions, this is fixed with bitstream version 3.2.1) */
end_granule = granulepos_add (op->granulepos, 1, enc->granule_shift);
} else {
end_granule = op->granulepos;
}
return theora_granule_time (&enc->state, end_granule) * GST_SECOND;
}
static gboolean
theora_enc_sink_event (GstPad * pad, GstEvent * event)
{
@ -554,10 +584,8 @@ theora_enc_sink_event (GstPad * pad, GstEvent * event)
if (enc->initialised) {
/* 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,
granulepos_add (op.granulepos, 1, enc->granule_shift)) *
GST_SECOND;
GstClockTime next_time =
theora_enc_get_ogg_packet_end_time (enc, &op);
theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
enc->next_ts = next_time;
@ -574,7 +602,7 @@ theora_enc_sink_event (GstPad * pad, GstEvent * event)
if (gst_structure_has_name (s, "GstForceKeyUnit")) {
GstClockTime next_ts;
/* make sure timestamps increment after reseting the decoder */
/* make sure timestamps increment after resetting the decoder */
next_ts = enc->next_ts + enc->timestamp_offset;
theora_enc_reset (enc);
@ -887,14 +915,8 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
ret = GST_FLOW_OK;
while (theora_encode_packetout (&enc->state, 0, &op)) {
/* This is where we hack around theora's broken idea of what granulepos
is -- normally we wouldn't need to add the 1, because granulepos
should be the presentation time of the last sample in the packet, but
theora starts with 0 instead of 1... */
GstClockTime next_time;
GstClockTime next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
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

@ -288,6 +288,9 @@ pipelines_vorbisdec_CFLAGS = $(AM_CFLAGS)
pipelines_oggmux_LDADD = $(LDADD) $(OGG_LIBS)
pipelines_oggmux_CFLAGS = $(AM_CFLAGS) $(OGG_CFLAGS)
pipelines_theoraenc_CFLAGS = $(GST_CFLAGS) $(THEORA_CFLAGS)
pipelines_theoraenc_LDADD = $(LDADD) $(THEORA_LIBS)
pipelines_simple_launch_lines_CFLAGS = \
$(GST_BASE_CFLAGS) \
$(AM_CFLAGS)

View file

@ -23,6 +23,8 @@
#include <gst/check/gstcheck.h>
#include <gst/check/gstbufferstraw.h>
#include <theora/theora.h>
#ifndef GST_DISABLE_PARSE
#define TIMESTAMP_OFFSET G_GINT64_CONSTANT(3249870963)
@ -50,12 +52,29 @@
", but got duration %" GST_TIME_FORMAT, \
GST_TIME_ARGS (duration), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)))
static gboolean old_libtheora;
static void
check_libtheora (void)
{
old_libtheora = (theora_version_number () <= 0x00030200);
}
static void
check_buffer_granulepos (GstBuffer * buffer, gint64 granulepos)
{
GstClockTime clocktime;
int framecount;
/* With old versions of libtheora, the granulepos represented the
* start time, not end time. Adapt for that. */
if (old_libtheora) {
if (granulepos >> GRANULEPOS_SHIFT)
granulepos -= 1 << GRANULEPOS_SHIFT;
else if (granulepos)
granulepos -= 1;
}
fail_unless (GST_BUFFER_OFFSET_END (buffer) == granulepos,
"expected granulepos %" G_GUINT64_FORMAT
", but got granulepos %" G_GUINT64_FORMAT,
@ -87,6 +106,15 @@ check_buffer_granulepos_from_starttime (GstBuffer * buffer,
gint64 granulepos, expected, framecount;
granulepos = GST_BUFFER_OFFSET_END (buffer);
/* Now convert to 'granulepos for start time', depending on libtheora
* version */
if (!old_libtheora) {
if (granulepos & ((1 << GRANULEPOS_SHIFT) - 1))
granulepos -= 1;
else if (granulepos)
granulepos -= 1 << GRANULEPOS_SHIFT;
}
framecount = granulepos >> GRANULEPOS_SHIFT;
framecount += granulepos & ((1 << GRANULEPOS_SHIFT) - 1);
expected = gst_util_uint64_scale (starttime, FRAMERATE, GST_SECOND);
@ -95,7 +123,7 @@ check_buffer_granulepos_from_starttime (GstBuffer * buffer,
"expected frame count %" G_GUINT64_FORMAT
" or %" G_GUINT64_FORMAT
", but got frame count %" G_GUINT64_FORMAT,
expected, expected + 1, granulepos);
expected, expected + 1, framecount);
}
GST_START_TEST (test_granulepos_offset)
@ -257,7 +285,7 @@ GST_START_TEST (test_continuity)
check_buffer_timestamp (buffer, 0);
/* plain division because I know the answer is exact */
check_buffer_duration (buffer, GST_SECOND / 10);
check_buffer_granulepos (buffer, 0);
check_buffer_granulepos (buffer, 1 << GRANULEPOS_SHIFT);
check_buffer_is_header (buffer, FALSE);
next_timestamp = GST_BUFFER_DURATION (buffer);
@ -268,7 +296,7 @@ GST_START_TEST (test_continuity)
buffer = gst_buffer_straw_get_buffer (bin, pad);
check_buffer_timestamp (buffer, next_timestamp);
check_buffer_duration (buffer, GST_SECOND / 10);
check_buffer_granulepos (buffer, 1);
check_buffer_granulepos (buffer, (1 << GRANULEPOS_SHIFT) | 1);
check_buffer_is_header (buffer, FALSE);
gst_buffer_unref (buffer);
@ -360,7 +388,7 @@ GST_START_TEST (test_discontinuity)
check_buffer_timestamp (buffer, 0);
/* plain division because I know the answer is exact */
check_buffer_duration (buffer, GST_SECOND / 10);
check_buffer_granulepos (buffer, 0);
check_buffer_granulepos (buffer, 1 << GRANULEPOS_SHIFT);
check_buffer_is_header (buffer, FALSE);
fail_if (GST_BUFFER_IS_DISCONT (buffer), "expected continuous buffer yo");
gst_buffer_unref (buffer);
@ -369,8 +397,8 @@ GST_START_TEST (test_discontinuity)
buffer = gst_buffer_straw_get_buffer (bin, pad);
check_buffer_duration (buffer, GST_SECOND / 10);
/* After a discont, we'll always get a keyframe, so this one should be
* 2<<GRANULEPOS_SHIFT */
check_buffer_granulepos (buffer, 2 << GRANULEPOS_SHIFT);
* 3<<GRANULEPOS_SHIFT */
check_buffer_granulepos (buffer, 3 << GRANULEPOS_SHIFT);
check_buffer_is_header (buffer, FALSE);
fail_unless (GST_BUFFER_IS_DISCONT (buffer),
"expected discontinuous buffer yo");
@ -381,7 +409,7 @@ GST_START_TEST (test_discontinuity)
fail_if (GST_BUFFER_IS_DISCONT (buffer), "expected continuous buffer yo");
/* plain division because I know the answer is exact */
check_buffer_duration (buffer, GST_SECOND / 10);
check_buffer_granulepos (buffer, (2 << GRANULEPOS_SHIFT) + 1);
check_buffer_granulepos (buffer, (3 << GRANULEPOS_SHIFT) | 1);
check_buffer_is_header (buffer, FALSE);
gst_buffer_unref (buffer);
}
@ -406,6 +434,8 @@ theoraenc_suite (void)
suite_add_tcase (s, tc_chain);
check_libtheora ();
#ifndef GST_DISABLE_PARSE
tcase_add_test (tc_chain, test_granulepos_offset);
tcase_add_test (tc_chain, test_continuity);