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

📄 mpeg3demux.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 4 页
字号:
    		clock_ref |= ((i & 0x000003ff) << 5);
    		clock_ref |= ((j & 0xf800) >> 11);
    		clock_ref_ext = (j >> 1) & 0x1ff;

   			demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000;
/* Skip 3 bytes */
			mpeg3io_read_int24(title->fs);
			i = mpeg3io_read_char(title->fs) & 0x7;

/* stuffing */
			mpeg3io_seek_relative(title->fs, i);  
		}
	}
	else
	{
		mpeg3io_seek_relative(title->fs, 2);
	}
	return 0;
}

/* Program packet reading core */
static int get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int header)
{
	unsigned long pts = 0, dts = 0;
	int stream_id;
	int pes_packet_length;
	long pes_packet_start;
	long decryption_offset;
	int i;
	mpeg3_t *file = demuxer->file;
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
	int scrambling = 0;

	stream_id = header & 0xff;
	pes_packet_length = mpeg3io_read_int16(title->fs);
	pes_packet_start = mpeg3io_tell(title->fs);








	if(stream_id != MPEG3_PRIVATE_STREAM_2 &&
		stream_id != MPEG3_PADDING_STREAM)
	{
		if((mpeg3io_next_char(title->fs) >> 6) == 0x02)
		{
/* Get MPEG-2 packet */
			int pes_header_bytes = 0;
    		int pts_dts_flags;
			int pes_header_data_length;


			demuxer->last_packet_decryption = mpeg3io_tell(title->fs);
			scrambling = mpeg3io_read_char(title->fs) & 0x30;
//scrambling = 1;
/* Reset scrambling bit for the mpeg3cat utility */
//			if(scrambling) demuxer->raw_data[demuxer->raw_offset - 1] &= 0xcf;



    		pts_dts_flags = (mpeg3io_read_char(title->fs) >> 6) & 0x3;
			pes_header_data_length = mpeg3io_read_char(title->fs);



/* Get Presentation and Decoding Time Stamps */
			if(pts_dts_flags == 2)
			{
				pts = (mpeg3io_read_char(title->fs) >> 1) & 7;  /* Only low 4 bits (7==1111) */
				pts <<= 15;
				pts |= (mpeg3io_read_int16(title->fs) >> 1);
				pts <<= 15;
				pts |= (mpeg3io_read_int16(title->fs) >> 1);
				pes_header_bytes += 5;
			}
    		else 
			if(pts_dts_flags == 3)
			{
        		pts = (mpeg3io_read_char(title->fs) >> 1) & 7;  /* Only low 4 bits (7==1111) */
        		pts <<= 15;
        		pts |= (mpeg3io_read_int16(title->fs) >> 1);
        		pts <<= 15;
        		pts |= (mpeg3io_read_int16(title->fs) >> 1);
        		dts = (mpeg3io_read_char(title->fs) >> 1) & 7;  /* Only low 4 bits (7==1111) */
        		dts <<= 15;
        		dts |= (mpeg3io_read_int16(title->fs) >> 1);
        		dts <<= 15;
        		dts |= (mpeg3io_read_int16(title->fs) >> 1);
        		pes_header_bytes += 10;
    		}

/* Skip unknown */
        	mpeg3io_seek_relative(title->fs, 
				pes_header_data_length - pes_header_bytes);
		}
		else
		{
			int pts_dts_flags;
/* Get MPEG-1 packet */
			while(mpeg3io_next_char(title->fs) == 0xff)
			{
				mpeg3io_read_char(title->fs);
			}

/* Skip STD buffer scale */
			if((mpeg3io_next_char(title->fs) & 0x40) == 0x40)
			{
				mpeg3io_seek_relative(title->fs, 2);
			}

/* Decide which timestamps are available */
			pts_dts_flags = mpeg3io_next_char(title->fs);

			if(pts_dts_flags >= 0x30)
			{
/* Get the presentation and decoding time stamp */
				pts = get_timestamp(demuxer);
				dts = get_timestamp(demuxer);
			}
			else
			if(pts_dts_flags >= 0x20)
			{
/* Get just the presentation time stamp */
				pts = get_timestamp(demuxer);
			}
			else
			if(pts_dts_flags == 0x0f)
			{
/* End of timestamps */
				mpeg3io_read_char(title->fs);
			}
			else
			{
				return 1;     /* Error */
			}
		}

/* Now extract the payload. */
		if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd)
		{
/* Audio data */
/* Take first stream ID if -1 */
			pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;




			if(demuxer->read_all)
				demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG;
			else
			if(demuxer->astream == -1) 
				demuxer->astream = stream_id & 0x0f;




			demuxer->pes_audio_time = demuxer->time;
			if(pts) demuxer->pes_audio_time = pts;


			if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio)
			{
				decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
				mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, 
					pes_packet_length, 
					title->fs);
				demuxer->data_size += pes_packet_length;
		  	}
			else 
			{
    			mpeg3io_seek_relative(title->fs, pes_packet_length);
			}
		}
    	else 
		if((stream_id >> 4) == 0xe)
		{
/* Video data */
/* Take first stream ID if -1 */
			pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;



			if(demuxer->read_all) 
				demuxer->vstream_table[stream_id & 0x0f] = 1;
			else
			if(demuxer->vstream == -1) 
				demuxer->vstream = stream_id & 0x0f;

       		demuxer->pes_video_time  = demuxer->time;;
       		if(pts) demuxer->pes_video_time = pts;



    	    if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video)
			{
//printf(__FUNCTION__ " stream_id=%x size=%x\n", stream_id, pes_packet_length);
				decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
				mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, 
					pes_packet_length, 
					title->fs);

				demuxer->data_size += pes_packet_length;
    	  	}
    		else 
			{
    			mpeg3io_seek_relative(title->fs, pes_packet_length);
    		}
    	}
    	else 
		if((stream_id == 0xbd || stream_id == 0xbf) && 
			mpeg3io_next_char(title->fs) != 0xff &&
			((mpeg3io_next_char(title->fs) & 0xf0) != 0x20))
		{
/* DVD audio data */
/* Get the audio format */
			int format;
//printf("get_ps_pes_packet 5 %x\n", packet_next_char(demuxer) & 0xf0);
			if((mpeg3io_next_char(title->fs) & 0xf0) == 0xa0)
				format = AUDIO_PCM;
			else
				format = AUDIO_AC3;

// Picks up bogus data if (& 0xf) or (& 0x7f)
			stream_id = mpeg3io_next_char(title->fs);
			demuxer->pes_audio_time = demuxer->time;
       		if(pts) demuxer->pes_audio_time = pts;

//printf("get_ps_pes_packet %x\n", stream_id);
/* Take first stream ID if not building TOC. */
			if(demuxer->read_all)
				demuxer->astream_table[stream_id] = format;
			else
			if(demuxer->astream == -1)
				demuxer->astream = stream_id;

      		if(stream_id == demuxer->astream && demuxer->do_audio)
			{
				demuxer->aformat = format;
				mpeg3io_read_int32(title->fs);

				pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
				decryption_offset = mpeg3io_tell(title->fs) - demuxer->last_packet_start;
				mpeg3io_read_data(demuxer->data_buffer + demuxer->data_size, 
					pes_packet_length, 
					title->fs);
				demuxer->data_size += pes_packet_length;
      		}
      		else
			{
				pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
    			mpeg3io_seek_relative(title->fs, pes_packet_length);
      		}
//printf("get_ps_pes_packet 6 %d\n", demuxer->astream_table[0x20]);
    	}
    	else 
		if(stream_id == 0xbc || 1)
		{
			pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
    		mpeg3io_seek_relative(title->fs, pes_packet_length);
    	}
	}
  	else 
	if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM)
	{
		pes_packet_length -= mpeg3io_tell(title->fs) - pes_packet_start;
    	mpeg3io_seek_relative(title->fs, pes_packet_length);
  	}





