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

📄 audio_stream.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
📖 第 1 页 / 共 2 页
字号:
	}

	if(ps->stream_id == 0){
		return 0;
	}

	extract_pes_packet_data(&packet, buffer, &pos);

	while(read_pes_packet_ps(ps->bs, &packet)){
		if(pos > 64*1024){
			break;
		}
		if(bs_tell(ps->bs) > 8*1024*1024){
			break;
		}
		if(packet.stream_id == ps->stream_id){
			extract_pes_packet_data(&packet, buffer+pos, &n);
			pos += n;
		}
	}

	p = buffer;
	last = p+pos-3;
	n = 0;
	while(p < last){
		if( (p[0] == 0xff) && ((p[1] & 0xf0) == 0xf0) ){
			sync = ((unsigned int)(p[0]) << 24) | ((unsigned int)(p[1]) << 16) | ((unsigned int)(p[2]) << 8) | p[3];
			if( ! parse_layer2_header(sync, &hd) ){
				p += 1;
				n = 0;
				continue;
			}
			if( p + hd.framesize >= last ){
				break;
			}
			if( (p[hd.framesize] == 0xff) && ((p[hd.framesize+1] & 0xf0) == 0xf0) ){
				n += 1;
				p += hd.framesize;
			}else{
				p += 1;
				n = 0;
			}
		}else{
			p += 1;
			n = 0;
		}
	}

	if(n == 0){
		return 0;
	}
	
	ps->frequency = hd.frequency;
	ps->channel = hd.channel;

	return 1;
}

static int set_start_pts_ps(AUDIO_PS *ps)
{
	__int64 audio_start_pts;
	__int64 video_start_pts;
	__int64 video_pts[3];
	
	PTS_DTS pts_dts;
	PES_PACKET packet;
	PES_STREAM_TYPE type;

	unsigned char *buffer;
	unsigned char *pos;
	unsigned char *last;

	int n;
	int closed_gop;

	int video_id;

	buffer = (unsigned char *)malloc(8*1024*1024);
	if(buffer == NULL){
		return 0;
	}
	
	init_pes_packet(&packet);
	
	pos = buffer;
	last = buffer;
	
	bs_seek(ps->bs, 0, SEEK_SET);

	video_id = 0;

	audio_start_pts = -1;
	video_start_pts = -1;
	video_pts[0] = -1;
	video_pts[1] = -1;
	video_pts[2] = -1;
	closed_gop = 0;

	while(read_pes_packet_ps(ps->bs, &packet)){
		if(extract_pes_stream_type(&packet, &type)){
			if(packet.stream_id == ps->stream_id){
				if(audio_start_pts < 0){
					extract_pes_pts_dts(&packet, &pts_dts);
					audio_start_pts = pts_dts.pts;
				}
			}else if(type.type == PES_STREAM_TYPE_VIDEO){
				if(video_id == 0){
					video_id = type.id;
				}else if(video_id != type.id){
					continue;
				}
				if(video_start_pts < 0){
					extract_pes_pts_dts(&packet, &pts_dts);
					extract_pes_packet_data(&packet, last, &n);
					last += n;
					if(pts_dts.pts >= 0){
						if(video_pts[0] < 0){
							video_pts[0] = pts_dts.pts;
						}else{
							video_pts[1] = pts_dts.pts;
						}
					}
					while( (pos = find_next_001(pos, last)) != NULL ){
						if(pos+3>=last){
							break;
						}
						if(pos[3] == 0xb8){
							if(pos+7<last){
								closed_gop = (pos[7] >> 6) & 1;
								pos += 7;
							}else{
								break;
							}
						}else if(pos[3] == 0x00){
							if(pos+5<last){
								int type = (pos[5]>>3) & 7;
								if(type == 1){
									if(!closed_gop){
										video_start_pts = video_pts[0];
										break;
									}else{
										video_pts[2] = video_pts[0];
										if(video_pts[1] >= 0){
											video_pts[0] = video_pts[1];
											video_pts[1] = -1;
										}else{
											video_pts[0] = -1;
										}
									}
								}else if(type == 2){
									if(video_pts[2] >= 0){
										video_start_pts = video_pts[2];
										break;
									}else{
										if(video_pts[1] >= 0){
											video_pts[0] = video_pts[1];
											video_pts[1] = -1;
										}else{
											video_pts[0] = -1;
										}
									}
								}else if(type == 3){
									if(video_pts[2] >= 0){
										video_start_pts = video_pts[0];
										break;
									}else{
										if(video_pts[1] >= 0){
											video_pts[0] = video_pts[1];
											video_pts[1] = -1;
										}else{
											video_pts[0] = -1;
										}
									}
								}
								pos += 5;
							}else{
								break;
							}
						}else{
							pos += 3;
						}
					}
					if(pos == NULL){
						pos = last-2;
					}
				}
			}
		}
		if( (audio_start_pts >= 0) && (video_start_pts >= 0) ){
			break;
		}
		if(bs_tell(ps->bs) > 8*1024*1024){
			break;
		}
	}

	free(buffer);
	release_pes_packet(&packet);

	if( (video_start_pts >= 0) && (audio_start_pts >= 0) ){
		ps->pts[0].back_pts = video_start_pts;
	}else{
		ps->pts[0].back_pts = audio_start_pts;
	}

	if(ps->pts[0].back_pts < 0){
		return 0;
	}

	return 1;
}

