changeset 28210:6fc5386a8b6b

added support for manual audio substream selection out of 0xFD PES streams (Blueray, multistream in the same pid)
author nicodvb
date Sun, 04 Jan 2009 13:12:51 +0000
parents 6e8d3a955f64
children 794c9edaad54
files DOCS/man/en/mplayer.1 cfg-common-opts.h cfg-common.h libmpdemux/demux_ts.c
diffstat 4 files changed, 81 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Sun Jan 04 13:08:13 2009 +0000
+++ b/DOCS/man/en/mplayer.1	Sun Jan 04 13:12:51 2009 +0000
@@ -1166,6 +1166,16 @@
 (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.
--- a/cfg-common-opts.h	Sun Jan 04 13:08:13 2009 +0000
+++ b/cfg-common-opts.h	Sun Jan 04 13:12:51 2009 +0000
@@ -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},
--- a/cfg-common.h	Sun Jan 04 13:08:13 2009 +0000
+++ b/cfg-common.h	Sun Jan 04 13:12:51 2009 +0000
@@ -53,6 +53,7 @@
 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"
--- a/libmpdemux/demux_ts.c	Sun Jan 04 13:08:13 2009 +0000
+++ b/libmpdemux/demux_ts.c	Sun Jan 04 13:12:51 2009 +0000
@@ -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 @@
 	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 @@
 		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;