//=========================================================================== // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved. // //=========================================================================== // // filename: ctimecod.cpp // // SMPTE Timecode support class // //--------------------------------------------------------- // // This code is provided for reference purposes only // // NOTES: // 1. Code is un-optimized for clarity // 2. Minimal error checking. // 3. Negative t/c values not supported // 4. File logging functions are here for illustrative // purposes but not used. // //--------------------------------------------------------- #include #include #include #include #include #include #include "ctimecod.h" // timecode conversion tables #define TC_LENGTH 11*sizeof(TCHAR) // length of a t/c string static long m_lNDFTable[] = {1080000L,108000L,18000L,1800L,300L,30L,10L,1L}; static long m_lDFTable[] = {1078920L,107892L,17982L,1798L,300L,30L,10L,1L}; static long m_l25Table[] = {900000L,90000L,15000L,1500L,250L,25L,10L,1L}; static long m_l24Table[] = {864000L,86400L,14400L,1440L,240L,24L,10L,1L}; //--------------------------------------------------------- // // ConvertStringToTimecode // // Timecode sample passed in contains desired framerate for conversion // //--------------------------------------------------------- DWORD CTimecode::ConvertStringToTimecode(TCHAR *lpszTimecode, PTIMECODE_SAMPLE pTimecodeSample) { int i, j; long *table; TCHAR temp; // select conversion table switch (pTimecodeSample->timecode.wFrameRate) { case AM_TIMECODE_30DROP: table = m_lDFTable; break; case AM_TIMECODE_30NONDROP: table = m_lNDFTable; break; case AM_TIMECODE_25: table = m_l25Table; break; case AM_TIMECODE_24: table = m_l24Table; break; default: table = m_lNDFTable; } pTimecodeSample->timecode.dwFrames = 0L; j = 0; for ( i = 0; lpszTimecode[i]!= 0; i++ ) { if ( (lpszTimecode[i] > '9') || (lpszTimecode[i] < '0') ) continue; temp = (lpszTimecode[i] - '0'); pTimecodeSample->timecode.dwFrames += (DWORD)temp * table[j]; j++; } return 0L; } //--------------------------------------------------------- // // ConvertTimecodeToString // //--------------------------------------------------------- DWORD CTimecode::ConvertTimecodeToString(PTIMECODE_SAMPLE pTimecodeSample, TCHAR *lpszTimecode) { int i, j, temp; long timecode; long *table; WORD wFCM; int flag = 0; // make local copies wFCM = pTimecodeSample->timecode.wFrameRate; timecode = pTimecodeSample->timecode.dwFrames; // select conversion table switch (wFCM) { case AM_TIMECODE_30DROP: table = m_lDFTable; break; case AM_TIMECODE_30NONDROP: table = m_lNDFTable; break; case AM_TIMECODE_25: table = m_l25Table; break; case AM_TIMECODE_24: table = m_l24Table; break; default: table = m_lNDFTable; } for ( i=0, j=0; j<(TC_LENGTH); i++, j++ ) { temp = (int)( timecode / table[i]); lpszTimecode[j] = temp + '0'; // ASCII conversion timecode -= temp * table[i]; // if minutesx10, do the drop frame test if ( i == 2 ) { if ( timecode < 2) flag = 1; // this means we are on a 10 minute // boundary and 2 frames should be // added later else timecode-=2L; } if ( i == 3 ) { // this is where the 2 frames get added in if ( !flag ) timecode+=2L; } // add punctuation if ( 1 == j || 4 == j || 7 == j ) { j++; if ( 8 == j && wFCM == AM_TIMECODE_30DROP ) lpszTimecode[j] = ';'; else lpszTimecode[j] = ':'; } } lpszTimecode[j] = 0; // null terminate return 0L; } // eof ctimecod.c