From: Wim Taymans Date: Sun, 3 Feb 2002 20:10:04 +0000 (+0000) Subject: Assorted fixes. X-Git-Tag: BRANCH-EVENTS2-ROOT~104 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=98ffdface2db429656b2f7b8f3cc5a301d498d75;p=platform%2Fupstream%2Fgst-plugins-good.git Assorted fixes. Original commit message from CVS: Assorted fixes. Use the new clocking stuff. --- diff --git a/configure.ac b/configure.ac index 91be69f..1c183b1 100644 --- a/configure.ac +++ b/configure.ac @@ -763,6 +763,7 @@ gst/chart/Makefile gst/cutter/Makefile gst/deinterlace/Makefile gst/flx/Makefile +gst/goom/Makefile gst/intfloat/Makefile gst/law/Makefile gst/level/Makefile @@ -835,6 +836,7 @@ ext/shout/Makefile ext/sidplay/Makefile ext/smoothwave/Makefile ext/vorbis/Makefile +ext/tarkin/Makefile ext/xmms/Makefile gst-libs/Makefile gst-libs/gst/Makefile diff --git a/ext/aalib/gstaasink.c b/ext/aalib/gstaasink.c index 7d41010..2e2d1dd 100644 --- a/ext/aalib/gstaasink.c +++ b/ext/aalib/gstaasink.c @@ -256,6 +256,14 @@ gst_aasink_sinkconnect (GstPad *pad, GstCaps *caps) } static void +gst_aasink_set_clock (GstElement *element, GstClock *clock) +{ + GstAASink *aasink = GST_AASINK (element); + + aasink->clock = clock; +} + +static void gst_aasink_init (GstAASink *aasink) { aasink->sinkpad = gst_pad_new_from_template ( @@ -264,9 +272,6 @@ gst_aasink_init (GstAASink *aasink) gst_pad_set_chain_function (aasink->sinkpad, gst_aasink_chain); gst_pad_set_connect_function (aasink->sinkpad, gst_aasink_sinkconnect); - aasink->clock = gst_clock_get_system(); - gst_clock_register(aasink->clock, GST_OBJECT(aasink)); - memcpy(&aasink->ascii_surf, &aa_defparams, sizeof (struct aa_hardware_params)); aasink->ascii_parms.bright = 0; aasink->ascii_parms.contrast = 16; @@ -279,6 +284,9 @@ gst_aasink_init (GstAASink *aasink) aasink->width = -1; aasink->height = -1; + aasink->clock = NULL; + GST_ELEMENT (aasink)->setclockfunc = gst_aasink_set_clock; + GST_FLAG_SET(aasink, GST_ELEMENT_THREAD_SUGGESTED); } @@ -324,7 +332,6 @@ static void gst_aasink_chain (GstPad *pad, GstBuffer *buf) { GstAASink *aasink; - GstClockTimeDiff jitter; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); @@ -342,15 +349,8 @@ gst_aasink_chain (GstPad *pad, GstBuffer *buf) GST_DEBUG (0,"videosink: clock wait: %llu\n", GST_BUFFER_TIMESTAMP(buf)); - jitter = gst_clock_current_diff(aasink->clock, GST_BUFFER_TIMESTAMP (buf)); - - if (jitter > 500000 || jitter < -500000) - { - GST_DEBUG (0, "jitter: %lld\n", jitter); - gst_clock_set (aasink->clock, GST_BUFFER_TIMESTAMP (buf)); - } - else { - gst_clock_wait(aasink->clock, GST_BUFFER_TIMESTAMP(buf), GST_OBJECT(aasink)); + if (aasink->clock) { + gst_element_clock_wait (GST_ELEMENT (aasink), aasink->clock, GST_BUFFER_TIMESTAMP(buf)); } aa_render (aasink->context, &aasink->ascii_parms, diff --git a/gst/avi/gstavidecoder.c b/gst/avi/gstavidecoder.c new file mode 100644 index 0000000..fdd283a --- /dev/null +++ b/gst/avi/gstavidecoder.c @@ -0,0 +1,370 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/*#define GST_DEBUG_ENABLED */ +#include + +#include "gstavidecoder.h" + + + +/* elementfactory information */ +static GstElementDetails gst_avi_decoder_details = { + ".avi decoder", + "Decoder/Video", + "Decodes a .avi file into audio and video", + VERSION, + "Erik Walthinsen \n" + "Wim Taymans ", + "(C) 1999", +}; + +static GstCaps* avi_typefind (GstBuffer *buf, gpointer private); + +/* typefactory for 'avi' */ +static GstTypeDefinition avidefinition = { + "avidecoder_video/avi", + "video/avi", + ".avi", + avi_typefind, +}; + +/* AviDecoder signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_BITRATE, + ARG_MEDIA_TIME, + ARG_CURRENT_TIME, + /* FILL ME */ +}; + +GST_PADTEMPLATE_FACTORY (sink_templ, + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "avidecoder_sink", + "video/avi", + "RIFF", GST_PROPS_STRING ("AVI") + ) +) + +GST_PADTEMPLATE_FACTORY (src_video_templ, + "video_src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "wincodec_src", + "video/raw", + "format", GST_PROPS_LIST ( + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R','G','B',' ')) + ), + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096) + ) +) + +GST_PADTEMPLATE_FACTORY (src_audio_templ, + "audio_src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "src_audio", + "audio/raw", + "format", GST_PROPS_STRING ("int"), + "law", GST_PROPS_INT (0), + "endianness", GST_PROPS_INT (G_BYTE_ORDER), + "signed", GST_PROPS_LIST ( + GST_PROPS_BOOLEAN (TRUE), + GST_PROPS_BOOLEAN (FALSE) + ), + "width", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "depth", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "rate", GST_PROPS_INT_RANGE (11025, 48000), + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +) + +static void gst_avi_decoder_class_init (GstAviDecoderClass *klass); +static void gst_avi_decoder_init (GstAviDecoder *avi_decoder); + +static void gst_avi_decoder_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + + + +static GstElementClass *parent_class = NULL; +/*static guint gst_avi_decoder_signals[LAST_SIGNAL] = { 0 }; */ + +GType +gst_avi_decoder_get_type(void) +{ + static GType avi_decoder_type = 0; + + if (!avi_decoder_type) { + static const GTypeInfo avi_decoder_info = { + sizeof(GstAviDecoderClass), + NULL, + NULL, + (GClassInitFunc)gst_avi_decoder_class_init, + NULL, + NULL, + sizeof(GstAviDecoder), + 0, + (GInstanceInitFunc)gst_avi_decoder_init, + }; + avi_decoder_type = g_type_register_static(GST_TYPE_BIN, "GstAviDecoder", &avi_decoder_info, 0); + } + return avi_decoder_type; +} + +static void +gst_avi_decoder_class_init (GstAviDecoderClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE, + g_param_spec_long ("bitrate","bitrate","bitrate", + G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */ + g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_MEDIA_TIME, + g_param_spec_long ("media_time","media_time","media_time", + G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */ + g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_CURRENT_TIME, + g_param_spec_long ("current_time","current_time","current_time", + G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */ + + parent_class = g_type_class_ref (GST_TYPE_BIN); + + gobject_class->get_property = gst_avi_decoder_get_property; +} + +static void +gst_avi_decoder_new_pad (GstElement *element, GstPad *pad, GstAviDecoder *avi_decoder) +{ + GstCaps *caps; + GstCaps *targetcaps = NULL; + const gchar *format; + gboolean type_found; + GstElement *type; + GstElement *new_element = NULL; + gchar *padname = NULL; + gchar *gpadname = NULL; +#define AVI_TYPE_VIDEO 1 +#define AVI_TYPE_AUDIO 2 + gint media_type = 0; + + GST_DEBUG (0, "avidecoder: new pad for element \"%s\"\n", gst_element_get_name (element)); + + caps = gst_pad_get_caps (pad); + format = gst_caps_get_string (caps, "format"); + + if (!strcmp (format, "strf_vids")) { + targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ)); + media_type = AVI_TYPE_VIDEO; + gpadname = g_strdup_printf ("video_%02d", avi_decoder->video_count++); + } + else if (!strcmp (format, "strf_auds")) { + targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_audio_templ)); + media_type = AVI_TYPE_AUDIO; + gpadname = g_strdup_printf ("audio_%02d", avi_decoder->audio_count++); + } + else if (!strcmp (format, "strf_iavs")) { + targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ)); + media_type = AVI_TYPE_VIDEO; + gpadname = g_strdup_printf ("video_%02d", avi_decoder->video_count++); + } + else { + g_assert_not_reached (); + } + + gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PAUSED); + + type = gst_elementfactory_make ("avitypes", + g_strdup_printf ("typeconvert%d", avi_decoder->count)); + + /* brin the element to the READY state so it can do our caps negotiation */ + gst_element_set_state (type, GST_STATE_READY); + + gst_pad_connect (pad, gst_element_get_pad (type, "sink")); + type_found = gst_util_get_bool_arg (G_OBJECT (type), "type_found"); + + if (type_found) { + + gst_bin_add (GST_BIN (avi_decoder), type); + + pad = gst_element_get_pad (type, "src"); + caps = gst_pad_get_caps (pad); + + if (gst_caps_check_compatibility (caps, targetcaps)) { + gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), + gst_element_get_pad (type, "src"), gpadname); + + avi_decoder->count++; + goto done; + } +#ifndef GST_DISABLE_AUTOPLUG + else { + GstAutoplug *autoplug; + autoplug = gst_autoplugfactory_make("static"); + + new_element = gst_autoplug_to_caps (autoplug, caps, targetcaps, NULL); + + padname = "src_00"; + } +#endif /* GST_DISABLE_AUTOPLUG */ + } + + if (!new_element && (media_type == AVI_TYPE_VIDEO)) { + padname = "src"; + } + else if (!new_element && (media_type == AVI_TYPE_AUDIO)) { + /*FIXME */ + padname = "src"; + } + + if (new_element) { + gst_pad_connect (pad, gst_element_get_pad (new_element, "sink")); + gst_element_set_name (new_element, g_strdup_printf ("element%d", avi_decoder->count)); + gst_bin_add (GST_BIN (avi_decoder), new_element); + + gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), + gst_element_get_pad (new_element, padname), gpadname); + + avi_decoder->count++; + } + else { + g_warning ("avidecoder: could not autoplug\n"); + } + +done: + gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PLAYING); +} + +static void +gst_avi_decoder_init (GstAviDecoder *avi_decoder) +{ + avi_decoder->demuxer = gst_elementfactory_make ("avidemux", "demux"); + + if (avi_decoder->demuxer) { + gst_bin_add (GST_BIN (avi_decoder), avi_decoder->demuxer); + + gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), + gst_element_get_pad (avi_decoder->demuxer, "sink"), "sink"); + + g_signal_connect (G_OBJECT (avi_decoder->demuxer),"new_pad", G_CALLBACK (gst_avi_decoder_new_pad), + avi_decoder); + } + else { + g_warning ("wow!, no avi demuxer found. help me\n"); + } + + avi_decoder->count = 0; + avi_decoder->audio_count = 0; + avi_decoder->video_count = 0; +} + +static GstCaps* +avi_typefind (GstBuffer *buf, + gpointer private) +{ + gchar *data = GST_BUFFER_DATA (buf); + GstCaps *new; + + GST_DEBUG (0,"avi_decoder: typefind\n"); + if (strncmp (&data[0], "RIFF", 4)) return NULL; + if (strncmp (&data[8], "AVI ", 4)) return NULL; + + new = GST_CAPS_NEW ("avi_typefind", + "video/avi", + "RIFF", GST_PROPS_STRING ("AVI")); + + return new; +} + +static void +gst_avi_decoder_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstAviDecoder *src; + + g_return_if_fail (GST_IS_AVI_DECODER (object)); + + src = GST_AVI_DECODER (object); + + switch(prop_id) { + case ARG_BITRATE: + break; + case ARG_MEDIA_TIME: + g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "media_time")); + break; + case ARG_CURRENT_TIME: + g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "current_time")); + break; + default: + break; + } +} + + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + GstTypeFactory *type; + + /* create an elementfactory for the avi_decoder element */ + factory = gst_elementfactory_new ("avidecoder", GST_TYPE_AVI_DECODER, + &gst_avi_decoder_details); + g_return_val_if_fail (factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_audio_templ)); + gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_video_templ)); + gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ)); + + type = gst_typefactory_new (&avidefinition); + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "avidecoder", + plugin_init +}; + diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 6082012..302bb6e 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -229,7 +229,9 @@ gst_avi_demux_init (GstAviDemux *avi_demux) avi_demux->state = GST_AVI_DEMUX_UNKNOWN; avi_demux->num_audio_pads = 0; avi_demux->num_video_pads = 0; + //avi_demux->next_time = 500000; avi_demux->next_time = 0; + avi_demux->init_audio = 0; avi_demux->flags = 0; avi_demux->index_entries = NULL; avi_demux->index_size = 0; @@ -324,6 +326,27 @@ gst_avi_demux_strh (GstAviDemux *avi_demux) GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: samplesize %d", GUINT32_FROM_LE (strh->samplesize)); avi_demux->fcc_type = GUINT32_FROM_LE (strh->type); + if (strh->type == GST_RIFF_FCC_auds) { + guint32 scale; + + scale = GUINT32_FROM_LE (strh->scale); + avi_demux->init_audio = GUINT32_FROM_LE (strh->init_frames); + if (!scale) + scale = 1; + avi_demux->audio_rate = GUINT32_FROM_LE (strh->rate) / scale; + } + else if (strh->type == GST_RIFF_FCC_vids) { + gfloat frame_rate; + guint32 scale; + + scale = GUINT32_FROM_LE (strh->scale); + if (!scale) + scale = 1; + frame_rate = (gfloat)GUINT32_FROM_LE (strh->rate) / scale; + + gst_element_send_event (GST_ELEMENT (avi_demux), + gst_event_new_info ("frame_rate", GST_PROPS_FLOAT (frame_rate), NULL)); + } return TRUE; } @@ -538,14 +561,26 @@ gst_avi_demux_strf_iavs (GstAviDemux *avi_demux) static void gst_avidemux_parse_index (GstAviDemux *avi_demux, - gulong offset) + gulong filepos, gulong offset) { GstBuffer *buf; gulong index_size; - buf = gst_pad_pullregion (avi_demux->sinkpad, GST_REGION_OFFSET_LEN, offset, 8); + if (!gst_bytestream_seek (avi_demux->bs, GST_SEEK_BYTEOFFSET_SET, filepos + offset)) { + GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek to index"); + return; + } + buf = gst_bytestream_read (avi_demux->bs, 8); + while (!buf) { + guint32 remaining; + GstEvent *event; + + gst_bytestream_get_status (avi_demux->bs, &remaining, &event); - if (!buf || GST_BUFFER_OFFSET (buf) != offset || GST_BUFFER_SIZE (buf) != 8) { + buf = gst_bytestream_read (avi_demux->bs, 8); + } + + if (GST_BUFFER_OFFSET (buf) != filepos + offset || GST_BUFFER_SIZE (buf) != 8) { GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not get index"); return; } @@ -556,8 +591,9 @@ gst_avidemux_parse_index (GstAviDemux *avi_demux, } index_size = GUINT32_FROM_LE(*(guint32 *)(GST_BUFFER_DATA (buf) + 4)); + gst_buffer_unref (buf); - buf = gst_pad_pullregion(avi_demux->sinkpad, GST_REGION_OFFSET_LEN, offset+8, index_size); + buf = gst_bytestream_read (avi_demux->bs, index_size); avi_demux->index_size = index_size/sizeof(gst_riff_index_entry); @@ -565,28 +601,11 @@ gst_avidemux_parse_index (GstAviDemux *avi_demux, avi_demux->index_entries = g_malloc (GST_BUFFER_SIZE (buf)); memcpy (avi_demux->index_entries, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buf); - buf = gst_pad_pullregion(avi_demux->sinkpad, GST_REGION_OFFSET_LEN, avi_demux->index_offset, 0); -} - -static void -gst_avidemux_forall_pads (GstAviDemux *avi_demux, GFunc func, gpointer user_data) -{ - gint i; - GstPad *pad; - - for(i=0; iaudio_pad[i]; - if (pad && GST_PAD_IS_CONNECTED (pad)) { - (*func) (pad, user_data); - } - } - - for(i=0; ivideo_pad[i]; - if (pad && GST_PAD_IS_CONNECTED (pad)) { - (*func) (pad, user_data); - } + if (!gst_bytestream_seek (avi_demux->bs, GST_SEEK_BYTEOFFSET_SET, filepos)) { + GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek back to movi"); + return; } } @@ -628,16 +647,19 @@ gst_avidemux_read_chunk (GstAviDemux *avi_demux, guint32 *id, guint32 *size) gst_riff_chunk *chunk; GstByteStream *bs = avi_demux->bs; - chunk = (gst_riff_chunk *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_chunk)); - if (chunk) { - *id = GUINT32_FROM_LE (chunk->id); - *size = GUINT32_FROM_LE (chunk->size); + do { + chunk = (gst_riff_chunk *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_chunk)); + if (chunk) { + *id = GUINT32_FROM_LE (chunk->id); + *size = GUINT32_FROM_LE (chunk->size); - gst_bytestream_flush (bs, sizeof (gst_riff_chunk)); + gst_bytestream_flush (bs, sizeof (gst_riff_chunk)); - return TRUE; - } - return gst_avidemux_handle_event (avi_demux); + return TRUE; + } + } while (gst_avidemux_handle_event (avi_demux)); + + return TRUE; } static gboolean @@ -672,16 +694,34 @@ gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, { guint32 datashowed; guint32 subchunksize = 0; /* size of a read subchunk */ + gchar *formtype; - /* flush the form type */ - if (!gst_bytestream_flush (bs, sizeof (guint32))) + formtype = gst_bytestream_peek_bytes (bs, sizeof (guint32)); + if (!formtype) return FALSE; + switch (GUINT32_FROM_LE (*((guint32*)formtype))) { + case GST_RIFF_LIST_movi: + gst_avidemux_parse_index (avi_demux, *filepos, *chunksize); + while (!gst_bytestream_flush (bs, sizeof (guint32))) { + guint32 remaining; + GstEvent *event; + + gst_bytestream_get_status (avi_demux->bs, &remaining, &event); + } + break; + default: + /* flush the form type */ + gst_bytestream_flush_fast (bs, sizeof (guint32)); + break; + } + datashowed = sizeof (guint32); /* we showed the form type */ *filepos += datashowed; /* for the rest of the routine */ while (datashowed < *chunksize) { /* while not showed all: */ + GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk filepos %08llx", *filepos); /* recurse for subchunks of RIFF and LIST chunks: */ if (!gst_avidemux_process_chunk (avi_demux, filepos, 0, rec_depth + 1, &subchunksize)) @@ -690,7 +730,8 @@ gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, subchunksize = ((subchunksize + 1) & ~1); datashowed += (sizeof (guint32) + sizeof (guint32) + subchunksize); - *filepos += subchunksize; + GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk done filepos %08llx, subchunksize %08x", + *filepos, subchunksize); } if (datashowed != *chunksize) { g_warning ("error parsing AVI"); @@ -737,6 +778,7 @@ gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, buf = gst_bytestream_peek (bs, *chunksize); GST_BUFFER_TIMESTAMP (buf) = avi_demux->next_time; + avi_demux->next_time += avi_demux->time_interval; if (avi_demux->video_need_flush[0]) { @@ -759,12 +801,19 @@ gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, GST_DEBUG (0,"gst_avi_demux_chain: tag found %08x size %08x\n", chunkid, *chunksize); + if (avi_demux->init_audio) { + //avi_demux->next_time += (*chunksize) * 1000000LL / avi_demux->audio_rate; + avi_demux->init_audio--; + } + if (GST_PAD_IS_CONNECTED (avi_demux->audio_pad[0])) { GstBuffer *buf; if (*chunksize) { buf = gst_bytestream_peek (bs, *chunksize); + GST_BUFFER_TIMESTAMP (buf) = -1LL; + if (avi_demux->audio_need_flush[0]) { GST_DEBUG (0,"audio flush\n"); avi_demux->audio_need_flush[0] = FALSE; @@ -787,6 +836,7 @@ gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos, GST_INFO (GST_CAT_PLUGIN_INFO, "chunkid %s, flush %08x, filepos %08llx", gst_riff_id_to_fourcc (chunkid), *chunksize, *filepos); + *filepos += *chunksize; if (!gst_bytestream_flush (bs, *chunksize)) { return gst_avidemux_handle_event (avi_demux); } diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h index 4703aad..67a9333 100644 --- a/gst/avi/gstavidemux.h +++ b/gst/avi/gstavidemux.h @@ -82,6 +82,8 @@ struct _GstAviDemux { gulong current_frame; guint32 flags; + guint32 init_audio; + guint32 audio_rate; guint num_audio_pads; guint num_video_pads; diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am index 1a44f51..0fc60f6 100644 --- a/sys/oss/Makefile.am +++ b/sys/oss/Makefile.am @@ -2,7 +2,7 @@ plugindir = $(libdir)/gst plugin_LTLIBRARIES = libgstossaudio.la libgstosshelper.la -libgstossaudio_la_SOURCES = gstosssink.c gstosssrc.c gstossaudio.c gstossgst.c +libgstossaudio_la_SOURCES = gstosssink.c gstosssrc.c gstossaudio.c gstossgst.c gstossclock.c libgstossaudio_la_CFLAGS = $(GST_CFLAGS) libgstossaudio_la_LIBADD = $(GST_LIBS) libgstossaudio_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@ @@ -10,5 +10,5 @@ libgstossaudio_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@ libgstosshelper_la_SOURCES = gstosshelper.c libgstosshelper_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@ -noinst_HEADERS = gstosssink.h gstosssrc.h gstossgst.h gstosshelper.h +noinst_HEADERS = gstosssink.h gstosssrc.h gstossgst.h gstosshelper.h gstossclock.h diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c index 86d07e2..8a6b7d3 100644 --- a/sys/oss/gstosssink.c +++ b/sys/oss/gstosssink.c @@ -49,6 +49,8 @@ static gboolean gst_osssink_open_audio (GstOssSink *sink); static void gst_osssink_close_audio (GstOssSink *sink); static gboolean gst_osssink_sync_parms (GstOssSink *osssink); static GstElementStateReturn gst_osssink_change_state (GstElement *element); +static void gst_osssink_set_clock (GstElement *element, GstClock *clock); +static GstClock* gst_osssink_get_clock (GstElement *element); static GstPadConnectReturn gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps); static void gst_osssink_set_property (GObject *object, guint prop_id, const GValue *value, @@ -159,11 +161,11 @@ gst_osssink_get_bufferpool (GstPad *pad) static void gst_osssink_finalize (GObject *object) { - GstOssSink *osssink = (GstOssSink *) object; + GstOssSink *osssink = (GstOssSink *) object; - g_free (osssink->device); + g_free (osssink->device); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } static void @@ -227,7 +229,6 @@ gst_osssink_init (GstOssSink *osssink) osssink->device = g_strdup ("/dev/dsp"); osssink->fd = -1; - osssink->clock = gst_clock_get_system(); osssink->channels = 1; osssink->frequency = 11025; osssink->fragment = 6; @@ -237,10 +238,16 @@ gst_osssink_init (GstOssSink *osssink) #else osssink->format = AFMT_S16_LE; #endif /* WORDS_BIGENDIAN */ - gst_clock_register (osssink->clock, GST_OBJECT (osssink)); + //gst_clock_register (osssink->clock, GST_OBJECT (osssink)); osssink->bufsize = 4096; + osssink->offset = 0LL; /* 6 buffers per chunk by default */ osssink->sinkpool = gst_buffer_pool_get_default (osssink->bufsize, 6); + + osssink->provided_clock = GST_CLOCK (gst_oss_clock_new ("OssClock", GST_ELEMENT (osssink))); + + GST_ELEMENT (osssink)->setclockfunc = gst_osssink_set_clock; + GST_ELEMENT (osssink)->getclockfunc = gst_osssink_get_clock; GST_FLAG_SET (osssink, GST_ELEMENT_THREAD_SUGGESTED); } @@ -262,6 +269,8 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) if (width != depth) return GST_PAD_CONNECT_REFUSED; + osssink->bps = 0; + law = gst_caps_get_int (caps, "law"); endianness = gst_caps_get_int (caps, "endianness"); sign = gst_caps_get_boolean (caps, "signed"); @@ -280,6 +289,7 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) else if (endianness == G_BIG_ENDIAN) format = AFMT_U16_BE; } + osssink->bps = 2; } else if (width == 8) { if (sign == TRUE) { @@ -288,6 +298,7 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) else { format = AFMT_U8; } + osssink->bps = 1; } } @@ -298,6 +309,9 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) osssink->channels = gst_caps_get_int (caps, "channels"); osssink->frequency = gst_caps_get_int (caps, "rate"); + osssink->bps *= osssink->channels; + osssink->bps *= osssink->frequency; + if (!gst_osssink_sync_parms (osssink)) { return GST_PAD_CONNECT_REFUSED; } @@ -314,8 +328,8 @@ gst_osssink_sync_parms (GstOssSink *osssink) gint target_channels; gint target_frequency; - g_return_if_fail (osssink != NULL); - g_return_if_fail (GST_IS_OSSSINK (osssink)); + g_return_val_if_fail (osssink != NULL, FALSE); + g_return_val_if_fail (GST_IS_OSSSINK (osssink), FALSE); if (osssink->fd == -1) return FALSE; @@ -341,12 +355,12 @@ gst_osssink_sync_parms (GstOssSink *osssink) ioctl (osssink->fd, SNDCTL_DSP_CHANNELS, &osssink->channels); ioctl (osssink->fd, SNDCTL_DSP_SPEED, &osssink->frequency); - ioctl (osssink->fd, SNDCTL_DSP_GETBLKSIZE, &frag); + ioctl (osssink->fd, SNDCTL_DSP_GETBLKSIZE, &osssink->fragment); ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); GST_INFO (GST_CAT_PLUGIN_INFO, "osssink: set sound card to %dHz %d bit %s (%d bytes buffer, %08x fragment)", osssink->frequency, osssink->format, - (osssink->channels == 2) ? "stereo" : "mono", ospace.bytes, frag); + (osssink->channels == 2) ? "stereo" : "mono", ospace.bytes, osssink->fragment); gst_element_send_event (GST_ELEMENT (osssink), gst_event_new_info ("samplerate", GST_PROPS_INT (osssink->frequency), NULL)); @@ -355,6 +369,9 @@ gst_osssink_sync_parms (GstOssSink *osssink) gst_element_send_event (GST_ELEMENT (osssink), gst_event_new_info ("bits", GST_PROPS_INT (osssink->format), NULL)); + osssink->fragment_time = (1000000 * osssink->fragment) / osssink->bps; + GST_INFO (GST_CAT_PLUGIN_INFO, "fragment time %lu %llu\n", osssink->bps, osssink->fragment_time); + if (target_format != osssink->format || target_channels != osssink->channels || target_frequency != osssink->frequency) @@ -366,43 +383,90 @@ gst_osssink_sync_parms (GstOssSink *osssink) return TRUE; } +static void +gst_osssink_set_clock (GstElement *element, GstClock *clock) +{ + GstOssSink *osssink; + + osssink = GST_OSSSINK (element); + + osssink->clock = clock; +} + +static GstClock* +gst_osssink_get_clock (GstElement *element) +{ + GstOssSink *osssink; + + osssink = GST_OSSSINK (element); + + return osssink->provided_clock; +} + static void gst_osssink_chain (GstPad *pad, GstBuffer *buf) { GstOssSink *osssink; - gboolean in_flush; - audio_buf_info ospace; + GstClockTime buftime; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - /* this has to be an audio buffer */ osssink = GST_OSSSINK (gst_pad_get_parent (pad)); -// g_return_if_fail(GST_FLAG_IS_SET(osssink,GST_STATE_RUNNING)); - if (GST_IS_EVENT (buf)) { - gst_pad_event_default (pad, GST_EVENT (buf)); - return; - } + buftime = GST_BUFFER_TIMESTAMP (buf); + + if (osssink->fd >= 0) { + if (!osssink->mute) { + guchar *data = GST_BUFFER_DATA (buf); + gint size = GST_BUFFER_SIZE (buf); + + if (osssink->clock) { + if (osssink->clock == osssink->provided_clock) { + guint64 time; + gint granularity, granularity_time; + count_info optr; + audio_buf_info ospace; + gint queued; + + /* FIXME, NEW_MEDIA/DISCONT?. Try to get our start point */ + if (osssink->offset == 0LL && buftime != -1LL) { + //gst_oss_clock_set_base (GST_OSS_CLOCK (osssink->clock), buftime); + osssink->offset = buftime; + } + + ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); + ioctl (osssink->fd, SNDCTL_DSP_GETOPTR, &optr); + + queued = (ospace.fragstotal * ospace.fragsize) - ospace.bytes; + time = osssink->offset + (optr.bytes) * 1000000LL / osssink->bps; + + GST_DEBUG (GST_PLUGIN_INFO, "sync %llu %llu %d\n", buftime, time, queued); + + granularity = ospace.fragsize; + //granularity = size; + granularity_time = granularity * osssink->fragment_time / ospace.fragsize; + + while (size > 0) { + write (osssink->fd, data, MIN (size, granularity)); + data += granularity; + size -= granularity; + time += granularity_time; + gst_clock_set_time (osssink->provided_clock, time); + } + } + else { + gst_element_clock_wait (GST_ELEMENT (osssink), osssink->clock, buftime); + + write (osssink->fd, data, size); + } + } + else { + audio_buf_info ospace; - g_signal_emit (G_OBJECT (osssink), gst_osssink_signals[SIGNAL_HANDOFF], 0, - osssink); - - if (GST_BUFFER_DATA (buf) != NULL) { -#ifndef GST_DISABLE_TRACE - gst_trace_add_entry(NULL, 0, buf, "osssink: writing to soundcard"); -#endif // GST_DISABLE_TRACE - //g_print("osssink: writing to soundcard\n"); - if (osssink->fd >= 0) { - if (!osssink->mute) { - gst_clock_wait (osssink->clock, GST_BUFFER_TIMESTAMP (buf), GST_OBJECT (osssink)); ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); - GST_DEBUG (GST_CAT_PLUGIN_INFO,"osssink: (%d bytes buffer) %d %p %d\n", ospace.bytes, - osssink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - write (osssink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - //write(STDOUT_FILENO,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + + if (ospace.bytes >= size) { + write (osssink->fd, data, size); + } } } } @@ -588,12 +652,38 @@ gst_osssink_change_state (GstElement *element) case GST_STATE_READY_TO_PAUSED: break; case GST_STATE_PAUSED_TO_PLAYING: + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), TRUE); break; case GST_STATE_PLAYING_TO_PAUSED: - if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) - ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + { + if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) { + if (osssink->bps) { + GstClockTime time; + audio_buf_info ospace; + count_info optr; + gint queued; + + ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); + ioctl (osssink->fd, SNDCTL_DSP_GETOPTR, &optr); + + queued = (ospace.fragstotal * ospace.fragsize) - ospace.bytes; + time = (optr.bytes + queued) * 1000000LL / osssink->bps; + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), FALSE); + gst_clock_set_time (osssink->provided_clock, time); + } + else { + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), FALSE); + } + } + break; + } case GST_STATE_PAUSED_TO_READY: + if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); break; case GST_STATE_READY_TO_NULL: if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h index fa42324..c526cea 100644 --- a/sys/oss/gstosssink.h +++ b/sys/oss/gstosssink.h @@ -28,6 +28,7 @@ #include #include +#include "gstossclock.h" #ifdef __cplusplus extern "C" { @@ -60,7 +61,7 @@ struct _GstOssSink { GstPad *sinkpad; GstBufferPool *sinkpool; - //GstClockTime clocktime; + GstClock *provided_clock; GstClock *clock; /* device */ @@ -75,6 +76,10 @@ struct _GstOssSink { gint fragment; gboolean mute; guint bufsize; + guint bps; + guint64 offset; + + guint64 fragment_time; }; struct _GstOssSinkClass {