HRESULT CHdmvClipInfo::FindMainMovie(LPCTSTR strFolder, CString& strPlaylistFile, CPlaylist& MainPlaylist, CPlaylist& MPLSPlaylists) { HRESULT hr = E_FAIL; CString strPath(strFolder); MainPlaylist.RemoveAll(); MPLSPlaylists.RemoveAll(); CPlaylist Playlist; CPlaylist PlaylistArray[1024]; int idx = 0; WIN32_FIND_DATA fd = {0}; HANDLE hFind = FindFirstFile(strPath + L"\\PLAYLIST\\*.mpls", &fd); if (hFind != INVALID_HANDLE_VALUE) { REFERENCE_TIME rtMax = 0; REFERENCE_TIME rtCurrent; CString strCurrentPlaylist; do { strCurrentPlaylist = strPath + L"\\PLAYLIST\\" + fd.cFileName; Playlist.RemoveAll(); // Main movie shouldn't have duplicate M2TS filename ... if (ReadPlaylist(strCurrentPlaylist, rtCurrent, Playlist) == S_OK) { if (rtCurrent > rtMax) { rtMax = rtCurrent; strPlaylistFile = strCurrentPlaylist; MainPlaylist.RemoveAll(); POSITION pos = Playlist.GetHeadPosition(); while (pos) { CAutoPtr<PlaylistItem> Item(DNew PlaylistItem(*Playlist.GetNext(pos))); MainPlaylist.AddTail(Item); } hr = S_OK; } if (rtCurrent >= (REFERENCE_TIME)MIN_LIMIT*600000000) { // Search duplicate playlists ... bool dublicate = false; for (int i = 0; i < idx; i++) { CPlaylist* pl = &PlaylistArray[i]; if (pl->GetCount() != Playlist.GetCount()) { continue; } POSITION pos1 = Playlist.GetHeadPosition(); POSITION pos2 = pl->GetHeadPosition(); dublicate = true; while (pos1 && pos2) { PlaylistItem* pli_1 = Playlist.GetNext(pos1); PlaylistItem* pli_2 = pl->GetNext(pos2); if (*pli_1 == *pli_2) { continue; } dublicate = false; break; } if (dublicate) { break; } } if (dublicate) { continue; } CAutoPtr<PlaylistItem> Item(DNew PlaylistItem); Item->m_strFileName = strCurrentPlaylist; Item->m_rtIn = 0; Item->m_rtOut = rtCurrent; MPLSPlaylists.AddTail(Item); POSITION pos = Playlist.GetHeadPosition(); while (pos) { CAutoPtr<PlaylistItem> Item(DNew PlaylistItem(*Playlist.GetNext(pos))); PlaylistArray[idx].AddTail(Item); } idx++; } } } while (FindNextFile(hFind, &fd)); FindClose(hFind); } if (MPLSPlaylists.GetCount() > 1) { // bubble sort for (size_t j = 0; j < MPLSPlaylists.GetCount(); j++) { for (size_t i = 0; i < MPLSPlaylists.GetCount()-1; i++) { if (MPLSPlaylists.GetAt(MPLSPlaylists.FindIndex(i))->Duration() < MPLSPlaylists.GetAt(MPLSPlaylists.FindIndex(i+1))->Duration()) { MPLSPlaylists.SwapElements(MPLSPlaylists.FindIndex(i), MPLSPlaylists.FindIndex(i+1)); } } } } return hr; }
HRESULT CHdmvClipInfo::ReadChapters(CString strPlaylistFile, CPlaylist& PlaylistItems, CPlaylistChapter& Chapters) { BYTE Buff[4]; CPath Path(strPlaylistFile); // Get BDMV folder Path.RemoveFileSpec(); Path.RemoveFileSpec(); m_hFile = CreateFile(strPlaylistFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (m_hFile != INVALID_HANDLE_VALUE) { REFERENCE_TIME* rtOffset = DNew REFERENCE_TIME[PlaylistItems.GetCount()]; REFERENCE_TIME rtSum = 0; USHORT nIndex = 0; POSITION pos = PlaylistItems.GetHeadPosition(); while (pos) { CHdmvClipInfo::PlaylistItem* PI = PlaylistItems.GetNext(pos); rtOffset[nIndex] = rtSum - PI->m_rtIn; rtSum = rtSum + PI->Duration(); nIndex++; } ReadBuffer(Buff, 4); if (memcmp(Buff, "MPLS", 4)) { SAFE_DELETE_ARRAY(rtOffset); return CloseFile(VFW_E_INVALID_FILE_FORMAT); } ReadBuffer(Buff, 4); if ((memcmp(Buff, "0200", 4)!=0) && (memcmp(Buff, "0100", 4)!=0)) { SAFE_DELETE_ARRAY(rtOffset); return CloseFile(VFW_E_INVALID_FILE_FORMAT); } LARGE_INTEGER Pos = {0, 0}; USHORT nMarkCount; ReadDword(); // PlayList_start_address Pos.QuadPart = ReadDword(); // PlayListMark_start_address // PlayListMark() SetFilePointerEx(m_hFile, Pos, NULL, FILE_BEGIN); ReadDword(); // length nMarkCount = ReadShort(); // number_of_PlayList_marks for (size_t i = 0; i < nMarkCount; i++) { PlaylistChapter Chapter; ReadByte(); // reserved_for_future_use Chapter.m_nMarkType = (PlaylistMarkType)ReadByte(); // mark_type Chapter.m_nPlayItemId = ReadShort(); // ref_to_PlayItem_id Chapter.m_rtTimestamp = REFERENCE_TIME(20000.0f*ReadDword()/90) + rtOffset[Chapter.m_nPlayItemId]; // mark_time_stamp Chapter.m_nEntryPID = ReadShort(); // entry_ES_PID Chapter.m_rtDuration = REFERENCE_TIME(20000.0f*ReadDword()/90); // duration if (Chapter.m_rtTimestamp < 0 || Chapter.m_rtTimestamp > rtSum) { continue; } Chapters.AddTail (Chapter); } CloseFile(S_OK); SAFE_DELETE_ARRAY(rtOffset); return S_OK; } return AmHresultFromWin32(GetLastError()); }