forked from tvheadend/tvheadend
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
mpegts: add netceiver support
The NetCeiver is a device that streams DVB via multicast. http://www.baycom.de/hardware/netceiver/ Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
- Loading branch information
Showing
9 changed files
with
686 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,247 @@ | ||
| /* | ||
| * Tvheadend - NetCeiver DVB "frontend" | ||
| * | ||
| * Copyright (C) 2013-2014 Sven Wegener | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include "tvheadend.h" | ||
| #include "notify.h" | ||
| #include "atomic.h" | ||
| #include "tvhpoll.h" | ||
| #include "settings.h" | ||
| #include "input.h" | ||
| #include "udp.h" | ||
|
|
||
| #include <sys/ioctl.h> | ||
| #include <sys/types.h> | ||
| #include <sys/stat.h> | ||
| #include <unistd.h> | ||
| #include <fcntl.h> | ||
| #include <assert.h> | ||
| #include <arpa/inet.h> | ||
|
|
||
|
|
||
| #define LOG_SUBSYS "netceiver" | ||
|
|
||
|
|
||
| static void netceiver_class_save(idnode_t *in) | ||
| { | ||
| htsmsg_t *c; | ||
|
|
||
| c = htsmsg_create_map(); | ||
| idnode_save(in, c); | ||
| hts_settings_save(c, "input/dvb/netceiver/%s", idnode_uuid_as_str(in)); | ||
| htsmsg_destroy(c); | ||
| } | ||
|
|
||
| static const idclass_t netceiver_class = | ||
| { | ||
| .ic_super = &mpegts_input_class, | ||
| .ic_class = "netceiver", | ||
| .ic_caption = "NetCeiver DVB Frontend", | ||
| .ic_save = netceiver_class_save, | ||
| .ic_properties = (const property_t[]) { | ||
| { | ||
| .type = PT_STR, | ||
| .id = "interface", | ||
| .name = "Interface", | ||
| .off = offsetof(netceiver_t, nc_interface), | ||
| }, | ||
| {}, | ||
| } | ||
| }; | ||
|
|
||
| static void *netceiver_input_thread(void *aux) | ||
| { | ||
| netceiver_t *nc = aux; | ||
| mpegts_mux_instance_t *mmi; | ||
| tvhpoll_event_t ev; | ||
| sbuf_t tsbuf; | ||
| char name[256]; | ||
|
|
||
| nc->mi_display_name((mpegts_input_t *) nc, name, sizeof(name)); | ||
|
|
||
| sbuf_init_fixed(&tsbuf, NETCEIVER_TS_IP_BUFFER_SIZE); | ||
|
|
||
| while (tvheadend_running) { | ||
| if (tvhpoll_wait(nc->nc_poll, &ev, 1, -1) < 1) | ||
| continue; | ||
|
|
||
| if (sbuf_read(&tsbuf, ev.data.fd) < 0) { | ||
| if (errno != EAGAIN && errno != EINTR) | ||
| tvherror(LOG_SUBSYS, "%s - read() error %d (%s)", name, errno, strerror(errno)); | ||
| continue; | ||
| } | ||
|
|
||
| mmi = LIST_FIRST(&nc->mi_mux_active); | ||
| if (!mmi) | ||
| continue; | ||
| mpegts_input_recv_packets((mpegts_input_t *) nc, mmi, &tsbuf, NULL, NULL); | ||
| } | ||
|
|
||
| sbuf_free(&tsbuf); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| static int netceiver_is_enabled(mpegts_input_t *mi, mpegts_mux_t *mm, int flags) | ||
| { | ||
| netceiver_t *nc = (netceiver_t *) mi; | ||
|
|
||
| if (!nc->nc_interface || !nc->nc_interface[0]) | ||
| return 0; | ||
|
|
||
| return mpegts_input_is_enabled(mi, mm, flags); | ||
| } | ||
|
|
||
| static int netceiver_start_mux(mpegts_input_t *mi, mpegts_mux_instance_t *mmi) | ||
| { | ||
| netceiver_t *nc = (netceiver_t *) mi; | ||
| dvb_mux_t *dm = (dvb_mux_t *) mmi->mmi_mux; | ||
|
|
||
| if (dm->mm_active) | ||
| return 0; | ||
|
|
||
| netceiver_start_monitor(nc, &dm->lm_tuning); | ||
|
|
||
| // required for tables subscribing to pids | ||
| dm->mm_active = mmi; | ||
|
|
||
| psi_tables_default(mmi->mmi_mux); | ||
| psi_tables_dvb(mmi->mmi_mux); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static void netceiver_stop_mux(mpegts_input_t *mi, mpegts_mux_instance_t *mmi) | ||
| { | ||
| netceiver_t *nc = (netceiver_t *) mi; | ||
|
|
||
| netceiver_stop_monitor(nc); | ||
| } | ||
|
|
||
| static mpegts_pid_t *netceiver_open_pid(mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, void *owner) | ||
| { | ||
| netceiver_t *nc = (netceiver_t *) mi; | ||
| dvb_mux_t *dm = (dvb_mux_t *) mm; | ||
| mpegts_service_t *s = owner; | ||
| mpegts_pid_t *mp; | ||
| int sid = 0; | ||
|
|
||
| mp = mpegts_input_open_pid(mi, mm, pid, type, owner); | ||
| if (!mp) | ||
| return NULL; | ||
|
|
||
| if (mp->nc_udp) | ||
| return mp; | ||
|
|
||
| if (type == MPS_STREAM && service_is_encrypted((service_t *) s)) { | ||
| sid = s->s_dvb_service_id; | ||
| } | ||
|
|
||
| mp->nc_udp = netceiver_tune(nc, NETCEIVER_GROUP_STREAM, &dm->lm_tuning, pid, sid); | ||
| if (mp->nc_udp) { | ||
| tvhpoll_event_t ev = { | ||
| .fd = mp->nc_udp->fd, | ||
| .data.fd = ev.fd, | ||
| .events = TVHPOLL_IN, | ||
| }; | ||
| tvhpoll_add(nc->nc_poll, &ev, 1); | ||
| } | ||
|
|
||
| return mp; | ||
| } | ||
|
|
||
| static void netceiver_close_pid(mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, void *owner) | ||
| { | ||
| mpegts_pid_t *mp; | ||
|
|
||
| mp = mpegts_mux_find_pid(mm, pid, 0); | ||
| if (!mp) | ||
| return; | ||
|
|
||
| if (mp->nc_udp) { | ||
| udp_close(mp->nc_udp); | ||
| mp->nc_udp = NULL; | ||
| } | ||
|
|
||
| mpegts_input_close_pid(mi, mm, pid, type, owner); | ||
| } | ||
|
|
||
| static idnode_set_t * | ||
| netceiver_network_list(mpegts_input_t *mi) | ||
| { | ||
| idnode_set_t *is = idnode_set_create(0); | ||
|
|
||
| idnode_find_all_add(is, &dvb_network_dvbt_class, NULL); | ||
| idnode_find_all_add(is, &dvb_network_dvbc_class, NULL); | ||
| idnode_find_all_add(is, &dvb_network_dvbs_class, NULL); | ||
| idnode_find_all_add(is, &dvb_network_atsc_class, NULL); | ||
|
|
||
| return is; | ||
| } | ||
|
|
||
| static netceiver_t *netceiver_create(const char *uuid, htsmsg_t *conf) | ||
| { | ||
| netceiver_t *nc = calloc(1, sizeof(*nc)); | ||
| nc = (netceiver_t *) mpegts_input_create0((mpegts_input_t *) nc, &netceiver_class, uuid, conf); | ||
|
|
||
| nc->mi_is_enabled = netceiver_is_enabled; | ||
| nc->mi_start_mux = netceiver_start_mux; | ||
| nc->mi_stop_mux = netceiver_stop_mux; | ||
| nc->mi_network_list = netceiver_network_list; | ||
| nc->mi_open_pid = netceiver_open_pid; | ||
| nc->mi_close_pid = netceiver_close_pid; | ||
|
|
||
| if (!nc->mi_name) | ||
| nc->mi_name = strdup("NetCeiver"); | ||
|
|
||
| nc->nc_poll = tvhpoll_create(256); | ||
| tvhthread_create(&nc->nc_input_thread, NULL, netceiver_input_thread, nc); | ||
|
|
||
| tvhdebug(LOG_SUBSYS, "created %s on interface %s", nc->mi_name, nc->nc_interface); | ||
|
|
||
| return nc; | ||
| } | ||
|
|
||
| static void netceiver_load_config(void) | ||
| { | ||
| htsmsg_t *s, *e; | ||
| htsmsg_field_t *f; | ||
|
|
||
| tvhdebug(LOG_SUBSYS, "loading NetCeiver configuration"); | ||
| if ((s = hts_settings_load_r(1, "input/dvb/netceiver"))) { | ||
| HTSMSG_FOREACH(f, s) { | ||
| tvhdebug(LOG_SUBSYS, "loading NetCeiver configuration from %s", f->hmf_name); | ||
| if (!(e = htsmsg_get_map_by_field(f))) | ||
| continue; | ||
| netceiver_create(f->hmf_name, e); | ||
| } | ||
| htsmsg_destroy(s); | ||
| } | ||
| } | ||
|
|
||
| void netceiver_init(void) | ||
| { | ||
| netceiver_monitor_init(); | ||
| netceiver_load_config(); | ||
| } | ||
|
|
||
| /****************************************************************************** | ||
| * Editor Configuration | ||
| * | ||
| * vim:sts=2:ts=2:sw=2:et | ||
| *****************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /* | ||
| * Tvheadend - NetCeiver DVB "frontend" | ||
| * | ||
| * Copyright (C) 2013-2014 Sven Wegener | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #ifndef __TVH_NETCEIVER_H__ | ||
| #define __TVH_NETCEIVER_H__ | ||
|
|
||
| #include "tvhpoll.h" | ||
|
|
||
| #define NETCEIVER_TS_PACKET_SIZE 188 | ||
| #define NETCEIVER_TS_PACKETS_PER_IP_PACKET 7 | ||
| #define NETCEIVER_TS_IP_PACKET_SIZE (NETCEIVER_TS_PACKETS_PER_IP_PACKET * NETCEIVER_TS_PACKET_SIZE) | ||
| #define NETCEIVER_TS_IP_BUFFER_SIZE (256 * NETCEIVER_TS_IP_PACKET_SIZE) | ||
|
|
||
| #define NETCEIVER_GROUP_STREAM 3 | ||
| #define NETCEIVER_GROUP_MONITOR 4 | ||
|
|
||
| typedef struct netceiver netceiver_t; | ||
|
|
||
| /* | ||
| * NetCeiver | ||
| */ | ||
|
|
||
| struct netceiver | ||
| { | ||
| mpegts_input_t; | ||
|
|
||
| const char *nc_interface; | ||
|
|
||
| pthread_t nc_input_thread; | ||
|
|
||
| tvhpoll_t *nc_poll; | ||
|
|
||
| udp_connection_t *nc_monitor_udp; | ||
| }; | ||
|
|
||
| void netceiver_init(void); | ||
| udp_connection_t *netceiver_tune(netceiver_t *nc, int group, dvb_mux_conf_t *dmc, int pid, int sid); | ||
|
|
||
| void netceiver_monitor_init(void); | ||
| void netceiver_start_monitor(netceiver_t *nc, dvb_mux_conf_t *dmc); | ||
| void netceiver_stop_monitor(netceiver_t *nc); | ||
|
|
||
| #endif /* __TVH_NETCEIVER_H__ */ |
Oops, something went wrong.