diff options
author | Underground78 <underground78@users.sourceforge.net> | 2013-09-08 22:49:23 +0400 |
---|---|---|
committer | Underground78 <underground78@users.sourceforge.net> | 2013-09-27 21:43:56 +0400 |
commit | 1c821dc0335af018da1b64ae3935ea15966d2bec (patch) | |
tree | b0dd2365c0ab6d94bbc97fbfb8b00582691ac8c7 | |
parent | 4a20646e056d612aea9eafbbfba59fc60ed7ce8c (diff) |
[MPC-HC] LAV Splitter: Exhibits MKV attachments through IDSMResourceBag interface.mpc-hc-1.7.0-5
-rw-r--r-- | common/DSUtilLite/DSMResourceBag.cpp | 191 | ||||
-rw-r--r-- | common/DSUtilLite/DSMResourceBag.h | 79 | ||||
-rw-r--r-- | common/DSUtilLite/DSUtilLite.vcxproj | 2 | ||||
-rw-r--r-- | common/DSUtilLite/DSUtilLite.vcxproj.filters | 6 | ||||
-rw-r--r-- | demuxer/Demuxers/LAVFDemuxer.cpp | 28 | ||||
-rw-r--r-- | demuxer/Demuxers/LAVFDemuxer.h | 4 | ||||
-rw-r--r-- | demuxer/LAVSplitter/LAVSplitter.cpp | 3 |
7 files changed, 307 insertions, 6 deletions
diff --git a/common/DSUtilLite/DSMResourceBag.cpp b/common/DSUtilLite/DSMResourceBag.cpp new file mode 100644 index 00000000..2e43ddf1 --- /dev/null +++ b/common/DSUtilLite/DSMResourceBag.cpp @@ -0,0 +1,191 @@ +/* + * (C) 2003-2006 Gabest + * (C) 2006-2013 see Authors.txt + * + * This file is part of MPC-HC. + * + * MPC-HC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * MPC-HC 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "stdafx.h" +#include "DSMResourceBag.h" + + +// +// CDSMResource +// + +CCritSec CDSMResource::m_csResources; +std::map<uintptr_t, CDSMResource*> CDSMResource::m_resources; + +CDSMResource::CDSMResource() + : mime(L"application/octet-stream") + , tag(0) +{ + CAutoLock cAutoLock(&m_csResources); + m_resources[reinterpret_cast<uintptr_t>(this)] = this; +} + +CDSMResource::CDSMResource(const CDSMResource& r) +{ + *this = r; + + CAutoLock cAutoLock(&m_csResources); + m_resources[reinterpret_cast<uintptr_t>(this)] = this; +} + +CDSMResource::CDSMResource(LPCWSTR name, LPCWSTR desc, LPCWSTR mime, BYTE* pData, int len, DWORD_PTR tag) +{ + this->name = name; + this->desc = desc; + this->mime = mime; + data.resize(len); + memcpy(data.data(), pData, data.size()); + this->tag = tag; + + CAutoLock cAutoLock(&m_csResources); + m_resources[reinterpret_cast<uintptr_t>(this)] = this; +} + +CDSMResource::~CDSMResource() +{ + CAutoLock cAutoLock(&m_csResources); + m_resources.erase(reinterpret_cast<uintptr_t>(this)); +} + +CDSMResource& CDSMResource::operator=(const CDSMResource& r) +{ + if (this != &r) { + tag = r.tag; + name = r.name; + desc = r.desc; + mime = r.mime; + data = r.data; + } + return *this; +} + +// +// IDSMResourceBagImpl +// + +IDSMResourceBagImpl::IDSMResourceBagImpl() +{ +} + +// IDSMResourceBag + +STDMETHODIMP_(DWORD) IDSMResourceBagImpl::ResGetCount() +{ + return (DWORD)m_resources.size(); +} + +STDMETHODIMP IDSMResourceBagImpl::ResGet(DWORD iIndex, BSTR* ppName, BSTR* ppDesc, BSTR* ppMime, BYTE** ppData, DWORD* pDataLen, DWORD_PTR* pTag) +{ + if (ppData) { + CheckPointer(pDataLen, E_POINTER); + } + + if (iIndex >= (DWORD)m_resources.size()) { + return E_INVALIDARG; + } + + CDSMResource& r = m_resources[iIndex]; + + if (ppName) { + *ppName = SysAllocString(r.name.data()); + if (*ppName == NULL) + return E_OUTOFMEMORY; + } + if (ppDesc) { + *ppDesc = SysAllocString(r.desc.data()); + if (*ppDesc == NULL) + return E_OUTOFMEMORY; + } + if (ppMime) { + *ppMime = SysAllocString(r.mime.data()); + if (*ppMime == NULL) + return E_OUTOFMEMORY; + } + if (ppData) { + *pDataLen = (DWORD)r.data.size(); + memcpy(*ppData = (BYTE*)CoTaskMemAlloc(*pDataLen), r.data.data(), *pDataLen); + } + if (pTag) { + *pTag = r.tag; + } + + return S_OK; +} + +STDMETHODIMP IDSMResourceBagImpl::ResSet(DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, const BYTE* pData, DWORD len, DWORD_PTR tag) +{ + if (iIndex >= (DWORD)m_resources.size()) { + return E_INVALIDARG; + } + + CDSMResource& r = m_resources[iIndex]; + + if (pName) { + r.name = pName; + } + if (pDesc) { + r.desc = pDesc; + } + if (pMime) { + r.mime = pMime; + } + if (pData || len == 0) { + r.data.resize(len); + if (pData) { + memcpy(r.data.data(), pData, r.data.size()); + } + } + r.tag = tag; + + return S_OK; +} + +STDMETHODIMP IDSMResourceBagImpl::ResAppend(LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag) +{ + m_resources.push_back(CDSMResource()); + return ResSet((DWORD)m_resources.size() - 1, pName, pDesc, pMime, pData, len, tag); +} + +STDMETHODIMP IDSMResourceBagImpl::ResRemoveAt(DWORD iIndex) +{ + if (iIndex >= (DWORD)m_resources.size()) { + return E_INVALIDARG; + } + + m_resources.erase(m_resources.cbegin() + iIndex); + + return S_OK; +} + +STDMETHODIMP IDSMResourceBagImpl::ResRemoveAll(DWORD_PTR tag) +{ + if (tag) { + for (auto crit = m_resources.cend() - 1; crit >= m_resources.begin(); --crit) { + if (crit->tag == tag) { + m_resources.erase(crit); + } + } + } else { + m_resources.clear(); + } + + return S_OK; +} diff --git a/common/DSUtilLite/DSMResourceBag.h b/common/DSUtilLite/DSMResourceBag.h new file mode 100644 index 00000000..a42ee2e1 --- /dev/null +++ b/common/DSUtilLite/DSMResourceBag.h @@ -0,0 +1,79 @@ +/* + * (C) 2003-2006 Gabest + * (C) 2006-2013 see Authors.txt + * + * This file is part of MPC-HC. + * + * MPC-HC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * MPC-HC 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include <string> +#include <vector> +#include <map> + +// IDSMResourceBag + +interface __declspec(uuid("EBAFBCBE-BDE0-489A-9789-05D5692E3A93")) +IDSMResourceBag : +public IUnknown { + STDMETHOD_(DWORD, ResGetCount)() PURE; + STDMETHOD(ResGet)(DWORD iIndex, BSTR * ppName, BSTR * ppDesc, BSTR * ppMime, BYTE** ppData, DWORD * pDataLen, DWORD_PTR * pTag) PURE; + STDMETHOD(ResSet)(DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, const BYTE * pData, DWORD len, DWORD_PTR tag) PURE; + STDMETHOD(ResAppend)(LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE * pData, DWORD len, DWORD_PTR tag) PURE; + STDMETHOD(ResRemoveAt)(DWORD iIndex) PURE; + STDMETHOD(ResRemoveAll)(DWORD_PTR tag) PURE; +}; + +class CDSMResource +{ +public: + DWORD_PTR tag; + std::wstring name, desc, mime; + std::vector<BYTE> data; + CDSMResource(); + CDSMResource(const CDSMResource& r); + CDSMResource(LPCWSTR name, LPCWSTR desc, LPCWSTR mime, BYTE* pData, int len, DWORD_PTR tag = 0); + virtual ~CDSMResource(); + CDSMResource& operator=(const CDSMResource& r); + + // global access to all resources + static CCritSec m_csResources; + static std::map<uintptr_t, CDSMResource*> m_resources; +}; + +class IDSMResourceBagImpl : public IDSMResourceBag +{ +protected: + std::vector<CDSMResource> m_resources; + +public: + IDSMResourceBagImpl(); + + void operator+=(const CDSMResource& r) { m_resources.push_back(r); } + + // IDSMResourceBag + + STDMETHODIMP_(DWORD) ResGetCount(); + STDMETHODIMP ResGet(DWORD iIndex, BSTR* ppName, BSTR* ppDesc, BSTR* ppMime, + BYTE** ppData, DWORD* pDataLen, DWORD_PTR* pTag = nullptr); + STDMETHODIMP ResSet(DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, + const BYTE* pData, DWORD len, DWORD_PTR tag = 0); + STDMETHODIMP ResAppend(LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, + BYTE* pData, DWORD len, DWORD_PTR tag = 0); + STDMETHODIMP ResRemoveAt(DWORD iIndex); + STDMETHODIMP ResRemoveAll(DWORD_PTR tag = 0); +}; diff --git a/common/DSUtilLite/DSUtilLite.vcxproj b/common/DSUtilLite/DSUtilLite.vcxproj index 2eaca878..f937a291 100644 --- a/common/DSUtilLite/DSUtilLite.vcxproj +++ b/common/DSUtilLite/DSUtilLite.vcxproj @@ -70,6 +70,7 @@ </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="BaseDSPropPage.h" /> + <ClInclude Include="DSMResourceBag.h" /> <ClInclude Include="PopupMenu.h" /> <ClInclude Include="BaseTrayIcon.h" /> <ClInclude Include="ByteParser.h" /> @@ -90,6 +91,7 @@ </ItemGroup> <ItemGroup> <ClCompile Include="BaseDSPropPage.cpp" /> + <ClCompile Include="DSMResourceBag.cpp" /> <ClCompile Include="PopupMenu.cpp" /> <ClCompile Include="BaseTrayIcon.cpp" /> <ClCompile Include="ByteParser.cpp" /> diff --git a/common/DSUtilLite/DSUtilLite.vcxproj.filters b/common/DSUtilLite/DSUtilLite.vcxproj.filters index 9073b986..dbe1b52f 100644 --- a/common/DSUtilLite/DSUtilLite.vcxproj.filters +++ b/common/DSUtilLite/DSUtilLite.vcxproj.filters @@ -75,6 +75,9 @@ <ClInclude Include="PopupMenu.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="DSMResourceBag.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="stdafx.cpp"> @@ -119,5 +122,8 @@ <ClCompile Include="PopupMenu.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="DSMResourceBag.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/demuxer/Demuxers/LAVFDemuxer.cpp b/demuxer/Demuxers/LAVFDemuxer.cpp index 1890abe5..4c4ac6dd 100644 --- a/demuxer/Demuxers/LAVFDemuxer.cpp +++ b/demuxer/Demuxers/LAVFDemuxer.cpp @@ -158,6 +158,7 @@ STDMETHODIMP CLAVFDemuxer::NonDelegatingQueryInterface(REFIID riid, void** ppv) m_bEnableTrackInfo && QI(ITrackInfo) QI2(IAMExtendedSeeking) QI2(IAMMediaContent) + QI(IDSMResourceBag) __super::NonDelegatingQueryInterface(riid, ppv); } @@ -491,11 +492,30 @@ STDMETHODIMP CLAVFDemuxer::InitAVFormat(LPCOLESTR pszFileName, BOOL bForce) UpdateSubStreams(); - if (st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && (st->codec->codec_id == AV_CODEC_ID_TTF || st->codec->codec_id == AV_CODEC_ID_OTF)) { - if (!m_pFontInstaller) { - m_pFontInstaller = new CFontInstaller(); + if (st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { + if (st->codec->codec_id == AV_CODEC_ID_TTF || st->codec->codec_id == AV_CODEC_ID_OTF) { + if (!m_pFontInstaller) { + m_pFontInstaller = new CFontInstaller(); + } + m_pFontInstaller->InstallFont(st->codec->extradata, st->codec->extradata_size); + } + + const AVDictionaryEntry* attachFilename = av_dict_get(st->metadata, "filename", NULL, 0); + const AVDictionaryEntry* attachMimeType = av_dict_get(st->metadata, "mimetype", NULL, 0); + if (attachFilename && attachMimeType) { + size_t len = strlen(attachFilename->value); + LPWSTR filename = new WCHAR[len + 1]; + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, attachFilename->value, -1, filename, len+1); + + len = strlen(attachMimeType->value); + LPWSTR mimetype = new WCHAR[len + 1]; + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, attachMimeType->value, -1, mimetype, len+1); + + ResAppend(filename, L"", mimetype, st->codec->extradata, (DWORD)st->codec->extradata_size); + + delete [] filename; + delete [] mimetype; } - m_pFontInstaller->InstallFont(st->codec->extradata, st->codec->extradata_size); } } diff --git a/demuxer/Demuxers/LAVFDemuxer.h b/demuxer/Demuxers/LAVFDemuxer.h index 405f19e9..7051a6ae 100644 --- a/demuxer/Demuxers/LAVFDemuxer.h +++ b/demuxer/Demuxers/LAVFDemuxer.h @@ -25,6 +25,7 @@ #include "BaseDemuxer.h" #include "IKeyFrameInfo.h" #include "ITrackInfo.h" +#include "DSMResourceBag.h" #include "FontInstaller.h" #define SUBMODE_FORCED_PGS_ONLY 0xFF @@ -33,7 +34,8 @@ class FormatInfo; class CBDDemuxer; #define FFMPEG_FILE_BUFFER_SIZE 32768 // default reading size for ffmpeg -class CLAVFDemuxer : public CBaseDemuxer, public IAMExtendedSeeking, public IKeyFrameInfo, public ITrackInfo, public IAMMediaContent +class CLAVFDemuxer : public CBaseDemuxer, public IAMExtendedSeeking, public IKeyFrameInfo, public ITrackInfo, public IAMMediaContent, + public IDSMResourceBagImpl { public: CLAVFDemuxer(CCritSec *pLock, ILAVFSettingsInternal *settings); diff --git a/demuxer/LAVSplitter/LAVSplitter.cpp b/demuxer/LAVSplitter/LAVSplitter.cpp index f55587f0..10661844 100644 --- a/demuxer/LAVSplitter/LAVSplitter.cpp +++ b/demuxer/LAVSplitter/LAVSplitter.cpp @@ -321,7 +321,8 @@ STDMETHODIMP CLAVSplitter::NonDelegatingQueryInterface(REFIID riid, void** ppv) *ppv = NULL; - if (m_pDemuxer && (riid == __uuidof(IKeyFrameInfo) || riid == __uuidof(ITrackInfo) || riid == IID_IAMExtendedSeeking || riid == IID_IAMMediaContent)) { + if (m_pDemuxer + && (riid == __uuidof(IKeyFrameInfo) || riid == __uuidof(ITrackInfo) || riid == IID_IAMExtendedSeeking || riid == IID_IAMMediaContent || riid == __uuidof(IDSMResourceBag))) { return m_pDemuxer->QueryInterface(riid, ppv); } |