- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }