mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-13 10:55:34 +00:00
dvdlpcmdec: add support for another format
The format specification can be found here: http://www.dvdforum.org/images/Guideline1394V10R0_20020911.pdf Note: This format is also used for Wifi-Display. https://bugzilla.gnome.org/show_bug.cgi?id=765807
This commit is contained in:
parent
35dc8d0f68
commit
9f51f72b37
2 changed files with 105 additions and 0 deletions
|
@ -36,6 +36,7 @@ static GstStaticPadTemplate gst_dvdlpcmdec_sink_template =
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS ("audio/x-private1-lpcm; "
|
GST_STATIC_CAPS ("audio/x-private1-lpcm; "
|
||||||
|
"audio/x-private2-lpcm; "
|
||||||
"audio/x-lpcm, "
|
"audio/x-lpcm, "
|
||||||
"width = (int) { 16, 20, 24 }, "
|
"width = (int) { 16, 20, 24 }, "
|
||||||
"rate = (int) { 32000, 44100, 48000, 96000 }, "
|
"rate = (int) { 32000, 44100, 48000, 96000 }, "
|
||||||
|
@ -239,6 +240,10 @@ gst_dvdlpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
|
||||||
dvdlpcmdec->mode = GST_LPCM_DVD;
|
dvdlpcmdec->mode = GST_LPCM_DVD;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (gst_structure_has_name (structure, "audio/x-private2-lpcm")) {
|
||||||
|
dvdlpcmdec->mode = GST_LPCM_1394;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
dvdlpcmdec->mode = GST_LPCM_RAW;
|
dvdlpcmdec->mode = GST_LPCM_RAW;
|
||||||
|
|
||||||
|
@ -500,6 +505,102 @@ negotiation_failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_dvdlpcmdec_parse_1394 (GstDvdLpcmDec * dvdlpcmdec, GstAdapter * adapter,
|
||||||
|
gint * offset, gint * len)
|
||||||
|
{
|
||||||
|
guint32 header;
|
||||||
|
const guint8 *data;
|
||||||
|
|
||||||
|
data = (const guint8 *) gst_adapter_map (adapter, 4);
|
||||||
|
if (!data)
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
|
header = GST_READ_UINT32_BE (data);
|
||||||
|
|
||||||
|
gst_adapter_unmap (adapter);
|
||||||
|
|
||||||
|
/* see if we have a new header */
|
||||||
|
if (header != dvdlpcmdec->header) {
|
||||||
|
GstAudioFormat format;
|
||||||
|
gint rate, channels;
|
||||||
|
|
||||||
|
if (header >> 24 != 0xa0)
|
||||||
|
goto invalid_data;
|
||||||
|
|
||||||
|
switch ((header >> 6) & 0x3) {
|
||||||
|
case 0x0:
|
||||||
|
format = GST_AUDIO_FORMAT_S16BE;
|
||||||
|
dvdlpcmdec->width = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = GST_AUDIO_FORMAT_UNKNOWN;
|
||||||
|
dvdlpcmdec->width = 0;
|
||||||
|
GST_WARNING ("Invalid quantization word length!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((header >> 3) & 0x7) {
|
||||||
|
case 0x1:
|
||||||
|
rate = 44100;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
rate = 48000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rate = 0;
|
||||||
|
GST_WARNING ("Invalid audio sampling frequency!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (header & 0x7) {
|
||||||
|
case 0x0: /* 2 channels dual-mono */
|
||||||
|
case 0x1: /* 2 channles stereo */
|
||||||
|
channels = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
channels = 0;
|
||||||
|
GST_WARNING ("Invalid number of audio channels!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_dvdlpcmdec_update_audio_formats (dvdlpcmdec, channels, rate, format);
|
||||||
|
|
||||||
|
if (!gst_dvdlpcmdec_set_output_format (dvdlpcmdec))
|
||||||
|
goto negotiation_failed;
|
||||||
|
|
||||||
|
dvdlpcmdec->header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset = 4;
|
||||||
|
*len = gst_adapter_available (adapter) - 4;
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
too_small:
|
||||||
|
{
|
||||||
|
/* Buffer is too small */
|
||||||
|
GST_ELEMENT_WARNING (dvdlpcmdec, STREAM, DECODE,
|
||||||
|
("Invalid data found parsing LPCM packet"),
|
||||||
|
("LPCM packet was too small. Dropping"));
|
||||||
|
*offset = gst_adapter_available (adapter);
|
||||||
|
return GST_FLOW_EOS;
|
||||||
|
}
|
||||||
|
invalid_data:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_WARNING (dvdlpcmdec, STREAM, DECODE,
|
||||||
|
("Invalid data found parsing LPCM packet"),
|
||||||
|
("LPCM packet contains invalid sub_stream_id."));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
negotiation_failed:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (dvdlpcmdec, STREAM, FORMAT, (NULL),
|
||||||
|
("Failed to configure output format"));
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dvdlpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
|
gst_dvdlpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
|
||||||
gint * offset, gint * len)
|
gint * offset, gint * len)
|
||||||
|
@ -517,6 +618,9 @@ gst_dvdlpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
|
||||||
|
|
||||||
case GST_LPCM_DVD:
|
case GST_LPCM_DVD:
|
||||||
return gst_dvdlpcmdec_parse_dvd (dvdlpcmdec, adapter, offset, len);
|
return gst_dvdlpcmdec_parse_dvd (dvdlpcmdec, adapter, offset, len);
|
||||||
|
|
||||||
|
case GST_LPCM_1394:
|
||||||
|
return gst_dvdlpcmdec_parse_1394 (dvdlpcmdec, adapter, offset, len);
|
||||||
}
|
}
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ typedef enum {
|
||||||
GST_LPCM_UNKNOWN,
|
GST_LPCM_UNKNOWN,
|
||||||
GST_LPCM_RAW,
|
GST_LPCM_RAW,
|
||||||
GST_LPCM_DVD,
|
GST_LPCM_DVD,
|
||||||
|
GST_LPCM_1394
|
||||||
} GstDvdLpcmMode;
|
} GstDvdLpcmMode;
|
||||||
|
|
||||||
struct _GstDvdLpcmDec {
|
struct _GstDvdLpcmDec {
|
||||||
|
|
Loading…
Reference in a new issue