AVDictionary *opts = NULL;
lav_muxer_t *lm = (lav_muxer_t*)m;
char app[128];
+ char mpegts_info[8];
#if LIBAVCODEC_VERSION_MAJOR > 58
const AVOutputFormat *fmt;
#else
return -1;
}
av_dict_set(&oc->metadata, "title", name, 0);
- av_dict_set(&oc->metadata, "service_name", name, 0);
- av_dict_set(&oc->metadata, "service_provider", app, 0);
+ av_dict_set(&lm->lm_oc->metadata, "title", name, 0);
+ if (ss->ss_si.si_service){
+ av_dict_set(&lm->lm_oc->metadata, "service_name", ss->ss_si.si_service, 0);
+ tvhdebug(LS_LIBAV, "service_name = %s", ss->ss_si.si_service);
+ } else
+ av_dict_set(&oc->metadata, "service_name", name, 0);
+ if (ss->ss_si.si_provider){
+ av_dict_set(&lm->lm_oc->metadata, "service_provider", ss->ss_si.si_provider, 0);
+ tvhdebug(LS_LIBAV, "service_provider = %s", ss->ss_si.si_provider);
+ } else
+ av_dict_set(&oc->metadata, "service_provider", app, 0);
lm->bsf_h264_filter = av_bsf_get_by_name("h264_mp4toannexb");
if (lm->bsf_h264_filter == NULL) {
tvhwarn(LS_LIBAV, "Failed to get BSF: h264_mp4toannexb");
}
lm->bsf_hevc_filter = av_bsf_get_by_name("hevc_mp4toannexb");
- if (lm->bsf_h264_filter == NULL) {
+ if (lm->bsf_hevc_filter == NULL) {
tvhwarn(LS_LIBAV, "Failed to get BSF: hevc_mp4toannexb");
}
lm->bsf_vp9_filter = av_bsf_get_by_name("vp9_superframe");
av_dict_set(&opts, "ism_lookahead", "0", 0);
}
+ if(lm->m_config.m_type == MC_MPEGTS) {
+ // parameters are required to make mpeg-ts output compliant with mpeg-ts standard
+ // implemented using documentation: https://ffmpeg.org/ffmpeg-formats.html#mpegts-1
+ if (lm->m_config.u.transcode.m_rewrite_sid > 0) {
+ // override from profile requested by teh user
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", lm->m_config.u.transcode.m_rewrite_sid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_service_id = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_service_id", mpegts_info, 0);
+ // if override requested by the user we let ffmpeg default to decide (0x1000)
+ if (!lm->m_config.u.transcode.m_rewrite_pmt) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_pmt_pid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_pmt_start_pid = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_pmt_start_pid", mpegts_info, 0);
+ }
+ if (!lm->m_config.u.transcode.m_rewrite_nit) {
+ av_dict_set(&opts, "mpegts_flags", "nit", 0);
+ }
+ }
+ else {
+ // we transfer as many parameters as possible
+ if (ss->ss_si.si_tsid) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_si.si_tsid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_transport_stream_id = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_transport_stream_id", mpegts_info, 0);
+ }
+ if (ss->ss_si.si_type) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_si.si_type);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_service_type = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_service_type", mpegts_info, 0);
+ }
+ if (ss->ss_pmt_pid) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_pmt_pid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_pmt_start_pid = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_pmt_start_pid", mpegts_info, 0);
+ }
+ if (ss->ss_pcr_pid) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_pcr_pid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_start_pid = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_start_pid", mpegts_info, 0);
+ }
+ if (ss->ss_service_id) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_service_id);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_service_id = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_service_id", mpegts_info, 0);
+ }
+ if (ss->ss_si.si_onid) {
+ snprintf(mpegts_info, sizeof(mpegts_info), "0x%04x", ss->ss_si.si_onid);
+ tvhdebug(LS_LIBAV, "MPEGTS: mpegts_original_network_id = %s", mpegts_info);
+ av_dict_set(&opts, "mpegts_original_network_id", mpegts_info, 0);
+ }
+ av_dict_set(&opts, "mpegts_flags", "nit", 0);
+ av_dict_set(&opts, "mpegts_copyts", "1", 0);
+ }
+ }
+
if(!lm->lm_oc->nb_streams) {
tvherror(LS_LIBAV, "No supported streams available");
lm->m_errors++;
typedef struct profile_transcode {
profile_t;
int pro_mc;
+#if ENABLE_LIBAV
+ uint16_t pro_rewrite_sid;
+ int pro_rewrite_pmt;
+ int pro_rewrite_nit;
+#endif
char *pro_vcodec;
char *pro_src_vcodec;
char *pro_acodec;
char *pro_src_scodec;
} profile_transcode_t;
+#if ENABLE_LIBAV
+static int
+profile_transcode_rewrite_sid_set (void *in, const void *v)
+{
+ profile_transcode_t *pro = (profile_transcode_t *)in;
+ const uint16_t *val = v;
+ if (*val != pro->pro_rewrite_sid) {
+ if (*val > 0) {
+ pro->pro_rewrite_pmt = 1;
+ pro->pro_rewrite_nit = 1;
+ }
+ pro->pro_rewrite_sid = *val;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+profile_transcode_int_set (void *in, const void *v, int *prop)
+{
+ profile_transcode_t *pro = (profile_transcode_t *)in;
+ int val = *(int *)v;
+ if (pro->pro_rewrite_sid > 0) val = 1;
+ if (val != *prop) {
+ *prop = val;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+profile_transcode_rewrite_pmt_set (void *in, const void *v)
+{
+ return profile_transcode_int_set(in, v, &((profile_transcode_t *)in)->pro_rewrite_pmt);
+}
+
+static int
+profile_transcode_rewrite_nit_set (void *in, const void *v)
+{
+ return profile_transcode_int_set(in, v, &((profile_transcode_t *)in)->pro_rewrite_nit);
+}
+#endif
static htsmsg_t *
profile_class_mc_list ( void *o, const char *lang )
.name = N_("Transcoding Settings"),
.number = 2,
},
+#if ENABLE_LIBAV
+ {
+ .name = N_("Rewrite MPEG-TS SI Table(s) Settings"),
+ .number = 3,
+ },
+#endif
{}
},
.ic_properties = (const property_t[]){
.opts = PO_DOC_NLIST,
.group = 1
},
+#if ENABLE_LIBAV
+ {
+ .type = PT_U16,
+ .id = "sid",
+ .name = N_("Rewrite Service ID"),
+ .desc = N_("Rewrite service identifier (SID) using the specified "
+ "value (usually 1). Zero means no rewrite; preserving "
+ "MPEG-TS original network and transport stream IDs"),
+ .off = offsetof(profile_transcode_t, pro_rewrite_sid),
+ .set = profile_transcode_rewrite_sid_set,
+ .opts = PO_EXPERT,
+ .def.i = 1,
+ .group = 3
+ },
+ {
+ .type = PT_BOOL,
+ .id = "rewrite_pmt",
+ .name = N_("Rewrite PMT"),
+ .desc = N_("Rewrite PMT (Program Map Table) packets to only "
+ "include information about the currently-streamed "
+ "service. "
+ "Rewrite can be unset only if 'Rewrite Service ID' "
+ "is set to zero."),
+ .off = offsetof(profile_transcode_t, pro_rewrite_pmt),
+ .set = profile_transcode_rewrite_pmt_set,
+ .opts = PO_EXPERT,
+ .def.i = 1,
+ .group = 3
+ },
+ {
+ .type = PT_BOOL,
+ .id = "rewrite_nit",
+ .name = N_("Rewrite NIT"),
+ .desc = N_("Rewrite NIT (Network Information Table) packets "
+ "to only include information about the currently-"
+ "streamed service. "
+ "Rewrite can be unset only if 'Rewrite Service ID' "
+ "is set to zero."),
+ .off = offsetof(profile_transcode_t, pro_rewrite_nit),
+ .set = profile_transcode_rewrite_nit_set,
+ .opts = PO_EXPERT,
+ .def.i = 1,
+ .group = 3
+ },
+#endif
{
.type = PT_STR,
.id = "pro_vcodec",
if (!profile_transcode_mc_valid(c.m_type))
c.m_type = MC_MATROSKA;
}
+ #if ENABLE_LIBAV
+ c.u.transcode.m_rewrite_sid = pro->pro_rewrite_sid;
+ c.u.transcode.m_rewrite_pmt = pro->pro_rewrite_pmt;
+ c.u.transcode.m_rewrite_nit = pro->pro_rewrite_nit;
+ #endif
assert(!prch->prch_muxer);
prch->prch_muxer = muxer_create(&c, hints);