From a1f1d4b4fa17753cb892494e105b2a686051e041 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Wed, 13 Apr 2011 18:46:30 +0200 Subject: Add backend functionality for controlling which input formats should be supported by the splitter. --- demuxer/Demuxers/BaseDemuxer.h | 13 ++++++ demuxer/Demuxers/Demuxers.vcxproj | 1 + demuxer/Demuxers/Demuxers.vcxproj.filters | 3 ++ demuxer/Demuxers/LAVFDemuxer.cpp | 43 +++++++++++++++--- demuxer/Demuxers/LAVFDemuxer.h | 6 +++ demuxer/Demuxers/LAVFInputFormats.cpp | 72 +++++++++++++++++++++++++++++++ demuxer/Demuxers/LAVFStreamInfo.cpp | 10 ----- demuxer/LAVSplitter/LAVSplitter.cpp | 49 +++++++++++++++++++++ demuxer/LAVSplitter/LAVSplitter.h | 7 +++ demuxer/LAVSplitter/StreamParser.cpp | 3 -- 10 files changed, 187 insertions(+), 20 deletions(-) create mode 100644 demuxer/Demuxers/LAVFInputFormats.cpp (limited to 'demuxer') diff --git a/demuxer/Demuxers/BaseDemuxer.h b/demuxer/Demuxers/BaseDemuxer.h index 3c3cccda..79e44f27 100644 --- a/demuxer/Demuxers/BaseDemuxer.h +++ b/demuxer/Demuxers/BaseDemuxer.h @@ -29,6 +29,19 @@ struct ILAVFSettings; +class FormatInfo { +public: + FormatInfo() : strName(NULL), strDescription(NULL) {} + FormatInfo(const char *name, const char *desc) : strName(name), strDescription(desc) {} + const char *strName; + const char *strDescription; + + // Comparison operators for sorting (NULL safe) + bool FormatInfo::operator < (const FormatInfo& rhs) const { return strName ? (rhs.strName ? strcmp(strName, rhs.strName) < 0 : false) : true; } + bool FormatInfo::operator > (const FormatInfo& rhs) const { return !(*this < rhs); } + bool FormatInfo::operator == (const FormatInfo& rhs) const { return (strName == rhs.strName) || (strName && rhs.strName && (strcmp(strName, rhs.strName) == 0)); } +}; + // Data Packet for queue storage class Packet { diff --git a/demuxer/Demuxers/Demuxers.vcxproj b/demuxer/Demuxers/Demuxers.vcxproj index 154b8080..d14cb4cd 100644 --- a/demuxer/Demuxers/Demuxers.vcxproj +++ b/demuxer/Demuxers/Demuxers.vcxproj @@ -139,6 +139,7 @@ + diff --git a/demuxer/Demuxers/Demuxers.vcxproj.filters b/demuxer/Demuxers/Demuxers.vcxproj.filters index 2ab59b7d..d2a6da50 100644 --- a/demuxer/Demuxers/Demuxers.vcxproj.filters +++ b/demuxer/Demuxers/Demuxers.vcxproj.filters @@ -83,5 +83,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/demuxer/Demuxers/LAVFDemuxer.cpp b/demuxer/Demuxers/LAVFDemuxer.cpp index 7f59f778..b72a4342 100644 --- a/demuxer/Demuxers/LAVFDemuxer.cpp +++ b/demuxer/Demuxers/LAVFDemuxer.cpp @@ -31,17 +31,37 @@ extern "C" { } #endif +extern void lavf_get_iformat_infos(AVInputFormat *pFormat, const char **pszName, const char **pszDescription); + static const AVRational AV_RATIONAL_TIMEBASE = {1, AV_TIME_BASE}; -CLAVFDemuxer::CLAVFDemuxer(CCritSec *pLock, ILAVFSettings *settings) - : CBaseDemuxer(L"lavf demuxer", pLock), m_avFormat(NULL), m_rtCurrent(0), m_bIsStream(false), m_bMatroska(false), m_bAVI(false), m_bMPEGTS(false), m_program(0), m_bVC1Correction(true), m_stOrigParser(NULL), m_pFontInstaller(NULL) +void CLAVFDemuxer::ffmpeg_init() { av_register_all(); register_protocol(&ufile_protocol); +} + +std::set CLAVFDemuxer::GetFormatList() +{ + std::set formats; + AVInputFormat *f = NULL; + while (f = av_iformat_next(f)) { + FormatInfo format; + lavf_get_iformat_infos(f, &format.strName, &format.strDescription); + if (format.strName) + formats.insert(format); + } + return formats; +} +CLAVFDemuxer::CLAVFDemuxer(CCritSec *pLock, ILAVFSettings *settings) + : CBaseDemuxer(L"lavf demuxer", pLock), m_avFormat(NULL), m_rtCurrent(0), m_bIsStream(false), m_bMatroska(false), m_bAVI(false), m_bMPEGTS(false), m_program(0), m_bVC1Correction(true), m_stOrigParser(NULL), m_pFontInstaller(NULL), m_pSettings(NULL), m_pszInputFormat(NULL) +{ m_bSubStreams = settings->GetSubstreamsEnabled(); m_bGenPTS = settings->GetGeneratePTS(); + m_pSettings = settings; + #ifdef DEBUG DbgSetModuleLevel (LOG_CUSTOM1, DWORD_MAX); // FFMPEG messages use custom1 av_log_set_callback(lavf_log_callback); @@ -132,11 +152,20 @@ STDMETHODIMP CLAVFDemuxer::InitAVFormat() { HRESULT hr = S_OK; + const char *format = NULL; + lavf_get_iformat_infos(m_avFormat->iformat, &format, NULL); + if (!format || !m_pSettings->IsFormatEnabled(format)) { + DbgLog((LOG_TRACE, 20, L"::InitAVFormat() - format of type '%S' disabled, failing", format ? format : m_avFormat->iformat->name)); + return E_FAIL; + } + + m_pszInputFormat = format ? format : m_avFormat->iformat->name; + unsigned int idx = 0; - m_bMatroska = (_strnicmp(m_avFormat->iformat->name, "matroska", 8) == 0); - m_bAVI = (_strnicmp(m_avFormat->iformat->name, "avi", 3) == 0); - m_bMPEGTS = (_strnicmp(m_avFormat->iformat->name, "mpegts", 6) == 0); + m_bMatroska = (_strnicmp(m_pszInputFormat, "matroska", 8) == 0); + m_bAVI = (_strnicmp(m_pszInputFormat, "avi", 3) == 0); + m_bMPEGTS = (_strnicmp(m_pszInputFormat, "mpegts", 6) == 0); if (m_bGenPTS) { m_avFormat->flags |= AVFMT_FLAG_GENPTS; @@ -446,7 +475,7 @@ STDMETHODIMP CLAVFDemuxer::SeekByte(int64_t pos, int flags) const char *CLAVFDemuxer::GetContainerFormat() const { - return m_avFormat->iformat->name; + return m_pszInputFormat; } HRESULT CLAVFDemuxer::StreamInfo(DWORD streamId, LCID *plcid, WCHAR **ppszName) const @@ -581,7 +610,7 @@ STDMETHODIMP CLAVFDemuxer::AddStream(int streamId) stream s; s.pid = streamId; - s.streamInfo = new CLAVFStreamInfo(pStream, m_avFormat->iformat->name, hr); + s.streamInfo = new CLAVFStreamInfo(pStream, m_pszInputFormat, hr); if(FAILED(hr)) { delete s.streamInfo; diff --git a/demuxer/Demuxers/LAVFDemuxer.h b/demuxer/Demuxers/LAVFDemuxer.h index d6ff9953..e0537344 100644 --- a/demuxer/Demuxers/LAVFDemuxer.h +++ b/demuxer/Demuxers/LAVFDemuxer.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include "BaseDemuxer.h" #include "IKeyFrameInfo.h" @@ -34,6 +35,9 @@ public: CLAVFDemuxer(CCritSec *pLock, ILAVFSettings *settings); ~CLAVFDemuxer(); + static void ffmpeg_init(); + static std::set GetFormatList(); + // IUnknown DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); @@ -94,6 +98,7 @@ private: private: AVFormatContext *m_avFormat; + const char *m_pszInputFormat; BOOL m_bIsStream; BOOL m_bMatroska; @@ -111,4 +116,5 @@ private: enum AVStreamParseType *m_stOrigParser; CFontInstaller *m_pFontInstaller; + ILAVFSettings *m_pSettings; }; diff --git a/demuxer/Demuxers/LAVFInputFormats.cpp b/demuxer/Demuxers/LAVFInputFormats.cpp new file mode 100644 index 00000000..16747af0 --- /dev/null +++ b/demuxer/Demuxers/LAVFInputFormats.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 Hendrik Leppkes + * http://www.1f0.de + * + * This Program 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 2, 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "stdafx.h" + +static const char *RAW_VIDEO = "rawvideo"; +static const char *RAW_VIDEO_DESC = "raw video files"; + +static const char *RAW_AUDIO = "rawaudio"; +static const char *RAW_AUDIO_DESC = "raw audio files"; + +struct lavf_iformat_map +{ + const char *orig_format; + const char *new_format; + const char *new_description; +} lavf_input_formats[] = { + // Shorten these formats + { "matroska,webm", "matroska", NULL }, + { "mov,mp4,m4a,3gp,3g2,mj2", "mp4", "MPEG-4/QuickTime format" }, + + // Raw Video formats (grouped into "rawvideo") + { "h264", RAW_VIDEO, RAW_VIDEO_DESC }, + { "vc1", RAW_VIDEO, RAW_VIDEO_DESC }, + + // Raw Audio Formats (grouped into "rawaudio") + { "ac3", RAW_AUDIO, RAW_AUDIO_DESC }, + + // Disabled Formats + { "ffm", NULL, NULL }, + { "ffmetadata", NULL, NULL }, + { "mpegtsraw", NULL, NULL }, + { "spdif", NULL, NULL }, + { "vc1test", NULL, NULL }, + { "yuv4mpegpipe", NULL, NULL }, +}; + +void lavf_get_iformat_infos(AVInputFormat *pFormat, const char **pszName, const char **pszDescription) +{ + const char *name = pFormat->name; + const char *desc = pFormat->long_name; + for (int i=0; icodec->codec_type) { case AVMEDIA_TYPE_AUDIO: hr = CreateAudioMediaType(avstream); diff --git a/demuxer/LAVSplitter/LAVSplitter.cpp b/demuxer/LAVSplitter/LAVSplitter.cpp index 14b5b953..eee07b5c 100644 --- a/demuxer/LAVSplitter/LAVSplitter.cpp +++ b/demuxer/LAVSplitter/LAVSplitter.cpp @@ -48,6 +48,13 @@ CLAVSplitter::CLAVSplitter(LPUNKNOWN pUnk, HRESULT* phr) , m_dRate(1.0), m_rtLastStart(_I64_MIN), m_rtLastStop(_I64_MIN) , m_pDemuxer(NULL) { + CLAVFDemuxer::ffmpeg_init(); + + m_InputFormats.clear(); + + std::set lavf_formats = CLAVFDemuxer::GetFormatList(); + m_InputFormats.insert(lavf_formats.begin(), lavf_formats.end()); + LoadSettings(); if(phr) { *phr = S_OK; } @@ -87,6 +94,17 @@ STDMETHODIMP CLAVSplitter::Close() return S_OK; } +// Default overrides for input formats +static BOOL get_iformat_default(std::string name) +{ + // Raw video formats lack timestamps.. + if (name == "rawvideo") { + return FALSE; + } + + return TRUE; +} + STDMETHODIMP CLAVSplitter::LoadSettings() { HRESULT hr; @@ -125,6 +143,17 @@ STDMETHODIMP CLAVSplitter::LoadSettings() bFlag = reg.ReadDWORD(L"generatePTS", hr); m_settings.generatePTS = SUCCEEDED(hr) ? bFlag : FALSE; + CreateRegistryKey(HKEY_CURRENT_USER, LAVF_REGISTRY_KEY_FORMATS); + CRegistry regF = CRegistry(HKEY_CURRENT_USER, LAVF_REGISTRY_KEY_FORMATS, hr); + + WCHAR wBuffer[80]; + std::set::iterator it; + for (it = m_InputFormats.begin(); it != m_InputFormats.end(); ++it) { + MultiByteToWideChar(CP_UTF8, 0, it->strName, -1, wBuffer, 80); + bFlag = regF.ReadBOOL(wBuffer, hr); + m_settings.formats[std::string(it->strName)] = SUCCEEDED(hr) ? bFlag : get_iformat_default(it->strName); + } + return S_OK; } @@ -143,6 +172,17 @@ STDMETHODIMP CLAVSplitter::SaveSettings() reg.WriteBOOL(L"audioParsing", m_settings.audioParsing); reg.WriteBOOL(L"generatePTS", m_settings.generatePTS); } + + CRegistry regF = CRegistry(HKEY_CURRENT_USER, LAVF_REGISTRY_KEY_FORMATS, hr); + if (SUCCEEDED(hr)) { + WCHAR wBuffer[80]; + std::set::iterator it; + for (it = m_InputFormats.begin(); it != m_InputFormats.end(); ++it) { + MultiByteToWideChar(CP_UTF8, 0, it->strName, -1, wBuffer, 80); + regF.WriteBOOL(wBuffer, m_settings.formats[std::string(it->strName)]); + } + } + if (m_pDemuxer) { m_pDemuxer->SettingsChanged(static_cast(this)); } @@ -1051,6 +1091,15 @@ STDMETHODIMP_(BOOL) CLAVSplitter::GetGeneratePTS() return m_settings.generatePTS; } +STDMETHODIMP_(BOOL) CLAVSplitter::IsFormatEnabled(const char *strFormat) +{ + std::string format(strFormat); + if (m_settings.formats.find(format) != m_settings.formats.end()) { + return m_settings.formats[format]; + } + return FALSE; +} + // static constructor CUnknown* WINAPI CLAVSplitterSource::CreateInstance(LPUNKNOWN pUnk, HRESULT* phr) { diff --git a/demuxer/LAVSplitter/LAVSplitter.h b/demuxer/LAVSplitter/LAVSplitter.h index d0853295..622c1846 100644 --- a/demuxer/LAVSplitter/LAVSplitter.h +++ b/demuxer/LAVSplitter/LAVSplitter.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "PacketQueue.h" #include "BaseDemuxer.h" @@ -35,6 +36,7 @@ #include "SettingsProp.h" #define LAVF_REGISTRY_KEY L"Software\\LAV\\Splitter" +#define LAVF_REGISTRY_KEY_FORMATS LAVF_REGISTRY_KEY L"\\Formats" class CLAVOutputPin; class CLAVInputPin; @@ -121,6 +123,7 @@ public: STDMETHODIMP_(BOOL) GetAudioParsingEnabled(); STDMETHODIMP SetGeneratePTS(BOOL bEnabled); STDMETHODIMP_(BOOL) GetGeneratePTS(); + STDMETHODIMP_(BOOL) IsFormatEnabled(const char *strFormat); // Settings helper std::list GetPreferredAudioLanguageList(); @@ -189,6 +192,8 @@ private: bool m_fFlushing; CAMEvent m_eEndFlush; + std::set m_InputFormats; + // Settings struct Settings { std::wstring prefAudioLangs; @@ -200,6 +205,8 @@ private: BOOL videoParsing; BOOL audioParsing; BOOL generatePTS; + + std::map formats; } m_settings; }; diff --git a/demuxer/LAVSplitter/StreamParser.cpp b/demuxer/LAVSplitter/StreamParser.cpp index e8fb654e..72f19dbb 100644 --- a/demuxer/LAVSplitter/StreamParser.cpp +++ b/demuxer/LAVSplitter/StreamParser.cpp @@ -35,9 +35,6 @@ CStreamParser::CStreamParser(CLAVOutputPin *pPin, const char *szContainer) : m_pPin(pPin), m_strContainer(szContainer), m_pPacketBuffer(NULL), m_gSubtype(GUID_NULL), m_fHasAccessUnitDelimiters(false) { - if (m_strContainer == "matroska,webm") { - m_strContainer = std::string("matroska"); - } } -- cgit v1.2.3