Merge pull request #64 from john-tornblom/streaming_mkv_fixes
Some streaming mkv fixes
This commit is contained in:
commit
405f766e1f
3 changed files with 81 additions and 46 deletions
|
@ -69,6 +69,7 @@ struct mk_mux {
|
|||
char *filename;
|
||||
int error;
|
||||
off_t fdpos; // Current position in file
|
||||
int seekable;
|
||||
|
||||
mk_track *tracks;
|
||||
int ntracks;
|
||||
|
@ -79,7 +80,7 @@ struct mk_mux {
|
|||
htsbuf_queue_t *cluster;
|
||||
int64_t cluster_tc;
|
||||
off_t cluster_pos;
|
||||
|
||||
int cluster_maxsize;
|
||||
|
||||
off_t segment_header_pos;
|
||||
|
||||
|
@ -551,6 +552,9 @@ mk_build_metadata2(const event_t *e)
|
|||
if(e->e_channel != NULL)
|
||||
addtag(q, build_tag_string("TVCHANNEL", e->e_channel->ch_name, 0, NULL));
|
||||
|
||||
if(e->e_title != NULL)
|
||||
addtag(q, build_tag_string("TITLE", e->e_title, 0, NULL));
|
||||
|
||||
if(e->e_episode.ee_onscreen)
|
||||
addtag(q, build_tag_string("SYNOPSIS",
|
||||
e->e_episode.ee_onscreen, 0, NULL));
|
||||
|
@ -635,7 +639,7 @@ mk_write_metaseek(mk_mux_t *mkm, int first)
|
|||
|
||||
if(first) {
|
||||
mk_write_to_fd(mkm, &q);
|
||||
} else {
|
||||
} else if(mkm->seekable) {
|
||||
off_t prev = mkm->fdpos;
|
||||
if(lseek(mkm->fd, mkm->segment_pos, SEEK_SET) == (off_t) -1)
|
||||
mkm->error = errno;
|
||||
|
@ -655,27 +659,15 @@ mk_write_metaseek(mk_mux_t *mkm, int first)
|
|||
*/
|
||||
static htsbuf_queue_t *
|
||||
mk_build_segment(mk_mux_t *mkm,
|
||||
const struct streaming_start *ss,
|
||||
const event_t *e)
|
||||
const struct streaming_start *ss)
|
||||
{
|
||||
htsbuf_queue_t q;
|
||||
htsbuf_queue_t *p = htsbuf_queue_alloc(0);
|
||||
htsbuf_queue_init(&q, 0);
|
||||
|
||||
mkm->segmentinfo_pos = p->hq_size;
|
||||
ebml_append_master(p, 0x1549a966, mk_build_segment_info(mkm));
|
||||
|
||||
mkm->segmentinfo_pos = 33;
|
||||
ebml_append_master(&q, 0x1549a966, mk_build_segment_info(mkm));
|
||||
|
||||
mkm->trackinfo_pos = 33 + q.hq_size;
|
||||
ebml_append_master(&q, 0x1654ae6b, mk_build_tracks(mkm, ss));
|
||||
|
||||
if(e) {
|
||||
mkm->metadata_pos = 33 + q.hq_size;
|
||||
ebml_append_master(&q, 0x1254c367, mk_build_metadata2(e));
|
||||
}
|
||||
|
||||
ebml_append_master(p, 0x114d9b74, mk_build_metaseek(mkm));
|
||||
htsbuf_appendq(p, &q);
|
||||
htsbuf_queue_flush(&q);
|
||||
mkm->trackinfo_pos = p->hq_size;
|
||||
ebml_append_master(p, 0x1654ae6b, mk_build_tracks(mkm, ss));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -702,6 +694,8 @@ mk_mux_create(const char *filename,
|
|||
mkm->filename = strdup(filename);
|
||||
mkm->fd = fd;
|
||||
mkm->title = strdup(de->de_title);
|
||||
mkm->cluster_maxsize = 2000000/4;
|
||||
mkm->seekable = 1;
|
||||
TAILQ_INIT(&mkm->cues);
|
||||
|
||||
mk_write_master(mkm, 0x1a45dfa3, mk_build_ebmlheader());
|
||||
|
@ -731,7 +725,7 @@ mk_mux_create(const char *filename,
|
|||
|
||||
mk_mux_t *
|
||||
mk_mux_stream_create(int fd, const struct streaming_start *ss,
|
||||
const event_t *e)
|
||||
const channel_t *ch)
|
||||
{
|
||||
mk_mux_t *mkm;
|
||||
htsbuf_queue_t q;
|
||||
|
@ -740,20 +734,27 @@ mk_mux_stream_create(int fd, const struct streaming_start *ss,
|
|||
getuuid(mkm->uuid);
|
||||
mkm->filename = strdup("Live stream");
|
||||
mkm->fd = fd;
|
||||
mkm->title = strdup(e ? e->e_title : mkm->filename);
|
||||
mkm->cluster_maxsize = 0;
|
||||
|
||||
if(ch && ch->ch_name)
|
||||
mkm->title = strdup(ch->ch_name);
|
||||
else
|
||||
mkm->title = strdup("Live stream");
|
||||
|
||||
TAILQ_INIT(&mkm->cues);
|
||||
|
||||
htsbuf_queue_init(&q, 0);
|
||||
|
||||
ebml_append_master(&q, 0x1a45dfa3, mk_build_ebmlheader());
|
||||
htsbuf_appendq(&q, mk_build_segment_header(0));
|
||||
htsbuf_appendq(&q, mk_build_segment(mkm, ss, e));
|
||||
htsbuf_appendq(&q, mk_build_segment(mkm, ss));
|
||||
|
||||
mk_write_queue(mkm, &q);
|
||||
|
||||
return mkm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -780,6 +781,22 @@ mk_close_cluster(mk_mux_t *mkm)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
mk_mux_append_meta(mk_mux_t *mkm, event_t *e)
|
||||
{
|
||||
htsbuf_queue_t q;
|
||||
|
||||
htsbuf_queue_init(&q, 0);
|
||||
ebml_append_master(&q, 0x1254c367, mk_build_metadata2(e));
|
||||
mk_write_queue(mkm, &q);
|
||||
|
||||
return mkm->error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -821,15 +838,15 @@ mk_write_frame_i(mk_mux_t *mkm, mk_track *t, th_pkt_t *pkt)
|
|||
return;
|
||||
}
|
||||
|
||||
if(vkeyframe && mkm->cluster && mkm->cluster->hq_size > clusersizemax/4)
|
||||
mk_close_cluster(mkm);
|
||||
|
||||
else if(mkm->cluster && mkm->cluster->hq_size > clusersizemax)
|
||||
if(vkeyframe && mkm->cluster && mkm->cluster->hq_size > mkm->cluster_maxsize)
|
||||
mk_close_cluster(mkm);
|
||||
|
||||
else if(!mkm->has_video && mkm->cluster && mkm->cluster->hq_size > clusersizemax/40)
|
||||
mk_close_cluster(mkm);
|
||||
|
||||
else if(mkm->cluster && mkm->cluster->hq_size > clusersizemax)
|
||||
mk_close_cluster(mkm);
|
||||
|
||||
if(mkm->cluster == NULL) {
|
||||
mkm->cluster_tc = pts;
|
||||
mkm->cluster = htsbuf_queue_alloc(0);
|
||||
|
@ -947,19 +964,21 @@ mk_mux_close(mk_mux_t *mkm)
|
|||
mk_write_metaseek(mkm, 0);
|
||||
totsize = mkm->fdpos;
|
||||
|
||||
// Rewrite segment info to update duration
|
||||
if(lseek(mkm->fd, mkm->segmentinfo_pos, SEEK_SET) == mkm->segmentinfo_pos)
|
||||
mk_write_master(mkm, 0x1549a966, mk_build_segment_info(mkm));
|
||||
else
|
||||
tvhlog(LOG_ERR, "MKV", "%s: Unable to write duration, seek failed -- %s",
|
||||
mkm->filename, strerror(errno));
|
||||
if(mkm->seekable) {
|
||||
// Rewrite segment info to update duration
|
||||
if(lseek(mkm->fd, mkm->segmentinfo_pos, SEEK_SET) == mkm->segmentinfo_pos)
|
||||
mk_write_master(mkm, 0x1549a966, mk_build_segment_info(mkm));
|
||||
else
|
||||
tvhlog(LOG_ERR, "MKV", "%s: Unable to write duration, seek failed -- %s",
|
||||
mkm->filename, strerror(errno));
|
||||
|
||||
// Rewrite segment header to update total size
|
||||
if(lseek(mkm->fd, mkm->segment_header_pos, SEEK_SET) == mkm->segment_header_pos) {
|
||||
mk_write_segment_header(mkm, totsize - mkm->segment_header_pos - 12);
|
||||
} else
|
||||
tvhlog(LOG_ERR, "MKV", "%s: Unable to write total size, seek failed -- %s",
|
||||
mkm->filename, strerror(errno));
|
||||
// Rewrite segment header to update total size
|
||||
if(lseek(mkm->fd, mkm->segment_header_pos, SEEK_SET) == mkm->segment_header_pos) {
|
||||
mk_write_segment_header(mkm, totsize - mkm->segment_header_pos - 12);
|
||||
} else
|
||||
tvhlog(LOG_ERR, "MKV", "%s: Unable to write total size, seek failed -- %s",
|
||||
mkm->filename, strerror(errno));
|
||||
}
|
||||
|
||||
close(mkm->fd);
|
||||
free(mkm->filename);
|
||||
|
|
|
@ -24,6 +24,8 @@ typedef struct mk_mux mk_mux_t;
|
|||
struct streaming_start;
|
||||
struct dvr_entry;
|
||||
struct th_pkt;
|
||||
struct channel;
|
||||
struct event;
|
||||
|
||||
mk_mux_t *mk_mux_create(const char *filename,
|
||||
const struct streaming_start *ss,
|
||||
|
@ -32,10 +34,12 @@ mk_mux_t *mk_mux_create(const char *filename,
|
|||
|
||||
mk_mux_t *mk_mux_stream_create(int fd,
|
||||
const struct streaming_start *ss,
|
||||
const event_t *e);
|
||||
const struct channel *ch);
|
||||
|
||||
int mk_mux_write_pkt(mk_mux_t *mkm, struct th_pkt *pkt);
|
||||
|
||||
int mk_mux_append_meta(mk_mux_t *mkm, struct event *e);
|
||||
|
||||
void mk_mux_close(mk_mux_t *mk_mux);
|
||||
|
||||
#endif // MKMUX_H__
|
||||
|
|
|
@ -133,6 +133,7 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
|
|||
streaming_message_t *sm;
|
||||
int run = 1;
|
||||
mk_mux_t *mkm = NULL;
|
||||
uint32_t event_id = 0;
|
||||
int timeouts = 0;
|
||||
|
||||
while(run) {
|
||||
|
@ -155,8 +156,8 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
|
|||
//Check socket status
|
||||
getsockopt(hc->hc_fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
|
||||
|
||||
//Abort upon socket error, or after 5 seconds of silence
|
||||
if(err || timeouts > 4){
|
||||
//Abort upon socket error, or after 20 seconds of silence
|
||||
if(err || timeouts >= 20){
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
|
@ -168,24 +169,34 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
|
|||
TAILQ_REMOVE(&sq->sq_queue, sm, sm_link);
|
||||
|
||||
switch(sm->sm_type) {
|
||||
case SMT_PACKET:
|
||||
case SMT_PACKET: {
|
||||
if(!mkm)
|
||||
break;
|
||||
|
||||
pkt_ref_inc(sm->sm_data);
|
||||
run = !mk_mux_write_pkt(mkm, sm->sm_data);
|
||||
sm->sm_data = NULL;
|
||||
|
||||
event_t *e = NULL;
|
||||
if(s->ths_channel)
|
||||
e = s->ths_channel->ch_epg_current;
|
||||
|
||||
if(e && event_id != e->e_id) {
|
||||
event_id = e->e_id;
|
||||
run = !mk_mux_append_meta(mkm, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SMT_START: {
|
||||
tvhlog(LOG_DEBUG, "webui", "Start streaming %s", hc->hc_url_orig);
|
||||
|
||||
if(s->ths_service->s_servicetype == ST_RADIO)
|
||||
http_output_content(hc, "audio/x-matroska");
|
||||
else
|
||||
http_output_content(hc, "video/x-matroska");
|
||||
|
||||
event_t *e = NULL; //epg_event_find_by_time(s->ths_channel, dispatch_clock);
|
||||
|
||||
mkm = mk_mux_stream_create(hc->hc_fd, sm->sm_data, e);
|
||||
mkm = mk_mux_stream_create(hc->hc_fd, sm->sm_data, s->ths_channel);
|
||||
break;
|
||||
}
|
||||
case SMT_STOP:
|
||||
|
@ -196,6 +207,7 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
|
|||
break;
|
||||
|
||||
case SMT_NOSTART:
|
||||
tvhlog(LOG_DEBUG, "webui", "Couldn't start stream for %s", hc->hc_url_orig);
|
||||
run = 0;
|
||||
break;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue