1.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.c Mon Nov 13 19:58:37 2006 +0000
1.2 +++ b/gst-plugins-mythtv/src/gstmythtvsrc.c Thu Nov 16 21:30:58 2006 +0000
1.3 @@ -90,7 +90,9 @@
1.4 static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
1.5 static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
1.6 static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
1.7 -//static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src );
1.8 +static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src );
1.9 +
1.10 +static gboolean gst_mythtv_src_do_seek( GstBaseSrc *base, GstSegment *segment );
1.11
1.12 static gboolean gst_mythtv_src_next_program_chain ( GstMythtvSrc *src );
1.13
1.14 @@ -104,6 +106,8 @@
1.15
1.16 static void gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
1.17
1.18 +static gboolean gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query);
1.19 +
1.20 //static gboolean gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event);
1.21 //static gboolean gst_mythtv_src_query ( GstPad * pad, GstQuery * query );
1.22
1.23 @@ -131,7 +135,7 @@
1.24 GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstPushSrc,
1.25 GST_TYPE_PUSH_SRC, _urihandler_init)
1.26
1.27 - static void
1.28 +static void
1.29 gst_mythtv_src_base_init (gpointer g_class)
1.30 {
1.31 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1.32 @@ -222,9 +226,9 @@
1.33 gstbasesrc_class->start = gst_mythtv_src_start;
1.34 gstbasesrc_class->stop = gst_mythtv_src_stop;
1.35 gstbasesrc_class->get_size = gst_mythtv_src_get_size;
1.36 - //gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
1.37 + gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
1.38
1.39 - //gstbasesrc_class->create = gst_mythtv_src_create;
1.40 + gstbasesrc_class->do_seek = gst_mythtv_src_do_seek;
1.41 gstpushsrc_class->create = gst_mythtv_src_create;
1.42
1.43 GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.44 @@ -271,16 +275,16 @@
1.45 this->th_mutex = NULL;
1.46
1.47 this->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
1.48 - //gst_pad_set_chain_function ( GST_BASE_SRC_PAD( GST_BASE_SRC( this ) ),
1.49 - // GST_DEBUG_FUNCPTR ( gst_mythtv_src_chain ) );
1.50 gst_element_add_pad (GST_ELEMENT (this), this->srcpad);
1.51
1.52 - //gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES );
1.53 + gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES );
1.54
1.55 - gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
1.56 + //gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
1.57
1.58 // gst_pad_set_event_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
1.59 // gst_mythtv_src_handle_event );
1.60 + gst_pad_set_query_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
1.61 + gst_mythtv_src_handle_query );
1.62
1.63 }
1.64
1.65 @@ -338,7 +342,7 @@
1.66 gint len = 0;
1.67 gint8 *data_ptr = g_malloc0( size );
1.68
1.69 - //GST_OBJECT_LOCK(src);
1.70 + GST_OBJECT_LOCK(src);
1.71
1.72 while ( sizetoread > 0 ) {
1.73
1.74 @@ -422,7 +426,7 @@
1.75 src->eos = TRUE;
1.76
1.77 done:
1.78 - //GST_OBJECT_UNLOCK(src);
1.79 + GST_OBJECT_UNLOCK(src);
1.80
1.81 return read;
1.82 }
1.83 @@ -598,13 +602,10 @@
1.84 if ( G_UNLIKELY (src->update_prog_chain) )
1.85 goto change_progchain;
1.86
1.87 - //gint64 new_offset = -1;
1.88 - /* just get from the adapter, no network effort... */
1.89 - //do
1.90 - //{
1.91 - /* Create the buffer. */
1.92 + /* just get from the adapter, no network effort... */
1.93 + /* Create the buffer. */
1.94 ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
1.95 - GST_BUFFER_OFFSET_NONE, MAX_READ_SIZE,
1.96 + src->read_offset /*GST_BUFFER_OFFSET_NONE*/, MAX_READ_SIZE,
1.97 GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf );
1.98
1.99 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1.100 @@ -616,7 +617,7 @@
1.101
1.102 read = do_read_request_response ( src, src->read_offset, MAX_READ_SIZE, outbuf );
1.103
1.104 - if (G_UNLIKELY (src->update_prog_chain) )
1.105 + if ( G_UNLIKELY (src->update_prog_chain) )
1.106 goto change_progchain;
1.107
1.108 if (G_UNLIKELY (read <= 0) || *outbuf == NULL) {
1.109 @@ -625,8 +626,6 @@
1.110 else
1.111 goto read_error;
1.112 }
1.113 -
1.114 - //} while ( TRUE );
1.115
1.116 done:
1.117 {
1.118 @@ -695,6 +694,64 @@
1.119
1.120 }
1.121
1.122 +static gboolean
1.123 +gst_mythtv_src_do_seek( GstBaseSrc *base, GstSegment *segment )
1.124 +{
1.125 + GstMythtvSrc *src = GST_MYTHTV_SRC( base );
1.126 + gint64 new_offset = 0;
1.127 + gboolean ret = TRUE;
1.128 +
1.129 + g_print( "[%s]DO Seek called! (start = %lld, stop = %lld)\n", __FUNCTION__, segment->start, segment->stop );
1.130 +
1.131 + /* verify if it needs to seek */
1.132 + if ( src->read_offset != segment->start )
1.133 + {
1.134 +
1.135 + new_offset = gmyth_file_transfer_seek( src->file_transfer, segment->start, SEEK_SET );
1.136 +
1.137 + g_print( "[%s] Segment offset start = %lld, SRC Offset = %lld, NEW actual backend SEEK Offset = %lld.\n",
1.138 + __FUNCTION__, segment->start, src->read_offset, new_offset );
1.139 + if ( G_UNLIKELY (new_offset < 0 ) )
1.140 + {
1.141 + ret = FALSE;
1.142 + if ( src->live_tv )
1.143 + goto change_progchain;
1.144 + else
1.145 + goto eos;
1.146 + }
1.147 +
1.148 + src->read_offset = new_offset;
1.149 +
1.150 + }
1.151 +
1.152 + return ret;
1.153 +
1.154 +eos:
1.155 + {
1.156 +
1.157 + GST_DEBUG_OBJECT (src, "EOS found on seeking!!!");
1.158 + gst_object_unref( src );
1.159 + return FALSE;
1.160 + }
1.161 +change_progchain:
1.162 + {
1.163 + GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.164 + (NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
1.165 + src->uri_name));
1.166 +
1.167 + gst_pad_push_event ( GST_BASE_SRC_PAD (base),
1.168 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) );
1.169 + /* go to the next program chain */
1.170 + src->unique_setup = FALSE;
1.171 + src->update_prog_chain = TRUE;
1.172 +
1.173 + gst_mythtv_src_next_program_chain( src );
1.174 +
1.175 + return TRUE;
1.176 + }
1.177 +
1.178 +}
1.179 +
1.180 #if 0
1.181 static void
1.182 gst_mythtv_src_read_ahead ( void *data ) {
1.183 @@ -814,7 +871,9 @@
1.184 //src->adapter = gst_adapter_new();
1.185 //g_static_rec_mutex_init( src->th_mutex );
1.186 //src->th_read_ahead = gst_task_create( (GstTaskFunction)gst_mythtv_src_read_ahead, src );
1.187 - }
1.188 + }
1.189 + //gst_pad_push_event ( GST_BASE_SRC_PAD (bsrc),
1.190 + // gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, src->content_size, 0 ) );
1.191
1.192 //GST_OBJECT_UNLOCK(src);
1.193
1.194 @@ -946,8 +1005,11 @@
1.195 #endif
1.196
1.197 src->content_size = src->file_transfer->filesize;
1.198 - while ( src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER*4 )
1.199 - src->content_size = gst_mythtv_src_get_position( src );
1.200 + if ( src->live_tv ) {
1.201 + wait_to_transfer = 0;
1.202 + while ( wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER )
1.203 + src->content_size = gst_mythtv_src_get_position( src );
1.204 + }
1.205
1.206 src->read_offset = 0;
1.207
1.208 @@ -977,74 +1039,6 @@
1.209
1.210 }
1.211
1.212 -#if 0
1.213 -/* handles queries for location in the stream in the requested format */
1.214 -static gboolean
1.215 -gst_mythtv_src_query ( GstPad * pad, GstQuery * query )
1.216 -{
1.217 - gboolean res = TRUE;
1.218 - GstMythtvSrc *mythtv;
1.219 -
1.220 - guint64 size = 0;
1.221 -
1.222 - mythtv = GST_GMYTHTV_SRC( GST_PAD_PARENT (pad) );
1.223 -
1.224 - size = gst_mythtv_src_get_position (mythtv);
1.225 -
1.226 - switch (GST_QUERY_TYPE (query)) {
1.227 -
1.228 - case GST_QUERY_POSITION:
1.229 - {
1.230 -
1.231 - //GstFormat format;
1.232 - gint64 cur = 0;
1.233 -
1.234 - /* save requested format */
1.235 - gst_query_parse_position (query, NULL, &cur);
1.236 -
1.237 - /* query peer for current position in time */
1.238 - g_print( "[%s] Actual size is %s than current size from sink. [ %lld, %lld ]\n", __FUNCTION__,
1.239 - ( size > cur ) ? "greater" : "lower", size, cur );
1.240 - gst_query_set_position (query, GST_FORMAT_BYTES, size);
1.241 - if ( size < cur )
1.242 - goto error;
1.243 -
1.244 - break;
1.245 - }
1.246 - #if 0
1.247 - case GST_QUERY_DURATION:
1.248 - {
1.249 - //GstFormat format;
1.250 - gint64 cur = 0;
1.251 -
1.252 - /* save requested format */
1.253 - gst_query_parse_position (query, NULL, &cur);
1.254 -
1.255 - /* query peer for current position in time */
1.256 - g_print( "[%s] Actual size is %s than current size from sink. [ %lld, %lld ]\n", __FUNCTION__,
1.257 - ( size * GST_SECOND > cur * GST_SECOND ) ? "greater" : "lower", size * GST_SECOND,
1.258 - cur * GST_SECOND );
1.259 - gst_query_set_position (query, GST_FORMAT_TIME, size * GST_SECOND );
1.260 -
1.261 - if ( size * GST_SECOND < cur * GST_SECOND )
1.262 - goto error;
1.263 -
1.264 - break;
1.265 - }
1.266 - #endif
1.267 - default:
1.268 - res = FALSE;
1.269 - break;
1.270 - }
1.271 -
1.272 - return res;
1.273 -
1.274 -error:
1.275 -
1.276 - return FALSE;
1.277 -}
1.278 -#endif
1.279 -
1.280 static gboolean
1.281 gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1.282 {
1.283 @@ -1053,8 +1047,8 @@
1.284 g_print( "[%s] Differs from previous content size: %d (max.: %d)\n", __FUNCTION__,
1.285 abs( src->content_size - src->prev_content_size ), GMYTHTV_TRANSFER_MAX_BUFFER );
1.286
1.287 - if (src->content_size <= 0) {
1.288 - ret= FALSE;
1.289 + if (src->content_size == -1) {
1.290 + //ret= FALSE;
1.291 } else if ( src->live_tv && ( abs( src->content_size - src->bytes_read ) <
1.292 GMYTHTV_TRANSFER_MAX_BUFFER ) ) {
1.293 //g_static_mutex_lock( &update_size_mutex );
1.294 @@ -1090,7 +1084,7 @@
1.295
1.296 *size = src->content_size;
1.297 g_print( "[%s] Content size = %lld\n", __FUNCTION__, src->content_size );
1.298 -
1.299 +
1.300 return ret;
1.301
1.302 }
1.303 @@ -1210,155 +1204,62 @@
1.304 }
1.305 #endif
1.306
1.307 -#if 0
1.308 static gboolean
1.309 gst_mythtv_src_is_seekable( GstBaseSrc *push_src )
1.310 {
1.311 return TRUE;
1.312 }
1.313 +
1.314 +static gboolean
1.315 +gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query)
1.316 +{
1.317 + gboolean res = FALSE;
1.318 + GstMythtvSrc *myth = GST_MYTHTV_SRC (gst_pad_get_parent (pad));
1.319 +
1.320 + switch (GST_QUERY_TYPE (query)) {
1.321 + case GST_QUERY_POSITION:
1.322 + gst_query_set_position (query, GST_FORMAT_BYTES,
1.323 + myth->read_offset );
1.324 + res = TRUE;
1.325 + GST_DEBUG_OBJECT (myth, "POS %d", myth->read_offset);
1.326 + break;
1.327 + case GST_QUERY_DURATION:
1.328 +#if 0
1.329 + if (myth->duration != 0) {
1.330 + gint64 total;
1.331 + gint64 fps;
1.332 +
1.333 + fps = nuv->h->i_fpsn / nuv->h->i_fpsd;
1.334 + total = gst_util_uint64_scale_int (GST_SECOND, nuv->h->i_video_blocks, fps);
1.335 #endif
1.336 -
1.337 -#if 0
1.338 -static GstFlowReturn
1.339 -gst_mythtv_src_file_transfer( GstMythtvSrc *src )
1.340 -{
1.341 - GstFlowReturn ret = GST_FLOW_OK;
1.342 - GstBuffer *buf = NULL;
1.343 - gint read = -1;
1.344 -
1.345 - /* The caller should know the number of bytes and not read beyond EOS. */
1.346 - if ( G_UNLIKELY (src->eos) )
1.347 - goto eos;
1.348 - if ( G_UNLIKELY (src->update_prog_chain) )
1.349 - goto change_progchain;
1.350 -
1.351 - do {
1.352 -
1.353 - /* Create the buffer. */
1.354 - buf = gst_buffer_new_and_alloc (4096);
1.355 -
1.356 - ret = gst_mythtv_src_read_bytes( src, GST_BUFFER_SIZE(buf), TRUE, &buf );
1.357 - if ( ret != GST_FLOW_OK )
1.358 - return ret;
1.359 -
1.360 - read = do_read_request_response ( src, src->read_offset, GST_BUFFER_SIZE(buf), &buf );
1.361 -
1.362 - if (G_UNLIKELY (src->update_prog_chain) )
1.363 - goto change_progchain;
1.364 -
1.365 - if (G_UNLIKELY (read <= 0) || buf == NULL) {
1.366 - if ( src->live_tv )
1.367 - goto change_progchain;
1.368 - else
1.369 - goto read_error;
1.370 - }
1.371 -
1.372 - if ( GST_FLOW_OK != ( ret = gst_pad_push ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), buf ) ) ) {
1.373 - goto done;
1.374 - }
1.375 -
1.376 - } while(TRUE);
1.377 -
1.378 -done:
1.379 - {
1.380 - const gchar *reason = gst_flow_get_name (ret);
1.381 -
1.382 - GST_DEBUG_OBJECT (src, "DONE task, reason %s", reason);
1.383 - return ret;
1.384 - }
1.385 -eos:
1.386 - {
1.387 - const gchar *reason = gst_flow_get_name (ret);
1.388 -
1.389 - GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
1.390 - return GST_FLOW_UNEXPECTED;
1.391 - }
1.392 - /* ERRORS */
1.393 -read_error:
1.394 - {
1.395 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.396 - (NULL), ("Could not read any bytes (%i, %s)", read,
1.397 - src->uri_name));
1.398 - return GST_FLOW_ERROR;
1.399 - }
1.400 -change_progchain:
1.401 - {
1.402 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.403 - (NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
1.404 - src->uri_name));
1.405 - // go to the next program chain
1.406 - src->unique_setup = FALSE;
1.407 - src->update_prog_chain = TRUE;
1.408 - src->mode = GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN;
1.409 -
1.410 - //GST_OBJECT_LOCK(src);
1.411 - //gst_mythtv_src_next_program_chain( src );
1.412 - //GST_OBJECT_UNLOCK(src);
1.413 - return GST_FLOW_OK;//GST_FLOW_ERROR_NO_DATA;
1.414 - }
1.415 -}
1.416 -
1.417 -static GstFlowReturn
1.418 -gst_mythtv_src_play (GstPad * pad)
1.419 -{
1.420 - GstFlowReturn res = GST_FLOW_OK;
1.421 - GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
1.422 -
1.423 - switch ( src->state ) {
1.424 - case GST_MYTHTV_SRC_FILE_TRANSFER:
1.425 - res = gst_mythtv_src_file_transfer( src );
1.426 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.427 - goto pause;
1.428 - }
1.429 - break;
1.430 - case GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN:
1.431 - src->read_offset = 0;
1.432 - src->bytes_read = 0;
1.433 - src->unique_setup = FALSE;
1.434 - if ( !gst_mythtv_src_next_program_chain( src ) ) {
1.435 - goto pause;
1.436 - }
1.437 - src->state = GST_MYTHTV_SRC_FILE_TRANSFER;
1.438 - break;
1.439 - case GST_MYTHTV_SRC_INVALID_DATA:
1.440 - goto pause;
1.441 + //gst_query_set_duration (query, GST_FORMAT_TIME, myth->content_size);
1.442 + GST_DEBUG_OBJECT (myth, "DURATION %d", myth->content_size);
1.443 + res = FALSE;
1.444 break;
1.445 default:
1.446 - g_assert_not_reached ();
1.447 + res = FALSE;
1.448 + break;
1.449 }
1.450
1.451 - GST_DEBUG_OBJECT (src, "state: %d res:%s", src->state,
1.452 - gst_flow_get_name (res));
1.453 + gst_object_unref (myth);
1.454
1.455 - return GST_FLOW_OK;
1.456 -
1.457 -pause:
1.458 - GST_LOG_OBJECT (src, "pausing task, reason %s", gst_flow_get_name (res));
1.459 - gst_pad_pause_task (src->srcpad);
1.460 - if (GST_FLOW_IS_FATAL (res)) {
1.461 - GST_ELEMENT_ERROR (src, STREAM, FAILED,
1.462 - ("Internal data stream error."),
1.463 - ("streaming stopped, reason %s", gst_flow_get_name (res)));
1.464 - gst_pad_send_event( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), gst_event_new_eos() );
1.465 - }
1.466 return res;
1.467 }
1.468 -#endif
1.469
1.470 static GstStateChangeReturn
1.471 gst_mythtv_src_change_state (GstElement * element, GstStateChange transition)
1.472 {
1.473 - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;//GST_STATE_CHANGE_NO_PREROLL;
1.474 + GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;//GST_STATE_CHANGE_NO_PREROLL;
1.475 GstMythtvSrc *src = GST_MYTHTV_SRC (element);
1.476
1.477 switch (transition) {
1.478 case GST_STATE_CHANGE_NULL_TO_READY:
1.479 - src->do_start = TRUE;
1.480 - src->unique_setup = FALSE;
1.481 + //src->do_start = TRUE;
1.482 + //src->unique_setup = FALSE;
1.483 break;
1.484 case GST_STATE_CHANGE_READY_TO_PAUSED:
1.485 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1.486 - src->eos = FALSE;
1.487 + //src->eos = FALSE;
1.488 break;
1.489 default:
1.490 break;
1.491 @@ -1603,7 +1504,7 @@
1.492 return TRUE;
1.493 }
1.494
1.495 - static void
1.496 + static void
1.497 gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
1.498 {
1.499 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;