mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +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>
|
2008-01-14 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct _GstTheoraDec
|
||||||
|
|
||||||
gboolean have_header;
|
gboolean have_header;
|
||||||
gboolean sent_newsegment;
|
gboolean sent_newsegment;
|
||||||
|
gboolean is_old_bitstream;
|
||||||
guint64 granulepos;
|
guint64 granulepos;
|
||||||
guint64 granule_shift;
|
guint64 granule_shift;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ struct _GstTheoraParse {
|
||||||
guint packetno;
|
guint packetno;
|
||||||
gboolean send_streamheader;
|
gboolean send_streamheader;
|
||||||
gboolean streamheader_received;
|
gboolean streamheader_received;
|
||||||
|
gboolean is_old_bitstream;
|
||||||
GstBuffer * streamheader[3];
|
GstBuffer * streamheader[3];
|
||||||
|
|
||||||
GQueue * event_queue;
|
GQueue * event_queue;
|
||||||
|
|
|
@ -51,15 +51,6 @@
|
||||||
#define GST_CAT_DEFAULT theoradec_debug
|
#define GST_CAT_DEFAULT theoradec_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
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
|
#define THEORA_DEF_CROP TRUE
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -150,8 +141,6 @@ gst_theora_dec_class_init (GstTheoraDecClass * klass)
|
||||||
gstelement_class->change_state = theora_dec_change_state;
|
gstelement_class->change_state = theora_dec_change_state;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
|
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
|
||||||
|
|
||||||
use_old_granulepos = (theora_version_number () <= 0x00030200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -242,7 +231,7 @@ _theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
|
||||||
framenum += granulepos - (framenum << ilog);
|
framenum += granulepos - (framenum << ilog);
|
||||||
|
|
||||||
/* This is 1-based for current libtheora, 0 based for old. Fix up. */
|
/* This is 1-based for current libtheora, 0 based for old. Fix up. */
|
||||||
if (!use_old_granulepos)
|
if (!dec->is_old_bitstream)
|
||||||
framenum -= 1;
|
framenum -= 1;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
|
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;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gboolean eret;
|
gboolean eret;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
guint32 bitstream_version;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
|
GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
|
||||||
dec->info.fps_numerator, dec->info.fps_denominator,
|
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);
|
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",
|
GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
|
||||||
dec->width, dec->height, dec->offset_x, dec->offset_y);
|
dec->width, dec->height, dec->offset_x, dec->offset_y);
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,7 @@ theora_parse_set_streamheader (GstTheoraParse * parse)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gint i;
|
gint i;
|
||||||
|
guint32 bitstream_version;
|
||||||
|
|
||||||
g_assert (!parse->streamheader_received);
|
g_assert (!parse->streamheader_received);
|
||||||
|
|
||||||
|
@ -341,6 +342,16 @@ theora_parse_set_streamheader (GstTheoraParse * parse)
|
||||||
parse->fps_d = parse->info.fps_denominator;
|
parse->fps_d = parse->info.fps_denominator;
|
||||||
parse->shift = _theora_ilog (parse->info.keyframe_frequency_force - 1);
|
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;
|
parse->streamheader_received = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,28 +402,36 @@ theora_parse_clear_queue (GstTheoraParse * parse)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint64
|
static gint64
|
||||||
make_granulepos (gint64 keyframe, gint64 frame, gint shift)
|
make_granulepos (GstTheoraParse * parse, gint64 keyframe, gint64 frame)
|
||||||
{
|
{
|
||||||
if (keyframe == -1)
|
if (keyframe == -1)
|
||||||
keyframe = 0;
|
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);
|
||||||
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
|
static void
|
||||||
parse_granulepos (gint64 granulepos, gint shift, gint64 * keyframe,
|
parse_granulepos (GstTheoraParse * parse, gint64 granulepos,
|
||||||
gint64 * frame)
|
gint64 * keyframe, gint64 * frame)
|
||||||
{
|
{
|
||||||
gint64 kf;
|
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)
|
if (keyframe)
|
||||||
*keyframe = kf;
|
*keyframe = kf;
|
||||||
if (frame)
|
if (frame)
|
||||||
*frame = kf + (granulepos & ((1 << shift) - 1));
|
*frame = kf + (granulepos & ((1 << parse->shift) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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),
|
next_time = gst_util_uint64_scale_int (GST_SECOND * (frame + 1),
|
||||||
parse->fps_d, parse->fps_n);
|
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_OFFSET (buf) = this_time;
|
||||||
GST_BUFFER_TIMESTAMP (buf) = this_time;
|
GST_BUFFER_TIMESTAMP (buf) = this_time;
|
||||||
GST_BUFFER_DURATION (buf) = next_time - 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 (parse->prev_keyframe < 0) {
|
||||||
if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
|
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);
|
&parse->prev_keyframe, NULL);
|
||||||
} else {
|
} else {
|
||||||
/* No previous keyframe known; can't extract one from this frame. That
|
/* 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;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gint64 keyframe, prev_frame, frame;
|
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);
|
prev_frame = frame - g_queue_get_length (parse->buffer_queue);
|
||||||
if (prev_frame < parse->prev_frame) {
|
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 (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
|
||||||
if (parse->prev_keyframe < 0) {
|
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);
|
&parse->prev_keyframe, NULL);
|
||||||
}
|
}
|
||||||
ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
|
ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
|
||||||
|
|
Loading…
Reference in a new issue