summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/mplayer.110
-rw-r--r--cfg-common-opts.h1
-rw-r--r--cfg-common.h1
-rw-r--r--libmpdemux/demux_ts.c69
4 files changed, 81 insertions, 0 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index c19c20fe63..9b8f8a3935 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -1166,6 +1166,16 @@ When playing an MPEG-TS stream, MPlayer/\:MEncoder will use the first program
(if present) with the chosen audio stream.
.
.TP
+.B \-ausid <ID> (also see \-alang)
+Select audio substream channel.
+Currently the valid range is 0x55..0x75 and applies only to MPEG-TS when handled
+by the native demuxer (not by libavformat).
+The format type may not be correctly identified because of how this information
+(or lack thereof) is embedded in the stream, but it will demux correctly the
+audio streams when multiple substreams are present.
+MPlayer prints the available substream IDs when run with \-identify.
+.
+.TP
.B \-alang <language code[,language code,...]> (also see \-aid)
Specify a priority list of audio languages to use.
Different container formats employ different language codes.
diff --git a/cfg-common-opts.h b/cfg-common-opts.h
index f9badb64b5..65d7a413ea 100644
--- a/cfg-common-opts.h
+++ b/cfg-common-opts.h
@@ -123,6 +123,7 @@
// select audio/video/subtitle stream
{"aid", &audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 8190, NULL},
+ {"ausid", &audio_substream_id, CONF_TYPE_INT, 0, 0, 0, NULL},
{"vid", &video_id, CONF_TYPE_INT, CONF_RANGE, 0, 8190, NULL},
{"sid", &dvdsub_id, CONF_TYPE_INT, CONF_RANGE, 0, 8190, NULL},
{"novideo", &video_id, CONF_TYPE_FLAG, 0, -1, -2, NULL},
diff --git a/cfg-common.h b/cfg-common.h
index c69deb2cbf..9a4e258f35 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -53,6 +53,7 @@ extern int demuxer_type, audio_demuxer_type, sub_demuxer_type;
extern int ts_prog;
extern int ts_keep_broken;
extern off_t ts_probe;
+extern int audio_substream_id;
extern off_t ps_probe;
#include "stream/tv.h"
diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c
index c0924d9ecf..3de0ce404b 100644
--- a/libmpdemux/demux_ts.c
+++ b/libmpdemux/demux_ts.c
@@ -59,6 +59,7 @@
int ts_prog;
int ts_keep_broken=0;
off_t ts_probe = 0;
+int audio_substream_id = -1;
extern char *dvdsub_lang, *audio_lang; //for -alang
typedef enum
@@ -1280,6 +1281,67 @@ static int mp4_parse_sl_packet(pmt_t *pmt, uint8_t *buf, uint16_t packet_len, in
return m;
}
+//this function parses the extension fields in the PES header and returns the substream_id, or -1 in case of errors
+static int parse_pes_extension_fields(unsigned char *p, int pkt_len)
+{
+ int skip;
+ unsigned char flags;
+
+ if(!(p[7] & 0x1)) //no extension_field
+ return -1;
+ skip = 9;
+ if(p[7] & 0x80)
+ {
+ skip += 5;
+ if(p[7] & 0x40)
+ skip += 5;
+ }
+ if(p[7] & 0x20) //escr_flag
+ skip += 6;
+ if(p[7] & 0x10) //es_rate_flag
+ skip += 3;
+ if(p[7] & 0x08)//dsm_trick_mode is unsupported, skip
+ {
+ skip = 0;//don't let's parse the extension fields
+ }
+ if(p[7] & 0x04) //additional_copy_info
+ skip += 1;
+ if(p[7] & 0x02) //pes_crc_flag
+ skip += 2;
+ if(skip >= pkt_len) //too few bytes
+ return -1;
+ flags = p[skip];
+ skip++;
+ if(flags & 0x80) //pes_private_data_flag
+ skip += 16;
+ if(skip >= pkt_len)
+ return -1;
+ if(flags & 0x40) //pack_header_field_flag
+ {
+ unsigned char l = p[skip];
+ skip += l;
+ }
+ if(flags & 0x20) //program_packet_sequence_counter
+ skip += 2;
+ if(flags & 0x10) //p_std
+ skip += 2;
+ if(skip >= pkt_len)
+ return -1;
+ if(flags & 0x01) //finally the long desired pes_extension2
+ {
+ unsigned char l = p[skip]; //ext2 flag+len
+ skip++;
+ if((l == 0x81) && (skip < pkt_len))
+ {
+ int ssid = p[skip];
+ mp_msg(MSGT_IDENTIFY, MSGL_V, "SUBSTREAM_ID=%d (0x%02X)\n", ssid, ssid);
+ return ssid;
+ }
+ }
+
+ return -1;
+}
+
static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es, int32_t type_from_pmt, pmt_t *pmt, int pid)
{
unsigned char *p;
@@ -1343,6 +1405,13 @@ static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es,
mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len);
return 0;
}
+
+ if(stream_id==0xfd)
+ {
+ int ssid = parse_pes_extension_fields(p, pkt_len);
+ if((audio_substream_id!=-1) && (ssid != audio_substream_id))
+ return 0;
+ }
p += header_len + 9;
packet_len -= header_len + 3;