static int set_filesize_and_sample_ps(AUDIO_PS *ps)
{
	int i,n;

	n = ps->bs->mf->count(ps->bs->mf);

	for(i=0;i<n;i++){
		if(!set_unit_pts_ps(ps, i)){
			return 0;
		}
	}

	ps->filesize = ps->bs->mf->border(ps->bs->mf, n-1);
	ps->sample = pts_to_sample(ps->pts[n].face_pts, ps->frequency);

	return 1;
}

static int set_unit_pts_ps(AUDIO_PS *ps, int unit)
{
	__int64 offset;
	__int64 sample;
	PTS_DTS pts_dts;
	PES_PACKET packet;

	int r;
	int count;

	bs_seek(ps->bs, ps->bs->mf->border(ps->bs->mf, unit), SEEK_SET);
	
	init_pes_packet(&packet);
	r = 0;
	count = 0;
	while(bs_prev_packet_prefix(ps->bs)){
		if( (bs_read_bits(ps->bs, 32)) == 0x100 + ps->stream_id){
			offset = bs_tell(ps->bs);
			if(read_pes_packet_ps(ps->bs, &packet)){
				extract_pes_pts_dts(&packet, &pts_dts);
				if(pts_dts.pts >= 0){
					sample = count_audio_frame(&packet) * 1152;
					if(sample == 0){
						/* stream has probrem
						 * pes packet contains no audio access unit head byte
						 * and pes packet has pts
						 */
						count+=1;
						if(count > 4){
							ps->pts[unit+1].face_pts = pts_dts.pts;
							break;
						}
						bs_seek(ps->bs, offset-4, SEEK_SET);
						continue;
					}
					ps->pts[unit+1].face_pts = pts_dts.pts - ps->pts[unit].back_pts + ps->pts[unit].face_pts;
					ps->pts[unit+1].face_pts += sample_to_pts(sample, ps->frequency);
					r = 1;
					break;
				}else{
					bs_seek(ps->bs, offset-4, SEEK_SET);
				}
			}else{
				bs_seek(ps->bs, offset-4, SEEK_SET);
			}
		}else{
			ps->bs->current -= 4;
		}
	}

	if(pts_dts.pts < 0){
		release_pes_packet(&packet);
		return 0;
	}

	bs_seek(ps->bs, ps->bs->mf->border(ps->bs->mf, unit), SEEK_SET);
	while(read_pes_packet_ps(ps->bs, &packet)){
		if(packet.stream_id == ps->stream_id){
			extract_pes_pts_dts(&packet, &pts_dts);
			if(pts_dts.pts >= 0){
				ps->pts[unit+1].back_pts = pts_dts.pts;
				break;
			}
		}
	}

	offset = ps->pts[unit+1].face_pts - ps->pts[unit].face_pts;
	offset -= ps->pts[unit+1].back_pts - ps->pts[unit].back_pts;

	if(offset < 0){
		offset = 0 - offset;
	}

	if(offset < 450){ /* under 5 msec */
		ps->pts[unit+1].face_pts = ps->pts[unit+1].back_pts - ps->pts[unit].back_pts + ps->pts[unit].face_pts;
	}
	
	release_pes_packet(&packet);
	
	return r;
}

