mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
ext/flac/gstflacdec.c: Only return true if we actually filled something in. Prevents player applications from showing...
Original commit message from CVS: * ext/flac/gstflacdec.c: (gst_flacdec_src_query): Only return true if we actually filled something in. Prevents player applications from showing a random length for flac files. * gst-libs/gst/riff/riff-read.c: (gst_riff_read_class_init), (gst_riff_read_use_event), (gst_riff_read_handle_event), (gst_riff_read_seek), (gst_riff_read_skip), (gst_riff_read_strh), (gst_riff_read_strf_vids_with_data), (gst_riff_read_strf_auds_with_data), (gst_riff_read_strf_iavs): OK, ok, so I implemented event handling. Apparently it's normal that we receive random events at random points without asking for it. * gst/avi/gstavidemux.c: (gst_avi_demux_reset), (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), (gst_avi_demux_handle_src_event), (gst_avi_demux_stream_index), (gst_avi_demux_sync), (gst_avi_demux_stream_scan), (gst_avi_demux_massage_index), (gst_avi_demux_stream_header), (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), (gst_avi_demux_stream_data), (gst_avi_demux_loop): * gst/avi/gstavidemux.h: Implement non-lineair chunk handling and subchunk processing. The first solves playback of AVI files where the audio and video data of individual buffers that we read are not synchronized. This should not happen according to the wonderful AVI specs, but of course it does happen in reality. It is also a prerequisite for the second. Subchunk processing allows us to cut chunks in small pieces and process each of these pieces separately. This is required because I've seen several AVI files with incredibly large audio chunks, even some files with only one audio chunk for the whole file. This allows for proper playback including seeking. This patch is supposed to fix all AVI A/V sync issues. * gst/flx/gstflxdec.c: (gst_flxdec_class_init), (flx_decode_chunks), (flx_decode_color), (gst_flxdec_loop): Work. * gst/modplug/gstmodplug.cc: Proper return value setting for the query() function. * gst/playback/gstplaybasebin.c: (setup_source): Being in non-playing state (after, e.g., EOS) is not necessarily a bad thing. Allow for that. This fixes playback of short files. They don't actually playback fully now, because the clock already runs. This means that small files (<500kB) with a small length (<2sec) will still not or barely play. Other files, such as mod or flx, will work correctly, however.
This commit is contained in:
parent
05a852a4d6
commit
2b6b70f42c
4 changed files with 149 additions and 72 deletions
45
ChangeLog
45
ChangeLog
|
@ -1,3 +1,48 @@
|
|||
2004-09-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* ext/flac/gstflacdec.c: (gst_flacdec_src_query):
|
||||
Only return true if we actually filled something in. Prevents
|
||||
player applications from showing a random length for flac files.
|
||||
* gst-libs/gst/riff/riff-read.c: (gst_riff_read_class_init),
|
||||
(gst_riff_read_use_event), (gst_riff_read_handle_event),
|
||||
(gst_riff_read_seek), (gst_riff_read_skip), (gst_riff_read_strh),
|
||||
(gst_riff_read_strf_vids_with_data),
|
||||
(gst_riff_read_strf_auds_with_data), (gst_riff_read_strf_iavs):
|
||||
OK, ok, so I implemented event handling. Apparently it's normal
|
||||
that we receive random events at random points without asking
|
||||
for it.
|
||||
* gst/avi/gstavidemux.c: (gst_avi_demux_reset),
|
||||
(gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query),
|
||||
(gst_avi_demux_handle_src_event), (gst_avi_demux_stream_index),
|
||||
(gst_avi_demux_sync), (gst_avi_demux_stream_scan),
|
||||
(gst_avi_demux_massage_index), (gst_avi_demux_stream_header),
|
||||
(gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry),
|
||||
(gst_avi_demux_stream_data), (gst_avi_demux_loop):
|
||||
* gst/avi/gstavidemux.h:
|
||||
Implement non-lineair chunk handling and subchunk processing.
|
||||
The first solves playback of AVI files where the audio and video
|
||||
data of individual buffers that we read are not synchronized.
|
||||
This should not happen according to the wonderful AVI specs, but
|
||||
of course it does happen in reality. It is also a prerequisite for
|
||||
the second. Subchunk processing allows us to cut chunks in small
|
||||
pieces and process each of these pieces separately. This is
|
||||
required because I've seen several AVI files with incredibly large
|
||||
audio chunks, even some files with only one audio chunk for the
|
||||
whole file. This allows for proper playback including seeking.
|
||||
This patch is supposed to fix all AVI A/V sync issues.
|
||||
* gst/flx/gstflxdec.c: (gst_flxdec_class_init),
|
||||
(flx_decode_chunks), (flx_decode_color), (gst_flxdec_loop):
|
||||
Work.
|
||||
* gst/modplug/gstmodplug.cc:
|
||||
Proper return value setting for the query() function.
|
||||
* gst/playback/gstplaybasebin.c: (setup_source):
|
||||
Being in non-playing state (after, e.g., EOS) is not necessarily
|
||||
a bad thing. Allow for that. This fixes playback of short files.
|
||||
They don't actually playback fully now, because the clock already
|
||||
runs. This means that small files (<500kB) with a small length
|
||||
(<2sec) will still not or barely play. Other files, such as mod
|
||||
or flx, will work correctly, however.
|
||||
|
||||
2004-09-28 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/speex/gstspeex.c: (plugin_init):
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include "riff-ids.h"
|
||||
#include "riff-read.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (riffread_debug);
|
||||
#define GST_CAT_DEFAULT riffread_debug
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
|
@ -76,6 +79,9 @@ gst_riff_read_class_init (GstRiffReadClass * klass)
|
|||
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (riffread_debug, "riffread",
|
||||
0, "RIFF stream helper class");
|
||||
|
||||
gstelement_class->change_state = gst_riff_read_change_state;
|
||||
}
|
||||
|
||||
|
@ -145,6 +151,64 @@ gst_riff_read_element_level_up (GstRiffRead * riff)
|
|||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event handler. Basic:
|
||||
* - EOS: end-of-file, stop processing, forward EOS.
|
||||
* - Interrupt: stop processing.
|
||||
* - Discont: shouldn't be handled here but in the seek handler. Error.
|
||||
* - Flush: ignore, since we check for flush flags manually. Don't forward.
|
||||
* - Others: warn, ignore.
|
||||
* Return value indicates whether to continue processing.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
gst_riff_read_use_event (GstRiffRead * riff, GstEvent * event)
|
||||
{
|
||||
if (!event) {
|
||||
GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
return FALSE;
|
||||
|
||||
case GST_EVENT_INTERRUPT:
|
||||
gst_event_unref (event);
|
||||
return FALSE;
|
||||
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
GST_WARNING_OBJECT (riff, "Unexected discont - might lose sync");
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
return TRUE;
|
||||
|
||||
case GST_EVENT_FLUSH:
|
||||
gst_event_unref (event);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
GST_WARNING ("don't know how to handle event %d", GST_EVENT_TYPE (event));
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* happy */
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_riff_read_handle_event (GstRiffRead * riff)
|
||||
{
|
||||
GstEvent *event = NULL;
|
||||
guint32 remaining;
|
||||
|
||||
gst_bytestream_get_status (riff->bs, &remaining, &event);
|
||||
|
||||
return gst_riff_read_use_event (riff, event);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the next tag plus length (may be NULL). Return
|
||||
* TRUE on success or FALSE on failure.
|
||||
|
@ -174,21 +238,8 @@ gst_riff_peek_head (GstRiffRead * riff,
|
|||
|
||||
/* read */
|
||||
while (gst_bytestream_peek_bytes (riff->bs, &data, 8) != 8) {
|
||||
GstEvent *event = NULL;
|
||||
guint32 remaining;
|
||||
|
||||
/* Here, we might encounter EOS */
|
||||
gst_bytestream_get_status (riff->bs, &remaining, &event);
|
||||
if (event && GST_IS_EVENT (event)) {
|
||||
gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
|
||||
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
if (eos)
|
||||
if (!gst_riff_read_handle_event (riff))
|
||||
return FALSE;
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse tag + length (if wanted) */
|
||||
|
@ -215,34 +266,11 @@ gst_riff_read_element_data (GstRiffRead * riff, guint length, guint * got_bytes)
|
|||
guint32 got;
|
||||
|
||||
while ((got = gst_bytestream_peek (riff->bs, &buf, length)) != length) {
|
||||
/*GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL)); */
|
||||
GstEvent *event = NULL;
|
||||
guint32 remaining;
|
||||
|
||||
gst_bytestream_get_status (riff->bs, &remaining, &event);
|
||||
if (event && GST_IS_EVENT (event)) {
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||
|
||||
if (buf)
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
if (got_bytes)
|
||||
*got_bytes = got;
|
||||
|
||||
if (!gst_riff_read_handle_event (riff))
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL));
|
||||
if (buf)
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
if (got_bytes)
|
||||
*got_bytes = got;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need 16-bit alignment */
|
||||
if (length & 1)
|
||||
|
@ -275,7 +303,9 @@ gst_riff_read_seek (GstRiffRead * riff, guint64 offset)
|
|||
/* first, flush remaining buffers */
|
||||
gst_bytestream_get_status (riff->bs, &remaining, &event);
|
||||
if (event) {
|
||||
g_warning ("Unexpected event before seek");
|
||||
GST_WARNING ("Unexpected event before seek");
|
||||
if (!gst_riff_read_use_event (riff, event))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (remaining)
|
||||
|
@ -301,10 +331,7 @@ gst_riff_read_seek (GstRiffRead * riff, guint64 offset)
|
|||
GST_WARNING ("No discontinuity event after seek - seek failed");
|
||||
break;
|
||||
} else if (GST_EVENT_TYPE (event) != GST_EVENT_DISCONTINUOUS) {
|
||||
GstEventType type = GST_EVENT_TYPE (event);
|
||||
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
if (type == GST_EVENT_EOS || type == GST_EVENT_INTERRUPT)
|
||||
if (!gst_riff_read_use_event (riff, event))
|
||||
return NULL;
|
||||
event = NULL;
|
||||
}
|
||||
|
@ -361,7 +388,7 @@ gboolean
|
|||
gst_riff_read_skip (GstRiffRead * riff)
|
||||
{
|
||||
guint32 tag, length;
|
||||
GstEvent *event;
|
||||
GstEvent *event = NULL;
|
||||
guint32 remaining;
|
||||
|
||||
if (!gst_riff_peek_head (riff, &tag, &length, NULL))
|
||||
|
@ -376,12 +403,9 @@ gst_riff_read_skip (GstRiffRead * riff)
|
|||
|
||||
/* see if we have that much data available */
|
||||
gst_bytestream_get_status (riff->bs, &remaining, &event);
|
||||
if (event && GST_IS_EVENT (event)) {
|
||||
gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
|
||||
|
||||
g_warning ("Unexpected event in skip");
|
||||
gst_pad_event_default (riff->sinkpad, event);
|
||||
if (eos)
|
||||
if (event) {
|
||||
GST_WARNING ("Unexpected event in skip");
|
||||
if (!gst_riff_read_use_event (riff, event))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -458,7 +482,7 @@ gst_riff_read_strh (GstRiffRead * riff, gst_riff_strh ** header)
|
|||
return FALSE;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strh)) {
|
||||
g_warning ("Too small strh (%d available, %d needed)",
|
||||
GST_WARNING ("Too small strh (%d available, %d needed)",
|
||||
GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strh));
|
||||
gst_buffer_unref (buf);
|
||||
return FALSE;
|
||||
|
@ -526,7 +550,7 @@ gst_riff_read_strf_vids_with_data (GstRiffRead * riff,
|
|||
return FALSE;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_vids)) {
|
||||
g_warning ("Too small strf_vids (%d available, %d needed)",
|
||||
GST_WARNING ("Too small strf_vids (%d available, %d needed)",
|
||||
GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_vids));
|
||||
gst_buffer_unref (buf);
|
||||
return FALSE;
|
||||
|
@ -620,7 +644,7 @@ gst_riff_read_strf_auds_with_data (GstRiffRead * riff,
|
|||
return FALSE;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_auds)) {
|
||||
g_warning ("Too small strf_auds (%d available, %d needed)",
|
||||
GST_WARNING ("Too small strf_auds (%d available, %d needed)",
|
||||
GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_auds));
|
||||
gst_buffer_unref (buf);
|
||||
return FALSE;
|
||||
|
@ -702,7 +726,7 @@ gst_riff_read_strf_iavs (GstRiffRead * riff, gst_riff_strf_iavs ** header)
|
|||
return FALSE;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_iavs)) {
|
||||
g_warning ("Too small strf_iavs (%d available, %d needed)",
|
||||
GST_WARNING ("Too small strf_iavs (%d available, %d needed)",
|
||||
GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_iavs));
|
||||
gst_buffer_unref (buf);
|
||||
return FALSE;
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#define JIFFIE (GST_SECOND/70)
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (flxdec_debug);
|
||||
#define GST_CAT_DEFAULT flxdec_debug
|
||||
|
||||
/* flx element information */
|
||||
static GstElementDetails flxdec_details = {
|
||||
"FLX Decoder",
|
||||
|
@ -133,6 +136,8 @@ gst_flxdec_class_init (GstFlxDecClass * klass)
|
|||
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (flxdec_debug, "flxdec", 0, "FLX video decoder");
|
||||
|
||||
gobject_class->set_property = gst_flxdec_set_property;
|
||||
gobject_class->get_property = gst_flxdec_get_property;
|
||||
|
||||
|
@ -206,9 +211,8 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, gchar * data, gchar * dest)
|
|||
break;
|
||||
|
||||
default:
|
||||
g_print ("GstFlxDec: Unimplented chunk type: 0x%02x size: %d\n",
|
||||
GST_WARNING ("Unimplented chunk type: 0x%02x size: %d - skipping",
|
||||
hdr->id, hdr->size);
|
||||
g_print ("GstFlxDec: Skipping...\n");
|
||||
data += rndalign (hdr->size) - FlxFrameChunkSize;
|
||||
break;
|
||||
}
|
||||
|
@ -228,7 +232,7 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
|
|||
data += 2;
|
||||
indx = 0;
|
||||
|
||||
g_print ("GstFlxDec: cmap packs: %d\n", packs);
|
||||
GST_LOG ("GstFlxDec: cmap packs: %d", packs);
|
||||
while (packs--) {
|
||||
/* color map index + skip count */
|
||||
indx += *data++;
|
||||
|
@ -238,7 +242,7 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
|
|||
if (count == 0)
|
||||
count = 256;
|
||||
|
||||
g_print ("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx);
|
||||
GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx);
|
||||
flx_set_palette_vector (flxdec->converter, indx, count, data, scale);
|
||||
|
||||
data += (count * 3);
|
||||
|
@ -449,7 +453,7 @@ gst_flxdec_loop (GstElement * element)
|
|||
databuf = flx_get_data (flxdec, FlxHeaderSize);
|
||||
|
||||
if (!databuf) {
|
||||
g_print ("empty buffer\n");
|
||||
GST_LOG ("empty buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -470,12 +474,12 @@ gst_flxdec_loop (GstElement * element)
|
|||
}
|
||||
|
||||
|
||||
g_print ("GstFlxDec: size : %d\n", flxh->size);
|
||||
g_print ("GstFlxDec: frames : %d\n", flxh->frames);
|
||||
g_print ("GstFlxDec: width : %d\n", flxh->width);
|
||||
g_print ("GstFlxDec: height : %d\n", flxh->height);
|
||||
g_print ("GstFlxDec: depth : %d\n", flxh->depth);
|
||||
g_print ("GstFlxDec: speed : %d\n", flxh->speed);
|
||||
GST_LOG ("size : %d\n", flxh->size);
|
||||
GST_LOG ("frames : %d\n", flxh->frames);
|
||||
GST_LOG ("width : %d\n", flxh->width);
|
||||
GST_LOG ("height : %d\n", flxh->height);
|
||||
GST_LOG ("depth : %d\n", flxh->depth);
|
||||
GST_LOG ("speed : %d\n", flxh->speed);
|
||||
|
||||
flxdec->next_time = 0;
|
||||
|
||||
|
@ -496,10 +500,10 @@ gst_flxdec_loop (GstElement * element)
|
|||
flx_colorspace_converter_new (flxh->width, flxh->height);
|
||||
|
||||
if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
|
||||
g_print ("GstFlxDec: (FLC) aspect_dx : %d\n", flxh->aspect_dx);
|
||||
g_print ("GstFlxDec: (FLC) aspect_dy : %d\n", flxh->aspect_dy);
|
||||
g_print ("GstFlxDec: (FLC) oframe1 : 0x%08x\n", flxh->oframe1);
|
||||
g_print ("GstFlxDec: (FLC) oframe2 : 0x%08x\n", flxh->oframe2);
|
||||
GST_LOG ("(FLC) aspect_dx : %d\n", flxh->aspect_dx);
|
||||
GST_LOG ("(FLC) aspect_dy : %d\n", flxh->aspect_dy);
|
||||
GST_LOG ("(FLC) oframe1 : 0x%08x\n", flxh->oframe1);
|
||||
GST_LOG ("(FLC) oframe2 : 0x%08x\n", flxh->oframe2);
|
||||
}
|
||||
|
||||
flxdec->size = (flxh->width * flxh->height);
|
||||
|
|
|
@ -346,15 +346,19 @@ gst_modplug_src_query (GstPad * pad, GstQueryType type,
|
|||
break;
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
default:
|
||||
case GST_FORMAT_TIME:
|
||||
tmp =
|
||||
((float) (modplug->mSoundFile->GetSongTime () *
|
||||
modplug->mSoundFile->GetCurrentPos ()) /
|
||||
(float) modplug->mSoundFile->GetMaxPosition ());
|
||||
*value = (gint64) (tmp * GST_SECOND);
|
||||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue