NutSplitter.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "StdAfx.h"
00023 #include <initguid.h>
00024 #include "NutSplitter.h"
00025 #include "..\..\..\..\include\moreuuids.h"
00026 
00027 #ifdef REGISTER_FILTER
00028 
00029 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00030 {
00031         {&MEDIATYPE_Stream, &MEDIASUBTYPE_Nut},
00032         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
00033 };
00034 
00035 const AMOVIESETUP_PIN sudpPins[] =
00036 {
00037     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00038     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00039 };
00040 
00041 const AMOVIESETUP_FILTER sudFilter[] =
00042 {
00043         {&__uuidof(CNutSplitterFilter), L"Nut Splitter", MERIT_NORMAL+1, countof(sudpPins), sudpPins},
00044         {&__uuidof(CNutSourceFilter), L"Nut Source", MERIT_NORMAL+1, 0, NULL},
00045 };
00046 
00047 CFactoryTemplate g_Templates[] =
00048 {
00049         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CNutSplitterFilter>, NULL, &sudFilter[0]},
00050         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CNutSourceFilter>, NULL, &sudFilter[1]},
00051 };
00052 
00053 int g_cTemplates = countof(g_Templates);
00054 
00055 STDAPI DllRegisterServer()
00056 {
00057         RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_Nut, _T("0,8,,F9526A624E55544D"), _T(".nut"), NULL);
00058 
00059         return AMovieDllRegisterServer2(TRUE);
00060 }
00061 
00062 STDAPI DllUnregisterServer()
00063 {
00064         UnRegisterSourceFilter(MEDIASUBTYPE_Nut);
00065 
00066         return AMovieDllRegisterServer2(FALSE);
00067 }
00068 
00069 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00070 
00071 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00072 {
00073     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00074 }
00075 
00076 #endif
00077 
00078 //
00079 // CNutSplitterFilter
00080 //
00081 
00082 CNutSplitterFilter::CNutSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00083         : CBaseSplitterFilter(NAME("CNutSplitterFilter"), pUnk, phr, __uuidof(this))
00084 {
00085 }
00086 
00087 HRESULT CNutSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00088 {
00089         CheckPointer(pAsyncReader, E_POINTER);
00090 
00091         HRESULT hr = E_FAIL;
00092 
00093         m_pFile.Free();
00094 
00095         m_pFile.Attach(new CNutFile(pAsyncReader, hr));
00096         if(!m_pFile) return E_OUTOFMEMORY;
00097         if(FAILED(hr)) {m_pFile.Free(); return hr;}
00098 
00099         m_rtNewStart = m_rtCurrent = 0;
00100         m_rtNewStop = m_rtStop = m_rtDuration = 0;
00101 
00102         // pins
00103 
00104         POSITION pos = m_pFile->m_streams.GetHeadPosition();
00105         while(pos)
00106         {
00107                 CNutFile::stream_header* sh = m_pFile->m_streams.GetNext(pos);
00108 
00109                 CArray<CMediaType> mts;
00110                 CMediaType mt;
00111 
00112                 if(sh->stream_class == CNutFile::SC_VIDEO)
00113                 {
00114                         CNutFile::video_stream_header& vsh = sh->vsh;
00115 
00116                         mt.majortype = MEDIATYPE_Video;
00117                         mt.subtype = FOURCCMap(*(DWORD*)sh->fourcc.GetData());
00118                         mt.formattype = FORMAT_VideoInfo;
00119 
00120                         VIDEOINFOHEADER vih;
00121                         memset(&vih, 0, sizeof(vih));
00122                         vih.dwBitRate = (DWORD)sh->average_bitrate;
00123                         vih.AvgTimePerFrame = 10000000i64 * sh->time_base_nom / sh->time_base_denom;
00124                         vih.bmiHeader.biSize = sizeof(vih.bmiHeader);
00125                         vih.bmiHeader.biCompression = mt.subtype.Data1;
00126                         vih.bmiHeader.biWidth = (LONG)vsh.width;
00127                         vih.bmiHeader.biHeight = (LONG)vsh.height;
00128                         mt.SetFormat((BYTE*)&vih, sizeof(vih));
00129 
00130                         mts.Add(mt);
00131 
00132                         if(vsh.sample_width && vsh.sample_height)
00133                         {
00134                                 VIDEOINFOHEADER2 vih2;
00135                                 memset(&vih2, 0, sizeof(vih2));
00136                                 vih2.dwBitRate = vih.dwBitRate;
00137                                 vih2.AvgTimePerFrame = vih.AvgTimePerFrame;
00138                                 vih2.dwPictAspectRatioX = (DWORD)vsh.sample_width;
00139                                 vih2.dwPictAspectRatioY = (DWORD)vsh.sample_height;
00140                                 vih2.bmiHeader = vih.bmiHeader;
00141                                 mt.SetFormat((BYTE*)&vih2, sizeof(vih2));
00142 
00143                                 mts.InsertAt(0, mt);
00144                         }
00145                 }
00146                 else if(sh->stream_class == CNutFile::SC_AUDIO)
00147                 {
00148                         CNutFile::audio_stream_header& ash = sh->ash;
00149                         // TODO
00150                 }
00151                 else if(sh->stream_class == CNutFile::SC_SUBTITLE)
00152                 {
00153                         // TODO
00154                 }
00155 
00156                 if(mts.GetCount() > 0)
00157                 {
00158                         CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Video", this, this, &hr));
00159                         AddOutputPin((DWORD)sh->stream_id, pPinOut);
00160                 }
00161         }
00162 
00163         // TODO
00164         m_rtNewStop = m_rtStop = m_rtDuration = 0;
00165 
00166         return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00167 }
00168 
00169 bool CNutSplitterFilter::DemuxInit()
00170 {
00171         if(!m_pFile) return(false);
00172         m_pFile->Seek(0);
00173         return(true);
00174 }
00175 
00176 void CNutSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00177 {
00178         POSITION pos = m_pFile->m_streams.GetHeadPosition();
00179         while(pos) m_pFile->m_streams.GetNext(pos)->msb_timestamp = 0;
00180 
00181     if(rt <= 0)
00182         {
00183                 m_pFile->Seek(0);
00184         }
00185         else
00186         {
00187                 m_pFile->Seek(0);
00188                 // TODO
00189         }
00190 }
00191 
00192 bool CNutSplitterFilter::DemuxLoop()
00193 {
00194         bool fKeyFrame = false;
00195 
00196         while(!CheckRequest(NULL) && m_pFile->GetPos() < m_pFile->GetLength())
00197         {
00198                 CNutFile::frame_header fh;
00199                 fh.checksum_flag = 1;
00200 
00201                 UINT64 id = 0;
00202 
00203                 if(m_pFile->BitRead(1, true) == 0)
00204                 {
00205                         fh.zero_bit = m_pFile->BitRead(1);
00206                         fh.priority = m_pFile->BitRead(2);
00207                 fh.checksum_flag = m_pFile->BitRead(1);
00208                         fh.msb_timestamp_flag = m_pFile->BitRead(1);
00209                         fh.subpacket_type = m_pFile->BitRead(2);
00210                         fh.reserved = m_pFile->BitRead(1);
00211                 }
00212                 else
00213                 {
00214                         if((id = m_pFile->BitRead(64)) == NUTK)
00215                         {
00216                                 fKeyFrame = true;
00217                                 continue;
00218                         }
00219                 }
00220 
00221                 CNutFile::packet_header ph;
00222                 m_pFile->Read(ph);
00223 
00224                 if(id == 0)
00225                 {
00226                         CNutFile::vint stream_id;
00227                         m_pFile->Read(stream_id);
00228 
00229                         CNutFile::stream_header* sh = NULL;
00230 
00231                         POSITION pos = m_pFile->m_streams.GetHeadPosition();
00232                         while(pos)
00233                         {
00234                                 CNutFile::stream_header* tmp = m_pFile->m_streams.GetNext(pos);
00235                                 if(tmp->stream_id == stream_id) {sh = tmp; break;}
00236                         }
00237 
00238                         if(sh)
00239                         {
00240                                 if(fh.msb_timestamp_flag)
00241                                         m_pFile->Read(sh->msb_timestamp);
00242 
00243                                 CNutFile::svint lsb_timestamp = 0;
00244                                 m_pFile->Read(lsb_timestamp);
00245 
00246 TRACE(_T("[%I64d]: %I64d:%I64d\n"), stream_id, sh->msb_timestamp, lsb_timestamp);
00247 
00248                                 CAutoPtr<Packet> p(new Packet());
00249                                 p->TrackNumber = (DWORD)stream_id;
00250                                 p->bSyncPoint = fKeyFrame;
00251                                 p->rtStart = 10000i64 * ((sh->msb_timestamp << sh->msb_timestamp_shift) + lsb_timestamp) 
00252                                         * sh->time_base_nom / sh->time_base_denom;
00253                                 p->rtStop = p->rtStart+1;
00254 
00255                                 fKeyFrame = false;
00256 
00257                                 CNutFile::vint len = ph.fptr - (m_pFile->GetPos() - ph.pos);
00258                                 if(fh.checksum_flag) len -= 4;
00259 
00260                                 if(fh.subpacket_type == 1)
00261                                 {
00262                                         p->pData.SetSize(len);
00263                                         m_pFile->CBaseSplitterFile::Read(p->pData.GetData(), p->pData.GetSize());
00264 
00265                                         if(FAILED(DeliverPacket(p)))
00266                                                 break;
00267                                 }
00268                                 else
00269                                 {
00270                                         // TODO
00271 /*
00272                                         vint subpacket_count;
00273                                         Read(subpacket_count);
00274 
00275                                         if(fh.subpacket_type & 1)
00276                                         {
00277                                                 CArray<vint> keyframe_run;
00278                                                 keyframe_run.SetSize(subpacket_count);
00279                                                 for(int i = 0; i < subpacket_count; i++)
00280                                                         Read(keyframe_run[i]);
00281                                         }
00282 
00283                                         CArray<vint> timestamp_diff;
00284                                         timestamp_diff.SetSize(subpacket_count);
00285                                         CArray<vint> timestamp_diff_run;
00286                                         timestamp_diff_run.SetSize(subpacket_count);
00287                                         for(int i = 0; i < subpacket_count; i++)
00288                                         {
00289                                                 Read(timestamp_diff[i]);
00290                                                 if(timestamp_diff[i] & 1)
00291                                                         Read(timestamp_diff_run[i]);
00292                                         }
00293 
00294                                         if(fh.subpacket_type & 2)
00295                                         {
00296                                                 CArray<string> subpacket_size_diff;
00297                                                 for(int i = 0; i < subpacket_count-1; i++)
00298                                                 {
00299                                                         Read(subpacket_size_diff[i]);
00300                                                 }
00301                                         }
00302 
00303                                         for(int i = 0; i < subpacket_count; i++)
00304                                         {
00305                                         }
00306 */
00307                                 }
00308                         }
00309                 }
00310 
00311                 if(fh.checksum_flag)
00312                 {
00313                         m_pFile->Seek(ph.pos + ph.fptr - 4);
00314                         ph.checksum = (UINT32)m_pFile->BitRead(32);
00315                 }
00316 
00317                 m_pFile->Seek(ph.pos + ph.fptr);
00318         }
00319 
00320         return(true);
00321 }
00322 
00323 // IMediaSeeking
00324 
00325 STDMETHODIMP CNutSplitterFilter::GetDuration(LONGLONG* pDuration)
00326 {
00327         CheckPointer(pDuration, E_POINTER);
00328         *pDuration = m_rtDuration;
00329         return S_OK;
00330 }
00331 
00332 //
00333 // CNutSourceFilter
00334 //
00335 
00336 CNutSourceFilter::CNutSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
00337         : CNutSplitterFilter(pUnk, phr)
00338 {
00339         m_clsid = __uuidof(this);
00340         m_pInput.Free();
00341 }

Generated on Tue Dec 13 14:47:21 2005 for guliverkli by  doxygen 1.4.5