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::ReadPlaylist(CString strPlaylistFile, REFERENCE_TIME& rtDuration, CPlaylist& Playlist, BOOL bFullInfoRead) { BYTE Buff[5]; CPath Path (strPlaylistFile); bool bDuplicate = false; rtDuration = 0; // 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) { DbgLog((LOG_TRACE, 3, _T("CHdmvClipInfo::ReadPlaylist() : %s"), strPlaylistFile)); ReadBuffer(Buff, 4); if (memcmp(Buff, "MPLS", 4)) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } ReadBuffer(Buff, 4); if ((memcmp(Buff, "0200", 4)) && (memcmp(Buff, "0100", 4))) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } LARGE_INTEGER Pos = {0, 0}; DWORD dwTemp; USHORT nPlaylistItems; Pos.QuadPart = ReadDword(); // PlayList_start_address ReadDword(); // PlayListMark_start_address // PlayList() SetFilePointerEx(m_hFile, Pos, NULL, FILE_BEGIN); ReadDword(); // length ReadShort(); // reserved_for_future_use nPlaylistItems = ReadShort(); // number_of_PlayItems ReadShort(); // number_of_SubPaths Pos.QuadPart += 10; __int64 TotalSize = 0; for (size_t i = 0; i < nPlaylistItems; i++) { CAutoPtr<PlaylistItem> Item(DNew PlaylistItem); SetFilePointerEx(m_hFile, Pos, NULL, FILE_BEGIN); Pos.QuadPart += ReadShort() + 2; ReadBuffer(Buff, 5); Item->m_strFileName.Format(_T("%s\\STREAM\\%c%c%c%c%c.M2TS"), CString(Path), Buff[0], Buff[1], Buff[2], Buff[3], Buff[4]); ReadBuffer(Buff, 4); if (memcmp(Buff, "M2TS", 4)) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } if (!::PathFileExists(Item->m_strFileName)) { DbgLog((LOG_TRACE, 3, _T(" ==> %s is missing, skip it"), Item->m_strFileName)); continue; } ReadBuffer(Buff, 3); dwTemp = ReadDword(); Item->m_rtIn = REFERENCE_TIME(20000.0f*dwTemp/90); dwTemp = ReadDword(); Item->m_rtOut = REFERENCE_TIME(20000.0f*dwTemp/90); Item->m_rtStartTime = rtDuration; rtDuration += (Item->m_rtOut - Item->m_rtIn); if (bFullInfoRead) { LARGE_INTEGER size = {0, 0}; HANDLE hFile = CreateFile(Item->m_strFileName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile != INVALID_HANDLE_VALUE) { GetFileSizeEx(hFile, &size); CloseHandle(hFile); } Item->m_SizeIn = TotalSize; TotalSize += size.QuadPart; Item->m_SizeOut = TotalSize; } POSITION pos = Playlist.GetHeadPosition(); while (pos) { PlaylistItem* pItem = Playlist.GetNext(pos); if (*pItem == *Item) { bDuplicate = true; break; } } DbgLog((LOG_TRACE, 3, _T(" ==> %s, Duration : %s [%15I64d], Total duration : %s, Size : %I64d"), Item->m_strFileName, ReftimeToString(Item->Duration()), Item->Duration(), ReftimeToString(rtDuration), Item->Size())); Playlist.AddTail(Item); } CloseFile(S_OK); if (bFullInfoRead) { POSITION pos = Playlist.GetHeadPosition(); while (pos) { PlaylistItem* pItem = Playlist.GetNext(pos); CString fname = pItem->m_strFileName; fname.Replace(L"\\STREAM\\", L"\\CLIPINF\\"); fname.Replace(L".M2TS", L".CLPI"); ReadInfo(fname, &pItem->m_sps); } } return Playlist.IsEmpty() ? E_FAIL : bDuplicate ? S_FALSE : S_OK; } return AmHresultFromWin32(GetLastError()); }