// Advance 2048 bytes if scrambled.  We might pick up a spurrius
// packet start code in the scrambled data otherwise.
	if(scrambling && 
		demuxer->last_packet_start + 0x800 > mpeg3io_tell(title->fs))
	{
		mpeg3io_seek_relative(title->fs, 
			demuxer->last_packet_start + 0x800 - mpeg3io_tell(title->fs));
	}





// Descramble if desired
	if(demuxer->data_size && scrambling)
	{
//printf(__FUNCTION__ " data_size=%x decryption_offset=%x\n", demuxer->data_size, decryption_offset);
		if(mpeg3_decrypt_packet(title->fs->css, 
			demuxer->data_buffer,
			decryption_offset))
		{
			fprintf(stderr, "get_ps_pes_packet: Decryption not available\n");
			return 1;
		}
	}

//if(mpeg3io_tell(title->fs) - demuxer->last_packet_start != 0x800)
//	printf(__FUNCTION__ " packet size == %d\n", mpeg3io_tell(title->fs) - demuxer->last_packet_start);

	return 0;
}

int mpeg3demux_read_program(mpeg3_demuxer_t *demuxer)
{
	int result = 0;
	int count = 0;
	mpeg3_t *file = demuxer->file;
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
	unsigned int header = 0;
	int pack_count = 0;

	demuxer->data_size = 0;
//printf("mpeg3demux_read_program 1 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);

	if(mpeg3io_eof(title->fs)) return 1;

//printf("mpeg3demux_read_program 2 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);







/* Search for next header */
/* Parse packet until the next packet start code */
	while(!result && !mpeg3io_eof(title->fs))
	{
		header = mpeg3io_read_int32(title->fs);



		if(header == MPEG3_PACK_START_CODE)
		{


// Start of next packet
			if(pack_count)
			{
				mpeg3io_seek_relative(title->fs, -4);
				break;
			}

			demuxer->last_packet_start = mpeg3io_tell(title->fs) - 4;
			result = get_pack_header(demuxer);
//printf("mpeg3demux_read_program MPEG3_PACK_START_CODE %d\n", result);
			pack_count++;



		}
		else
		if(header == MPEG3_SYSTEM_START_CODE && pack_count)
		{



 			result = get_system_header(demuxer);
//printf("mpeg3demux_read_program MPEG3_SYSTEM_START_CODE %d\n", result);



		}
		else
		if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX && pack_count)
		{


			result = get_ps_pes_packet(demuxer, header);
//printf("mpeg3demux_read_program MPEG3_PACKET_START_CODE_PREFIX %d %08x\n", result, header);



		}
		else
		{
// Try again.
			mpeg3io_seek_relative(title->fs, -3);
		}
	}
