From 2b8ad616a453d78f60aa5344211e55bcadf93397 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sat, 24 Jan 2015 21:55:01 +0100 Subject: [PATCH] profile: add matroska/mpegts muxers from libav --- src/muxer.c | 5 ++ src/muxer/muxer_libav.c | 2 - src/profile.c | 175 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 174 insertions(+), 8 deletions(-) diff --git a/src/muxer.c b/src/muxer.c index 9fb718995..223a8e031 100644 --- a/src/muxer.c +++ b/src/muxer.c @@ -42,6 +42,7 @@ static struct strtab container_audio_mime[] = { { "audio/x-matroska", MC_MATROSKA }, { "audio/x-matroska", MC_AVMATROSKA }, { "audio/webm", MC_WEBM }, + { "audio/webm", MC_AVWEBM }, { "audio/x-mpegts", MC_MPEGTS }, { "audio/mpeg", MC_MPEGPS }, { "application/octet-stream", MC_PASS }, @@ -57,6 +58,7 @@ static struct strtab container_video_mime[] = { { "video/x-matroska", MC_MATROSKA }, { "video/x-matroska", MC_AVMATROSKA }, { "video/webm", MC_WEBM }, + { "video/webm", MC_AVWEBM }, { "video/x-mpegts", MC_MPEGTS }, { "video/mpeg", MC_MPEGPS }, { "application/octet-stream", MC_PASS }, @@ -76,6 +78,7 @@ static struct strtab container_name[] = { { "pass", MC_PASS }, { "raw", MC_RAW }, { "avmatroska", MC_AVMATROSKA }, + { "avwebm", MC_AVWEBM }, }; @@ -91,6 +94,7 @@ static struct strtab container_audio_file_suffix[] = { { "bin", MC_PASS }, { "bin", MC_RAW }, { "mka", MC_AVMATROSKA }, + { "webm", MC_AVWEBM }, }; @@ -106,6 +110,7 @@ static struct strtab container_video_file_suffix[] = { { "bin", MC_PASS }, { "bin", MC_RAW }, { "mkv", MC_AVMATROSKA }, + { "webm", MC_AVWEBM }, }; diff --git a/src/muxer/muxer_libav.c b/src/muxer/muxer_libav.c index 3b6b197f7..9160af687 100644 --- a/src/muxer/muxer_libav.c +++ b/src/muxer/muxer_libav.c @@ -105,8 +105,6 @@ lav_muxer_add_stream(lav_muxer_t *lm, break; } - - if(ssc->ssc_gh) { if (ssc->ssc_type == SCT_H264) { sbuf_t hdr; diff --git a/src/profile.c b/src/profile.c index 73a672f14..c21ededc4 100755 --- a/src/profile.c +++ b/src/profile.c @@ -48,10 +48,18 @@ static void profile_class_save ( idnode_t *in ); void profile_register(const idclass_t *clazz, profile_builder_t builder) { - profile_build_t *pb = calloc(1, sizeof(*pb)); + profile_build_t *pb = calloc(1, sizeof(*pb)), *pb2; pb->clazz = clazz; pb->build = builder; - LIST_INSERT_HEAD(&profile_builders, pb, link); + pb2 = LIST_FIRST(&profile_builders); + if (pb2) { + /* append tail */ + while (LIST_NEXT(pb2, link)) + pb2 = LIST_NEXT(pb2, link); + LIST_INSERT_AFTER(pb2, pb, link); + } else { + LIST_INSERT_HEAD(&profile_builders, pb, link); + } } static profile_build_t * @@ -852,7 +860,7 @@ const idclass_t profile_mpegts_pass_class = { .ic_super = &profile_class, .ic_class = "profile-mpegts", - .ic_caption = "MPEG-TS Pass-through", + .ic_caption = "MPEG-TS Pass-through /build-in", .ic_properties = (const property_t[]){ { .type = PT_BOOL, @@ -936,7 +944,7 @@ const idclass_t profile_matroska_class = { .ic_super = &profile_class, .ic_class = "profile-matroska", - .ic_caption = "Matroska (mkv)", + .ic_caption = "Matroska (mkv) /build-in", .ic_properties = (const property_t[]){ { .type = PT_BOOL, @@ -1008,11 +1016,164 @@ profile_matroska_builder(void) #if ENABLE_LIBAV -static int profile_transcode_experimental_codecs = 1; +/* + * LibAV/MPEG-TS muxer + */ +typedef struct profile_libav_mpegts { + profile_t; +} profile_libav_mpegts_t; + +const idclass_t profile_libav_mpegts_class = +{ + .ic_super = &profile_class, + .ic_class = "profile-libav-mpegts", + .ic_caption = "MPEG-TS /av-lib", + .ic_properties = (const property_t[]){ + { } + } +}; + +static int +profile_libav_mpegts_reopen(profile_chain_t *prch, + muxer_config_t *m_cfg, int flags) +{ + muxer_config_t c; + + if (m_cfg) + c = *m_cfg; /* do not alter the original parameter */ + else + memset(&c, 0, sizeof(c)); + c.m_type = MC_MPEGTS; + + assert(!prch->prch_muxer); + prch->prch_muxer = muxer_create(&c); + return 0; +} + +static int +profile_libav_mpegts_open(profile_chain_t *prch, + muxer_config_t *m_cfg, int flags, size_t qsize) +{ + int r; + + prch->prch_sq.sq_maxsize = qsize; + + r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0); + if (r) { + profile_chain_close(prch); + return r; + } + + profile_libav_mpegts_reopen(prch, m_cfg, flags); + return 0; +} + +static muxer_container_type_t +profile_libav_mpegts_get_mc(profile_t *_pro) +{ + return MC_MPEGTS; +} + +static profile_t * +profile_libav_mpegts_builder(void) +{ + profile_libav_mpegts_t *pro = calloc(1, sizeof(*pro)); + pro->pro_reopen = profile_libav_mpegts_reopen; + pro->pro_open = profile_libav_mpegts_open; + pro->pro_get_mc = profile_libav_mpegts_get_mc; + return (profile_t *)pro; +} + +/* + * LibAV/Matroska muxer + */ +typedef struct profile_libav_matroska { + profile_t; + int pro_webm; +} profile_libav_matroska_t; + +const idclass_t profile_libav_matroska_class = +{ + .ic_super = &profile_class, + .ic_class = "profile-libav-matroska", + .ic_caption = "Matroska /av-lib", + .ic_properties = (const property_t[]){ + { + .type = PT_BOOL, + .id = "webm", + .name = "WEBM", + .off = offsetof(profile_libav_matroska_t, pro_webm), + .def.i = 0, + }, + { } + } +}; + +static int +profile_libav_matroska_reopen(profile_chain_t *prch, + muxer_config_t *m_cfg, int flags) +{ + profile_libav_matroska_t *pro = (profile_libav_matroska_t *)prch->prch_pro; + muxer_config_t c; + + if (m_cfg) + c = *m_cfg; /* do not alter the original parameter */ + else + memset(&c, 0, sizeof(c)); + if (c.m_type != MC_AVWEBM) + c.m_type = MC_AVMATROSKA; + if (pro->pro_webm) + c.m_type = MC_AVWEBM; + + assert(!prch->prch_muxer); + prch->prch_muxer = muxer_create(&c); + return 0; +} + +static int +profile_libav_matroska_open(profile_chain_t *prch, + muxer_config_t *m_cfg, int flags, size_t qsize) +{ + int r; + + prch->prch_sq.sq_maxsize = qsize; + + r = profile_htsp_work(prch, &prch->prch_sq.sq_st, 0, 0); + if (r) { + profile_chain_close(prch); + return r; + } + + profile_libav_matroska_reopen(prch, m_cfg, flags); + + return 0; +} + +static muxer_container_type_t +profile_libav_matroska_get_mc(profile_t *_pro) +{ + profile_libav_matroska_t *pro = (profile_libav_matroska_t *)_pro; + if (pro->pro_webm) + return MC_AVWEBM; + return MC_AVMATROSKA; +} + +static profile_t * +profile_libav_matroska_builder(void) +{ + profile_libav_matroska_t *pro = calloc(1, sizeof(*pro)); + pro->pro_reopen = profile_libav_matroska_reopen; + pro->pro_open = profile_libav_matroska_open; + pro->pro_get_mc = profile_libav_matroska_get_mc; + return (profile_t *)pro; +} /* * Transcoding + packet-like muxers */ + +static int profile_transcode_experimental_codecs = 1; + typedef struct profile_transcode { profile_t; int pro_mc; @@ -1175,7 +1336,7 @@ const idclass_t profile_transcode_class = { .ic_super = &profile_class, .ic_class = "profile-transcode", - .ic_caption = "Transcode", + .ic_caption = "Transcode /av-lib", .ic_properties = (const property_t[]){ { .type = PT_INT, @@ -1452,6 +1613,8 @@ profile_init(void) profile_register(&profile_matroska_class, profile_matroska_builder); profile_register(&profile_htsp_class, profile_htsp_builder); #if ENABLE_LIBAV + profile_register(&profile_libav_mpegts_class, profile_libav_mpegts_builder); + profile_register(&profile_libav_matroska_class, profile_libav_matroska_builder); profile_transcode_experimental_codecs = getenv("TVHEADEND_LIBAV_NO_EXPERIMENTAL_CODECS") ? 0 : 1; profile_register(&profile_transcode_class, profile_transcode_builder); -- 2.47.3