locked
Anybody familiar with ATSC GPS Seconds? RRS feed

  • Question

  • Hi there,

    I want to parse the STT and EIT tables of ATSC transport streams, but i don't know how to convert the system_time(in STT) and start_time(in EIT) fields (GPS Seconds) to time format!
    Can anybody help me? Thanks in advance!
    Friday, April 24, 2009 3:02 AM

All replies

  • system_time_table_section() {
    table_id 8 0xCD
    section_syntax_indicator 1 ‘1’
    private_indicator 1 ‘1’
    reserved 2 ‘11’
    section_length 12 uimsbf
    table_id_extension 16 0x0000
    reserved 2 ‘11’
    version_number 5 ‘00000’
    current_next_indicator 1 ‘1’
    section_number 8 0x00
    last_section_number 8 0x00
    protocol_version 8 uimsbf
    system_time 32 uimsbf
    GPS_UTC_offset 8 uimsbf
    daylight_savings 16 uimsbf
    for (i=0; i<N;i++) {
    descriptor()
    }
    CRC_32 32 rpchof
    }
    uchar uOffsetSeconds;
    
    void siParseSTT(u_char *pSTT)
    {	
    	u_int system_time;	
    	BYTE *p = (BYTE*)&system_time;
    	memcpy((void*)(p+3), pSTT+9, 1);
    	memcpy((void*)(p+2), pSTT+10, 1);
    	memcpy((void*)(p+1), pSTT+11, 1);
    	memcpy((void*)p, pSTT+12, 1);	
    
    	CTime t(1980, 01, 06, 0, 0, 0);
    	time_t osBinaryTime = t.GetTime();  
    	system_time += osBinaryTime;
    	CTime time(system_time);	
    
    	int nYear, nMonth, nDate, nHour, nMinute, nSecond;
    	nYear = time.GetYear();
    	nMonth = time.GetMonth();
    	nDate = time.GetDay();
    	nHour = time.GetHour();
    	nMinute = time.GetMinute();
    	nSecond = time.GetSecond();
    	
    	BYTE GPS_UTC_offset;
    	memcpy((void*)&GPS_UTC_offset, pSTT+13, 1);
    	uOffsetSeconds = GPS_UTC_offset;
    	WORD daylight_savings;
    	memcpy((void*)&daylight_savings, pSTT+14, 2);
    }













    Friday, April 24, 2009 6:09 AM
  • event_information_table_section() {
    table_id 8 0xCB
    section_syntax_indicator 1 ‘1’
    private_indicator 1 ‘1’
    reserved 2 ‘11’
    section_length 12 uimsbf
    source_id 16 uimsbf
    reserved 2 ’11’
    version_number 5 uimsbf
    current_next_indicator 1 ‘1’
    section_number 8 uimsbf
    last_section_number 8 uimsbf
    protocol_version 8 uimsbf
    num_events_in_section 8 uimsbf
    for (j=0; j< num_events_in_section; j++) {
    reserved 2 ‘11’
    event_id 14 uimsbf
    start_time 32 uimsbf
    reserved 2 ‘11’
    ETM_location 2 uimsbf
    length_in_seconds 20 uimsbf
    title_length 8 uimsbf
    title_text() var
    reserved 4 ‘1111’
    descriptors_length 12
    for (i=0; i<N; i++) {
    descriptor()
    }
    }
    CRC_32 32 rpchof
    }


    #define swap(a) a=(unsigned int)a >> 8 | a << 8
    void siParseEIT(u_char *pEIT)
    {
     WORD source_id;
     memcpy((void*)&source_id, pEIT+3, sizeof(WORD));
     BYTE num_events_in_section;
     memcpy((void*)&num_events_in_section, pEIT+9, sizeof(WORD));
     BYTE *p = (BYTE*)(pEIT+10);
     for (int i=0; i<num_events_in_section; ++i)
     {
      u_int start_time;  
      BYTE *q = (BYTE*)&start_time;
      memcpy((void*)(q+3), p+2, 1);
      memcpy((void*)(q+2), p+3, 1);
      memcpy((void*)(q+1), p+4, 1);
      memcpy((void*)q, p+5, 1);

      CTime t(1980, 01, 06, 0, 0, 0);
      time_t osBinaryTime = t.GetTime(); 
      start_time += osBinaryTime;
      start_time -= uOffsetSeconds;
      CTime time(start_time);

      int nYear, nMonth, nDate, nHour, nMinute, nSecond;
      nYear = time.GetYear();
      nMonth = time.GetMonth();
      nDate = time.GetDay();
      nHour = time.GetHour();
      nMinute = time.GetMinute();
      nSecond = time.GetSecond();
      nHour -= 8;
      
      int length_in_seconds = 0;
      q = (BYTE*)&length_in_seconds;
      memcpy((void*)(q+2), p+6, 1);
      memcpy((void*)(q+1), p+7, 1);
      memcpy((void*)q, p+8, 1);
      length_in_seconds = length_in_seconds << 12;
      length_in_seconds = length_in_seconds >> 12;
      int nHours, nMinutes;
      nHours = length_in_seconds / 3600;
      nMinutes = (length_in_seconds % 3600) / 60;

      BYTE title_length;
      memcpy((void*)&title_length, p+9+8, 1);
      char title_text[256] = "";
      memcpy((void*)title_text, p+10+8, title_length);
      WORD descriptors_length;
      memcpy((void*)&descriptors_length, p+10+title_length+8, 2);
      swap(descriptors_length);
      descriptors_length = descriptors_length << 4;
      descriptors_length = descriptors_length >> 4;
      p += 12 +title_length +descriptors_length+8;
     }
    }

    • Edited by MIKENJE Thursday, April 30, 2009 2:50 AM
    Friday, April 24, 2009 6:17 AM
  • terrestrial_virtual_channel_table_section() {
    table_id 8 0xC8
    section_syntax_indicator 1 ‘1’
    private_indicator 1 ‘1’
    reserved 2 ‘11’
    section_length 12 uimsbf
    transport_stream_id 16 uimsbf
    reserved 2 ‘11’
    version_number 5 uimsbf
    current_next_indicator 1 bslbf
    section_number 8 uimsbf
    last_section_number 8 uimsbf
    protocol_version 8 uimsbf
    num_channels_in_section 8 uimsbf
    for (i=0; i< num_channels_in_section; i++) {
    short_name 7*16 uimsbf
    reserved 4 ‘1111’
    major_channel_number 10 uimsbf
    minor_channel_number 10 uimsbf
    modulation_mode 8 uimsbf
    carrier_frequency 32 uimsbf
    channel_TSID 16 uimsbf
    program_number 16 uimsbf
    ETM_location 2 uimsbf
    access_controlled 1 bslbf
    hidden 1 bslbf
    reserved 2 ‘11’
    hide_guide 1 bslbf
    reserved 3 ‘111’
    service_type 6 uimsbf
    source_id 16 uimsbf
    reserved 6 ‘111111’
    descriptors_length 10 uimsbf
    for (i=0; i<N; i++) {
    descriptor()
    }
    }
    reserved 6 ‘111111’
    additional_descriptors_length 10 uimsbf
    for (j=0; j<N; j++) {
    additional_descriptor()
    }
    CRC_32 32 rpchof
    }


    void siParseVCT(BYTE *pVCTSec)

        WORD transport_stream_id;
        memcpy((void*)&transport_stream_id, pVCTSec+3, sizeof(WORD)); 
       
        BYTE *p = pVCTSec+10;
        u_char num_channels_in_section = *(pVCTSec+9);
        for (int i=0; i<num_channels_in_section; ++i)
        {
            BYTE *b;         
            WORD major_channel_number;
            b = (BYTE*)&major_channel_number;
            *b = *(p+15);
            *(b+1) = *(p+14);
            major_channel_number = major_channel_number<<4;
            major_channel_number = major_channel_number>>6;
         
            WORD minor_channel_number;
            b = (BYTE*)&minor_channel_number;
            *b = *(p+16);
            *(b+1) = *(p+15);
            minor_channel_number = minor_channel_number<<6;
            minor_channel_number = minor_channel_number>>6;
           
            WORD descriptors_length;
            b = (BYTE*)&descriptors_length;
            *b = *(p+31);
            *(b+1) = *(p+30);
            descriptors_length = descriptors_length<<6;
            descriptors_length = descriptors_length>>6;
            p += 32;
            p += descriptors_length;    
        }
    }
    Friday, April 24, 2009 6:27 AM
  • void siParseMGT(u_char *Buffer, WORD arrPID[], int& nLen)

     WORD tables_defined;
     memcpy((void*)&tables_defined, (void*)(Buffer+9), sizeof(WORD));
     swap(tables_defined);
     BYTE *p = (BYTE*)(Buffer+11);
     for (int i=0; i<tables_defined; ++i)
     {
      WORD table_type_PID;
      memcpy((void*)&table_type_PID, (void*)(p+2), sizeof(WORD));
      swap(table_type_PID);
      table_type_PID = table_type_PID << 3;
      table_type_PID = table_type_PID >> 3;
      arrPID[i] = table_type_PID;  
      WORD table_type_descriptors_length;
      memcpy((void*)&table_type_descriptors_length, (void*)(p+9), sizeof(WORD));
      swap(table_type_descriptors_length);
      table_type_descriptors_length = table_type_descriptors_length << 4;
      table_type_descriptors_length = table_type_descriptors_length >> 4;
      p += 11;
      p += table_type_descriptors_length;
     }

     nLen = i-1;
    }


    HRESULT GetMGTInfo()
    {
     PID pid = 0x1FFB;
     TID tid = 0xC7;
     HRESULT hr = S_OK;
     IMpeg2Data *pMpeg2Data = NULL;
     ISectionList *pSectionList = NULL;
     PSECTION pSection = NULL;
     DWORD dwTimeOut = 3000;
     DWORD dwLen = 0;
     WORD wSectionCount = 0; 

     hr = m_pBuild->FindInterface(NULL, NULL, m_pSaT, IID_IMpeg2Data, (void**)&pMpeg2Data);
     if (SUCCEEDED(hr))
     {
      hr = pMpeg2Data->GetTable(pid, tid, NULL, dwTimeOut, &pSectionList);
      if (SUCCEEDED(hr))
      {
       hr = pSectionList->GetNumberOfSections(&wSectionCount);
       for (int i=0; i<wSectionCount; i++)
       {
        hr = pSectionList->GetSectionData(i, &dwLen, &pSection);
        if (SUCCEEDED(hr))
        {
         BYTE *pdata = new BYTE[dwLen];
         WORD *pW = &pSection->Header.W;
         BYTE *pB = (BYTE*)pW;
         memcpy(pdata + 1, pB + 1, 1);
         memcpy(pdata + 2, pB, 1);
         memcpy(pdata + 3, (BYTE*)pSection->SectionData, dwLen - 3);
              
         WORD arrPID[256];
         int nLen;
         siParseMGT(pdata, arrPID, nLen);
         for (int i=0; i<nLen+1; ++i)
         {
          hr = GetEITInfo(arrPID[i]);
         }
        }
       }
      }
     }
     if (pMpeg2Data)
     {
      pMpeg2Data->Release();
      pMpeg2Data = NULL;
     }
     return hr;
    }

    Thursday, April 30, 2009 12:46 AM