mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
asfmux: port to 0.11
This commit is contained in:
parent
1fa5624762
commit
e79cae3002
8 changed files with 357 additions and 246 deletions
|
@ -300,7 +300,7 @@ AG_GST_DEFAULT_ELEMENTS
|
||||||
dnl *** plug-ins to include ***
|
dnl *** plug-ins to include ***
|
||||||
dnl Non ported plugins (non-dependant, then dependant)
|
dnl Non ported plugins (non-dependant, then dependant)
|
||||||
dnl Make sure you have a space before and after all plugins
|
dnl Make sure you have a space before and after all plugins
|
||||||
GST_PLUGINS_NONPORTED=" aiff asfmux \
|
GST_PLUGINS_NONPORTED=" aiff \
|
||||||
camerabin cdxaparse coloreffects \
|
camerabin cdxaparse coloreffects \
|
||||||
dccp faceoverlay festival \
|
dccp faceoverlay festival \
|
||||||
fieldanalysis freeverb freeze frei0r gaudieffects \
|
fieldanalysis freeverb freeze frei0r gaudieffects \
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <gst/gst-i18n-plugin.h>
|
#include <gst/gst-i18n-plugin.h>
|
||||||
#include "gstasfmux.h"
|
#include "gstasfmux.h"
|
||||||
|
|
||||||
|
@ -149,12 +150,14 @@ static GstStaticPadTemplate audio_sink_factory =
|
||||||
"audio/mpeg, layer = (int) 3, mpegversion = (int) 1, "
|
"audio/mpeg, layer = (int) 3, mpegversion = (int) 1, "
|
||||||
"channels = (int) [1,2], rate = (int) [8000,96000]"));
|
"channels = (int) [1,2], rate = (int) [8000,96000]"));
|
||||||
|
|
||||||
static void gst_asf_mux_base_init (gpointer g_class);
|
|
||||||
static void gst_asf_mux_class_init (GstAsfMuxClass * klass);
|
static void gst_asf_mux_class_init (GstAsfMuxClass * klass);
|
||||||
static void gst_asf_mux_init (GstAsfMux * asfmux);
|
static void gst_asf_mux_init (GstAsfMux * asfmux);
|
||||||
|
|
||||||
|
static gboolean gst_asf_mux_audio_set_caps (GstPad * pad, GstCaps * caps);
|
||||||
|
static gboolean gst_asf_mux_video_set_caps (GstPad * pad, GstCaps * caps);
|
||||||
|
|
||||||
static GstPad *gst_asf_mux_request_new_pad (GstElement * element,
|
static GstPad *gst_asf_mux_request_new_pad (GstElement * element,
|
||||||
GstPadTemplate * templ, const gchar * name);
|
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||||
static void gst_asf_mux_set_property (GObject * object,
|
static void gst_asf_mux_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_asf_mux_get_property (GObject * object,
|
static void gst_asf_mux_get_property (GObject * object,
|
||||||
|
@ -162,7 +165,8 @@ static void gst_asf_mux_get_property (GObject * object,
|
||||||
static GstStateChangeReturn gst_asf_mux_change_state (GstElement * element,
|
static GstStateChangeReturn gst_asf_mux_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
|
||||||
static gboolean gst_asf_mux_sink_event (GstPad * pad, GstEvent * event);
|
static gboolean gst_asf_mux_sink_event (GstCollectPads * pads,
|
||||||
|
GstCollectData * cdata, GstEvent * event, GstAsfMux * asfmux);
|
||||||
|
|
||||||
static void gst_asf_mux_pad_reset (GstAsfPad * data);
|
static void gst_asf_mux_pad_reset (GstAsfPad * data);
|
||||||
static GstFlowReturn gst_asf_mux_collected (GstCollectPads * collect,
|
static GstFlowReturn gst_asf_mux_collected (GstCollectPads * collect,
|
||||||
|
@ -178,7 +182,7 @@ gst_asf_mux_get_type (void)
|
||||||
if (!asfmux_type) {
|
if (!asfmux_type) {
|
||||||
static const GTypeInfo asfmux_info = {
|
static const GTypeInfo asfmux_info = {
|
||||||
sizeof (GstAsfMuxClass),
|
sizeof (GstAsfMuxClass),
|
||||||
gst_asf_mux_base_init,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
(GClassInitFunc) gst_asf_mux_class_init,
|
(GClassInitFunc) gst_asf_mux_class_init,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -233,26 +237,6 @@ gst_asf_mux_reset (GstAsfMux * asfmux)
|
||||||
gst_tag_setter_reset_tags (GST_TAG_SETTER (asfmux));
|
gst_tag_setter_reset_tags (GST_TAG_SETTER (asfmux));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_asf_mux_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&src_factory));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&audio_sink_factory));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&video_sink_factory));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class, "ASF muxer",
|
|
||||||
"Codec/Muxer",
|
|
||||||
"Muxes audio and video into an ASF stream",
|
|
||||||
"Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (asfmux_debug, "asfmux", 0, "Muxer for ASF streams");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_asf_mux_finalize (GObject * object)
|
gst_asf_mux_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -321,17 +305,26 @@ gst_asf_mux_class_init (GstAsfMuxClass * klass)
|
||||||
gstelement_class->request_new_pad =
|
gstelement_class->request_new_pad =
|
||||||
GST_DEBUG_FUNCPTR (gst_asf_mux_request_new_pad);
|
GST_DEBUG_FUNCPTR (gst_asf_mux_request_new_pad);
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_asf_mux_change_state);
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_asf_mux_change_state);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&src_factory));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&audio_sink_factory));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&video_sink_factory));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class, "ASF muxer",
|
||||||
|
"Codec/Muxer",
|
||||||
|
"Muxes audio and video into an ASF stream",
|
||||||
|
"Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (asfmux_debug, "asfmux", 0, "Muxer for ASF streams");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_asf_mux_init (GstAsfMux * asfmux)
|
gst_asf_mux_init (GstAsfMux * asfmux)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
|
||||||
|
|
||||||
asfmux->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
asfmux->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
||||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (asfmux->srcpad));
|
|
||||||
gst_pad_set_caps (asfmux->srcpad, caps);
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
gst_pad_use_fixed_caps (asfmux->srcpad);
|
gst_pad_use_fixed_caps (asfmux->srcpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (asfmux), asfmux->srcpad);
|
gst_element_add_pad (GST_ELEMENT (asfmux), asfmux->srcpad);
|
||||||
|
|
||||||
|
@ -339,6 +332,9 @@ gst_asf_mux_init (GstAsfMux * asfmux)
|
||||||
gst_collect_pads_set_function (asfmux->collect,
|
gst_collect_pads_set_function (asfmux->collect,
|
||||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_asf_mux_collected),
|
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_asf_mux_collected),
|
||||||
asfmux);
|
asfmux);
|
||||||
|
gst_collect_pads_set_event_function (asfmux->collect,
|
||||||
|
(GstCollectPadsEventFunction) GST_DEBUG_FUNCPTR (gst_asf_mux_sink_event),
|
||||||
|
asfmux);
|
||||||
|
|
||||||
asfmux->payloads = NULL;
|
asfmux->payloads = NULL;
|
||||||
asfmux->prop_packet_size = DEFAULT_PACKET_SIZE;
|
asfmux->prop_packet_size = DEFAULT_PACKET_SIZE;
|
||||||
|
@ -350,14 +346,26 @@ gst_asf_mux_init (GstAsfMux * asfmux)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_asf_mux_sink_event (GstPad * pad, GstEvent * event)
|
gst_asf_mux_sink_event (GstCollectPads * pads, GstCollectData * cdata,
|
||||||
|
GstEvent * event, GstAsfMux * asfmux)
|
||||||
{
|
{
|
||||||
gboolean ret;
|
GstAsfPad *asfpad = (GstAsfPad *) cdata;
|
||||||
GstAsfMux *asfmux;
|
gboolean ret = TRUE;
|
||||||
GstAsfPad *asfpad = (GstAsfPad *) gst_pad_get_element_private (pad);
|
|
||||||
|
|
||||||
asfmux = GST_ASF_MUX_CAST (gst_pad_get_parent (pad));
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
gst_event_parse_caps (event, &caps);
|
||||||
|
if (asfpad->is_audio)
|
||||||
|
ret = gst_asf_mux_audio_set_caps (cdata->pad, caps);
|
||||||
|
else
|
||||||
|
ret = gst_asf_mux_video_set_caps (cdata->pad, caps);
|
||||||
|
gst_event_unref (event);
|
||||||
|
event = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_EVENT_TAG:{
|
case GST_EVENT_TAG:{
|
||||||
GST_DEBUG_OBJECT (asfmux, "received tag event");
|
GST_DEBUG_OBJECT (asfmux, "received tag event");
|
||||||
/* we discard tag events that come after we started
|
/* we discard tag events that come after we started
|
||||||
|
@ -374,7 +382,7 @@ gst_asf_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
gst_tag_setter_merge_tags (setter, list, mode);
|
gst_tag_setter_merge_tags (setter, list, mode);
|
||||||
} else {
|
} else {
|
||||||
if (asfpad->taglist == NULL) {
|
if (asfpad->taglist == NULL) {
|
||||||
asfpad->taglist = gst_tag_list_new ();
|
asfpad->taglist = gst_tag_list_new_empty ();
|
||||||
}
|
}
|
||||||
gst_tag_list_insert (asfpad->taglist, list, GST_TAG_MERGE_REPLACE);
|
gst_tag_list_insert (asfpad->taglist, list, GST_TAG_MERGE_REPLACE);
|
||||||
}
|
}
|
||||||
|
@ -385,8 +393,9 @@ gst_asf_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = asfmux->collect_event (pad, event);
|
if (event != NULL)
|
||||||
gst_object_unref (asfmux);
|
return gst_collect_pads_event_default (pads, cdata, event, FALSE);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,10 +412,9 @@ static GstFlowReturn
|
||||||
gst_asf_mux_push_buffer (GstAsfMux * asfmux, GstBuffer * buf)
|
gst_asf_mux_push_buffer (GstAsfMux * asfmux, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (asfmux->srcpad));
|
|
||||||
ret = gst_pad_push (asfmux->srcpad, buf);
|
ret = gst_pad_push (asfmux->srcpad, buf);
|
||||||
if (ret == GST_FLOW_OK)
|
if (ret == GST_FLOW_OK)
|
||||||
asfmux->file_size += GST_BUFFER_SIZE (buf);
|
asfmux->file_size += gst_buffer_get_size (buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +513,7 @@ gst_asf_mux_get_content_description_tags (GstAsfMux * asfmux,
|
||||||
if (asftags->tags != NULL) {
|
if (asftags->tags != NULL) {
|
||||||
gst_tag_list_free (asftags->tags);
|
gst_tag_list_free (asftags->tags);
|
||||||
}
|
}
|
||||||
asftags->tags = gst_tag_list_new ();
|
asftags->tags = gst_tag_list_new_empty ();
|
||||||
asftags->cont_desc_size = 0;
|
asftags->cont_desc_size = 0;
|
||||||
asftags->ext_cont_desc_size = 0;
|
asftags->ext_cont_desc_size = 0;
|
||||||
|
|
||||||
|
@ -633,7 +641,7 @@ gst_asf_mux_get_headers_size (GstAsfMux * asfmux)
|
||||||
size += ASF_VIDEO_SPECIFIC_DATA_SIZE;
|
size += ASF_VIDEO_SPECIFIC_DATA_SIZE;
|
||||||
|
|
||||||
if (asfpad->codec_data)
|
if (asfpad->codec_data)
|
||||||
size += GST_BUFFER_SIZE (asfpad->codec_data);
|
size += gst_buffer_get_size (asfpad->codec_data);
|
||||||
|
|
||||||
stream_num++;
|
stream_num++;
|
||||||
}
|
}
|
||||||
|
@ -713,7 +721,7 @@ gst_asf_mux_write_stream_properties (GstAsfMux * asfmux, guint8 ** buf,
|
||||||
|
|
||||||
/* codec specific data length */
|
/* codec specific data length */
|
||||||
if (asfpad->codec_data)
|
if (asfpad->codec_data)
|
||||||
codec_data_length = GST_BUFFER_SIZE (asfpad->codec_data);
|
codec_data_length = gst_buffer_get_size (asfpad->codec_data);
|
||||||
if (asfpad->is_audio)
|
if (asfpad->is_audio)
|
||||||
media_specific_data_length = ASF_AUDIO_SPECIFIC_DATA_SIZE;
|
media_specific_data_length = ASF_AUDIO_SPECIFIC_DATA_SIZE;
|
||||||
else
|
else
|
||||||
|
@ -800,7 +808,7 @@ gst_asf_mux_write_stream_properties (GstAsfMux * asfmux, guint8 ** buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codec_data_length > 0)
|
if (codec_data_length > 0)
|
||||||
memcpy (*buf, GST_BUFFER_DATA (asfpad->codec_data), codec_data_length);
|
gst_buffer_extract (asfpad->codec_data, 0, *buf, codec_data_length);
|
||||||
|
|
||||||
*buf += codec_data_length;
|
*buf += codec_data_length;
|
||||||
}
|
}
|
||||||
|
@ -1286,6 +1294,9 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
guint64 padding = asfmux->prop_padding;
|
guint64 padding = asfmux->prop_padding;
|
||||||
|
GstSegment segment;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
if (padding < ASF_PADDING_OBJECT_SIZE)
|
if (padding < ASF_PADDING_OBJECT_SIZE)
|
||||||
padding = 0;
|
padding = 0;
|
||||||
|
|
||||||
|
@ -1293,9 +1304,13 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
||||||
GST_INFO_OBJECT (asfmux, "Writing headers");
|
GST_INFO_OBJECT (asfmux, "Writing headers");
|
||||||
asfmux->state = GST_ASF_MUX_STATE_HEADERS;
|
asfmux->state = GST_ASF_MUX_STATE_HEADERS;
|
||||||
|
|
||||||
|
caps = gst_pad_get_pad_template_caps (asfmux->srcpad);
|
||||||
|
gst_pad_set_caps (asfmux->srcpad, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
/* let downstream know we think in BYTES and expect to do seeking later */
|
/* let downstream know we think in BYTES and expect to do seeking later */
|
||||||
gst_pad_push_event (asfmux->srcpad,
|
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
|
gst_pad_push_event (asfmux->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
gst_asf_generate_file_id (&asfmux->file_id);
|
gst_asf_generate_file_id (&asfmux->file_id);
|
||||||
|
|
||||||
|
@ -1318,14 +1333,16 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
||||||
asftags->cont_desc_size +
|
asftags->cont_desc_size +
|
||||||
asftags->ext_cont_desc_size +
|
asftags->ext_cont_desc_size +
|
||||||
metadata_obj_size + padding + ASF_DATA_OBJECT_SIZE);
|
metadata_obj_size + padding + ASF_DATA_OBJECT_SIZE);
|
||||||
bufdata = GST_BUFFER_DATA (buf);
|
|
||||||
|
|
||||||
gst_asf_mux_write_header_object (asfmux, &bufdata, GST_BUFFER_SIZE (buf) -
|
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||||
|
bufdata = map.data;
|
||||||
|
|
||||||
|
gst_asf_mux_write_header_object (asfmux, &bufdata, map.size -
|
||||||
ASF_DATA_OBJECT_SIZE, 2 + stream_num);
|
ASF_DATA_OBJECT_SIZE, 2 + stream_num);
|
||||||
|
|
||||||
/* get the position of the file properties object for
|
/* get the position of the file properties object for
|
||||||
* updating it in gst_asf_mux_stop_file */
|
* updating it in gst_asf_mux_stop_file */
|
||||||
asfmux->file_properties_object_position = bufdata - GST_BUFFER_DATA (buf);
|
asfmux->file_properties_object_position = bufdata - map.data;
|
||||||
gst_asf_mux_write_file_properties (asfmux, &bufdata);
|
gst_asf_mux_write_file_properties (asfmux, &bufdata);
|
||||||
|
|
||||||
for (walk = asfmux->collect->data; walk; walk = g_slist_next (walk)) {
|
for (walk = asfmux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||||
|
@ -1361,7 +1378,7 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
||||||
gst_asf_mux_write_padding_object (asfmux, &bufdata, padding);
|
gst_asf_mux_write_padding_object (asfmux, &bufdata, padding);
|
||||||
|
|
||||||
/* store data object position for later updating some fields */
|
/* store data object position for later updating some fields */
|
||||||
asfmux->data_object_position = bufdata - GST_BUFFER_DATA (buf);
|
asfmux->data_object_position = bufdata - map.data;
|
||||||
gst_asf_mux_write_data_object (asfmux, &bufdata);
|
gst_asf_mux_write_data_object (asfmux, &bufdata);
|
||||||
|
|
||||||
/* set streamheader in source pad if 'streamable' */
|
/* set streamheader in source pad if 'streamable' */
|
||||||
|
@ -1369,17 +1386,18 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
||||||
g_value_init (&streamheader, GST_TYPE_ARRAY);
|
g_value_init (&streamheader, GST_TYPE_ARRAY);
|
||||||
gst_asf_mux_put_buffer_in_streamheader (&streamheader, buf);
|
gst_asf_mux_put_buffer_in_streamheader (&streamheader, buf);
|
||||||
|
|
||||||
caps = gst_caps_ref (GST_PAD_CAPS (asfmux->srcpad));
|
caps = gst_pad_get_current_caps (asfmux->srcpad);
|
||||||
caps = gst_caps_make_writable (caps);
|
caps = gst_caps_make_writable (caps);
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
gst_structure_set_value (structure, "streamheader", &streamheader);
|
gst_structure_set_value (structure, "streamheader", &streamheader);
|
||||||
gst_pad_set_caps (asfmux->srcpad, caps);
|
gst_pad_set_caps (asfmux->srcpad, caps);
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
|
||||||
g_value_unset (&streamheader);
|
g_value_unset (&streamheader);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (bufdata - GST_BUFFER_DATA (buf) == GST_BUFFER_SIZE (buf));
|
g_assert (bufdata - map.data == map.size);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
return gst_asf_mux_push_buffer (asfmux, buf);
|
return gst_asf_mux_push_buffer (asfmux, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1423,11 +1441,11 @@ gst_asf_mux_add_simple_index_entry (GstAsfMux * asfmux,
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_asf_mux_send_packet (GstAsfMux * asfmux, GstBuffer * buf)
|
gst_asf_mux_send_packet (GstAsfMux * asfmux, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
g_assert (GST_BUFFER_SIZE (buf) == asfmux->packet_size);
|
g_assert (gst_buffer_get_size (buf) == asfmux->packet_size);
|
||||||
asfmux->total_data_packets++;
|
asfmux->total_data_packets++;
|
||||||
GST_LOG_OBJECT (asfmux,
|
GST_LOG_OBJECT (asfmux,
|
||||||
"Pushing a packet of size %u and timestamp %" G_GUINT64_FORMAT,
|
"Pushing a packet of size %u and timestamp %" G_GUINT64_FORMAT,
|
||||||
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
gst_buffer_get_size (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||||
GST_LOG_OBJECT (asfmux, "Total data packets: %" G_GUINT64_FORMAT,
|
GST_LOG_OBJECT (asfmux, "Total data packets: %" G_GUINT64_FORMAT,
|
||||||
asfmux->total_data_packets);
|
asfmux->total_data_packets);
|
||||||
return gst_asf_mux_push_buffer (asfmux, buf);
|
return gst_asf_mux_push_buffer (asfmux, buf);
|
||||||
|
@ -1457,6 +1475,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
AsfPayload *payload;
|
AsfPayload *payload;
|
||||||
guint32 payload_size;
|
guint32 payload_size;
|
||||||
guint offset;
|
guint offset;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
if (asfmux->payloads == NULL)
|
if (asfmux->payloads == NULL)
|
||||||
return GST_FLOW_OK; /* nothing to send is ok */
|
return GST_FLOW_OK; /* nothing to send is ok */
|
||||||
|
@ -1464,10 +1483,11 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
GST_LOG_OBJECT (asfmux, "Flushing payloads");
|
GST_LOG_OBJECT (asfmux, "Flushing payloads");
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (asfmux->packet_size);
|
buf = gst_buffer_new_and_alloc (asfmux->packet_size);
|
||||||
memset (GST_BUFFER_DATA (buf), 0, asfmux->packet_size);
|
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||||
|
memset (map.data, 0, asfmux->packet_size);
|
||||||
|
|
||||||
/* 1 for the multiple payload flags */
|
/* 1 for the multiple payload flags */
|
||||||
data = GST_BUFFER_DATA (buf) + asfmux->payload_parsing_info_size + 1;
|
data = map.data + asfmux->payload_parsing_info_size + 1;
|
||||||
size_left = asfmux->packet_size - asfmux->payload_parsing_info_size - 1;
|
size_left = asfmux->packet_size - asfmux->payload_parsing_info_size - 1;
|
||||||
|
|
||||||
has_keyframe = FALSE;
|
has_keyframe = FALSE;
|
||||||
|
@ -1509,7 +1529,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
GST_DEBUG_OBJECT (asfmux, "replicated data length: %d",
|
GST_DEBUG_OBJECT (asfmux, "replicated data length: %d",
|
||||||
(gint) payload->replicated_data_length);
|
(gint) payload->replicated_data_length);
|
||||||
GST_DEBUG_OBJECT (asfmux, "payload size: %u",
|
GST_DEBUG_OBJECT (asfmux, "payload size: %u",
|
||||||
GST_BUFFER_SIZE (payload->data));
|
gst_buffer_get_size (payload->data));
|
||||||
GST_DEBUG_OBJECT (asfmux, "presentation time: %" G_GUINT32_FORMAT " (%"
|
GST_DEBUG_OBJECT (asfmux, "presentation time: %" G_GUINT32_FORMAT " (%"
|
||||||
GST_TIME_FORMAT ")", payload->presentation_time,
|
GST_TIME_FORMAT ")", payload->presentation_time,
|
||||||
GST_TIME_ARGS (payload->presentation_time * GST_MSECOND));
|
GST_TIME_ARGS (payload->presentation_time * GST_MSECOND));
|
||||||
|
@ -1554,7 +1574,8 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
payload = (AsfPayload *) aux->data;
|
payload = (AsfPayload *) aux->data;
|
||||||
asfmux->payloads = g_slist_remove (asfmux->payloads, payload);
|
asfmux->payloads = g_slist_remove (asfmux->payloads, payload);
|
||||||
asfmux->payload_data_size -=
|
asfmux->payload_data_size -=
|
||||||
(GST_BUFFER_SIZE (payload->data) + ASF_MULTIPLE_PAYLOAD_HEADER_SIZE);
|
(gst_buffer_get_size (payload->data) +
|
||||||
|
ASF_MULTIPLE_PAYLOAD_HEADER_SIZE);
|
||||||
gst_asf_payload_free (payload);
|
gst_asf_payload_free (payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1586,7 +1607,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
asfmux->payload_data_size);
|
asfmux->payload_data_size);
|
||||||
|
|
||||||
/* fill payload parsing info */
|
/* fill payload parsing info */
|
||||||
data = GST_BUFFER_DATA (buf);
|
data = map.data;
|
||||||
/* flags */
|
/* flags */
|
||||||
GST_WRITE_UINT8 (data, (0x0 << 7) | /* no error correction */
|
GST_WRITE_UINT8 (data, (0x0 << 7) | /* no error correction */
|
||||||
(ASF_FIELD_TYPE_DWORD << 5) | /* packet length type */
|
(ASF_FIELD_TYPE_DWORD << 5) | /* packet length type */
|
||||||
|
@ -1637,11 +1658,12 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
||||||
|
|
||||||
/* multiple payloads flags */
|
/* multiple payloads flags */
|
||||||
GST_WRITE_UINT8 (data + offset, 0x2 << 6 | payloads_count);
|
GST_WRITE_UINT8 (data + offset, 0x2 << 6 | payloads_count);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
if (payloads_count == 0) {
|
if (payloads_count == 0) {
|
||||||
GST_WARNING_OBJECT (asfmux, "Sending packet without any payload");
|
GST_WARNING_OBJECT (asfmux, "Sending packet without any payload");
|
||||||
}
|
}
|
||||||
asfmux->data_object_size += GST_BUFFER_SIZE (buf);
|
asfmux->data_object_size += gst_buffer_get_size (buf);
|
||||||
if (!has_keyframe)
|
if (!has_keyframe)
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
return gst_asf_mux_send_packet (asfmux, buf);
|
return gst_asf_mux_send_packet (asfmux, buf);
|
||||||
|
@ -1671,8 +1693,12 @@ gst_asf_mux_push_simple_index (GstAsfMux * asfmux, GstAsfVideoPad * pad)
|
||||||
g_slist_length (pad->simple_index) * ASF_SIMPLE_INDEX_ENTRY_SIZE;
|
g_slist_length (pad->simple_index) * ASF_SIMPLE_INDEX_ENTRY_SIZE;
|
||||||
GstBuffer *buf = gst_buffer_new_and_alloc (object_size);
|
GstBuffer *buf = gst_buffer_new_and_alloc (object_size);
|
||||||
GSList *walk;
|
GSList *walk;
|
||||||
guint8 *data = GST_BUFFER_DATA (buf);
|
guint8 *data;
|
||||||
guint32 entries_count = g_slist_length (pad->simple_index);
|
guint32 entries_count = g_slist_length (pad->simple_index);
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||||
|
data = map.data;
|
||||||
|
|
||||||
gst_asf_put_guid (data, guids[ASF_SIMPLE_INDEX_OBJECT_INDEX]);
|
gst_asf_put_guid (data, guids[ASF_SIMPLE_INDEX_OBJECT_INDEX]);
|
||||||
GST_WRITE_UINT64_LE (data + 16, object_size);
|
GST_WRITE_UINT64_LE (data + 16, object_size);
|
||||||
|
@ -1699,7 +1725,8 @@ gst_asf_mux_push_simple_index (GstAsfMux * asfmux, GstAsfVideoPad * pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (asfmux, "Pushing the simple index");
|
GST_DEBUG_OBJECT (asfmux, "Pushing the simple index");
|
||||||
g_assert (data - GST_BUFFER_DATA (buf) == object_size);
|
g_assert (data - map.data == object_size);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
return gst_asf_mux_push_buffer (asfmux, buf);
|
return gst_asf_mux_push_buffer (asfmux, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1751,6 +1778,9 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
||||||
GSList *walk;
|
GSList *walk;
|
||||||
GstClockTime play_duration = 0;
|
GstClockTime play_duration = 0;
|
||||||
guint32 bitrate = 0;
|
guint32 bitrate = 0;
|
||||||
|
GstSegment segment;
|
||||||
|
GstMapInfo map;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
/* write indexes */
|
/* write indexes */
|
||||||
ret = gst_asf_mux_write_indexes (asfmux);
|
ret = gst_asf_mux_write_indexes (asfmux);
|
||||||
|
@ -1771,22 +1801,25 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
||||||
* values we didn't know back then */
|
* values we didn't know back then */
|
||||||
GST_DEBUG_OBJECT (asfmux,
|
GST_DEBUG_OBJECT (asfmux,
|
||||||
"Sending new segment to file properties object position");
|
"Sending new segment to file properties object position");
|
||||||
event =
|
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
segment.start = segment.position =
|
||||||
asfmux->file_properties_object_position + 40, GST_CLOCK_TIME_NONE, 0);
|
asfmux->file_properties_object_position + 40;
|
||||||
|
event = gst_event_new_segment (&segment);
|
||||||
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
||||||
GST_ERROR_OBJECT (asfmux, "Failed to update file properties object");
|
GST_ERROR_OBJECT (asfmux, "Failed to update file properties object");
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
/* All file properties fields except the first 40 bytes */
|
/* All file properties fields except the first 40 bytes */
|
||||||
buf = gst_buffer_new_and_alloc (ASF_FILE_PROPERTIES_OBJECT_SIZE - 40);
|
buf = gst_buffer_new_and_alloc (ASF_FILE_PROPERTIES_OBJECT_SIZE - 40);
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||||
|
data = map.data;
|
||||||
|
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf), asfmux->file_size);
|
GST_WRITE_UINT64_LE (data, asfmux->file_size);
|
||||||
gst_asf_put_time (GST_BUFFER_DATA (buf) + 8, gst_asf_get_current_time ());
|
gst_asf_put_time (data + 8, gst_asf_get_current_time ());
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 16, asfmux->total_data_packets);
|
GST_WRITE_UINT64_LE (data + 16, asfmux->total_data_packets);
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 24, (play_duration / 100) +
|
GST_WRITE_UINT64_LE (data + 24, (play_duration / 100) +
|
||||||
ASF_MILI_TO_100NANO (asfmux->preroll));
|
ASF_MILI_TO_100NANO (asfmux->preroll));
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 32, (play_duration / 100)); /* TODO send duration */
|
GST_WRITE_UINT64_LE (data + 32, (play_duration / 100)); /* TODO send duration */
|
||||||
|
|
||||||
/* if play duration is smaller then preroll, player might have problems */
|
/* if play duration is smaller then preroll, player might have problems */
|
||||||
if (asfmux->preroll > play_duration / GST_MSECOND) {
|
if (asfmux->preroll > play_duration / GST_MSECOND) {
|
||||||
|
@ -1795,13 +1828,14 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
||||||
("Preroll time larger than streams duration, "
|
("Preroll time larger than streams duration, "
|
||||||
"try setting a smaller preroll value next time"));
|
"try setting a smaller preroll value next time"));
|
||||||
}
|
}
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 40, asfmux->preroll);
|
GST_WRITE_UINT64_LE (data + 40, asfmux->preroll);
|
||||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 48, 0x2); /* flags - seekable */
|
GST_WRITE_UINT32_LE (data + 48, 0x2); /* flags - seekable */
|
||||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 52, asfmux->packet_size);
|
GST_WRITE_UINT32_LE (data + 52, asfmux->packet_size);
|
||||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 56, asfmux->packet_size);
|
GST_WRITE_UINT32_LE (data + 56, asfmux->packet_size);
|
||||||
/* FIXME - we want the max instantaneous bitrate, for vbr streams, we can't
|
/* FIXME - we want the max instantaneous bitrate, for vbr streams, we can't
|
||||||
* get it this way, this would be the average, right? */
|
* get it this way, this would be the average, right? */
|
||||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 60, bitrate); /* max bitrate */
|
GST_WRITE_UINT32_LE (data + 60, bitrate); /* max bitrate */
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
/* we don't use gst_asf_mux_push_buffer because we are overwriting
|
/* we don't use gst_asf_mux_push_buffer because we are overwriting
|
||||||
* already sent data */
|
* already sent data */
|
||||||
|
@ -1814,19 +1848,20 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
||||||
GST_DEBUG_OBJECT (asfmux, "Seeking back to data object");
|
GST_DEBUG_OBJECT (asfmux, "Seeking back to data object");
|
||||||
|
|
||||||
/* seek back to the data object */
|
/* seek back to the data object */
|
||||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
segment.start = segment.position = asfmux->data_object_position + 16;
|
||||||
asfmux->data_object_position + 16, GST_CLOCK_TIME_NONE, 0);
|
event = gst_event_new_segment (&segment);
|
||||||
|
|
||||||
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
||||||
GST_ERROR_OBJECT (asfmux, "Seek to update data object failed");
|
GST_ERROR_OBJECT (asfmux, "Seek to update data object failed");
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (32); /* qword+guid+qword */
|
buf = gst_buffer_new_and_alloc (32); /* qword+guid+qword */
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf), asfmux->data_object_size +
|
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||||
ASF_DATA_OBJECT_SIZE);
|
data = map.data;
|
||||||
gst_asf_put_guid (GST_BUFFER_DATA (buf) + 8, asfmux->file_id);
|
GST_WRITE_UINT64_LE (data, asfmux->data_object_size + ASF_DATA_OBJECT_SIZE);
|
||||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 24, asfmux->total_data_packets);
|
gst_asf_put_guid (data + 8, asfmux->file_id);
|
||||||
|
GST_WRITE_UINT64_LE (data + 24, asfmux->total_data_packets);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
return gst_pad_push (asfmux->srcpad, buf);
|
return gst_pad_push (asfmux->srcpad, buf);
|
||||||
}
|
}
|
||||||
|
@ -1871,7 +1906,7 @@ gst_asf_mux_process_buffer (GstAsfMux * asfmux, GstAsfPad * pad,
|
||||||
payload->replicated_data_length = 8;
|
payload->replicated_data_length = 8;
|
||||||
|
|
||||||
/* replicated data - 1) media object size */
|
/* replicated data - 1) media object size */
|
||||||
payload->media_object_size = GST_BUFFER_SIZE (buf);
|
payload->media_object_size = gst_buffer_get_size (buf);
|
||||||
/* replicated data - 2) presentation time */
|
/* replicated data - 2) presentation time */
|
||||||
if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
|
if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
|
||||||
GST_ERROR_OBJECT (asfmux, "Received buffer without timestamp");
|
GST_ERROR_OBJECT (asfmux, "Received buffer without timestamp");
|
||||||
|
@ -1896,7 +1931,7 @@ gst_asf_mux_process_buffer (GstAsfMux * asfmux, GstAsfPad * pad,
|
||||||
|
|
||||||
asfmux->payloads = g_slist_append (asfmux->payloads, payload);
|
asfmux->payloads = g_slist_append (asfmux->payloads, payload);
|
||||||
asfmux->payload_data_size +=
|
asfmux->payload_data_size +=
|
||||||
GST_BUFFER_SIZE (buf) + ASF_MULTIPLE_PAYLOAD_HEADER_SIZE;
|
gst_buffer_get_size (buf) + ASF_MULTIPLE_PAYLOAD_HEADER_SIZE;
|
||||||
GST_LOG_OBJECT (asfmux, "Payload data size: %" G_GUINT32_FORMAT,
|
GST_LOG_OBJECT (asfmux, "Payload data size: %" G_GUINT32_FORMAT,
|
||||||
asfmux->payload_data_size);
|
asfmux->payload_data_size);
|
||||||
|
|
||||||
|
@ -1931,7 +1966,7 @@ gst_asf_mux_collected (GstCollectPads * collect, gpointer data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (asfmux->state == GST_ASF_MUX_STATE_EOS))
|
if (G_UNLIKELY (asfmux->state == GST_ASF_MUX_STATE_EOS))
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_EOS;
|
||||||
|
|
||||||
/* select the earliest buffer */
|
/* select the earliest buffer */
|
||||||
walk = asfmux->collect->data;
|
walk = asfmux->collect->data;
|
||||||
|
@ -1999,7 +2034,7 @@ gst_asf_mux_collected (GstCollectPads * collect, gpointer data)
|
||||||
}
|
}
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
gst_pad_push_event (asfmux->srcpad, gst_event_new_eos ());
|
gst_pad_push_event (asfmux->srcpad, gst_event_new_eos ());
|
||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_EOS;
|
||||||
}
|
}
|
||||||
asfmux->state = GST_ASF_MUX_STATE_EOS;
|
asfmux->state = GST_ASF_MUX_STATE_EOS;
|
||||||
}
|
}
|
||||||
|
@ -2201,7 +2236,7 @@ gst_asf_mux_video_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
videopad->vidinfo.bit_cnt = 24;
|
videopad->vidinfo.bit_cnt = 24;
|
||||||
|
|
||||||
/* in case we have a fourcc, we use it */
|
/* in case we have a fourcc, we use it */
|
||||||
if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
|
if (gst_structure_get_uint (structure, "format", &fourcc)) {
|
||||||
videopad->vidinfo.compression = fourcc;
|
videopad->vidinfo.compression = fourcc;
|
||||||
} else {
|
} else {
|
||||||
gint version;
|
gint version;
|
||||||
|
@ -2233,7 +2268,7 @@ refuse_caps:
|
||||||
|
|
||||||
static GstPad *
|
static GstPad *
|
||||||
gst_asf_mux_request_new_pad (GstElement * element,
|
gst_asf_mux_request_new_pad (GstElement * element,
|
||||||
GstPadTemplate * templ, const gchar * req_name)
|
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
||||||
GstAsfMux *asfmux = GST_ASF_MUX_CAST (element);
|
GstAsfMux *asfmux = GST_ASF_MUX_CAST (element);
|
||||||
|
@ -2241,7 +2276,9 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
||||||
GstAsfPad *collect_pad;
|
GstAsfPad *collect_pad;
|
||||||
gboolean is_audio;
|
gboolean is_audio;
|
||||||
guint collect_size = 0;
|
guint collect_size = 0;
|
||||||
gchar *name;
|
gchar *name = NULL;
|
||||||
|
const gchar *pad_name = NULL;
|
||||||
|
gint pad_id;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (asfmux, "Requested pad: %s", GST_STR_NULL (req_name));
|
GST_DEBUG_OBJECT (asfmux, "Requested pad: %s", GST_STR_NULL (req_name));
|
||||||
|
|
||||||
|
@ -2251,27 +2288,37 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
|
if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
|
||||||
name = g_strdup_printf ("audio_%02d", asfmux->stream_number + 1);
|
/* don't mix named and unnamed pads, if the pad already exists we fail when
|
||||||
|
* trying to add it */
|
||||||
|
if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
|
||||||
|
pad_name = req_name;
|
||||||
|
} else {
|
||||||
|
name = g_strdup_printf ("audio_%u", asfmux->stream_number + 1);
|
||||||
|
pad_name = name;
|
||||||
|
}
|
||||||
GST_DEBUG_OBJECT (asfmux, "Adding new pad %s", name);
|
GST_DEBUG_OBJECT (asfmux, "Adding new pad %s", name);
|
||||||
newpad = gst_pad_new_from_template (templ, name);
|
newpad = gst_pad_new_from_template (templ, pad_name);
|
||||||
g_free (name);
|
|
||||||
is_audio = TRUE;
|
is_audio = TRUE;
|
||||||
gst_pad_set_setcaps_function (newpad,
|
} else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
|
||||||
GST_DEBUG_FUNCPTR (gst_asf_mux_audio_set_caps));
|
/* don't mix named and unnamed pads, if the pad already exists we fail when
|
||||||
} else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
|
* trying to add it */
|
||||||
name = g_strdup_printf ("video_%02d", asfmux->stream_number + 1);
|
if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
|
||||||
|
pad_name = req_name;
|
||||||
|
} else {
|
||||||
|
name = g_strdup_printf ("video_%u", asfmux->stream_number + 1);
|
||||||
|
pad_name = name;
|
||||||
|
}
|
||||||
GST_DEBUG_OBJECT (asfmux, "Adding new pad %s", name);
|
GST_DEBUG_OBJECT (asfmux, "Adding new pad %s", name);
|
||||||
newpad = gst_pad_new_from_template (templ, name);
|
newpad = gst_pad_new_from_template (templ, name);
|
||||||
g_free (name);
|
|
||||||
is_audio = FALSE;
|
is_audio = FALSE;
|
||||||
gst_pad_set_setcaps_function (newpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_asf_mux_video_set_caps));
|
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (asfmux, "This is not our template!");
|
GST_WARNING_OBJECT (asfmux, "This is not our template!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (name);
|
||||||
|
|
||||||
/* add pad to collections */
|
/* add pad to collections */
|
||||||
if (is_audio) {
|
if (is_audio) {
|
||||||
collect_size = sizeof (GstAsfAudioPad);
|
collect_size = sizeof (GstAsfAudioPad);
|
||||||
|
@ -2293,14 +2340,6 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
||||||
asfmux->stream_number += 1;
|
asfmux->stream_number += 1;
|
||||||
collect_pad->stream_number = asfmux->stream_number;
|
collect_pad->stream_number = asfmux->stream_number;
|
||||||
|
|
||||||
/* FIXME: hacked way to override/extend the event function of
|
|
||||||
* GstCollectPads; because it sets its own event function giving
|
|
||||||
* the element no access to events.
|
|
||||||
*/
|
|
||||||
asfmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
|
|
||||||
gst_pad_set_event_function (newpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_asf_mux_sink_event));
|
|
||||||
|
|
||||||
gst_pad_set_active (newpad, TRUE);
|
gst_pad_set_active (newpad, TRUE);
|
||||||
gst_element_add_pad (element, newpad);
|
gst_element_add_pad (element, newpad);
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,6 @@ struct _GstAsfMux
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
GstCollectPads *collect;
|
GstCollectPads *collect;
|
||||||
GstPadEventFunction collect_event;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAsfMuxClass
|
struct _GstAsfMuxClass
|
||||||
|
|
|
@ -213,7 +213,7 @@ gst_asf_file_info_free (GstAsfFileInfo * info)
|
||||||
guint32
|
guint32
|
||||||
gst_asf_payload_get_size (AsfPayload * payload)
|
gst_asf_payload_get_size (AsfPayload * payload)
|
||||||
{
|
{
|
||||||
return ASF_MULTIPLE_PAYLOAD_HEADER_SIZE + GST_BUFFER_SIZE (payload->data);
|
return ASF_MULTIPLE_PAYLOAD_HEADER_SIZE + gst_buffer_get_size (payload->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -338,9 +338,9 @@ gst_asf_put_payload (guint8 * buf, AsfPayload * payload)
|
||||||
GST_WRITE_UINT8 (buf + 6, payload->replicated_data_length);
|
GST_WRITE_UINT8 (buf + 6, payload->replicated_data_length);
|
||||||
GST_WRITE_UINT32_LE (buf + 7, payload->media_object_size);
|
GST_WRITE_UINT32_LE (buf + 7, payload->media_object_size);
|
||||||
GST_WRITE_UINT32_LE (buf + 11, payload->presentation_time);
|
GST_WRITE_UINT32_LE (buf + 11, payload->presentation_time);
|
||||||
GST_WRITE_UINT16_LE (buf + 15, (guint16) GST_BUFFER_SIZE (payload->data));
|
GST_WRITE_UINT16_LE (buf + 15, (guint16) gst_buffer_get_size (payload->data));
|
||||||
memcpy (buf + 17, GST_BUFFER_DATA (payload->data),
|
gst_buffer_extract (payload->data, 0, buf + 17,
|
||||||
GST_BUFFER_SIZE (payload->data));
|
gst_buffer_get_size (payload->data));
|
||||||
|
|
||||||
payload->packet_count++;
|
payload->packet_count++;
|
||||||
}
|
}
|
||||||
|
@ -377,18 +377,15 @@ gst_asf_put_subpayload (guint8 * buf, AsfPayload * payload, guint16 size)
|
||||||
GST_WRITE_UINT32_LE (buf + 7, payload->media_object_size);
|
GST_WRITE_UINT32_LE (buf + 7, payload->media_object_size);
|
||||||
GST_WRITE_UINT32_LE (buf + 11, payload->presentation_time);
|
GST_WRITE_UINT32_LE (buf + 11, payload->presentation_time);
|
||||||
size -= ASF_MULTIPLE_PAYLOAD_HEADER_SIZE;
|
size -= ASF_MULTIPLE_PAYLOAD_HEADER_SIZE;
|
||||||
payload_size = size < GST_BUFFER_SIZE (payload->data) ?
|
payload_size = size < gst_buffer_get_size (payload->data) ?
|
||||||
size : GST_BUFFER_SIZE (payload->data);
|
size : gst_buffer_get_size (payload->data);
|
||||||
GST_WRITE_UINT16_LE (buf + 15, payload_size);
|
GST_WRITE_UINT16_LE (buf + 15, payload_size);
|
||||||
memcpy (buf + 17, GST_BUFFER_DATA (payload->data), payload_size);
|
gst_buffer_extract (payload->data, 0, buf + 17, payload_size);
|
||||||
|
|
||||||
/* updates the payload to the remaining data */
|
/* updates the payload to the remaining data */
|
||||||
payload->offset_in_media_obj += payload_size;
|
payload->offset_in_media_obj += payload_size;
|
||||||
newbuf = gst_buffer_create_sub (payload->data, payload_size,
|
newbuf = gst_buffer_copy_region (payload->data, GST_BUFFER_COPY_ALL,
|
||||||
GST_BUFFER_SIZE (payload->data) - payload_size);
|
payload_size, gst_buffer_get_size (payload->data) - payload_size);
|
||||||
payload->data = gst_buffer_make_metadata_writable (payload->data);
|
|
||||||
gst_buffer_copy_metadata (payload->data, newbuf, GST_BUFFER_COPY_FLAGS |
|
|
||||||
GST_BUFFER_COPY_CAPS);
|
|
||||||
GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (payload->data);
|
GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (payload->data);
|
||||||
gst_buffer_unref (payload->data);
|
gst_buffer_unref (payload->data);
|
||||||
payload->data = newbuf;
|
payload->data = newbuf;
|
||||||
|
@ -424,6 +421,33 @@ gst_asf_match_and_peek_obj_size (const guint8 * data, const Guid * guid)
|
||||||
return GST_READ_UINT64_LE (data + ASF_GUID_SIZE);
|
return GST_READ_UINT64_LE (data + ASF_GUID_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_asf_match_and_peek_obj_size_buf:
|
||||||
|
* @buf: buffer to be peeked at
|
||||||
|
* @guid: pointer to a guid
|
||||||
|
*
|
||||||
|
* Compares the first bytes of buf against the guid parameter and
|
||||||
|
* if they match gets the object size (that are right after the guid in
|
||||||
|
* asf objects).
|
||||||
|
*
|
||||||
|
* In case the guids don't match, 0 is returned.
|
||||||
|
* If the guid is NULL the match is assumed to be true.
|
||||||
|
*
|
||||||
|
* Returns: The size of the object in case the guid matches, 0 otherwise
|
||||||
|
*/
|
||||||
|
guint64
|
||||||
|
gst_asf_match_and_peek_obj_size_buf (GstBuffer * buf, const Guid * guid)
|
||||||
|
{
|
||||||
|
GstMapInfo map;
|
||||||
|
guint64 res;
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
res = gst_asf_match_and_peek_obj_size (map.data, guid);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_asf_parse_mult_payload:
|
* gst_asf_parse_mult_payload:
|
||||||
* @reader: a #GstByteReader ready to read the multiple payload data
|
* @reader: a #GstByteReader ready to read the multiple payload data
|
||||||
|
@ -539,15 +563,17 @@ gst_asf_parse_packet (GstBuffer * buffer, GstAsfPacketInfo * packet,
|
||||||
guint32 send_time = 0;
|
guint32 send_time = 0;
|
||||||
guint16 duration = 0;
|
guint16 duration = 0;
|
||||||
gboolean has_keyframe;
|
gboolean has_keyframe;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
if (packet_size != 0 && GST_BUFFER_SIZE (buffer) != packet_size) {
|
if (packet_size != 0 && gst_buffer_get_size (buffer) != packet_size) {
|
||||||
GST_WARNING ("ASF packets should be aligned with buffers");
|
GST_WARNING ("ASF packets should be aligned with buffers");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader = gst_byte_reader_new_from_buffer (buffer);
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
reader = gst_byte_reader_new (map.data, map.size);
|
||||||
|
|
||||||
GST_LOG ("Starting packet parsing, size: %u", GST_BUFFER_SIZE (buffer));
|
GST_LOG ("Starting packet parsing, size: %u", gst_buffer_get_size (buffer));
|
||||||
if (!gst_byte_reader_get_uint8 (reader, &first))
|
if (!gst_byte_reader_get_uint8 (reader, &first))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -673,6 +699,7 @@ gst_asf_parse_packet (GstBuffer * buffer, GstAsfPacketInfo * packet,
|
||||||
packet->seq_field_type = seq_len_type;
|
packet->seq_field_type = seq_len_type;
|
||||||
packet->err_cor_len = err_length;
|
packet->err_cor_len = err_length;
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
gst_byte_reader_free (reader);
|
gst_byte_reader_free (reader);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -680,6 +707,7 @@ error:
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
GST_WARNING ("Error while parsing data packet");
|
GST_WARNING ("Error while parsing data packet");
|
||||||
end:
|
end:
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
gst_byte_reader_free (reader);
|
gst_byte_reader_free (reader);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -738,16 +766,20 @@ gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info)
|
||||||
guint32 i;
|
guint32 i;
|
||||||
GstByteReader *reader;
|
GstByteReader *reader;
|
||||||
guint64 object_size;
|
guint64 object_size;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
object_size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (buffer),
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
|
||||||
|
object_size = gst_asf_match_and_peek_obj_size (map.data,
|
||||||
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
||||||
if (object_size == 0) {
|
if (object_size == 0) {
|
||||||
GST_WARNING ("ASF: Cannot parse, header guid not found at the beginning "
|
GST_WARNING ("ASF: Cannot parse, header guid not found at the beginning "
|
||||||
" of data");
|
" of data");
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader = gst_byte_reader_new_from_buffer (buffer);
|
reader = gst_byte_reader_new (map.data, map.size);
|
||||||
|
|
||||||
if (!gst_byte_reader_skip (reader, ASF_GUID_OBJSIZE_SIZE))
|
if (!gst_byte_reader_skip (reader, ASF_GUID_OBJSIZE_SIZE))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -785,6 +817,7 @@ error:
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
GST_WARNING ("ASF: Error while parsing headers");
|
GST_WARNING ("ASF: Error while parsing headers");
|
||||||
end:
|
end:
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
gst_byte_reader_free (reader);
|
gst_byte_reader_free (reader);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ gboolean gst_asf_parse_packet (GstBuffer * buffer, GstAsfPacketInfo * packet,
|
||||||
gboolean trust_delta_flag, guint packet_size);
|
gboolean trust_delta_flag, guint packet_size);
|
||||||
guint64 gst_asf_match_and_peek_obj_size (const guint8 * data,
|
guint64 gst_asf_match_and_peek_obj_size (const guint8 * data,
|
||||||
const Guid * guid);
|
const Guid * guid);
|
||||||
|
guint64 gst_asf_match_and_peek_obj_size_buf (GstBuffer * buf,
|
||||||
|
const Guid * guid);
|
||||||
gboolean gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info);
|
gboolean gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info);
|
||||||
|
|
||||||
/* ASF tags
|
/* ASF tags
|
||||||
|
|
|
@ -46,7 +46,8 @@ static GstStateChangeReturn gst_asf_parse_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
static void gst_asf_parse_loop (GstPad * pad);
|
static void gst_asf_parse_loop (GstPad * pad);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstAsfParse, gst_asf_parse, GstElement, GST_TYPE_ELEMENT);
|
#define gst_asf_parse_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstAsfParse, gst_asf_parse, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_asf_parse_reset (GstAsfParse * asfparse)
|
gst_asf_parse_reset (GstAsfParse * asfparse)
|
||||||
|
@ -61,29 +62,62 @@ gst_asf_parse_reset (GstAsfParse * asfparse)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_asf_parse_sink_activate (GstPad * pad)
|
gst_asf_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
|
||||||
{
|
{
|
||||||
if (gst_pad_check_pull_range (pad)) {
|
GstQuery *query;
|
||||||
return gst_pad_activate_pull (pad, TRUE);
|
gboolean pull_mode;
|
||||||
} else {
|
|
||||||
return gst_pad_activate_push (pad, TRUE);
|
query = gst_query_new_scheduling ();
|
||||||
|
|
||||||
|
if (!gst_pad_peer_query (sinkpad, query)) {
|
||||||
|
gst_query_unref (query);
|
||||||
|
goto activate_push;
|
||||||
|
}
|
||||||
|
|
||||||
|
pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
|
||||||
|
gst_query_unref (query);
|
||||||
|
|
||||||
|
if (!pull_mode)
|
||||||
|
goto activate_push;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (sinkpad, "activating pull");
|
||||||
|
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
|
||||||
|
|
||||||
|
activate_push:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (sinkpad, "activating push");
|
||||||
|
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_asf_parse_sink_activate_pull (GstPad * pad, gboolean active)
|
gst_asf_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
|
||||||
|
GstPadMode mode, gboolean active)
|
||||||
{
|
{
|
||||||
if (active) {
|
gboolean res;
|
||||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_asf_parse_loop, pad);
|
|
||||||
} else {
|
switch (mode) {
|
||||||
return gst_pad_stop_task (pad);
|
case GST_PAD_MODE_PULL:
|
||||||
|
if (active) {
|
||||||
|
res =
|
||||||
|
gst_pad_start_task (pad, (GstTaskFunction) gst_asf_parse_loop, pad);
|
||||||
|
} else {
|
||||||
|
res = gst_pad_stop_task (pad);
|
||||||
|
}
|
||||||
|
case GST_PAD_MODE_PUSH:
|
||||||
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_asf_parse_push (GstAsfParse * asfparse, GstBuffer * buf)
|
gst_asf_parse_push (GstAsfParse * asfparse, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
gst_buffer_set_caps (buf, asfparse->outcaps);
|
|
||||||
return gst_pad_push (asfparse->srcpad, buf);
|
return gst_pad_push (asfparse->srcpad, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +127,12 @@ gst_asf_parse_parse_data_object (GstAsfParse * asfparse, GstBuffer * buffer)
|
||||||
GstByteReader *reader;
|
GstByteReader *reader;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
guint64 packet_count = 0;
|
guint64 packet_count = 0;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (asfparse, "Parsing data object");
|
GST_DEBUG_OBJECT (asfparse, "Parsing data object");
|
||||||
|
|
||||||
reader = gst_byte_reader_new_from_buffer (buffer);
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
reader = gst_byte_reader_new (map.data, map.size);
|
||||||
/* skip to packet count */
|
/* skip to packet count */
|
||||||
if (!gst_byte_reader_skip (reader, 40))
|
if (!gst_byte_reader_skip (reader, 40))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -112,12 +148,14 @@ gst_asf_parse_parse_data_object (GstAsfParse * asfparse, GstBuffer * buffer)
|
||||||
packet_count);
|
packet_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
gst_byte_reader_free (reader);
|
gst_byte_reader_free (reader);
|
||||||
return gst_asf_parse_push (asfparse, buffer);
|
return gst_asf_parse_push (asfparse, buffer);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ret = GST_FLOW_ERROR;
|
ret = GST_FLOW_ERROR;
|
||||||
GST_ERROR_OBJECT (asfparse, "Error while parsing data object headers");
|
GST_ERROR_OBJECT (asfparse, "Error while parsing data object headers");
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
gst_byte_reader_free (reader);
|
gst_byte_reader_free (reader);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +199,7 @@ gst_asf_parse_pull_headers (GstAsfParse * asfparse)
|
||||||
GstBuffer *headers = NULL;
|
GstBuffer *headers = NULL;
|
||||||
guint64 size;
|
guint64 size;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
|
if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
|
||||||
ASF_GUID_OBJSIZE_SIZE, &guid_and_size)) != GST_FLOW_OK) {
|
ASF_GUID_OBJSIZE_SIZE, &guid_and_size)) != GST_FLOW_OK) {
|
||||||
|
@ -168,8 +207,10 @@ gst_asf_parse_pull_headers (GstAsfParse * asfparse)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
asfparse->offset += ASF_GUID_OBJSIZE_SIZE;
|
asfparse->offset += ASF_GUID_OBJSIZE_SIZE;
|
||||||
size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (guid_and_size),
|
gst_buffer_map (guid_and_size, &map, GST_MAP_READ);
|
||||||
|
size = gst_asf_match_and_peek_obj_size (map.data,
|
||||||
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
||||||
|
gst_buffer_unmap (guid_and_size, &map);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing");
|
GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing");
|
||||||
|
@ -209,7 +250,7 @@ gst_asf_parse_pull_data_header (GstAsfParse * asfparse)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
asfparse->offset += ASF_DATA_OBJECT_SIZE;
|
asfparse->offset += ASF_DATA_OBJECT_SIZE;
|
||||||
asfparse->data_size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (buf),
|
asfparse->data_size = gst_asf_match_and_peek_obj_size_buf (buf,
|
||||||
&(guids[ASF_DATA_OBJECT_INDEX]));
|
&(guids[ASF_DATA_OBJECT_INDEX]));
|
||||||
if (asfparse->data_size == 0) {
|
if (asfparse->data_size == 0) {
|
||||||
GST_ERROR_OBJECT (asfparse, "Unexpected object, was expecting data object");
|
GST_ERROR_OBJECT (asfparse, "Unexpected object, was expecting data object");
|
||||||
|
@ -262,8 +303,7 @@ gst_asf_parse_pull_indexes (GstAsfParse * asfparse)
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
/* we can peek at the object size */
|
/* we can peek at the object size */
|
||||||
obj_size =
|
obj_size = gst_asf_match_and_peek_obj_size_buf (guid_and_size, NULL);
|
||||||
gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (guid_and_size), NULL);
|
|
||||||
if (obj_size == 0) {
|
if (obj_size == 0) {
|
||||||
GST_ERROR_OBJECT (asfparse, "Incomplete object found");
|
GST_ERROR_OBJECT (asfparse, "Incomplete object found");
|
||||||
gst_buffer_unref (guid_and_size);
|
gst_buffer_unref (guid_and_size);
|
||||||
|
@ -346,9 +386,9 @@ pause:
|
||||||
GST_INFO_OBJECT (asfparse, "Pausing sinkpad task");
|
GST_INFO_OBJECT (asfparse, "Pausing sinkpad task");
|
||||||
gst_pad_pause_task (pad);
|
gst_pad_pause_task (pad);
|
||||||
|
|
||||||
if (ret == GST_FLOW_UNEXPECTED) {
|
if (ret == GST_FLOW_EOS) {
|
||||||
gst_pad_push_event (asfparse->srcpad, gst_event_new_eos ());
|
gst_pad_push_event (asfparse->srcpad, gst_event_new_eos ());
|
||||||
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
|
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
|
||||||
GST_ELEMENT_ERROR (asfparse, STREAM, FAILED,
|
GST_ELEMENT_ERROR (asfparse, STREAM, FAILED,
|
||||||
(NULL), ("streaming task paused, reason %s (%d)", reason, ret));
|
(NULL), ("streaming task paused, reason %s (%d)", reason, ret));
|
||||||
gst_pad_push_event (asfparse->srcpad, gst_event_new_eos ());
|
gst_pad_push_event (asfparse->srcpad, gst_event_new_eos ());
|
||||||
|
@ -357,12 +397,12 @@ pause:
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
gst_asf_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstAsfParse *asfparse;
|
GstAsfParse *asfparse;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
asfparse = GST_ASF_PARSE (GST_PAD_PARENT (pad));
|
asfparse = GST_ASF_PARSE (parent);
|
||||||
gst_adapter_push (asfparse->adapter, buffer);
|
gst_adapter_push (asfparse->adapter, buffer);
|
||||||
|
|
||||||
switch (asfparse->parse_state) {
|
switch (asfparse->parse_state) {
|
||||||
|
@ -372,9 +412,10 @@ gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
|
||||||
/* we can peek at the object size */
|
/* we can peek at the object size */
|
||||||
asfparse->headers_size =
|
asfparse->headers_size =
|
||||||
gst_asf_match_and_peek_obj_size (gst_adapter_peek
|
gst_asf_match_and_peek_obj_size (gst_adapter_map
|
||||||
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE),
|
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE),
|
||||||
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
||||||
|
gst_adapter_unmap (asfparse->adapter);
|
||||||
|
|
||||||
if (asfparse->headers_size == 0) {
|
if (asfparse->headers_size == 0) {
|
||||||
/* something is wrong, this probably ain't an ASF stream */
|
/* something is wrong, this probably ain't an ASF stream */
|
||||||
|
@ -401,9 +442,10 @@ gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
|
||||||
/* we can peek at the object size */
|
/* we can peek at the object size */
|
||||||
asfparse->data_size =
|
asfparse->data_size =
|
||||||
gst_asf_match_and_peek_obj_size (gst_adapter_peek
|
gst_asf_match_and_peek_obj_size (gst_adapter_map
|
||||||
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE),
|
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE),
|
||||||
&(guids[ASF_DATA_OBJECT_INDEX]));
|
&(guids[ASF_DATA_OBJECT_INDEX]));
|
||||||
|
gst_adapter_unmap (asfparse->adapter);
|
||||||
|
|
||||||
if (asfparse->data_size == 0) {
|
if (asfparse->data_size == 0) {
|
||||||
/* something is wrong */
|
/* something is wrong */
|
||||||
|
@ -447,8 +489,9 @@ gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
if (gst_adapter_available (asfparse->adapter) >= ASF_GUID_OBJSIZE_SIZE) {
|
if (gst_adapter_available (asfparse->adapter) >= ASF_GUID_OBJSIZE_SIZE) {
|
||||||
guint64 obj_size;
|
guint64 obj_size;
|
||||||
/* we can peek at the object size */
|
/* we can peek at the object size */
|
||||||
obj_size = gst_asf_match_and_peek_obj_size (gst_adapter_peek
|
obj_size = gst_asf_match_and_peek_obj_size (gst_adapter_map
|
||||||
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE), NULL);
|
(asfparse->adapter, ASF_GUID_OBJSIZE_SIZE), NULL);
|
||||||
|
gst_adapter_unmap (asfparse->adapter);
|
||||||
if (gst_adapter_available (asfparse->adapter) >= obj_size) {
|
if (gst_adapter_available (asfparse->adapter) >= obj_size) {
|
||||||
GST_DEBUG_OBJECT (asfparse, "Skiping object");
|
GST_DEBUG_OBJECT (asfparse, "Skiping object");
|
||||||
ret = gst_asf_parse_push (asfparse,
|
ret = gst_asf_parse_push (asfparse,
|
||||||
|
@ -467,23 +510,6 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_asf_parse_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&src_factory));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&sink_factory));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class, "ASF parser",
|
|
||||||
"Parser", "Parses ASF", "Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (asfparse_debug, "asfparse", 0,
|
|
||||||
"Parser for ASF streams");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_asf_parse_finalize (GObject * object)
|
gst_asf_parse_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -511,17 +537,28 @@ gst_asf_parse_class_init (GstAsfParseClass * klass)
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_asf_parse_change_state);
|
GST_DEBUG_FUNCPTR (gst_asf_parse_change_state);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&src_factory));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&sink_factory));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class, "ASF parser",
|
||||||
|
"Parser", "Parses ASF", "Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (asfparse_debug, "asfparse", 0,
|
||||||
|
"Parser for ASF streams");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_asf_parse_init (GstAsfParse * asfparse, GstAsfParseClass * klass)
|
gst_asf_parse_init (GstAsfParse * asfparse)
|
||||||
{
|
{
|
||||||
asfparse->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
|
asfparse->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
|
||||||
gst_pad_set_chain_function (asfparse->sinkpad, gst_asf_parse_chain);
|
gst_pad_set_chain_function (asfparse->sinkpad, gst_asf_parse_chain);
|
||||||
gst_pad_set_activate_function (asfparse->sinkpad,
|
gst_pad_set_activate_function (asfparse->sinkpad,
|
||||||
gst_asf_parse_sink_activate);
|
gst_asf_parse_sink_activate);
|
||||||
gst_pad_set_activatepull_function (asfparse->sinkpad,
|
gst_pad_set_activatemode_function (asfparse->sinkpad,
|
||||||
gst_asf_parse_sink_activate_pull);
|
gst_asf_parse_sink_activate_mode);
|
||||||
gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->sinkpad);
|
||||||
|
|
||||||
asfparse->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
asfparse->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
||||||
|
@ -529,7 +566,7 @@ gst_asf_parse_init (GstAsfParse * asfparse, GstAsfParseClass * klass)
|
||||||
gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->srcpad);
|
gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->srcpad);
|
||||||
|
|
||||||
asfparse->adapter = gst_adapter_new ();
|
asfparse->adapter = gst_adapter_new ();
|
||||||
asfparse->outcaps = gst_caps_new_simple ("video/x-ms-asf", NULL);
|
asfparse->outcaps = gst_caps_new_empty_simple ("video/x-ms-asf");
|
||||||
asfparse->asfinfo = gst_asf_file_info_new ();
|
asfparse->asfinfo = gst_asf_file_info_new ();
|
||||||
asfparse->packetinfo = g_new0 (GstAsfPacketInfo, 1);
|
asfparse->packetinfo = g_new0 (GstAsfPacketInfo, 1);
|
||||||
gst_asf_parse_reset (asfparse);
|
gst_asf_parse_reset (asfparse);
|
||||||
|
|
|
@ -51,15 +51,15 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer);
|
gst_rtp_asf_pay_handle_buffer (GstRTPBasePayload * rtppay, GstBuffer * buffer);
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps);
|
gst_rtp_asf_pay_set_caps (GstRTPBasePayload * rtppay, GstCaps * caps);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpAsfPay, gst_rtp_asf_pay, GstBaseRTPPayload,
|
#define gst_rtp_asf_pay_parent_class parent_class
|
||||||
GST_TYPE_BASE_RTP_PAYLOAD);
|
G_DEFINE_TYPE (GstRtpAsfPay, gst_rtp_asf_pay, GST_TYPE_RTP_BASE_PAYLOAD);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_asf_pay_init (GstRtpAsfPay * rtpasfpay, GstRtpAsfPayClass * klass)
|
gst_rtp_asf_pay_init (GstRtpAsfPay * rtpasfpay)
|
||||||
{
|
{
|
||||||
rtpasfpay->first_ts = 0;
|
rtpasfpay->first_ts = 0;
|
||||||
rtpasfpay->config = NULL;
|
rtpasfpay->config = NULL;
|
||||||
|
@ -80,44 +80,40 @@ gst_rtp_asf_pay_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtp_asf_pay_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_asf_pay_sink_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_rtp_asf_pay_src_template));
|
|
||||||
gst_element_class_set_details_simple (element_class, "RTP ASF payloader",
|
|
||||||
"Codec/Payloader/Network",
|
|
||||||
"Payload-encodes ASF into RTP packets (MS_RTSP)",
|
|
||||||
"Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtp_asf_pay_class_init (GstRtpAsfPayClass * klass)
|
gst_rtp_asf_pay_class_init (GstRtpAsfPayClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
GstElementClass *gstelement_class;
|
||||||
|
GstRTPBasePayloadClass *gstbasertppayload_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
gstbasertppayload_class = (GstRTPBasePayloadClass *) klass;
|
||||||
|
|
||||||
gobject_class->finalize = gst_rtp_asf_pay_finalize;
|
gobject_class->finalize = gst_rtp_asf_pay_finalize;
|
||||||
|
|
||||||
gstbasertppayload_class->handle_buffer = gst_rtp_asf_pay_handle_buffer;
|
gstbasertppayload_class->handle_buffer = gst_rtp_asf_pay_handle_buffer;
|
||||||
gstbasertppayload_class->set_caps = gst_rtp_asf_pay_set_caps;
|
gstbasertppayload_class->set_caps = gst_rtp_asf_pay_set_caps;
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_asf_pay_sink_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&gst_rtp_asf_pay_src_template));
|
||||||
|
gst_element_class_set_details_simple (gstelement_class, "RTP ASF payloader",
|
||||||
|
"Codec/Payloader/Network",
|
||||||
|
"Payload-encodes ASF into RTP packets (MS_RTSP)",
|
||||||
|
"Thiago Santos <thiagoss@embedded.ufcg.edu.br>");
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (rtpasfpay_debug, "rtpasfpay", 0,
|
GST_DEBUG_CATEGORY_INIT (rtpasfpay_debug, "rtpasfpay", 0,
|
||||||
"ASF RTP Payloader");
|
"ASF RTP Payloader");
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps)
|
gst_rtp_asf_pay_set_caps (GstRTPBasePayload * rtppay, GstCaps * caps)
|
||||||
{
|
{
|
||||||
/* FIXME change application for the actual content */
|
/* FIXME change application for the actual content */
|
||||||
gst_basertppayload_set_options (rtppay, "application", TRUE, "X-ASF-PF",
|
gst_rtp_base_payload_set_options (rtppay, "application", TRUE, "X-ASF-PF",
|
||||||
1000);
|
1000);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +121,7 @@ gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstBaseRTPPayload *rtppay;
|
GstRTPBasePayload *rtppay;
|
||||||
GstAsfPacketInfo *packetinfo;
|
GstAsfPacketInfo *packetinfo;
|
||||||
guint8 flags;
|
guint8 flags;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
@ -134,7 +130,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
guint32 size_left;
|
guint32 size_left;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
rtppay = GST_BASE_RTP_PAYLOAD (rtpasfpay);
|
rtppay = GST_RTP_BASE_PAYLOAD (rtpasfpay);
|
||||||
packetinfo = &rtpasfpay->packetinfo;
|
packetinfo = &rtpasfpay->packetinfo;
|
||||||
|
|
||||||
if (!gst_asf_parse_packet (buffer, packetinfo, TRUE,
|
if (!gst_asf_parse_packet (buffer, packetinfo, TRUE,
|
||||||
|
@ -161,13 +157,13 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
buffer = gst_buffer_make_writable (buffer);
|
buffer = gst_buffer_make_writable (buffer);
|
||||||
switch (packetinfo->padd_field_type) {
|
switch (packetinfo->padd_field_type) {
|
||||||
case ASF_FIELD_TYPE_DWORD:
|
case ASF_FIELD_TYPE_DWORD:
|
||||||
GST_WRITE_UINT32_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
|
gst_buffer_memset (buffer, offset, 0, 4);
|
||||||
break;
|
break;
|
||||||
case ASF_FIELD_TYPE_WORD:
|
case ASF_FIELD_TYPE_WORD:
|
||||||
GST_WRITE_UINT16_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
|
gst_buffer_memset (buffer, offset, 0, 2);
|
||||||
break;
|
break;
|
||||||
case ASF_FIELD_TYPE_BYTE:
|
case ASF_FIELD_TYPE_BYTE:
|
||||||
GST_BUFFER_DATA (buffer)[offset] = 0;
|
gst_buffer_memset (buffer, offset, 0, 1);
|
||||||
break;
|
break;
|
||||||
case ASF_FIELD_TYPE_NONE:
|
case ASF_FIELD_TYPE_NONE:
|
||||||
default:
|
default:
|
||||||
|
@ -189,23 +185,26 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
* This flag tells us to push the packet.
|
* This flag tells us to push the packet.
|
||||||
*/
|
*/
|
||||||
gboolean force_push = FALSE;
|
gboolean force_push = FALSE;
|
||||||
|
GstRTPBuffer rtp;
|
||||||
|
|
||||||
/* we have no output buffer pending, create one */
|
/* we have no output buffer pending, create one */
|
||||||
if (rtpasfpay->current == NULL) {
|
if (rtpasfpay->current == NULL) {
|
||||||
GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer");
|
GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer");
|
||||||
rtpasfpay->current =
|
rtpasfpay->current =
|
||||||
gst_rtp_buffer_new_allocate_len (GST_BASE_RTP_PAYLOAD_MTU (rtpasfpay),
|
gst_rtp_buffer_new_allocate_len (GST_RTP_BASE_PAYLOAD_MTU (rtpasfpay),
|
||||||
0, 0);
|
0, 0);
|
||||||
rtpasfpay->cur_off = gst_rtp_buffer_get_header_len (rtpasfpay->current);
|
rtpasfpay->cur_off = 0;
|
||||||
rtpasfpay->has_ts = FALSE;
|
rtpasfpay->has_ts = FALSE;
|
||||||
rtpasfpay->marker = FALSE;
|
rtpasfpay->marker = FALSE;
|
||||||
}
|
}
|
||||||
data = GST_BUFFER_DATA (rtpasfpay->current) + rtpasfpay->cur_off;
|
gst_rtp_buffer_map (rtpasfpay->current, GST_MAP_READWRITE, &rtp);
|
||||||
size_left = GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off;
|
data = gst_rtp_buffer_get_payload (&rtp);
|
||||||
|
data += rtpasfpay->cur_off;
|
||||||
|
size_left = gst_rtp_buffer_get_payload_len (&rtp) - rtpasfpay->cur_off;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %"
|
GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %"
|
||||||
G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, packet_offset,
|
G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, packet_offset,
|
||||||
GST_BUFFER_SIZE (buffer));
|
gst_buffer_get_size (buffer));
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Output rtpbuffer status");
|
GST_DEBUG_OBJECT (rtpasfpay, "Output rtpbuffer status");
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Current offset: %" G_GUINT32_FORMAT,
|
GST_DEBUG_OBJECT (rtpasfpay, "Current offset: %" G_GUINT32_FORMAT,
|
||||||
|
@ -230,8 +229,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
rtpasfpay->ts = packetinfo->send_time;
|
rtpasfpay->ts = packetinfo->send_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off >=
|
if (size_left >= packet_util_size + 8) {
|
||||||
packet_util_size + 8) {
|
|
||||||
/* enough space for the rest of the packet */
|
/* enough space for the rest of the packet */
|
||||||
if (packet_offset == 0) {
|
if (packet_offset == 0) {
|
||||||
flags = flags | 0x40;
|
flags = flags | 0x40;
|
||||||
|
@ -243,8 +241,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
data[0] = flags;
|
data[0] = flags;
|
||||||
GST_WRITE_UINT32_BE (data + 4,
|
GST_WRITE_UINT32_BE (data + 4,
|
||||||
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
||||||
memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
|
gst_buffer_extract (buffer, packet_offset, data + 8, packet_util_size);
|
||||||
packet_util_size);
|
|
||||||
|
|
||||||
/* updating status variables */
|
/* updating status variables */
|
||||||
rtpasfpay->cur_off += 8 + packet_util_size;
|
rtpasfpay->cur_off += 8 + packet_util_size;
|
||||||
|
@ -258,8 +255,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
GST_WRITE_UINT24_BE (data + 1, packet_offset);
|
GST_WRITE_UINT24_BE (data + 1, packet_offset);
|
||||||
GST_WRITE_UINT32_BE (data + 4,
|
GST_WRITE_UINT32_BE (data + 4,
|
||||||
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
||||||
memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
|
gst_buffer_extract (buffer, packet_offset, data + 8, size_left - 8);
|
||||||
size_left - 8);
|
|
||||||
|
|
||||||
/* updating status variables */
|
/* updating status variables */
|
||||||
rtpasfpay->cur_off += size_left;
|
rtpasfpay->cur_off += size_left;
|
||||||
|
@ -272,31 +268,27 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||||
/* there is not enough room for any more buffers */
|
/* there is not enough room for any more buffers */
|
||||||
if (force_push || size_left <= 8) {
|
if (force_push || size_left <= 8) {
|
||||||
|
|
||||||
|
gst_rtp_buffer_set_ssrc (&rtp, rtppay->current_ssrc);
|
||||||
|
gst_rtp_buffer_set_marker (&rtp, rtpasfpay->marker);
|
||||||
|
gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_BASE_PAYLOAD_PT (rtppay));
|
||||||
|
gst_rtp_buffer_set_seq (&rtp, rtppay->seqnum + 1);
|
||||||
|
gst_rtp_buffer_set_timestamp (&rtp, packetinfo->send_time);
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
|
/* trim remaining bytes not used */
|
||||||
if (size_left != 0) {
|
if (size_left != 0) {
|
||||||
/* trim remaining bytes not used */
|
gst_buffer_set_size (rtpasfpay->current,
|
||||||
GstBuffer *aux = gst_buffer_create_sub (rtpasfpay->current, 0,
|
gst_buffer_get_size (rtpasfpay->current) - size_left);
|
||||||
GST_BUFFER_SIZE (rtpasfpay->current) - size_left);
|
|
||||||
gst_buffer_unref (rtpasfpay->current);
|
|
||||||
rtpasfpay->current = aux;
|
|
||||||
}
|
}
|
||||||
gst_rtp_buffer_set_ssrc (rtpasfpay->current, rtppay->current_ssrc);
|
|
||||||
gst_rtp_buffer_set_marker (rtpasfpay->current, rtpasfpay->marker);
|
|
||||||
gst_rtp_buffer_set_payload_type (rtpasfpay->current,
|
|
||||||
GST_BASE_RTP_PAYLOAD_PT (rtppay));
|
|
||||||
gst_rtp_buffer_set_seq (rtpasfpay->current, rtppay->seqnum + 1);
|
|
||||||
gst_rtp_buffer_set_timestamp (rtpasfpay->current, packetinfo->send_time);
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer);
|
GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
|
||||||
gst_buffer_set_caps (rtpasfpay->current,
|
|
||||||
GST_PAD_CAPS (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay)));
|
|
||||||
|
|
||||||
rtppay->seqnum++;
|
rtppay->seqnum++;
|
||||||
rtppay->timestamp = packetinfo->send_time;
|
rtppay->timestamp = packetinfo->send_time;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer");
|
GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer");
|
||||||
ret =
|
ret =
|
||||||
gst_pad_push (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay),
|
gst_pad_push (GST_RTP_BASE_PAYLOAD_SRCPAD (rtppay),
|
||||||
rtpasfpay->current);
|
rtpasfpay->current);
|
||||||
rtpasfpay->current = NULL;
|
rtpasfpay->current = NULL;
|
||||||
if (ret != GST_FLOW_OK) {
|
if (ret != GST_FLOW_OK) {
|
||||||
|
@ -313,6 +305,8 @@ static GstFlowReturn
|
||||||
gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
||||||
{
|
{
|
||||||
gchar *maxps;
|
gchar *maxps;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
g_return_val_if_fail (rtpasfpay->headers, GST_FLOW_ERROR);
|
g_return_val_if_fail (rtpasfpay->headers, GST_FLOW_ERROR);
|
||||||
|
|
||||||
if (!gst_asf_parse_headers (rtpasfpay->headers, &rtpasfpay->asfinfo))
|
if (!gst_asf_parse_headers (rtpasfpay->headers, &rtpasfpay->asfinfo))
|
||||||
|
@ -327,8 +321,9 @@ gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
||||||
|
|
||||||
/* get the config for caps */
|
/* get the config for caps */
|
||||||
g_free (rtpasfpay->config);
|
g_free (rtpasfpay->config);
|
||||||
rtpasfpay->config = g_base64_encode (GST_BUFFER_DATA (rtpasfpay->headers),
|
gst_buffer_map (rtpasfpay->headers, &map, GST_MAP_READ);
|
||||||
GST_BUFFER_SIZE (rtpasfpay->headers));
|
rtpasfpay->config = g_base64_encode (map.data, map.size);
|
||||||
|
gst_buffer_unmap (rtpasfpay->headers, &map);
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Serialized headers to base64 string %s",
|
GST_DEBUG_OBJECT (rtpasfpay, "Serialized headers to base64 string %s",
|
||||||
rtpasfpay->config);
|
rtpasfpay->config);
|
||||||
|
|
||||||
|
@ -338,7 +333,7 @@ gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
||||||
rtpasfpay->config);
|
rtpasfpay->config);
|
||||||
maxps =
|
maxps =
|
||||||
g_strdup_printf ("%" G_GUINT32_FORMAT, rtpasfpay->asfinfo.packet_size);
|
g_strdup_printf ("%" G_GUINT32_FORMAT, rtpasfpay->asfinfo.packet_size);
|
||||||
gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpasfpay), "maxps",
|
gst_rtp_base_payload_set_outcaps (GST_RTP_BASE_PAYLOAD (rtpasfpay), "maxps",
|
||||||
G_TYPE_STRING, maxps, "config", G_TYPE_STRING, rtpasfpay->config, NULL);
|
G_TYPE_STRING, maxps, "config", G_TYPE_STRING, rtpasfpay->config, NULL);
|
||||||
g_free (maxps);
|
g_free (maxps);
|
||||||
|
|
||||||
|
@ -353,7 +348,7 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
gst_rtp_asf_pay_handle_buffer (GstRTPBasePayload * rtppay, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstRtpAsfPay *rtpasfpay = GST_RTP_ASF_PAY_CAST (rtppay);
|
GstRtpAsfPay *rtpasfpay = GST_RTP_ASF_PAY_CAST (rtppay);
|
||||||
|
|
||||||
|
@ -361,7 +356,7 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
||||||
GST_LOG_OBJECT (rtpasfpay,
|
GST_LOG_OBJECT (rtpasfpay,
|
||||||
"Dropping buffer as we already pushed all packets");
|
"Dropping buffer as we already pushed all packets");
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
return GST_FLOW_UNEXPECTED; /* we already finished our job */
|
return GST_FLOW_EOS; /* we already finished our job */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive headers
|
/* receive headers
|
||||||
|
@ -369,20 +364,20 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
||||||
if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) {
|
if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) {
|
||||||
guint64 header_size;
|
guint64 header_size;
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (buffer) < 24) { /* guid+object size size */
|
if (gst_buffer_get_size (buffer) < 24) { /* guid+object size size */
|
||||||
GST_ERROR_OBJECT (rtpasfpay,
|
GST_ERROR_OBJECT (rtpasfpay,
|
||||||
"Buffer too small, smaller than a Guid and object size");
|
"Buffer too small, smaller than a Guid and object size");
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
header_size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (buffer),
|
header_size = gst_asf_match_and_peek_obj_size_buf (buffer,
|
||||||
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
||||||
if (header_size > 0) {
|
if (header_size > 0) {
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "ASF header guid received, size %"
|
GST_DEBUG_OBJECT (rtpasfpay, "ASF header guid received, size %"
|
||||||
G_GUINT64_FORMAT, header_size);
|
G_GUINT64_FORMAT, header_size);
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (buffer) < header_size) {
|
if (gst_buffer_get_size (buffer) < header_size) {
|
||||||
GST_ERROR_OBJECT (rtpasfpay, "Headers should be contained in a single"
|
GST_ERROR_OBJECT (rtpasfpay, "Headers should be contained in a single"
|
||||||
" buffer");
|
" buffer");
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
@ -396,14 +391,16 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Storing headers");
|
GST_DEBUG_OBJECT (rtpasfpay, "Storing headers");
|
||||||
if (GST_BUFFER_SIZE (buffer) == header_size) {
|
if (gst_buffer_get_size (buffer) == header_size) {
|
||||||
rtpasfpay->headers = buffer;
|
rtpasfpay->headers = buffer;
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
} else {
|
} else {
|
||||||
/* headers are a subbuffer of thie buffer */
|
/* headers are a subbuffer of thie buffer */
|
||||||
GstBuffer *aux = gst_buffer_create_sub (buffer, header_size,
|
GstBuffer *aux = gst_buffer_copy_region (buffer,
|
||||||
GST_BUFFER_SIZE (buffer) - header_size);
|
GST_BUFFER_COPY_ALL, header_size,
|
||||||
rtpasfpay->headers = gst_buffer_create_sub (buffer, 0, header_size);
|
gst_buffer_get_size (buffer) - header_size);
|
||||||
|
rtpasfpay->headers = gst_buffer_copy_region (buffer,
|
||||||
|
GST_BUFFER_COPY_ALL, 0, header_size);
|
||||||
gst_buffer_replace (&buffer, aux);
|
gst_buffer_replace (&buffer, aux);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,21 +412,25 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (rtpasfpay->state == ASF_DATA_OBJECT)) {
|
if (G_UNLIKELY (rtpasfpay->state == ASF_DATA_OBJECT)) {
|
||||||
if (GST_BUFFER_SIZE (buffer) != ASF_DATA_OBJECT_SIZE) {
|
GstMapInfo map;
|
||||||
|
|
||||||
|
if (gst_buffer_get_size (buffer) != ASF_DATA_OBJECT_SIZE) {
|
||||||
GST_ERROR_OBJECT (rtpasfpay, "Received buffer of different size of "
|
GST_ERROR_OBJECT (rtpasfpay, "Received buffer of different size of "
|
||||||
"the data object header");
|
"the data object header");
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_asf_match_guid (GST_BUFFER_DATA (buffer),
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
&(guids[ASF_DATA_OBJECT_INDEX]))) {
|
if (gst_asf_match_guid (map.data, &(guids[ASF_DATA_OBJECT_INDEX]))) {
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
GST_DEBUG_OBJECT (rtpasfpay, "Received data object header");
|
GST_DEBUG_OBJECT (rtpasfpay, "Received data object header");
|
||||||
rtpasfpay->headers = gst_buffer_append (rtpasfpay->headers, buffer);
|
rtpasfpay->headers = gst_buffer_append (rtpasfpay->headers, buffer);
|
||||||
rtpasfpay->state = ASF_PACKETS;
|
rtpasfpay->state = ASF_PACKETS;
|
||||||
|
|
||||||
return gst_rtp_asf_pay_parse_headers (rtpasfpay);
|
return gst_rtp_asf_pay_parse_headers (rtpasfpay);
|
||||||
} else {
|
} else {
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
GST_ERROR_OBJECT (rtpasfpay, "Unexpected object received (was expecting "
|
GST_ERROR_OBJECT (rtpasfpay, "Unexpected object received (was expecting "
|
||||||
"data object)");
|
"data object)");
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
@ -454,7 +455,7 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
||||||
GST_INFO_OBJECT (rtpasfpay, "Packets ended");
|
GST_INFO_OBJECT (rtpasfpay, "Packets ended");
|
||||||
rtpasfpay->state = ASF_END;
|
rtpasfpay->state = ASF_END;
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_EOS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define __GST_RTP_ASF_PAY_H__
|
#define __GST_RTP_ASF_PAY_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/rtp/gstbasertppayload.h>
|
#include <gst/rtp/gstrtpbasepayload.h>
|
||||||
#include <gst/rtp/gstrtpbuffer.h>
|
#include <gst/rtp/gstrtpbuffer.h>
|
||||||
#include <gst/base/gstadapter.h>
|
#include <gst/base/gstadapter.h>
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ typedef struct _GstRtpAsfPayClass GstRtpAsfPayClass;
|
||||||
|
|
||||||
struct _GstRtpAsfPay
|
struct _GstRtpAsfPay
|
||||||
{
|
{
|
||||||
GstBaseRTPPayload rtppay;
|
GstRTPBasePayload rtppay;
|
||||||
|
|
||||||
enum GstRtpAsfPayState state;
|
enum GstRtpAsfPayState state;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ struct _GstRtpAsfPay
|
||||||
|
|
||||||
struct _GstRtpAsfPayClass
|
struct _GstRtpAsfPayClass
|
||||||
{
|
{
|
||||||
GstBaseRTPPayloadClass parent_class;
|
GstRTPBasePayloadClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_rtp_asf_pay_get_type (void);
|
GType gst_rtp_asf_pay_get_type (void);
|
||||||
|
|
Loading…
Reference in a new issue