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

📄 audio_stream.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************
                   MPEG Audio stream read module
 *******************************************************************/
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "bitstream.h"
#include "001.h"
#include "pes.h"
#include "memory_stream.h"
#include "memory_buffer.h"
#include "layer2.h"

#define AUDIO_STREAM_C
#include "audio_stream.h"

typedef struct {
	__int64 back_pts;
	__int64 face_pts;
} PTS_MAP;

typedef struct {

	__int64 filesize;
	__int64 sample;

	__int64 position;

	BITSTREAM *bs;
	int stream_id;

	int frequency;
	int channel;

	PTS_MAP *pts;
	
	MEMORY_BUFFER buffer;
} AUDIO_PS;

static int check_ps(unsigned char *buffer, int size);

static AUDIO_PS *open_ps(char *path);
static void close_ps(void *audio_stream);
static __int64 tell_ps(int stream);
static __int64 seek_ps(int stream, __int64 sample);
static int read_ps(int stream, void *buffer, int size);
static unsigned int next_sync_ps(int stream);
static void get_info_ps(int stream, AUDIO_INFO *info);

static int setup_format_ps(AUDIO_PS *ps);
static int set_start_pts_ps(AUDIO_PS *ps);
static int set_filesize_and_sample_ps(AUDIO_PS *ps);
static int set_unit_pts_ps(AUDIO_PS *ps, int unit);
static int read_pes_packet_ps(BITSTREAM *in, PES_PACKET *out);
static __int64 pts_to_sample(__int64 pts, int rate);
static __int64 sample_to_pts(__int64 sample, int rate);
static int count_audio_frame(PES_PACKET *packet);
static unsigned char *find_sync_current_ps_buffer(AUDIO_PS *ps);

AUDIO_STREAM *audio_stream_open(char *path)
{
	int fd;
	
	AUDIO_STREAM *r;

	int n;
	unsigned char buffer[512*1204];

	fd = _open(path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
	if(fd < 0){
		return NULL;
	}
	n = _read(fd, buffer, sizeof(buffer));
	_close(fd);
	
	r = (AUDIO_STREAM *)calloc(1, sizeof(AUDIO_STREAM));
	if(r == NULL){
		return NULL;
	}
	
	if(check_ps(buffer, n)){
		r->stream = (int)open_ps(path);
		r->close = close_ps;
		r->tell = tell_ps;
		r->seek = seek_ps;
		r->read = read_ps;
		r->next_sync = next_sync_ps;
		r->get_info = get_info_ps;
	}else{
		r->stream = 0;
	}

	if(r->stream == 0){
		free(r);
		r = NULL;
	}

	return r;
}

static int check_ps(unsigned char *buffer, int size)
{
	int n;
	unsigned char *pos;
	unsigned char *last;
	
	if( (buffer == NULL) || (size < 1) ){
		return 0;
	}

	pos = buffer;
	last = pos + size;

	while( (pos = find_next_001(pos, last)) != NULL ){
		if( (pos[3] & 0xe0) == 0xc0 ){
			n = (pos[4] << 8) + pos[5] + 6;
			if( (pos+n+4 < last) && (pos[n] == 0) && (pos[n+1] == 0) && ((pos[n+2] == 1) || (pos[n+2] == 0)) ){
				/*
				 *  packet_start_code + packet_length 偺愭偑
				 *  next_start_code_prefix 偐 padding 偱偁傟偽丄PS 偲敾掕
				 *  TMPGEnc 偺 VCD 僥儞僾儗乕僩偱嶌惉偝傟偨僗僩儕乕儉偱偼
				 *  Audio PES packet 偺師偺 3 byte 偑 start_code_prefix
				 *  偵側偭偰偄側偄偺偱 padding byte 傕擣幆偡傞傛偆偵廋惓
				 */
				return 1;
			}else{
				pos += 4;
			}
		}else{
			pos += 4;
		}
	}

	return 0;
}

static AUDIO_PS *open_ps(char *path)
{
	int i,n;
	AUDIO_PS *r;

	r = (AUDIO_PS *)calloc(1, sizeof(AUDIO_PS));
	if(r == NULL){
		return NULL;
	}

	r->bs = bs_open(path);
	if(r->bs == NULL){
		free(r);
		return NULL;
	}

	n = r->bs->mf->count(r->bs->mf);
	r->pts = (PTS_MAP *)malloc(sizeof(PTS_MAP)*(n+1));
	if(r->pts == NULL){
		bs_close(r->bs);
		free(r);
		return NULL;
	}
	for(i=0;i<n;i++){
		r->pts[i].back_pts = -1;
		r->pts[i].face_pts = 0;
	}

	if(!setup_format_ps(r)){
		free(r->pts);
		bs_close(r->bs);
		free(r);
		return NULL;
	}
	
	if(!set_start_pts_ps(r)){
		free(r->pts);
		bs_close(r->bs);
		free(r);
		return NULL;
	}

	if(!set_filesize_and_sample_ps(r)){
		free(r->pts);
		bs_close(r->bs);
		free(r);
		return NULL;
	}

	mb_init(&(r->buffer));
	seek_ps((int)r, 0);
	
	return r;
}

static void close_ps(void *audio_stream)
{
	AUDIO_STREAM *p;
	AUDIO_PS     *ps;

	if(audio_stream){
		p = (AUDIO_STREAM *)audio_stream;
		ps = (AUDIO_PS *)p->stream;
		bs_close(ps->bs);
		mb_release(&(ps->buffer));
		free(ps->pts);
		free(ps);
		free(p);
	}
}

static __int64 tell_ps(int stream)
{
	AUDIO_PS *ps;

	ps = (AUDIO_PS *)stream;

	return ps->position;
}

static __int64 seek_ps(int stream, __int64 sample)
{
	__int64 first, last, i, m, n;
	__int64 border;
	__int64 audio_pts;
	__int64 emergency;

	PTS_DTS pts_dts;
	PES_PACKET packet;

	AUDIO_PS *ps;

	int size;
	int find;
	int part;

	ps = (AUDIO_PS *)stream;

	mb_release(&(ps->buffer));

	init_pes_packet(&packet);

	find = 0;
	first = 0;
	last  = ps->filesize;

	size = ps->bs->mf->count(ps->bs->mf);
	part = 0;
	while(part<size-1){
		m = pts_to_sample(ps->pts[part+1].face_pts, ps->frequency);
		if(sample < m){
			last = ps->bs->mf->border(ps->bs->mf, part);
			break;
		}
		first = ps->bs->mf->border(ps->bs->mf, part);
		part += 1;
	}
	
	border = last;

	if(sample >= 1152){
		/* hack to cancel work area reset. */
		sample -= 1152;
	}

	emergency = 0;
	while(!find){
		i = first + (last - first)/2;

		if(last-first < 256){
			break;
		}

		bs_seek(ps->bs, i, 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){
					audio_pts = pts_dts.pts;
					break;
				}
			}
		}

		if( border < bs_tell(ps->bs) ){
			last = i;
			continue;
		}

		if( (packet.stream_id != ps->stream_id) || (pts_dts.pts < 0) ){
			break;
		}

		m = pts_to_sample(pts_dts.pts - ps->pts[part].back_pts + ps->pts[part].face_pts, ps->frequency);
		n = m + count_audio_frame(&packet) * 1152 + 1152;

		if( (m <= sample) && (sample < n) ){
			find = 1;
			break;
		}else if(sample < n){
			last = i;
		}else{
			first = bs_tell(ps->bs);
			emergency = first;
		}
	}

	if(!find){
		bs_seek(ps->bs, emergency, 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){
					break;
				}
			}
		}
		m = pts_to_sample(pts_dts.pts - ps->pts[part].back_pts + ps->pts[part].face_pts, ps->frequency);
	}

	ps->position = m;
	size = get_pes_packet_data_length(&packet);
	mb_append(&(ps->buffer), packet.data+(packet.size-size), size);

	release_pes_packet(&packet);

	return ps->position;
}

static int read_ps(int stream, void *buffer, int size)
{
	AUDIO_PS *ps;
	PES_PACKET packet;

	int n;
	int r;
	
	ps = (AUDIO_PS *)stream;

	r = 0;
	if( ps->buffer.pos+size <= ps->buffer.buffer+ps->buffer.size ){
		memcpy(buffer, ps->buffer.pos, size);
		ps->buffer.pos += size;
		r = size;
	}else{
		init_pes_packet(&packet);
		while(read_pes_packet_ps(ps->bs, &packet)){
			if(packet.stream_id == ps->stream_id){
				n = get_pes_packet_data_length(&packet);
				mb_append(&(ps->buffer), packet.data+(packet.size-n), n);
				if(ps->buffer.pos+size <= ps->buffer.buffer+ps->buffer.size){
					memcpy(buffer, ps->buffer.pos, size);
					ps->buffer.pos += size;
					r = size;
					break;
				}
			}
		}
		release_pes_packet(&packet);
	}
	
	if(r){
		ps->position += 1152;
	}else{
		memset(buffer, 0, size);
	}

	return r;
}

static unsigned int next_sync_ps(int stream)
{
	AUDIO_PS *ps;
	PES_PACKET packet;

	int n;
	unsigned int r;
	unsigned char *pos;

	ps = (AUDIO_PS *)stream;

	init_pes_packet(&packet);
	
	r = 0;
	while( (pos = find_sync_current_ps_buffer(ps)) == NULL ){
		n = 0;
		while(read_pes_packet_ps(ps->bs, &packet)){
			if(packet.stream_id == ps->stream_id){
				n = get_pes_packet_data_length(&packet);
				mb_append(&(ps->buffer), packet.data+(packet.size-n), n);
				break;
			}
		}
		if(n == 0){
			break;
		}
	}

	release_pes_packet(&packet);

	if( pos && (pos+3 < ps->buffer.buffer+ps->buffer.size) ){
		r = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3];
	}

	return r;
}

static void get_info_ps(int stream, AUDIO_INFO *info)
{
	AUDIO_PS *ps;

	ps = (AUDIO_PS *)stream;

	info->sample = ps->sample;
	info->frequency = ps->frequency;
	info->channel = ps->channel;
}

static int setup_format_ps(AUDIO_PS *ps)
{
	PES_PACKET packet;
	PES_STREAM_TYPE type;

	LAYER2_HEADER hd;
	
	unsigned char buffer[256*1024];
	unsigned char *p,*last;

	unsigned int sync;
	int n,pos;

	bs_seek(ps->bs, 0, SEEK_SET);

	init_pes_packet(&packet);

	ps->stream_id = 0;
	
	while(read_pes_packet_ps(ps->bs, &packet)){
		if(extract_pes_stream_type(&packet, &type)){
			if(type.type == PES_STREAM_TYPE_AUDIO){
				ps->stream_id = packet.stream_id;
				break;
			}
		}
		if(bs_tell(ps->bs) > 8*1024*1024){
			break;
		}

⌨️ 快捷键说明

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