00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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);
00074 }
00075
00076 #endif
00077
00078
00079
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
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
00150 }
00151 else if(sh->stream_class == CNutFile::SC_SUBTITLE)
00152 {
00153
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
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
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
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
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
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
00334
00335
00336 CNutSourceFilter::CNutSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
00337 : CNutSplitterFilter(pUnk, phr)
00338 {
00339 m_clsid = __uuidof(this);
00340 m_pInput.Free();
00341 }