I'm too lazy to comment this

Original commit message from CVS:
Lots of LPCM support work from Martin. This fixes the mimetype being set and interprets sound stream properties better so it's just iedntified as audio/raw. Thanks go to Martin Soto <soto@informatik.uni-kl.de> - see #106875 for more info
This commit is contained in:
Ronald S. Bultje 2003-05-14 21:54:41 +00:00
parent 2cf0ef34e1
commit ab8278b082
2 changed files with 140 additions and 7 deletions

View file

@ -122,8 +122,26 @@ GST_PAD_TEMPLATE_FACTORY (pcm_factory,
GST_PAD_SOMETIMES,
GST_CAPS_NEW (
"mpeg_demux_pcm",
"audio/x-lpcm",
NULL
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BIG_ENDIAN),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_LIST (
GST_PROPS_INT (16),
GST_PROPS_INT (20),
GST_PROPS_INT (24)
),
"depth", GST_PROPS_LIST (
GST_PROPS_INT (16),
GST_PROPS_INT (20),
GST_PROPS_INT (24)
),
"rate", GST_PROPS_LIST (
GST_PROPS_INT (48000),
GST_PROPS_INT (96000)
),
"channels", GST_PROPS_INT_RANGE (1, 8)
)
);
@ -148,6 +166,9 @@ static gboolean gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer
static void gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse,
GstData *data, GstClockTime time);
static void gst_mpeg_demux_lpcm_set_caps (GstPad *pad, guint8 sample_info);
static void gst_mpeg_demux_dvd_audio_clear (GstMPEGDemux *mpeg_demux, int channel);
static void gst_mpeg_demux_handle_discont (GstMPEGParse *mpeg_parse);
static gboolean gst_mpeg_demux_handle_src_event (GstPad *pad, GstEvent *event);
@ -223,6 +244,9 @@ gst_mpeg_demux_init (GstMPEGDemux *mpeg_demux)
for (i=0;i<NUM_PRIVATE_1_STREAMS;i++) {
mpeg_demux->private_1_stream[i] = NULL;
}
for (i=0;i<NUM_PCM_STREAMS;i++) {
mpeg_demux->pcm_stream[i] = NULL;
}
for (i=0;i<NUM_SUBTITLE_STREAMS;i++) {
mpeg_demux->subtitle_stream[i] = NULL;
}
@ -265,7 +289,6 @@ gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse, GstData *data, GstClockTime
}
}
}
static void
gst_mpeg_demux_handle_discont (GstMPEGParse *mpeg_parse)
{
@ -788,6 +811,22 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
GST_DEBUG (0, "we have a pcm_stream packet, track %d",
ps_id_code - 0xA0);
outstream = &mpeg_demux->pcm_stream[ps_id_code - 0xA0];
/* Check for changes in the sample format. */
if (*outstream != NULL &&
basebuf[headerlen + 9] !=
mpeg_demux->lpcm_sample_info[ps_id_code - 0xA0]) {
/* Change the pad caps.*/
gst_mpeg_demux_lpcm_set_caps((*outstream)->pad, basebuf[headerlen + 9]);
}
/* Store the sample info. */
mpeg_demux->lpcm_sample_info[ps_id_code - 0xA0] =
basebuf[headerlen + 9];
/* Get rid of the LPCM header. */
headerlen += 7;
datalen -= 7;
break;
case 0x20 ... 0x2f:
GST_DEBUG (0, "we have a subtitle_stream packet, track %d",
@ -838,10 +877,16 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
case 0xBD:
switch (ps_id_code) {
case 0x80 ... 0x87:
name = g_strdup_printf ("private_stream_1.%d",ps_id_code - 0x80);
/* Erase any DVD audio pads. */
gst_mpeg_demux_dvd_audio_clear (mpeg_demux, ps_id_code - 0x80);
name = g_strdup_printf ("private_stream_1_%d",ps_id_code - 0x80);
newtemp = GST_PAD_TEMPLATE_GET (private1_factory);
break;
case 0xA0 ... 0xA7:
/* Erase any DVD audio pads. */
gst_mpeg_demux_dvd_audio_clear (mpeg_demux, ps_id_code - 0xA0);
name = g_strdup_printf ("pcm_stream_%d", ps_id_code - 0xA0);
newtemp = GST_PAD_TEMPLATE_GET (pcm_factory);
break;
@ -883,9 +928,16 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
/* create the pad and add it to self */
*outpad = gst_pad_new_from_template (newtemp, name);
caps = gst_pad_template_get_caps (newtemp);
gst_pad_try_set_caps (*outpad, caps);
gst_caps_unref (caps);
if (ps_id_code < 0xA0 || ps_id_code > 0xA7) {
caps = gst_pad_template_get_caps (newtemp);
gst_pad_try_set_caps (*outpad, caps);
gst_caps_unref (caps);
}
else {
gst_mpeg_demux_lpcm_set_caps(*outpad,
mpeg_demux->lpcm_sample_info[ps_id_code
- 0xA0]);
}
gst_pad_set_formats_function (*outpad, gst_mpeg_demux_get_src_formats);
gst_pad_set_convert_function (*outpad, gst_mpeg_parse_convert_src);
@ -947,6 +999,82 @@ gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
return TRUE;
}
/**
* Set the capabilities of the given pad based on the provided LPCM
* sample information.
*/
static void
gst_mpeg_demux_lpcm_set_caps (GstPad *pad, guint8 sample_info)
{
gint width, rate, channels;
GstCaps *caps;
/* Determine the sample width. */
switch (sample_info & 0xC0) {
case 0x80:
width = 24;
break;
case 0x40:
width = 20;
break;
default:
width = 16;
break;
}
/* Determine the rate. */
if (sample_info & 0x10) {
rate = 96000;
}
else {
rate = 48000;
}
/* Determine the number of channels. */
channels = (sample_info & 0x7) + 1;
caps = GST_CAPS_NEW (
"mpeg_demux_pcm",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BIG_ENDIAN),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (width),
"depth", GST_PROPS_INT (width),
"rate", GST_PROPS_INT (rate),
"channels", GST_PROPS_INT (channels)
);
gst_pad_try_set_caps (pad, caps);
}
/**
* Erase the DVD audio pad (if any) associated to the given channel.
*/
static void
gst_mpeg_demux_dvd_audio_clear (GstMPEGDemux *mpeg_demux, int channel)
{
GstMPEGStream **stream = NULL;
if (mpeg_demux->private_1_stream[channel] != NULL) {
stream = &mpeg_demux->private_1_stream[channel];
}
else if (mpeg_demux->pcm_stream[channel] != NULL) {
stream = &mpeg_demux->pcm_stream[channel];
}
if (stream == NULL) {
return;
}
gst_pad_unlink ((*stream)->pad, gst_pad_get_peer((*stream)->pad));
gst_element_remove_pad (GST_ELEMENT (mpeg_demux), (*stream)->pad);
g_free (*stream);
*stream = NULL;
}
const GstFormat*
gst_mpeg_demux_get_src_formats (GstPad *pad)
{

View file

@ -89,6 +89,11 @@ struct _GstMPEGDemux {
GstMPEGStream *video_stream[NUM_VIDEO_STREAMS];
GstMPEGStream *audio_stream[NUM_AUDIO_STREAMS];
/* The type of linear PCM samples associated to each channel. The
values are bit fields with the same format of the sample_info
field in the linear PCM header. */
guint8 lpcm_sample_info[NUM_PCM_STREAMS];
GstIndex *index;
};