bool CEASpliterFilter::DemuxInit() { SVP_LogMsg5(L" CEASpliterFilter::DemuxInit"); if(!m_pFile) return(false); return(true); }
//, pInfo->strId, pInfo->strPath, szUpdfilesPath + pInfo->strTempName int cupdatenetlib::downloadFileByID(UpdateInfo* pInfo, bool UsingMd5){ CString szTmpFilename = this->svpToolBox.getTmpFileName(); CString szPostPerm; CString szTmpPath = szUpdfilesPath + pInfo->strTempName; if (UsingMd5) szPostPerm.Format(_T("setupfileid=%s&MD5=%s"), pInfo->strId, pInfo->strCurrentMD5); else szPostPerm.Format(_T("setupfileid=%s"), pInfo->strId); int rret = 0; if (PostUsingCurl(szPostPerm, szTmpFilename, my_progress_func)){ ////check MD5 of the downloaded file... //we should do the check here, but now fro one given file we can have 2 kind of downloads, //thus the MD5 is not determined. SO we just check the result file. //if (IsMd5Match(szTmpFilename, pInfo->strDownloadfileMD5)) //{ if (IsFileGziped(szTmpFilename)) svpToolBox.unpackGZfile( szTmpFilename, szTmpPath ); else bool b = ApplyEnsemblePatch(szBasePath + pInfo->strPath, szTmpFilename, szTmpPath); //check the MD5 of the result file... rret = IsMd5Match(szTmpPath, pInfo->strFileMd5); SVP_LogMsg5(L"Md5 %d %s %s", rret, szTmpPath, pInfo->strFileMd5); pInfo->bReadyToCopy = rret; //} } DeleteFile(szTmpFilename); return rret; }
HRESULT CStreamSwitcherOutputPin::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties) { CStreamSwitcherInputPin* pIn = ((CStreamSwitcherFilter*)m_pFilter)->GetInputPin(); if(!pIn || !pIn->IsConnected()) { SVP_LogMsg5(L"DecideBufferSize if(!pIn || !pIn->IsConnected()) {"); return E_UNEXPECTED; } CComPtr<IMemAllocator> pAllocatorIn; pIn->GetAllocator(&pAllocatorIn); if(!pAllocatorIn){ SVP_LogMsg5(L"DecideBufferSize pIn->GetAllocator(&pAllocatorIn);"); return E_UNEXPECTED; } HRESULT hr; if(FAILED(hr = pAllocatorIn->GetProperties(pProperties))) { SVP_LogMsg5(L"DecideBufferSize if(FAILED(hr = pAllocatorIn->GetProperties(pProperties))) {"); return hr; } if( pIn->CurrentMediaType().majortype == MEDIATYPE_Audio){ if(pProperties->cBuffers < 8) pProperties->cBuffers = 8; WAVEFORMATEX* wfe = (WAVEFORMATEX*)pIn->CurrentMediaType().pbFormat; pProperties->cbBuffer = (long) ((__int64) pProperties->cbBuffer * 8 / min( wfe->nChannels ,8 ) * 96000 / min( wfe->nSamplesPerSec, 96000)); } ALLOCATOR_PROPERTIES Actual; if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) { SVP_LogMsg5(L"DecideBufferSize if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) {"); return hr; } hr = (pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer ? E_FAIL : NOERROR); SVP_LogMsg5(L"DecideBufferSize %d %d %d %d %x",pProperties->cBuffers ,Actual.cBuffers , pProperties->cbBuffer , Actual.cbBuffer , hr ); return hr; }
bool CEASpliterFilter::DemuxLoop() { SVP_LogMsg5(L" CEASpliterFilter::DemuxLoop"); HRESULT hr = S_OK; ea_read_packet(); return(true); }
void CEASpliterFilter::DemuxSeek(REFERENCE_TIME rt) { SVP_LogMsg5(L" CEASpliterFilter::DemuxSeek"); if(rt <= 0 ) { m_pFile->Seek(0); } }
HRESULT CROStream::Read( void *pv, ULONG cb, ULONG *pcbRead ) { SVP_LogMsg5(L" CROStream::Read %f %d", double(m_pos), cb); if(!m_pAsyncReader) return E_FAIL; UINT readed = cb; HRESULT hr = m_pAsyncReader->SyncRead(m_pos, cb, (BYTE*)pv); if( FAILED(hr) ) { SVP_LogMsg5(L"CROStream::Read Filed %x", hr); return( HRESULT_FROM_WIN32( GetLastError() ) ); } m_pos+= cb; *pcbRead =readed; SVP_LogMsg5(L" CROStream::Read End "); return( S_OK ); }
BOOL CSVPNet::CheckUpdaterExe(CString szFileVerHash, CString szPath){ FILE* stream_updater_exe; CString szTmpFilename = this->svpToolBox.getTmpFileName(); if ( _wfopen_s( &stream_updater_exe, szTmpFilename, _T("wb") ) != 0){ return 0; //input file open error } CURL *curl; CURLcode res; CString szPostPerm; szPostPerm.Format(_T( "branch=updater%s¤t=%s" ), BRANCHVER, szFileVerHash); int rret = 0; curl = curl_easy_init(); if(curl) { long respcode; this->SetCURLopt(curl); curl_easy_setopt(curl, CURLOPT_URL, GetUrlByType('upda' , iTryID)); int iDescLen = 0; char* szPostFields = svpToolBox.CStringToUTF8(szPostPerm, &iDescLen) ; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)szPostFields); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)stream_updater_exe); res = curl_easy_perform(curl); if(res == 0){ curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &respcode); if(respcode == 200){ //good to go rret = 1; }else{ //error SVP_LogMsg(_T("None Update Required For Updater")); } }else{ //error SVP_LogMsg5(_T("HTTP connection error %d %s ") , res, CStringW(curl_easy_strerror(res))); //TODO handle this } curl_easy_cleanup(curl); } fclose(stream_updater_exe); if (rret){ if ( this->svpToolBox.unpackGZfile( szTmpFilename , szPath) == 0 ){ SVP_LogMsg(_T("Copy Updater.exe Sucesssed")); }else{ SVP_LogMsg(_T("Copy Updater.exe Failed")); rret = 0; } } return rret; }
HRESULT CROStream::Stat( STATSTG *pstatstg, DWORD grfStatFlag ) { SVP_LogMsg5(L" CROStream::Stat "); if(!m_pAsyncReader) return E_FAIL; if( ( NULL == pstatstg ) || ( STATFLAG_NONAME != grfStatFlag ) ) { return( E_INVALIDARG ); } LONGLONG llTotal, llAvalible; m_pAsyncReader->Length(&llTotal, &llAvalible); memset( pstatstg, 0, sizeof( STATSTG ) ); pstatstg->type = STGTY_STREAM; pstatstg->cbSize.QuadPart = ( llTotal ); SVP_LogMsg5(L" CROStream::Stat "); return( S_OK ); }
bool cupdatenetlib::PostUsingCurl(CString strFields, CString strReturnFile, curl_progress_callback pCallback) { FILE* stream_file_list; if ( _wfopen_s( &stream_file_list, strReturnFile, _T("wb") ) != 0){ return false; //input file open error } CURL *curl; CURLcode res; CString szPostPerm = strFields; bool rret = false; SVP_LogMsg(strFields); curl = curl_easy_init(); if(curl) { long respcode; this->SetCURLopt(curl); curl_easy_setopt(curl, CURLOPT_URL, szUrl); //curl_easy_setopt(curl, CURLOPT_URL, "http://svplayer.shooter.cn/api/updater.php"); int iDescLen = 0; char* szPostFields = svpToolBox.CStringToUTF8(szPostPerm, &iDescLen) ; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)szPostFields); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)stream_file_list); if (pCallback) { curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, pCallback); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); } res = curl_easy_perform(curl); if (szPostFields) delete szPostFields; if(res == 0){ curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &respcode); if(respcode == 200){ //good to go rret = true; }else{ //error SVP_LogMsg(_T("None Update Required ")); } }else{ //error SVP_LogMsg5(_T("HTTP connection error %d "), res); //TODO handle this } curl_easy_cleanup(curl); } fclose(stream_file_list); return rret; }
HRESULT CROStream::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition ) { SVP_LogMsg5(L" CROStream::Seek %f %d %x",double(dlibMove.QuadPart), dwOrigin, m_pAsyncReader); if(!m_pAsyncReader) return E_FAIL; SVP_LogMsg5(L" CROStream::Seek2 %d %x", dwOrigin, plibNewPosition); switch( dwOrigin ) { case STREAM_SEEK_SET: SVP_LogMsg5(L" CROStream::Seek3"); m_pos = dlibMove.QuadPart; SVP_LogMsg5(L" CROStream::Seek4"); break; case STREAM_SEEK_CUR: m_pos += dlibMove.QuadPart; break; case STREAM_SEEK_END: m_pos = m_len + dlibMove.QuadPart; break; default: return( E_INVALIDARG ); }; SVP_LogMsg5(L" CROStream::Seek5"); //BYTE* ptrDummy; //m_pAsyncReader->SyncRead( dlibMove.QuadPart, 0, ptrDummy); //plibNewPosition->QuadPart = (m_pAsyncReader->Seek(dlibMove.QuadPart, dwMoveMethod)); if(plibNewPosition){ plibNewPosition->QuadPart = m_pos; SVP_LogMsg5(L" CROStream::Seek End %d %d", plibNewPosition->HighPart, plibNewPosition->LowPart); }else{ SVP_LogMsg5(L" CROStream::Seek6"); } return( S_OK ); }
int CSVPNet::WetherNeedUploadSub(CString fnVideoFilePath, CString szFileHash,CString fnSubHash, int iDelayMS){ CURL *curl; CURLcode res; CString szPostPerm ; szPostPerm.Format(_T( "pathinfo=%s&filehash=%s&subhash=%s&subdelay=%d" ) , fnVideoFilePath ,szFileHash , fnSubHash, iDelayMS); int rret = -1; curl = curl_easy_init(); if(curl) { long respcode; this->SetCURLopt(curl); curl_easy_setopt(curl, CURLOPT_URL, GetUrlByType('upsb', iTryID)); int iDescLen = 0; char* szPostFields = svpToolBox.CStringToUTF8(szPostPerm, &iDescLen) ; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)szPostFields); res = curl_easy_perform(curl); if(res == 0){ curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &respcode); if(respcode == 200){ //good to go // continues to upload sub rret = 1; }if(respcode == 404){ //error rret = 0; SVP_LogMsg(_T("Already Have same sub in databases")); } }else{ //error SVP_LogMsg5(_T("HTTP connection error %d %s ") , res, CStringW(curl_easy_strerror(res))); //TODO handle this } curl_easy_cleanup(curl); } return rret; }
int CSVPNet::QuerySubByVideoPathOrHash_STL(std::wstring szFilePath, std::wstring szFileHash, std::wstring szVHash, std::wstring szLang) { CURL *curl; CURLcode res; int ret = 0; std::wstring szPostPerm = L"pathinfo=" + szFilePath + L"&filehash=" + szFileHash + L"&vhash=" + szVHash + L"&lang=" + szLang + L"&shortname=" + svpToolBox.GetShortFileNameForSearch_STL(szFilePath); struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; curl_global_init(CURL_GLOBAL_ALL); char* szTerm2; char* szTerm3; int iDescLen = 0; szTerm2 = svpToolBox.CStringToUTF8(szFilePath.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "pathinfo", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); szTerm3 = svpToolBox.CStringToUTF8(szFileHash.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filehash", CURLFORM_COPYCONTENTS, szTerm3,CURLFORM_END); szVHash = genVHash(szTerm2, szTerm3, uniqueIDHash); free(szTerm2); free(szTerm3); if (!szVHash.empty()) { szTerm2 = svpToolBox.CStringToUTF8(szVHash.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "vhash", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); } AppSettings& s = AfxGetAppSettings(); std::wstring szSVPSubPerf = (LPCTSTR)s.szSVPSubPerf; if (!szSVPSubPerf.empty()) { szTerm2 = svpToolBox.CStringToUTF8(szSVPSubPerf.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "perf", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); } if (!szLang.empty()) { szTerm2 = svpToolBox.CStringToUTF8(szLang.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "lang", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); } szTerm2 = svpToolBox.CStringToUTF8(svpToolBox.GetShortFileNameForSearch_STL(szFilePath).c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "shortname", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); FILE *stream_http_recv_buffer = svpToolBox.getTmpFileSteam(); if (!stream_http_recv_buffer) { SVP_LogMsg(_T("TmpFile Creation for http recv buff fail")); //// TODO: 1. warning!! OR switch to memfile system return -1; } int err = 0; curl = curl_easy_init(); if (curl) { long respcode; wchar_t szFailMsg[1024]; SetCURLopt(curl); curl_easy_setopt(curl, CURLOPT_URL, GetUrlByType('sapi', iTryID)); //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION , &(this->handleSubQuery)); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)stream_http_recv_buffer); //int iDescLen = 0; //char* szPostFields = svpToolBox.CStringToUTF8(szPostPerm, &iDescLen) ; //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)szPostFields); //curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, iDescLen); res = curl_easy_perform(curl); if (res == 0) { curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &respcode); //double contentlength; //curl_easy_getinfo(curl,CURLINFO_SIZE_DOWNLOAD, &contentlength); //SVP_LogMsg5(L" contentlength %f", contentlength); if (respcode == 200) { //good to go //SVP_LogMsg(_T("字幕已经找到,正在处理..."), 31); ret = 1; } else { //error SVP_LogMsg5(_T("HTTP return code is not 200 but %d") , respcode); err = 1; } } else { //error LONG l_oserr = 0; curl_easy_getinfo(curl,CURLINFO_OS_ERRNO,&l_oserr); err = 2; swprintf_s(szFailMsg, 1024, L"%s", CStringW(curl_easy_strerror(res))); //szFailMsg.Format(L"%s",CStringW(curl_easy_strerror(res))); if(!lstrcmp(szFailMsg, L"Couldn't connect to server")); lstrcat(szFailMsg, ResStr(IDS_LOG_MSG_SVPSUB_PLEASE_CHECK_FIREWALL)); SVP_LogMsg5(_T("HTTP connection error %s %d"), szFailMsg, l_oserr); //TODO handle this } /* always cleanup */ curl_easy_cleanup(curl); //free(szPostFields); //if not error, process data if (ret) { int extErr = ExtractDataFromAiSubRecvBuffer_STL(szFilePath, stream_http_recv_buffer); if (extErr && extErr != -2) { // -2 if there is none match subtile SVP_LogMsg(_T("Error On Extract DataFromAiSubRecvBuffer ")); //TODO handle this err = 3; } } else { wchar_t szMsg[1024]; swprintf_s(szMsg, 1024, ResStr(IDS_LOG_MSG_SVPSUB_NETWORK_FAIL), szFailMsg); SVP_LogMsg(szMsg);//,31 m_lastFailedMsg = szMsg; err = 4; } /* if (this->mainBufferSize > 0){ char statCode = this->mainBuffer[0]; if(statCode <= 0){ //error handle }else{ //handSubFiles } } if (this->mainBuffer){ free(this->mainBuffer); }*/ } //this->mainBuffer = NULL; //this->mainBufferSize = 0; fclose(stream_http_recv_buffer); return err; }
int CSVPNet::UploadSubFileByVideoAndHash(std::wstring fnVideoFilePath, std::wstring szFileHash, std::wstring szSubHash, std::vector<std::wstring>* fnSubPaths, int iDelayMS, std::vector<std::wstring>* szaPostTerms) { CURL *curl; CURLcode res; //CString szPostPerm = _T( "pathinfo=" ) + fnVideoFilePath + _T("&filehash=") + szFileHash ; int iTotalFiles = fnSubPaths -> size(); SVP_LogMsg(_T("Upload Begin")); struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; char errorbuf[CURL_ERROR_SIZE]; curl_global_init(CURL_GLOBAL_ALL); char* szTerm2; char* szTerm3; int iDescLen = 0; szTerm2 = svpToolBox.CStringToUTF8(fnVideoFilePath.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "pathinfo", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); szTerm2 = svpToolBox.CStringToUTF8(szSubHash.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "subhash", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); szTerm3 = svpToolBox.CStringToUTF8(szFileHash.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filehash", CURLFORM_COPYCONTENTS, szTerm3,CURLFORM_END); free(szTerm3); std::wstring szVHash = (LPCTSTR)genVHash(szTerm2, szTerm3, uniqueIDHash); if (!szVHash.empty()) { szTerm2 = svpToolBox.CStringToUTF8(szVHash.c_str(), &iDescLen); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "vhash", CURLFORM_COPYCONTENTS, szTerm2,CURLFORM_END); free(szTerm2); } szTerm2 = (char*)malloc(64); _itoa_s(iDelayMS , szTerm2, 64, 10); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "subdelay", CURLFORM_COPYCONTENTS, szTerm2, CURLFORM_END); free(szTerm2); for (int i = 0; i < fnSubPaths -> size(); i++) { char szFname[22]; /* Fill in the file upload field */ std::wstring szgzFile = svpToolBox.getSameTmpName(fnSubPaths -> at(i).c_str()) ; SVP_LogMsg(_T("Gziping ") + CString(fnSubPaths -> at(i).c_str()) + _T(" to ") + szgzFile.c_str()); svpToolBox.packGZfile(fnSubPaths -> at(i).c_str(), szgzFile.c_str()); szTerm2 = svpToolBox.CStringToUTF8(szgzFile.c_str(), &iDescLen, CP_ACP); //SVP_LogMsg(fnSubPaths->GetAt(i)); sprintf_s(szFname, 22, "subfile[%d]", i); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, szFname, CURLFORM_FILE, szTerm2,CURLFORM_END); free(szTerm2); } int retx = -1; curl = curl_easy_init(); if (curl) { long respcode; SetCURLopt(curl); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuf ); curl_easy_setopt(curl, CURLOPT_URL, GetUrlByType('upsb',iTryID)); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); res = curl_easy_perform(curl); if (res == 0) { curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &respcode); if (respcode == 200) { //good to go // continues to upload sub retx = 0; SVP_LogMsg(ResStr(IDS_LOG_MSG_SVPSUB_UPLOAD_FINISHED), 31); } else if (respcode == 404) { //error retx = 0; SVP_LogMsg(_T("Already Have same sub in databases")); } } else //error SVP_LogMsg5(_T("HTTP connection error %d %s ") , res, CStringW(curl_easy_strerror(res))); //TODO handle this curl_easy_cleanup(curl); } /* then cleanup the formpost chain */ curl_formfree(formpost); return retx; }
HRESULT CMpegSplitterFile::Init() { HRESULT hr; SVP_LogMsg5(L"HRESULT CMpegSplitterFile::Init()"); // get the type first m_type = us; Seek(0); if(m_type == us) { if(BitRead(32, true) == 'TFrc') Seek(0x67c); int cnt = 0, limit = 4; for(trhdr h; cnt < limit && Read(h); cnt++) Seek(h.next); if(cnt >= limit) m_type = ts; } Seek(0); if(m_type == us) { int cnt = 0, limit = 4; for(pvahdr h; cnt < limit && Read(h); cnt++) Seek(GetPos() + h.length); if(cnt >= limit) m_type = pva; } Seek(0); if(m_type == us) { BYTE b; for(int i = 0; (i < 4 || GetPos() < 65536) && m_type == us && NextMpegStartCode(b); i++) { if(b == 0xba) { pshdr h; if(Read(h)) { m_type = ps; m_rate = int(h.bitrate/8); break; } } else if((b&0xe0) == 0xc0 // audio, 110xxxxx, mpeg1/2/3 || (b&0xf0) == 0xe0 // video, 1110xxxx, mpeg1/2 // || (b&0xbd) == 0xbd) // private stream 1, 0xbd, ac3/dts/lpcm/subpic || b == 0xbd) // private stream 1, 0xbd, ac3/dts/lpcm/subpic { peshdr h; if(Read(h, b) && BitRead(24, true) == 0x000001) { m_type = es; } } } } Seek(0); if(m_type == us) { return E_FAIL; } // min/max pts & bitrate m_rtMin = m_posMin = _I64_MAX; m_rtMax = m_posMax = 0; if(IsRandomAccess() || IsStreaming()) { if(IsStreaming()) { for(int i = 0; i < 20 || i < 50 && S_OK != HasMoreData(1024*100, 100); i++); } CAtlList<__int64> fps; for(int i = 0, j = 5; i <= j; i++) fps.AddTail(i*GetLength()/j); for(__int64 pfp = 0; fps.GetCount(); ) { __int64 fp = fps.RemoveHead(); fp = min(GetLength() - MEGABYTE/8, fp); fp = max(pfp, fp); __int64 nfp = fp + (pfp == 0 ? 5*MEGABYTE : MEGABYTE/8); if(FAILED(hr = SearchStreams(fp, nfp))) return hr; pfp = nfp; } } else { if(FAILED(hr = SearchStreams(0, MEGABYTE/8))) return hr; } if(m_posMax - m_posMin <= 0 || m_rtMax - m_rtMin <= 0) return E_FAIL; int indicated_rate = m_rate; int detected_rate = int(10000000i64 * (m_posMax - m_posMin) / (m_rtMax - m_rtMin)); // normally "detected" should always be less than "indicated", but sometimes it can be a few percent higher (+10% is allowed here) // (update: also allowing +/-50k/s) if(indicated_rate == 0 || ((float)detected_rate / indicated_rate) < 1.1 || abs(detected_rate - indicated_rate) < 50*1024) m_rate = detected_rate; else ; // TODO: in this case disable seeking, or try doing something less drastical... //#ifndef DEBUG if(m_streams[audio].GetCount() < 1 && m_type == ts){ SVP_LogMsg5(_T("ts and no audio %d %d"), m_streams[audio].GetCount(), m_streams[unknown].GetCount()); return E_FAIL; } if(m_streams[video].GetCount()) { if (!m_bIsHdmv && m_streams[subpic].GetCount()) { stream s; s.mt.majortype = MEDIATYPE_Video; s.mt.subtype = MEDIASUBTYPE_DVD_SUBPICTURE; s.mt.formattype = FORMAT_None; m_streams[subpic].Insert(s, this); } else { // Add fake stream for "No subtitle" AddHdmvPGStream (NO_SUBTITLE_PID, "---"); } }else if(m_type == ts){ SVP_LogMsg5(_T("ts and no video")); return E_FAIL; } //#endif Seek(0); SVP_LogMsg5(_T("ts %d %d %d"), m_streams[video].GetCount() , m_streams[audio].GetCount(), m_bIsHdmv); return S_OK; }
/*---------------------------------------------------------------------- | AP4_AtomFactory::CreateAtomFromStream +---------------------------------------------------------------------*/ AP4_Result AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, AP4_Size& bytes_available, AP4_Atom*& atom, AP4_Atom* parent) { AP4_Result result; // NULL by default atom = NULL; // check that there are enough bytes for at least a header if (bytes_available < 8) return AP4_ERROR_EOS; // remember current stream offset AP4_Offset start; stream.Tell(start); // read atom size AP4_UI32 size; result = stream.ReadUI32(size); if (AP4_FAILED(result)) { stream.Seek(start); return result; } if (size == 0) { // atom extends to end of file AP4_Size streamSize = 0; stream.GetSize(streamSize); if (streamSize >= start) { size = streamSize - start; } } // check the size (we don't handle extended size yet) if (size != 1 && size < 8 || size > bytes_available) { stream.Seek(start); return AP4_ERROR_INVALID_FORMAT; } // read atom type AP4_Atom::Type type; result = stream.ReadUI32(type); if (AP4_FAILED(result)) { stream.Seek(start); return result; } if (size == 1) { AP4_UI32 size_high; result = stream.ReadUI32(size_high); if (AP4_FAILED(result) ) { stream.Seek(start); return AP4_ERROR_INVALID_FORMAT; } result = stream.ReadUI32(size); if (AP4_FAILED(result)) { stream.Seek(start); return result; } if(size_high > 0) { SVP_LogMsg5(L"CreateAtomFromStream 64 bits long %x %x" ,UINT(size_high), UINT(size)); size = (((ULONGLONG)size_high) << 32) | size; } } // create the atom switch (type) { case AP4_ATOM_TYPE_MOOV: atom = DNew AP4_MoovAtom(size, stream, *this); break; case AP4_ATOM_TYPE_MVHD: atom = DNew AP4_MvhdAtom(size, stream); break; case AP4_ATOM_TYPE_TRAK: atom = DNew AP4_TrakAtom(size, stream, *this); break; case AP4_ATOM_TYPE_HDLR: atom = DNew AP4_HdlrAtom(size, stream); break; case AP4_ATOM_TYPE_DREF: atom = DNew AP4_DrefAtom(size, stream, *this); break; case AP4_ATOM_TYPE_URL: atom = DNew AP4_UrlAtom(size, stream); break; case AP4_ATOM_TYPE_TKHD: atom = DNew AP4_TkhdAtom(size, stream); break; case AP4_ATOM_TYPE_MDHD: atom = DNew AP4_MdhdAtom(size, stream); break; case AP4_ATOM_TYPE_STSD: atom = DNew AP4_StsdAtom(size, stream, *this); break; case AP4_ATOM_TYPE_STSC: atom = DNew AP4_StscAtom(size, stream); break; case AP4_ATOM_TYPE_STCO: atom = DNew AP4_StcoAtom(size, stream); break; case AP4_ATOM_TYPE_CO64: atom = DNew AP4_Co64Atom(size, stream); break; case AP4_ATOM_TYPE_STSZ: atom = DNew AP4_StszAtom(size, stream); break; case AP4_ATOM_TYPE_STTS: atom = DNew AP4_SttsAtom(size, stream); break; case AP4_ATOM_TYPE_CTTS: atom = DNew AP4_CttsAtom(size, stream); break; case AP4_ATOM_TYPE_STSS: atom = DNew AP4_StssAtom(size, stream); break; case AP4_ATOM_TYPE_MP4S: atom = DNew AP4_Mp4sSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_MP4A: atom = parent && parent->GetType() == AP4_ATOM_TYPE_STSD ? (AP4_Atom*)DNew AP4_Mp4aSampleEntry(size, stream, *this) : (AP4_Atom*)DNew AP4_UnknownAtom(type, size, false, stream); break; case AP4_ATOM_TYPE_MP4V: atom = DNew AP4_Mp4vSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_AVC1: atom = DNew AP4_Avc1SampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_ENCA: atom = DNew AP4_EncaSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_ENCV: atom = DNew AP4_EncvSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_ESDS: atom = DNew AP4_EsdsAtom(size, stream); break; case AP4_ATOM_TYPE_VMHD: atom = DNew AP4_VmhdAtom(size, stream); break; case AP4_ATOM_TYPE_SMHD: atom = DNew AP4_SmhdAtom(size, stream); break; case AP4_ATOM_TYPE_NMHD: atom = DNew AP4_NmhdAtom(size, stream); break; case AP4_ATOM_TYPE_HMHD: atom = DNew AP4_HmhdAtom(size, stream); break; case AP4_ATOM_TYPE_FRMA: atom = DNew AP4_FrmaAtom(size, stream); break; case AP4_ATOM_TYPE_SCHM: atom = DNew AP4_SchmAtom(size, stream); break; case AP4_ATOM_TYPE_FTYP: atom = DNew AP4_FtypAtom(size, stream); break; case AP4_ATOM_TYPE_RTP: if (m_Context == AP4_ATOM_TYPE_HNTI) { atom = DNew AP4_RtpAtom(size, stream); } else { atom = DNew AP4_RtpHintSampleEntry(size, stream, *this); } break; case AP4_ATOM_TYPE_TIMS: atom = DNew AP4_TimsAtom(size, stream); break; case AP4_ATOM_TYPE_SDP: atom = DNew AP4_SdpAtom(size, stream); break; case AP4_ATOM_TYPE_IKMS: atom = DNew AP4_IkmsAtom(size, stream); break; case AP4_ATOM_TYPE_ISFM: atom = DNew AP4_IsfmAtom(size, stream); break; case AP4_ATOM_TYPE_HINT: atom = DNew AP4_TrefTypeAtom(type, size, stream); break; // container atoms case AP4_ATOM_TYPE_TREF: case AP4_ATOM_TYPE_HNTI: case AP4_ATOM_TYPE_STBL: case AP4_ATOM_TYPE_MDIA: case AP4_ATOM_TYPE_DINF: case AP4_ATOM_TYPE_MINF: case AP4_ATOM_TYPE_SCHI: case AP4_ATOM_TYPE_SINF: case AP4_ATOM_TYPE_UDTA: case AP4_ATOM_TYPE_ILST: case AP4_ATOM_TYPE_NAM: case AP4_ATOM_TYPE_ART: case AP4_ATOM_TYPE_WRT: case AP4_ATOM_TYPE_ALB: case AP4_ATOM_TYPE_DAY: case AP4_ATOM_TYPE_TOO: case AP4_ATOM_TYPE_CMT: case AP4_ATOM_TYPE_GEN: case AP4_ATOM_TYPE_TRKN: case AP4_ATOM_TYPE_EDTS: case AP4_ATOM_TYPE_WAVE: case AP4_ATOM_TYPE_CMOV: { AP4_UI32 context = m_Context; m_Context = type; // set the context for the children atom = DNew AP4_ContainerAtom(type, size, false, stream, *this); m_Context = context; // restore the previous context break; } // full container atoms case AP4_ATOM_TYPE_META: atom = DNew AP4_ContainerAtom(type, size, true, stream, *this); break; // other case AP4_ATOM_TYPE_AVCC: atom = DNew AP4_AvcCAtom(size, stream); break; case AP4_ATOM_TYPE_TEXT: atom = DNew AP4_TextSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_TX3G: atom = DNew AP4_Tx3gSampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_FTAB: atom = DNew AP4_FtabAtom(size, stream); break; case AP4_ATOM_TYPE_CVID: case AP4_ATOM_TYPE_SVQ1: case AP4_ATOM_TYPE_SVQ2: case AP4_ATOM_TYPE_SVQ3: case AP4_ATOM_TYPE_H263: case AP4_ATOM_TYPE_S263: case AP4_ATOM_TYPE_JPEG: case AP4_ATOM_TYPE_RLE: case AP4_ATOM_TYPE_MJPA: atom = DNew AP4_VisualSampleEntry(type, size, stream, *this); break; case AP4_ATOM_TYPE_SAMR: case AP4_ATOM_TYPE__MP3: case AP4_ATOM_TYPE_IMA4: case AP4_ATOM_TYPE_QDMC: case AP4_ATOM_TYPE_QDM2: case AP4_ATOM_TYPE_TWOS: case AP4_ATOM_TYPE_SOWT: case AP4_ATOM_TYPE_RAW: case AP4_ATOM_TYPE_ULAW: atom = DNew AP4_AudioSampleEntry(type, size, stream, *this); break; case AP4_ATOM_TYPE__AC3: // AC3-in-MP4 from ISO Standard case AP4_ATOM_TYPE_SAC3: // AC3-in-MP4 from Nero Stuff >.< atom = DNew AP4_AC3SampleEntry(size, stream, *this); break; case AP4_ATOM_TYPE_CHPL: atom = DNew AP4_ChplAtom(size, stream); break; case AP4_ATOM_TYPE_DATA: atom = DNew AP4_DataAtom(size, stream); break; case AP4_ATOM_TYPE_DCOM: atom = DNew AP4_DcomAtom(size, stream); break; case AP4_ATOM_TYPE_CMVD: atom = DNew AP4_CmvdAtom(size, stream, *this); break; default: if(parent && parent->GetType() == AP4_ATOM_TYPE_STSD && (type & 0xffff0000) == AP4_ATOM_TYPE('m', 's', 0, 0)) { atom = DNew AP4_AudioSampleEntry(type, size, stream, *this); } else // try all the external type handlers { atom = NULL; AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem(); while (handler_item) { TypeHandler* handler = handler_item->GetData(); if (AP4_SUCCEEDED(handler->CreateAtom(type, size, stream, atom))) { break; } handler_item = handler_item->GetNext(); } if (atom == NULL) { // no custom handlers, create a generic atom //SVP_LogMsg5(L"MP4 XXX type %x", type); atom = DNew AP4_UnknownAtom(type, size, false, stream); } } break; } // skip to the end of the atom bytes_available -= size; result = stream.Seek(start+size); if (AP4_FAILED(result)) { delete atom; atom = NULL; } return result; }
HRESULT CEASpliterFilter::CreateOutputs(IAsyncReader* pAsyncReader) { SVP_LogMsg5(L" CEASpliterFilter::CreateOutputs"); CheckPointer(pAsyncReader, E_POINTER); HRESULT hr = E_FAIL; m_pFile.Free(); m_pFile.Attach(new CEAFile(pAsyncReader, hr)); if(!m_pFile) return E_OUTOFMEMORY; if(FAILED(hr)) {m_pFile.Free(); return hr;} m_rtNewStart = m_rtCurrent = 0; m_rtNewStop = m_rtStop = m_rtDuration = 0; m_pFile->Seek(0); DWORD EAFileTag = bswap_32((DWORD)m_pFile->BitRead(32)); switch(EAFileTag) { case ISNh_TAG: case SCHl_TAG: case SEAD_TAG: case SHEN_TAG: case kVGT_TAG: case MADk_TAG: case MPCh_TAG: case MVhd_TAG: case MVIh_TAG: SVP_LogMsg5(L"GotEA Tag"); break; default: return hr; } m_pFile->Seek(0); EaDemuxContext *ea = (EaDemuxContext *)m_pea; SVP_LogMsg5(L"EABefore Info %x %x", ea->audio_codec, ea->video_codec);; process_header(); SVP_LogMsg5(L"GotEA Info %d %d", ea->audio_codec, ea->video_codec);; int idPin = 0; while(ea->video_codec){ CMediaType mt; mt.SetSampleSize(1); mt.subtype = GUID_NULL; switch(ea->video_codec){ case CODEC_ID_VP6: { mt.majortype = MEDIATYPE_Video; mt.formattype = FORMAT_VideoInfo; VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER)); memset(vih, 0, sizeof(VIDEOINFOHEADER)); BITMAPINFOHEADER* bih = &vih->bmiHeader; vih->bmiHeader.biWidth = ea->width; vih->bmiHeader.biHeight = ea->height; bih->biCompression = '26PV'; mt.subtype = MEDIASUBTYPE_VP62; } break; case CODEC_ID_MPEG2VIDEO: //TODO: handle MPEG2 in vp6 /*mt.formattype = FORMAT_MPEG2Video; MPEG2VIDEOINFO* vih = (MPEG2VIDEOINFO*)mt.AllocFormatBuffer(FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + headerSize); memset(vih, 0, mt.FormatLength()); vih->hdr.bmiHeader.biSize = sizeof(vih->hdr.bmiHeader); vih->hdr.bmiHeader.biPlanes = 1; vih->hdr.bmiHeader.biBitCount = 24; vih->hdr.bmiHeader.biWidth = ea->width; vih->hdr.bmiHeader.biHeight = ea->height; */ case CODEC_ID_MDEC: case CODEC_ID_CMV: case CODEC_ID_TGV: case CODEC_ID_TGQ: case CODEC_ID_TQI: case CODEC_ID_MAD: SVP_LogMsg5(L"sorry we cant handle this now"); break; } if(mt.subtype == GUID_NULL) break; CAtlArray<CMediaType> mts; mts.Add(mt); CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Video", this, this, &hr)); EXECUTE_ASSERT(SUCCEEDED(AddOutputPin(idPin, pPinOut))); idPin++; break; } if(ea->audio_codec){ CMediaType mt; mt.SetSampleSize(1); mt.majortype = MEDIATYPE_Audio; mt.formattype = FORMAT_WaveFormatEx; switch(ea->audio_codec){ case CODEC_ID_MP3: mt.subtype = MEDIASUBTYPE_MP3; { WAVEFORMATEX* wfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX)); memset(wfe, 0, sizeof(WAVEFORMATEX)); wfe->nSamplesPerSec = ea->sample_rate; wfe->wBitsPerSample = ea->bytes * 8; wfe->nChannels = ea->num_channels; } break; case CODEC_ID_ADPCM_EA: case CODEC_ID_ADPCM_EA_R1: case CODEC_ID_ADPCM_EA_R2: case CODEC_ID_ADPCM_EA_R3: case CODEC_ID_PCM_S16LE_PLANAR: case CODEC_ID_PCM_S8: case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_MULAW: case CODEC_ID_ADPCM_IMA_EA_EACS: case CODEC_ID_ADPCM_IMA_EA_SEAD: break; } if(mt.subtype != GUID_NULL){ CAtlArray<CMediaType> mts; mts.Add(mt); CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Audio", this, this, &hr)); EXECUTE_ASSERT(SUCCEEDED(AddOutputPin(idPin, pPinOut))); } } SVP_LogMsg5(L"EA Out %d", m_pOutputs.GetCount()); m_rtNewStop = m_rtStop = m_rtDuration ; return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL; }