# HG changeset patch # User rosfran # Date 1163085629 0 # Node ID 959df0ca7621db30ce70978715479668ad5df048 # Parent 04a6aeac87b05555526c6ac6e59c3278d3c5624f [svn r74] Changed the set_active on PADs, fixed some offset on video and audio. diff -r 04a6aeac87b0 -r 959df0ca7621 gst-plugins-nuvdemux/src/gstnuvdemux.c --- a/gst-plugins-nuvdemux/src/gstnuvdemux.c Tue Nov 07 23:11:23 2006 +0000 +++ b/gst-plugins-nuvdemux/src/gstnuvdemux.c Thu Nov 09 15:20:29 2006 +0000 @@ -52,15 +52,13 @@ #include #include -#define GETTEXT_PACKAGE "gst-plugins-nuvdemux-0.10.3" -#include +#include "gst/gst-i18n-plugin.h" #include "gstnuvdemux.h" GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug); #define GST_CAT_DEFAULT nuvdemux_debug -#define DEMUX_INDEX_SIZE_MAX (100000) #define GST_FLOW_ERROR_NO_DATA -101 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT); @@ -90,11 +88,11 @@ GST_STATIC_CAPS_ANY); /* NUV Demux indexes init/dispose callers */ -static nuv_demux_index* gst_nuv_demux_index_new (void); -static void gst_nuv_demux_index_destroy (nuv_demux_index *p_idx); +static void gst_nuv_demux_index_init( nuv_demux_index **p_idx ); +static void gst_nuv_demux_index_clean( nuv_demux_index **p_idx ); /* NUV Demux indexes manipulation functions */ -static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset ); +//static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset ); static void gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset ); static gint64 gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time ); @@ -107,12 +105,16 @@ static GstFlowReturn gst_nuv_demux_play (GstPad * pad); static gboolean gst_nuv_demux_sink_activate_pull (GstPad * sinkpad, gboolean active); -static gboolean gst_nuv_demux_sink_activate_push (GstPad * pad, - gboolean active); static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad); static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size, gboolean move, GstBuffer ** buffer); static void gst_nuv_demux_reset (GstNuvDemux * nuv); +static gboolean gst_nuv_demux_handle_sink_event (GstPad * sinkpad, + GstEvent * event); +static gboolean gst_nuv_demux_handle_audio_src_event (GstPad * sinkpad, + GstEvent * event); +static gboolean gst_nuv_demux_handle_video_src_event (GstPad * sinkpad, + GstEvent * event); static void gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv); static void gst_nuv_demux_send_eos (GstNuvDemux * nuv); @@ -180,15 +182,14 @@ gst_pad_set_activatepull_function (nuv->sinkpad, gst_nuv_demux_sink_activate_pull); - gst_pad_set_activatepush_function (nuv->sinkpad, - gst_nuv_demux_sink_activate_push); - gst_pad_set_chain_function (nuv->sinkpad, GST_DEBUG_FUNCPTR (gst_nuv_demux_chain)); + gst_pad_set_event_function (nuv->sinkpad, gst_nuv_demux_handle_sink_event); + gst_element_add_pad (GST_ELEMENT (nuv), nuv->sinkpad); - nuv->index_entries = gst_nuv_demux_index_new (); + gst_nuv_demux_index_init( &nuv->index_entries ); nuv->adapter = NULL; nuv->mpeg_buffer = NULL; @@ -208,7 +209,7 @@ } if ( nuv->index_entries != NULL ) { - gst_nuv_demux_index_destroy (nuv->index_entries); + gst_nuv_demux_index_clean( &nuv->index_entries ); nuv->index_entries = NULL; } @@ -225,20 +226,22 @@ * Indexes (timecode offset conversion) functions *****************************************************************************/ -static nuv_demux_index* -gst_nuv_demux_index_new (void) +static void +gst_nuv_demux_index_init( nuv_demux_index **p_idx ) { - return g_new0 (nuv_demux_index, 1); + *p_idx = g_new0( nuv_demux_index, 1 ); + (*p_idx)->i_idx = 0; + (*p_idx)->i_idx_max = 0; } static void -gst_nuv_demux_index_destroy (nuv_demux_index *p_idx) +gst_nuv_demux_index_clean( nuv_demux_index **p_idx ) { - if (p_idx != NULL) { - g_free (p_idx->idx); - p_idx->idx = NULL; - g_free (p_idx); + if ( *p_idx != NULL ) { + g_free( *p_idx ); + *p_idx = NULL; } + } static void @@ -250,13 +253,13 @@ // return; /* Be sure to append new entry (we don't insert point) */ - if (p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time) + if( p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time ) return; /* */ - if (p_idx->i_idx >= p_idx->i_idx_max) + if( p_idx->i_idx >= p_idx->i_idx_max ) { - if (p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX) + if( p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX ) { /* Avoid too big index */ const gint64 i_length = p_idx->idx[p_idx->i_idx-1].i_time - @@ -265,20 +268,20 @@ gint i, j; /* We try to reduce the resolution of the index by a factor 2 */ - for (i = 1, j = 1; i < p_idx->i_idx; i++) + for( i = 1, j = 1; i < p_idx->i_idx; i++ ) { - if (p_idx->idx[i].i_time < j * i_length / i_count) + if( p_idx->idx[i].i_time < j * i_length / i_count ) continue; p_idx->idx[j++] = p_idx->idx[i]; } p_idx->i_idx = j; - if (p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4) + if( p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4 ) { /* We haven't created enough space * (This method won't create a good index but work for sure) */ - for (i = 0; i < p_idx->i_idx/2; i++) + for( i = 0; i < p_idx->i_idx/2; i++ ) p_idx->idx[i] = p_idx->idx[2*i]; p_idx->i_idx /= 2; } @@ -286,8 +289,6 @@ else { p_idx->i_idx_max += 1000; - p_idx->idx = g_realloc (p_idx->idx, - p_idx->i_idx_max*sizeof(nuv_demux_index_entry)); } } @@ -342,50 +343,26 @@ return p_idx->idx[i_max].i_offset; } -static gint64 -gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset ) +/***************************************************************************** + * Utils functions + *****************************************************************************/ + +static gboolean +gst_nuv_demux_handle_sink_event (GstPad * sinkpad, GstEvent * event) { - nuv_demux_index *p_idx = nuv->index_entries; + gboolean res = FALSE; - g_return_val_if_fail( p_idx != NULL && p_idx->idx != NULL, i_offset ); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + res = TRUE; + break; + default: + return gst_pad_event_default (sinkpad, event); + break; + } - gint i_min = 0; - gint i_max = p_idx->i_idx-1; - - /* Empty index */ - if( p_idx->i_idx <= 0 ) - return -1; - - /* Special border case */ - if( i_offset <= p_idx->idx[0].i_offset ) - return p_idx->idx[0].i_offset; - if( i_offset == p_idx->idx[i_max].i_offset ) - return p_idx->idx[i_max].i_offset; - if( i_offset > p_idx->idx[i_max].i_offset ) - return -1; - - /* Dicho */ - for( ;; ) - { - gint i_med; - - if ( i_max - i_min <= 1 ) - break; - - i_med = (i_min+i_max)/2; - if( p_idx->idx[i_med].i_offset < i_offset ) - i_min = i_med; - else if( p_idx->idx[i_med].i_offset > i_offset ) - i_max = i_med; - else - return p_idx->idx[i_med].i_offset; - } - - /* return nearest */ - if( i_offset - p_idx->idx[i_min].i_offset < p_idx->idx[i_max].i_offset - i_offset ) - return p_idx->idx[i_min].i_offset; - else - return p_idx->idx[i_max].i_offset; + gst_event_unref (event); + return res; } /* HeaderLoad: @@ -559,12 +536,18 @@ } static gboolean -gst_nuv_demux_handle_src_event (GstPad * pad, GstEvent * event) +gst_nuv_demux_handle_audio_src_event (GstPad * pad, GstEvent * event) { gst_event_unref (event); return FALSE; } +static gboolean +gst_nuv_demux_handle_video_src_event (GstPad * pad, GstEvent * event) +{ + gst_event_unref (event); + return FALSE; +} static void gst_nuv_demux_create_pads (GstNuvDemux * nuv) @@ -584,15 +567,13 @@ (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL); gst_pad_use_fixed_caps (nuv->src_video_pad); - gst_pad_set_active (nuv->src_video_pad, TRUE); gst_pad_set_caps (nuv->src_video_pad, video_caps); + gst_pad_set_event_function (nuv->src_video_pad, + gst_nuv_demux_handle_video_src_event); gst_pad_set_active (nuv->src_video_pad, TRUE); gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad); - gst_pad_set_event_function (nuv->src_video_pad, - gst_nuv_demux_handle_src_event); - gst_caps_unref (video_caps); } @@ -609,14 +590,13 @@ "mpegversion", G_TYPE_INT, nuv->eh->i_version, NULL); gst_pad_use_fixed_caps (nuv->src_audio_pad); - gst_pad_set_active (nuv->src_audio_pad, TRUE); gst_pad_set_caps (nuv->src_audio_pad, audio_caps); + + gst_pad_set_event_function (nuv->src_audio_pad, + gst_nuv_demux_handle_audio_src_event); gst_pad_set_active (nuv->src_audio_pad, TRUE); gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad); - gst_pad_set_event_function (nuv->src_audio_pad, - gst_nuv_demux_handle_src_event); - gst_caps_unref (audio_caps); } @@ -642,14 +622,19 @@ GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf = NULL; nuv_frame_header *h = nuv->fh; + + gint64 table_timecode = 0; if (h->i_type == 'R') goto done; + table_timecode = h->i_timecode; - GST_DEBUG_OBJECT (nuv, "starting append index"); - /* append the frame's header timecode field, and the actual offset */ - gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->offset ); + /* append the frame's header timecode field, and the actual offset */ + if ( h->i_type == 'V' ) + gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->video_offset ); + else if ( h->i_type == 'A' ) + gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->audio_offset ); if (h->i_length > 0) { ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf); @@ -659,71 +644,80 @@ /* search for a valid timecode in the indexes list (find the nearest valid timecode) */ if ( h->i_timecode < 0 ) { /* convert this actual timecode to a valid index in the timecode's table */ - gint64 pos = gst_nuv_demux_index_convert_time (nuv, h->i_timecode); - - /* find the nearest empty frame slot */ - gint64 near_off = gst_nuv_demux_index_find_offset (nuv, pos); + gint64 pos = gst_nuv_demux_index_convert_time( nuv, h->i_timecode ); /* just get the timecode from the timecode's table */ - GST_BUFFER_TIMESTAMP (buf) = nuv->index_entries->idx[near_off].i_time * GST_MSECOND; + table_timecode = nuv->index_entries->idx[pos].i_time * GST_MSECOND; } else { - GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND; + table_timecode = h->i_timecode * GST_MSECOND; } - } - - GST_DEBUG_OBJECT (nuv, "index appended"); + + GST_BUFFER_TIMESTAMP (buf) = table_timecode; + } switch (h->i_type) { case 'V': { if (h->i_length == 0) break; - - GST_BUFFER_OFFSET (buf) = nuv->video_offset; + + if ( !gst_pad_is_linked( nuv->src_video_pad ) ) + break; + + //GST_PAD_STREAM_LOCK(nuv->src_video_pad); + + GST_BUFFER_SIZE (buf) = h->i_length; gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad)); ret = gst_pad_push (nuv->src_video_pad, buf); - if (ret != GST_FLOW_OK) { - GST_WARNING_OBJECT (nuv, "error pushing on srcpad %s, is linked? = %d", - gst_pad_get_name (nuv->src_video_pad), gst_pad_is_linked (nuv->src_video_pad)); - } - nuv->video_offset++; + nuv->video_offset += h->i_length; + + //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad); break; } case 'A': { if (h->i_length == 0) break; - - GST_BUFFER_OFFSET (buf) = nuv->audio_offset; + + if ( !gst_pad_is_linked( nuv->src_audio_pad ) ) + break; + + //GST_PAD_STREAM_LOCK(nuv->src_audio_pad); + + GST_BUFFER_SIZE (buf) = h->i_length; gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad)); ret = gst_pad_push (nuv->src_audio_pad, buf); - if (ret != GST_FLOW_OK) { - GST_WARNING_OBJECT (nuv, "Error pushing on srcpad %s, is linked? = %d", - gst_pad_get_name (nuv->src_audio_pad), gst_pad_is_linked (nuv->src_audio_pad)); - } - nuv->audio_offset++; + nuv->audio_offset += h->i_length; + + //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad); break; } case 'S': { - /* switch (h->i_compression) { case 'V': - GST_DEBUG_OBJECT (nuv, "Video New Segment"); - nuv->video_offset = 0; + if ( !gst_pad_is_linked( nuv->src_video_pad ) ) + break; + + //GST_PAD_STREAM_LOCK(nuv->src_video_pad); gst_pad_push_event (nuv->src_video_pad, - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, - 0)); + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode, + GST_CLOCK_TIME_NONE, 0)); + //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad); break; - case 'A': - GST_DEBUG_OBJECT (nuv, "Audio New Segment"); + case 'A': + if ( !gst_pad_is_linked( nuv->src_audio_pad ) ) + break; + + //GST_PAD_STREAM_LOCK(nuv->src_audio_pad); gst_pad_push_event (nuv->src_audio_pad, - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0)); + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode, + GST_CLOCK_TIME_NONE, 0)); + //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad); break; default: break; } - */ } default: if (buf != NULL) @@ -732,8 +726,6 @@ break; } - GST_DEBUG_OBJECT (nuv, "data sent"); - done: nuv->state = GST_NUV_DEMUX_FRAME_HEADER; g_free (nuv->fh); @@ -751,7 +743,7 @@ gst_nuv_demux_read_bytes (nuv, nuv->mpeg_data_size, TRUE, &nuv->mpeg_buffer); if (ret != GST_FLOW_OK) { - return GST_FLOW_ERROR; + return ret; //GST_FLOW_ERROR; } GST_BUFFER_SIZE (nuv->mpeg_buffer) = nuv->mpeg_data_size; nuv->state = GST_NUV_DEMUX_EXTEND_HEADER; @@ -912,7 +904,7 @@ case GST_NUV_DEMUX_MOVI: res = gst_nuv_demux_stream_data (nuv); - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { + if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA) && (res != GST_FLOW_CUSTOM_ERROR)) { goto pause; } break; @@ -929,8 +921,6 @@ return GST_FLOW_OK; pause: - g_debug ("PAUSE"); - GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res)); gst_pad_pause_task (nuv->sinkpad); if (GST_FLOW_IS_FATAL (res)) { @@ -965,13 +955,13 @@ *buffer = gst_buffer_new (); return ret; } - + if (nuv->mode == 0) { ret = gst_pad_pull_range (nuv->sinkpad, nuv->offset, size, buffer); if (ret == GST_FLOW_OK) { - if (move) { - nuv->offset += size; - } + if (move) { + nuv->offset += size; + } /* got eos */ } else if (ret == GST_FLOW_UNEXPECTED) { gst_nuv_demux_send_eos (nuv); @@ -982,11 +972,7 @@ return GST_FLOW_ERROR_NO_DATA; if (move) { - guint8 *data = NULL; - - data = (guint8 *) gst_adapter_take (nuv->adapter, size); - *buffer = gst_buffer_new (); - gst_buffer_set_data (*buffer, data, size); + *buffer = gst_adapter_take_buffer (nuv->adapter, size); } else { guint8 *data = NULL; @@ -995,6 +981,8 @@ gst_buffer_set_data (*buffer, data, size); } } + + return ret; } @@ -1006,14 +994,20 @@ if (gst_pad_check_pull_range (sinkpad)) { nuv->mode = 0; - nuv->adapter = NULL; + if (nuv->adapter) { + gst_adapter_clear (nuv->adapter); + g_object_unref (nuv->adapter); + nuv->adapter = NULL; + } res = gst_pad_activate_pull (sinkpad, TRUE); - GST_DEBUG_OBJECT (nuv, "starting PULL mode"); } else { nuv->mode = 1; - nuv->adapter = gst_adapter_new (); + if (nuv->adapter) { + gst_adapter_clear (nuv->adapter); + } else { + nuv->adapter = gst_adapter_new (); + } res = gst_pad_activate_push (sinkpad, TRUE); - GST_DEBUG_OBJECT (nuv, "starting PUSH mode"); } g_object_unref (nuv); @@ -1035,22 +1029,6 @@ return TRUE; } -static gboolean -gst_nuv_demux_sink_activate_push (GstPad * pad, gboolean active) -{ - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad)); - - if (active) { - GST_DEBUG_OBJECT (nuv, "activating push/chain function"); - } else { - GST_DEBUG_OBJECT (nuv, "deactivating push/chain function"); - } - - gst_object_unref (nuv); - - return TRUE; -} - static GstFlowReturn gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf) { @@ -1058,10 +1036,6 @@ gst_adapter_push (nuv->adapter, buf); - GST_DEBUG_OBJECT (nuv, "PUSH adapter %d", gst_adapter_available (nuv->adapter)); - - gst_object_unref (nuv); - return gst_nuv_demux_play (pad); } @@ -1116,7 +1090,7 @@ gst_nuv_demux_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - + switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: break; @@ -1146,6 +1120,7 @@ { #ifdef ENABLE_NLS setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); #endif /* ENABLE_NLS */ if (!gst_element_register (plugin, "nuvdemux", GST_RANK_SECONDARY, diff -r 04a6aeac87b0 -r 959df0ca7621 gst-plugins-nuvdemux/src/gstnuvdemux.h --- a/gst-plugins-nuvdemux/src/gstnuvdemux.h Tue Nov 07 23:11:23 2006 +0000 +++ b/gst-plugins-nuvdemux/src/gstnuvdemux.h Thu Nov 09 15:20:29 2006 +0000 @@ -38,6 +38,8 @@ #define GST_IS_NUV_DEMUX_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_NUV_DEMUX)) +#define DEMUX_INDEX_SIZE_MAX (100000) + /* Indexes (timecodes/offsets) conversion structures */ typedef struct { @@ -51,7 +53,7 @@ gint i_idx; gint i_idx_max; - nuv_demux_index_entry *idx; + nuv_demux_index_entry idx[DEMUX_INDEX_SIZE_MAX]; } nuv_demux_index; /* */ @@ -107,7 +109,7 @@ 0x02: gauss 5 pixel (8,1,1,1,1)/12 0x04: cartoon filter */ - gint i_timecode; /* ms */ + gint32 i_timecode; /* ms */ gint i_length; /* V,A,T: length of following data S: length of packet correl */