mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 00:58:12 +00:00
gst/flv/: Introduce demuxing support for AAC and
Original commit message from CVS: 2008-06-14 Julien Moutte <julien@fluendo.com> * gst/flv/gstflvdemux.c: (gst_flv_demux_cleanup), (gst_flv_demux_dispose): * gst/flv/gstflvdemux.h: * gst/flv/gstflvparse.c: (gst_flv_parse_audio_negotiate), (gst_flv_parse_tag_audio), (gst_flv_parse_video_negotiate), (gst_flv_parse_tag_video): Introduce demuxing support for AAC and H.264/AVC inside FLV. * sys/dshowdecwrapper/gstdshowaudiodec.c: (gst_dshowaudiodec_init), (gst_dshowaudiodec_chain), (gst_dshowaudiodec_push_buffer), (gst_dshowaudiodec_sink_event), (gst_dshowaudiodec_setup_graph): * sys/dshowdecwrapper/gstdshowaudiodec.h: * sys/dshowdecwrapper/gstdshowvideodec.c: (gst_dshowvideodec_init), (gst_dshowvideodec_sink_event), (gst_dshowvideodec_chain), (gst_dshowvideodec_push_buffer), (gst_dshowvideodec_src_getcaps): * sys/dshowdecwrapper/gstdshowvideodec.h: Lot of random fixes to improve stability (ref counting, safety checks...)
This commit is contained in:
parent
7d5e4116a6
commit
bb7f93bd4e
8 changed files with 318 additions and 216 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2008-06-14 Julien Moutte <julien@fluendo.com>
|
||||||
|
|
||||||
|
* gst/flv/gstflvdemux.c: (gst_flv_demux_cleanup),
|
||||||
|
(gst_flv_demux_dispose):
|
||||||
|
* gst/flv/gstflvdemux.h:
|
||||||
|
* gst/flv/gstflvparse.c: (gst_flv_parse_audio_negotiate),
|
||||||
|
(gst_flv_parse_tag_audio), (gst_flv_parse_video_negotiate),
|
||||||
|
(gst_flv_parse_tag_video): Introduce demuxing support for AAC and
|
||||||
|
H.264/AVC inside FLV.
|
||||||
|
* sys/dshowdecwrapper/gstdshowaudiodec.c: (gst_dshowaudiodec_init),
|
||||||
|
(gst_dshowaudiodec_chain), (gst_dshowaudiodec_push_buffer),
|
||||||
|
(gst_dshowaudiodec_sink_event), (gst_dshowaudiodec_setup_graph):
|
||||||
|
* sys/dshowdecwrapper/gstdshowaudiodec.h:
|
||||||
|
* sys/dshowdecwrapper/gstdshowvideodec.c: (gst_dshowvideodec_init),
|
||||||
|
(gst_dshowvideodec_sink_event), (gst_dshowvideodec_chain),
|
||||||
|
(gst_dshowvideodec_push_buffer), (gst_dshowvideodec_src_getcaps):
|
||||||
|
* sys/dshowdecwrapper/gstdshowvideodec.h: Lot of random fixes
|
||||||
|
to improve stability (ref counting, safety checks...)
|
||||||
|
|
||||||
2008-06-13 Wim Taymans <wim.taymans@collabora.co.uk>
|
2008-06-13 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
* gst/real/gstrealaudiodec.c: (gst_real_audio_dec_probe_modules):
|
* gst/real/gstrealaudiodec.c: (gst_real_audio_dec_probe_modules):
|
||||||
|
|
|
@ -118,6 +118,16 @@ gst_flv_demux_cleanup (GstFLVDemux * demux)
|
||||||
|
|
||||||
gst_adapter_clear (demux->adapter);
|
gst_adapter_clear (demux->adapter);
|
||||||
|
|
||||||
|
if (demux->audio_codec_data) {
|
||||||
|
gst_buffer_unref (demux->audio_codec_data);
|
||||||
|
demux->audio_codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (demux->video_codec_data) {
|
||||||
|
gst_buffer_unref (demux->video_codec_data);
|
||||||
|
demux->video_codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (demux->audio_pad) {
|
if (demux->audio_pad) {
|
||||||
gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
|
gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
|
||||||
gst_object_unref (demux->audio_pad);
|
gst_object_unref (demux->audio_pad);
|
||||||
|
@ -1098,6 +1108,16 @@ gst_flv_demux_dispose (GObject * object)
|
||||||
demux->new_seg_event = NULL;
|
demux->new_seg_event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (demux->audio_codec_data) {
|
||||||
|
gst_buffer_unref (demux->audio_codec_data);
|
||||||
|
demux->audio_codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (demux->video_codec_data) {
|
||||||
|
gst_buffer_unref (demux->video_codec_data);
|
||||||
|
demux->video_codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (demux->audio_pad) {
|
if (demux->audio_pad) {
|
||||||
gst_object_unref (demux->audio_pad);
|
gst_object_unref (demux->audio_pad);
|
||||||
demux->audio_pad = NULL;
|
demux->audio_pad = NULL;
|
||||||
|
|
|
@ -88,6 +88,7 @@ struct _GstFLVDemux
|
||||||
gboolean audio_need_discont;
|
gboolean audio_need_discont;
|
||||||
gboolean audio_need_segment;
|
gboolean audio_need_segment;
|
||||||
gboolean audio_linked;
|
gboolean audio_linked;
|
||||||
|
GstBuffer * audio_codec_data;
|
||||||
|
|
||||||
/* Video infos */
|
/* Video infos */
|
||||||
guint32 w;
|
guint32 w;
|
||||||
|
@ -100,6 +101,7 @@ struct _GstFLVDemux
|
||||||
gboolean video_need_segment;
|
gboolean video_need_segment;
|
||||||
gboolean video_linked;
|
gboolean video_linked;
|
||||||
gboolean got_par;
|
gboolean got_par;
|
||||||
|
GstBuffer * video_codec_data;
|
||||||
|
|
||||||
gboolean random_access;
|
gboolean random_access;
|
||||||
gboolean need_header;
|
gboolean need_header;
|
||||||
|
|
|
@ -391,6 +391,90 @@ gst_flv_parse_tag_script (GstFLVDemux * demux, const guint8 * data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_flv_parse_audio_negotiate (GstFLVDemux * demux, guint32 codec_tag,
|
||||||
|
guint32 rate, guint32 channels, guint32 width)
|
||||||
|
{
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
gchar *codec_name = NULL;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
switch (codec_tag) {
|
||||||
|
case 1:
|
||||||
|
caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
|
||||||
|
"swf", NULL);
|
||||||
|
codec_name = "Shockwave ADPCM";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
caps = gst_caps_new_simple ("audio/mpeg",
|
||||||
|
"mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
|
||||||
|
codec_name = "MPEG 1 Audio, Layer 3 (MP3)";
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
case 3:
|
||||||
|
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||||
|
"endianness", G_TYPE_INT, G_BYTE_ORDER,
|
||||||
|
"signed", G_TYPE_BOOLEAN, TRUE,
|
||||||
|
"width", G_TYPE_INT, width, "depth", G_TYPE_INT, width, NULL);
|
||||||
|
codec_name = "Raw Audio";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
caps = gst_caps_new_simple ("audio/x-nellymoser", NULL);
|
||||||
|
codec_name = "Nellymoser ASAO";
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
caps = gst_caps_new_simple ("audio/mpeg",
|
||||||
|
"mpegversion", G_TYPE_INT, 4, NULL);
|
||||||
|
codec_name = "AAC";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!caps)) {
|
||||||
|
GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_set_simple (caps,
|
||||||
|
"rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
|
||||||
|
|
||||||
|
if (demux->audio_codec_data) {
|
||||||
|
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
|
||||||
|
demux->audio_codec_data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_pad_set_caps (demux->audio_pad, caps);
|
||||||
|
|
||||||
|
if (G_LIKELY (ret)) {
|
||||||
|
/* Store the caps we have set */
|
||||||
|
demux->audio_codec_tag = codec_tag;
|
||||||
|
demux->rate = rate;
|
||||||
|
demux->channels = channels;
|
||||||
|
demux->width = width;
|
||||||
|
|
||||||
|
if (codec_name) {
|
||||||
|
if (demux->taglist == NULL)
|
||||||
|
demux->taglist = gst_tag_list_new ();
|
||||||
|
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
||||||
|
GST_TAG_AUDIO_CODEC, codec_name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
|
||||||
|
GST_PTR_FORMAT, caps);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
|
||||||
|
GST_PTR_FORMAT, caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
size_t data_size)
|
size_t data_size)
|
||||||
|
@ -433,7 +517,11 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
}
|
}
|
||||||
/* Codec tag */
|
/* Codec tag */
|
||||||
codec_tag = flags >> 4;
|
codec_tag = flags >> 4;
|
||||||
codec_data = 1;
|
if (codec_tag == 10) { /* AAC has an extra byte for packet type */
|
||||||
|
codec_data = 2;
|
||||||
|
} else {
|
||||||
|
codec_data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
|
GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
|
||||||
"%d bits width, codec tag %u (flags %02X)", channels, rate, width,
|
"%d bits width, codec tag %u (flags %02X)", channels, rate, width,
|
||||||
|
@ -441,8 +529,6 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
|
|
||||||
/* If we don't have our audio pad created, then create it. */
|
/* If we don't have our audio pad created, then create it. */
|
||||||
if (G_UNLIKELY (!demux->audio_pad)) {
|
if (G_UNLIKELY (!demux->audio_pad)) {
|
||||||
GstCaps *caps = NULL;
|
|
||||||
gchar *codec_name = NULL;
|
|
||||||
|
|
||||||
demux->audio_pad = gst_pad_new ("audio", GST_PAD_SRC);
|
demux->audio_pad = gst_pad_new ("audio", GST_PAD_SRC);
|
||||||
if (G_UNLIKELY (!demux->audio_pad)) {
|
if (G_UNLIKELY (!demux->audio_pad)) {
|
||||||
|
@ -454,64 +540,17 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
/* Make it active */
|
/* Make it active */
|
||||||
gst_pad_set_active (demux->audio_pad, TRUE);
|
gst_pad_set_active (demux->audio_pad, TRUE);
|
||||||
|
|
||||||
switch (codec_tag) {
|
/* Negotiate caps */
|
||||||
case 1:
|
if (!gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels,
|
||||||
caps =
|
width)) {
|
||||||
gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
|
|
||||||
"swf", NULL);
|
|
||||||
codec_name = "Shockwave ADPCM";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
caps = gst_caps_new_simple ("audio/mpeg",
|
|
||||||
"mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
|
|
||||||
codec_name = "MPEG 1 Audio, Layer 3 (MP3)";
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
case 3:
|
|
||||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
|
||||||
"endianness", G_TYPE_INT, G_BYTE_ORDER,
|
|
||||||
"signed", G_TYPE_BOOLEAN, TRUE,
|
|
||||||
"width", G_TYPE_INT, width, "depth", G_TYPE_INT, width, NULL);
|
|
||||||
codec_name = "Raw Audio";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
caps = gst_caps_new_simple ("audio/x-nellymoser", NULL);
|
|
||||||
codec_name = "Nellymoser ASAO";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!caps)) {
|
|
||||||
GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
gst_object_unref (demux->audio_pad);
|
gst_object_unref (demux->audio_pad);
|
||||||
demux->audio_pad = NULL;
|
demux->audio_pad = NULL;
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_caps_set_simple (caps,
|
|
||||||
"rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
|
|
||||||
|
|
||||||
gst_pad_set_caps (demux->audio_pad, caps);
|
|
||||||
if (codec_name) {
|
|
||||||
if (demux->taglist == NULL)
|
|
||||||
demux->taglist = gst_tag_list_new ();
|
|
||||||
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
|
||||||
GST_TAG_AUDIO_CODEC, codec_name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
|
||||||
caps);
|
GST_PAD_CAPS (demux->audio_pad));
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
|
|
||||||
/* Store the caps we have set */
|
|
||||||
demux->audio_codec_tag = codec_tag;
|
|
||||||
demux->rate = rate;
|
|
||||||
demux->channels = channels;
|
|
||||||
demux->width = width;
|
|
||||||
|
|
||||||
/* Set functions on the pad */
|
/* Set functions on the pad */
|
||||||
gst_pad_set_query_type_function (demux->audio_pad,
|
gst_pad_set_query_type_function (demux->audio_pad,
|
||||||
|
@ -537,61 +576,10 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
/* Check if caps have changed */
|
/* Check if caps have changed */
|
||||||
if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
|
if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
|
||||||
codec_tag != demux->audio_codec_tag || width != demux->width)) {
|
codec_tag != demux->audio_codec_tag || width != demux->width)) {
|
||||||
GstCaps *caps = NULL;
|
|
||||||
gchar *codec_name = NULL;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
|
GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
|
||||||
|
|
||||||
switch (codec_tag) {
|
/* Negotiate caps */
|
||||||
case 1:
|
gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels, width);
|
||||||
caps =
|
|
||||||
gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
|
|
||||||
"swf", NULL);
|
|
||||||
codec_name = "Shockwave ADPCM";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
caps = gst_caps_new_simple ("audio/mpeg",
|
|
||||||
"mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
|
|
||||||
codec_name = "MPEG 1 Audio, Layer 3 (MP3)";
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
case 3:
|
|
||||||
caps = gst_caps_new_simple ("audio/x-raw-int", NULL);
|
|
||||||
codec_name = "Raw Audio";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
caps = gst_caps_new_simple ("audio/x-nellymoser", NULL);
|
|
||||||
codec_name = "Nellymoser ASAO";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!caps)) {
|
|
||||||
GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_caps_set_simple (caps,
|
|
||||||
"rate", G_TYPE_INT, rate,
|
|
||||||
"channels", G_TYPE_INT, channels, "width", G_TYPE_INT, width, NULL);
|
|
||||||
|
|
||||||
gst_pad_set_caps (demux->audio_pad, caps);
|
|
||||||
if (codec_name) {
|
|
||||||
if (demux->taglist == NULL)
|
|
||||||
demux->taglist = gst_tag_list_new ();
|
|
||||||
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
|
||||||
GST_TAG_AUDIO_CODEC, codec_name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
|
|
||||||
/* Store the caps we have set */
|
|
||||||
demux->audio_codec_tag = codec_tag;
|
|
||||||
demux->rate = rate;
|
|
||||||
demux->channels = channels;
|
|
||||||
demux->width = width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push taglist if present */
|
/* Push taglist if present */
|
||||||
|
@ -627,8 +615,38 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy (GST_BUFFER_DATA (buffer), data + 7 + codec_data,
|
||||||
|
MIN (demux->tag_data_size - codec_data, GST_BUFFER_SIZE (buffer)));
|
||||||
|
|
||||||
demux->audio_linked = TRUE;
|
demux->audio_linked = TRUE;
|
||||||
|
|
||||||
|
if (demux->audio_codec_tag == 10) {
|
||||||
|
guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
|
||||||
|
|
||||||
|
switch (aac_packet_type) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
/* AudioSpecificConfic data */
|
||||||
|
GST_LOG_OBJECT (demux, "got an AAC codec data packet");
|
||||||
|
if (demux->audio_codec_data) {
|
||||||
|
gst_buffer_unref (demux->audio_codec_data);
|
||||||
|
}
|
||||||
|
demux->audio_codec_data = buffer;
|
||||||
|
/* Use that buffer data in the caps */
|
||||||
|
gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels, width);
|
||||||
|
goto beach;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
/* AAC raw packet */
|
||||||
|
GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
|
||||||
|
aac_packet_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill buffer with data */
|
/* Fill buffer with data */
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
|
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
|
||||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||||
|
@ -663,9 +681,6 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
||||||
demux->audio_need_segment = FALSE;
|
demux->audio_need_segment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (buffer), data + 7 + codec_data,
|
|
||||||
demux->tag_data_size - codec_data);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
|
GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
|
||||||
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
|
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
|
||||||
GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
||||||
|
@ -678,6 +693,74 @@ beach:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_flv_parse_video_negotiate (GstFLVDemux * demux, guint32 codec_tag)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
gchar *codec_name = NULL;
|
||||||
|
|
||||||
|
/* Generate caps for that pad */
|
||||||
|
switch (codec_tag) {
|
||||||
|
case 2:
|
||||||
|
caps = gst_caps_new_simple ("video/x-flash-video", NULL);
|
||||||
|
codec_name = "Sorenson Video";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
caps = gst_caps_new_simple ("video/x-flash-screen", NULL);
|
||||||
|
codec_name = "Flash Screen Video";
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
|
||||||
|
codec_name = "On2 VP6 Video";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
caps = gst_caps_new_simple ("video/x-h264", NULL);
|
||||||
|
codec_name = "H.264/AVC Video";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!caps)) {
|
||||||
|
GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
|
||||||
|
demux->par_x, demux->par_y, NULL);
|
||||||
|
|
||||||
|
if (demux->video_codec_data) {
|
||||||
|
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
|
||||||
|
demux->video_codec_data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_pad_set_caps (demux->video_pad, caps);
|
||||||
|
|
||||||
|
if (G_LIKELY (ret)) {
|
||||||
|
/* Store the caps we have set */
|
||||||
|
demux->video_codec_tag = codec_tag;
|
||||||
|
|
||||||
|
if (codec_name) {
|
||||||
|
if (demux->taglist == NULL)
|
||||||
|
demux->taglist = gst_tag_list_new ();
|
||||||
|
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
||||||
|
GST_TAG_VIDEO_CODEC, codec_name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
|
||||||
|
GST_PTR_FORMAT, caps);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
|
||||||
|
GST_PTR_FORMAT, caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
size_t data_size)
|
size_t data_size)
|
||||||
|
@ -710,6 +793,8 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
codec_tag = flags & 0x0F;
|
codec_tag = flags & 0x0F;
|
||||||
if (codec_tag == 4 || codec_tag == 5) {
|
if (codec_tag == 4 || codec_tag == 5) {
|
||||||
codec_data = 2;
|
codec_data = 2;
|
||||||
|
} else if (codec_tag == 7) {
|
||||||
|
codec_data = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
|
GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
|
||||||
|
@ -717,9 +802,6 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
|
|
||||||
/* If we don't have our video pad created, then create it. */
|
/* If we don't have our video pad created, then create it. */
|
||||||
if (G_UNLIKELY (!demux->video_pad)) {
|
if (G_UNLIKELY (!demux->video_pad)) {
|
||||||
GstCaps *caps = NULL;
|
|
||||||
gchar *codec_name = NULL;
|
|
||||||
|
|
||||||
demux->video_pad = gst_pad_new ("video", GST_PAD_SRC);
|
demux->video_pad = gst_pad_new ("video", GST_PAD_SRC);
|
||||||
if (G_UNLIKELY (!demux->video_pad)) {
|
if (G_UNLIKELY (!demux->video_pad)) {
|
||||||
GST_WARNING_OBJECT (demux, "failed creating video pad");
|
GST_WARNING_OBJECT (demux, "failed creating video pad");
|
||||||
|
@ -729,54 +811,19 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
/* Make it active */
|
/* Make it active */
|
||||||
gst_pad_set_active (demux->video_pad, TRUE);
|
gst_pad_set_active (demux->video_pad, TRUE);
|
||||||
|
|
||||||
/* Generate caps for that pad */
|
if (!gst_flv_parse_video_negotiate (demux, codec_tag)) {
|
||||||
switch (codec_tag) {
|
|
||||||
case 2:
|
|
||||||
caps = gst_caps_new_simple ("video/x-flash-video", NULL);
|
|
||||||
codec_name = "Sorenson Video";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
caps = gst_caps_new_simple ("video/x-flash-screen", NULL);
|
|
||||||
codec_name = "Flash Screen Video";
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
|
|
||||||
codec_name = "On2 VP6 Video";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_WARNING_OBJECT (demux, "unsupported video codec tag %d", codec_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!caps)) {
|
|
||||||
GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
|
|
||||||
gst_object_unref (demux->video_pad);
|
gst_object_unref (demux->video_pad);
|
||||||
demux->video_pad = NULL;
|
demux->video_pad = NULL;
|
||||||
ret = GST_FLOW_ERROR;
|
ret = GST_FLOW_ERROR;
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
|
|
||||||
demux->par_x, demux->par_y, NULL);
|
|
||||||
|
|
||||||
/* When we ve set pixel-aspect-ratio we use that boolean to detect a
|
/* When we ve set pixel-aspect-ratio we use that boolean to detect a
|
||||||
* metadata tag that would come later and trigger a caps change */
|
* metadata tag that would come later and trigger a caps change */
|
||||||
demux->got_par = FALSE;
|
demux->got_par = FALSE;
|
||||||
|
|
||||||
gst_pad_set_caps (demux->video_pad, caps);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
|
||||||
caps);
|
GST_PAD_CAPS (demux->video_pad));
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
if (codec_name) {
|
|
||||||
if (demux->taglist == NULL)
|
|
||||||
demux->taglist = gst_tag_list_new ();
|
|
||||||
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
|
||||||
GST_TAG_VIDEO_CODEC, codec_name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store the caps we have set */
|
|
||||||
demux->video_codec_tag = codec_tag;
|
|
||||||
|
|
||||||
/* Set functions on the pad */
|
/* Set functions on the pad */
|
||||||
gst_pad_set_query_type_function (demux->video_pad,
|
gst_pad_set_query_type_function (demux->video_pad,
|
||||||
|
@ -801,54 +848,14 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
|
|
||||||
/* Check if caps have changed */
|
/* Check if caps have changed */
|
||||||
if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
|
if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
|
||||||
GstCaps *caps = NULL;
|
|
||||||
gchar *codec_name = NULL;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
|
GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
|
||||||
|
|
||||||
/* Generate caps for that pad */
|
gst_flv_parse_video_negotiate (demux, codec_tag);
|
||||||
switch (codec_tag) {
|
|
||||||
case 2:
|
|
||||||
caps = gst_caps_new_simple ("video/x-flash-video", NULL);
|
|
||||||
codec_name = "Sorenson Video";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
caps = gst_caps_new_simple ("video/x-flash-screen", NULL);
|
|
||||||
codec_name = "Flash Screen Video";
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
caps = gst_caps_new_simple ("video/x-vp6", NULL);
|
|
||||||
codec_name = "On2 VP6 Video";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_WARNING_OBJECT (demux, "unsupported video codec tag %d", codec_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!caps)) {
|
|
||||||
GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
|
|
||||||
demux->par_x, demux->par_y, NULL);
|
|
||||||
|
|
||||||
/* When we ve set pixel-aspect-ratio we use that boolean to detect a
|
/* When we ve set pixel-aspect-ratio we use that boolean to detect a
|
||||||
* metadata tag that would come later and trigger a caps change */
|
* metadata tag that would come later and trigger a caps change */
|
||||||
demux->got_par = FALSE;
|
demux->got_par = FALSE;
|
||||||
|
|
||||||
gst_pad_set_caps (demux->video_pad, caps);
|
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
if (codec_name) {
|
|
||||||
if (demux->taglist == NULL)
|
|
||||||
demux->taglist = gst_tag_list_new ();
|
|
||||||
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
|
|
||||||
GST_TAG_VIDEO_CODEC, codec_name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store the caps we have set */
|
|
||||||
demux->video_codec_tag = codec_tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push taglist if present */
|
/* Push taglist if present */
|
||||||
|
@ -886,6 +893,36 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
|
|
||||||
demux->video_linked = TRUE;
|
demux->video_linked = TRUE;
|
||||||
|
|
||||||
|
memcpy (GST_BUFFER_DATA (buffer), data + 7 + codec_data,
|
||||||
|
MIN (demux->tag_data_size - codec_data, GST_BUFFER_SIZE (buffer)));
|
||||||
|
|
||||||
|
if (demux->video_codec_tag == 7) {
|
||||||
|
guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
|
||||||
|
|
||||||
|
switch (avc_packet_type) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
/* AVCDecoderConfigurationRecord data */
|
||||||
|
GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
|
||||||
|
if (demux->video_codec_data) {
|
||||||
|
gst_buffer_unref (demux->video_codec_data);
|
||||||
|
}
|
||||||
|
demux->video_codec_data = buffer;
|
||||||
|
/* Use that buffer data in the caps */
|
||||||
|
gst_flv_parse_video_negotiate (demux, codec_tag);
|
||||||
|
goto beach;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
/* H.264 NALU packet */
|
||||||
|
GST_LOG_OBJECT (demux, "got a H.264 NALU audio packet");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
|
||||||
|
avc_packet_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill buffer with data */
|
/* Fill buffer with data */
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
|
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
|
||||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||||
|
@ -934,10 +971,6 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
||||||
demux->video_need_segment = FALSE;
|
demux->video_need_segment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: safety checks */
|
|
||||||
memcpy (GST_BUFFER_DATA (buffer), data + 7 + codec_data,
|
|
||||||
demux->tag_data_size - codec_data);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
|
GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
|
||||||
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
|
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
|
||||||
", keyframe (%d)", GST_BUFFER_SIZE (buffer),
|
", keyframe (%d)", GST_BUFFER_SIZE (buffer),
|
||||||
|
|
|
@ -308,6 +308,8 @@ gst_dshowaudiodec_init (GstDshowAudioDec * adec,
|
||||||
adec->layer = 0;
|
adec->layer = 0;
|
||||||
adec->codec_data = NULL;
|
adec->codec_data = NULL;
|
||||||
|
|
||||||
|
adec->last_ret = GST_FLOW_OK;
|
||||||
|
|
||||||
CoInitializeEx (NULL, COINIT_MULTITHREADED);
|
CoInitializeEx (NULL, COINIT_MULTITHREADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +422,6 @@ end:
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
|
gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
|
GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
|
||||||
gboolean discount = FALSE;
|
gboolean discount = FALSE;
|
||||||
|
|
||||||
|
@ -436,13 +437,20 @@ gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
|
||||||
/* setup dshow graph */
|
/* setup dshow graph */
|
||||||
if (!gst_dshowaudiodec_setup_graph (adec)) {
|
if (!gst_dshowaudiodec_setup_graph (adec)) {
|
||||||
return GST_FLOW_ERROR;
|
adec->last_ret = GST_FLOW_ERROR;
|
||||||
|
goto beach;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!adec->gstdshowsrcfilter) {
|
if (!adec->gstdshowsrcfilter) {
|
||||||
/* we are not setup */
|
/* we are not setup */
|
||||||
ret = GST_FLOW_WRONG_STATE;
|
adec->last_ret = GST_FLOW_WRONG_STATE;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_FLOW_IS_FATAL (adec->last_ret)) {
|
||||||
|
GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error "
|
||||||
|
"%s", gst_flow_get_name (adec->last_ret));
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +478,7 @@ gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
beach:
|
beach:
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
gst_object_unref (adec);
|
gst_object_unref (adec);
|
||||||
return ret;
|
return adec->last_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -509,7 +517,7 @@ gst_dshowaudiodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
/* buffer is in our segment allocate a new out buffer and clip it if needed */
|
/* buffer is in our segment allocate a new out buffer and clip it if needed */
|
||||||
|
|
||||||
/* allocate a new buffer for raw audio */
|
/* allocate a new buffer for raw audio */
|
||||||
gst_pad_alloc_buffer (adec->srcpad, GST_BUFFER_OFFSET_NONE,
|
adec->last_ret = gst_pad_alloc_buffer (adec->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||||
size, GST_PAD_CAPS (adec->srcpad), &out_buf);
|
size, GST_PAD_CAPS (adec->srcpad), &out_buf);
|
||||||
if (!out_buf) {
|
if (!out_buf) {
|
||||||
GST_CAT_ERROR_OBJECT (dshowaudiodec_debug, adec,
|
GST_CAT_ERROR_OBJECT (dshowaudiodec_debug, adec,
|
||||||
|
@ -518,10 +526,10 @@ gst_dshowaudiodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set buffer properties */
|
/* set buffer properties */
|
||||||
GST_BUFFER_SIZE (out_buf) = size;
|
|
||||||
GST_BUFFER_TIMESTAMP (out_buf) = buf_start;
|
GST_BUFFER_TIMESTAMP (out_buf) = buf_start;
|
||||||
GST_BUFFER_DURATION (out_buf) = buf_stop - buf_start;
|
GST_BUFFER_DURATION (out_buf) = buf_stop - buf_start;
|
||||||
memcpy (GST_BUFFER_DATA (out_buf), buffer, size);
|
memcpy (GST_BUFFER_DATA (out_buf), buffer,
|
||||||
|
MIN (size, GST_BUFFER_SIZE (out_buf)));
|
||||||
|
|
||||||
/* we have to remove some heading samples */
|
/* we have to remove some heading samples */
|
||||||
if (clip_start > buf_start) {
|
if (clip_start > buf_start) {
|
||||||
|
@ -560,7 +568,7 @@ gst_dshowaudiodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
GST_BUFFER_DURATION (out_buf)),
|
GST_BUFFER_DURATION (out_buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (out_buf)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (out_buf)));
|
||||||
|
|
||||||
gst_pad_push (adec->srcpad, out_buf);
|
adec->last_ret = gst_pad_push (adec->srcpad, out_buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -608,6 +616,9 @@ gst_dshowaudiodec_sink_event (GstPad * pad, GstEvent * event)
|
||||||
ret = gst_pad_event_default (pad, event);
|
ret = gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (adec);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +910,6 @@ gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec)
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
adec->setup = TRUE;
|
adec->setup = TRUE;
|
||||||
end:
|
end:
|
||||||
gst_object_unref (adec);
|
|
||||||
if (input_format)
|
if (input_format)
|
||||||
g_free (input_format);
|
g_free (input_format);
|
||||||
if (gstdshowinterface)
|
if (gstdshowinterface)
|
||||||
|
|
|
@ -69,6 +69,8 @@ struct _GstDshowAudioDec
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
|
GstFlowReturn last_ret;
|
||||||
|
|
||||||
/* filters interfaces*/
|
/* filters interfaces*/
|
||||||
IBaseFilter *srcfilter;
|
IBaseFilter *srcfilter;
|
||||||
IGstDshowInterface *gstdshowsrcfilter;
|
IGstDshowInterface *gstdshowsrcfilter;
|
||||||
|
|
|
@ -329,6 +329,8 @@ gst_dshowvideodec_init (GstDshowVideoDec * vdec,
|
||||||
vdec->decfilter = NULL;
|
vdec->decfilter = NULL;
|
||||||
vdec->sinkfilter = NULL;
|
vdec->sinkfilter = NULL;
|
||||||
|
|
||||||
|
vdec->last_ret = GST_FLOW_OK;
|
||||||
|
|
||||||
vdec->filtergraph = NULL;
|
vdec->filtergraph = NULL;
|
||||||
vdec->mediafilter = NULL;
|
vdec->mediafilter = NULL;
|
||||||
vdec->gstdshowsrcfilter = NULL;
|
vdec->gstdshowsrcfilter = NULL;
|
||||||
|
@ -659,20 +661,28 @@ gst_dshowvideodec_sink_event (GstPad * pad, GstEvent * event)
|
||||||
ret = gst_pad_event_default (pad, event);
|
ret = gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (vdec);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer)
|
gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
|
GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
|
||||||
gboolean discount = FALSE;
|
gboolean discount = FALSE;
|
||||||
GstClockTime stop;
|
GstClockTime stop;
|
||||||
|
|
||||||
if (!vdec->gstdshowsrcfilter) {
|
if (!vdec->gstdshowsrcfilter) {
|
||||||
/* we are not setup */
|
/* we are not setup */
|
||||||
ret = GST_FLOW_WRONG_STATE;
|
vdec->last_ret = GST_FLOW_WRONG_STATE;
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_FLOW_IS_FATAL (vdec->last_ret)) {
|
||||||
|
GST_DEBUG_OBJECT (vdec, "last decoding iteration generated a fatal error "
|
||||||
|
"%s", gst_flow_get_name (vdec->last_ret));
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,7 +717,7 @@ beach:
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
gst_object_unref (vdec);
|
gst_object_unref (vdec);
|
||||||
|
|
||||||
return ret;
|
return vdec->last_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -733,8 +743,9 @@ gst_dshowvideodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buffer is in our segment allocate a new out buffer and clip its timestamps */
|
/* buffer is in our segment allocate a new out buffer and clip its
|
||||||
gst_pad_alloc_buffer (vdec->srcpad, GST_BUFFER_OFFSET_NONE,
|
* timestamps */
|
||||||
|
vdec->last_ret = gst_pad_alloc_buffer (vdec->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||||
size, GST_PAD_CAPS (vdec->srcpad), &buf);
|
size, GST_PAD_CAPS (vdec->srcpad), &buf);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
GST_CAT_WARNING_OBJECT (dshowvideodec_debug, vdec,
|
GST_CAT_WARNING_OBJECT (dshowvideodec_debug, vdec,
|
||||||
|
@ -743,7 +754,6 @@ gst_dshowvideodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set buffer properties */
|
/* set buffer properties */
|
||||||
GST_BUFFER_SIZE (buf) = size;
|
|
||||||
GST_BUFFER_TIMESTAMP (buf) = clip_start;
|
GST_BUFFER_TIMESTAMP (buf) = clip_start;
|
||||||
GST_BUFFER_DURATION (buf) = clip_stop - clip_start;
|
GST_BUFFER_DURATION (buf) = clip_stop - clip_start;
|
||||||
|
|
||||||
|
@ -760,7 +770,7 @@ gst_dshowvideodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
buffer + (size - ((line + 1) * (stride))), stride);
|
buffer + (size - ((line + 1) * (stride))), stride);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy (GST_BUFFER_DATA (buf), buffer, size);
|
memcpy (GST_BUFFER_DATA (buf), buffer, MIN (size, GST_BUFFER_SIZE (buf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec,
|
GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec,
|
||||||
|
@ -771,7 +781,7 @@ gst_dshowvideodec_push_buffer (byte * buffer, long size, byte * src_object,
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
||||||
|
|
||||||
/* push the buffer downstream */
|
/* push the buffer downstream */
|
||||||
gst_pad_push (vdec->srcpad, buf);
|
vdec->last_ret = gst_pad_push (vdec->srcpad, buf);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -781,6 +791,7 @@ static GstCaps *
|
||||||
gst_dshowvideodec_src_getcaps (GstPad * pad)
|
gst_dshowvideodec_src_getcaps (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
|
GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
|
||||||
if (!vdec->srccaps)
|
if (!vdec->srccaps)
|
||||||
vdec->srccaps = gst_caps_new_empty ();
|
vdec->srccaps = gst_caps_new_empty ();
|
||||||
|
@ -795,7 +806,7 @@ gst_dshowvideodec_src_getcaps (GstPad * pad)
|
||||||
&output_pin)) {
|
&output_pin)) {
|
||||||
GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
|
GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
|
||||||
("failed getting ouput pin from the decoder"), (NULL));
|
("failed getting ouput pin from the decoder"), (NULL));
|
||||||
return NULL;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = IPin_EnumMediaTypes (output_pin, &enum_mediatypes);
|
hres = IPin_EnumMediaTypes (output_pin, &enum_mediatypes);
|
||||||
|
@ -848,9 +859,12 @@ gst_dshowvideodec_src_getcaps (GstPad * pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vdec->srccaps)
|
if (vdec->srccaps)
|
||||||
return gst_caps_ref (vdec->srccaps);
|
caps = gst_caps_ref (vdec->srccaps);
|
||||||
|
|
||||||
return NULL;
|
beach:
|
||||||
|
gst_object_unref (vdec);
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
|
@ -71,6 +71,8 @@ struct _GstDshowVideoDec
|
||||||
/* caps of our src pad */
|
/* caps of our src pad */
|
||||||
GstCaps *srccaps;
|
GstCaps *srccaps;
|
||||||
|
|
||||||
|
GstFlowReturn last_ret;
|
||||||
|
|
||||||
/* list of dshow mediatypes coresponding to the caps list */
|
/* list of dshow mediatypes coresponding to the caps list */
|
||||||
GList *mediatypes;
|
GList *mediatypes;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue