⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg_demux.cpp

📁 linux下实现视频播放的播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    {	// 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 + -