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 <mmreg.h>
00024 #include "MpegSplitterFile.h"
00025
00026 #include <initguid.h>
00027 #include "..\..\..\..\include\moreuuids.h"
00028
00029 #define MEGABYTE 1024*1024
00030 #define ISVALIDPID(pid) (pid >= 0x10 && pid < 0x1fff)
00031
00032 CMpegSplitterFile::CMpegSplitterFile(IAsyncReader* pAsyncReader, HRESULT& hr)
00033 : CBaseSplitterFileEx(pAsyncReader, hr)
00034 , m_type(us)
00035 , m_rate(0)
00036 {
00037 if(SUCCEEDED(hr)) hr = Init();
00038 }
00039
00040 HRESULT CMpegSplitterFile::Init()
00041 {
00042 HRESULT hr;
00043
00044
00045
00046 m_type = us;
00047
00048 Seek(0);
00049
00050 if(m_type == us)
00051 {
00052 int cnt = 0, limit = 4;
00053 for(trhdr h; cnt < limit && Read(h); cnt++) Seek(h.next);
00054 if(cnt >= limit) m_type = ts;
00055 }
00056
00057 Seek(0);
00058
00059 if(m_type == us)
00060 {
00061 int cnt = 0, limit = 4;
00062 for(pvahdr h; cnt < limit && Read(h); cnt++) Seek(GetPos() + h.length);
00063 if(cnt >= limit) m_type = pva;
00064 }
00065
00066 Seek(0);
00067
00068 if(m_type == us)
00069 {
00070 BYTE b;
00071 for(int i = 0; (i < 4 || GetPos() < 65536) && m_type == us && NextMpegStartCode(b); i++)
00072 {
00073 if(b == 0xba)
00074 {
00075 pshdr h;
00076 if(Read(h))
00077 {
00078 m_type = ps;
00079 m_rate = h.bitrate/8;
00080 break;
00081 }
00082 }
00083 else if((b&0xe0) == 0xc0
00084 || (b&0xf0) == 0xe0
00085
00086 || b == 0xbd)
00087 {
00088 peshdr h;
00089 if(Read(h, b))
00090 {
00091 m_type = es;
00092 }
00093 }
00094 }
00095 }
00096
00097 Seek(0);
00098
00099 if(m_type == us)
00100 {
00101 return E_FAIL;
00102 }
00103
00104
00105
00106 if(IsStreaming())
00107 {
00108 for(int i = 0; i < 50 && GetLength() < 1024*100 || i < 20; i++)
00109 Sleep(100);
00110 }
00111
00112
00113
00114 m_rtMin = m_posMin = _I64_MAX;
00115 m_rtMax = m_posMax = 0;
00116
00117 CList<__int64> fps;
00118 for(int i = 0, j = 5; i <= j; i++)
00119 fps.AddTail(i*GetLength()/j);
00120
00121 for(__int64 pfp = 0; fps.GetCount(); )
00122 {
00123 __int64 fp = fps.RemoveHead();
00124 fp = min(GetLength() - MEGABYTE/8, fp);
00125 fp = max(pfp, fp);
00126 __int64 nfp = fp + (pfp == 0 ? 5*MEGABYTE : MEGABYTE/8);
00127 if(FAILED(hr = SearchStreams(fp, nfp)))
00128 return hr;
00129 pfp = nfp;
00130 }
00131
00132 if(m_posMax - m_posMin <= 0 || m_rtMax - m_rtMin <= 0)
00133 return E_FAIL;
00134
00135 int indicated_rate = m_rate;
00136 int detected_rate = 10000000i64 * (m_posMax - m_posMin) / (m_rtMax - m_rtMin);
00137
00138
00139 if(indicated_rate == 0 || ((float)detected_rate / indicated_rate) < 1.1
00140 || abs(detected_rate - indicated_rate) < 50*1024)
00141 m_rate = detected_rate;
00142 else ;
00143
00144 #ifndef DEBUG
00145 if(m_streams[video].GetCount() || m_streams[subpic].GetCount())
00146 {
00147 stream s;
00148 s.mt.majortype = MEDIATYPE_Video;
00149 s.mt.subtype = MEDIASUBTYPE_DVD_SUBPICTURE;
00150 s.mt.formattype = FORMAT_None;
00151 m_streams[subpic].Insert(s);
00152 }
00153 #endif
00154
00155 Seek(0);
00156
00157 return S_OK;
00158 }
00159
00160 REFERENCE_TIME CMpegSplitterFile::NextPTS(DWORD TrackNum)
00161 {
00162 REFERENCE_TIME rt = -1;
00163 __int64 rtpos = -1;
00164
00165 BYTE b;
00166
00167 while(GetPos() < GetLength())
00168 {
00169 if(m_type == ps || m_type == es)
00170 {
00171 if(!NextMpegStartCode(b))
00172 {ASSERT(0); break;}
00173
00174 rtpos = GetPos()-4;
00175
00176 if(b >= 0xbd && b < 0xf0)
00177 {
00178 peshdr h;
00179 if(!Read(h, b) || !h.len) continue;
00180
00181 __int64 pos = GetPos();
00182
00183 if(h.fpts && AddStream(0, b, h.len) == TrackNum)
00184 {
00185 ASSERT(h.pts >= m_rtMin && h.pts <= m_rtMax);
00186 rt = h.pts;
00187 break;
00188 }
00189
00190 Seek(pos + h.len);
00191 }
00192 }
00193 else if(m_type == ts)
00194 {
00195 trhdr h;
00196 if(!Read(h)) continue;
00197
00198 rtpos = GetPos()-4;
00199
00200 if(h.payload && h.payloadstart && ISVALIDPID(h.pid))
00201 {
00202 peshdr h2;
00203 if(NextMpegStartCode(b, 4) && Read(h2, b))
00204 {
00205 if(h2.fpts && AddStream(h.pid, b, h.bytes - (GetPos() - rtpos)) == TrackNum)
00206 {
00207 ASSERT(h2.pts >= m_rtMin && h2.pts <= m_rtMax);
00208 rt = h2.pts;
00209 break;
00210 }
00211 }
00212 }
00213
00214 Seek(h.next);
00215 }
00216 else if(m_type == pva)
00217 {
00218 pvahdr h;
00219 if(!Read(h)) continue;
00220
00221 if(h.fpts)
00222 {
00223 rt = h.pts;
00224 break;
00225 }
00226 }
00227 }
00228
00229 if(rtpos >= 0) Seek(rtpos);
00230 if(rt >= 0) rt -= m_rtMin;
00231
00232 return rt;
00233 }
00234
00235 HRESULT CMpegSplitterFile::SearchStreams(__int64 start, __int64 stop)
00236 {
00237 Seek(start);
00238 stop = min(stop, GetLength());
00239
00240 while(GetPos() < stop)
00241 {
00242 BYTE b;
00243
00244 if(m_type == ps || m_type == es)
00245 {
00246 if(!NextMpegStartCode(b)) continue;
00247
00248 if(b == 0xba)
00249 {
00250 pshdr h;
00251 if(!Read(h)) continue;
00252 }
00253 else if(b == 0xbb)
00254 {
00255 pssyshdr h;
00256 if(!Read(h)) continue;
00257 }
00258 else if(b >= 0xbd && b < 0xf0)
00259 {
00260 peshdr h;
00261 if(!Read(h, b)) continue;
00262
00263 if(h.type == mpeg2 && h.scrambling) {ASSERT(0); return E_FAIL;}
00264
00265 if(h.fpts)
00266 {
00267 if(m_rtMin == _I64_MAX) {m_rtMin = h.pts; m_posMin = GetPos();}
00268 if(m_rtMin < h.pts && m_rtMax < h.pts) {m_rtMax = h.pts; m_posMax = GetPos();}
00269
00270
00271
00272
00273
00274
00275 }
00276
00277 __int64 pos = GetPos();
00278 AddStream(0, b, h.len);
00279 if(h.len) Seek(pos + h.len);
00280 }
00281 }
00282 else if(m_type == ts)
00283 {
00284 trhdr h;
00285 if(!Read(h)) continue;
00286
00287
00288
00289 __int64 pos = GetPos();
00290
00291 if(h.payload && ISVALIDPID(h.pid))
00292 {
00293 peshdr h2;
00294 if(h.payloadstart && NextMpegStartCode(b, 4) && Read(h2, b))
00295 {
00296 if(h2.type == mpeg2 && h2.scrambling) {ASSERT(0); return E_FAIL;}
00297
00298 if(h2.fpts)
00299 {
00300 if(m_rtMin == _I64_MAX) {m_rtMin = h2.pts; m_posMin = GetPos();}
00301 if(m_rtMin < h2.pts && m_rtMax < h2.pts) {m_rtMax = h2.pts; m_posMax = GetPos();}
00302 }
00303 }
00304 else
00305 {
00306 b = 0;
00307 }
00308
00309 AddStream(h.pid, b, h.bytes - (GetPos() - pos));
00310 }
00311
00312 Seek(h.next);
00313 }
00314 else if(m_type == pva)
00315 {
00316 pvahdr h;
00317 if(!Read(h)) continue;
00318
00319 if(h.fpts)
00320 {
00321 if(m_rtMin == _I64_MAX) {m_rtMin = h.pts; m_posMin = GetPos();}
00322 if(m_rtMin < h.pts && m_rtMax < h.pts) {m_rtMax = h.pts; m_posMax = GetPos();}
00323 }
00324
00325 __int64 pos = GetPos();
00326 if(h.streamid == 1) AddStream(h.streamid, 0xe0, h.length);
00327 else if(h.streamid == 2) AddStream(h.streamid, 0xc0, h.length);
00328 if(h.length) Seek(pos + h.length);
00329 }
00330 }
00331
00332 return S_OK;
00333 }
00334
00335 DWORD CMpegSplitterFile::AddStream(WORD pid, BYTE pesid, DWORD len)
00336 {
00337 if(pid)
00338 {
00339 if(pesid) m_pid2pes[pid] = pesid;
00340 else m_pid2pes.Lookup(pid, pesid);
00341 }
00342
00343 stream s;
00344 s.pid = pid;
00345 s.pesid = pesid;
00346
00347 int type = unknown;
00348
00349 if(pesid >= 0xe0 && pesid < 0xf0)
00350 {
00351 __int64 pos = GetPos();
00352
00353 if(type == unknown)
00354 {
00355 CMpegSplitterFile::seqhdr h;
00356 if(!m_streams[video].Find(s) && Read(h, len, &s.mt))
00357 type = video;
00358 }
00359
00360 Seek(pos);
00361
00362 if(type == unknown)
00363 {
00364 CMpegSplitterFile::avchdr h;
00365 if(!m_streams[video].Find(s) && Read(h, len, &s.mt))
00366 type = video;
00367 }
00368 }
00369 else if(pesid >= 0xc0 && pesid < 0xe0)
00370 {
00371 __int64 pos = GetPos();
00372
00373 if(type == unknown)
00374 {
00375 CMpegSplitterFile::mpahdr h;
00376 if(!m_streams[audio].Find(s) && Read(h, len, false, &s.mt))
00377 type = audio;
00378 }
00379
00380 Seek(pos);
00381
00382 if(type == unknown)
00383 {
00384 CMpegSplitterFile::aachdr h;
00385 if(!m_streams[audio].Find(s) && Read(h, len, &s.mt))
00386 type = audio;
00387 }
00388 }
00389 else if(pesid == 0xbd)
00390 {
00391 if(s.pid)
00392 {
00393 if(!m_streams[audio].Find(s))
00394 {
00395 __int64 pos = GetPos();
00396
00397 if(type == unknown)
00398 {
00399 CMpegSplitterFile::ac3hdr h;
00400 if(Read(h, len, &s.mt))
00401 type = audio;
00402 }
00403
00404 Seek(pos);
00405
00406 if(type == unknown)
00407 {
00408 CMpegSplitterFile::dtshdr h;
00409 if(Read(h, len, &s.mt))
00410 type = audio;
00411 }
00412 }
00413 }
00414 else
00415 {
00416 BYTE b = (BYTE)BitRead(8, true);
00417 WORD w = (WORD)BitRead(16, true);
00418 DWORD dw = (DWORD)BitRead(32, true);
00419
00420 if(b >= 0x80 && b < 0x88 || w == 0x0b77)
00421 {
00422 s.ps1id = (b >= 0x80 && b < 0x88) ? (BYTE)(BitRead(32) >> 24) : 0x80;
00423
00424 CMpegSplitterFile::ac3hdr h;
00425 if(!m_streams[audio].Find(s) && Read(h, len, &s.mt))
00426 type = audio;
00427 }
00428 else if(b >= 0x88 && b < 0x90 || dw == 0x7ffe8001)
00429 {
00430 s.ps1id = (b >= 0x88 && b < 0x90) ? (BYTE)(BitRead(32) >> 24) : 0x88;
00431
00432 CMpegSplitterFile::dtshdr h;
00433 if(!m_streams[audio].Find(s) && Read(h, len, &s.mt))
00434 type = audio;
00435 }
00436 else if(b >= 0xa0 && b < 0xa8)
00437 {
00438 s.ps1id = (b >= 0xa0 && b < 0xa8) ? (BYTE)(BitRead(32) >> 24) : 0xa0;
00439
00440 CMpegSplitterFile::lpcmhdr h;
00441 if(Read(h, &s.mt) && !m_streams[audio].Find(s))
00442 type = audio;
00443 }
00444 else if(b >= 0x20 && b < 0x40)
00445 {
00446 s.ps1id = (BYTE)BitRead(8);
00447
00448 CMpegSplitterFile::dvdspuhdr h;
00449 if(!m_streams[subpic].Find(s) && Read(h, &s.mt))
00450 type = subpic;
00451 }
00452 else if(b >= 0x70 && b < 0x80)
00453 {
00454 s.ps1id = (BYTE)BitRead(8);
00455
00456 CMpegSplitterFile::svcdspuhdr h;
00457 if(!m_streams[subpic].Find(s) && Read(h, &s.mt))
00458 type = subpic;
00459 }
00460 else if(b >= 0x00 && b < 0x10)
00461 {
00462 s.ps1id = (BYTE)BitRead(8);
00463
00464 CMpegSplitterFile::cvdspuhdr h;
00465 if(!m_streams[subpic].Find(s) && Read(h, &s.mt))
00466 type = subpic;
00467 }
00468 else if(w == 0xffa0 || w == 0xffa1)
00469 {
00470 s.ps1id = (BYTE)BitRead(8);
00471 s.pid = (WORD)((BitRead(8) << 8) | BitRead(16));
00472
00473 CMpegSplitterFile::ps2audhdr h;
00474 if(!m_streams[audio].Find(s) && Read(h, &s.mt))
00475 type = audio;
00476 }
00477 else if(w == 0xff90)
00478 {
00479 s.ps1id = (BYTE)BitRead(8);
00480 s.pid = (WORD)((BitRead(8) << 8) | BitRead(16));
00481
00482 w = BitRead(16, true);
00483
00484 if(w == 0x0b77)
00485 {
00486 CMpegSplitterFile::ac3hdr h;
00487 if(!m_streams[audio].Find(s) && Read(h, len, &s.mt))
00488 type = audio;
00489 }
00490 else if(w == 0x0000)
00491 {
00492 CMpegSplitterFile::ps2subhdr h;
00493 if(!m_streams[subpic].Find(s) && Read(h, &s.mt))
00494 type = subpic;
00495 }
00496 }
00497 }
00498 }
00499 else if(pesid == 0xbe)
00500 {
00501 }
00502 else if(pesid == 0xbf)
00503 {
00504 }
00505
00506 if(type != unknown && !m_streams[type].Find(s))
00507 {
00508 if(s.pid)
00509 {
00510 for(int i = 0; i < unknown; i++)
00511 {
00512 if(m_streams[i].Find(s)) { return s;}
00513 }
00514 }
00515
00516 m_streams[type].Insert(s);
00517 }
00518
00519 return s;
00520 }