Ohhhh Shean, that hurt!
Oh well, if we must,
Here is my something , to you , to help you learn...
so, in the codebase there is a file subscriptions.c in which the following <snippet> of code can be seen for a function "subscription_reschedule" ..
/**
/
void
subscription_reschedule(void)
{
static int reenter = 0;
th_subscription_t
s;
service_t t;
service_instance_t
si;
streaming_message_t sm;
int error, postpone = INT_MAX, postpone2;
assert(reenter == 0);
reenter = 1;
lock_assert(&global_lock);
LIST_FOREACH(s, &subscriptions, ths_global_link) {
if (!s->ths_service && !s->ths_channel) continue;
if (s->ths_flags & SUBSCRIPTION_ONESHOT) continue;
/* Postpone the tuner decision
/
/ Leave some time to wakeup tuners through DBus or so
/
if (s->ths_postpone_end > mclk()) {
postpone2 = mono2sec(s->ths_postpone_end - mclk());
if (postpone > postpone2)
postpone = postpone2;
sm = streaming_msg_create_code(SMT_GRACE, postpone + 5);
streaming_target_deliver(s->ths_output, sm);
continue;
}
t = s->ths_service;
if(t != NULL && s->ths_current_instance != NULL) {
/ Already got a service
/
if(subgetstate(s) != SUBSCRIPTION_BAD_SERVICE)
continue; / And it not bad, so we're happy
/
tvhwarn(LS_SUBSCRIPTION, "%04X: service instance is bad, reason: %s",
shortid(s), streaming_code2txt(s->ths_testing_error));
t->s_streaming_status = 0;
t->s_status = SERVICE_IDLE;
si = s->ths_current_instance;
assert(si != NULL);
subscription_unlink_service0(s, SM_CODE_BAD_SOURCE, 0);
si->si_error = s->ths_testing_error;
time(&si->si_error_time);
if (!s->ths_channel)
s->ths_service = si->si_s;
s->ths_last_error = 0;
}
error = s->ths_testing_error;
si = subscription_start_instance(s, &error);
s->ths_current_instance = si;
if(si == NULL) {
if (s->ths_last_error != error || s->ths_last_find + sec2mono(2) >= mclk()) {
tvhtrace(LS_SUBSCRIPTION, "%04X: instance not available, retrying", shortid(s));
if (s->ths_last_error != error)
s->ths_last_find = mclk();
s->ths_last_error = error;
continue;
}
if (s->ths_flags & SUBSCRIPTION_RESTART) {
if (s->ths_channel)
tvhwarn(LS_SUBSCRIPTION, "%04X: restarting channel %s",
shortid(s), channel_get_name(s->ths_channel));
else
tvhwarn(LS_SUBSCRIPTION, "%04X: restarting service %s",
shortid(s), s->ths_service->s_nicename);
s->ths_testing_error = 0;
s->ths_current_instance = NULL;
service_instance_list_clear(&s->ths_instances);
sm = streaming_msg_create_code(SMT_NOSTART_WARN, error);
streaming_target_deliver(s->ths_output, sm);
continue;
}
/ No service available
/
sm = streaming_msg_create_code(SMT_NOSTART, error);
streaming_target_deliver(s->ths_output, sm);
subscription_show_none(s);
continue;
}
subscription_link_service(s, si->si_s);
subscription_show_info(s);
}
while ((s = LIST_FIRST(&subscriptions_remove)))
subscription_unsubscribe(s, 0);
if (postpone <= 0 || postpone == INT_MAX)
postpone = 2;
mtimer_arm_rel(&subscription_reschedule_timer,
subscription_reschedule_cb, NULL, sec2mono(postpone));
reenter = 0;
}
So what this does it basically set a +5 second counter from subscribing to a mux to scan for services. This is the bug-bear for me, because of all the reasons I set out above. What this basically does is lock in a 5 second timeout (in fact it appears to be a 5 second timer not timeout) that must elapse prior to a mux being deemed providing a service (there will only be one per http link in a m3u list of http links, where each link is in fact a channel.
So what?
It appears that some grace time is introduced before the message adding a stream input is created, for every mux scan; TVH creates a mux for every http link (again uncessessary but understandable as the devs had to knife and fork IPTV into existing evolved TVH architecture). TVH passes mutexed messages around to invoke/terminate certain internal functions - quite a good and proven coding methodology.
And i want to make the point here , that some of you lot [well two of you!] keep pushing this nonsense that i am requesting TVH to work the way I want it to, but in fact the reality is that many users will want the same functionality. You can - as I did - even find posts on this VERY forum where members are asking for improved IPTV function surrounding the completely irrelevant use of muxes & sevices - for IPTV. Im sorry to be the bearer of bad news but muxes and services are COMPLETELY irrelevant for IPTV - you do not need to "scan" IPTV as you do for DVB cards across Dbus. It is complete hogwash to suggest that TVH "needs to do this" . Technically, it does not. Period! The reason I suspect the devs "chose" this was infact nothing to do with IPTV per-se but more to do with the architecture of TVH that has evolved over years from DVB card use, where and completely ligitimately, muxers and services are indeed managed through IOCTL across hardware. This is simply NOT the case for (http) IPTV streams where the http layer functionality has everything needed. If one must "scan" a service then all that needs to be done is "tune" to the channel (http link) and decode the PMT/PMA headers to determine a working .ts stream (mpegts). But even then there is an arugment that says "Im not bothered if the channel is online right now, just bloody create the channel so I can watch it later/in future". That is the users perogative if they choose to have this behaviour, i.e. give them everything on offer in the m3u - blindly.
Right, point made, lets get back to that code above. So around 2 seconds (more like upto 5 on my box) per channel to unneccessarily scan for a service. Lets say 3 seconds for each, well at 500 channels (not uncommon if you have UK, USA, Canada, Australia IPTV) well thats around 2,500 seconds to complete the mux scan - FORTY ONE MINUTES ! This is silly for users who want to provide a m3u and just have the channel list "appear" as per DVBLink and MythTV altough mythTV is slow but nowhere near as slow as TVH in creating the channel list.
So what can we do,
well ,
lots of things possible but I would go for just not adding the grace time when dealing with a mpegts mux. This would avoid rewriting much of the code and carry on in the manner the devs have already, to bring IPTV functionality code in. Quite simply then ,to set all timeouts and grace periods for http streams to zero.
Another option is to not create the stream message at all, and just link the mux to a service. This is the code that does this, again from subscriptions.c:-
subscription_link_service(th_subscription_t s, service_t
t)
{
streaming_message_t sm;
subsetstate(s, SUBSCRIPTION_TESTING_SERVICE);
s->ths_service = t;
LIST_INSERT_HEAD(&t->s_subscriptions, s, ths_service_link);
tvhtrace(LS_SUBSCRIPTION, "%04X: linking sub %p to svc %p type %i",
shortid(s), s, t, t->s_type);
pthread_mutex_lock(&t->s_stream_mutex);
if(TAILQ_FIRST(&t->s_filt_components) != NULL ||
t->s_type != STYPE_STD) {
streaming_msg_free(s->ths_start_message);
s->ths_start_message =
streaming_msg_create_data(SMT_START, service_build_stream_start(t));
}
// Link to service output
streaming_target_connect(&t->s_streaming_pad, &s->ths_input);
streaming_pad_deliver(&t->s_streaming_pad,
streaming_msg_create_code(SMT_GRACE,
s->ths_postpone +
t->s_grace_delay));
if(s->ths_start_message != NULL && t->s_streaming_status & TSS_PACKETS) {
subsetstate(s, SUBSCRIPTION_GOT_SERVICE);
// Send a START message to the subscription client
streaming_target_deliver(s->ths_output, s->ths_start_message);
s->ths_start_message = NULL;
t->s_running = 1;
// Send status report
sm = streaming_msg_create_code(SMT_SERVICE_STATUS,
t->s_streaming_status);
streaming_target_deliver(s->ths_output, sm);
}
pthread_mutex_unlock(&t->s_stream_mutex);
}
This is more clunky because of this whole interaction between muxes and services, but from what I can see it is simple enough to cut out the stream message request (that checks for valid data from a mux) and just create a service (the http link) to the mux from which the channel is created.
But all this got me thinking,
Why am I spending all this time exploring TVH, just write my own IPTV server that does what I and others want. A simple live TV and record for IPTV only. So I am .....
;)