📄 mpeg_demux.cpp
字号:
{ // If this was already filled/* if(pat_entries[entry].valid_pmt) continue;*/ if(pid != pat_entries[entry].pmtpid) { LOG_MSG("PID not equal 0x%x!", pat_entries[entry].pmtpid); continue; } if((ndx = ProcessHeader(pat_entries[entry].first_pmt)) < 0) return false; // Skip to the start of the section. ndx += pkt[ndx] + 1; // Now pointing to the start of the section. Check the table id. if(pkt[ndx++] != 2) { ERROR_MSG("Table ID not 2!"); return false; } // Check the section syntax indicator. if((pkt[ndx] & 0xc0) != 0x80) { ERROR_MSG("Invalid syntax indicator!"); return false; } // Check and get section length. if((pkt[ndx] & 0x0c) != 0) { ERROR_MSG("Section length invalid!"); return false; } length = ((pkt[ndx++] & 0x03) << 8); length |= pkt[ndx++]; DEBUG_MSG("Detected length %d", length); if(length > 0x3fd) { ERROR_MSG("Length is too large!"); return false; } begin = ndx; // Skip the program number ndx += 2; // We want only current tables. if(!(pkt[ndx++] & 0x01)) { ERROR_MSG("No current tables!"); return false; } // Get the number of this section. number = pkt[ndx++]; DEBUG_MSG("Number of the current section %d", number); // Get the number of the last section. last = pkt[ndx++]; DEBUG_MSG("Number of the last section %d", last); // Get the PCRPID. pat_entries[entry].pcrpid = (pkt[ndx++] & 0x1f) << 8; pat_entries[entry].pcrpid |= pkt[ndx++]; ERROR_MSG("PCR on PID 0x%x", pat_entries[entry].pcrpid); // Skip the descriptors (if any). descriptors_length = (pkt[ndx++] & 0x0f) << 8; descriptors_length |= pkt[ndx++]; ndx += descriptors_length; MPEG2_Transport_AudioPID = MPEG2_Transport_VideoPID = 0; // Now we have the actual program data. while (ndx < begin + length - 4) { num_streams = pat_entries[entry].num_streams; ERROR_MSG("Found new stream %d, type: 0x%x", num_streams, pkt[ndx]); switch (pkt[ndx++]) { case 0x01: pat_entries[entry].streams[num_streams].stream_type = "MPEG1 Video"; m_video = true; break; case 0x02: pat_entries[entry].streams[num_streams].stream_type = "MPEG2 Video"; m_video = true; break; case 0x03: pat_entries[entry].streams[num_streams].stream_type = "MPEG1 Audio"; m_audio = true; break; case 0x04: pat_entries[entry].streams[num_streams].stream_type = "MPEG2 Audio"; m_audio = true; break; case 0x05: pat_entries[entry].streams[num_streams].stream_type = "Private Sections"; break; case 0x06: case 0x07: pat_entries[entry].streams[num_streams].stream_type = "Teletext/Subtitling"; break; case 0x0f: case 0x11: // The demuxing code is the same for MPEG and AAC. // The only difference will be the filename. // The demuxing code will look at the audio sync word to // decide between the two. //type = 0x04; pat_entries[entry].streams[num_streams].stream_type = "AAC Audio"; m_audio = true; break; case 0x1b: pat_entries[entry].streams[num_streams].stream_type = "h264 Video"; m_video = true; break; case 0x81: pat_entries[entry].streams[num_streams].stream_type = "AC3 Audio"; break; default: pat_entries[entry].streams[num_streams].stream_type = "Other"; break; } pat_entries[entry].streams[num_streams].pid = (pkt[ndx++] & 0x1f) << 8; pat_entries[entry].streams[num_streams].pid |= pkt[ndx++] & 0xFF; ERROR_MSG("%s on PID 0x%x", pat_entries[entry].streams[num_streams].stream_type, pat_entries[entry].streams[num_streams].pid); // Increment stream counter if(pat_entries[entry].num_streams < MAX_STREAMS - 1) { pat_entries[entry].num_streams++; } else { ERROR_MSG("MAX_STREAMS reached!"); } // Skip the ES descriptors. es_descriptors_length = (pkt[ndx++] & 0x0f) << 8; es_descriptors_length |= pkt[ndx++]; ndx += es_descriptors_length; } pat_entries[entry].first_pmt = false; // If this is the last section number, we're done. if(number == last) num_valid_pmts++; } return true;}void mpeg_demux::ProcessVideoPacket(){ int ndx; Packet packet; unsigned int flags; DEBUG_MSG("Processing video packet.."); if((ndx = ProcessHeader(m_video)) < 0) return; // Start packet, we should now look for PES header if((pkt[1] & 0x40) >> 6) { if((pkt[ndx] == 0x0) && (pkt[ndx + 1] == 0x0) && (pkt[ndx + 2] == 0x1)) DEBUG_MSG("PES header found!"); else { DEBUG_MSG("Not a PES header: 0x%x 0x%x 0x%x", pkt[ndx], pkt[ndx + 1], pkt[ndx + 2]); return; } // Check for scrambling if(pkt[ndx + 6] & 0x60) { ERROR_MSG("PES Scrambling: 0x%x", pkt[ndx + 6] & 0x60); } // Skip PES header (3 bytes) + stream ID (1 byte) // PES packet length (2 bytes) + extension flags (1 byte) ndx += 7; flags = pkt[ndx++]; DEBUG_MSG("PES header length %d", pkt[ndx]); packet.pes_flag = true; // Stop at Packet_Header_Length field & get timestamp if((flags & 0x80) && (pkt[ndx] > 4)) { // Ignore bit 33, or mask would be 0x0e packet.pts = (pkt[ndx+1] & 0x06) << 29; packet.pts |= (pkt[ndx+2]) << 22; packet.pts |= (pkt[ndx+3] & 0xfe) << 14; packet.pts |= (pkt[ndx+4]) << 7; packet.pts |= (pkt[ndx+5] & 0xfe) >> 1; // Convert to ms packet.pts /= 90; } // Make sure first packet has PTS stamp if(m_video && (packet.pts == 0)) { LOG_MSG("Missing PTS timestamp"); return; } // Now, skip rest of PES-header ndx += pkt[ndx] + 1; /*if(!Start_Flag) { // Start_Flag becomes true after the first I frame. // So VideoPTS will be left at the value corresponding to // the first I frame. VideoPTS = pts_stamp; }*/ // Check that we have a SEQ header (00 00 01 B3 for mpeg2) if(m_video) { // Some streams have an extra 00 ?? if((pkt[ndx+2] == 0x0) && (pkt[ndx+3] == 0x1)) { LOG_MSG("Additional data before ES!"); ndx++; } if(SeqHeader(pkt+ndx)) { DEBUG_MSG("Found Sequence header."); m_video = false; } else { DEBUG_MSG("No Sequence header at ndx: %d (bytes 0x%x 0x%x 0x%x 0x%x 0x%x)!", ndx, pkt[ndx], pkt[ndx+1], pkt[ndx+2], pkt[ndx+3], pkt[ndx+4]); return; } } DEBUG_MSG("Video PES starts with 0x%x 0x%x 0x%x 0x%x 0x%x", pkt[ndx], pkt[ndx+1], pkt[ndx+2], pkt[ndx+3], pkt[ndx+4]); } // We are at the start of ES :-) // Length is TS_PACKET_SIZE - ndx packet.data = pkt+ndx; packet.size = TS_PACKET_SIZE - ndx; if(videodec) { videodec->WriteData(&packet); DEBUG_MSG("Wrote %d bytes to video decoder", TS_PACKET_SIZE - ndx); } else { ERROR_MSG("No video decoder connected!"); }}void mpeg_demux::ProcessAudioPacket(){ int ndx; Packet packet; unsigned int flags; DEBUG_MSG("Processing audio packet.."); if((ndx = ProcessHeader(m_audio)) < 0) return; // Start packet, we should now look for PES header if((pkt[1] & 0x40) >> 6) { if((pkt[ndx] == 0x0) && (pkt[ndx + 1] == 0x0) && (pkt[ndx + 2] == 0x1)) DEBUG_MSG("PES header found!"); else { LOG_MSG("No PES header in audio stream!"); return; } // Skip PES header (3 bytes) + stream ID (1 byte) // PES packet length (2 bytes) + extension flags (1 byte) ndx += 7; flags = pkt[ndx++]; DEBUG_MSG("PES header length %d", pkt[ndx]); // Stop at Packet_Header_Length field & get timestamp if((flags & 0x80) && (pkt[ndx] > 4)) { // Ignore bit 33, or mask would be 0x0e packet.pts = (pkt[ndx+1] & 0x6) << 29; packet.pts |= (pkt[ndx+2]) << 22; packet.pts |= (pkt[ndx+3] & 0xfe) << 14; packet.pts |= (pkt[ndx+4]) << 7; packet.pts |= (pkt[ndx+5] & 0xfe) >> 1; // Convert to ms packet.pts /= 90; DEBUG_MSG("Found PTS %d", packet.pts); } // Now, skip rest of PES-header ndx += pkt[ndx] + 1; // Make sure first packet has PTS stamp if(m_audio && (packet.pts == 0)) { LOG_MSG("Missing PTS timestamp"); return; } DEBUG_MSG("Audio PES starts with 0x%x 0x%x 0x%x 0x%x 0x%x", pkt[ndx], pkt[ndx+1], pkt[ndx+2], pkt[ndx+3], pkt[ndx+4]); packet.pes_flag = true; packet.data = pkt+ndx; packet.size = TS_PACKET_SIZE - ndx; if((audiodec) && (audiodec->WriteData(&packet))) { DEBUG_MSG("Wrote %d bytes to audio decoder", TS_PACKET_SIZE - ndx); m_audio = false; } else { LOG_MSG("Audio decoder not ready yet."); } return; } // We are at the start of ES :-) // Length is TS_PACKET_SIZE - ndx packet.data = pkt+ndx; packet.size = TS_PACKET_SIZE - ndx; if(audiodec) { audiodec->WriteData(&packet); DEBUG_MSG("Wrote %d bytes to audio decoder", TS_PACKET_SIZE - ndx); } else { LOG_MSG("No audio decoder connected!"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -