gst-plugins-mythtv/src/gstmythtvsrc.c
branchtrunk
changeset 81 56e39289fa96
parent 71 55c7f31b85aa
child 87 9ea342c364de
     1.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.c	Tue Nov 07 22:53:53 2006 +0000
     1.2 +++ b/gst-plugins-mythtv/src/gstmythtvsrc.c	Mon Nov 13 19:58:37 2006 +0000
     1.3 @@ -38,14 +38,14 @@
     1.4   
     1.5  #define GMYTHTV_TRANSFER_MAX_WAITS	100
     1.6  
     1.7 -#define GMYTHTV_TRANSFER_MAX_BUFFER	4*1024
     1.8 +#define GMYTHTV_TRANSFER_MAX_BUFFER	128*1024
     1.9  //( 32*1024  )
    1.10  
    1.11  /* 4*1024 ??? */
    1.12 -#define MAX_READ_SIZE              	4*1024
    1.13 +#define MAX_READ_SIZE              	2*1024
    1.14  //( 32*1024 )
    1.15  
    1.16 -#define GST_FLOW_ERROR_NO_DATA  -101
    1.17 +#define GST_FLOW_ERROR_NO_DATA  		-101
    1.18  
    1.19  /* stablish a maximum iteration value to the IS_RECORDING message */
    1.20  static guint wait_to_transfer = 0;
    1.21 @@ -56,18 +56,11 @@
    1.22      "Control and receive data as a client over the network via raw socket connections using the MythTV protocol",
    1.23      "Rosfran Borges <rosfran.borges@indt.org.br>" );
    1.24  
    1.25 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    1.26 +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ( "src",
    1.27      GST_PAD_SRC,
    1.28      GST_PAD_ALWAYS,
    1.29      GST_STATIC_CAPS ("video/x-nuv") );
    1.30 -
    1.31 -/*
    1.32 -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
    1.33 -    GST_PAD_SINK,
    1.34 -    GST_PAD_SOMETIMES,
    1.35 -    GST_STATIC_CAPS ("video/x-nuv") );
    1.36 -*/
    1.37 -
    1.38 +    
    1.39  enum
    1.40  {
    1.41    PROP_0,
    1.42 @@ -86,13 +79,18 @@
    1.43  
    1.44  static void gst_mythtv_src_finalize (GObject * gobject);
    1.45  
    1.46 +/*
    1.47  static GstFlowReturn gst_mythtv_src_create (GstBaseSrc * psrc, guint64 offset, 
    1.48  	guint size, GstBuffer ** outbuf);
    1.49 +*/
    1.50 +
    1.51 +//static GstFlowReturn gst_mythtv_src_chain ( GstPad* pad, GstBuffer* outbuf );
    1.52 +static GstFlowReturn gst_mythtv_src_create ( GstPushSrc* psrc, GstBuffer** outbuf );
    1.53  
    1.54  static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
    1.55  static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
    1.56  static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
    1.57 -static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src );
    1.58 +//static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src );
    1.59  
    1.60  static gboolean gst_mythtv_src_next_program_chain ( GstMythtvSrc *src );
    1.61  
    1.62 @@ -127,11 +125,11 @@
    1.63        "MythTV src");
    1.64  }
    1.65  
    1.66 -GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstBaseSrc,
    1.67 -    GST_TYPE_BASE_SRC, _urihandler_init)
    1.68 +//GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstBaseSrc,
    1.69 +//    GST_TYPE_BASE_SRC, _urihandler_init)
    1.70      
    1.71 -//GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstPushSrc,
    1.72 -//    GST_TYPE_PUSH_SRC, _urihandler_init)
    1.73 +GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstPushSrc,
    1.74 +    GST_TYPE_PUSH_SRC, _urihandler_init)
    1.75      
    1.76    static void
    1.77  gst_mythtv_src_base_init (gpointer g_class)
    1.78 @@ -140,21 +138,23 @@
    1.79  
    1.80    gst_element_class_add_pad_template (element_class,
    1.81        gst_static_pad_template_get (&srctemplate));
    1.82 -
    1.83 +      
    1.84    gst_element_class_set_details (element_class, &gst_mythtv_src_details);
    1.85    
    1.86    element_class->change_state = gst_mythtv_src_change_state;
    1.87 +  
    1.88  }
    1.89  
    1.90  static void
    1.91  gst_mythtv_src_class_init (GstMythtvSrcClass * klass)
    1.92  {
    1.93    GObjectClass *gobject_class; 
    1.94 -  //GstPushSrcClass *gstpushsrc_class;
    1.95 +  GstPushSrcClass *gstpushsrc_class;
    1.96    GstBaseSrcClass *gstbasesrc_class;
    1.97  
    1.98    gobject_class = (GObjectClass *) klass;
    1.99    gstbasesrc_class = (GstBaseSrcClass *) klass;
   1.100 +  gstpushsrc_class = (GstPushSrcClass *) klass;
   1.101  
   1.102    gobject_class->set_property = gst_mythtv_src_set_property;
   1.103    gobject_class->get_property = gst_mythtv_src_get_property;
   1.104 @@ -222,9 +222,10 @@
   1.105    gstbasesrc_class->start = gst_mythtv_src_start;
   1.106    gstbasesrc_class->stop = gst_mythtv_src_stop;
   1.107    gstbasesrc_class->get_size = gst_mythtv_src_get_size;
   1.108 -  gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
   1.109 -
   1.110 -  gstbasesrc_class->create = gst_mythtv_src_create;
   1.111 +  //gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
   1.112 +  
   1.113 +  //gstbasesrc_class->create = gst_mythtv_src_create;
   1.114 +  gstpushsrc_class->create = gst_mythtv_src_create;
   1.115      
   1.116    GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
   1.117        "MythTV Client Source");
   1.118 @@ -265,24 +266,21 @@
   1.119    
   1.120    this->adapter = NULL;
   1.121    
   1.122 -  //this->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
   1.123 -  //gst_element_add_pad (GST_ELEMENT (this), this->sinkpad);
   1.124 +  //this->th_read_ahead = NULL;
   1.125    
   1.126 -  /*
   1.127 +  this->th_mutex = NULL;
   1.128 +  
   1.129    this->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
   1.130 +  //gst_pad_set_chain_function ( GST_BASE_SRC_PAD( GST_BASE_SRC( this ) ), 
   1.131 +  //		GST_DEBUG_FUNCPTR ( gst_mythtv_src_chain ) );
   1.132    gst_element_add_pad (GST_ELEMENT (this), this->srcpad);
   1.133 -  */  
   1.134    
   1.135 -  gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES );  
   1.136 +  //gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES );  
   1.137  
   1.138    gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
   1.139 -
   1.140 +  
   1.141   // gst_pad_set_event_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
   1.142    //    gst_mythtv_src_handle_event );
   1.143 -/*
   1.144 -  gst_pad_set_query_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
   1.145 -      gst_mythtv_src_query );
   1.146 -*/
   1.147  
   1.148  }
   1.149  
   1.150 @@ -290,6 +288,16 @@
   1.151  gst_mythtv_src_finalize (GObject * gobject)
   1.152  {
   1.153    GstMythtvSrc *this = GST_MYTHTV_SRC (gobject);
   1.154 +  
   1.155 +  if ( this->th_mutex != NULL ) {
   1.156 +  	g_static_rec_mutex_free( this->th_mutex );
   1.157 +  	this->th_mutex = NULL;
   1.158 +  }
   1.159 +
   1.160 +  if ( this->th_read_ahead != NULL ) {
   1.161 +  	gst_task_stop( this->th_read_ahead );
   1.162 +  	this->th_read_ahead = NULL;
   1.163 +  }
   1.164  
   1.165    if (this->mythtv_caps) {
   1.166      gst_caps_unref (this->mythtv_caps);
   1.167 @@ -328,19 +336,20 @@
   1.168    /* Loop sending the Myth File Transfer request:
   1.169     * Retry whilst authentication fails and we supply it. */
   1.170    gint len = 0;
   1.171 +  gint8 *data_ptr = g_malloc0( size );
   1.172    
   1.173 -  GST_OBJECT_LOCK(src);
   1.174 +  //GST_OBJECT_LOCK(src);
   1.175  
   1.176    while ( sizetoread > 0 ) {
   1.177  
   1.178      len = gmyth_file_transfer_read( src->file_transfer,
   1.179 -						GST_BUFFER_DATA( *outbuf ) + read, sizetoread, TRUE );
   1.180 +						data_ptr + read, sizetoread, TRUE );
   1.181  
   1.182      if ( len > 0 ) {
   1.183 -      read += len;      
   1.184 +      read += len;
   1.185        sizetoread -= len;
   1.186      } 
   1.187 -    else if ( len <= 0 ) 
   1.188 +    else if ( len <= 0 )
   1.189      {
   1.190      	read = -1;
   1.191  
   1.192 @@ -366,16 +375,15 @@
   1.193  					  goto get_file_pos;
   1.194  					g_print( "\t[%s]\tGET_POSITION: file_position = %lld\n",
   1.195  					    __FUNCTION__, size_tmp );
   1.196 -				    } else if ( abs( src->content_size - src->bytes_read ) < GMYTHTV_TRANSFER_MAX_BUFFER ) {
   1.197 -				      src->prev_content_size = src->content_size;
   1.198 +				    } /*else {				      
   1.199  				      gint64 new_offset = gmyth_file_transfer_get_file_position( src->file_transfer );
   1.200  				      if ( new_offset > 0 && src->content_size <= new_offset ) {
   1.201  								  src->content_size = new_offset;
   1.202  				      } else {
   1.203  								src->update_prog_chain = TRUE;
   1.204  				      }
   1.205 -				    }
   1.206 -				    goto done;
   1.207 +				      src->prev_content_size = src->content_size;
   1.208 +				    }*/
   1.209  				  }
   1.210  			goto done;
   1.211      }
   1.212 @@ -389,19 +397,21 @@
   1.213    if ( read > 0 ) {
   1.214      src->read_offset += read;
   1.215      src->bytes_read += read;
   1.216 -    //src->content_size += src->bytes_read;
   1.217  
   1.218      g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
   1.219 -	"OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read, 
   1.220 -	src->read_offset, src->content_size );
   1.221 +			"OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read, 
   1.222 +			src->read_offset, src->content_size );
   1.223  
   1.224      GST_BUFFER_SIZE (*outbuf) = read; //GST_BUFFER_SIZE (buffer) = read;
   1.225 +    GST_BUFFER_MALLOCDATA( *outbuf ) = g_malloc0( GST_BUFFER_SIZE (*outbuf) );
   1.226 +    GST_BUFFER_DATA( *outbuf ) = GST_BUFFER_MALLOCDATA( *outbuf );
   1.227 +    g_memmove( GST_BUFFER_DATA( *outbuf ), data_ptr, read );
   1.228      GST_BUFFER_OFFSET (*outbuf) = offset; //GST_BUFFER_OFFSET (buffer) = offset;
   1.229      GST_BUFFER_OFFSET_END (*outbuf) = offset + read;//GST_BUFFER_OFFSET_END (buffer) = offset + read;
   1.230  
   1.231      g_print( "Got buffer: [%s]\t\tBUFFER --->SIZE = %d, OFFSET = %llu, "\
   1.232 -	"OFFSET_END = %llu.\n\n", __FUNCTION__, GST_BUFFER_SIZE (*outbuf), 
   1.233 -	GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf) );
   1.234 +			"OFFSET_END = %llu.\n\n", __FUNCTION__, GST_BUFFER_SIZE (*outbuf), 
   1.235 +			GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf) );
   1.236  
   1.237    } else if ( !src->live_tv )
   1.238      goto eos;
   1.239 @@ -412,58 +422,91 @@
   1.240    src->eos = TRUE;
   1.241  
   1.242  done:
   1.243 -  GST_OBJECT_UNLOCK(src);
   1.244 +  //GST_OBJECT_UNLOCK(src);
   1.245  
   1.246    return read;
   1.247  }
   1.248  
   1.249 +#if 0
   1.250  static GstFlowReturn
   1.251  gst_mythtv_src_create ( GstBaseSrc * psrc, guint64 offset, guint size, GstBuffer **outbuf)
   1.252  {
   1.253    GstMythtvSrc *src;
   1.254    GstFlowReturn ret = GST_FLOW_OK;
   1.255    gint read = -1;
   1.256 +  gint adapter_size = -1;
   1.257 +  
   1.258 +  guint max_adapter_rep = 40;
   1.259    
   1.260    src = GST_MYTHTV_SRC (psrc);
   1.261 +  
   1.262    /* The caller should know the number of bytes and not read beyond EOS. */
   1.263    if (G_UNLIKELY (src->eos))
   1.264      goto eos;
   1.265    if ( G_UNLIKELY (src->update_prog_chain) )
   1.266      goto change_progchain;
   1.267 +
   1.268 +  g_static_rec_mutex_lock( src->th_mutex );
   1.269    
   1.270 -  GST_OBJECT_LOCK(src);
   1.271 +  while ( ( ( adapter_size = gst_adapter_available_fast( src->adapter ) ) < size ) &&
   1.272 +  		--max_adapter_rep > 0 )
   1.273 +  {
   1.274 +  	g_print ( "[%s] %d - Waiting for read_ahead task...\n", __FUNCTION__, max_adapter_rep );
   1.275 +  	GST_TASK_WAIT( src->th_read_ahead );
   1.276 +  }
   1.277 +  	
   1.278 +  g_static_rec_mutex_unlock( src->th_mutex );
   1.279  
   1.280 -  if (G_UNLIKELY (src->read_offset != offset)) {
   1.281 -    gint64 new_offset = gmyth_file_transfer_seek(src->file_transfer, offset, SEEK_SET);
   1.282 -    g_print( "[%s] SRC Offset = %lld, NEW actual backend SEEK Offset = %lld.\n",
   1.283 -    	__FUNCTION__, src->read_offset, new_offset );
   1.284 -    if (G_UNLIKELY (new_offset < 0 ) )//|| new_offset != src->read_offset)) {
   1.285 -    {
   1.286 -      GST_OBJECT_UNLOCK(src);
   1.287 -      if ( src->live_tv )
   1.288 -      	goto change_progchain;
   1.289 -      else
   1.290 -      	goto eos;
   1.291 -    }
   1.292 -
   1.293 +	gint64 new_offset = -1;
   1.294 +	/* just get from the adapter, no network effort... */
   1.295 +	if ( offset > src->adapter_offset && size <= adapter_size )	
   1.296 +	{
   1.297 +		
   1.298 +		GstBuffer *buf = gst_adapter_take_buffer( src->adapter, size );
   1.299 +		*outbuf = gst_buffer_create_sub( buf, offset, size );
   1.300 +		src->read_offset = new_offset = offset;
   1.301 +		read = size;
   1.302 +		
   1.303 +		gst_adapter_flush( src->adapter, size );
   1.304 +		
   1.305 +	} else {
   1.306 +		/* no data on adapter... do all these mythtv network calls! */
   1.307 +		
   1.308 +		/* verify if it needs to seek */
   1.309 +		if ( src->read_offset != offset ) 
   1.310 +  	{
   1.311 +		
   1.312 +	  	new_offset = gmyth_file_transfer_seek( src->file_transfer, offset, SEEK_SET );
   1.313 +	  	
   1.314 +	    g_print( "[%s] SRC Offset = %lld, NEW actual backend SEEK Offset = %lld.\n",
   1.315 +	    	__FUNCTION__, src->read_offset, new_offset );
   1.316 +	    if ( G_UNLIKELY (new_offset < 0 ) )
   1.317 +	    {
   1.318 +	      if ( src->live_tv )
   1.319 +	      	goto change_progchain;
   1.320 +	      else
   1.321 +	      	goto eos;
   1.322 +	    }
   1.323 +	    
   1.324 +  	}
   1.325 +	
   1.326      src->read_offset = offset;
   1.327 -  }
   1.328 -  GST_OBJECT_UNLOCK(src);
   1.329 -  
   1.330 -  /* Create the buffer. */
   1.331 -  ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
   1.332 -      src->read_offset, size,
   1.333 -      //src->icy_caps ? src->icy_caps :
   1.334 -      GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf);
   1.335 -
   1.336 -  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
   1.337 -    if ( src->live_tv )
   1.338 -    	goto change_progchain;
   1.339 -    else
   1.340 -    	goto done;
   1.341 -  }
   1.342 -  
   1.343 -  read = do_read_request_response ( src, src->read_offset, size, outbuf );
   1.344 +  	
   1.345 +	  /* Create the buffer. */
   1.346 +	  ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
   1.347 +	      src->read_offset, size,
   1.348 +	      GST_PAD_CAPS ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)) ), outbuf);
   1.349 +	
   1.350 +	  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
   1.351 +	    if ( src->live_tv )
   1.352 +	    	goto change_progchain;
   1.353 +	    else
   1.354 +	    	goto done;
   1.355 +	  }
   1.356 +	  
   1.357 +	  read = do_read_request_response ( src, src->read_offset, size, outbuf ); 
   1.358 +  	
   1.359 +	}
   1.360  
   1.361    if (G_UNLIKELY (src->update_prog_chain) )
   1.362      goto change_progchain;
   1.363 @@ -474,6 +517,29 @@
   1.364      else
   1.365      	goto read_error;
   1.366    }
   1.367 +  
   1.368 +  if ( read > 0 ) {
   1.369 +    src->read_offset += read;
   1.370 +    src->bytes_read += read;
   1.371 +    
   1.372 +    #if 0
   1.373 +    g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
   1.374 +			"OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read, 
   1.375 +			src->read_offset, src->content_size );
   1.376 +
   1.377 +    GST_BUFFER_SIZE (*outbuf) = read; //GST_BUFFER_SIZE (buffer) = read;
   1.378 +    //GST_BUFFER_MALLOCDATA( *outbuf ) = g_malloc0( GST_BUFFER_SIZE (*outbuf) );
   1.379 +    //GST_BUFFER_DATA( *outbuf ) = GST_BUFFER_MALLOCDATA( *outbuf );
   1.380 +    //g_memmove( GST_BUFFER_DATA( *outbuf ), data_ptr, read );
   1.381 +    GST_BUFFER_OFFSET (*outbuf) = offset; //GST_BUFFER_OFFSET (buffer) = offset;
   1.382 +    GST_BUFFER_OFFSET_END (*outbuf) = offset + read;//GST_BUFFER_OFFSET_END (buffer) = offset + read;
   1.383 +
   1.384 +    g_print( "Got buffer: [%s]\t\tBUFFER --->SIZE = %d, OFFSET = %llu, "\
   1.385 +			"OFFSET_END = %llu.\n\n", __FUNCTION__, GST_BUFFER_SIZE (*outbuf), 
   1.386 +			GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf) );
   1.387 +		#endif
   1.388 +			
   1.389 +  }
   1.390  
   1.391  done:
   1.392   {
   1.393 @@ -502,13 +568,101 @@
   1.394      GST_ELEMENT_ERROR (src, RESOURCE, READ,
   1.395  		(NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
   1.396  		  src->uri_name));
   1.397 +		  
   1.398 +		gst_pad_push_event ( GST_BASE_SRC_PAD (GST_BASE_SRC (src)),
   1.399 +  			gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) );
   1.400  		// go to the next program chain
   1.401  		src->unique_setup = FALSE;
   1.402  		src->update_prog_chain = TRUE;
   1.403  		
   1.404 -		//GST_OBJECT_LOCK(src);
   1.405  		gst_mythtv_src_next_program_chain( src );
   1.406 -		//GST_OBJECT_UNLOCK(src);
   1.407 +		
   1.408 +    return GST_FLOW_ERROR_NO_DATA;
   1.409 +  }
   1.410 +
   1.411 +}
   1.412 +#endif
   1.413 +
   1.414 +static GstFlowReturn
   1.415 +gst_mythtv_src_create ( GstPushSrc* psrc, GstBuffer** outbuf )
   1.416 +{
   1.417 +  GstMythtvSrc *src;
   1.418 +  GstFlowReturn ret = GST_FLOW_OK;
   1.419 +  gint read = -1;
   1.420 +  
   1.421 +  src = GST_MYTHTV_SRC ( psrc );
   1.422 +  
   1.423 +  /* The caller should know the number of bytes and not read beyond EOS. */
   1.424 +  if (G_UNLIKELY (src->eos))
   1.425 +    goto eos;
   1.426 +  if ( G_UNLIKELY (src->update_prog_chain) )
   1.427 +    goto change_progchain;
   1.428 +
   1.429 +	//gint64 new_offset = -1;
   1.430 +	/* just get from the adapter, no network effort... */
   1.431 +	//do	
   1.432 +	//{		
   1.433 +	/* Create the buffer. */
   1.434 +  ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
   1.435 +      GST_BUFFER_OFFSET_NONE, MAX_READ_SIZE,
   1.436 +      GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf );
   1.437 +
   1.438 +  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
   1.439 +    if ( src->live_tv )
   1.440 +    	goto change_progchain;
   1.441 +    else
   1.442 +    	goto done;
   1.443 +  }
   1.444 +  
   1.445 +  read = do_read_request_response ( src, src->read_offset, MAX_READ_SIZE, outbuf );	  
   1.446 +  
   1.447 +  if (G_UNLIKELY (src->update_prog_chain) )
   1.448 +    goto change_progchain;
   1.449 +
   1.450 +  if (G_UNLIKELY (read <= 0) || *outbuf == NULL) {
   1.451 +  	if ( src->live_tv )
   1.452 +    	goto change_progchain;
   1.453 +    else
   1.454 +    	goto read_error;
   1.455 +  }
   1.456 +	  							
   1.457 +	//} while ( TRUE );
   1.458 +
   1.459 +done:
   1.460 + {
   1.461 +    const gchar *reason = gst_flow_get_name (ret);
   1.462 +
   1.463 +    GST_DEBUG_OBJECT (src, "DONE task, reason %s", reason);
   1.464 +  	return ret;
   1.465 + }
   1.466 +eos:
   1.467 +  {
   1.468 +    const gchar *reason = gst_flow_get_name (ret);
   1.469 +
   1.470 +    GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
   1.471 +    return GST_FLOW_UNEXPECTED;
   1.472 +  }
   1.473 +  /* ERRORS */
   1.474 +read_error:
   1.475 +  {
   1.476 +    GST_ELEMENT_ERROR (src, RESOURCE, READ,
   1.477 +	(NULL), ("Could not read any bytes (%i, %s)", read,
   1.478 +	  src->uri_name));
   1.479 +    return GST_FLOW_ERROR;
   1.480 +  }
   1.481 +change_progchain:
   1.482 +  {
   1.483 +    GST_ELEMENT_ERROR (src, RESOURCE, READ,
   1.484 +		(NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
   1.485 +		  src->uri_name));
   1.486 +		  
   1.487 +		gst_pad_push_event ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
   1.488 +  			gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) );
   1.489 +		// go to the next program chain
   1.490 +		src->unique_setup = FALSE;
   1.491 +		src->update_prog_chain = TRUE;
   1.492 +		
   1.493 +		gst_mythtv_src_next_program_chain( src );
   1.494  		
   1.495      return GST_FLOW_ERROR_NO_DATA;
   1.496    }
   1.497 @@ -541,6 +695,43 @@
   1.498  
   1.499  }
   1.500  
   1.501 +#if 0
   1.502 +static void 
   1.503 +gst_mythtv_src_read_ahead ( void *data ) {
   1.504 +	
   1.505 +	GstMythtvSrc *src = NULL;
   1.506 +	
   1.507 +	GstBuffer *buffer = NULL;
   1.508 +	
   1.509 +	guint size = 512;
   1.510 +	
   1.511 +	gint read = 0;
   1.512 +	
   1.513 +	src = GST_MYTHTV_SRC( data );
   1.514 +	
   1.515 +	GST_PAD_STREAM_TRYLOCK( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) );
   1.516 +	
   1.517 +	/*if ( gst_adapter_available( src->adapter ) ) && ( read < MAX_READ_SIZE )) */
   1.518 +	do {
   1.519 +		buffer = gst_buffer_new_and_alloc( size );
   1.520 +
   1.521 +		read += do_read_request_response ( src, src->adapter_offset, size, &buffer );
   1.522 +		
   1.523 +		gst_adapter_push( src->adapter, buffer );
   1.524 +		
   1.525 +		//gst_buffer_unref( buffer );		
   1.526 +	} while ( read < MAX_READ_SIZE );
   1.527 +	
   1.528 +	GST_PAD_BLOCK_SIGNAL( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) );
   1.529 +	
   1.530 +	GST_PAD_STREAM_UNLOCK( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) );
   1.531 +	
   1.532 +	gst_object_unref( src );
   1.533 +	
   1.534 +	return;	
   1.535 +}
   1.536 +#endif
   1.537 +
   1.538  /* create a socket for connecting to remote server */
   1.539  static gboolean
   1.540  gst_mythtv_src_start ( GstBaseSrc * bsrc )
   1.541 @@ -560,13 +751,13 @@
   1.542      goto done;
   1.543    }
   1.544  
   1.545 -  GST_OBJECT_LOCK(src);
   1.546 +  //GST_OBJECT_LOCK(src);
   1.547  
   1.548    if ( src->live_tv ) {
   1.549      src->spawn_livetv = gmyth_livetv_new( );
   1.550      if ( gmyth_livetv_setup( src->spawn_livetv ) == FALSE ) {
   1.551        ret = FALSE;
   1.552 -      GST_OBJECT_UNLOCK( src );
   1.553 +      //GST_OBJECT_UNLOCK( src );
   1.554        goto init_failed;
   1.555      }    
   1.556  
   1.557 @@ -585,7 +776,7 @@
   1.558        g_string_new( src->uri_name ), -1, src->mythtv_version );
   1.559  
   1.560    if ( src->file_transfer == NULL ) {
   1.561 -    GST_OBJECT_UNLOCK(src);
   1.562 +    //GST_OBJECT_UNLOCK(src);
   1.563  
   1.564      goto init_failed;
   1.565    }
   1.566 @@ -607,7 +798,7 @@
   1.567    ret = gmyth_file_transfer_setup( &(src->file_transfer), src->live_tv );
   1.568  
   1.569    if ( ret == FALSE ) {
   1.570 -    GST_OBJECT_UNLOCK(src);
   1.571 +    //GST_OBJECT_UNLOCK(src);
   1.572  #ifndef GST_DISABLE_GST_DEBUG  
   1.573      if ( src->mythtv_msgs_dbg )
   1.574        g_printerr( "MythTV FileTransfer request failed when setting up socket connection!\n" );  	  
   1.575 @@ -618,8 +809,14 @@
   1.576    src->content_size = src->file_transfer->filesize;
   1.577  
   1.578    src->do_start = FALSE;
   1.579 +  
   1.580 +  if ( src->live_tv ) {
   1.581 +  	//src->adapter = gst_adapter_new();
   1.582 +  	//g_static_rec_mutex_init( src->th_mutex );
   1.583 +  	//src->th_read_ahead = gst_task_create( (GstTaskFunction)gst_mythtv_src_read_ahead, src );
   1.584 +  }  	
   1.585  
   1.586 -  GST_OBJECT_UNLOCK(src);
   1.587 +  //GST_OBJECT_UNLOCK(src);
   1.588  
   1.589  done:
   1.590    return TRUE;
   1.591 @@ -645,13 +842,15 @@
   1.592      GST_ELEMENT_ERROR (src, RESOURCE, READ,
   1.593  		(NULL), ("Seek failed, go to the next program info... (%s)",
   1.594  		  src->uri_name));
   1.595 +		  
   1.596 +		gst_pad_push_event ( GST_BASE_SRC_PAD (GST_BASE_SRC (src)),
   1.597 +  			gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) );
   1.598 +  			
   1.599  		// go to the next program chain
   1.600  		src->unique_setup = FALSE;
   1.601  		src->update_prog_chain = TRUE;
   1.602  		
   1.603 -		//GST_OBJECT_LOCK(src);
   1.604  		gst_mythtv_src_next_program_chain( src );
   1.605 -		//GST_OBJECT_UNLOCK(src);
   1.606  		
   1.607      return TRUE;
   1.608    }
   1.609 @@ -673,6 +872,8 @@
   1.610    } else {
   1.611      goto done;
   1.612    }
   1.613 +  
   1.614 +	GST_PAD_STREAM_LOCK( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) );
   1.615  
   1.616    if (src->file_transfer) {
   1.617      g_object_unref (src->file_transfer);
   1.618 @@ -748,11 +949,13 @@
   1.619    while ( src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER*4 )
   1.620      src->content_size = gst_mythtv_src_get_position( src );
   1.621  
   1.622 -  src->read_offset = 0;
   1.623 -
   1.624 -  src->update_prog_chain = FALSE;
   1.625 +  src->read_offset = 0;  
   1.626    
   1.627  done:
   1.628 +	src->update_prog_chain = FALSE;
   1.629 +	
   1.630 +	GST_PAD_STREAM_UNLOCK( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) );
   1.631 +	
   1.632    return TRUE;
   1.633  
   1.634    /* ERRORS */
   1.635 @@ -1007,11 +1210,13 @@
   1.636  }
   1.637  #endif
   1.638  
   1.639 +#if 0
   1.640  static gboolean
   1.641  gst_mythtv_src_is_seekable( GstBaseSrc *push_src )
   1.642  {
   1.643    return TRUE;
   1.644  }
   1.645 +#endif
   1.646  
   1.647  #if 0
   1.648  static GstFlowReturn
   1.649 @@ -1172,15 +1377,14 @@
   1.650      case GST_STATE_CHANGE_PAUSED_TO_READY:
   1.651        g_print( "[%s] PAUSED to READY called!\n", __FUNCTION__ );
   1.652        if ( src->live_tv && src->update_prog_chain ) {
   1.653 -      	GstPad *pad_peer;
   1.654 -  			gst_pad_push_event ( pad_peer = gst_pad_get_peer( GST_BASE_SRC_PAD (GST_BASE_SRC (src)) ),
   1.655 -      			gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, -1, 0 ) );
   1.656 +      	
   1.657 +  			gst_pad_push_event ( GST_BASE_SRC_PAD (GST_BASE_SRC (src)),
   1.658 +      			gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) );
   1.659 +
   1.660  				src->read_offset = 0;
   1.661  				src->bytes_read = 0;
   1.662 -				src->unique_setup = FALSE;
   1.663 -				GST_OBJECT_LOCK( src );
   1.664 +				src->unique_setup = FALSE;				
   1.665  				gst_mythtv_src_next_program_chain( src );
   1.666 -				GST_OBJECT_UNLOCK( src );
   1.667        }
   1.668        break;
   1.669      default: