mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
ext/theora/: Take a 2nd stab at handling libtheora granulepos changes in the decoder and parser by inspecting the bit...
Original commit message from CVS: * ext/theora/gsttheoradec.h: * ext/theora/gsttheoraparse.h: * ext/theora/theoradec.c: * ext/theora/theoraparse.c: Take a 2nd stab at handling libtheora granulepos changes in the decoder and parser by inspecting the bitstream version of the incoming data.
This commit is contained in:
parent
3809775d31
commit
7ff360cea9
5 changed files with 53 additions and 23 deletions
|
@ -1,3 +1,12 @@
|
|||
2008-01-14 Jan Schmidt <jan.schmidt@sun.com>
|
||||
|
||||
* ext/theora/gsttheoradec.h:
|
||||
* ext/theora/gsttheoraparse.h:
|
||||
* ext/theora/theoradec.c:
|
||||
* ext/theora/theoraparse.c:
|
||||
Take a 2nd stab at handling libtheora granulepos changes in the decoder
|
||||
and parser by inspecting the bitstream version of the incoming data.
|
||||
|
||||
2008-01-14 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
* configure.ac:
|
||||
|
|
|
@ -64,6 +64,7 @@ struct _GstTheoraDec
|
|||
|
||||
gboolean have_header;
|
||||
gboolean sent_newsegment;
|
||||
gboolean is_old_bitstream;
|
||||
guint64 granulepos;
|
||||
guint64 granule_shift;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ struct _GstTheoraParse {
|
|||
guint packetno;
|
||||
gboolean send_streamheader;
|
||||
gboolean streamheader_received;
|
||||
gboolean is_old_bitstream;
|
||||
GstBuffer * streamheader[3];
|
||||
|
||||
GQueue * event_queue;
|
||||
|
|
|
@ -51,15 +51,6 @@
|
|||
#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
|
||||
{
|
||||
|
@ -150,8 +141,6 @@ 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
|
||||
|
@ -242,7 +231,7 @@ _theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
|
|||
framenum += granulepos - (framenum << ilog);
|
||||
|
||||
/* This is 1-based for current libtheora, 0 based for old. Fix up. */
|
||||
if (!use_old_granulepos)
|
||||
if (!dec->is_old_bitstream)
|
||||
framenum -= 1;
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
|
||||
|
@ -791,6 +780,7 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gboolean eret;
|
||||
GstEvent *event;
|
||||
guint32 bitstream_version;
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
|
||||
dec->info.fps_numerator, dec->info.fps_denominator,
|
||||
|
@ -841,6 +831,16 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||
|
||||
dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);
|
||||
|
||||
/* 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. We check the bitstream version from the header so
|
||||
* we know which way to interpret the incoming granuepos
|
||||
*/
|
||||
bitstream_version = (dec->info.version_major << 16) |
|
||||
(dec->info.version_minor << 8) | dec->info.version_subminor;
|
||||
dec->is_old_bitstream = (bitstream_version <= 0x00030200);
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
|
||||
dec->width, dec->height, dec->offset_x, dec->offset_y);
|
||||
|
||||
|
|
|
@ -313,6 +313,7 @@ theora_parse_set_streamheader (GstTheoraParse * parse)
|
|||
{
|
||||
GstCaps *caps;
|
||||
gint i;
|
||||
guint32 bitstream_version;
|
||||
|
||||
g_assert (!parse->streamheader_received);
|
||||
|
||||
|
@ -341,6 +342,16 @@ theora_parse_set_streamheader (GstTheoraParse * parse)
|
|||
parse->fps_d = parse->info.fps_denominator;
|
||||
parse->shift = _theora_ilog (parse->info.keyframe_frequency_force - 1);
|
||||
|
||||
/* 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. We check the bitstream version from the header so
|
||||
* we know which way to interpret the incoming granuepos
|
||||
*/
|
||||
bitstream_version = (parse->info.version_major << 16) |
|
||||
(parse->info.version_minor << 8) | parse->info.version_subminor;
|
||||
parse->is_old_bitstream = (bitstream_version <= 0x00030200);
|
||||
|
||||
parse->streamheader_received = TRUE;
|
||||
}
|
||||
|
||||
|
@ -391,28 +402,36 @@ theora_parse_clear_queue (GstTheoraParse * parse)
|
|||
}
|
||||
|
||||
static gint64
|
||||
make_granulepos (gint64 keyframe, gint64 frame, gint shift)
|
||||
make_granulepos (GstTheoraParse * parse, gint64 keyframe, gint64 frame)
|
||||
{
|
||||
if (keyframe == -1)
|
||||
keyframe = 0;
|
||||
/* If using newer theora, offset the granulepos by +1, see comment
|
||||
* in theora_parse_set_streamheader */
|
||||
if (!parse->is_old_bitstream)
|
||||
keyframe += 1;
|
||||
|
||||
g_return_val_if_fail (frame >= keyframe, -1);
|
||||
g_return_val_if_fail (frame - keyframe < 1 << shift, -1);
|
||||
g_return_val_if_fail (frame - keyframe < 1 << parse->shift, -1);
|
||||
|
||||
return (keyframe << shift) + (frame - keyframe);
|
||||
return (keyframe << parse->shift) + (frame - keyframe);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_granulepos (gint64 granulepos, gint shift, gint64 * keyframe,
|
||||
gint64 * frame)
|
||||
parse_granulepos (GstTheoraParse * parse, gint64 granulepos,
|
||||
gint64 * keyframe, gint64 * frame)
|
||||
{
|
||||
gint64 kf;
|
||||
|
||||
kf = granulepos >> shift;
|
||||
kf = granulepos >> parse->shift;
|
||||
/* If using newer theora, offset the granulepos by -1, see comment
|
||||
* in theora_parse_set_streamheader */
|
||||
if (!parse->is_old_bitstream)
|
||||
kf -= 1;
|
||||
if (keyframe)
|
||||
*keyframe = kf;
|
||||
if (frame)
|
||||
*frame = kf + (granulepos & ((1 << shift) - 1));
|
||||
*frame = kf + (granulepos & ((1 << parse->shift) - 1));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -474,7 +493,7 @@ theora_parse_push_buffer (GstTheoraParse * parse, GstBuffer * buf,
|
|||
next_time = gst_util_uint64_scale_int (GST_SECOND * (frame + 1),
|
||||
parse->fps_d, parse->fps_n);
|
||||
|
||||
GST_BUFFER_OFFSET_END (buf) = make_granulepos (keyframe, frame, parse->shift);
|
||||
GST_BUFFER_OFFSET_END (buf) = make_granulepos (parse, keyframe, frame);
|
||||
GST_BUFFER_OFFSET (buf) = this_time;
|
||||
GST_BUFFER_TIMESTAMP (buf) = this_time;
|
||||
GST_BUFFER_DURATION (buf) = next_time - this_time;
|
||||
|
@ -521,7 +540,7 @@ theora_parse_drain_queue_prematurely (GstTheoraParse * parse)
|
|||
|
||||
if (parse->prev_keyframe < 0) {
|
||||
if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
|
||||
parse_granulepos (GST_BUFFER_OFFSET_END (buf), parse->shift,
|
||||
parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
|
||||
&parse->prev_keyframe, NULL);
|
||||
} else {
|
||||
/* No previous keyframe known; can't extract one from this frame. That
|
||||
|
@ -550,7 +569,7 @@ theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos)
|
|||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gint64 keyframe, prev_frame, frame;
|
||||
|
||||
parse_granulepos (granulepos, parse->shift, &keyframe, &frame);
|
||||
parse_granulepos (parse, granulepos, &keyframe, &frame);
|
||||
|
||||
prev_frame = frame - g_queue_get_length (parse->buffer_queue);
|
||||
if (prev_frame < parse->prev_frame) {
|
||||
|
@ -606,7 +625,7 @@ theora_parse_queue_buffer (GstTheoraParse * parse, GstBuffer * buf)
|
|||
|
||||
if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
|
||||
if (parse->prev_keyframe < 0) {
|
||||
parse_granulepos (GST_BUFFER_OFFSET_END (buf), parse->shift,
|
||||
parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
|
||||
&parse->prev_keyframe, NULL);
|
||||
}
|
||||
ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
|
||||
|
|
Loading…
Reference in a new issue