diff options
Diffstat (limited to 'src')
28 files changed, 687 insertions, 57 deletions
diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h index e0fb6c33b..a7ba002ab 100644 --- a/src/demuxers/demux.h +++ b/src/demuxers/demux.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux.h,v 1.25 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux.h,v 1.26 2002/11/28 10:21:05 petli Exp $ */ #ifndef HAVE_DEMUX_H @@ -32,7 +32,7 @@ #include "input_plugin.h" #endif -#define DEMUXER_PLUGIN_IFACE_VERSION 17 +#define DEMUXER_PLUGIN_IFACE_VERSION 18 #define DEMUX_OK 0 #define DEMUX_FINISHED 1 @@ -168,10 +168,45 @@ struct demux_plugin_s { vo_frame_t *frame); /* + * return capabilities of demuxed stream + */ + + uint32_t (*get_capabilities) (demux_plugin_t *this); + + /* + * request optional data from input plugin. + */ + int (*get_optional_data) (demux_plugin_t *this, void *data, int data_type); + + /* * "backwards" link to plugin class */ demux_class_t *demux_class; } ; +/* + * possible capabilites a demux plugin can have: + */ +#define DEMUX_CAP_NOCAP 0x00000000 + +/* + * DEMUX_CAP_AUDIOLANG: + * DEMUX_CAP_SPULANG: + * demux plugin knows something about audio/spu languages, + * e.g. knows that audio stream #0 is english, + * audio stream #1 is german, ... Same bits as INPUT + * capabilities . + */ + +#define DEMUX_CAP_AUDIOLANG 0x00000008 +#define DEMUX_CAP_SPULANG 0x00000010 + + +#define DEMUX_OPTIONAL_UNSUPPORTED 0 +#define DEMUX_OPTIONAL_SUCCESS 1 + +#define DEMUX_OPTIONAL_DATA_AUDIOLANG 2 +#define DEMUX_OPTIONAL_DATA_SPULANG 3 + #endif diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c index e6cc0f0d5..e0dacb8e6 100644 --- a/src/demuxers/demux_aiff.c +++ b/src/demuxers/demux_aiff.c @@ -19,7 +19,7 @@ * * AIFF File Demuxer by Mike Melanson (melanson@pcisys.net) * - * $Id: demux_aiff.c,v 1.17 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_aiff.c,v 1.18 2002/11/28 10:21:05 petli Exp $ * */ @@ -322,6 +322,17 @@ static int demux_aiff_get_stream_length (demux_plugin_t *this_gen) { return this->running_time; } +static uint32_t demux_aiff_get_capabilities(demux_plugin_t *this_gen) +{ + return DEMUX_CAP_NOCAP; +} + +static int demux_aiff_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) +{ + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -345,6 +356,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_aiff_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_aiff_get_capabilities; + this->demux_plugin.get_optional_data = demux_aiff_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -456,6 +469,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "aiff", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "aiff", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index ca3957e55..2bd3f1f05 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_asf.c,v 1.82 2002/11/20 20:22:52 tmattern Exp $ + * $Id: demux_asf.c,v 1.83 2002/11/28 10:21:05 petli Exp $ * * demultiplexer for asf streams * @@ -1316,6 +1316,15 @@ static int demux_asf_get_stream_length (demux_plugin_t *this_gen) { return this->length; } +static uint32_t demux_asf_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_asf_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { @@ -1400,6 +1409,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.get_stream_length = demux_asf_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_asf_get_capabilities; + this->demux_plugin.get_optional_data = demux_asf_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -1457,6 +1468,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "asf", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "asf", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 0f577dd41..69b222ae5 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_avi.c,v 1.133 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_avi.c,v 1.134 2002/11/28 10:21:05 petli Exp $ * * demultiplexer for avi streams * @@ -1470,6 +1470,15 @@ static int demux_avi_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_avi_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_avi_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -1493,6 +1502,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_avi_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_avi_get_capabilities; + this->demux_plugin.get_optional_data = demux_avi_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -1615,6 +1626,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "avi", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "avi", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_cda.c b/src/demuxers/demux_cda.c index 68a2b6290..b555f11b9 100644 --- a/src/demuxers/demux_cda.c +++ b/src/demuxers/demux_cda.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_cda.c,v 1.34 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_cda.c,v 1.35 2002/11/28 10:21:05 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -169,6 +169,15 @@ static int demux_cda_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_cda_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_cda_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -192,6 +201,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_cda_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_cda_get_capabilities; + this->demux_plugin.get_optional_data = demux_cda_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -283,6 +294,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "cda", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "cda", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_eawve.c b/src/demuxers/demux_eawve.c index 2ac79b7cd..443c06bca 100644 --- a/src/demuxers/demux_eawve.c +++ b/src/demuxers/demux_eawve.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_eawve.c,v 1.8 2002/11/26 18:51:32 komadori Exp $ + * $Id: demux_eawve.c,v 1.9 2002/11/28 10:21:05 petli Exp $ * * demux_eawve.c, Demuxer plugin for Electronic Arts' WVE file format * @@ -353,6 +353,15 @@ static int demux_eawve_get_stream_length(demux_eawve_t *this) return this->num_samples / 22050; } +static uint32_t demux_eawve_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_eawve_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t* open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -371,6 +380,8 @@ static demux_plugin_t* open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = (void*)demux_eawve_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_eawve_get_capabilities; + this->demux_plugin.get_optional_data = demux_eawve_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -467,6 +478,6 @@ static void *init_plugin (xine_t *xine, void *data) } plugin_info_t xine_plugin_info[] = { - { PLUGIN_DEMUX, 17, "wve", XINE_VERSION_CODE, NULL, (void*)init_plugin}, + { PLUGIN_DEMUX, 18, "wve", XINE_VERSION_CODE, NULL, (void*)init_plugin}, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index 0e1f5297d..34dd9e79e 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_elem.c,v 1.62 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_elem.c,v 1.63 2002/11/28 10:21:06 petli Exp $ * * demultiplexer for elementary mpeg streams * @@ -185,6 +185,15 @@ static int demux_mpeg_elem_get_stream_length(demux_plugin_t *this_gen) { return 0 ; /*FIXME: implement */ } +static uint32_t demux_mpeg_elem_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_mpeg_elem_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -203,6 +212,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_mpeg_elem_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_mpeg_elem_get_capabilities; + this->demux_plugin.get_optional_data = demux_mpeg_elem_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -340,6 +351,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "elem", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "elem", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index 23befca4c..8eef08e4b 100644 --- a/src/demuxers/demux_film.c +++ b/src/demuxers/demux_film.c @@ -21,7 +21,7 @@ * For more information on the FILM file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_film.c,v 1.44 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_film.c,v 1.45 2002/11/28 10:21:06 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -639,6 +639,15 @@ static int demux_film_get_stream_length (demux_plugin_t *this_gen) { return this->total_time; } +static uint32_t demux_film_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_film_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -662,6 +671,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_film_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_film_get_capabilities; + this->demux_plugin.get_optional_data = demux_film_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -790,6 +801,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "film", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "film", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c index 661319928..be4aeed61 100644 --- a/src/demuxers/demux_fli.c +++ b/src/demuxers/demux_fli.c @@ -22,7 +22,7 @@ * avoid while programming a FLI decoder, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_fli.c,v 1.27 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_fli.c,v 1.28 2002/11/28 10:21:06 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -269,6 +269,15 @@ static int demux_fli_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_fli_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_fli_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -292,6 +301,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_fli_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_fli_get_capabilities; + this->demux_plugin.get_optional_data = demux_fli_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -405,6 +416,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "fli", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "fli", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_idcin.c b/src/demuxers/demux_idcin.c index 07b9878a6..d3623d023 100644 --- a/src/demuxers/demux_idcin.c +++ b/src/demuxers/demux_idcin.c @@ -63,7 +63,7 @@ * - if any bytes exceed 63, do not shift the bytes at all before * transmitting them to the video decoder * - * $Id: demux_idcin.c,v 1.28 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_idcin.c,v 1.29 2002/11/28 10:21:06 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -444,6 +444,15 @@ static int demux_idcin_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_idcin_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_idcin_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -467,6 +476,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_idcin_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_idcin_get_capabilities; + this->demux_plugin.get_optional_data = demux_idcin_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -579,6 +590,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "idcin", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "idcin", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 014061329..e6c29ff7b 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg.c,v 1.97 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_mpeg.c,v 1.98 2002/11/28 10:21:06 petli Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -883,6 +883,15 @@ static int demux_mpeg_get_stream_length (demux_plugin_t *this_gen) { } +static uint32_t demux_mpeg_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_mpeg_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { demux_mpeg_t *this; @@ -899,6 +908,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_mpeg_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_mpeg_get_capabilities; + this->demux_plugin.get_optional_data = demux_mpeg_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -1130,6 +1141,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "mpeg", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "mpeg", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 9e30a0187..5b051cca1 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg_block.c,v 1.145 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_mpeg_block.c,v 1.146 2002/11/28 10:21:06 petli Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -965,6 +965,14 @@ static int demux_mpeg_block_get_video_frame (demux_plugin_t *this_gen, return 0; } +static uint32_t demux_mpeg_block_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_mpeg_block_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -990,6 +998,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_mpeg_block_get_stream_length; this->demux_plugin.get_video_frame = demux_mpeg_block_get_video_frame; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_mpeg_block_get_capabilities; + this->demux_plugin.get_optional_data = demux_mpeg_block_get_optional_data; this->demux_plugin.demux_class = class_gen; this->scratch = xine_xmalloc_aligned (512, 4096, (void**) &this->scratch_base); @@ -1168,6 +1178,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "mpeg_block", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "mpeg_block", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index fe225e4ef..d49e3aeeb 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpgaudio.c,v 1.81 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_mpgaudio.c,v 1.82 2002/11/28 10:21:06 petli Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -457,6 +457,15 @@ static int demux_mpgaudio_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_mpgaudio_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_mpgaudio_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -571,6 +580,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_status = demux_mpgaudio_get_status; this->demux_plugin.get_stream_length = demux_mpgaudio_get_stream_length; this->demux_plugin.get_video_frame = NULL; + this->demux_plugin.get_capabilities = demux_mpgaudio_get_capabilities; + this->demux_plugin.get_optional_data = demux_mpgaudio_get_optional_data; this->demux_plugin.demux_class = class_gen; this->input = input; @@ -642,6 +653,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "mp3", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "mp3", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 05d9e89c2..d83361c4b 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ogg.c,v 1.53 2002/11/20 11:57:40 mroi Exp $ + * $Id: demux_ogg.c,v 1.54 2002/11/28 10:21:06 petli Exp $ * * demultiplexer for ogg streams * @@ -921,6 +921,15 @@ static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_ogg_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_ogg_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { @@ -1002,6 +1011,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.get_stream_length = demux_ogg_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_ogg_get_capabilities; + this->demux_plugin.get_optional_data = demux_ogg_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -1062,6 +1073,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "ogg", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "ogg", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index 8aa29878f..c76d8909a 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -30,7 +30,7 @@ * build_frame_table * free_qt_info * - * $Id: demux_qt.c,v 1.120 2002/11/25 02:28:35 tmmm Exp $ + * $Id: demux_qt.c,v 1.121 2002/11/28 10:21:06 petli Exp $ * */ @@ -2112,6 +2112,15 @@ static int demux_qt_get_stream_length (demux_plugin_t *this_gen) { return (this->qt->duration / this->qt->timescale); } +static uint32_t demux_qt_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_qt_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -2140,6 +2149,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_qt_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_qt_get_capabilities; + this->demux_plugin.get_optional_data = demux_qt_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -2286,6 +2297,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "quicktime", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "quicktime", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 934c092ce..f2bcc4588 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -21,7 +21,7 @@ * For more information regarding the Real file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_real.c,v 1.17 2002/11/26 00:37:28 guenter Exp $ + * $Id: demux_real.c,v 1.18 2002/11/28 10:21:07 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -1023,6 +1023,15 @@ static int demux_real_get_stream_length (demux_plugin_t *this_gen) { return this->duration / 1000; } +static uint32_t demux_real_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_real_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -1126,6 +1135,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_real_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_real_get_capabilities; + this->demux_plugin.get_optional_data = demux_real_get_optional_data; this->demux_plugin.demux_class = class_gen; strncpy (this->last_mrl, input->get_mrl (input), 1024); @@ -1183,6 +1194,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "real", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "real", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index 46a98c3ac..6f97fb81a 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -19,7 +19,7 @@ * * RealAudio File Demuxer by Mike Melanson (melanson@pcisys.net) * - * $Id: demux_realaudio.c,v 1.5 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_realaudio.c,v 1.6 2002/11/28 10:21:07 petli Exp $ * */ @@ -267,6 +267,15 @@ static int demux_ra_get_stream_length (demux_plugin_t *this_gen) { return (int)(this->data_size / this->wave.nAvgBytesPerSec); } +static uint32_t demux_ra_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_ra_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -290,6 +299,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_ra_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_ra_get_capabilities; + this->demux_plugin.get_optional_data = demux_ra_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -400,7 +411,7 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "realaudio", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "realaudio", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c index 131cd200a..016503344 100644 --- a/src/demuxers/demux_roq.c +++ b/src/demuxers/demux_roq.c @@ -21,7 +21,7 @@ * For more information regarding the RoQ file format, visit: * http://www.csse.monash.edu.au/~timf/ * - * $Id: demux_roq.c,v 1.30 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_roq.c,v 1.31 2002/11/28 10:21:07 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -390,6 +390,15 @@ static int demux_roq_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_roq_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_roq_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -413,6 +422,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_roq_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_roq_get_capabilities; + this->demux_plugin.get_optional_data = demux_roq_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -521,6 +532,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "roq", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "roq", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c index 409825fab..fcda4a928 100644 --- a/src/demuxers/demux_smjpeg.c +++ b/src/demuxers/demux_smjpeg.c @@ -21,7 +21,7 @@ * For more information on the SMJPEG file format, visit: * http://www.lokigames.com/development/smjpeg.php3 * - * $Id: demux_smjpeg.c,v 1.26 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_smjpeg.c,v 1.27 2002/11/28 10:21:07 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -401,6 +401,15 @@ static int demux_smjpeg_get_stream_length (demux_plugin_t *this_gen) { return this->duration / 1000; } +static uint32_t demux_smjpeg_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_smjpeg_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -424,6 +433,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_smjpeg_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_smjpeg_get_capabilities; + this->demux_plugin.get_optional_data = demux_smjpeg_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -549,6 +560,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "smjpeg", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "smjpeg", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_snd.c b/src/demuxers/demux_snd.c index 90a4fd961..f08cdf70f 100644 --- a/src/demuxers/demux_snd.c +++ b/src/demuxers/demux_snd.c @@ -19,7 +19,7 @@ * * SND/AU File Demuxer by Mike Melanson (melanson@pcisys.net) * - * $Id: demux_snd.c,v 1.18 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_snd.c,v 1.19 2002/11/28 10:21:07 petli Exp $ * */ @@ -305,6 +305,15 @@ static int demux_snd_get_stream_length (demux_plugin_t *this_gen) { return this->running_time; } +static uint32_t demux_snd_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_snd_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -328,6 +337,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_snd_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_snd_get_capabilities; + this->demux_plugin.get_optional_data = demux_snd_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -440,6 +451,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "snd", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "snd", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 7464cc5bd..c6962d0bd 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.66 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_ts.c,v 1.67 2002/11/28 10:21:07 petli Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -35,6 +35,9 @@ * Date Author * ---- ------ * + * 25-Nov-2002 Peter Liljenberg + * - Added DVBSUB support + * * 07-Nov-2992 Howdy Pierce * - various bugfixes * @@ -75,6 +78,52 @@ * TODO: do without memcpys, preview buffers */ + +/** HOW TO IMPLEMENT A DVBSUB DECODER. + * + * The DVBSUB protocol is specified in ETSI EN 300 743. It can be + * downloaded for free (registration required, though) from + * www.etsi.org. + * + * The spu_decoder should handle the packet type BUF_SPU_DVB. + * + * BUF_SPU_DVBSUB packets without the flag BUF_FLAG_SPECIAL contain + * the payload of the PES packets carrying DVBSUB data. Since the + * payload can be broken up over several buf_element_t and the DVBSUB + * is PES oriented, the CCCC field (low 16 bits) is used to convey the + * packet boundaries to the decoder: + * + * + For the first buffer of a packet, buf->content points to the + * first byte of the PES payload. CCCC is set to the length of the + * payload. The decoder can use this value to determine when a + * complete PES packet has been collected. + * + * + For the following buffers of the PES packet, CCCC is 0. + * + * The decoder can either use this information to reconstruct the PES + * payload, or ignore it and implement a parser that handles the + * irregularites at the start and end of PES packets. + * + * In any case buf->pts is always set to the PTS of the PES packet. + * + * + * BUF_SPU_DVB with BUF_FLAG_SPECIAL set contains no payload, and is + * used to pass control information to the decoder. + * + * If decoder_info[1] == BUF_SPECIAL_SPU_DVB_DESCRIPTOR then + * decoder_info[2] either points to a spu_dvb_descriptor_t or is 0. + * + * If it is 0, the user has disabled the subtitling, or has selected a + * channel that is not present in the stream. The decoder should + * remove any visible subtitling. + * + * If it is a pointer, the decoder should reset itself and start + * extracting the subtitle service identified by comp_page_id and + * aux_page_id in the spu_dvb_descriptor_t, (the composition and + * auxilliary page ids, respectively). + **/ + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -149,6 +198,15 @@ typedef struct { } demux_ts_media; +/* DVBSUB */ +#define MAX_NO_SPU_LANGS 16 +typedef struct { + spu_dvb_descriptor_t desc; + int pid; + int media_index; +} demux_ts_spu_lang; + + typedef struct { /* * The first field must be the "base class" for the plugin! @@ -189,7 +247,8 @@ typedef struct { unsigned int audioPid; unsigned int videoMedia; unsigned int audioMedia; - + char audioLang[4]; + int send_end_buffers; int ignore_scr_discont; int send_newpts; @@ -202,6 +261,12 @@ typedef struct { uint32_t rstat[NPKT_PER_READ + 1]; #endif + /* DVBSUB */ + unsigned int spu_pid; + unsigned int spu_media; + demux_ts_spu_lang spu_langs[MAX_NO_SPU_LANGS]; + int no_spu_langs; + int current_spu_channel; } demux_ts_t; typedef struct { @@ -239,9 +304,11 @@ static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data, static void check_newpts( demux_ts_t*this, int64_t pts ) { +#ifdef TS_LOG printf ("demux_ts: check_newpts %lld, send_newpts %d, buf_flag_seek %d\n", pts, this->send_newpts, this->buf_flag_seek); - +#endif + if (this->send_newpts && pts) { if (this->buf_flag_seek) { @@ -257,6 +324,61 @@ static void check_newpts( demux_ts_t*this, int64_t pts ) { /* + * demux_ts_update_spu_channel + * + * Send a BUF_SPU_DVB with BUF_SPECIAL_SPU_DVB_DESCRIPTOR to tell + * the decoder to reset itself on the new channel. + */ +static void demux_ts_update_spu_channel(demux_ts_t *this) +{ + xine_event_t ui_event; + buf_element_t *buf; + + this->current_spu_channel = this->stream->spu_channel; + + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + + buf->type = BUF_SPU_DVB; + buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_SPECIAL; + buf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR; + buf->size = 0; + + if (this->current_spu_channel >= 0 + && this->current_spu_channel < this->no_spu_langs) + { + demux_ts_spu_lang *lang = &this->spu_langs[this->current_spu_channel]; + + buf->decoder_info[2] = (uint32_t) &(lang->desc); + + this->spu_pid = lang->pid; + this->spu_media = lang->media_index; + +#ifdef TS_LOG + printf("demux_ts: DVBSUB: selecting lang: %s page %ld %ld\n", + lang->desc.lang, lang->desc.comp_page_id, lang->desc.aux_page_id); +#endif + } + else + { + buf->decoder_info[2] = 0; + + this->spu_pid = INVALID_PID; + +#ifdef TS_LOG + printf("demux_ts: DVBSUB: deselecting lang\n"); +#endif + } + + this->video_fifo->put(this->video_fifo, buf); + + /* Inform UI of SPU channel changes */ + ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; + ui_event.data_length = 0; + xine_event_send(this->stream, &ui_event); +} + +/* * demux_ts_parse_pat * * Parse a program association table (PAT). @@ -385,6 +507,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, this->pmt_pid[program_count] = pmt_pid; this->audioPid = INVALID_PID; this->videoPid = INVALID_PID; + this->spu_pid = INVALID_PID; } this->pmt_pid[program_count] = pmt_pid; @@ -496,6 +619,16 @@ static int demux_ts_parse_pes_header (demux_ts_media *m, m->type = BUF_AUDIO_A52; return 1; + } else if (m->descriptor_tag == 0x06 + && p[0] == 0x20 && p[1] == 0x00) { + /* DVBSUB */ + long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; + + m->content = p; + m->size = packet_len; + m->type = BUF_SPU_DVB + payload_len; + + return 1; } else if ((p[0] & 0xE0) == 0x20) { spu_id = (p[0] & 0x1f); @@ -636,6 +769,13 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, printf ("demux_ts: produced buffer, pts=%lld\n", m->pts); #endif + /* DVBSUB: reset PES packet length field in buffer type, to + * indicate that the next buffer is in the middle of a PES + * packet. + **/ + if ((m->type & 0xffff0000) == BUF_SPU_DVB) { + m->type = BUF_SPU_DVB; + } } memcpy(m->buf->mem + m->buffered_bytes, ts, len); m->buffered_bytes += len; @@ -664,6 +804,28 @@ static void demux_ts_pes_new(demux_ts_t*this, m->buffered_bytes = 0; } + +/* Find the first ISO 639 language descriptor (tag 10) and + * store the 3-char code in dest, nullterminated. If no + * code is found, zero out dest. + **/ +static void demux_ts_get_lang_desc(demux_ts_t *this, char *dest, + const unsigned char *data, int length) +{ + while (length >= 2 && length >= 2 + data[1]) + { + if (data[0] == 10 && data[1] >= 4) + { + memcpy(dest, data + 2, 3); + dest[3] = 0; + printf("demux_ts: found ISO 639 lang: %s\n", dest); + return; + } + } + printf("demux_ts: found no ISO 639 lang\n"); + memset(dest, 0, 4); +} + /* * NAME demux_ts_parse_pmt * @@ -846,6 +1008,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this, * Extract the elementary streams. */ mediaIndex = 0; + this->no_spu_langs = 0; while (section_length > 0) { unsigned int streamInfoLength; @@ -884,6 +1047,8 @@ static void demux_ts_parse_pmt (demux_ts_t *this, demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo,stream[0]); this->audioPid = pid; this->audioMedia = mediaIndex; + demux_ts_get_lang_desc(this, this->audioLang, + stream + 5, streamInfoLength); } break; case ISO_13818_PRIVATE: @@ -904,8 +1069,47 @@ static void demux_ts_parse_pmt (demux_ts_t *this, demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo,stream[0]); this->audioPid = pid; this->audioMedia = mediaIndex; + demux_ts_get_lang_desc(this, this->audioLang, + stream + 5, streamInfoLength); break; } + + /* DVBSUB */ + else if (stream[i] == 0x59) + { + int pos; + + for (pos = i + 2; + pos + 8 <= i + 2 + stream[i + 1] + && this->no_spu_langs < MAX_NO_SPU_LANGS; + pos += 8) + { + int no = this->no_spu_langs; + demux_ts_spu_lang *lang = &this->spu_langs[no]; + + this->no_spu_langs++; + + memcpy(lang->desc.lang, &stream[pos], 3); + lang->desc.lang[3] = 0; + lang->desc.comp_page_id = + (stream[pos + 4] << 8) | stream[pos + 5]; + lang->desc.aux_page_id = + (stream[pos + 6] << 8) | stream[pos + 7]; + lang->pid = pid; + lang->media_index = mediaIndex; + + demux_ts_pes_new(this, mediaIndex, + pid, this->video_fifo, + stream[0]); + +#ifdef TS_LOG + printf("demux_ts: DVBSUB: pid %u: %s page %ld %ld\n", + pid, lang->desc.lang, + lang->desc.comp_page_id, + lang->desc.aux_page_id); +#endif + } + } } break; case PRIVATE_A52: @@ -920,6 +1124,8 @@ static void demux_ts_parse_pmt (demux_ts_t *this, demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo, stream[0]); this->audioPid = pid; this->audioMedia = mediaIndex; + demux_ts_get_lang_desc(this, this->audioLang, + stream + 5, streamInfoLength); } break; default: @@ -953,6 +1159,9 @@ static void demux_ts_parse_pmt (demux_ts_t *this, #endif this->pcrPid = pid; } + + /* DVBSUB: update spu decoder */ + demux_ts_update_spu_channel(this); } static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { @@ -1309,7 +1518,17 @@ static void demux_ts_parse_packet (demux_ts_t*this) { #endif return; } - if ((this->audioPid == INVALID_PID) && (this->videoPid == INVALID_PID)) { + /* DVBSUB */ + else if (pid == this->spu_pid) { +#ifdef TS_LOG + printf ("demux_ts: SPU pid: %.4x\n", pid); +#endif + demux_ts_buffer_pes (this, originalPkt+data_offset, this->spu_media, + payload_unit_start_indicator, continuity_counter, + data_len); + return; + } + if ((this->audioPid == INVALID_PID) && (this->videoPid == INVALID_PID)) { program_count = 0; while ((this->program_number[program_count] != INVALID_PROGRAM) ) { if (pid == this->pmt_pid[program_count]) { @@ -1340,6 +1559,13 @@ static int demux_ts_send_chunk (demux_plugin_t *this_gen) { demux_ts_parse_packet(this); + /* DVBSUB: check if channel has changed. Dunno if I should, or + * even could, lock the xine object. */ + if (this->stream->spu_channel != this->current_spu_channel) + { + demux_ts_update_spu_channel(this); + } + return this->status; } @@ -1395,6 +1621,11 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) { this->last_PCR = 0; this->scrambled_npids = 0; + /* DVBSUB */ + this->spu_pid = INVALID_PID; + this->no_spu_langs = 0; + this->current_spu_channel = this->stream->spu_channel; + /* FIXME ? */ this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1; this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 1; @@ -1470,6 +1701,57 @@ static int demux_ts_get_video_frame (demux_plugin_t *this_gen, } +static uint32_t demux_ts_get_capabilities(demux_plugin_t *this_gen) +{ + return DEMUX_CAP_AUDIOLANG | DEMUX_CAP_SPULANG; +} + +static int demux_ts_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) +{ + demux_ts_t *this = (demux_ts_t *) this_gen; + char *str = data; + + /* be a bit paranoid */ + if (this == NULL || this->stream == NULL) + return DEMUX_OPTIONAL_UNSUPPORTED; + + switch (data_type) + { + case DEMUX_OPTIONAL_DATA_AUDIOLANG: + if (this->audioLang[0]) + { + strcpy(str, this->audioLang); + } + else + { + sprintf(str, "%3i", xine_get_audio_channel(this->stream)); + } + return DEMUX_OPTIONAL_SUCCESS; + + case DEMUX_OPTIONAL_DATA_SPULANG: + if (this->current_spu_channel >= 0 + && this->current_spu_channel < this->no_spu_langs) + { + memcpy(str, this->spu_langs[this->current_spu_channel].desc.lang, 3); + str[4] = 0; + } + else if (this->current_spu_channel == -1) + { + strcpy(str, "none"); + } + else + { + sprintf(str, "%3i", this->current_spu_channel); + } + return DEMUX_OPTIONAL_SUCCESS; + + default: + return DEMUX_OPTIONAL_UNSUPPORTED; + } +} + + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { @@ -1583,6 +1865,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.get_stream_length = demux_ts_get_stream_length; this->demux_plugin.get_video_frame = demux_ts_get_video_frame; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_ts_get_capabilities; + this->demux_plugin.get_optional_data = demux_ts_get_optional_data; this->demux_plugin.demux_class = class_gen; /* @@ -1617,6 +1901,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, } #endif + /* DVBSUB */ + this->spu_pid = INVALID_PID; + this->no_spu_langs = 0; + this->current_spu_channel = this->stream->spu_channel; + return &this->demux_plugin; } @@ -1672,6 +1961,6 @@ static void *init_class (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "mpeg-ts", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_DEMUX, 18, "mpeg-ts", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_voc.c b/src/demuxers/demux_voc.c index ea0e60135..7517bb7e3 100644 --- a/src/demuxers/demux_voc.c +++ b/src/demuxers/demux_voc.c @@ -23,7 +23,7 @@ * It will only play that block if it is PCM data. More variations will be * supported as they are encountered. * - * $Id: demux_voc.c,v 1.18 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_voc.c,v 1.19 2002/11/28 10:21:07 petli Exp $ * */ @@ -298,6 +298,15 @@ static int demux_voc_get_stream_length (demux_plugin_t *this_gen) { return this->running_time; } +static uint32_t demux_voc_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_voc_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -321,6 +330,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_voc_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_voc_get_capabilities; + this->demux_plugin.get_optional_data = demux_voc_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -428,6 +439,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "voc", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "voc", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_vqa.c b/src/demuxers/demux_vqa.c index d4be21f51..fcc407970 100644 --- a/src/demuxers/demux_vqa.c +++ b/src/demuxers/demux_vqa.c @@ -27,7 +27,7 @@ * block needs information from the previous audio block in order to be * decoded, thus making random seeking difficult. * - * $Id: demux_vqa.c,v 1.21 2002/11/22 20:13:14 guenter Exp $ + * $Id: demux_vqa.c,v 1.22 2002/11/28 10:21:07 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -339,6 +339,15 @@ static int demux_vqa_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_vqa_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_vqa_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -364,6 +373,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_vqa_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_vqa_get_capabilities; + this->demux_plugin.get_optional_data = demux_vqa_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -468,6 +479,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "vqa", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "vqa", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index 60b2a67d2..424f0f1b3 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -20,7 +20,7 @@ * MS WAV File Demuxer by Mike Melanson (melanson@pcisys.net) * based on WAV specs that are available far and wide * - * $Id: demux_wav.c,v 1.26 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_wav.c,v 1.27 2002/11/28 10:21:08 petli Exp $ * */ @@ -297,6 +297,15 @@ static int demux_wav_get_stream_length (demux_plugin_t *this_gen) { return (int)(this->data_size / this->wave->nAvgBytesPerSec); } +static uint32_t demux_wav_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_wav_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -320,6 +329,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_wav_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_wav_get_capabilities; + this->demux_plugin.get_optional_data = demux_wav_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -442,6 +453,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "wav", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "wav", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_wc3movie.c b/src/demuxers/demux_wc3movie.c index 202e704ee..cf66e7c4f 100644 --- a/src/demuxers/demux_wc3movie.c +++ b/src/demuxers/demux_wc3movie.c @@ -22,7 +22,7 @@ * For more information on the MVE file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_wc3movie.c,v 1.26 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_wc3movie.c,v 1.27 2002/11/28 10:21:08 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -656,6 +656,15 @@ static int demux_mve_get_stream_length (demux_plugin_t *this_gen) { return 0; } +static uint32_t demux_mve_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_mve_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -679,6 +688,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_mve_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_mve_get_capabilities; + this->demux_plugin.get_optional_data = demux_mve_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -778,6 +789,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "wc3movie", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "wc3movie", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_yuv4mpeg2.c b/src/demuxers/demux_yuv4mpeg2.c index 1c1725d59..7a5efa641 100644 --- a/src/demuxers/demux_yuv4mpeg2.c +++ b/src/demuxers/demux_yuv4mpeg2.c @@ -22,7 +22,7 @@ * tools, visit: * http://mjpeg.sourceforge.net/ * - * $Id: demux_yuv4mpeg2.c,v 1.11 2002/11/20 11:57:41 mroi Exp $ + * $Id: demux_yuv4mpeg2.c,v 1.12 2002/11/28 10:21:08 petli Exp $ */ #ifdef HAVE_CONFIG_H @@ -316,6 +316,15 @@ static int demux_yuv4mpeg2_get_stream_length (demux_plugin_t *this_gen) { this->fps); } +static uint32_t demux_yuv4mpeg2_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_yuv4mpeg2_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input_gen) { @@ -339,6 +348,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_stream_length = demux_yuv4mpeg2_get_stream_length; this->demux_plugin.get_video_frame = NULL; this->demux_plugin.got_video_frame_cb= NULL; + this->demux_plugin.get_capabilities = demux_yuv4mpeg2_get_capabilities; + this->demux_plugin.get_optional_data = demux_yuv4mpeg2_get_optional_data; this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; @@ -444,6 +455,6 @@ static void *init_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 17, "yuv4mpeg2", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_DEMUX, 18, "yuv4mpeg2", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index cf59a9317..4dc34bd45 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.h,v 1.79 2002/11/18 03:03:09 guenter Exp $ + * $Id: buffer.h,v 1.80 2002/11/28 10:21:08 petli Exp $ * * * contents: @@ -182,6 +182,7 @@ extern "C" { #define BUF_SPU_DVD 0x04000000 #define BUF_SPU_TEXT 0x04010000 #define BUF_SPU_CC 0x04020000 +#define BUF_SPU_DVB 0x04030000 /* demuxer block types: */ @@ -324,6 +325,24 @@ struct buf_element_s { #define SPU_DVD_SUBTYPE_NAV 4 +/* In a BUF_SPECIAL_SPU_DVB_DESCRIPTOR + * decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR + * decoder_info[2] = pointer to spu_dvb_descriptor_t, or NULL + * decoder_info[3] = + * + * This buffer is used to tell a DVBSUB decoder when the stream + * changes. For more information on how to write a DVBSUB decoder, + * see the comment at the top of src/demuxers/demux_ts.c + **/ +#define BUF_SPECIAL_SPU_DVB_DESCRIPTOR 9 +typedef struct spu_dvb_descriptor_s spu_dvb_descriptor_t; +struct spu_dvb_descriptor_s +{ + char lang[4]; + long comp_page_id; + long aux_page_id; +} ; + typedef struct palette_entry_s palette_entry_t; struct palette_entry_s { diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index b753ce535..91c549aa2 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.c,v 1.196 2002/11/25 12:36:05 mroi Exp $ + * $Id: xine.c,v 1.197 2002/11/28 10:21:08 petli Exp $ * * top-level xine functions * @@ -1085,6 +1085,20 @@ int xine_get_video_frame (xine_stream_t *stream, int xine_get_spu_lang (xine_stream_t *stream, int channel, char *lang) { + /* Ask the demuxer first (e.g. TS extracts this information from + * the stream) + **/ + if (stream->demux_plugin) { + if (stream->demux_plugin->get_capabilities (stream->demux_plugin) & DEMUX_CAP_SPULANG) { + stream->demux_plugin->get_optional_data (stream->demux_plugin, lang, + DEMUX_OPTIONAL_DATA_SPULANG); + return 1; + } + } + + /* No match, check with input plugin instead (e.g. DVD gets this + * info from the IFO). + **/ if (stream->input_plugin) { if (stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_SPULANG) { stream->input_plugin->get_optional_data (stream->input_plugin, lang, @@ -1098,6 +1112,14 @@ int xine_get_spu_lang (xine_stream_t *stream, int channel, char *lang) { int xine_get_audio_lang (xine_stream_t *stream, int channel, char *lang) { + if (stream->demux_plugin) { + if (stream->demux_plugin->get_capabilities (stream->demux_plugin) & DEMUX_CAP_AUDIOLANG) { + stream->demux_plugin->get_optional_data (stream->demux_plugin, lang, + DEMUX_OPTIONAL_DATA_AUDIOLANG); + return 1; + } + } + if (stream->input_plugin) { if (stream->input_plugin->get_capabilities (stream->input_plugin) & INPUT_CAP_AUDIOLANG) { stream->input_plugin->get_optional_data (stream->input_plugin, lang, |