读取TS流文件并将其中的音频单独摘取出来的功能实现代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int boolean;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#define FALSE 0
#define TRUE 1
#define MPEGTS_NORMAL_TS_PACKETSIZE 188
#define MAX_AUDIO_STREAM_NUM 256
typedef struct tagAudioStream
{
FILE *fp;
boolean started;
uint16 pid;
}AudioStream;
static AudioStream audio_stream[MAX_AUDIO_STREAM_NUM] = {0};
void init_audio_stream()
{
memset(audio_stream, 0, sizeof(AudioStream)*MAX_AUDIO_STREAM_NUM);
}
void uninit_audio_stream()
{
int i=0;
for(i=0; i<MAX_AUDIO_STREAM_NUM; i++)
{
if(audio_stream[i].fp != NULL)
fclose(audio_stream[i].fp);
}
}
AudioStream* new_stream(uint16 pid, boolean started)
{
int i=0;
for(i=0; i<MAX_AUDIO_STREAM_NUM; i++)
{
if(audio_stream[i].pid == pid)
{
if(audio_stream[i].started)
{
return audio_stream+i;
}
else if (started)
{
char name[32] = {0};
sprintf(name, "%d.mp3", pid);
audio_stream[i].fp = fopen(name, "wb");
audio_stream[i].started = TRUE;
return audio_stream+i;
}
return NULL;
}
}
for(i=0; i<MAX_AUDIO_STREAM_NUM; i++)
{
if(audio_stream[i].pid == 0)
{
audio_stream[i].fp = NULL;
audio_stream[i].pid = pid;
if(started)
{
audio_stream[i].started = TRUE;
return audio_stream+i;
}
else
{
audio_stream[i].started = FALSE;
return NULL;
}
}
}
return NULL;
}
void write_audio_stream(AudioStream *audio_stream, uint8* data, int data_len)
{
if(audio_stream == NULL || data == NULL || data_len == 0)
return;
if(audio_stream->fp)
{
fwrite(data, 1, data_len, audio_stream->fp);
}
}
static int gst_pes_filter_parse (uint8 *in_data, int data_len)
{
uint8 *data = in_data;
int datalen = data_len;
boolean have_size = FALSE;
/* get start code */
if((data[0] != 0x00) || (data[1] != 0x00) || (data[2] != 0x01) || (data[3] != 0xC0))
return 0;
/* skip start code and length */
data += 6;
datalen -= 6;
/* stuffing bits, first two bits are '10' for mpeg2 pes so this code is
* not triggered. */
while (TRUE)
{
if (*data != 0xff)
break;
datalen--;
}
/* STD buffer size, never for mpeg2 */
if ((*data & 0xc0) == 0x40)
{
data+=2;
datalen -= 2;
}
/* PTS but no DTS, never for mpeg2 */
if ((*data & 0xf0) == 0x20)
{
data+=5;
datalen -= 5;
}
/* PTS and DTS, never for mpeg2 */
else if ((*data & 0xf0) == 0x30)
{
data +=10;
datalen -= 10;
}
else if ((*data & 0xc0) == 0x80)
{
/* mpeg2 case */
uint8 flags;
uint8 header_data_length = 0;
flags = *data++;
flags = *data++;
/* 8: PES_header_data_length */
header_data_length = *data++;
datalen -= 3;
/* only DTS: this is invalid */
if ((flags & 0xc0) == 0x40)
return 0;
/* check for PTS */
if ((flags & 0x80))
{
header_data_length -= 5;
datalen -= 5;
}
/* check for DTS */
if ((flags & 0x40))
{
header_data_length -= 5;
datalen -= 5;
}
/* ESCR_flag */
if ((flags & 0x20))
{
data += 6;
header_data_length -= 6;
datalen -= 6;
}
/* ES_rate_flag */
if ((flags & 0x10))
{
data += 3;
header_data_length -= 3;
datalen -= 3;
}
/* DSM_trick_mode_flag */
if ((flags & 0x08))
{
data += 1;
header_data_length -= 1;
datalen -= 1;
}
/* PES_extension_flag */
if ((flags & 0x01))
{
flags = *data++;
header_data_length -= 1;
datalen -= 1;
if ((flags & 0x80))
{
data += 16;
header_data_length -= 16;
datalen -= 16;
}
/* pack_header_field_flag */
if ((flags & 0x40))
{
uint8 pack_field_length = *data;
data += pack_field_length + 1;
header_data_length -= pack_field_length + 1;
datalen -= pack_field_length + 1;
}
/* program_packet_sequence_counter_flag */
if ((flags & 0x20))
{
data += 2;
header_data_length -= 2;
datalen -= 2;
}
/* P-STD_buffer_flag */
if ((flags & 0x10))
{
data += 2;
header_data_length -= 2;
datalen -= 2;
}
/* PES_extension_flag_2 */
if ((flags & 0x01))
{
uint8 PES_extension_field_length = *data++;
data += PES_extension_field_length & 0x7f;
header_data_length -= (PES_extension_field_length & 0x7f) + 1;
datalen -= (PES_extension_field_length & 0x7f) + 1;
}
}
/* calculate the amount of real data in this PES packet */
data += header_data_length;
datalen -= header_data_length;
}
else if (*data == 0x0f)
{
/* Not sure what this clause is for */
data++;
datalen--;
}
else
{
return 0;
}
return datalen;
}
void parse_ts_packet(uint8 *in_data)
{
uint16 PID;
boolean payload_unit_start_indicator;
const uint8 *data = in_data;
uint32 datalen = MPEGTS_NORMAL_TS_PACKETSIZE;
AudioStream *audio_stream = NULL;
PID = ((data[1] & 0x1f) << 8) | data[2];
if(PID == 0x1FFF)
{
return;
}
payload_unit_start_indicator = (data[1] & 0x40) == 0x40;
if(payload_unit_start_indicator)
{
int left_len = gst_pes_filter_parse(data+0x4, 0xB8);
if(left_len)
{
audio_stream = new_stream(PID, payload_unit_start_indicator);
write_audio_stream(audio_stream, data+MPEGTS_NORMAL_TS_PACKETSIZE-left_len, left_len);
}
}
else
{
audio_stream = new_stream(PID, FALSE);
write_audio_stream(audio_stream, data+0x4, 0xB8);
}
}
int main()
{
uint8 buffer[MPEGTS_NORMAL_TS_PACKETSIZE] = {0};
FILE *fp = NULL;
fp = fopen("d:\\wang.ts", "rb");
if(fp == NULL)
{
return 0;
}
init_audio_stream();
while(MPEGTS_NORMAL_TS_PACKETSIZE == fread(buffer, 1, MPEGTS_NORMAL_TS_PACKETSIZE, fp))
{
parse_ts_packet(buffer);
}
uninit_audio_stream();
fclose(fp);
return 0;
}
(carlsonlee_freec) |