[Mediaportal-svn] r24289 - in branches/TsReader_NALU: . TsReader TsReader/bin/Debug TsReader/bin/Re
Turn your PC into a very advanced MediaCenter/HTPC
Brought to you by:
gereonheitmann,
morpheus_xx
From: <tou...@te...> - 2009-11-30 21:35:04
|
Author: tourettes_ Date: 2009-11-30 22:36:36 +0100 (Mon, 30 Nov 2009) New Revision: 24289 Modified: branches/TsReader_NALU/Filters.sln branches/TsReader_NALU/TsReader/TsReader.vcproj branches/TsReader_NALU/TsReader/bin/Debug/TsReader.ax branches/TsReader_NALU/TsReader/bin/Debug/TsReader.pdb branches/TsReader_NALU/TsReader/bin/Debug/vc90.pdb branches/TsReader_NALU/TsReader/bin/Release/TsReader.ax branches/TsReader_NALU/TsReader/source/AudioPin.cpp branches/TsReader_NALU/TsReader/source/Buffer.cpp branches/TsReader_NALU/TsReader/source/Buffer.h branches/TsReader_NALU/TsReader/source/DeMultiplexer.cpp branches/TsReader_NALU/TsReader/source/DeMultiplexer.h branches/TsReader_NALU/TsReader/source/FileReader.cpp branches/TsReader_NALU/TsReader/source/FrameHeaderParser.cpp branches/TsReader_NALU/TsReader/source/FrameHeaderParser.h branches/TsReader_NALU/TsReader/source/GolombBuffer.h branches/TsReader_NALU/TsReader/source/IAudioStream.h branches/TsReader_NALU/TsReader/source/ISubtitleStream.h branches/TsReader_NALU/TsReader/source/ITeletextSource.h branches/TsReader_NALU/TsReader/source/MediaSeeking.cpp branches/TsReader_NALU/TsReader/source/MemoryBuffer.cpp branches/TsReader_NALU/TsReader/source/MemoryReader.cpp branches/TsReader_NALU/TsReader/source/MemorySink.cpp branches/TsReader_NALU/TsReader/source/MpegPesParser.cpp branches/TsReader_NALU/TsReader/source/MultiFileReader.cpp branches/TsReader_NALU/TsReader/source/PatParser.cpp branches/TsReader_NALU/TsReader/source/PcrDecoder.cpp branches/TsReader_NALU/TsReader/source/PidTable.cpp branches/TsReader_NALU/TsReader/source/PmtParser.cpp branches/TsReader_NALU/TsReader/source/RTSPClient.cpp branches/TsReader_NALU/TsReader/source/SubtitlePin.cpp branches/TsReader_NALU/TsReader/source/TSThread.cpp branches/TsReader_NALU/TsReader/source/TsDuration.cpp branches/TsReader_NALU/TsReader/source/TsFileSeek.cpp branches/TsReader_NALU/TsReader/source/TsReader.cpp branches/TsReader_NALU/TsReader/source/TsReader.h branches/TsReader_NALU/TsReader/source/VideoPin.cpp branches/TsReader_NALU/TsReader/source/VideoPin.h branches/TsReader_NALU/TsReader/source/WaitEvent.cpp branches/TsReader_NALU/TsReader/source/mediaformats.h Log: Ambass' 3rd version as baseline Modified: branches/TsReader_NALU/Filters.sln =================================================================== --- branches/TsReader_NALU/Filters.sln 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/Filters.sln 2009-11-30 21:36:36 UTC (rev 24289) @@ -2,44 +2,14 @@ # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DvbCoreUtils", "DvbCoreUtils\DvbCoreUtils.vcproj", "{4B134B4C-4EF6-4647-9CEA-A59FF0013357}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TsWriter", "TsWriter\MPTSWriter.vcproj", "{FCF30D16-2C9E-4429-B605-4ACA43023E71}" - ProjectSection(ProjectDependencies) = postProject - {4B134B4C-4EF6-4647-9CEA-A59FF0013357} = {4B134B4C-4EF6-4647-9CEA-A59FF0013357} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TsReader", "TsReader\TsReader.vcproj", "{79B3DC38-9D2C-4D9E-98F8-A610260B46A9}" ProjectSection(ProjectDependencies) = postProject {4B134B4C-4EF6-4647-9CEA-A59FF0013357} = {4B134B4C-4EF6-4647-9CEA-A59FF0013357} {3C398BD4-5714-4802-AB86-D43ADD15B3C0} = {3C398BD4-5714-4802-AB86-D43ADD15B3C0} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StreamingServer", "StreamingServer\StreamingServer.vcproj", "{EACCF7EE-35F6-4A62-8C4A-64E1B0FF5A56}" - ProjectSection(ProjectDependencies) = postProject - {3C398BD4-5714-4802-AB86-D43ADD15B3C0} = {3C398BD4-5714-4802-AB86-D43ADD15B3C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MP_DVB_Subtitles", "DVBSubtitle2\DVBSubtitle2.vcproj", "{68A0BF54-311B-4EB9-A859-398357D6B591}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MPFileWriter", "MPWriter\MPWriter.vcproj", "{4D369052-C13D-4013-91A7-688C86BC9652}" - ProjectSection(ProjectDependencies) = postProject - {3C398BD4-5714-4802-AB86-D43ADD15B3C0} = {3C398BD4-5714-4802-AB86-D43ADD15B3C0} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LiveMedia555", "LiveMedia555\LiveMedia555.vcproj", "{3C398BD4-5714-4802-AB86-D43ADD15B3C0}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MPAudioswitcher", "MPAudioswitcher\MPAudioSwitcher.vcproj", "{D8DB3E7E-D50E-4EC3-A9B9-DAD18F5FE466}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dvblib", "dvblib\dvblib.vcproj", "{0DD8968F-A6F6-4365-9CC1-9CF87A76178B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TsMuxer", "TsMuxer\TsMuxer.vcproj", "{8AC0B595-EB93-4CBE-BEC7-E4A3D65DF3A6}" - ProjectSection(ProjectDependencies) = postProject - {3C398BD4-5714-4802-AB86-D43ADD15B3C0} = {3C398BD4-5714-4802-AB86-D43ADD15B3C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dxerr9", "DXErr9\dxerr9.vcproj", "{1FC036DE-1148-45E1-ADD3-FE1B20B652A7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MPIPTVSource", "MPIPTVSource\MPIPTVSource.vcproj", "{5350E032-962F-495B-A178-3CE264B5619E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -50,50 +20,14 @@ {4B134B4C-4EF6-4647-9CEA-A59FF0013357}.Debug|Win32.Build.0 = Debug|Win32 {4B134B4C-4EF6-4647-9CEA-A59FF0013357}.Release|Win32.ActiveCfg = Release|Win32 {4B134B4C-4EF6-4647-9CEA-A59FF0013357}.Release|Win32.Build.0 = Release|Win32 - {FCF30D16-2C9E-4429-B605-4ACA43023E71}.Debug|Win32.ActiveCfg = Debug|Win32 - {FCF30D16-2C9E-4429-B605-4ACA43023E71}.Debug|Win32.Build.0 = Debug|Win32 - {FCF30D16-2C9E-4429-B605-4ACA43023E71}.Release|Win32.ActiveCfg = Release|Win32 - {FCF30D16-2C9E-4429-B605-4ACA43023E71}.Release|Win32.Build.0 = Release|Win32 {79B3DC38-9D2C-4D9E-98F8-A610260B46A9}.Debug|Win32.ActiveCfg = Debug|Win32 {79B3DC38-9D2C-4D9E-98F8-A610260B46A9}.Debug|Win32.Build.0 = Debug|Win32 {79B3DC38-9D2C-4D9E-98F8-A610260B46A9}.Release|Win32.ActiveCfg = Release|Win32 {79B3DC38-9D2C-4D9E-98F8-A610260B46A9}.Release|Win32.Build.0 = Release|Win32 - {EACCF7EE-35F6-4A62-8C4A-64E1B0FF5A56}.Debug|Win32.ActiveCfg = Debug|Win32 - {EACCF7EE-35F6-4A62-8C4A-64E1B0FF5A56}.Debug|Win32.Build.0 = Debug|Win32 - {EACCF7EE-35F6-4A62-8C4A-64E1B0FF5A56}.Release|Win32.ActiveCfg = Release|Win32 - {EACCF7EE-35F6-4A62-8C4A-64E1B0FF5A56}.Release|Win32.Build.0 = Release|Win32 - {68A0BF54-311B-4EB9-A859-398357D6B591}.Debug|Win32.ActiveCfg = Debug|Win32 - {68A0BF54-311B-4EB9-A859-398357D6B591}.Debug|Win32.Build.0 = Debug|Win32 - {68A0BF54-311B-4EB9-A859-398357D6B591}.Release|Win32.ActiveCfg = Release|Win32 - {68A0BF54-311B-4EB9-A859-398357D6B591}.Release|Win32.Build.0 = Release|Win32 - {4D369052-C13D-4013-91A7-688C86BC9652}.Debug|Win32.ActiveCfg = Debug|Win32 - {4D369052-C13D-4013-91A7-688C86BC9652}.Debug|Win32.Build.0 = Debug|Win32 - {4D369052-C13D-4013-91A7-688C86BC9652}.Release|Win32.ActiveCfg = Release|Win32 - {4D369052-C13D-4013-91A7-688C86BC9652}.Release|Win32.Build.0 = Release|Win32 {3C398BD4-5714-4802-AB86-D43ADD15B3C0}.Debug|Win32.ActiveCfg = Debug|Win32 {3C398BD4-5714-4802-AB86-D43ADD15B3C0}.Debug|Win32.Build.0 = Debug|Win32 {3C398BD4-5714-4802-AB86-D43ADD15B3C0}.Release|Win32.ActiveCfg = Release|Win32 {3C398BD4-5714-4802-AB86-D43ADD15B3C0}.Release|Win32.Build.0 = Release|Win32 - {D8DB3E7E-D50E-4EC3-A9B9-DAD18F5FE466}.Debug|Win32.ActiveCfg = Debug|Win32 - {D8DB3E7E-D50E-4EC3-A9B9-DAD18F5FE466}.Debug|Win32.Build.0 = Debug|Win32 - {D8DB3E7E-D50E-4EC3-A9B9-DAD18F5FE466}.Release|Win32.ActiveCfg = Release|Win32 - {D8DB3E7E-D50E-4EC3-A9B9-DAD18F5FE466}.Release|Win32.Build.0 = Release|Win32 - {0DD8968F-A6F6-4365-9CC1-9CF87A76178B}.Debug|Win32.ActiveCfg = Debug|Win32 - {0DD8968F-A6F6-4365-9CC1-9CF87A76178B}.Debug|Win32.Build.0 = Debug|Win32 - {0DD8968F-A6F6-4365-9CC1-9CF87A76178B}.Release|Win32.ActiveCfg = Release|Win32 - {0DD8968F-A6F6-4365-9CC1-9CF87A76178B}.Release|Win32.Build.0 = Release|Win32 - {8AC0B595-EB93-4CBE-BEC7-E4A3D65DF3A6}.Debug|Win32.ActiveCfg = Debug|Win32 - {8AC0B595-EB93-4CBE-BEC7-E4A3D65DF3A6}.Debug|Win32.Build.0 = Debug|Win32 - {8AC0B595-EB93-4CBE-BEC7-E4A3D65DF3A6}.Release|Win32.ActiveCfg = Release|Win32 - {8AC0B595-EB93-4CBE-BEC7-E4A3D65DF3A6}.Release|Win32.Build.0 = Release|Win32 - {1FC036DE-1148-45E1-ADD3-FE1B20B652A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {1FC036DE-1148-45E1-ADD3-FE1B20B652A7}.Debug|Win32.Build.0 = Debug|Win32 - {1FC036DE-1148-45E1-ADD3-FE1B20B652A7}.Release|Win32.ActiveCfg = Release|Win32 - {1FC036DE-1148-45E1-ADD3-FE1B20B652A7}.Release|Win32.Build.0 = Release|Win32 - {5350E032-962F-495B-A178-3CE264B5619E}.Debug|Win32.ActiveCfg = Debug|Win32 - {5350E032-962F-495B-A178-3CE264B5619E}.Debug|Win32.Build.0 = Debug|Win32 - {5350E032-962F-495B-A178-3CE264B5619E}.Release|Win32.ActiveCfg = Release|Win32 - {5350E032-962F-495B-A178-3CE264B5619E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modified: branches/TsReader_NALU/TsReader/TsReader.vcproj =================================================================== --- branches/TsReader_NALU/TsReader/TsReader.vcproj 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/TsReader.vcproj 2009-11-30 21:36:36 UTC (rev 24289) @@ -20,8 +20,8 @@ OutputDirectory=".\obj\Release" IntermediateDirectory=".\obj\Release" ConfigurationType="2" - UseOfMFC="0" - UseOfATL="0" + UseOfMFC="2" + UseOfATL="2" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" > @@ -131,7 +131,8 @@ OutputDirectory=".\obj\Debug" IntermediateDirectory=".\obj\Debug" ConfigurationType="2" - UseOfMFC="0" + UseOfMFC="2" + UseOfATL="1" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" > @@ -160,7 +161,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""$(DSHOW_BASE)";"$(WINDOWS_SDK)Include\";"$(DXSDK_DIR)Include";..\LiveMedia555\BasicUsageEnvironment/include;..\LiveMedia555\groupsock/include;../LiveMedia555/liveMedia;..\LiveMedia555\liveMedia/include;..\LiveMedia555\UsageEnvironment/include;../LiveMedia555/MediaPortal;..\shared;..\streamingserver\Source" - PreprocessorDefinitions="DBG=1;DEBUG;_DEBUG;INC_OLE2;STRICT;_WIN32_WINNT=0x0400;WIN32;_WIN32;_MT;_DLL;_X86_=1;WINVER=0x0400;_CRT_SECURE_NO_DEPRECATE" + PreprocessorDefinitions="DBG=1;DEBUG;_DEBUG;INC_OLE2;STRICT;_MT;_DLL;_X86_=1;_CRT_SECURE_NO_DEPRECATE" BasicRuntimeChecks="3" RuntimeLibrary="3" PrecompiledHeaderFile=".\obj\Debug/FileWriter.pch" @@ -262,6 +263,10 @@ > </File> <File + RelativePath=".\source\H264Nalu.cpp" + > + </File> + <File RelativePath=".\source\MediaSeeking.cpp" > </File> @@ -367,6 +372,10 @@ > </File> <File + RelativePath=".\source\H264Nalu.h" + > + </File> + <File RelativePath=".\source\IAudioStream.h" > </File> Modified: branches/TsReader_NALU/TsReader/bin/Debug/TsReader.ax =================================================================== (Binary files differ) Modified: branches/TsReader_NALU/TsReader/bin/Debug/TsReader.pdb =================================================================== (Binary files differ) Modified: branches/TsReader_NALU/TsReader/bin/Debug/vc90.pdb =================================================================== (Binary files differ) Modified: branches/TsReader_NALU/TsReader/bin/Release/TsReader.ax =================================================================== (Binary files differ) Modified: branches/TsReader_NALU/TsReader/source/AudioPin.cpp =================================================================== --- branches/TsReader_NALU/TsReader/source/AudioPin.cpp 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/AudioPin.cpp 2009-11-30 21:36:36 UTC (rev 24289) @@ -21,6 +21,9 @@ #pragma warning(disable:4996) #pragma warning(disable:4995) +#include <afx.h> +#include <afxwin.h> + #include <winsock2.h> #include <ws2tcpip.h> #include <streams.h> @@ -513,7 +516,8 @@ if (!m_pTsReaderFilter->GetVideoPin()->IsConnected()) { - m_pTsReaderFilter->SetWaitForSeekToEof(false) ; + LogDebug("Wait for seeking to eof - false - AudioPin, thread start"); + m_pTsReaderFilter->SetWaitForSeekToEof(false); demux.SetVideoChanging(false); } else Modified: branches/TsReader_NALU/TsReader/source/Buffer.cpp =================================================================== --- branches/TsReader_NALU/TsReader/source/Buffer.cpp 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/Buffer.cpp 2009-11-30 21:36:36 UTC (rev 24289) @@ -18,6 +18,10 @@ * http://www.gnu.org/copyleft/gpl.html * */ + +#include <afx.h> +#include <afxwin.h> + #include <winsock2.h> #include <ws2tcpip.h> #include <streams.h> @@ -33,17 +37,28 @@ { bufferCount++; m_bDiscontinuity=false; - m_iLength=0; - m_pBuffer = new byte[MAX_BUFFER_SIZE]; - // LogDebug("buffers:%d",bufferCount); + m_iLength=0; + m_pBuffer = new byte[MAX_BUFFER_SIZE]; + m_iSize = MAX_BUFFER_SIZE; + //LogDebug("buffers:%d",bufferCount); } +CBuffer::CBuffer(unsigned long size) +{ + bufferCount++; + m_bDiscontinuity=false; + m_iLength=0; + m_pBuffer = new byte[size]; + m_iSize = size; + //LogDebug("buffers:%d",bufferCount); +} + CBuffer::~CBuffer() { bufferCount--; - delete [] m_pBuffer; - m_pBuffer=NULL; - m_iLength=0; + delete [] m_pBuffer; + m_pBuffer=NULL; + m_iLength=0; } @@ -106,18 +121,18 @@ ///returns the length in bytes of the PES packet int CBuffer::Length() { - return m_iLength; + return m_iLength; } ///*************************************************************** ///returns the PES packet byte* CBuffer::Data() { - if (m_pBuffer==NULL) - { - return NULL; - } - return m_pBuffer; + if (m_pBuffer==NULL) + { + return NULL; + } + return m_pBuffer; } ///*************************************************************** @@ -144,14 +159,14 @@ // Adds data contained in pBuffer to this pes packet void CBuffer::Add(CBuffer* pBuffer) { - if(pBuffer && ( MAX_BUFFER_SIZE >= m_iLength + pBuffer->Length())) + if(pBuffer && ( m_iSize >= m_iLength + pBuffer->Length())) { memcpy(&m_pBuffer[m_iLength], pBuffer->Data(), pBuffer->Length()); - m_iLength+=pBuffer->Length(); + m_iLength+=pBuffer->Length(); } else { - LogDebug("CBuffer::Add CBuffer - sanity check failed! MAX_BUFFER_SIZE %d lenght %d", MAX_BUFFER_SIZE, pBuffer->Length()+m_iLength ); + LogDebug("CBuffer::Add CBuffer - sanity check failed! MAX_BUFFER_SIZE %d lenght %d", m_iSize, pBuffer->Length()+m_iLength ); if(pBuffer == NULL) { LogDebug(" pBuffer was NULL!"); @@ -163,14 +178,14 @@ // Adds data contained to this pes packet void CBuffer::Add(byte* data, int len) { - if((MAX_BUFFER_SIZE >= m_iLength + len ) && data) + if((m_iSize >= m_iLength + len ) && data) { memcpy(&m_pBuffer[m_iLength], data, len); - m_iLength+=len; + m_iLength+=len; } else { - LogDebug("CBuffer::Add - sanity check failed! MAX_BUFFER_SIZE %d lenght %d", MAX_BUFFER_SIZE, m_iLength + len ); + LogDebug("CBuffer::Add - sanity check failed! MAX_BUFFER_SIZE %d lenght %d", m_iSize, m_iLength + len ); if(data == NULL) { LogDebug(" data was NULL!"); Modified: branches/TsReader_NALU/TsReader/source/Buffer.h =================================================================== --- branches/TsReader_NALU/TsReader/source/Buffer.h 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/Buffer.h 2009-11-30 21:36:36 UTC (rev 24289) @@ -25,6 +25,7 @@ { public: CBuffer(void); + CBuffer(unsigned long size); ~CBuffer(void); int Length(); byte* Data(); @@ -52,4 +53,5 @@ int m_iLength; int m_frameType ; int m_frameCount ; + unsigned int m_iSize; }; Modified: branches/TsReader_NALU/TsReader/source/DeMultiplexer.cpp =================================================================== --- branches/TsReader_NALU/TsReader/source/DeMultiplexer.cpp 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/DeMultiplexer.cpp 2009-11-30 21:36:36 UTC (rev 24289) @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Team MediaPortal + * Copyright (C) 2005-2009 Team MediaPortal * http://www.team-mediaportal.com * * This Program is free software; you can redistribute it and/or modify @@ -21,6 +21,9 @@ #pragma warning(disable:4996) #pragma warning(disable:4995) +#include <afx.h> +#include <afxwin.h> + #include <winsock2.h> #include <ws2tcpip.h> #include <streams.h> @@ -33,30 +36,96 @@ #include "subtitlePin.h" #include "..\..\DVBSubtitle2\Source\IDVBSub.h" #include "mediaFormats.h" +#include "h264nalu.h" #include <cassert> #define MAX_BUF_SIZE 8000 -#define OUTPUT_PACKET_LENGTH 0x6000e -#define BUFFER_LENGTH 0x1000 -#define FALLBACK_PACKETS_SD 300 -#define FALLBACK_PACKETS_HD 1500 +#define BUFFER_LENGTH 0x1000 +#define READ_SIZE (1316*30) + extern void LogDebug(const char *fmt, ...) ; -#define READ_SIZE (1316*30) - // *** UNCOMMENT THE NEXT LINE TO ENABLE DYNAMIC VIDEO PIN HANDLING!!!! ****** #define USE_DYNAMIC_PINS - extern int ShowBuffer ; +#define DNew new // For MPC-HC source compatibility +class CH246IFrameScanner +{ +private: + bool m_bFound; + bool m_bSeenEnough; + +public: + CH246IFrameScanner() + { + m_bFound = false; + m_bSeenEnough = false; + } + + bool SeenEnough() + { + return m_bSeenEnough; + } + + bool Found() + { + return m_bFound && m_bSeenEnough; + } + + void ProcessNALU(Packet *p) + { + ProcessNALU(p->GetData(), p->GetDataSize()); + } + + void ProcessNALU(byte *buffer, int len) + { + if (len < 5) + return; + + switch (buffer[4] & 0x9f) + { + case 1: // Coded slice of a non-IDR picture + case 2: // Coded slice data partition A + { + CGolombBuffer slice(buffer+5, len-5); + slice.UExpGolombRead(); // skip first_mb_in_slice + UINT slice_type = slice.UExpGolombRead(); + if (slice_type != 2 && // I slice + slice_type != 4 && // SI slice + slice_type != 7 && // I slice + slice_type != 9) // SI slice + { + m_bSeenEnough = true; + m_bFound = false; + return; + } + } + break; + case 5: // Coded slice of an IDR picture + m_bSeenEnough = m_bFound = true; + return; + case 9: // Access unit delimiter + if (len > 5 && (buffer[5] >> 5) == 2) + m_bSeenEnough = m_bFound = true; + break; + case 10: // End of sequence + // TODO: raise EndOfGOP flag so next NAL is considered start of I-Frame + break; + } + } +}; + CDeMultiplexer::CDeMultiplexer(CTsDuration& duration,CTsReaderFilter& filter) :m_duration(duration) ,m_filter(filter) { m_patParser.SetCallBack(this); - m_pCurrentVideoBuffer = new CBuffer(); + //Do not create here, as the size is adjusted dynamically to save memory + //m_pCurrentVideoBuffer = new CBuffer(); + m_pCurrentVideoBuffer = NULL; m_pCurrentAudioBuffer = new CBuffer(); m_pCurrentSubtitleBuffer = new CBuffer(); m_iAudioStream=0; @@ -96,7 +165,7 @@ m_IframeSample=0x7FFFFFFF00000000LL ; m_LastVideoSample=0 ; m_LastDataFromRtsp=GetTickCount() ; - m_mpegPesParser=new CMpegPesParser(); + m_mpegPesParser=new CMpegPesParser(); } CDeMultiplexer::~CDeMultiplexer() @@ -105,7 +174,7 @@ delete m_pCurrentVideoBuffer; delete m_pCurrentAudioBuffer; delete m_pCurrentSubtitleBuffer; - delete m_mpegPesParser; + delete m_mpegPesParser; m_subtitleStreams.clear(); m_audioStreams.clear(); @@ -345,6 +414,7 @@ LogDebug("demux:flush video"); CAutoLock lock (&m_sectionVideo); delete m_pCurrentVideoBuffer; + m_pCurrentVideoBuffer = NULL; ivecBuffers it =m_vecVideoBuffers.begin(); while (it != m_vecVideoBuffers.end()) { @@ -362,10 +432,11 @@ it=m_t_vecVideoBuffers.erase(it); } - /*if(this->pTeletextEventCallback != NULL) - { - this->CallTeletextEventCallback(TELETEXT_EVENT_BUFFER_OUT_UPDATE,m_outVideoBuffer); - }*/ + m_p.Free(); + m_pl.RemoveAll(); + m_fHasAccessUnitDelimiters = false; + + m_VideoPrevCC = -1 ; m_bIframeFound=false; m_FirstVideoSample=0x7FFFFFFF00000000LL ; @@ -373,7 +444,6 @@ m_LastVideoSample=0 ; m_lastVideoPTS.IsValid=false; m_VideoValidPES = false ; - m_pCurrentVideoBuffer = new CBuffer(); Reset() ; // PacketSync reset. } @@ -508,10 +578,6 @@ { CBuffer* videoBuffer=*it; m_vecVideoBuffers.erase(it); - //m_outVideoBuffer++; - //if(this->pTeletextEventCallback != NULL){ - // this->CallTeletextEventCallback(TELETEXT_EVENT_BUFFER_OUT_UPDATE,m_outVideoBuffer); - //} return videoBuffer; } } @@ -525,10 +591,10 @@ // or NULL if there is none available CBuffer* CDeMultiplexer::GetAudio() { - if (m_iAudioStream == -1) return NULL; + if (m_iAudioStream == -1) return NULL; - //if there is no audio pid, then simply return NULL - if ((m_audioPid==0) || IsVideoChanging()) + // if there is no audio pid, then simply return NULL + if ((m_audioPid==0) || IsVideoChanging()) { ReadFromFile(true,false); return NULL; @@ -536,39 +602,10 @@ // when there are no audio packets at the moment // then try to read some from the current file - while ((m_vecAudioBuffers.size()==0) || - ( m_filter.GetVideoPin()->IsConnected() && - (!m_bIframeFound || (m_IframeSample.Millisecs() + 150 >= m_LastAudioSample.Millisecs())))) + while ((m_vecAudioBuffers.size()==0) || + ( m_filter.GetVideoPin()->IsConnected() )&& + (!m_bIframeFound || (m_IframeSample.Millisecs() + 150 >= m_LastAudioSample.Millisecs()))) { - /*if (m_audioStreams.size() > 1) - { - if( m_iAudioReadCount > 10 && m_iAudioStream == 0) // no audio packets avail. lets try the next audio stream if any available - { - int previousAudioStream = m_iAudioStream; - int newAudioStream = m_iAudioStream; - if (m_audioStreams.size() > newAudioStream+1) - { - newAudioStream++; //try next avail stream - } - else - { - newAudioStream = 0; // try the first stream - } - - if (previousAudioStream != newAudioStream) - { - LogDebug("demux:no audio found with stream index = %i, setting audio index = %i", previousAudioStream, newAudioStream); - - SetAudioStream( newAudioStream ); - m_iAudioReadCount = 0; - } - } - else - { - m_iAudioReadCount++; - } - }*/ - //if filter is stopped or //end of file has been reached or //demuxer should stop getting audio packets @@ -620,13 +657,12 @@ m_bSetVideoDiscontinuity=false; DWORD dwBytesProcessed=0; DWORD m_Time = GetTickCount() ; - while ((GetTickCount() - m_Time) < 5000) + while((GetTickCount() - m_Time) < 5000) { int BytesRead =ReadFromFile(false,false) ; - if (BytesRead==0) Sleep(10) ; + if (BytesRead==0) Sleep(10) ; if (dwBytesProcessed>5000000 || GetAudioStreamCount()>0) { - // dynamic pins are currently disabled #ifdef USE_DYNAMIC_PINS if ((!m_mpegPesParser->basicVideoInfo.isValid && m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid>1) && dwBytesProcessed<5000000) { @@ -688,9 +724,9 @@ { if (!m_filter.IsTimeShifting()) { -// LogDebug("demux:endoffile...%d",GetTickCount()-m_LastDataFromRtsp ); - //set EOF flag and return - if (GetTickCount()-m_LastDataFromRtsp > 2000) // A bit crappy, but no better idea... + //LogDebug("demux:endoffile...%d",GetTickCount()-m_LastDataFromRtsp ); + //set EOF flag and return + if (GetTickCount()-m_LastDataFromRtsp > 2000) // A bit crappy, but no better idea... { LogDebug("demux:endoffile"); m_bEndOfFile=true; @@ -756,18 +792,26 @@ m_patParser.OnTsPacket(tsPacket); - if (m_iPatVersion==-1) return ; // First Pat not found + if (m_iPatVersion==-1) + { + // First Pat not found + return; + } - // Wait for new PAT if required. - if ((m_iPatVersion & 0x0F) != (m_ReqPatVersion & 0x0F)) - { - if (m_ReqPatVersion==-1) - { // Now, unless channel change, - m_ReqPatVersion = m_iPatVersion ; // Initialize Pat Request. - m_WaitNewPatTmo = GetTickCount() ; // Now, unless channel change request,timeout will be always true. - } - if (GetTickCount() < m_WaitNewPatTmo) return ; // Timeout not reached. - } + // Wait for new PAT if required. + if ((m_iPatVersion & 0x0F) != (m_ReqPatVersion & 0x0F)) + { + if (m_ReqPatVersion==-1) + { // Now, unless channel change, + m_ReqPatVersion = m_iPatVersion; // Initialize Pat Request. + m_WaitNewPatTmo = GetTickCount(); // Now, unless channel change request,timeout will be always true. + } + if (GetTickCount() < m_WaitNewPatTmo) + { + // Timeout not reached. + return; + } + } //if we have no PCR pid (yet) then there's nothing to decode, so return if (m_pids.PcrPid==0) return; @@ -838,10 +882,10 @@ //LogDebug("FillAudio - audio PID %d", m_audioPid ); if (m_iAudioStream<0 || m_iAudioStream>=m_audioStreams.size()) return; - m_audioPid= m_audioStreams[m_iAudioStream].pid; + m_audioPid=m_audioStreams[m_iAudioStream].pid; if (m_audioPid==0 || m_audioPid != header.Pid) return; if (m_filter.GetAudioPin()->IsConnected()==false) return; - if ( header.AdaptionFieldOnly() )return; + if (header.AdaptionFieldOnly())return; if(!CheckContinuity(m_AudioPrevCC, header)) { @@ -865,7 +909,7 @@ if (m_t_vecAudioBuffers.size()) { - CBuffer *Cbuf=*m_t_vecAudioBuffers.begin() ; + CBuffer *Cbuf=*m_t_vecAudioBuffers.begin(); byte *p = Cbuf->Data() ; if ((p[0]==0) && (p[1]==0) && (p[2]==1)) { @@ -883,39 +927,36 @@ diff=pts.ToClock()-m_lastAudioPTS.ToClock(); if (diff>10.0) { - LogDebug("DeMultiplexer::FillAudio pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastAudioPTS.ToClock()); - m_AudioValidPES=false ; + LogDebug("DeMultiplexer::FillAudio pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastAudioPTS.ToClock()); + m_AudioValidPES=false; } - else - m_lastAudioPTS=pts; + else + { + m_lastAudioPTS=pts; + } Cbuf->SetPts(pts); -// if (ShowBuffer) -// { -// CRefTime Ref ; -// Cbuf->MediaTime(Ref) ; -// LogDebug("Aud/Dmx : %03.3f", (float)Ref.Millisecs()/1000.0f); -// } + } //skip pes header int headerLen=9+p[8] ; - int len = Cbuf->Length()-headerLen ; + int len = Cbuf->Length()-headerLen; if (len > 0) { - byte *ps = p+headerLen ; - Cbuf->SetLength(len) ; - while(len--) *p++ = *ps++ ; // memcpy could be not safe. + byte *ps = p+headerLen; + Cbuf->SetLength(len); + while(len--) *p++ = *ps++; // memcpy could be not safe. } else { - LogDebug(" No data") ; - m_AudioValidPES=false ; + LogDebug(" No data"); + m_AudioValidPES=false; } } else { - LogDebug("Pes header 0-0-1 fail") ; - m_AudioValidPES=false ; + LogDebug("Pes header 0-0-1 fail"); + m_AudioValidPES=false; } if (m_AudioValidPES) @@ -935,20 +976,20 @@ // Check if queue is no abnormally long.. if (m_vecAudioBuffers.size()>MAX_BUF_SIZE) { - ivecBuffers it = m_vecAudioBuffers.begin() ; + ivecBuffers it = m_vecAudioBuffers.begin(); delete *it ; m_vecAudioBuffers.erase(it); } - it = m_t_vecAudioBuffers.begin() ; + it = m_t_vecAudioBuffers.begin(); - CRefTime Ref ; + CRefTime Ref; if((*it)->MediaTime(Ref)) { - if (Ref < m_FirstAudioSample) m_FirstAudioSample = Ref ; - if (Ref > m_LastAudioSample) m_LastAudioSample = Ref ; + if (Ref < m_FirstAudioSample) m_FirstAudioSample = Ref; + if (Ref > m_LastAudioSample) m_LastAudioSample = Ref; } - m_vecAudioBuffers.push_back(*it) ; + m_vecAudioBuffers.push_back(*it); m_t_vecAudioBuffers.erase(it); } } @@ -957,13 +998,13 @@ while (m_t_vecAudioBuffers.size()) { ivecBuffers it ; - it = m_t_vecAudioBuffers.begin() ; + it = m_t_vecAudioBuffers.begin(); m_t_vecAudioBuffers.erase(it); } - m_bSetAudioDiscontinuity=true ; + m_bSetAudioDiscontinuity=true; } } - m_AudioValidPES = true ; + m_AudioValidPES = true; } if (m_AudioValidPES) @@ -991,14 +1032,14 @@ } } + /// This method will check if the tspacket is an video packet -/// ifso, it decodes the PES video packet and stores it in the video buffers void CDeMultiplexer::FillVideo(CTsHeader& header, byte* tsPacket) { if (m_pids.videoPids.size() == 0 || m_pids.videoPids[0].Pid==0) return; if (header.Pid!=m_pids.videoPids[0].Pid) return; - if ( header.AdaptionFieldOnly() )return; + if ( header.AdaptionFieldOnly() ) return; if(!CheckContinuity(m_VideoPrevCC, header)) { @@ -1009,9 +1050,271 @@ m_VideoPrevCC = header.ContinuityCounter; CAutoLock lock (&m_sectionVideo); + + if( m_pids.videoPids[0].VideoServiceType==SERVICE_TYPE_VIDEO_MPEG1 || + m_pids.videoPids[0].VideoServiceType==SERVICE_TYPE_VIDEO_MPEG2 ) + { + FillVideoMPEG2(header, tsPacket); + } + else + { +// ParseVideoH264(header, tsPacket) ; + FillVideoH264(header, tsPacket); + } +} + +void CDeMultiplexer::FillVideoH264(CTsHeader& header, byte* tsPacket) +{ + int headerlen = header.PayLoadStart; + + CPcr pts; + CPcr dts; + + bool ptsAvailable = false; + + if (header.PayloadUnitStart) + { + if ((tsPacket[header.PayLoadStart]==0) && + (tsPacket[header.PayLoadStart+1]==0) && + (tsPacket[header.PayLoadStart+2]==1)) + { + int pesHeaderLen=9+tsPacket[header.PayLoadStart + 8]; + headerlen += pesHeaderLen; + + if (CPcr::DecodeFromPesHeader(&tsPacket[header.PayLoadStart],0,pts,dts)) + { + ptsAvailable = true; + double diff; + if (!m_lastVideoPTS.IsValid) + m_lastVideoPTS=pts; + if (m_lastVideoPTS>pts) + diff=m_lastVideoPTS.ToClock()-pts.ToClock(); + else + diff=pts.ToClock()-m_lastVideoPTS.ToClock(); + if (diff>10.0) + { + LogDebug("DeMultiplexer::FillVideo pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock()); + m_VideoValidPES=false ; + } + else + { + m_lastVideoPTS=pts; + } + } + } + else + { + LogDebug("Pes 0-0-1 fail") ; + return; + } + } + + CAutoPtr<Packet> p(DNew Packet()); + p->TrackNumber = 0; // TrackNumber is not used + p->bSyncPoint = !!pts.IsValid; + p->bAppendable = !pts.IsValid; + p->rtStart = pts.IsValid ? (pts.PcrReferenceBase) : Packet::INVALID_TIME; + p->rtStop = p->rtStart+1; + + int dataLen = 188-headerlen; + + p->SetCount(dataLen); + p->SetData(&tsPacket[headerlen],dataLen); + + if(!m_p) + { + m_p.Attach(DNew Packet()); + m_p->TrackNumber = p->TrackNumber; + m_p->bDiscontinuity = p->bDiscontinuity; p->bDiscontinuity = FALSE; + m_p->bSyncPoint = p->bSyncPoint; p->bSyncPoint = FALSE; + m_p->rtStart = p->rtStart; p->rtStart = Packet::INVALID_TIME; + m_p->rtStop = p->rtStop; p->rtStop = Packet::INVALID_TIME; + } + + m_p->Append(*p); + + BYTE* start = m_p->GetData(); + BYTE* end = start + m_p->GetCount(); + + while(start <= end-4 && *(DWORD*)start != 0x01000000) start++; + + while(start <= end-4) + { + BYTE* next = start+1; + + while(next <= end-4 && *(DWORD*)next != 0x01000000) next++; + + if(next >= end-4) break; + + int size = next - start; + + CH264Nalu Nalu; + Nalu.SetBuffer (start, size, 0); + + CAutoPtr<Packet> p2; + + while (Nalu.ReadNext()) + { + DWORD dwNalLength = + ((Nalu.GetDataLength() >> 24) & 0x000000ff) | + ((Nalu.GetDataLength() >> 8) & 0x0000ff00) | + ((Nalu.GetDataLength() << 8) & 0x00ff0000) | + ((Nalu.GetDataLength() << 24) & 0xff000000); + + CAutoPtr<Packet> p3(DNew Packet()); + + p3->SetCount (Nalu.GetDataLength()+sizeof(dwNalLength)); + + memcpy (p3->GetData(), &dwNalLength, sizeof(dwNalLength)); + memcpy (p3->GetData()+sizeof(dwNalLength), Nalu.GetDataBuffer(), Nalu.GetDataLength()); + + if (p2 == NULL) + p2 = p3; + else + p2->Append(*p3); + } + + p2->TrackNumber = m_p->TrackNumber; + p2->bDiscontinuity = m_p->bDiscontinuity; m_p->bDiscontinuity = FALSE; + p2->bSyncPoint = m_p->bSyncPoint; m_p->bSyncPoint = FALSE; + p2->rtStart = m_p->rtStart; m_p->rtStart = Packet::INVALID_TIME; + p2->rtStop = m_p->rtStop; m_p->rtStop = Packet::INVALID_TIME; + p2->pmt = m_p->pmt; m_p->pmt = NULL; + + m_pl.AddTail(p2); + + if(p->rtStart != Packet::INVALID_TIME) {m_p->rtStart = p->rtStart; m_p->rtStop = p->rtStop; p->rtStart = Packet::INVALID_TIME;} + if(p->bDiscontinuity) {m_p->bDiscontinuity = p->bDiscontinuity; p->bDiscontinuity = FALSE;} + if(p->bSyncPoint) {m_p->bSyncPoint = p->bSyncPoint; p->bSyncPoint = FALSE;} + if(m_p->pmt) DeleteMediaType(m_p->pmt); m_p->pmt = p->pmt; p->pmt = NULL; + + start = next; + } + if(start > m_p->GetData()) + { + m_p->RemoveAt(0, start - m_p->GetData()); + } + + for(POSITION pos = m_pl.GetHeadPosition(); pos; m_pl.GetNext(pos)) + { + if(pos == m_pl.GetHeadPosition()) + continue; + + Packet* pPacket = m_pl.GetAt(pos); + BYTE* pData = pPacket->GetData(); + + if((pData[4]&0x1f) == 0x09) m_fHasAccessUnitDelimiters = true; + if((pData[4]&0x1f) == 0x09 || !m_fHasAccessUnitDelimiters && pPacket->rtStart != Packet::INVALID_TIME) + { + p = m_pl.RemoveHead(); + //LogDebug("Output NALU Type: %d", p->GetAt(4)&0x1f); + CH246IFrameScanner iFrameScanner; + iFrameScanner.ProcessNALU(p); + + while(pos != m_pl.GetHeadPosition()) + { + CAutoPtr<Packet> p2 = m_pl.RemoveHead(); + if (!iFrameScanner.SeenEnough()) + iFrameScanner.ProcessNALU(p2); + + //LogDebug("Output NALU Type: %d", p2->GetAt(4)&0x1f); + p->Append(*p2); + } + + CPcr timestamp; + if(p->rtStart != Packet::INVALID_TIME ) + { + timestamp.PcrReferenceBase = p->rtStart; + timestamp.IsValid=true; + } + + //LogDebug("frame len %d decoded PTS %f p timestamp %f", p->GetCount(), pts.ToClock(), timestamp.ToClock()); + + m_pCurrentVideoBuffer = new CBuffer(p->GetCount()); + m_pCurrentVideoBuffer->Add(p->GetData(), p->GetCount()); + m_pCurrentVideoBuffer->SetPts(timestamp); + + int lastVidResX=m_mpegPesParser->basicVideoInfo.width; + int lastVidResY=m_mpegPesParser->basicVideoInfo.height; + + bool parsed=m_mpegPesParser->OnTsPacket(p->GetData(), p->GetCount(),(m_pids.videoPids[0].VideoServiceType==SERVICE_TYPE_VIDEO_MPEG2)); + + bool Gop = parsed ; //iFrameScanner.Found(); +// LogDebug( "Gop ? %d, parsed %d, Old res=%dx%d, res=%dx%d",Gop, parsed, lastVidResX,lastVidResY,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height); + m_pCurrentVideoBuffer->SetFrameType(Gop? 'I':'?'); + m_pCurrentVideoBuffer->SetFrameCount(0); + + CRefTime Ref; + m_pCurrentVideoBuffer->MediaTime(Ref); + + if ((Gop || m_bIframeFound) && m_filter.GetVideoPin()->IsConnected()) + { + // Must use p->rtStart as CPcr is UINT64 and INVALID_TIME is LONGLONG + // Too risky to change CPcr implementation at this time + if(p->rtStart != Packet::INVALID_TIME) + { + if (Gop && !m_bIframeFound) + { + m_IframeSample = Ref; + m_bIframeFound=true; + + + CPcr timestamp2; + timestamp2.PcrReferenceBase = p->rtStart; + timestamp2.IsValid=true; + LogDebug(" I-FRAME %f ", timestamp2.ToClock()); + } + if (Ref < m_FirstVideoSample) m_FirstVideoSample = Ref; + if (Ref > m_LastVideoSample) m_LastVideoSample = Ref; + } + + if (m_bSetVideoDiscontinuity) + { + m_bSetVideoDiscontinuity=false; + m_pCurrentVideoBuffer->SetDiscontinuity(); + } + } + + m_vecVideoBuffers.push_back(m_pCurrentVideoBuffer); + m_pCurrentVideoBuffer = NULL; + + if (lastVidResX!=m_mpegPesParser->basicVideoInfo.width || lastVidResY!=m_mpegPesParser->basicVideoInfo.height) + { + LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced); + + if (m_mpegParserTriggerFormatChange) + { + LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser"); + SetVideoChanging(true); + m_filter.OnMediaTypeChanged(3); + m_mpegParserTriggerFormatChange=false; + } + LogDebug("DeMultiplexer: triggering OnVideoFormatChanged"); + m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced); + } + else + { + if (m_mpegParserTriggerFormatChange && Gop) + { + LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now."); + m_filter.OnMediaTypeChanged(3); + m_mpegParserTriggerFormatChange=false; + } + } + } + } + return; +} +void CDeMultiplexer::FillVideoMPEG2(CTsHeader& header, byte* tsPacket) +{ //does tspacket contain the start of a pes packet? if (header.PayloadUnitStart) { + if (!m_pCurrentVideoBuffer) + { + m_pCurrentVideoBuffer = new CBuffer(); + } + //yes packet contains start of a pes packet. //does current buffer hold any data ? if (m_pCurrentVideoBuffer->Length() > 0) @@ -1050,13 +1353,6 @@ } Cbuf->SetPts(pts); - -// if (ShowBuffer) -// { -// CRefTime Ref ; -// Cbuf->MediaTime(Ref) ; -// LogDebug("Vid/Dmx : %03.3f, %d", (float)Ref.Millisecs()/1000.0f,dts.IsValid); -// } } //skip pes header int headerLen=9+p[8] ; @@ -1128,24 +1424,13 @@ marker += p[offset]; if (marker == 0x0100) { -// static char tc[]="xibpxxxxXIPBXXXX" ; -// if (!found) - // { - // found=true ; + (*it)->SetFrameType(tc[((p[offset+2]>>3)&7)+(Gop<<3)]); (*it)->SetFrameCount((p[offset+2]>>6)+(p[offset+1]<<2)) ; - // } - // LogDebug("Vid/Dmx : ------ %c %d", tc[((p[offset+2]>>3)&7)+(Gop<<3)], (p[offset+2]>>6)+(p[offset+1]<<2)); break ; } } -// { -// CRefTime Ref ; -// (*it)->MediaTime(Ref) ; -// LogDebug("Vid/Dmx : %03.3f %c %d", (float)Ref.Millisecs()/1000.0f, tc[((p[offset+2]>>3)&7)+(Gop<<3)], ((p[offset+2]>>3)&7)+(Gop<<3)); -// } - } else { @@ -1165,36 +1450,35 @@ } } { - - int lastVidResX=m_mpegPesParser->basicVideoInfo.width; - int lastVidResY=m_mpegPesParser->basicVideoInfo.height; + int lastVidResX=m_mpegPesParser->basicVideoInfo.width; + int lastVidResY=m_mpegPesParser->basicVideoInfo.height; - bool parsed=m_mpegPesParser->OnTsPacket((*it)->Data(),(*it)->Length(),(m_pids.videoPids[0].VideoServiceType==SERVICE_TYPE_VIDEO_MPEG2)); + bool parsed=m_mpegPesParser->OnTsPacket((*it)->Data(),(*it)->Length(),(m_pids.videoPids[0].VideoServiceType==SERVICE_TYPE_VIDEO_MPEG2)); - if (lastVidResX!=m_mpegPesParser->basicVideoInfo.width || lastVidResY!=m_mpegPesParser->basicVideoInfo.height) - { - LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced); + if (lastVidResX!=m_mpegPesParser->basicVideoInfo.width || lastVidResY!=m_mpegPesParser->basicVideoInfo.height) + { + LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced); - if (m_mpegParserTriggerFormatChange) - { - LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser"); - SetVideoChanging(true); - m_filter.OnMediaTypeChanged(3); - m_mpegParserTriggerFormatChange=false; + if (m_mpegParserTriggerFormatChange) + { + LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser"); + SetVideoChanging(true); + m_filter.OnMediaTypeChanged(3); + m_mpegParserTriggerFormatChange=false; + } + LogDebug("DeMultiplexer: triggering OnVideoFormatChanged"); + m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced); } - LogDebug("DeMultiplexer: triggering OnVideoFormatChanged"); - m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced); - } - else - { - if (m_mpegParserTriggerFormatChange && Gop) + else { - LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now."); - m_filter.OnMediaTypeChanged(3); - m_mpegParserTriggerFormatChange=false; + if (m_mpegParserTriggerFormatChange && Gop) + { + LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now."); + m_filter.OnMediaTypeChanged(3); + m_mpegParserTriggerFormatChange=false; + } } } - } //yes, then move the full PES in main queue. while (m_t_vecVideoBuffers.size()) @@ -1207,23 +1491,22 @@ CRefTime Ref ; if((*it)->MediaTime(Ref)) { - if (Gop && !m_bIframeFound) - m_IframeSample = Ref ; - if (Ref < m_FirstVideoSample) m_FirstVideoSample = Ref ; - if (Ref > m_LastVideoSample) m_LastVideoSample = Ref ; + if (Gop && !m_bIframeFound) m_IframeSample = Ref; + if (Ref < m_FirstVideoSample) m_FirstVideoSample = Ref; + if (Ref > m_LastVideoSample) m_LastVideoSample = Ref; } m_bIframeFound=true ; - if (m_bSetVideoDiscontinuity) - { - m_bSetVideoDiscontinuity=false; - (*it)->SetDiscontinuity(); - } - m_vecVideoBuffers.push_back(*it) ; + if (m_bSetVideoDiscontinuity) + { + m_bSetVideoDiscontinuity=false; + (*it)->SetDiscontinuity(); + } + m_vecVideoBuffers.push_back(*it); m_t_vecVideoBuffers.erase(it); } else { - delete (*it) ; + delete (*it); m_t_vecVideoBuffers.erase(it); } } @@ -1233,15 +1516,15 @@ { while (m_t_vecVideoBuffers.size()) { - ivecBuffers it ; - it = m_t_vecVideoBuffers.begin() ; - delete (*it) ; + ivecBuffers it; + it = m_t_vecVideoBuffers.begin(); + delete (*it); m_t_vecVideoBuffers.erase(it); } - m_bSetVideoDiscontinuity=true ; + m_bSetVideoDiscontinuity=true; } } - m_VideoValidPES = true ; + m_VideoValidPES = true; } if (m_VideoValidPES) @@ -1330,8 +1613,6 @@ if(pTeletextEventCallback != NULL) { - //LogDebug("Compensation: %i",m_filter.Compensation.Millisecs()); - //(*pTeletextEventCallback)(TELETEXT_EVENT_COMPENSATION_UPDATE,m_filter.Compensation.Millisecs() * 90); (*pTeletextEventCallback)(TELETEXT_EVENT_PACKET_PCR_UPDATE,m_streamPcr.PcrReferenceBase - m_duration.FirstStartPcr().PcrReferenceBase - (m_filter.Compensation.Millisecs() * 90 )); } if(pTeletextPacketCallback != NULL) @@ -1532,226 +1813,6 @@ } } -/// -/// Method which stops the graph -HRESULT CDeMultiplexer::DoStop() -{ - LogDebug("demux:DoStop"); - HRESULT hr = E_UNEXPECTED; - - FILTER_INFO Info; - if (SUCCEEDED(m_filter.QueryFilterInfo(&Info)) && Info.pGraph != NULL) - { - // Get IMediaFilter interface - IMediaFilter* pMediaFilter = NULL; - hr = Info.pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); - if (!pMediaFilter) - { - Info.pGraph->Release(); - return m_filter.Stop(); - } - else - pMediaFilter->Release(); - - IMediaControl *pMediaControl; - if (SUCCEEDED(Info.pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl))) - { - hr = pMediaControl->Stop(); - pMediaControl->Release(); - } - else - { - LogDebug("Could not get IMediaControl interface"); - } - - Info.pGraph->Release(); - - if (FAILED(hr)) - { - LogDebug("Stopping graph failed with 0x%x", hr); - return S_OK; - } - } - return hr; -} - -/// -/// Method which starts the graph -HRESULT CDeMultiplexer::DoStart() -{ - LogDebug("demux:DoStart"); - HRESULT hr = S_OK; - - FILTER_INFO Info; - if (SUCCEEDED(m_filter.QueryFilterInfo(&Info)) && Info.pGraph != NULL) - { - // Get IMediaFilter interface - IMediaFilter* pMediaFilter = NULL; - hr = Info.pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); - if (!pMediaFilter) - { - Info.pGraph->Release(); - return m_filter.Run(NULL); - } - else - pMediaFilter->Release(); - - IMediaControl *pMediaControl; - if (SUCCEEDED(Info.pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl))) - { - hr = pMediaControl->Run(); - pMediaControl->Release(); - } - - Info.pGraph->Release(); - - if (FAILED(hr)) - { - return S_OK; - } - } - return S_OK; -} - -/// -/// Returns if graph is stopped -HRESULT CDeMultiplexer::IsStopped() -{ - LogDebug("demux:IsStopped"); - HRESULT hr = S_FALSE; - - FILTER_STATE state = State_Stopped; - - FILTER_INFO Info; - if (SUCCEEDED(m_filter.QueryFilterInfo(&Info)) && Info.pGraph != NULL) - { - // Get IMediaFilter interface - IMediaFilter* pMediaFilter = NULL; - hr = Info.pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); - if (!pMediaFilter) - { - Info.pGraph->Release(); - hr = m_filter.GetState(200, &state); - if (state == State_Stopped) - { - if (hr == S_OK || hr == VFW_S_STATE_INTERMEDIATE || VFW_S_CANT_CUE) - return S_OK; - } - } - else - pMediaFilter->Release(); - - IMediaControl *pMediaControl; - if (SUCCEEDED(Info.pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl))) - { - hr = pMediaControl->GetState(200, (OAFilterState*)&state); - pMediaControl->Release(); - } - - Info.pGraph->Release(); - - if (state == State_Stopped) - { - if (hr == S_OK || hr == VFW_S_STATE_INTERMEDIATE || VFW_S_CANT_CUE) - return S_OK; - } - } - return S_FALSE; -} - - -/// -/// Returns if graph is playing -HRESULT CDeMultiplexer::IsPlaying() -{ - LogDebug("demux:IsPlaying"); - - HRESULT hr = S_FALSE; - - FILTER_STATE state = State_Stopped; - - FILTER_INFO Info; - if (SUCCEEDED(m_filter.QueryFilterInfo(&Info)) && Info.pGraph != NULL) - { - // Get IMediaFilter interface - IMediaFilter* pMediaFilter = NULL; - hr = Info.pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); - if (!pMediaFilter) - { - Info.pGraph->Release(); - hr = m_filter.GetState(200, &state); - if (state == State_Running) - { - if (hr == S_OK || hr == VFW_S_STATE_INTERMEDIATE || VFW_S_CANT_CUE) - return S_OK; - } - - return S_FALSE; - } - else - pMediaFilter->Release(); - - IMediaControl *pMediaControl = NULL; - if (SUCCEEDED(Info.pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl))) - { - hr = pMediaControl->GetState(200, (OAFilterState*)&state); - pMediaControl->Release(); - } - - Info.pGraph->Release(); - - if (state == State_Running) - { - if (hr == S_OK || hr == VFW_S_STATE_INTERMEDIATE || VFW_S_CANT_CUE) - return S_OK; - } - } - return S_FALSE; -} -bool CreateFilter(const WCHAR *Name, IBaseFilter **Filter, REFCLSID FilterCategory) -{ - HRESULT hr; - - // Create the system device enumerator. - CComPtr<ICreateDevEnum> devenum; - hr = devenum.CoCreateInstance(CLSID_SystemDeviceEnum); - if (FAILED(hr)) - return false; - - // Create an enumerator for this category. - CComPtr<IEnumMoniker> classenum; - hr = devenum->CreateClassEnumerator(FilterCategory, &classenum, 0); - if (hr != S_OK) - return false; - - // Find the filter that matches the name given. - CComVariant name(Name); - CComPtr<IMoniker> moniker; - while (classenum->Next(1, &moniker, 0) == S_OK) - { - CComPtr<IPropertyBag> properties; - hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&properties); - if (FAILED(hr)) - return false; - - CComVariant friendlyname; - hr = properties->Read(L"FriendlyName", &friendlyname, 0); - if (FAILED(hr)) - return false; - - if (name == friendlyname) - { - hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void **)Filter); - return SUCCEEDED(hr); - } - moniker.Release(); - } - - // Couldn't find a matching filter. - return false; -} - - ///Returns whether the demuxer is allowed to block in GetAudio() or not bool CDeMultiplexer::HoldAudio() { @@ -1804,19 +1865,17 @@ void CDeMultiplexer::RequestNewPat(void) { - m_ReqPatVersion++ ; - m_ReqPatVersion &= 0x0F ; - LogDebug("Request new PAT = %d", m_ReqPatVersion) ; - m_WaitNewPatTmo=GetTickCount()+10000 ; + m_ReqPatVersion++; + m_ReqPatVersion &= 0x0F; + LogDebug("Request new PAT = %d", m_ReqPatVersion); + m_WaitNewPatTmo=GetTickCount()+10000; } void CDeMultiplexer::ClearRequestNewPat(void) { - m_ReqPatVersion=m_iPatVersion ; // Used for AnalogTv or channel change fail. + m_ReqPatVersion=m_iPatVersion; // Used for AnalogTv or channel change fail. } - - void CDeMultiplexer::SetTeletextEventCallback(int (CALLBACK *pTeletextEventCallback)(int eventcode, DWORD64 eval)) { this->pTeletextEventCallback = pTeletextEventCallback; @@ -1836,7 +1895,6 @@ { if(pTeletextEventCallback != NULL) { - //LogDebug("CallTeletextEventCallback %i %i", eventCode,eventValue); (*pTeletextEventCallback)(eventCode,eventValue); } } Modified: branches/TsReader_NALU/TsReader/source/DeMultiplexer.h =================================================================== --- branches/TsReader_NALU/TsReader/source/DeMultiplexer.h 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/DeMultiplexer.h 2009-11-30 21:36:36 UTC (rev 24289) @@ -19,6 +19,10 @@ * */ #pragma once + +#include "StdAfx.h" +#include <atlbase.h> +#include <atlcoll.h> #include "buffer.h" #include "MultiFileReader.h" #include "tsDuration.h" @@ -35,8 +39,25 @@ #include <map> #include <dvdmedia.h> #include "MpegPesParser.h" + using namespace std; class CTsReaderFilter; + +// Used for H.264 video stream demuxing +class Packet : public CAtlArray<BYTE> +{ +public: + DWORD TrackNumber; + BOOL bDiscontinuity, bSyncPoint, bAppendable; + static const REFERENCE_TIME INVALID_TIME = _I64_MIN; + REFERENCE_TIME rtStart, rtStop; + AM_MEDIA_TYPE* pmt; + Packet() {pmt = NULL; bDiscontinuity = bAppendable = FALSE;} + virtual ~Packet() {if(pmt) DeleteMediaType(pmt);} + virtual int GetDataSize() {return GetCount();} + void SetData(const void* ptr, DWORD len) {SetCount(len); memcpy(GetData(), ptr, len);} +}; + class CDeMultiplexer : public CPacketSync, public IPatParserCallback { public: @@ -55,6 +76,8 @@ bool CheckContinuity(int prevCC, CTsHeader& header); void FillAudio(CTsHeader& header, byte* tsPacket); void FillVideo(CTsHeader& header, byte* tsPacket); + void FillVideoH264(CTsHeader& header, byte* tsPacket); + void FillVideoMPEG2(CTsHeader& header, byte* tsPacket); void FillTeletext(CTsHeader& header, byte* tsPacket); void SetEndOfFile(bool bEndOfFile); CPidTable GetPidTable(); @@ -119,17 +142,13 @@ int pid; int subtitleType; // 0=DVB, 1=teletext <-- needs enum char language[4]; - } ; + }; vector<struct stAudioStream> m_audioStreams; vector<struct stSubtitleStream> m_subtitleStreams; int ReadFromFile(bool isAudio, bool isVideo); bool m_bEndOfFile; HRESULT RenderFilterPin(CBasePin* pin, bool isAudio, bool isVideo); - HRESULT DoStart(); - HRESULT DoStop(); - HRESULT IsStopped(); - HRESULT IsPlaying(); CCritSec m_sectionAudio; CCritSec m_sectionVideo; CCritSec m_sectionSubtitle; @@ -144,14 +163,14 @@ vector<CBuffer*> m_vecAudioBuffers; vector<CBuffer*> m_t_vecAudioBuffers; typedef vector<CBuffer*>::iterator ivecBuffers; - int m_AudioPrevCC ; - int m_VideoPrevCC ; - bool m_AudioValidPES ; - bool m_VideoValidPES ; - CRefTime m_FirstAudioSample ; - CRefTime m_LastAudioSample ; - CRefTime m_FirstVideoSample ; - CRefTime m_LastVideoSample ; + int m_AudioPrevCC; + int m_VideoPrevCC; + bool m_AudioValidPES; + bool m_VideoValidPES; + CRefTime m_FirstAudioSample; + CRefTime m_LastAudioSample; + CRefTime m_FirstVideoSample; + CRefTime m_LastVideoSample; CBuffer* m_pCurrentTeletextBuffer; CBuffer* m_pCurrentSubtitleBuffer; @@ -166,14 +185,13 @@ unsigned int m_audioPid; unsigned int m_currentSubtitlePid; unsigned int m_iSubtitleStream; - unsigned int m_currentTeletextPid; // Ziphnor + unsigned int m_currentTeletextPid; unsigned int m_iAudioReadCount; bool m_bHoldAudio; bool m_bHoldVideo; bool m_bHoldSubtitle; - //bool m_bPreferAC3; int m_iAudioIdx; int m_iPatVersion; int m_ReqPatVersion; @@ -193,5 +211,8 @@ int (CALLBACK *pTeletextEventCallback)(int,DWORD64); int (CALLBACK *pSubUpdateCallback)(int c, void* opts,int* bi); - // used to sync teletext packets with video + // Used only for H.264 stream demuxing + CAutoPtr<Packet> m_p; + CAutoPtrList<Packet> m_pl; + bool m_fHasAccessUnitDelimiters; }; Modified: branches/TsReader_NALU/TsReader/source/FileReader.cpp =================================================================== --- branches/TsReader_NALU/TsReader/source/FileReader.cpp 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/FileReader.cpp 2009-11-30 21:36:36 UTC (rev 24289) @@ -23,7 +23,8 @@ * nate can be reached on the forums at * http://forums.dvbowners.com/ */ -#include <windows.h> +#include "StdAfx.h" + #include "FileReader.h" //#include "global.h" extern void LogDebug(const char *fmt, ...) ; @@ -43,40 +44,40 @@ FileReader::~FileReader() { - CloseFile(); - if (m_pFileName) - delete m_pFileName; + CloseFile(); + if (m_pFileName) + delete m_pFileName; } HRESULT FileReader::GetFileName(LPOLESTR *lpszFileName) { - *lpszFileName = m_pFileName; - return S_OK; + *lpszFileName = m_pFileName; + return S_OK; } HRESULT FileReader::SetFileName(LPCOLESTR pszFileName) { - // Is this a valid filename supplied - //CheckPointer(pszFileName,E_POINTER); + // Is this a valid filename supplied + //CheckPointer(pszFileName,E_POINTER); - if(wcslen(pszFileName) > MAX_PATH) - return ERROR_FILENAME_EXCED_RANGE; + if(wcslen(pszFileName) > MAX_PATH) + return ERROR_FILENAME_EXCED_RANGE; - // Take a copy of the filename + // Take a copy of the filename - if (m_pFileName) - { - delete[] m_pFileName; - m_pFileName = NULL; - } - m_pFileName = new WCHAR[1+lstrlenW(pszFileName)]; - if (m_pFileName == NULL) - return E_OUTOFMEMORY; + if (m_pFileName) + { + delete[] m_pFileName; + m_pFileName = NULL; + } + m_pFileName = new WCHAR[1+lstrlenW(pszFileName)]; + if (m_pFileName == NULL) + return E_OUTOFMEMORY; - wcscpy(m_pFileName, pszFileName); + wcscpy(m_pFileName, pszFileName); - return S_OK; + return S_OK; } // Modified: branches/TsReader_NALU/TsReader/source/FrameHeaderParser.cpp =================================================================== --- branches/TsReader_NALU/TsReader/source/FrameHeaderParser.cpp 2009-11-30 21:33:37 UTC (rev 24288) +++ branches/TsReader_NALU/TsReader/source/FrameHeaderParser.cpp 2009-11-30 21:36:36 UTC (rev 24289) @@ -19,6 +19,9 @@ * */ +#include "StdAfx.h" +#include <streams.h> + #include "FrameHeaderParser.h" #include <wxdebug.h> #include <dvdmedia.h> @@ -1178,33 +1181,38 @@ { while(GetRemaining()>4 && (h.spslen==0 || h.ppslen==0)) { - // check for NALU startcode - DWORD dwStartCode=BitRead(32,true); - if (dwStartCode!=0x00000001) - { - BitRead(8); - continue; - } - - // skip the startcode - BitRead(32); + //// check for NALU startcode + //DWORD dwStartCode=BitRead(24,true); + //if (dwStartCode!=0x00000001) + //{ + // BitRead(8); + // continue; + //} + // + //// skip the startcode + //BitRead(24); + int nal_len = BitRead(32); + INT64 next_nal = GetPos()+nal_len; int id=BitRead(8); int nal_type=id & 0x9f; - if(h.spspos != 0 && h.spslen == 0) - { - INT64 curpos=GetPos(); - h.spslen = curpos - h.spspos; - } - if(h.ppspos != 0 && h.ppslen == 0) - { - INT64 curpos=GetPos(); - h.ppslen = curpos - h.ppspos; - } + //if(h.spspos != 0 && h.spslen == 0) + //{ + // INT64 curpos=GetPos(); + // h.spslen = curpos - h.spspos; + //} + //if(h.ppspos != 0 && h.ppslen == 0) + //{ + // INT64 curpos=GetPos(); + // h.ppslen = curpos - h.ppspos; + //} // we only want pic param and sequence param sets - if (nal_type!=0x7 && nal_type!=0x8) + if (nal_type!=0x7 && nal_type!=0x8 || id & 0x60 == 0) + { + Seek(next_nal); continue; + } if(nal_type==0x7) { @@ -1217,10 +1225,11 @@ __int64 time_scale; long fixed_frame_rate_flag; - h.spspos = GetPos(); + h.spspos = GetPos() - 5; + ... [truncated message content] |