Commit e3d1cd8e authored by Måns Rullgård's avatar Måns Rullgård

PSM support in MPEG-PS demuxer.

Based on a patch by Leon Woestenberg <leonw at mailcan dot com>

Originally committed as revision 4093 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 09c3e44e
...@@ -91,6 +91,19 @@ typedef struct { ...@@ -91,6 +91,19 @@ typedef struct {
#define DTS_ID 0x8a #define DTS_ID 0x8a
#define LPCM_ID 0xa0 #define LPCM_ID 0xa0
#define STREAM_TYPE_VIDEO_MPEG1 0x01
#define STREAM_TYPE_VIDEO_MPEG2 0x02
#define STREAM_TYPE_AUDIO_MPEG1 0x03
#define STREAM_TYPE_AUDIO_MPEG2 0x04
#define STREAM_TYPE_PRIVATE_SECTION 0x05
#define STREAM_TYPE_PRIVATE_DATA 0x06
#define STREAM_TYPE_AUDIO_AAC 0x0f
#define STREAM_TYPE_VIDEO_MPEG4 0x10
#define STREAM_TYPE_VIDEO_H264 0x1b
#define STREAM_TYPE_AUDIO_AC3 0x81
#define STREAM_TYPE_AUDIO_DTS 0x8a
static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 }; static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };
#ifdef CONFIG_ENCODERS #ifdef CONFIG_ENCODERS
...@@ -1268,6 +1281,7 @@ static int mpegps_probe(AVProbeData *p) ...@@ -1268,6 +1281,7 @@ static int mpegps_probe(AVProbeData *p)
typedef struct MpegDemuxContext { typedef struct MpegDemuxContext {
int header_state; int header_state;
unsigned char psm_es_type[256];
} MpegDemuxContext; } MpegDemuxContext;
static int mpegps_read_header(AVFormatContext *s, static int mpegps_read_header(AVFormatContext *s,
...@@ -1358,6 +1372,40 @@ static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) ...@@ -1358,6 +1372,40 @@ static int find_prev_start_code(ByteIOContext *pb, int *size_ptr)
} }
#endif #endif
/**
* Extracts stream types from a program stream map
* According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35
*
* @return number of bytes occupied by PSM in the bitstream
*/
static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb)
{
int psm_length, ps_info_length, es_map_length;
psm_length = get_be16(pb);
get_byte(pb);
get_byte(pb);
ps_info_length = get_be16(pb);
/* skip program_stream_info */
url_fskip(pb, ps_info_length);
es_map_length = get_be16(pb);
/* at least one es available? */
while (es_map_length >= 4){
unsigned char type = get_byte(pb);
unsigned char es_id = get_byte(pb);
uint16_t es_info_length = get_be16(pb);
/* remember mapping from stream id to stream type */
m->psm_es_type[es_id] = type;
/* skip program_stream_info */
url_fskip(pb, es_info_length);
es_map_length -= 4 + es_info_length;
}
get_be32(pb); /* crc32 */
return 2 + psm_length;
}
/* read the next PES header. Return its position in ppos /* read the next PES header. Return its position in ppos
(if not NULL), and its start code, pts and dts. (if not NULL), and its start code, pts and dts.
*/ */
...@@ -1389,6 +1437,11 @@ static int mpegps_read_pes_header(AVFormatContext *s, ...@@ -1389,6 +1437,11 @@ static int mpegps_read_pes_header(AVFormatContext *s,
url_fskip(&s->pb, len); url_fskip(&s->pb, len);
goto redo; goto redo;
} }
if (startcode == PROGRAM_STREAM_MAP) {
mpegps_psm_parse(m, &s->pb);
goto redo;
}
/* find matching stream */ /* find matching stream */
if (!((startcode >= 0x1c0 && startcode <= 0x1df) || if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
(startcode >= 0x1e0 && startcode <= 0x1ef) || (startcode >= 0x1e0 && startcode <= 0x1ef) ||
...@@ -1463,7 +1516,7 @@ static int mpegps_read_pes_header(AVFormatContext *s, ...@@ -1463,7 +1516,7 @@ static int mpegps_read_pes_header(AVFormatContext *s,
else if( c!= 0xf ) else if( c!= 0xf )
goto redo; goto redo;
if (startcode == 0x1bd) { if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) {
if (len < 1) if (len < 1)
goto redo; goto redo;
startcode = get_byte(&s->pb); startcode = get_byte(&s->pb);
...@@ -1496,8 +1549,9 @@ static int mpegps_read_pes_header(AVFormatContext *s, ...@@ -1496,8 +1549,9 @@ static int mpegps_read_pes_header(AVFormatContext *s,
static int mpegps_read_packet(AVFormatContext *s, static int mpegps_read_packet(AVFormatContext *s,
AVPacket *pkt) AVPacket *pkt)
{ {
MpegDemuxContext *m = s->priv_data;
AVStream *st; AVStream *st;
int len, startcode, i, type, codec_id = 0; int len, startcode, i, type, codec_id = 0, es_type;
int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work
redo: redo:
...@@ -1511,7 +1565,35 @@ static int mpegps_read_packet(AVFormatContext *s, ...@@ -1511,7 +1565,35 @@ static int mpegps_read_packet(AVFormatContext *s,
if (st->id == startcode) if (st->id == startcode)
goto found; goto found;
} }
if (startcode >= 0x1e0 && startcode <= 0x1ef) {
es_type = m->psm_es_type[startcode & 0xff];
if(es_type > 0){
if(es_type == STREAM_TYPE_VIDEO_MPEG1){
codec_id = CODEC_ID_MPEG2VIDEO;
type = CODEC_TYPE_VIDEO;
} else if(es_type == STREAM_TYPE_VIDEO_MPEG2){
codec_id = CODEC_ID_MPEG2VIDEO;
type = CODEC_TYPE_VIDEO;
} else if(es_type == STREAM_TYPE_AUDIO_MPEG1 ||
es_type == STREAM_TYPE_AUDIO_MPEG2){
codec_id = CODEC_ID_MP3;
type = CODEC_TYPE_AUDIO;
} else if(es_type == STREAM_TYPE_AUDIO_AAC){
codec_id = CODEC_ID_AAC;
type = CODEC_TYPE_AUDIO;
} else if(es_type == STREAM_TYPE_VIDEO_MPEG4){
codec_id = CODEC_ID_MPEG4;
type = CODEC_TYPE_VIDEO;
} else if(es_type == STREAM_TYPE_VIDEO_H264){
codec_id = CODEC_ID_H264;
type = CODEC_TYPE_VIDEO;
} else if(es_type == STREAM_TYPE_AUDIO_AC3){
codec_id = CODEC_ID_AC3;
type = CODEC_TYPE_AUDIO;
} else {
goto skip;
}
} else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
type = CODEC_TYPE_VIDEO; type = CODEC_TYPE_VIDEO;
codec_id = CODEC_ID_MPEG2VIDEO; codec_id = CODEC_ID_MPEG2VIDEO;
} else if (startcode >= 0x1c0 && startcode <= 0x1df) { } else if (startcode >= 0x1c0 && startcode <= 0x1df) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment