[vlc-devel] [PATCH 5/5] dlna: add GetProtocolInfo action
Shaleen Jain
shaleen at jain.sh
Tue Oct 23 08:51:22 CEST 2018
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.
---
modules/services_discovery/Makefile.am | 1 +
modules/stream_out/dlna/dlna.cpp | 273 ++++++-
modules/stream_out/dlna/dlna.hpp | 28 +-
modules/stream_out/dlna/profile_names.hpp | 833 ++++++++++++++++++++++
4 files changed, 1099 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 1b59cb1e4f..0b3dea0247 100644
--- a/modules/services_discovery/Makefile.am
+++ b/modules/services_discovery/Makefile.am
@@ -29,6 +29,7 @@ sd_LTLIBRARIES += $(LTLIBmtp)
libupnp_plugin_la_SOURCES = services_discovery/upnp.cpp services_discovery/upnp.hpp \
services_discovery/upnp-wrapper.hpp \
services_discovery/upnp-wrapper.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 e0c266d8e3..39acfd0150 100644
--- a/modules/stream_out/dlna/dlna.cpp
+++ b/modules/stream_out/dlna/dlna.cpp
@@ -66,8 +66,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 );
@@ -84,6 +85,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 GetVencOption( sout_stream_t *, vlc_fourcc_t *,
@@ -154,14 +156,66 @@ char *getServerIPAddress() {
return ip;
}
-bool sout_stream_sys_t::canDecodeAudio(vlc_fourcc_t i_codec) const
+std::string dlna_write_protocol_info (dlna_transport_protocol_t type,
+ dlna_org_conversion_t ci,
+ dlna_org_operation_t op,
+ dlna_org_flags_t flags,
+ dlna_profile_t p)
{
- return i_codec == VLC_CODEC_MP4A;
+ std::ostringstream protocol;
+ char dlna_info[448];
+
+ if (type == DLNA_TRANSPORT_PROTOCOL_HTTP)
+ protocol << "http-get:*:";
+
+ protocol << p.mime;
+ protocol << ":";
+
+ if (p.name != "*")
+ protocol << "DLNA.ORG_PN=" << p.name.c_str() << ";";
+
+ sprintf (dlna_info, "%s=%.2x;%s=%d;%s=%.8x%.24x",
+ "DLNA.ORG_OP", op, "DLNA.ORG_CI", ci,
+ "DLNA.ORG_FLAGS", flags, 0);
+ protocol << dlna_info;
+
+ return protocol.str();
}
-bool sout_stream_sys_t::canDecodeVideo(vlc_fourcc_t i_codec) const
+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(item);
+ }
+ return elems;
+}
+
+ProtocolPtr sout_stream_sys_t::canDecodeAudio(vlc_fourcc_t audio_codec) const
{
- return i_codec == VLC_CODEC_H264;
+ for (protocol_info_t protocol : device_protocols) {
+ if (protocol.profile.media == DLNA_CLASS_AUDIO
+ && protocol.profile.audio_codec == audio_codec)
+ {
+ return std::make_unique<protocol_info_t>(protocol);
+ }
+ }
+ return nullptr;
+}
+
+ProtocolPtr sout_stream_sys_t::canDecodeVideo(vlc_fourcc_t audio_codec,
+ vlc_fourcc_t video_codec) const
+{
+ 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::make_unique<protocol_info_t>(protocol);
+ }
+ }
+ return nullptr;
}
bool sout_stream_sys_t::startSoutChain(sout_stream_t *p_stream,
@@ -495,32 +549,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);
}
}
@@ -528,6 +562,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 )
{
@@ -554,13 +644,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;
ssout << GetVcodecOption( p_stream, &i_codec_video,
&p_original_video->video, i_quality );
}
@@ -575,8 +665,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 << "}}";
char *ip = getServerIPAddress();
if (ip == NULL)
@@ -595,7 +685,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);
@@ -713,15 +803,126 @@ 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
+ if( IXML_NodeList *protocol_list = ixmlDocument_getElementsByTagName( response , "Sink" ) )
+ {
+ if ( IXML_Node* protocol_node = ixmlNodeList_item( protocol_list, 0 ) )
+ {
+ 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=";
+
+ if (protocol_info.at(3) == "*")
+ {
+ profile_name = "*";
+ }
+ else if (std::size_t index = protocol_info.at(3).find(tag) != 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;
+ 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;
+ std::string dlna_protocol = dlna_write_protocol_info(proto.transport,
+ proto.ci,
+ DLNA_ORG_OPERATION_RANGE,
+ flags,
+ proto.profile
+ );
+
+ 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;
arg_list.push_back(std::make_pair("InstanceID", "0"));
arg_list.push_back(std::make_pair("CurrentURI", uri));
- arg_list.push_back(std::make_pair("CurrentURIMetaData", "")); // NOT_IMPLEMENTED
+ arg_list.push_back(std::make_pair("CurrentURIMetaData", meta_data));
IXML_Document *p_response = SendAction("SetAVTransportURI",
AV_TRANSPORT_SERVICE_TYPE, arg_list);
+
+ free(meta_data);
if(!p_response)
{
return VLC_EGENERIC;
@@ -855,6 +1056,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 59ff3d6c8d..7dcc2d7007 100644
--- a/modules/stream_out/dlna/dlna.hpp
+++ b/modules/stream_out/dlna/dlna.hpp
@@ -26,6 +26,31 @@
#include "../../services_discovery/upnp-wrapper.hpp"
#include "dlna_common.hpp"
+#include "profile_names.hpp"
+
+struct protocol_info_t {
+ dlna_transport_protocol_t transport = DLNA_TRANSPORT_PROTOCOL_HTTP;
+ dlna_org_conversion_t ci = DLNA_ORG_CONVERSION_NONE;
+ dlna_profile_t profile;
+};
+
+typedef std::unique_ptr<protocol_info_t> ProtocolPtr;
+inline ProtocolPtr make_protocol(protocol_info_t a)
+{
+ return std::make_unique<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 +78,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 0000000000..3a00f7b41a
--- /dev/null
+++ b/modules/stream_out/dlna/profile_names.hpp
@@ -0,0 +1,833 @@
+/*****************************************************************************
+ * profile_names.hpp : DLNA media profile names
+ *****************************************************************************
+ * Copyright (C) 2004-2018 VLC authors and VideoLAN
+ *
+ * Authors: Shaleen Jain <shaleen at 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()
+ : name()
+ , mux()
+ , mime()
+ , 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(profile)
+ , mux(mux)
+ , mime(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(profile)
+ , mux(mux)
+ , mime(mime)
+ , media(media)
+ , video_codec(video)
+ , audio_codec(audio)
+ {};
+};
+
+const dlna_profile_t default_audio_profile = {
+ "MP3",
+ "ts",
+ "audio/mpeg",
+ DLNA_CLASS_AUDIO,
+ VLC_CODEC_NONE,
+ VLC_CODEC_MPGA,
+};
+
+/**
+ * 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,
+ },
+ {
+ "MP3",
+ "ts",
+ "audio/mpeg",
+ DLNA_CLASS_AUDIO,
+ VLC_CODEC_NONE,
+ VLC_CODEC_MP3,
+ },
+ {
+ "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 */
--
2.19.1
More information about the vlc-devel
mailing list