diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2014-02-26 02:03:47 +0400 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2014-03-04 16:49:53 +0400 |
commit | 05bc672e969c8a2fcacc3f9175f7f4df7d70dc42 (patch) | |
tree | c7b52830d8448cca46c3fe018f5dbb6f71fe62ff /demuxer | |
parent | 9c60f574f0b4073ebb8a9aa295113abe0c3fb912 (diff) |
Parsing of ICY metadata
Diffstat (limited to 'demuxer')
-rw-r--r-- | demuxer/Demuxers/LAVFDemuxer.cpp | 54 | ||||
-rw-r--r-- | demuxer/Demuxers/LAVFDemuxer.h | 3 |
2 files changed, 57 insertions, 0 deletions
diff --git a/demuxer/Demuxers/LAVFDemuxer.cpp b/demuxer/Demuxers/LAVFDemuxer.cpp index 409db466..ce31ab0e 100644 --- a/demuxer/Demuxers/LAVFDemuxer.cpp +++ b/demuxer/Demuxers/LAVFDemuxer.cpp @@ -445,6 +445,30 @@ STDMETHODIMP CLAVFDemuxer::InitAVFormat(LPCOLESTR pszFileName, BOOL bForce) CheckBDM2TSCPLI(pszFileName); } + char *icy_headers = nullptr; + if (av_opt_get(m_avFormat, "icy_metadata_headers", AV_OPT_SEARCH_CHILDREN, (uint8_t **)&icy_headers) >= 0 && icy_headers && strlen(icy_headers) > 0) { + std::string icyHeaders(icy_headers); + std::stringstream icyHeaderStream(icyHeaders); + + std::string line; + while (std::getline(icyHeaderStream, line)) { + int seperatorIdx = line.find_first_of(":"); + std::string token = line.substr(0, seperatorIdx); + std::string value = line.substr(seperatorIdx + 1); + if (_stricmp(token.c_str(), "icy-name") == 0) { + // not entirely correct, but this way it gets exported through IAMMediaContent + av_dict_set(&m_avFormat->metadata, "artist", value.c_str(), 0); + } else if (_stricmp(token.c_str(), "icy-description") == 0) { + av_dict_set(&m_avFormat->metadata, "comment", value.c_str(), 0); + } else if (_stricmp(token.c_str(), "icy-genre") == 0) { + av_dict_set(&m_avFormat->metadata, "genre", value.c_str(), 0); + } + } + + ParseICYMetadataPacket(); + } + av_freep(&icy_headers); + SAFE_CO_FREE(m_stOrigParser); m_stOrigParser = (enum AVStreamParseType *)CoTaskMemAlloc(m_avFormat->nb_streams * sizeof(enum AVStreamParseType)); if (!m_stOrigParser) @@ -870,6 +894,34 @@ STDMETHODIMP CLAVFDemuxer::CreatePacketMediaType(Packet *pPacket, enum AVCodecID return S_OK; } +STDMETHODIMP CLAVFDemuxer::ParseICYMetadataPacket() +{ + char *icy_data = nullptr; + if (av_opt_get(m_avFormat, "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN, (uint8_t **)&icy_data) >= 0 && icy_data && strlen(icy_data) > 0) { + std::string icyData(icy_data); + size_t idx = icyData.find("StreamTitle"); + if (idx != std::string::npos) { + // strip StreamTitle token and = + std::string value = icyData.substr(idx + 12); + idx = value.find_first_of(";"); + if (idx != std::string::npos) + value = value.substr(0, idx); + if (value[0] == '\'' || value[0] == '"') + value = value.substr(1); + if (value[value.length() - 1] == '\'' || value[value.length() - 1] == '"') + value = value.substr(0, value.length() - 1); + if (value.length() > 0) { + av_dict_set(&m_avFormat->metadata, "title", value.c_str(), 0); + } + } + // clear value, and only read again when its send again + av_opt_set(m_avFormat, "icy_metadata_packet", "", AV_OPT_SEARCH_CHILDREN); + } + av_freep(&icy_data); + + return S_OK; +} + STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket) { CheckPointer(ppPacket, E_POINTER); @@ -1051,6 +1103,8 @@ STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket) return E_FAIL; } + ParseICYMetadataPacket(); + *ppPacket = pPacket; return S_OK; } diff --git a/demuxer/Demuxers/LAVFDemuxer.h b/demuxer/Demuxers/LAVFDemuxer.h index 35511675..a740366f 100644 --- a/demuxer/Demuxers/LAVFDemuxer.h +++ b/demuxer/Demuxers/LAVFDemuxer.h @@ -21,6 +21,8 @@ #include <Qnetwork.h> #include <set> +#include <algorithm> +#include <sstream> #include "BaseDemuxer.h" #include "IKeyFrameInfo.h" @@ -162,6 +164,7 @@ private: STDMETHODIMP GetBSTRMetadata(const char *key, BSTR *pbstrValue, int stream = -1); STDMETHODIMP CreatePacketMediaType(Packet *pPacket, enum AVCodecID codec_id, BYTE *extradata, int extradata_size, BYTE *paramchange, int paramchange_size); + STDMETHODIMP ParseICYMetadataPacket(); private: AVFormatContext *m_avFormat = nullptr; |