/* * File: PacketPES.cpp * Author: felipe * * Created on 19 de Outubro de 2009, 14:49 */ #include "extratorCC.h" #include #include #include #include #include #include "dprintf.h" using namespace std; ExtratorCC::ExtratorCC() { ouvintes = new list(); PTS = 0; // Inicia o mutex mutex = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t)); pthread_mutex_init(mutex, NULL); } void ExtratorCC::notifySection(int PID, unsigned char* section, int sectionSize) { //cout << "Recebi PES com a PID: " << PID << endl; packetPES(section); } void ExtratorCC::notifyErroCRC(int numErroCRC, int PID, int tableID, int tableIDX, unsigned char* section, int sectionSize) { } void ExtratorCC::notifyOldSection(int PID, int tableID, int tableIDX) { } ExtratorCC::~ExtratorCC() { if (ouvintes) { // nao deleta os ouvintes mesmo, apenas a lista ouvintes->clear(); delete ouvintes; } if (mutex) { int ret = pthread_mutex_destroy(mutex); if (ret) DDDPRINTF("erro destruindo mutex\n"); free(mutex); } } /*void ExtratorCC::chegouInput(unsigned char *pacote) { // Mutex para evitar bug multiplas chamadas dos notificadores pthread_mutex_lock(mutex); //packetPES(pacote); pthread_mutex_unlock(mutex); }*/ int ExtratorCC::contemAF(unsigned char * pacote) { return pacote[3] & 0x20; } int ExtratorCC::contemDTS(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 6) & 0x03); } int ExtratorCC::contemESCR(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 5) & 0x01); } int ExtratorCC::contemDSM(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 3) & 0x01); } int ExtratorCC::contemPES_extension(unsigned char * ExtratorCC) { return ExtratorCC[7] & 0x01; } int ExtratorCC::contemAdditional(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 2) & 0x01); } int ExtratorCC::contemPES_CRC(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 1) & 0x01); } int ExtratorCC::contemES_rate(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 4) & 0x01); } int ExtratorCC::contemPayloadData(unsigned char *pacote) { return pacote[3] & 0x10; } int ExtratorCC::contemPayloadStartIndicator(unsigned char *pacote) { return pacote[1] & 0x40; } int ExtratorCC::contemPCR(unsigned char * pacote) { return pacote[5] & 0x10; } int ExtratorCC::contemPTS(unsigned char * ExtratorCC) { return ((ExtratorCC[7] >> 6) & 0x02); } short unsigned ExtratorCC::GetTamanhoAF(unsigned char *pacote) { return pacote[4]; } int ExtratorCC::verificaPESStartCode(unsigned char * ExtratorCC) { // cout << "Start Code: " << ((PESPacket[0] << 16) | (PESPacket[1] << 8) | (PESPacket[2])) << endl; return (((ExtratorCC[0] << 16) | (ExtratorCC[1] << 8) | (ExtratorCC[2])) == 0x000001) ? 1 : 0; } int ExtratorCC::verificaPESStreamID(unsigned char * ExtratorCC) { int stream_id = ExtratorCC[3]; return ((stream_id != 0xBC) && (stream_id != 0xBE) && (stream_id != 0xBF) && (stream_id != 0xF0) && (stream_id != 0xF1) && (stream_id != 0xFF) && (stream_id != 0xF2) && (stream_id != 0xF8)); } int ExtratorCC::verificaPESStreamIDSynchronized(unsigned char * ExtratorCC) { int stream_id = ExtratorCC[3]; return ((stream_id == 0xBD)); } /* Extrai o PTS (Presentation Time Stamp) do pacote PES e retorna um * int64_t contendo os 33-bits extraídos */ int64_t ExtratorCC::extractPTS(unsigned char* PESPacket) { int64_t pts, c1, c2, c3 = 0; // leitura do 1º campo do PTS[32..30] c1 = ((PESPacket[9] & 0x0E) >> 1); // 0x0E = 00001110 pts = c1; // leitura do 2º campo do PTS[29..15] c2 = (((PESPacket[10] << 8) | (PESPacket[11])) >> 1); // >> 1 tira o marker_bit pts = (((pts << 16) | (c2 << 1)) >> 1); // leitura do 3º campo do PTS[14..0] c3 = (((PESPacket[12] << 8) | (PESPacket[13])) >> 1); pts = (((pts << 16) | (c3 << 1)) >> 1); return pts; } /* Extrai o DTS 33-bits (Decoding Time Stamp) do pacote PES */ int64_t ExtratorCC::extractDTS(unsigned char* PESPacket) { int64_t dts, c1, c2, c3 = 0; // leitura do 1º campo do DTS[32..30] c1 = ((PESPacket[14] & 0x0E) >> 1); // 0x0E = 00001110 dts = c1; // leitura do 2º campo do DTS[29..15] c2 = (((PESPacket[15] << 8) | (PESPacket[16])) >> 1); // >> 1 tira o marker_bit dts = (((dts << 16) | (c2 << 1)) >> 1); // leitura do 3º campo do DTS[14..0] c3 = (((PESPacket[17] << 8) | (PESPacket[18])) >> 1); dts = (((dts << 16) | (c3 << 1)) >> 1); return dts; } int ExtratorCC::packetPES(unsigned char *pacote) { int N1, N2, PES_header_data_length, PES_packet_length, cont_stuffing_byte = 0, cont_PES_packet_data_byte = 0; int pack_stuffing_length, system_header_start_code, PES_packet_data_byte; this->PTS = 0; this->DTS = 0; int inicioPESData = 0; if ((!verificaPESStartCode(pacote + inicioPESData)) || (!verificaPESStreamIDSynchronized(pacote + inicioPESData))) { return -1; } PES_packet_data_byte = inicioPESData + 9; PES_packet_length = (((pacote[inicioPESData + 4] & 0xFF) << 8) | (pacote[inicioPESData + 5] & 0xFF)); PES_header_data_length = pacote[inicioPESData + 8]; cont_PES_packet_data_byte = 3; /* PTS_DTS_flags = '10' */ if (contemPTS(pacote + inicioPESData) == 2) { PTS = extractPTS(pacote); PES_packet_data_byte += 5; cont_stuffing_byte += 5; } /* PTS_DTS_flags = '11' */ if (contemDTS(pacote + inicioPESData) == 3) { PTS = extractPTS(pacote); DTS = extractDTS(pacote); PES_packet_data_byte += 10; cont_stuffing_byte += 10; } if (contemESCR(pacote + inicioPESData) == 1) { PES_packet_data_byte += 6; cont_stuffing_byte += 6; } if (contemES_rate(pacote + inicioPESData) == 1) { PES_packet_data_byte += 3; cont_stuffing_byte += 3; } if (contemDSM(pacote + inicioPESData) == 1) { PES_packet_data_byte += 1; cont_stuffing_byte += 1; } if (contemAdditional(pacote + inicioPESData) == 1) { PES_packet_data_byte += 1; cont_stuffing_byte += 1; } if (contemPES_CRC(pacote + inicioPESData) == 1) { PES_packet_data_byte += 2; cont_stuffing_byte += 2; } if (contemPES_extension(pacote + inicioPESData) == 1) { int flag = PES_packet_data_byte; int PES_extension_field_length, PES_private_data_flag, pack_header_field_flag; int program_packet_sequence_counter_flag, PSTD_buffer_flag, PES_extension_flag_2; PES_packet_data_byte += 1; cont_stuffing_byte += 1; PES_private_data_flag = ((pacote[flag] >> 7) & 0x01); if (PES_private_data_flag == 1) { PES_packet_data_byte += 16; cont_stuffing_byte += 16; } pack_header_field_flag = ((pacote[flag] >> 6) & 0x01); if (pack_header_field_flag == 1) { PES_packet_data_byte += 14; cont_stuffing_byte += 15; pack_stuffing_length = pacote[PES_packet_data_byte] & 0x07; PES_packet_data_byte += 1; for (int i = 0; i < pack_stuffing_length; i++) { PES_packet_data_byte++; cont_stuffing_byte++; } system_header_start_code = (pacote[PES_packet_data_byte] << 24) | (pacote[PES_packet_data_byte + 1] << 16) | (pacote[PES_packet_data_byte + 2] << 8) | (pacote[PES_packet_data_byte + 3]); if (system_header_start_code == 0x000001BB) { PES_packet_data_byte += 12; cont_stuffing_byte += 12; while (pacote[PES_packet_data_byte] == 0x01) { PES_packet_data_byte += 3; cont_stuffing_byte += 3; } } } program_packet_sequence_counter_flag = ((pacote[flag] >> 5) & 0x01); if (program_packet_sequence_counter_flag == 1) { PES_packet_data_byte += 2; cont_stuffing_byte += 2; } PSTD_buffer_flag = ((pacote[flag] >> 4) & 0x01); if (PSTD_buffer_flag == 1) { PES_packet_data_byte += 2; cont_stuffing_byte += 2; } PES_extension_flag_2 = pacote[flag] & 0x01; if (PES_extension_flag_2 == 1) { PES_extension_field_length = pacote[PES_packet_data_byte] & 0x7F; PES_packet_data_byte += 1; cont_stuffing_byte += 1; for (int i = 0; i < PES_extension_field_length; i++) { PES_packet_data_byte++; cont_stuffing_byte++; } } } N1 = PES_header_data_length - cont_stuffing_byte; cont_PES_packet_data_byte += cont_stuffing_byte + N1; N2 = PES_packet_length - cont_PES_packet_data_byte; for (int i = 0; i < N1; i++) { PES_packet_data_byte++; } synchronizedPesData(PES_packet_data_byte, pacote); return 0; } void ExtratorCC::synchronizedPesData(int PES_packet_data_byte, unsigned char *pacote) { int PES_data_private_data_byte; PES_packet_data_byte += 2; PES_data_private_data_byte = pacote[PES_packet_data_byte] & 0x0F; PES_packet_data_byte += 1; for (int i = 0; i < PES_data_private_data_byte; i++) { PES_packet_data_byte++; } dataGroup(PES_packet_data_byte, pacote); } void ExtratorCC::dataGroup(int PES_packet_data_byte, unsigned char *pacote) { int data_group_id, data_group_size; data_group_id = (pacote[PES_packet_data_byte] >> 2) & 0x3F; PES_packet_data_byte += 3; data_group_size = (pacote[PES_packet_data_byte] << 8) | (pacote[PES_packet_data_byte + 1]); PES_packet_data_byte += 2; captionData(PES_packet_data_byte, pacote, data_group_id); } void ExtratorCC::captionData(int PES_packet_data_byte, unsigned char *pacote, int data_group_id) { int TDM, data_unit_loop_length; TDM = (pacote[PES_packet_data_byte] >> 6) & 0x03; PES_packet_data_byte += 1; if (TDM == 1 || TDM == 2) { PES_packet_data_byte += 5; } if (data_group_id > 0) { data_unit_loop_length = (pacote[PES_packet_data_byte] << 16) | (pacote[PES_packet_data_byte + 1] << 8) | (pacote[PES_packet_data_byte + 2]); PES_packet_data_byte += 4; dataUnit(PES_packet_data_byte, pacote); } } void ExtratorCC::dataUnit(int PES_packet_data_byte, unsigned char *pacote) { int data_unit_parameter, data_unit_size, controle_CSI_count, controle_CSI, flag; unsigned char msg[300]; // TODO ver qual eh o valor maximo que isso pode atingir int k = 0; // contador que vai percorrer msg //FILE * pFile; //stringstream st; //string resultadoo, finall; //pFile = fopen ("tempo2.txt" , "a+"); //if (pFile == NULL) perror ("Error opening file"); data_unit_parameter = pacote[PES_packet_data_byte]; PES_packet_data_byte += 1; data_unit_size = (pacote[PES_packet_data_byte] << 16) | (pacote[PES_packet_data_byte + 1] << 8) | (pacote[PES_packet_data_byte + 2]); PES_packet_data_byte += 3; // printf("\nPACOTE: "); // for (int f = 0; f < data_unit_size + 10; f++) { // printf(" %x", pacote[f + PES_packet_data_byte]); //} for (int i = 0; i < data_unit_size; i++) { if (pacote[PES_packet_data_byte + i] < 0x1C) { } else if (pacote[PES_packet_data_byte + i] == 0x1C) { i += 2; } else if (pacote[PES_packet_data_byte + i] > 0x1C && pacote[PES_packet_data_byte + i] < 0x20) { } else if (pacote[PES_packet_data_byte + i] >= 0x80 && pacote[PES_packet_data_byte + i] <= 0x8A) { } else if (pacote[PES_packet_data_byte + i] == 0x8B) { i += 1; if (pacote[PES_packet_data_byte + i] == 0x60 || pacote[PES_packet_data_byte + i] == 0x41 || pacote[PES_packet_data_byte + i] == 0x44 || pacote[PES_packet_data_byte + i] == 0x45 || pacote[PES_packet_data_byte + i] == 0x6B || pacote[PES_packet_data_byte + i] == 0x64) { } } else if (pacote[PES_packet_data_byte + i] == 0x90) { if (pacote[PES_packet_data_byte + i + 1] == 0x20) i += 2; else i += 1; } else if (pacote[PES_packet_data_byte + i] == 0x91) { i += 1; if (pacote[PES_packet_data_byte + i] == 0x40 || pacote[PES_packet_data_byte + i] == 0x47 || pacote[PES_packet_data_byte + i] == 0x4F) { } } else if (pacote[PES_packet_data_byte + i] == 0x92) { if (pacote[PES_packet_data_byte + i + 1] == 0x20) i += 2; else i += 1; } else if (pacote[PES_packet_data_byte + i] == 0x93) { i += 1; if (pacote[PES_packet_data_byte + i] == 0x40 || pacote[PES_packet_data_byte + i] == 0x41 || pacote[PES_packet_data_byte + i] == 0x42) { } } else if (pacote[PES_packet_data_byte + i] == 0x94) { i += 1; if (pacote[PES_packet_data_byte + i] == 0x40 || pacote[PES_packet_data_byte + i] == 0x44 || pacote[PES_packet_data_byte + i] == 0x45) { } } else if (pacote[PES_packet_data_byte + i] == 0x97 || pacote[PES_packet_data_byte + i] == 0x98) { i += 1; } else if (pacote[PES_packet_data_byte + i] == 0x99 || pacote[PES_packet_data_byte + i] == 0x9A) { } else if (pacote[PES_packet_data_byte + i] == 0x9B) { controle_CSI_count = 0; flag = 0; controle_CSI = PES_packet_data_byte + i; while (flag == 0) { if (pacote[controle_CSI] == 0x53 || pacote[controle_CSI] == 0x54 || pacote[controle_CSI] == 0x6E || pacote[controle_CSI] == 0x61 || pacote[controle_CSI] == 0x56 || pacote[controle_CSI] == 0x5F || pacote[controle_CSI] == 0x57 || pacote[controle_CSI] == 0x5B || pacote[controle_CSI] == 0x5C || pacote[controle_CSI] == 0x58 || pacote[controle_CSI] == 0x59 || pacote[controle_CSI] == 0x42 || pacote[controle_CSI] == 0x5D || pacote[controle_CSI] == 0x5E || pacote[controle_CSI] == 0x62 || pacote[controle_CSI] == 0x65 || pacote[controle_CSI] == 0x63 || pacote[controle_CSI] == 0x64 || pacote[controle_CSI] == 0x66 || pacote[controle_CSI] == 0x68 || pacote[controle_CSI] == 0x69 || pacote[controle_CSI] == 0x6F) { flag = 1; i += controle_CSI_count; } controle_CSI++; controle_CSI_count++; } } else { if (pacote[PES_packet_data_byte + i] < 0x20) msg[k++] = ' '; else msg[k++] = pacote[PES_packet_data_byte + i]; } } msg[k] = '\0'; printf("\n****************************************************************************************"); printf("\nMensagem extraida do CC: "); printf("\033[31m"); printf("_%s_", msg); printf("\033[0m"); printf("\n\n"); //printf("\nTEMPO DE EXTRAÇÃO: %lld\n\n", calculoFinal); printf("PTS = %lld\n", PTS); //printf("DTS = %lld\n", DTS); notificaOuvintes(msg); } void ExtratorCC::registraOuvinte(OuvinteCC * ouvinte) { ouvintes->push_back(ouvinte); } void ExtratorCC::removeOuvinte(OuvinteCC * ouvinte) { ouvintes->remove(ouvinte); } void ExtratorCC::notificaOuvintes(unsigned char * CC) { for (list::iterator i = ouvintes->begin(); i != ouvintes->end(); i++) { (*i)->notificaCC(CC, PTS); } }