//printf("mpeg3demux_read_program 3 %d %x %llx\n", result, title->fs->current_byte, title->fs->total_bytes);







// Ignore errors in the parsing.  Just quit if eof.
	result = 0;






	demuxer->last_packet_end = mpeg3io_tell(title->fs);

/*
 * if(demuxer->last_packet_end - demuxer->last_packet_start != 0x800)
 * 	printf(__FUNCTION__ " packet_size=%x data_size=%x packet_start=%x\n",
 * 		demuxer->last_packet_end - demuxer->last_packet_start,
 * 		demuxer->data_size,
 * 		demuxer->last_packet_start);
 */
//printf("mpeg3demux_read_program 5 %d\n", result);

//printf("read_program 3\n");
//	if(!result) result = mpeg3io_eof(title->fs);

	return result;
}

static double lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte)
{
	int i;
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];

	if(!title->timecode_table_size) return 0;

	for(i = title->timecode_table_size - 1; 
		i >= 0 && title->timecode_table[i].start_byte > byte;
		i--)
		;
	if(i < 0) i = 0;
	return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time;
}





































int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer)
{
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
	int result = 0;
	int do_seek = 0;
	int last_timecode = demuxer->current_timecode;
//printf("mpeg3_advance_timecode 0\n");fflush(stdout);






/* Don't do anything when constructing timecode table */
	if(!title->timecode_table || 
		!title->timecode_table_size || 
		demuxer->read_all) return 0;





//printf("mpeg3_advance_timecode 1\n");fflush(stdout);
	if(!demuxer->reverse)
	{




/* Get inside the current timecode */
		if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte)
		{
			mpeg3io_seek(title->fs, 
				title->timecode_table[demuxer->current_timecode].start_byte);
		}





/* Get the next timecode */
		while(!result && 
			(mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte ||
				demuxer->current_program != title->timecode_table[demuxer->current_timecode].program))
		{
			demuxer->current_timecode++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -