diff -r 56e39289fa96 -r edcd63c2ac77 gst-plugins-mythtv/src/gstmythtvsrc.c --- a/gst-plugins-mythtv/src/gstmythtvsrc.c Mon Nov 13 19:58:37 2006 +0000 +++ b/gst-plugins-mythtv/src/gstmythtvsrc.c Thu Nov 16 21:30:58 2006 +0000 @@ -90,7 +90,9 @@ static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc); static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc); static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size); -//static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src ); +static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src ); + +static gboolean gst_mythtv_src_do_seek( GstBaseSrc *base, GstSegment *segment ); static gboolean gst_mythtv_src_next_program_chain ( GstMythtvSrc *src ); @@ -104,6 +106,8 @@ static void gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data); +static gboolean gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query); + //static gboolean gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event); //static gboolean gst_mythtv_src_query ( GstPad * pad, GstQuery * query ); @@ -131,7 +135,7 @@ GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstPushSrc, GST_TYPE_PUSH_SRC, _urihandler_init) - static void +static void gst_mythtv_src_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); @@ -222,9 +226,9 @@ gstbasesrc_class->start = gst_mythtv_src_start; gstbasesrc_class->stop = gst_mythtv_src_stop; gstbasesrc_class->get_size = gst_mythtv_src_get_size; - //gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable; + gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable; - //gstbasesrc_class->create = gst_mythtv_src_create; + gstbasesrc_class->do_seek = gst_mythtv_src_do_seek; gstpushsrc_class->create = gst_mythtv_src_create; GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0, @@ -271,16 +275,16 @@ this->th_mutex = NULL; this->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - //gst_pad_set_chain_function ( GST_BASE_SRC_PAD( GST_BASE_SRC( this ) ), - // GST_DEBUG_FUNCPTR ( gst_mythtv_src_chain ) ); gst_element_add_pad (GST_ELEMENT (this), this->srcpad); - //gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES ); + gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES ); - gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE ); + //gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE ); // gst_pad_set_event_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)), // gst_mythtv_src_handle_event ); + gst_pad_set_query_function ( GST_BASE_SRC_PAD(GST_BASE_SRC(this)), + gst_mythtv_src_handle_query ); } @@ -338,7 +342,7 @@ gint len = 0; gint8 *data_ptr = g_malloc0( size ); - //GST_OBJECT_LOCK(src); + GST_OBJECT_LOCK(src); while ( sizetoread > 0 ) { @@ -422,7 +426,7 @@ src->eos = TRUE; done: - //GST_OBJECT_UNLOCK(src); + GST_OBJECT_UNLOCK(src); return read; } @@ -598,13 +602,10 @@ if ( G_UNLIKELY (src->update_prog_chain) ) goto change_progchain; - //gint64 new_offset = -1; - /* just get from the adapter, no network effort... */ - //do - //{ - /* Create the buffer. */ + /* just get from the adapter, no network effort... */ + /* Create the buffer. */ ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), - GST_BUFFER_OFFSET_NONE, MAX_READ_SIZE, + src->read_offset /*GST_BUFFER_OFFSET_NONE*/, MAX_READ_SIZE, GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf ); if (G_UNLIKELY (ret != GST_FLOW_OK)) { @@ -616,7 +617,7 @@ read = do_read_request_response ( src, src->read_offset, MAX_READ_SIZE, outbuf ); - if (G_UNLIKELY (src->update_prog_chain) ) + if ( G_UNLIKELY (src->update_prog_chain) ) goto change_progchain; if (G_UNLIKELY (read <= 0) || *outbuf == NULL) { @@ -625,8 +626,6 @@ else goto read_error; } - - //} while ( TRUE ); done: { @@ -695,6 +694,64 @@ } +static gboolean +gst_mythtv_src_do_seek( GstBaseSrc *base, GstSegment *segment ) +{ + GstMythtvSrc *src = GST_MYTHTV_SRC( base ); + gint64 new_offset = 0; + gboolean ret = TRUE; + + g_print( "[%s]DO Seek called! (start = %lld, stop = %lld)\n", __FUNCTION__, segment->start, segment->stop ); + + /* verify if it needs to seek */ + if ( src->read_offset != segment->start ) + { + + new_offset = gmyth_file_transfer_seek( src->file_transfer, segment->start, SEEK_SET ); + + g_print( "[%s] Segment offset start = %lld, SRC Offset = %lld, NEW actual backend SEEK Offset = %lld.\n", + __FUNCTION__, segment->start, src->read_offset, new_offset ); + if ( G_UNLIKELY (new_offset < 0 ) ) + { + ret = FALSE; + if ( src->live_tv ) + goto change_progchain; + else + goto eos; + } + + src->read_offset = new_offset; + + } + + return ret; + +eos: + { + + GST_DEBUG_OBJECT (src, "EOS found on seeking!!!"); + gst_object_unref( src ); + return FALSE; + } +change_progchain: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, + (NULL), ("Seek failed, go to the next program info... (%i, %s)", read, + src->uri_name)); + + gst_pad_push_event ( GST_BASE_SRC_PAD (base), + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0 ) ); + /* go to the next program chain */ + src->unique_setup = FALSE; + src->update_prog_chain = TRUE; + + gst_mythtv_src_next_program_chain( src ); + + return TRUE; + } + +} + #if 0 static void gst_mythtv_src_read_ahead ( void *data ) { @@ -814,7 +871,9 @@ //src->adapter = gst_adapter_new(); //g_static_rec_mutex_init( src->th_mutex ); //src->th_read_ahead = gst_task_create( (GstTaskFunction)gst_mythtv_src_read_ahead, src ); - } + } + //gst_pad_push_event ( GST_BASE_SRC_PAD (bsrc), + // gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, src->content_size, 0 ) ); //GST_OBJECT_UNLOCK(src); @@ -946,8 +1005,11 @@ #endif src->content_size = src->file_transfer->filesize; - while ( src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER*4 ) - src->content_size = gst_mythtv_src_get_position( src ); + if ( src->live_tv ) { + wait_to_transfer = 0; + while ( wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER ) + src->content_size = gst_mythtv_src_get_position( src ); + } src->read_offset = 0; @@ -977,74 +1039,6 @@ } -#if 0 -/* handles queries for location in the stream in the requested format */ -static gboolean -gst_mythtv_src_query ( GstPad * pad, GstQuery * query ) -{ - gboolean res = TRUE; - GstMythtvSrc *mythtv; - - guint64 size = 0; - - mythtv = GST_GMYTHTV_SRC( GST_PAD_PARENT (pad) ); - - size = gst_mythtv_src_get_position (mythtv); - - switch (GST_QUERY_TYPE (query)) { - - case GST_QUERY_POSITION: - { - - //GstFormat format; - gint64 cur = 0; - - /* save requested format */ - gst_query_parse_position (query, NULL, &cur); - - /* query peer for current position in time */ - g_print( "[%s] Actual size is %s than current size from sink. [ %lld, %lld ]\n", __FUNCTION__, - ( size > cur ) ? "greater" : "lower", size, cur ); - gst_query_set_position (query, GST_FORMAT_BYTES, size); - if ( size < cur ) - goto error; - - break; - } - #if 0 - case GST_QUERY_DURATION: - { - //GstFormat format; - gint64 cur = 0; - - /* save requested format */ - gst_query_parse_position (query, NULL, &cur); - - /* query peer for current position in time */ - g_print( "[%s] Actual size is %s than current size from sink. [ %lld, %lld ]\n", __FUNCTION__, - ( size * GST_SECOND > cur * GST_SECOND ) ? "greater" : "lower", size * GST_SECOND, - cur * GST_SECOND ); - gst_query_set_position (query, GST_FORMAT_TIME, size * GST_SECOND ); - - if ( size * GST_SECOND < cur * GST_SECOND ) - goto error; - - break; - } - #endif - default: - res = FALSE; - break; - } - - return res; - -error: - - return FALSE; -} -#endif - static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size) { @@ -1053,8 +1047,8 @@ g_print( "[%s] Differs from previous content size: %d (max.: %d)\n", __FUNCTION__, abs( src->content_size - src->prev_content_size ), GMYTHTV_TRANSFER_MAX_BUFFER ); - if (src->content_size <= 0) { - ret= FALSE; + if (src->content_size == -1) { + //ret= FALSE; } else if ( src->live_tv && ( abs( src->content_size - src->bytes_read ) < GMYTHTV_TRANSFER_MAX_BUFFER ) ) { //g_static_mutex_lock( &update_size_mutex ); @@ -1090,7 +1084,7 @@ *size = src->content_size; g_print( "[%s] Content size = %lld\n", __FUNCTION__, src->content_size ); - + return ret; } @@ -1210,155 +1204,62 @@ } #endif -#if 0 static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *push_src ) { return TRUE; } + +static gboolean +gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query) +{ + gboolean res = FALSE; + GstMythtvSrc *myth = GST_MYTHTV_SRC (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + gst_query_set_position (query, GST_FORMAT_BYTES, + myth->read_offset ); + res = TRUE; + GST_DEBUG_OBJECT (myth, "POS %d", myth->read_offset); + break; + case GST_QUERY_DURATION: +#if 0 + if (myth->duration != 0) { + gint64 total; + gint64 fps; + + fps = nuv->h->i_fpsn / nuv->h->i_fpsd; + total = gst_util_uint64_scale_int (GST_SECOND, nuv->h->i_video_blocks, fps); #endif - -#if 0 -static GstFlowReturn -gst_mythtv_src_file_transfer( GstMythtvSrc *src ) -{ - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *buf = NULL; - gint read = -1; - - /* The caller should know the number of bytes and not read beyond EOS. */ - if ( G_UNLIKELY (src->eos) ) - goto eos; - if ( G_UNLIKELY (src->update_prog_chain) ) - goto change_progchain; - - do { - - /* Create the buffer. */ - buf = gst_buffer_new_and_alloc (4096); - - ret = gst_mythtv_src_read_bytes( src, GST_BUFFER_SIZE(buf), TRUE, &buf ); - if ( ret != GST_FLOW_OK ) - return ret; - - read = do_read_request_response ( src, src->read_offset, GST_BUFFER_SIZE(buf), &buf ); - - if (G_UNLIKELY (src->update_prog_chain) ) - goto change_progchain; - - if (G_UNLIKELY (read <= 0) || buf == NULL) { - if ( src->live_tv ) - goto change_progchain; - else - goto read_error; - } - - if ( GST_FLOW_OK != ( ret = gst_pad_push ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), buf ) ) ) { - goto done; - } - - } while(TRUE); - -done: - { - const gchar *reason = gst_flow_get_name (ret); - - GST_DEBUG_OBJECT (src, "DONE task, reason %s", reason); - return ret; - } -eos: - { - const gchar *reason = gst_flow_get_name (ret); - - GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason); - return GST_FLOW_UNEXPECTED; - } - /* ERRORS */ -read_error: - { - GST_ELEMENT_ERROR (src, RESOURCE, READ, - (NULL), ("Could not read any bytes (%i, %s)", read, - src->uri_name)); - return GST_FLOW_ERROR; - } -change_progchain: - { - GST_ELEMENT_ERROR (src, RESOURCE, READ, - (NULL), ("Seek failed, go to the next program info... (%i, %s)", read, - src->uri_name)); - // go to the next program chain - src->unique_setup = FALSE; - src->update_prog_chain = TRUE; - src->mode = GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN; - - //GST_OBJECT_LOCK(src); - //gst_mythtv_src_next_program_chain( src ); - //GST_OBJECT_UNLOCK(src); - return GST_FLOW_OK;//GST_FLOW_ERROR_NO_DATA; - } -} - -static GstFlowReturn -gst_mythtv_src_play (GstPad * pad) -{ - GstFlowReturn res = GST_FLOW_OK; - GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad)); - - switch ( src->state ) { - case GST_MYTHTV_SRC_FILE_TRANSFER: - res = gst_mythtv_src_file_transfer( src ); - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { - goto pause; - } - break; - case GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN: - src->read_offset = 0; - src->bytes_read = 0; - src->unique_setup = FALSE; - if ( !gst_mythtv_src_next_program_chain( src ) ) { - goto pause; - } - src->state = GST_MYTHTV_SRC_FILE_TRANSFER; - break; - case GST_MYTHTV_SRC_INVALID_DATA: - goto pause; + //gst_query_set_duration (query, GST_FORMAT_TIME, myth->content_size); + GST_DEBUG_OBJECT (myth, "DURATION %d", myth->content_size); + res = FALSE; break; default: - g_assert_not_reached (); + res = FALSE; + break; } - GST_DEBUG_OBJECT (src, "state: %d res:%s", src->state, - gst_flow_get_name (res)); + gst_object_unref (myth); - return GST_FLOW_OK; - -pause: - GST_LOG_OBJECT (src, "pausing task, reason %s", gst_flow_get_name (res)); - gst_pad_pause_task (src->srcpad); - if (GST_FLOW_IS_FATAL (res)) { - GST_ELEMENT_ERROR (src, STREAM, FAILED, - ("Internal data stream error."), - ("streaming stopped, reason %s", gst_flow_get_name (res))); - gst_pad_send_event( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), gst_event_new_eos() ); - } return res; } -#endif static GstStateChangeReturn gst_mythtv_src_change_state (GstElement * element, GstStateChange transition) { - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;//GST_STATE_CHANGE_NO_PREROLL; + GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;//GST_STATE_CHANGE_NO_PREROLL; GstMythtvSrc *src = GST_MYTHTV_SRC (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - src->do_start = TRUE; - src->unique_setup = FALSE; + //src->do_start = TRUE; + //src->unique_setup = FALSE; break; case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - src->eos = FALSE; + //src->eos = FALSE; break; default: break; @@ -1603,7 +1504,7 @@ return TRUE; } - static void + static void gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data) { GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;