mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +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 Non ported plugins (non-dependant, then dependant)
|
||||
dnl Make sure you have a space before and after all plugins
|
||||
GST_PLUGINS_NONPORTED=" aiff asfmux \
|
||||
GST_PLUGINS_NONPORTED=" aiff \
|
||||
camerabin cdxaparse coloreffects \
|
||||
dccp faceoverlay festival \
|
||||
fieldanalysis freeverb freeze frei0r gaudieffects \
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#include "gstasfmux.h"
|
||||
|
||||
|
@ -149,12 +150,14 @@ static GstStaticPadTemplate audio_sink_factory =
|
|||
"audio/mpeg, layer = (int) 3, mpegversion = (int) 1, "
|
||||
"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_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,
|
||||
GstPadTemplate * templ, const gchar * name);
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||
static void gst_asf_mux_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
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,
|
||||
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 GstFlowReturn gst_asf_mux_collected (GstCollectPads * collect,
|
||||
|
@ -178,7 +182,7 @@ gst_asf_mux_get_type (void)
|
|||
if (!asfmux_type) {
|
||||
static const GTypeInfo asfmux_info = {
|
||||
sizeof (GstAsfMuxClass),
|
||||
gst_asf_mux_base_init,
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_asf_mux_class_init,
|
||||
NULL,
|
||||
|
@ -233,26 +237,6 @@ gst_asf_mux_reset (GstAsfMux * 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
|
||||
gst_asf_mux_finalize (GObject * object)
|
||||
{
|
||||
|
@ -321,17 +305,26 @@ gst_asf_mux_class_init (GstAsfMuxClass * klass)
|
|||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_asf_mux_request_new_pad);
|
||||
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
|
||||
gst_asf_mux_init (GstAsfMux * asfmux)
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
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_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,
|
||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_asf_mux_collected),
|
||||
asfmux);
|
||||
gst_collect_pads_set_event_function (asfmux->collect,
|
||||
(GstCollectPadsEventFunction) GST_DEBUG_FUNCPTR (gst_asf_mux_sink_event),
|
||||
asfmux);
|
||||
|
||||
asfmux->payloads = NULL;
|
||||
asfmux->prop_packet_size = DEFAULT_PACKET_SIZE;
|
||||
|
@ -350,14 +346,26 @@ gst_asf_mux_init (GstAsfMux * asfmux)
|
|||
}
|
||||
|
||||
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;
|
||||
GstAsfMux *asfmux;
|
||||
GstAsfPad *asfpad = (GstAsfPad *) gst_pad_get_element_private (pad);
|
||||
GstAsfPad *asfpad = (GstAsfPad *) cdata;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
asfmux = GST_ASF_MUX_CAST (gst_pad_get_parent (pad));
|
||||
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:{
|
||||
GST_DEBUG_OBJECT (asfmux, "received tag event");
|
||||
/* 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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
@ -385,8 +393,9 @@ gst_asf_mux_sink_event (GstPad * pad, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
ret = asfmux->collect_event (pad, event);
|
||||
gst_object_unref (asfmux);
|
||||
if (event != NULL)
|
||||
return gst_collect_pads_event_default (pads, cdata, event, FALSE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -403,10 +412,9 @@ static GstFlowReturn
|
|||
gst_asf_mux_push_buffer (GstAsfMux * asfmux, GstBuffer * buf)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (asfmux->srcpad));
|
||||
ret = gst_pad_push (asfmux->srcpad, buf);
|
||||
if (ret == GST_FLOW_OK)
|
||||
asfmux->file_size += GST_BUFFER_SIZE (buf);
|
||||
asfmux->file_size += gst_buffer_get_size (buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -505,7 +513,7 @@ gst_asf_mux_get_content_description_tags (GstAsfMux * asfmux,
|
|||
if (asftags->tags != NULL) {
|
||||
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->ext_cont_desc_size = 0;
|
||||
|
||||
|
@ -633,7 +641,7 @@ gst_asf_mux_get_headers_size (GstAsfMux * asfmux)
|
|||
size += ASF_VIDEO_SPECIFIC_DATA_SIZE;
|
||||
|
||||
if (asfpad->codec_data)
|
||||
size += GST_BUFFER_SIZE (asfpad->codec_data);
|
||||
size += gst_buffer_get_size (asfpad->codec_data);
|
||||
|
||||
stream_num++;
|
||||
}
|
||||
|
@ -713,7 +721,7 @@ gst_asf_mux_write_stream_properties (GstAsfMux * asfmux, guint8 ** buf,
|
|||
|
||||
/* codec specific data length */
|
||||
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)
|
||||
media_specific_data_length = ASF_AUDIO_SPECIFIC_DATA_SIZE;
|
||||
else
|
||||
|
@ -800,7 +808,7 @@ gst_asf_mux_write_stream_properties (GstAsfMux * asfmux, guint8 ** buf,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1286,6 +1294,9 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
|||
GstCaps *caps;
|
||||
GstStructure *structure;
|
||||
guint64 padding = asfmux->prop_padding;
|
||||
GstSegment segment;
|
||||
GstMapInfo map;
|
||||
|
||||
if (padding < ASF_PADDING_OBJECT_SIZE)
|
||||
padding = 0;
|
||||
|
||||
|
@ -1293,9 +1304,13 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
|||
GST_INFO_OBJECT (asfmux, "Writing 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 */
|
||||
gst_pad_push_event (asfmux->srcpad,
|
||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event (asfmux->srcpad, gst_event_new_segment (&segment));
|
||||
|
||||
gst_asf_generate_file_id (&asfmux->file_id);
|
||||
|
||||
|
@ -1318,14 +1333,16 @@ gst_asf_mux_start_file (GstAsfMux * asfmux)
|
|||
asftags->cont_desc_size +
|
||||
asftags->ext_cont_desc_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);
|
||||
|
||||
/* get the position of the file properties object for
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
gst_structure_set_value (structure, "streamheader", &streamheader);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1423,11 +1441,11 @@ gst_asf_mux_add_simple_index_entry (GstAsfMux * asfmux,
|
|||
static GstFlowReturn
|
||||
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++;
|
||||
GST_LOG_OBJECT (asfmux,
|
||||
"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,
|
||||
asfmux->total_data_packets);
|
||||
return gst_asf_mux_push_buffer (asfmux, buf);
|
||||
|
@ -1457,6 +1475,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||
AsfPayload *payload;
|
||||
guint32 payload_size;
|
||||
guint offset;
|
||||
GstMapInfo map;
|
||||
|
||||
if (asfmux->payloads == NULL)
|
||||
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");
|
||||
|
||||
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 */
|
||||
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;
|
||||
|
||||
has_keyframe = FALSE;
|
||||
|
@ -1509,7 +1529,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||
GST_DEBUG_OBJECT (asfmux, "replicated data length: %d",
|
||||
(gint) payload->replicated_data_length);
|
||||
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_TIME_FORMAT ")", payload->presentation_time,
|
||||
GST_TIME_ARGS (payload->presentation_time * GST_MSECOND));
|
||||
|
@ -1554,7 +1574,8 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||
payload = (AsfPayload *) aux->data;
|
||||
asfmux->payloads = g_slist_remove (asfmux->payloads, payload);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1586,7 +1607,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||
asfmux->payload_data_size);
|
||||
|
||||
/* fill payload parsing info */
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
data = map.data;
|
||||
/* flags */
|
||||
GST_WRITE_UINT8 (data, (0x0 << 7) | /* no error correction */
|
||||
(ASF_FIELD_TYPE_DWORD << 5) | /* packet length type */
|
||||
|
@ -1637,11 +1658,12 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||
|
||||
/* multiple payloads flags */
|
||||
GST_WRITE_UINT8 (data + offset, 0x2 << 6 | payloads_count);
|
||||
gst_buffer_unmap (buf, &map);
|
||||
|
||||
if (payloads_count == 0) {
|
||||
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)
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
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;
|
||||
GstBuffer *buf = gst_buffer_new_and_alloc (object_size);
|
||||
GSList *walk;
|
||||
guint8 *data = GST_BUFFER_DATA (buf);
|
||||
guint8 *data;
|
||||
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_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");
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1751,6 +1778,9 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
|||
GSList *walk;
|
||||
GstClockTime play_duration = 0;
|
||||
guint32 bitrate = 0;
|
||||
GstSegment segment;
|
||||
GstMapInfo map;
|
||||
guint8 *data;
|
||||
|
||||
/* write indexes */
|
||||
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 */
|
||||
GST_DEBUG_OBJECT (asfmux,
|
||||
"Sending new segment to file properties object position");
|
||||
event =
|
||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
||||
asfmux->file_properties_object_position + 40, GST_CLOCK_TIME_NONE, 0);
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
segment.start = segment.position =
|
||||
asfmux->file_properties_object_position + 40;
|
||||
event = gst_event_new_segment (&segment);
|
||||
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
||||
GST_ERROR_OBJECT (asfmux, "Failed to update file properties object");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
/* All file properties fields except the first 40 bytes */
|
||||
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_asf_put_time (GST_BUFFER_DATA (buf) + 8, gst_asf_get_current_time ());
|
||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 16, asfmux->total_data_packets);
|
||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 24, (play_duration / 100) +
|
||||
GST_WRITE_UINT64_LE (data, asfmux->file_size);
|
||||
gst_asf_put_time (data + 8, gst_asf_get_current_time ());
|
||||
GST_WRITE_UINT64_LE (data + 16, asfmux->total_data_packets);
|
||||
GST_WRITE_UINT64_LE (data + 24, (play_duration / 100) +
|
||||
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 (asfmux->preroll > play_duration / GST_MSECOND) {
|
||||
|
@ -1795,13 +1828,14 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
|||
("Preroll time larger than streams duration, "
|
||||
"try setting a smaller preroll value next time"));
|
||||
}
|
||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 40, asfmux->preroll);
|
||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 48, 0x2); /* flags - seekable */
|
||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 52, asfmux->packet_size);
|
||||
GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf) + 56, asfmux->packet_size);
|
||||
GST_WRITE_UINT64_LE (data + 40, asfmux->preroll);
|
||||
GST_WRITE_UINT32_LE (data + 48, 0x2); /* flags - seekable */
|
||||
GST_WRITE_UINT32_LE (data + 52, 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
|
||||
* 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
|
||||
* already sent data */
|
||||
|
@ -1814,19 +1848,20 @@ gst_asf_mux_stop_file (GstAsfMux * asfmux)
|
|||
GST_DEBUG_OBJECT (asfmux, "Seeking back to data object");
|
||||
|
||||
/* seek back to the data object */
|
||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
||||
asfmux->data_object_position + 16, GST_CLOCK_TIME_NONE, 0);
|
||||
|
||||
segment.start = segment.position = asfmux->data_object_position + 16;
|
||||
event = gst_event_new_segment (&segment);
|
||||
if (!gst_pad_push_event (asfmux->srcpad, event)) {
|
||||
GST_ERROR_OBJECT (asfmux, "Seek to update data object failed");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_and_alloc (32); /* qword+guid+qword */
|
||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf), asfmux->data_object_size +
|
||||
ASF_DATA_OBJECT_SIZE);
|
||||
gst_asf_put_guid (GST_BUFFER_DATA (buf) + 8, asfmux->file_id);
|
||||
GST_WRITE_UINT64_LE (GST_BUFFER_DATA (buf) + 24, asfmux->total_data_packets);
|
||||
gst_buffer_map (buf, &map, GST_MAP_WRITE);
|
||||
data = map.data;
|
||||
GST_WRITE_UINT64_LE (data, asfmux->data_object_size + ASF_DATA_OBJECT_SIZE);
|
||||
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);
|
||||
}
|
||||
|
@ -1871,7 +1906,7 @@ gst_asf_mux_process_buffer (GstAsfMux * asfmux, GstAsfPad * pad,
|
|||
payload->replicated_data_length = 8;
|
||||
|
||||
/* 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 */
|
||||
if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
|
||||
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->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,
|
||||
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))
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
return GST_FLOW_EOS;
|
||||
|
||||
/* select the earliest buffer */
|
||||
walk = asfmux->collect->data;
|
||||
|
@ -1999,7 +2034,7 @@ gst_asf_mux_collected (GstCollectPads * collect, gpointer data)
|
|||
}
|
||||
if (ret == GST_FLOW_OK) {
|
||||
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;
|
||||
}
|
||||
|
@ -2201,7 +2236,7 @@ gst_asf_mux_video_set_caps (GstPad * pad, GstCaps * caps)
|
|||
videopad->vidinfo.bit_cnt = 24;
|
||||
|
||||
/* 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;
|
||||
} else {
|
||||
gint version;
|
||||
|
@ -2233,7 +2268,7 @@ refuse_caps:
|
|||
|
||||
static GstPad *
|
||||
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);
|
||||
GstAsfMux *asfmux = GST_ASF_MUX_CAST (element);
|
||||
|
@ -2241,7 +2276,9 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
|||
GstAsfPad *collect_pad;
|
||||
gboolean is_audio;
|
||||
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));
|
||||
|
||||
|
@ -2251,27 +2288,37 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
|
||||
name = g_strdup_printf ("audio_%02d", asfmux->stream_number + 1);
|
||||
if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
|
||||
/* 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);
|
||||
newpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
newpad = gst_pad_new_from_template (templ, pad_name);
|
||||
is_audio = TRUE;
|
||||
gst_pad_set_setcaps_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_asf_mux_audio_set_caps));
|
||||
} else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
|
||||
name = g_strdup_printf ("video_%02d", asfmux->stream_number + 1);
|
||||
} else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
|
||||
/* 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, "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);
|
||||
newpad = gst_pad_new_from_template (templ, name);
|
||||
g_free (name);
|
||||
is_audio = FALSE;
|
||||
gst_pad_set_setcaps_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_asf_mux_video_set_caps));
|
||||
} else {
|
||||
GST_WARNING_OBJECT (asfmux, "This is not our template!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
|
||||
/* add pad to collections */
|
||||
if (is_audio) {
|
||||
collect_size = sizeof (GstAsfAudioPad);
|
||||
|
@ -2293,14 +2340,6 @@ gst_asf_mux_request_new_pad (GstElement * element,
|
|||
asfmux->stream_number += 1;
|
||||
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_element_add_pad (element, newpad);
|
||||
|
||||
|
|
|
@ -144,7 +144,6 @@ struct _GstAsfMux
|
|||
GstPad *srcpad;
|
||||
|
||||
GstCollectPads *collect;
|
||||
GstPadEventFunction collect_event;
|
||||
};
|
||||
|
||||
struct _GstAsfMuxClass
|
||||
|
|
|
@ -213,7 +213,7 @@ gst_asf_file_info_free (GstAsfFileInfo * info)
|
|||
guint32
|
||||
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_UINT32_LE (buf + 7, payload->media_object_size);
|
||||
GST_WRITE_UINT32_LE (buf + 11, payload->presentation_time);
|
||||
GST_WRITE_UINT16_LE (buf + 15, (guint16) GST_BUFFER_SIZE (payload->data));
|
||||
memcpy (buf + 17, GST_BUFFER_DATA (payload->data),
|
||||
GST_BUFFER_SIZE (payload->data));
|
||||
GST_WRITE_UINT16_LE (buf + 15, (guint16) gst_buffer_get_size (payload->data));
|
||||
gst_buffer_extract (payload->data, 0, buf + 17,
|
||||
gst_buffer_get_size (payload->data));
|
||||
|
||||
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 + 11, payload->presentation_time);
|
||||
size -= ASF_MULTIPLE_PAYLOAD_HEADER_SIZE;
|
||||
payload_size = size < GST_BUFFER_SIZE (payload->data) ?
|
||||
size : GST_BUFFER_SIZE (payload->data);
|
||||
payload_size = size < gst_buffer_get_size (payload->data) ?
|
||||
size : gst_buffer_get_size (payload->data);
|
||||
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 */
|
||||
payload->offset_in_media_obj += payload_size;
|
||||
newbuf = gst_buffer_create_sub (payload->data, payload_size,
|
||||
GST_BUFFER_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);
|
||||
newbuf = gst_buffer_copy_region (payload->data, GST_BUFFER_COPY_ALL,
|
||||
payload_size, gst_buffer_get_size (payload->data) - payload_size);
|
||||
GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (payload->data);
|
||||
gst_buffer_unref (payload->data);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* @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;
|
||||
guint16 duration = 0;
|
||||
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");
|
||||
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))
|
||||
goto error;
|
||||
|
||||
|
@ -673,6 +699,7 @@ gst_asf_parse_packet (GstBuffer * buffer, GstAsfPacketInfo * packet,
|
|||
packet->seq_field_type = seq_len_type;
|
||||
packet->err_cor_len = err_length;
|
||||
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_byte_reader_free (reader);
|
||||
return ret;
|
||||
|
||||
|
@ -680,6 +707,7 @@ error:
|
|||
ret = FALSE;
|
||||
GST_WARNING ("Error while parsing data packet");
|
||||
end:
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_byte_reader_free (reader);
|
||||
return ret;
|
||||
}
|
||||
|
@ -738,16 +766,20 @@ gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info)
|
|||
guint32 i;
|
||||
GstByteReader *reader;
|
||||
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]));
|
||||
if (object_size == 0) {
|
||||
GST_WARNING ("ASF: Cannot parse, header guid not found at the beginning "
|
||||
" of data");
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
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))
|
||||
goto error;
|
||||
|
@ -785,6 +817,7 @@ error:
|
|||
ret = FALSE;
|
||||
GST_WARNING ("ASF: Error while parsing headers");
|
||||
end:
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_byte_reader_free (reader);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,8 @@ gboolean gst_asf_parse_packet (GstBuffer * buffer, GstAsfPacketInfo * packet,
|
|||
gboolean trust_delta_flag, guint packet_size);
|
||||
guint64 gst_asf_match_and_peek_obj_size (const guint8 * data,
|
||||
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);
|
||||
|
||||
/* ASF tags
|
||||
|
|
|
@ -46,7 +46,8 @@ static GstStateChangeReturn gst_asf_parse_change_state (GstElement * element,
|
|||
GstStateChange transition);
|
||||
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
|
||||
gst_asf_parse_reset (GstAsfParse * asfparse)
|
||||
|
@ -61,29 +62,62 @@ gst_asf_parse_reset (GstAsfParse * asfparse)
|
|||
}
|
||||
|
||||
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)) {
|
||||
return gst_pad_activate_pull (pad, TRUE);
|
||||
} else {
|
||||
return gst_pad_activate_push (pad, TRUE);
|
||||
GstQuery *query;
|
||||
gboolean pull_mode;
|
||||
|
||||
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
|
||||
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) {
|
||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_asf_parse_loop, pad);
|
||||
} else {
|
||||
return gst_pad_stop_task (pad);
|
||||
gboolean res;
|
||||
|
||||
switch (mode) {
|
||||
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
|
||||
gst_asf_parse_push (GstAsfParse * asfparse, GstBuffer * buf)
|
||||
{
|
||||
gst_buffer_set_caps (buf, asfparse->outcaps);
|
||||
return gst_pad_push (asfparse->srcpad, buf);
|
||||
}
|
||||
|
||||
|
@ -93,10 +127,12 @@ gst_asf_parse_parse_data_object (GstAsfParse * asfparse, GstBuffer * buffer)
|
|||
GstByteReader *reader;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
guint64 packet_count = 0;
|
||||
GstMapInfo map;
|
||||
|
||||
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 */
|
||||
if (!gst_byte_reader_skip (reader, 40))
|
||||
goto error;
|
||||
|
@ -112,12 +148,14 @@ gst_asf_parse_parse_data_object (GstAsfParse * asfparse, GstBuffer * buffer)
|
|||
packet_count);
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_byte_reader_free (reader);
|
||||
return gst_asf_parse_push (asfparse, buffer);
|
||||
|
||||
error:
|
||||
ret = GST_FLOW_ERROR;
|
||||
GST_ERROR_OBJECT (asfparse, "Error while parsing data object headers");
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
gst_byte_reader_free (reader);
|
||||
return ret;
|
||||
}
|
||||
|
@ -161,6 +199,7 @@ gst_asf_parse_pull_headers (GstAsfParse * asfparse)
|
|||
GstBuffer *headers = NULL;
|
||||
guint64 size;
|
||||
GstFlowReturn ret;
|
||||
GstMapInfo map;
|
||||
|
||||
if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
|
||||
ASF_GUID_OBJSIZE_SIZE, &guid_and_size)) != GST_FLOW_OK) {
|
||||
|
@ -168,8 +207,10 @@ gst_asf_parse_pull_headers (GstAsfParse * asfparse)
|
|||
goto leave;
|
||||
}
|
||||
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]));
|
||||
gst_buffer_unmap (guid_and_size, &map);
|
||||
|
||||
if (size == 0) {
|
||||
GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing");
|
||||
|
@ -209,7 +250,7 @@ gst_asf_parse_pull_data_header (GstAsfParse * asfparse)
|
|||
return ret;
|
||||
}
|
||||
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]));
|
||||
if (asfparse->data_size == 0) {
|
||||
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)
|
||||
break;
|
||||
/* we can peek at the object size */
|
||||
obj_size =
|
||||
gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (guid_and_size), NULL);
|
||||
obj_size = gst_asf_match_and_peek_obj_size_buf (guid_and_size, NULL);
|
||||
if (obj_size == 0) {
|
||||
GST_ERROR_OBJECT (asfparse, "Incomplete object found");
|
||||
gst_buffer_unref (guid_and_size);
|
||||
|
@ -346,9 +386,9 @@ pause:
|
|||
GST_INFO_OBJECT (asfparse, "Pausing sinkpad task");
|
||||
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 ());
|
||||
} 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,
|
||||
(NULL), ("streaming task paused, reason %s (%d)", reason, ret));
|
||||
gst_pad_push_event (asfparse->srcpad, gst_event_new_eos ());
|
||||
|
@ -357,12 +397,12 @@ pause:
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||
gst_asf_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstAsfParse *asfparse;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
asfparse = GST_ASF_PARSE (GST_PAD_PARENT (pad));
|
||||
asfparse = GST_ASF_PARSE (parent);
|
||||
gst_adapter_push (asfparse->adapter, buffer);
|
||||
|
||||
switch (asfparse->parse_state) {
|
||||
|
@ -372,9 +412,10 @@ gst_asf_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
/* we can peek at the object 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),
|
||||
&(guids[ASF_HEADER_OBJECT_INDEX]));
|
||||
gst_adapter_unmap (asfparse->adapter);
|
||||
|
||||
if (asfparse->headers_size == 0) {
|
||||
/* 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 */
|
||||
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),
|
||||
&(guids[ASF_DATA_OBJECT_INDEX]));
|
||||
gst_adapter_unmap (asfparse->adapter);
|
||||
|
||||
if (asfparse->data_size == 0) {
|
||||
/* 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) {
|
||||
guint64 obj_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);
|
||||
gst_adapter_unmap (asfparse->adapter);
|
||||
if (gst_adapter_available (asfparse->adapter) >= obj_size) {
|
||||
GST_DEBUG_OBJECT (asfparse, "Skiping object");
|
||||
ret = gst_asf_parse_push (asfparse,
|
||||
|
@ -467,23 +510,6 @@ end:
|
|||
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
|
||||
gst_asf_parse_finalize (GObject * object)
|
||||
{
|
||||
|
@ -511,17 +537,28 @@ gst_asf_parse_class_init (GstAsfParseClass * klass)
|
|||
|
||||
gstelement_class->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
|
||||
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");
|
||||
gst_pad_set_chain_function (asfparse->sinkpad, gst_asf_parse_chain);
|
||||
gst_pad_set_activate_function (asfparse->sinkpad,
|
||||
gst_asf_parse_sink_activate);
|
||||
gst_pad_set_activatepull_function (asfparse->sinkpad,
|
||||
gst_asf_parse_sink_activate_pull);
|
||||
gst_pad_set_activatemode_function (asfparse->sinkpad,
|
||||
gst_asf_parse_sink_activate_mode);
|
||||
gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->sinkpad);
|
||||
|
||||
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);
|
||||
|
||||
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->packetinfo = g_new0 (GstAsfPacketInfo, 1);
|
||||
gst_asf_parse_reset (asfparse);
|
||||
|
|
|
@ -51,15 +51,15 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
|||
);
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer);
|
||||
gst_rtp_asf_pay_handle_buffer (GstRTPBasePayload * rtppay, GstBuffer * buffer);
|
||||
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,
|
||||
GST_TYPE_BASE_RTP_PAYLOAD);
|
||||
#define gst_rtp_asf_pay_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstRtpAsfPay, gst_rtp_asf_pay, GST_TYPE_RTP_BASE_PAYLOAD);
|
||||
|
||||
static void
|
||||
gst_rtp_asf_pay_init (GstRtpAsfPay * rtpasfpay, GstRtpAsfPayClass * klass)
|
||||
gst_rtp_asf_pay_init (GstRtpAsfPay * rtpasfpay)
|
||||
{
|
||||
rtpasfpay->first_ts = 0;
|
||||
rtpasfpay->config = NULL;
|
||||
|
@ -80,44 +80,40 @@ gst_rtp_asf_pay_finalize (GObject * 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
|
||||
gst_rtp_asf_pay_class_init (GstRtpAsfPayClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
||||
GstElementClass *gstelement_class;
|
||||
GstRTPBasePayloadClass *gstbasertppayload_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
gstbasertppayload_class = (GstRTPBasePayloadClass *) klass;
|
||||
|
||||
gobject_class->finalize = gst_rtp_asf_pay_finalize;
|
||||
|
||||
gstbasertppayload_class->handle_buffer = gst_rtp_asf_pay_handle_buffer;
|
||||
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,
|
||||
"ASF RTP Payloader");
|
||||
}
|
||||
|
||||
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 */
|
||||
gst_basertppayload_set_options (rtppay, "application", TRUE, "X-ASF-PF",
|
||||
gst_rtp_base_payload_set_options (rtppay, "application", TRUE, "X-ASF-PF",
|
||||
1000);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -125,7 +121,7 @@ gst_rtp_asf_pay_set_caps (GstBaseRTPPayload * rtppay, GstCaps * caps)
|
|||
static GstFlowReturn
|
||||
gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
||||
{
|
||||
GstBaseRTPPayload *rtppay;
|
||||
GstRTPBasePayload *rtppay;
|
||||
GstAsfPacketInfo *packetinfo;
|
||||
guint8 flags;
|
||||
guint8 *data;
|
||||
|
@ -134,7 +130,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
|||
guint32 size_left;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
rtppay = GST_BASE_RTP_PAYLOAD (rtpasfpay);
|
||||
rtppay = GST_RTP_BASE_PAYLOAD (rtpasfpay);
|
||||
packetinfo = &rtpasfpay->packetinfo;
|
||||
|
||||
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);
|
||||
switch (packetinfo->padd_field_type) {
|
||||
case ASF_FIELD_TYPE_DWORD:
|
||||
GST_WRITE_UINT32_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
|
||||
gst_buffer_memset (buffer, offset, 0, 4);
|
||||
break;
|
||||
case ASF_FIELD_TYPE_WORD:
|
||||
GST_WRITE_UINT16_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0);
|
||||
gst_buffer_memset (buffer, offset, 0, 2);
|
||||
break;
|
||||
case ASF_FIELD_TYPE_BYTE:
|
||||
GST_BUFFER_DATA (buffer)[offset] = 0;
|
||||
gst_buffer_memset (buffer, offset, 0, 1);
|
||||
break;
|
||||
case ASF_FIELD_TYPE_NONE:
|
||||
default:
|
||||
|
@ -189,23 +185,26 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
|||
* This flag tells us to push the packet.
|
||||
*/
|
||||
gboolean force_push = FALSE;
|
||||
GstRTPBuffer rtp;
|
||||
|
||||
/* we have no output buffer pending, create one */
|
||||
if (rtpasfpay->current == NULL) {
|
||||
GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer");
|
||||
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);
|
||||
rtpasfpay->cur_off = gst_rtp_buffer_get_header_len (rtpasfpay->current);
|
||||
rtpasfpay->cur_off = 0;
|
||||
rtpasfpay->has_ts = FALSE;
|
||||
rtpasfpay->marker = FALSE;
|
||||
}
|
||||
data = GST_BUFFER_DATA (rtpasfpay->current) + rtpasfpay->cur_off;
|
||||
size_left = GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off;
|
||||
gst_rtp_buffer_map (rtpasfpay->current, GST_MAP_READWRITE, &rtp);
|
||||
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: %"
|
||||
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, "Current offset: %" G_GUINT32_FORMAT,
|
||||
|
@ -230,8 +229,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
|||
rtpasfpay->ts = packetinfo->send_time;
|
||||
}
|
||||
|
||||
if (GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off >=
|
||||
packet_util_size + 8) {
|
||||
if (size_left >= packet_util_size + 8) {
|
||||
/* enough space for the rest of the packet */
|
||||
if (packet_offset == 0) {
|
||||
flags = flags | 0x40;
|
||||
|
@ -243,8 +241,7 @@ gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer)
|
|||
data[0] = flags;
|
||||
GST_WRITE_UINT32_BE (data + 4,
|
||||
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
||||
memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
|
||||
packet_util_size);
|
||||
gst_buffer_extract (buffer, packet_offset, data + 8, packet_util_size);
|
||||
|
||||
/* updating status variables */
|
||||
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_UINT32_BE (data + 4,
|
||||
(gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts);
|
||||
memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset,
|
||||
size_left - 8);
|
||||
gst_buffer_extract (buffer, packet_offset, data + 8, size_left - 8);
|
||||
|
||||
/* updating status variables */
|
||||
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 */
|
||||
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) {
|
||||
/* trim remaining bytes not used */
|
||||
GstBuffer *aux = gst_buffer_create_sub (rtpasfpay->current, 0,
|
||||
GST_BUFFER_SIZE (rtpasfpay->current) - size_left);
|
||||
gst_buffer_unref (rtpasfpay->current);
|
||||
rtpasfpay->current = aux;
|
||||
gst_buffer_set_size (rtpasfpay->current,
|
||||
gst_buffer_get_size (rtpasfpay->current) - size_left);
|
||||
}
|
||||
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_set_caps (rtpasfpay->current,
|
||||
GST_PAD_CAPS (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay)));
|
||||
|
||||
rtppay->seqnum++;
|
||||
rtppay->timestamp = packetinfo->send_time;
|
||||
|
||||
GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer");
|
||||
ret =
|
||||
gst_pad_push (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay),
|
||||
gst_pad_push (GST_RTP_BASE_PAYLOAD_SRCPAD (rtppay),
|
||||
rtpasfpay->current);
|
||||
rtpasfpay->current = NULL;
|
||||
if (ret != GST_FLOW_OK) {
|
||||
|
@ -313,6 +305,8 @@ static GstFlowReturn
|
|||
gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
||||
{
|
||||
gchar *maxps;
|
||||
GstMapInfo map;
|
||||
|
||||
g_return_val_if_fail (rtpasfpay->headers, GST_FLOW_ERROR);
|
||||
|
||||
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 */
|
||||
g_free (rtpasfpay->config);
|
||||
rtpasfpay->config = g_base64_encode (GST_BUFFER_DATA (rtpasfpay->headers),
|
||||
GST_BUFFER_SIZE (rtpasfpay->headers));
|
||||
gst_buffer_map (rtpasfpay->headers, &map, GST_MAP_READ);
|
||||
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",
|
||||
rtpasfpay->config);
|
||||
|
||||
|
@ -338,7 +333,7 @@ gst_rtp_asf_pay_parse_headers (GstRtpAsfPay * rtpasfpay)
|
|||
rtpasfpay->config);
|
||||
maxps =
|
||||
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_free (maxps);
|
||||
|
||||
|
@ -353,7 +348,7 @@ error:
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -361,7 +356,7 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
|||
GST_LOG_OBJECT (rtpasfpay,
|
||||
"Dropping buffer as we already pushed all packets");
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_UNEXPECTED; /* we already finished our job */
|
||||
return GST_FLOW_EOS; /* we already finished our job */
|
||||
}
|
||||
|
||||
/* receive headers
|
||||
|
@ -369,20 +364,20 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
|||
if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) {
|
||||
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,
|
||||
"Buffer too small, smaller than a Guid and object size");
|
||||
gst_buffer_unref (buffer);
|
||||
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]));
|
||||
if (header_size > 0) {
|
||||
GST_DEBUG_OBJECT (rtpasfpay, "ASF header guid received, 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"
|
||||
" 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");
|
||||
if (GST_BUFFER_SIZE (buffer) == header_size) {
|
||||
if (gst_buffer_get_size (buffer) == header_size) {
|
||||
rtpasfpay->headers = buffer;
|
||||
return GST_FLOW_OK;
|
||||
} else {
|
||||
/* headers are a subbuffer of thie buffer */
|
||||
GstBuffer *aux = gst_buffer_create_sub (buffer, header_size,
|
||||
GST_BUFFER_SIZE (buffer) - header_size);
|
||||
rtpasfpay->headers = gst_buffer_create_sub (buffer, 0, header_size);
|
||||
GstBuffer *aux = gst_buffer_copy_region (buffer,
|
||||
GST_BUFFER_COPY_ALL, 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);
|
||||
}
|
||||
}
|
||||
|
@ -415,21 +412,25 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
|||
}
|
||||
|
||||
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 "
|
||||
"the data object header");
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
if (gst_asf_match_guid (GST_BUFFER_DATA (buffer),
|
||||
&(guids[ASF_DATA_OBJECT_INDEX]))) {
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
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");
|
||||
rtpasfpay->headers = gst_buffer_append (rtpasfpay->headers, buffer);
|
||||
rtpasfpay->state = ASF_PACKETS;
|
||||
|
||||
return gst_rtp_asf_pay_parse_headers (rtpasfpay);
|
||||
} else {
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
GST_ERROR_OBJECT (rtpasfpay, "Unexpected object received (was expecting "
|
||||
"data object)");
|
||||
gst_buffer_unref (buffer);
|
||||
|
@ -454,7 +455,7 @@ gst_rtp_asf_pay_handle_buffer (GstBaseRTPPayload * rtppay, GstBuffer * buffer)
|
|||
GST_INFO_OBJECT (rtpasfpay, "Packets ended");
|
||||
rtpasfpay->state = ASF_END;
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
return GST_FLOW_EOS;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define __GST_RTP_ASF_PAY_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/rtp/gstbasertppayload.h>
|
||||
#include <gst/rtp/gstrtpbasepayload.h>
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
|
||||
|
@ -53,7 +53,7 @@ typedef struct _GstRtpAsfPayClass GstRtpAsfPayClass;
|
|||
|
||||
struct _GstRtpAsfPay
|
||||
{
|
||||
GstBaseRTPPayload rtppay;
|
||||
GstRTPBasePayload rtppay;
|
||||
|
||||
enum GstRtpAsfPayState state;
|
||||
|
||||
|
@ -77,7 +77,7 @@ struct _GstRtpAsfPay
|
|||
|
||||
struct _GstRtpAsfPayClass
|
||||
{
|
||||
GstBaseRTPPayloadClass parent_class;
|
||||
GstRTPBasePayloadClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_rtp_asf_pay_get_type (void);
|
||||
|
|
Loading…
Reference in a new issue