From 0a34ce334a7c8b2d3926148be30f5b69fd253e41 Mon Sep 17 00:00:00 2001 From: Shaleen Jain <shaleen@jain.sh> Date: Fri, 17 Aug 2018 19:11:57 +0530 Subject: [PATCH] dlna: add GetProtocolInfo action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for querying media formats supported by a Media Renderer device. Profiles related to H264/HEVC and MP3/AAC/AC-3 codecs are added. We transcode to the default/mandatory DLNA audio and video profiles for any non-supported formats since these are suppose to be supported by every DLNA certified device. Signed-off-by: Thomas Guillem <thomas@gllm.fr> Signed-off-by: Hugo Beauzée-Luyssen <hugo@beauzee.fr> --- modules/services_discovery/Makefile.am | 1 + modules/stream_out/dlna/dlna.cpp | 268 ++++++- modules/stream_out/dlna/dlna.hpp | 41 +- modules/stream_out/dlna/profile_names.hpp | 846 ++++++++++++++++++++++ 4 files changed, 1120 insertions(+), 36 deletions(-) create mode 100644 modules/stream_out/dlna/profile_names.hpp diff --git a/modules/services_discovery/Makefile.am b/modules/services_discovery/Makefile.am index 135946047769..4f234c5fffc1 100644 --- a/modules/services_discovery/Makefile.am +++ b/modules/services_discovery/Makefile.am @@ -31,6 +31,7 @@ libupnp_plugin_la_SOURCES = services_discovery/upnp.cpp services_discovery/upnp. services_discovery/upnp-wrapper.cpp \ stream_out/renderer_common.hpp \ stream_out/renderer_common.cpp \ + stream_out/dlna/profile_names.hpp \ stream_out/dlna/dlna_common.hpp \ stream_out/dlna/dlna.hpp \ stream_out/dlna/dlna.cpp diff --git a/modules/stream_out/dlna/dlna.cpp b/modules/stream_out/dlna/dlna.cpp index 0158e9306bb3..0965782d06c7 100644 --- a/modules/stream_out/dlna/dlna.cpp +++ b/modules/stream_out/dlna/dlna.cpp @@ -68,8 +68,9 @@ struct sout_stream_sys_t std::shared_ptr<MediaRenderer> renderer; UpnpInstanceWrapper *p_upnp; - bool canDecodeAudio( vlc_fourcc_t i_codec ) const; - bool canDecodeVideo( vlc_fourcc_t i_codec ) const; + ProtocolPtr canDecodeAudio( vlc_fourcc_t i_codec ) const; + ProtocolPtr canDecodeVideo( vlc_fourcc_t audio_codec, + vlc_fourcc_t video_codec ) const; bool startSoutChain( sout_stream_t* p_stream, const std::vector<sout_stream_id_sys_t*> &new_streams, const std::string &sout ); @@ -86,6 +87,7 @@ struct sout_stream_sys_t int http_port; std::vector<sout_stream_id_sys_t*> streams; std::vector<sout_stream_id_sys_t*> out_streams; + std::vector<protocol_info_t> device_protocols; private: std::string GetAcodecOption( sout_stream_t *, vlc_fourcc_t *, const audio_format_t *, int ); @@ -153,14 +155,67 @@ char *getServerIPAddress() { return ip; } -bool sout_stream_sys_t::canDecodeAudio(vlc_fourcc_t i_codec) const +std::string dlna_write_protocol_info (const protocol_info_t info) { - return i_codec == VLC_CODEC_MP4A; + std::ostringstream protocol; + char dlna_info[448]; + + if (info.transport == DLNA_TRANSPORT_PROTOCOL_HTTP) + protocol << "http-get:*:"; + + protocol << info.profile.mime; + protocol << ":"; + + if (info.profile.name != "*") + protocol << "DLNA.ORG_PN=" << info.profile.name.c_str() << ";"; + + dlna_org_flags_t flags = DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE | + DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE | + DLNA_ORG_FLAG_CONNECTION_STALL | + DLNA_ORG_FLAG_DLNA_V15; + sprintf (dlna_info, "%s=%.2x;%s=%d;%s=%.8x%.24x", + "DLNA.ORG_OP", DLNA_ORG_OPERATION_RANGE, + "DLNA.ORG_CI", info.ci, + "DLNA.ORG_FLAGS", flags, 0); + protocol << dlna_info; + + return protocol.str(); +} + +std::vector<std::string> split(const std::string &s, char delim) { + std::stringstream ss(s); + std::string item; + std::vector<std::string> elems; + while (std::getline(ss, item, delim)) { + elems.push_back(std::move(item)); + } + return elems; +} + +ProtocolPtr sout_stream_sys_t::canDecodeAudio(vlc_fourcc_t audio_codec) const +{ + for (protocol_info_t protocol : device_protocols) { + if (protocol.profile.media == DLNA_CLASS_AUDIO + && protocol.profile.audio_codec == audio_codec) + { + return std::unique_ptr<protocol_info_t>(new protocol_info_t(protocol)); + } + } + return nullptr; } -bool sout_stream_sys_t::canDecodeVideo(vlc_fourcc_t i_codec) const +ProtocolPtr sout_stream_sys_t::canDecodeVideo(vlc_fourcc_t audio_codec, + vlc_fourcc_t video_codec) const { - return i_codec == VLC_CODEC_H264; + for (protocol_info_t protocol : device_protocols) { + if (protocol.profile.media == DLNA_CLASS_AV + && protocol.profile.audio_codec == audio_codec + && protocol.profile.video_codec == video_codec) + { + return std::unique_ptr<protocol_info_t>(new protocol_info_t(protocol)); + } + } + return nullptr; } bool sout_stream_sys_t::startSoutChain(sout_stream_t *p_stream, @@ -279,32 +334,12 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream ) const es_format_t *p_es = &stream->fmt; if (p_es->i_cat == AUDIO_ES) { - if (!canDecodeAudio( p_es->i_codec )) - { - msg_Dbg( p_stream, "can't remux audio track %d codec %4.4s", - p_es->i_id, (const char*)&p_es->i_codec ); - p_original_audio = p_es; - canRemux = false; - } - else if (i_codec_audio == 0) - { - i_codec_audio = p_es->i_codec; - } + p_original_audio = p_es; new_streams.push_back(stream); } else if (b_supports_video && p_es->i_cat == VIDEO_ES) { - if (!canDecodeVideo( p_es->i_codec )) - { - msg_Dbg( p_stream, "can't remux video track %d codec %4.4s", - p_es->i_id, (const char*)&p_es->i_codec ); - p_original_video = p_es; - canRemux = false; - } - else if (i_codec_video == 0) - { - i_codec_video = p_es->i_codec; - } + p_original_video = p_es; new_streams.push_back(stream); } } @@ -312,6 +347,62 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream ) if (new_streams.empty()) return VLC_SUCCESS; + ProtocolPtr stream_protocol; + // check if we have an audio only stream + if (!p_original_video && p_original_audio) + { + if( !(stream_protocol = canDecodeAudio(p_original_audio->i_codec)) ) + { + msg_Dbg( p_stream, "can't remux audio track %d codec %4.4s", + p_original_audio->i_id, (const char*)&p_original_audio->i_codec ); + stream_protocol = make_protocol(default_audio_protocol); + canRemux = false; + } + else + i_codec_audio = p_original_audio->i_codec; + } + // video only stream + else if (p_original_video && !p_original_audio) + { + if( !(stream_protocol = canDecodeVideo(VLC_CODEC_NONE, + p_original_video->i_codec)) ) + { + msg_Dbg(p_stream, "can't remux video track %d codec: %4.4s", + p_original_video->i_id, (const char*)&p_original_video->i_codec); + stream_protocol = make_protocol(default_video_protocol); + canRemux = false; + } + else + i_codec_video = p_original_video->i_codec; + } + else + { + if( !(stream_protocol = canDecodeVideo( p_original_audio->i_codec, + p_original_video->i_codec)) ) + { + msg_Dbg(p_stream, "can't remux video track %d with audio: %4.4s and video: %4.4s", + p_original_video->i_id, (const char*)&p_original_audio->i_codec, + (const char*)&p_original_video->i_codec); + stream_protocol = make_protocol(default_video_protocol); + canRemux = false; + + // check which codec needs transcoding + if (stream_protocol->profile.audio_codec == p_original_audio->i_codec) + i_codec_audio = p_original_audio->i_codec; + if (stream_protocol->profile.video_codec == p_original_video->i_codec) + i_codec_video = p_original_video->i_codec; + } + else + { + i_codec_audio = p_original_audio->i_codec; + i_codec_video = p_original_video->i_codec; + } + } + + msg_Dbg( p_stream, "using DLNA profile %s:%s", + stream_protocol->profile.mime.c_str(), + stream_protocol->profile.name.c_str() ); + std::ostringstream ssout; if ( !canRemux ) { @@ -338,13 +429,13 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream ) ssout << "transcode{"; if ( i_codec_audio == 0 && p_original_audio ) { - i_codec_audio = VLC_CODEC_MP4A; + i_codec_audio = stream_protocol->profile.audio_codec; ssout << GetAcodecOption( p_stream, &i_codec_audio, &p_original_audio->audio, i_quality ); } if ( i_codec_video == 0 && p_original_video ) { - i_codec_video = VLC_CODEC_H264; + i_codec_video = stream_protocol->profile.video_codec; try { ssout << vlc_sout_renderer_GetVcodecOption( p_stream, { i_codec_video }, @@ -364,8 +455,8 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream ) std::string root_url = ss.str(); ssout << "http{dst=:" << http_port << root_url - << ",mux=" << "mp4stream" - << ",access=http{mime=" << "video/mp4" << "}}"; + << ",mux=" << stream_protocol->profile.mux + << ",access=http{mime=" << stream_protocol->profile.mime << "}}"; auto ip = vlc::wrap_cptr<char>(getServerIPAddress()); if (ip == nullptr) @@ -386,7 +477,7 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream ) msg_Dbg(p_stream, "AVTransportURI: %s", uri); renderer->Stop(); - renderer->SetAVTransportURI(uri); + renderer->SetAVTransportURI(uri, *stream_protocol); renderer->Play("1"); free(uri); @@ -506,16 +597,121 @@ int MediaRenderer::Stop() return VLC_SUCCESS; } -int MediaRenderer::SetAVTransportURI(const char* uri) +std::vector<protocol_info_t> MediaRenderer::GetProtocolInfo() +{ + std::string protocol_csv; + std::vector<protocol_info_t> supported_protocols; + std::list<std::pair<const char*, const char*>> arg_list; + + IXML_Document *response = SendAction("GetProtocolInfo", + CONNECTION_MANAGER_SERVICE_TYPE, arg_list); + if(!response) + { + return supported_protocols; + } + + // Get the CSV list of protocols/profiles supported by the device + IXML_NodeList *protocol_list = ixmlDocument_getElementsByTagName( response , "Sink" ); + if( protocol_list ) + { + IXML_Node* protocol_node = ixmlNodeList_item( protocol_list, 0 ); + if ( protocol_node ) + { + IXML_Node* p_text_node = ixmlNode_getFirstChild( protocol_node ); + if ( p_text_node ) + { + protocol_csv.assign(ixmlNode_getNodeValue( p_text_node )); + } + } + ixmlNodeList_free( protocol_list); + } + ixmlDocument_free(response); + + msg_Dbg(parent, "Device supports protocols: %s", protocol_csv.c_str()); + // parse the CSV list + // format: <transportProtocol>:<network>:<mime>:<additionalInfo> + std::vector<std::string> protocols = split(protocol_csv, ','); + for (std::string protocol : protocols ) { + std::vector<std::string> protocol_info = split(protocol, ':'); + + // We only support http transport for now. + if (protocol_info.size() == 4 && protocol_info.at(0) == "http-get") + { + protocol_info_t proto; + + // Get the DLNA profile name + std::string profile_name; + std::string tag = "DLNA.ORG_PN="; + std::size_t index = protocol_info.at(3).find(tag); + + if (protocol_info.at(3) == "*") + { + profile_name = "*"; + } + else if (index != std::string::npos) + { + std::size_t end = protocol_info.at(3).find(';', index + 1); + int start = index + tag.length() - 1; + int length = end - start; + profile_name = protocol_info.at(3).substr(start, length); + } + + // Match our supported profiles to device profiles + for (dlna_profile_t profile : dlna_profile_list) { + if (protocol_info.at(2) == profile.mime + && (profile_name == profile.name || profile_name == "*")) + { + proto.profile = std::move(profile); + supported_protocols.push_back(proto); + // we do not break here to account for wildcards + // as protocolInfo's fourth field aka <additionalInfo> + } + } + } + } + + msg_Dbg( parent , "Got %zu supported profiles", supported_protocols.size() ); + return supported_protocols; +} + +int MediaRenderer::SetAVTransportURI(const char* uri, const protocol_info_t& proto) { + static const char didl[] = + "<DIDL-Lite " + "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" " + "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\" " + "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<item id=\"f-0\" parentID=\"0\" restricted=\"0\">" + "<dc:title>%s</dc:title>" + "<upnp:class>%s</upnp:class>" + "<res protocolInfo=\"%s\">%s</res>" + "</item>" + "</DIDL-Lite>"; + + bool audio = proto.profile.media == DLNA_CLASS_AUDIO; + std::string dlna_protocol = dlna_write_protocol_info(proto); + + char *meta_data; + if (asprintf(&meta_data, didl, + audio ? "Audio" : "Video", + audio ? "object.item.audioItem" : "object.item.videoItem", + dlna_protocol.c_str(), + uri) < 0) { + return VLC_ENOMEM; + } + + msg_Dbg(parent, "didl: %s", meta_data); std::list<std::pair<const char*, const char*>> arg_list = { {"InstanceID", "0"}, {"CurrentURI", uri}, - {"CurrentURIMetaData", ""}, // NOT_IMPLEMENTED + {"CurrentURIMetaData", meta_data}, }; IXML_Document *p_response = SendAction("SetAVTransportURI", AV_TRANSPORT_SERVICE_TYPE, arg_list); + + free(meta_data); if(!p_response) { return VLC_EGENERIC; @@ -651,6 +847,8 @@ int OpenSout( vlc_object_t *p_this ) goto error; } + p_sys->device_protocols = p_sys->renderer->GetProtocolInfo(); + p_stream->pf_add = Add; p_stream->pf_del = Del; p_stream->pf_send = Send; diff --git a/modules/stream_out/dlna/dlna.hpp b/modules/stream_out/dlna/dlna.hpp index 9768d38336fb..d4a18ebd526a 100644 --- a/modules/stream_out/dlna/dlna.hpp +++ b/modules/stream_out/dlna/dlna.hpp @@ -26,6 +26,44 @@ #include "../../services_discovery/upnp-wrapper.hpp" #include "dlna_common.hpp" +#include "profile_names.hpp" + +struct protocol_info_t { + protocol_info_t() = default; + protocol_info_t(const protocol_info_t&) = default; + + // aggreate initializers do not work in c++11 + // for class types with default member initializers + protocol_info_t(dlna_transport_protocol_t transport, + dlna_org_conversion_t ci, + dlna_profile_t profile) + : transport(transport) + , ci(ci) + , profile(profile) + {} + + dlna_transport_protocol_t transport = DLNA_TRANSPORT_PROTOCOL_HTTP; + dlna_org_conversion_t ci = DLNA_ORG_CONVERSION_NONE; + dlna_profile_t profile; +}; + +using ProtocolPtr = std::unique_ptr<protocol_info_t>; +static inline ProtocolPtr make_protocol(protocol_info_t a) +{ + return std::unique_ptr<protocol_info_t>(new protocol_info_t(a)); +} + +const protocol_info_t default_audio_protocol = { + DLNA_TRANSPORT_PROTOCOL_HTTP, + DLNA_ORG_CONVERSION_TRANSCODED, + default_audio_profile, +}; + +const protocol_info_t default_video_protocol = { + DLNA_TRANSPORT_PROTOCOL_HTTP, + DLNA_ORG_CONVERSION_TRANSCODED, + default_video_profile, +}; namespace DLNA { @@ -53,7 +91,8 @@ public: int Play(const char *speed); int Stop(); - int SetAVTransportURI(const char* uri); + std::vector<protocol_info_t> GetProtocolInfo(); + int SetAVTransportURI(const char* uri, const protocol_info_t& proto); }; } diff --git a/modules/stream_out/dlna/profile_names.hpp b/modules/stream_out/dlna/profile_names.hpp new file mode 100644 index 000000000000..a131183f9bed --- /dev/null +++ b/modules/stream_out/dlna/profile_names.hpp @@ -0,0 +1,846 @@ +/***************************************************************************** + * profile_names.hpp : DLNA media profile names + ***************************************************************************** + * Copyright © 2018 VLC authors and VideoLAN + * + * Authors: Shaleen Jain <shaleen@jain.sh> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifndef DLNA_PROFILES_H +#define DLNA_PROFILES_H + +#include<string> +#include<vlc_common.h> +#include<vlc_fourcc.h> +#include<vector> + +#define VLC_CODEC_NONE 0 +#define CODEC_PROFILE_NONE 0 + +enum dlna_transport_protocol_t { + DLNA_TRANSPORT_PROTOCOL_UNKNOWN, + DLNA_TRANSPORT_PROTOCOL_HTTP, + DLNA_TRANSPORT_PROTOCOL_RTP, + DLNA_TRANSPORT_PROTOCOL_ANY +}; + +/** + * DLNA.ORG_CI: conversion indicator parameter (integer) + * 0 not transcoded + * 1 transcoded + */ +enum dlna_org_conversion_t { + DLNA_ORG_CONVERSION_NONE = 0, + DLNA_ORG_CONVERSION_TRANSCODED = 1, +}; + +/** + * DLNA.ORG_OP: operations parameter (string) + * "00" (or "0") neither time seek range nor range supported + * "01" range supported + * "10" time seek range supported + * "11" both time seek range and range supported + */ +enum dlna_org_operation_t { + DLNA_ORG_OPERATION_NONE = 0x00, + DLNA_ORG_OPERATION_RANGE = 0x01, + DLNA_ORG_OPERATION_TIMESEEK = 0x10, +}; + +/** + * DLNA.ORG_FLAGS, padded with 24 trailing 0s + * 80000000 31 senderPaced + * 40000000 30 lsopTimeBasedSeekSupported + * 20000000 29 lsopByteBasedSeekSupported + * 10000000 28 playcontainerSupported + * 8000000 27 s0IncreasingSupported + * 4000000 26 sNIncreasingSupported + * 2000000 25 rtspPauseSupported + * 1000000 24 streamingTransferModeSupported + * 800000 23 interactiveTransferModeSupported + * 400000 22 backgroundTransferModeSupported + * 200000 21 connectionStallingSupported + * 100000 20 dlnaVersion15Supported + * + * Example: (1 << 24) | (1 << 22) | (1 << 21) | (1 << 20) + * DLNA.ORG_FLAGS=01700000[000000000000000000000000] // [] show padding + */ +enum dlna_org_flags_t { + DLNA_ORG_FLAG_SENDER_PACED = (1 << 31), + DLNA_ORG_FLAG_TIME_BASED_SEEK = (1 << 30), + DLNA_ORG_FLAG_BYTE_BASED_SEEK = (1 << 29), + DLNA_ORG_FLAG_PLAY_CONTAINER = (1 << 28), + DLNA_ORG_FLAG_S0_INCREASE = (1 << 27), + DLNA_ORG_FLAG_SN_INCREASE = (1 << 26), + DLNA_ORG_FLAG_RTSP_PAUSE = (1 << 25), + DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE = (1 << 24), + DLNA_ORG_FLAG_INTERACTIVE_TRANSFERT_MODE = (1 << 23), + DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE = (1 << 22), + DLNA_ORG_FLAG_CONNECTION_STALL = (1 << 21), + DLNA_ORG_FLAG_DLNA_V15 = (1 << 20), +}; + +inline dlna_org_flags_t operator|(dlna_org_flags_t a, dlna_org_flags_t b) +{ + return static_cast<dlna_org_flags_t>(static_cast<int>(a) | static_cast<int>(b)); +} + +enum dlna_media_class_t { + DLNA_CLASS_UNKNOWN, + DLNA_CLASS_IMAGE, + DLNA_CLASS_AUDIO, + DLNA_CLASS_AV, + DLNA_CLASS_COLLECTION +}; + +/** + * DLNA profile. + * This specifies the DLNA profile one file/stream is compatible with. + */ +class dlna_profile_t { +public: + std::string name; + std::string mux; + std::string mime; + dlna_media_class_t media; + vlc_fourcc_t video_codec; + vlc_fourcc_t audio_codec; + + dlna_profile_t() + : video_codec(VLC_CODEC_UNKNOWN) + , audio_codec(VLC_CODEC_UNKNOWN) + {}; + + dlna_profile_t(std::string profile, std::string mux, std::string mime, + vlc_fourcc_t video, vlc_fourcc_t audio) + : name(std::move(profile)) + , mux(std::move(mux)) + , mime(std::move(mime)) + , media(DLNA_CLASS_AV) + , video_codec(video) + , audio_codec(audio) + {}; + + dlna_profile_t(std::string profile, std::string mux, std::string mime, + dlna_media_class_t media, vlc_fourcc_t video, vlc_fourcc_t audio) + : name(std::move(profile)) + , mux(std::move(mux)) + , mime(std::move(mime)) + , media(media) + , video_codec(video) + , audio_codec(audio) + {}; +}; + +const dlna_profile_t default_audio_profile = { + "AAC_ISO_320", + "mp4stream", + "audio/mp4", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MP4A, +}; + +/** + * AVC Main Profile SD video with MPEG-4 AAC audio, encapsulated in MP4. + */ +const dlna_profile_t default_video_profile = { + "AVC_MP4_MP_SD", + "mp4stream", + "video/mp4", + DLNA_CLASS_AV, + VLC_CODEC_H264, + VLC_CODEC_MP4A, +}; + +std::vector<dlna_profile_t> dlna_profile_list = { + + default_audio_profile, + default_video_profile, + + //------ Audio Profiles ------// + + { + "*", + "ogg", + "application/ogg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_VORBIS, + }, + { + "*", + "ogg", + "application/ogg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_OPUS, + }, + { + "*", + "ogg", + "audio/x-vorbis", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_VORBIS, + }, + { + "*", + "ogg", + "audio/x-vorbis+ogg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_VORBIS, + }, + { + "*", + "ogg", + "audio/ogg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_OPUS, + }, + { + "*", + "ogg", + "audio/ogg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_VORBIS, + }, + { + "AAC_ISO", + "mp4stream", + "audio/mp4", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MP4A, + }, + { + "MP3", + "ts", + "audio/mpeg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MP3, + }, + { + "MP3", + "ts", + "audio/mpeg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MPGA, + }, + { + "MP3X", + "ts", + "audio/mpeg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MPGA, + }, + { + "MP3X", + "ts", + "audio/mpeg", + DLNA_CLASS_AUDIO, + VLC_CODEC_NONE, + VLC_CODEC_MP3, + }, + + //------ Video Profiles ------// + + /** + * MPEG-2 HD/SD video wrapped in MPEG-2 transport stream as constrained by + * SCTE-43 standards, with AC-3 audio, without a timestamp field + */ + { + "MPEG_TS_NA_ISO", + "ts", + "video/mpeg", + VLC_CODEC_MP2V, + VLC_CODEC_A52, + }, + /** + * North America region profile for MPEG-2 HD + * 3Dframe-compatible video with AC-3 audio, + * utilizing a DLNA Transport Packet without a Timestamp field + */ + { + "MPEG_TS_NA_3DFC_ISO", + "ts", + "video/mpeg", + VLC_CODEC_MP2V, + VLC_CODEC_A52, + }, + /** + * MPEG-2 Video, wrapped in MPEG-2 transport stream, Main Profile, + * Standard Definition, with AC-3 audio, without a timestamp field. + */ + { + "MPEG_TS_SD_EU_AC3_ISO", + "ts", + "video/mpeg", + VLC_CODEC_MP2V, + VLC_CODEC_A52, + }, + /** + * MPEG-2 Video, wrapped in MPEG-2 transport stream, Main Profile + * Standard Definition, with AC-3 audio, with a valid non-zero timestamp + * field. + */ + { + "MPEG_TS_SD_EU_AC3_T", + "ts", + "video/mpeg", + VLC_CODEC_MP2V, + VLC_CODEC_A52, + }, + /** + * MPEG-2 Main Profile at Main, High-1 440 and High Level with MPEG-2 AAC + * encapsulated in MPEG-2 TS with valid timestamp + */ + { + "MPEG_TS_JP_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_MP2V, + VLC_CODEC_MP4A, + }, + /** + * MPEG-2 Video, encapsulated in MPEG-2 transport stream, Main Profile + * at Main Level, with MPEG-1 L2 audio, with a valid non-zero timestamp + * field. + */ + { + "MPEG_TS_SD_JP_MPEG1_L2_T", + "ts", + "video/mpeg", + VLC_CODEC_MP2V, + VLC_CODEC_MP2, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, with a valid + * non-zero timestamp field. + */ + { + "AVC_TS_NA_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, with a valid + * non-zero timestamp field. + */ + { + "AVC_TS_NA_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, with a valid + * non-zero timestamp field. + */ + { + "AVC_TS_NA_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, with a valid + * non-zero timestamp field. + */ + { + "AVC_TS_NA_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_MP2, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, + * without a timestamp field. + */ + { + "AVC_TS_NA_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, + * without a timestamp field. + */ + { + "AVC_TS_NA_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, + * without a timestamp field. + */ + { + "AVC_TS_NA_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC video wrapped in MPEG-2 transport stream, as + * constrained by SCTE standards, + * with AC-3, Enhanced AC-3, MPEG-4 HE-AAC + * v2 or MPEG-1 Layer II audio, + * without a timestamp field. + */ + { + "AVC_TS_NA_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_MP2, + }, + /** + * AVC high profile, HD 3D frame-compatible video + * wrapped in MPEG-2 transport stream with AC-3, + * Enhanced AC-3 or HE AAC audio, without a Timestamp field. + */ + { + "AVC_TS_NA_3DFC_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC high profile, HD 3D frame-compatible video + * wrapped in MPEG-2 transport stream with AC-3, + * Enhanced AC-3 or HE AAC audio, without a Timestamp field. + */ + { + "AVC_TS_NA_3DFC_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC high profile, HD 3D frame-compatible video + * wrapped in MPEG-2 transport stream with AC-3, + * Enhanced AC-3 or HE AAC audio, without a Timestamp field. + */ + { + "AVC_TS_NA_3DFC_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC video wrapped in MPEG-2 TS transport stream + * as constrained by DVB standards, with AC-3, + * Enhanced AC-3 and MPEG-4 HE-AAC v2 audio. + */ + { + "AVC_TS_EU_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC video wrapped in MPEG-2 TS transport stream + * as constrained by DVB standards, with AC-3, + * Enhanced AC-3 and MPEG-4 HE-AAC v2 audio. + */ + { + "AVC_TS_EU_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC video wrapped in MPEG-2 TS transport stream + * as constrained by DVB standards, with AC-3, + * Enhanced AC-3 and MPEG-4 HE-AAC v2 audio. + */ + { + "AVC_TS_EU_ISO", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * European region profile for HD/SD resolution. + * AVC video using the Scalable High Profile (SVC) + * wrapped in MPEG-2 Transport Stream with AC-3 audio, + * with a valid non-zero timestamp field. + */ + { + "AVC_TS_SHP_HD_EU_AC3_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * European region profile for HD/SD resolution. AVC video using the + * Scalable High Profile (SVC) wrapped in MPEG-2 Transport Stream + * with MPEG-4 HE-AAC v2 Level 4 audio, with a valid non-zero timestamp field. + */ + { + "AVC_TS_SHP_HD_EU_HEAACv2_L4_T", + "ts", + "video/vnd.dlna.mpeg-tts", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC HD/SD video with AC-3 audio including dual-mono channel mode, wrapped + * in MPEG-2 TS with valid timestamp for 24 Hz system. + */ + { + "AVC_TS_HD_24_AC3_X_T", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC HD/SD video with AC-3 audio including dual-mono channel mode, wrapped + * in MPEG-2 TS with valid timestamp for 50 Hz system. + */ + { + "AVC_TS_HD_50_AC3_X_T", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC HD/SD video with AC-3 audio including dual-mono channel mode, + * wrapped in MPEG-2 TS with valid timestamp for 60 Hz system. + */ + { + "AVC_TS_HD_60_AC3_X_T", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC wrapped in MPEG-2 transport stream, Main/High profile, with + * MPEG-2 AAC audio, with a valid non-zero timestamp field. + */ + { + "AVC_TS_JP_AAC_T", + "ts", + "video/mpeg", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC video with MPEG-4 HE-AAC v2 + * and Enhanced AC-3 audio, encapsulated in MP4. + */ + { + "AVC_MP4_EU", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC video with MPEG-4 HE-AAC v2 + * and Enhanced AC-3 audio, encapsulated in MP4. + */ + { + "AVC_MP4_EU", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_A52, + }, + /** + * AVC wrapped in MP4 baseline profile CIF15 with AAC LC audio. + */ + { + "AVC_MP4_BL_CIF15_AAC_520", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC wrapped in MP4 baseline profile CIF30 with AAC LC audio. + */ + { + "AVC_MP4_BL_CIF30_AAC_940", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile video with Enhanced AC-3 audio, encapsulated in MP4. + */ + { + "AVC_MP4_MP_SD_EAC3", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC High Profile HD video with MPEG-4 AAC audio, encapsulated in MP4. + */ + { + "AVC_MP4_MP_SD", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC High Profile video with Enhanced AC-3 audio, encapsulated in MP4. + */ + { + "AVC_MP4_HP_HD_EAC3", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_EAC3, + }, + /** + * AVC high profile video with HE AAC v2 stereo or HE AAC 7.1-channel audio, + * encapsulated in an MP4 file. + */ + { + "AVC_MP4_HD_HEAACv2_L6", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile video with MPEG-4 AAC audio, encapsulated in MKV. + */ + { + "AVC_MKV_MP_HD_AAC_MULT5", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile video with MPEG-4 HE-AAC audio, encapsulated in MKV. + */ + { + "AVC_MKV_MP_HD_HEAAC_L4", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile video with MP3 audio, encapsulated in MKV + */ + { + "AVC_MKV_MP_HD_MPEG1_L3", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MPGA, + }, + /** + * AVC Main Profile video with MP3 audio, encapsulated in MKV + */ + { + "AVC_MKV_MP_HD_MPEG1_L3", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP3, + }, + /** + * AVC High Profile video with MP3 audio, encapsulated in MKV + */ + { + "AVC_MKV_HP_HD_MPEG1_L3", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MPGA, + }, + /** + * AVC High Profile video with MP3 audio, encapsulated in MKV + */ + { + "AVC_MKV_HP_HD_MPEG1_L3", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP3, + }, + /** + * AVC High Profile video with MPEG-4 AAC audio, encapsulated in MKV. + */ + { + "AVC_MKV_HP_HD_AAC_MULT5", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC High Profile video with MPEG-4 HE-AAC audio, encapsulated in MKV. + */ + { + "AVC_MKV_HP_HD_HEAAC_L4", + "avformat{mux=matroska,options={live=1}}", + "video/x-matroska", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC SD video wrapped in MPEG-2 transport stream, as constrained by + * SCTE standards, with AAC audio and optional enhanced audio, + * without a timestamp field and constrained to an SD video profile + */ + { + "DASH_AVC_TS_SD_ISO", + "ts", + "video/mp2t", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC HD video wrapped in MPEG-2 transport stream, as constrained by + * SCTE standards, with AAC audio and optional enhanced audio, + * without a timestamp field and constrained to an HD video profile + */ + { + "DASH_AVC_TS_HD_ISO", + "ts", + "video/mp2t", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile SD video with AAC audio and optional enhanced audio, + * encapsulated in MP4 conforming to the additional DECE CFF requirements + * including encryption and constrained to the DECE SD profile requirements. + */ + { + "DASH_AVC_MP4_SD", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile HD video with AAC audio and optional enhanced audio, + * encapsulated in MP4 conforming to the additional DECE CFF requirements + * including encryption and constrained to the DECE HD profile requirements. + */ + { + "DASH_AVC_MP4_HD", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC Main Profile video with HE AACv2 L4 audio, encapsulated in MP4. + */ + { + "DASH_AVC_MP4_SD_HEAACv2_L4", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC High Profile video with HE AACv2 L4 audio, encapsulated in MP4. + */ + { + "DASH_AVC_MP4_HD_HEAACv2_L4", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * AVC high profile video with HE AAC v2 stereo or HE AAC 7.1-channel audio, + * encapsulated in an MP4 file suitable for MPEG DASH conformant adaptive delivery + */ + { + "DASH_AVC_MP4_HD_HEAACv2_L6", + "mp4stream", + "video/mp4", + VLC_CODEC_H264, + VLC_CODEC_MP4A, + }, + /** + * HEVC High Profile HD and UHD video with AC-3, + * Enhanced AC-3, HE-AACv2 or MPEG-1 LII audio, + * encapsulated in MP4. + */ + { + "DASH_HEVC_MP4_UHD_NA", + "mp4stream", + "video/mp4", + VLC_CODEC_HEVC, + VLC_CODEC_MP2, + }, +}; + +#endif /* DLNA_PROFILES_H */ -- GitLab