mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
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:
parent
3feb4bc8c5
commit
57fab036b1
6 changed files with 125 additions and 29 deletions
23
ChangeLog
23
ChangeLog
|
@ -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
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 49c2fc5c9bff0e9858e89978bd98164a386de51d
|
||||
Subproject commit bd02d788384b40ff511cac0e32aa77f51a68912d
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue