📄 audio_stream.c
字号:
/*******************************************************************
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 + -