dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss)
{
const source_info_t *si = &ss->ss_si;
+ streaming_start_t *ss_copy;
const streaming_start_component_t *ssc;
- int i;
+ char res[11], asp[6], sr[6], ch[7];
dvr_config_t *cfg = de->de_config;
profile_chain_t *prch = de->de_chain;
+ htsmsg_t *info, *e;
+ htsmsg_field_t *f;
muxer_t *muxer;
+ int i;
if (!cfg) {
dvr_rec_fatal_error(de, "Unable to determine config profile");
return -1;
}
- if(muxer_init(muxer, ss, lang_str_get(de->de_title, NULL))) {
+ ss_copy = streaming_start_copy(ss);
+
+ if(muxer_init(muxer, ss_copy, lang_str_get(de->de_title, NULL))) {
dvr_rec_fatal_error(de, "Unable to init file");
- return -1;
+ goto _err;
}
if(cfg->dvr_tag_files) {
if(muxer_write_meta(muxer, de->de_bcast, de->de_comment)) {
dvr_rec_fatal_error(de, "Unable to write meta data");
- return -1;
+ goto _err;
}
}
"sample rate",
"channels");
- for(i = 0; i < ss->ss_num_components; i++) {
- ssc = &ss->ss_components[i];
+ info = htsmsg_create_list();
+ for(i = 0; i < ss_copy->ss_num_components; i++) {
+ ssc = &ss_copy->ss_components[i];
- char res[11];
- char asp[6];
- char sr[6];
- char ch[7];
+ if(ssc->ssc_muxer_disabled)
+ continue;
+
+ e = htsmsg_create_map();
+ htsmsg_add_str(e, "type", streaming_component_type2txt(ssc->ssc_type));
+ if (ssc->ssc_lang && ssc->ssc_lang[0])
+ htsmsg_add_str(e, "language", ssc->ssc_lang);
if(SCT_ISAUDIO(ssc->ssc_type)) {
+ htsmsg_add_u32(e, "audio_type", ssc->ssc_audio_type);
if(ssc->ssc_sri)
snprintf(sr, sizeof(sr), "%d", sri_to_rate(ssc->ssc_sri));
else
else
snprintf(ch, sizeof(ch), "%d", ssc->ssc_channels);
} else {
- sr[0] = 0;
- ch[0] = 0;
+ sr[0] = ch[0] = 0;
}
if(SCT_ISVIDEO(ssc->ssc_type)) {
ssc->ssc_width, ssc->ssc_height);
else
strcpy(res, "?");
- } else {
- res[0] = 0;
- }
- if(SCT_ISVIDEO(ssc->ssc_type)) {
if(ssc->ssc_aspect_num && ssc->ssc_aspect_den)
snprintf(asp, sizeof(asp), "%d:%d",
ssc->ssc_aspect_num, ssc->ssc_aspect_den);
else
strcpy(asp, "?");
+
+ htsmsg_add_u32(e, "width", ssc->ssc_width);
+ htsmsg_add_u32(e, "height", ssc->ssc_height);
+ htsmsg_add_u32(e, "duration", ssc->ssc_frameduration);
+ htsmsg_add_u32(e, "aspect_num", ssc->ssc_aspect_num);
+ htsmsg_add_u32(e, "aspect_den", ssc->ssc_aspect_den);
} else {
- asp[0] = 0;
+ res[0] = asp[0] = 0;
+ }
+
+ if (SCT_ISSUBTITLE(ssc->ssc_type)) {
+ htsmsg_add_u32(e, "composition_id", ssc->ssc_composition_id);
+ htsmsg_add_u32(e, "ancillary_id", ssc->ssc_ancillary_id);
}
tvhlog(LOG_INFO, "dvr",
sr,
ch,
ssc->ssc_disabled ? "<disabled, no valid input>" : "");
+ htsmsg_add_msg(info, NULL, e);
}
+ streaming_start_unref(ss_copy);
+
+ /* update the info field for a filename */
+ if ((f = htsmsg_field_last(de->de_files)) != NULL &&
+ (e = htsmsg_field_get_map(f)) != NULL) {
+ htsmsg_set_msg(e, "info", info);
+ } else {
+ htsmsg_destroy(info);
+ }
return 0;
+
+_err:
+ streaming_start_unref(ss_copy);
+ return -1;
}
/**
*
*/
-void
-htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f)
+static void
+htsmsg_field_data_destroy(htsmsg_t *msg, htsmsg_field_t *f)
{
- TAILQ_REMOVE(&msg->hm_fields, f, hmf_link);
-
switch(f->hmf_type) {
case HMF_MAP:
case HMF_LIST:
default:
break;
}
+ f->hmf_flags &= ~HMF_ALLOCED;
+}
+
+/**
+ *
+ */
+void
+htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f)
+{
+ TAILQ_REMOVE(&msg->hm_fields, f, hmf_link);
+
+ htsmsg_field_data_destroy(msg, f);
+
if(f->hmf_flags & HMF_NAME_ALLOCED)
free((void *)f->hmf_name);
free(f);
/*
*
*/
-htsmsg_t *
-htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub)
+static htsmsg_t *
+htsmsg_field_set_msg(htsmsg_field_t *f, htsmsg_t *sub)
{
- htsmsg_field_t *f;
-
- f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP,
- HMF_NAME_ALLOCED);
-
assert(sub->hm_data == NULL);
f->hmf_msg.hm_islist = sub->hm_islist;
TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
return NULL;
}
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub)
+{
+ htsmsg_field_t *f;
+
+ f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP,
+ HMF_NAME_ALLOCED);
+ return htsmsg_field_set_msg(f, sub);
+}
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_set_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub)
+{
+ htsmsg_field_t *f = htsmsg_field_find(msg, name);
+ if (!f)
+ return htsmsg_add_msg(msg, name, sub);
+ htsmsg_field_data_destroy(msg, f);
+ return htsmsg_field_set_msg(f, sub);
+}
+
/*
*/
htsmsg_t *htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub);
+/**
+ * Add/update an field where source is a list or map message.
+ */
+htsmsg_t *htsmsg_set_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub);
+
/**
* Add an field where source is a double
*/
const char* (*m_mime) (struct muxer *, /* Figure out the mimetype */
const struct streaming_start *);
int (*m_init) (struct muxer *, /* Init The muxer with streams */
- const struct streaming_start *,
+ struct streaming_start *,
const char *);
int (*m_reconfigure)(struct muxer *, /* Reconfigure the muxer on */
const struct streaming_start *); /* stream changes */
static inline int muxer_open_stream (muxer_t *m, int fd)
{ if(m && fd >= 0) return m->m_open_stream(m, fd); return -1; }
-static inline int muxer_init (muxer_t *m, const struct streaming_start *ss, const char *name)
+static inline int muxer_init (muxer_t *m, struct streaming_start *ss, const char *name)
{ if(m && ss) return m->m_init(m, ss, name); return -1; }
static inline int muxer_reconfigure (muxer_t *m, const struct streaming_start *ss)
* Init the muxer with streams
*/
static int
-lav_muxer_init(muxer_t* m, const struct streaming_start *ss, const char *name)
+lav_muxer_init(muxer_t* m, struct streaming_start *ss, const char *name)
{
int i;
- const streaming_start_component_t *ssc;
+ streaming_start_component_t *ssc;
AVFormatContext *oc;
lav_muxer_t *lm = (lav_muxer_t*)m;
char app[128];
tvhlog(LOG_WARNING, "libav", "%s is not supported in %s",
streaming_component_type2txt(ssc->ssc_type),
muxer_container_type2txt(lm->m_config.m_type));
+ ssc->ssc_muxer_disabled = 1;
continue;
}
if(lav_muxer_add_stream(lm, ssc)) {
tvhlog(LOG_ERR, "libav", "Failed to add %s stream",
streaming_component_type2txt(ssc->ssc_type));
+ ssc->ssc_muxer_disabled = 1;
continue;
}
}
*
*/
static htsbuf_queue_t *
-mk_build_tracks(mk_muxer_t *mk, const streaming_start_t *ss)
+mk_build_tracks(mk_muxer_t *mk, streaming_start_t *ss)
{
- const streaming_start_component_t *ssc;
+ streaming_start_component_t *ssc;
const char *codec_id;
int i, tracktype;
htsbuf_queue_t *q = htsbuf_queue_alloc(0), *t;
break;
default:
+ ssc->ssc_muxer_disabled = 1;
tr->disabled = 1;
continue;
}
*/
static htsbuf_queue_t *
mk_build_segment(mk_muxer_t *mk,
- const streaming_start_t *ss)
+ streaming_start_t *ss)
{
htsbuf_queue_t *p = htsbuf_queue_alloc(0);
* Init the muxer with a title and some tracks
*/
static int
-mkv_muxer_init(muxer_t *m, const streaming_start_t *ss, const char *name)
+mkv_muxer_init(muxer_t *m, streaming_start_t *ss, const char *name)
{
mk_muxer_t *mk = (mk_muxer_t *)m;
htsbuf_queue_t q, *a;
* Init the passthrough muxer with streams
*/
static int
-pass_muxer_init(muxer_t* m, const struct streaming_start *ss, const char *name)
+pass_muxer_init(muxer_t* m, struct streaming_start *ss, const char *name)
{
return pass_muxer_reconfigure(m, ss);
}
uint8_t ssc_ext_sri;
uint8_t ssc_channels;
uint8_t ssc_disabled;
+ uint8_t ssc_muxer_disabled;
pktbuf_t *ssc_gh;
struct timeval tp;
int err = 0;
socklen_t errlen = sizeof(err);
+ streaming_start_t *ss_copy;
int64_t mono;
if(muxer_open_stream(mux, hc->hc_fd))
return;
}
- if(muxer_init(mux, sm->sm_data, name) < 0)
+ ss_copy = streaming_start_copy((streaming_start_t *)sm->sm_data);
+ if(muxer_init(mux, ss_copy, name) < 0)
run = 0;
+ streaming_start_unref(ss_copy);
started = 1;
} else if(muxer_reconfigure(mux, sm->sm_data) < 0) {