static int read_pes_packet_ps(BITSTREAM *in, PES_PACKET *out)
{
	int code, n, m;
	unsigned char buf[6];
	
	do{
		if(! bs_next_packet_prefix(in)){
			return 0;
		}

		code = bs_get_bits(in, 32);
		
	}while(code < 0x1bc);

	release_pes_packet(out);
	buf[0] = 0;
	buf[1] = 0;
	buf[2] = 1;
	buf[3] = (unsigned char)( code & 0xff );

	n = bs_get_bits(in, 16);
	buf[4] = (unsigned char)( (n >> 8) & 0xff );
	buf[5] = (unsigned char)( n & 0xff );
	
	append_pes_packet_data(out, buf, sizeof(buf));
	while(n){
		m = bs_read(in, out->data+out->size, n);
		n -= m;
		out->size += m;
		if(m == 0){
			return 0;
		}
	}
	return out->size;
}

static __int64 pts_to_sample(__int64 pts, int rate)
{
	__int64 sec;
	__int64 mod;

	sec = pts/90000;
	mod = pts%90000;

	return (sec*rate+(mod*rate/90000));
}

static __int64 sample_to_pts(__int64 sample, int rate)
{
	__int64 sec;
	__int64 mod;

	sec = sample / rate;
	mod = sample % rate;

	return (sec*90000+(mod*90000/rate));
}

static int count_audio_frame(PES_PACKET *packet)
{
	int r;
	int n;
	unsigned int  sync;
	
	unsigned char *pos;
	unsigned char *last;

	LAYER2_HEADER head;

	n = get_pes_packet_data_length(packet);
	pos = packet->data+packet->size-n;
	last = pos+n-3;

	r = 0;
	while(pos<last){
		if( (pos[0] == 0xff) && ((pos[1] & 0xf0) == 0xf0) ){
			sync = ((unsigned int)(pos[0]) << 24) | ((unsigned int)(pos[1]) << 16) | ((unsigned int)(pos[2]) << 8) | ((unsigned int)(pos[3]));
			if(! parse_layer2_header(sync, &head)){
				pos += 1;
				continue;
			}
			if( pos+head.framesize >= last ){
				break;
			}
			if( (pos[head.framesize] == 0xff) && ((pos[head.framesize+1] & 0xf0) == 0xf0) ){
				r += 1;
				pos += head.framesize;
			}else{
				pos += 1;
			}
		}else{
			pos += 1;
		}
	}

	if(pos != last){
		r += 1;
	}

	return r;
}

static unsigned char *find_sync_current_ps_buffer(AUDIO_PS *ps)
{
	unsigned char *pos;
	unsigned char *last;
	unsigned int sync;

	LAYER2_HEADER h;

	last = ps->buffer.buffer+ps->buffer.size;
	while( (pos = mb_next_fff(&(ps->buffer))) != NULL ){
		if(pos+4 >= last ){
			break;
		}
		sync = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3];
		if(parse_layer2_header(sync, &h)){
			if( pos+h.framesize == last ){
				return pos;
			}
			if( pos+h.framesize+1 >= last ){
				break;
			}
			if( (pos[h.framesize] == 0xff) && ((pos[h.framesize+1] & 0xf0) == 0xf0) ){
				return pos;
			}
		}
		ps->buffer.pos += 1;
	}

	return NULL;
}

⌨️ 快捷键说明

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