/******************************************************************* PES treating module *******************************************************************/ #include #define PES_C #include "pes.h" typedef struct { int pes_scrambling_control; int pes_priority; int data_alignment_indicator; int copyright; int original_or_copy; int pts_dts_flag; int escr_flag; int es_rate_flag; int dsm_trick_mode_flag; int additional_copy_info_flag; int pes_crc_flag; int pes_extention_flag; int pes_header_data_length; }STANDARD_PES_HEADER; int read_pes_packet(BITSTREAM *in, PES_PACKET *out); unsigned int get_pes_packet_data_length(PES_PACKET *p); int extract_pes_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type); int extract_pes_packet_data(PES_PACKET *p, unsigned char *data, unsigned int *length); static unsigned int private_1_stream_data_length(PES_PACKET *p); static unsigned int audio_stream_data_length(PES_PACKET *p); static unsigned int video_stream_data_length(PES_PACKET *p); static int private_1_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type); static int audio_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type); static int video_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type); static int extract_standard_pes_header(PES_PACKET *p, STANDARD_PES_HEADER *sph); int read_pes_packet(BITSTREAM *in, PES_PACKET *out) { int code, n, m; do{ if(! bs_next_packet_prefix(in)){ return 0; } bs_erase_bits(in, 24); code = bs_get_bits(in, 8); }while(code < 0xbc); out->stream_id = code; n = bs_get_bits(in, 16); out->data_length = 0; while(n){ m = bs_read(in, out->data+out->data_length, n); n -= m; out->data_length += m; if(m == 0){ return 0; } } return out->data_length; } unsigned int get_pes_packet_data_length(PES_PACKET *p) { if(p->stream_id == 0xbd){ return private_1_stream_data_length(p); }else if(p->stream_id >= 0xc0 && p->stream_id <= 0xdf){ return audio_stream_data_length(p); }else if(p->stream_id >= 0xe0 && p->stream_id <= 0xef){ return video_stream_data_length(p); }else{ return 0; } } int extract_pes_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type) { if(p->stream_id == 0xbd){ return private_1_stream_type(p, type); }else if(p->stream_id >= 0xc0 && p->stream_id <= 0xdf){ return audio_stream_type(p, type); }else if(p->stream_id >= 0xe0 && p->stream_id <= 0xef){ return video_stream_type(p, type); }else{ return 0; } } int extract_pes_packet_data(PES_PACKET *p, unsigned char *data, unsigned int *length) { if((data == NULL) || (length == NULL) ){ return 0; } *length = get_pes_packet_data_length(p); memcpy(data, p->data+(p->data_length-(*length)), *length); return *length; } static unsigned int private_1_stream_data_length(PES_PACKET *p) { unsigned int r; unsigned char *w; STANDARD_PES_HEADER sph; extract_standard_pes_header(p, &sph); w = p->data + sph.pes_header_data_length; r = 0; if( (w[0] >= 0x80) && (w[0] <= 0x8f) ){ /* AC3 stream */ r = p->data_length - sph.pes_header_data_length - 4; }else{ /* unknown stream */ } return r; } static unsigned int audio_stream_data_length(PES_PACKET *p) { STANDARD_PES_HEADER sph; extract_standard_pes_header(p, &sph); return p->data_length - sph.pes_header_data_length; } static unsigned int video_stream_data_length(PES_PACKET *p) { STANDARD_PES_HEADER sph; extract_standard_pes_header(p, &sph); return p->data_length - sph.pes_header_data_length; } static int private_1_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type) { unsigned char *w; STANDARD_PES_HEADER sph; extract_standard_pes_header(p, &sph); w = p->data + sph.pes_header_data_length; if( (w[0] >= 0x80) && (w[0] <= 0x8f) ){ type->type = PES_STREAM_TYPE_AC3; type->id = w[0] & 0x0f; return 1; }else{ type->type = PES_STREAM_TYPE_UNKNOWN; type->id = 0; return 0; } } static int audio_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type) { type->type = PES_STREAM_TYPE_AUDIO; type->id = p->stream_id & 0x1f; return 1; } static int video_stream_type(PES_PACKET *p, PES_STREAM_TYPE *type) { type->type = PES_STREAM_TYPE_VIDEO; type->id = p->stream_id & 0x0f; return 1; } static int extract_standard_pes_header(PES_PACKET *p, STANDARD_PES_HEADER *sph) { if( (p == NULL) || (sph == NULL) ){ return 0; } sph->pes_scrambling_control = (p->data[0] & 0x30) >> 4; sph->pes_priority = (p->data[0] & 0x08) >> 3; sph->data_alignment_indicator = (p->data[0] & 0x04) >> 2; sph->copyright = (p->data[0] & 0x02) >> 1; sph->original_or_copy = (p->data[0] & 0x01); sph->pts_dts_flag = (p->data[1] & 0xC0) >> 6; sph->escr_flag = (p->data[1] & 0x20) >> 5; sph->es_rate_flag = (p->data[1] & 0x10) >> 4; sph->dsm_trick_mode_flag = (p->data[1] & 0x08) >> 3; sph->additional_copy_info_flag = (p->data[1] & 0x04) >> 2; sph->pes_crc_flag = (p->data[1] & 0x02) >> 1; sph->pes_extention_flag = (p->data[1] & 0x01); sph->pes_header_data_length = p->data[2] + 3; return 1; }