From e79cae30027df0cc388e223bd28c350256544bf5 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Apr 2012 16:55:18 +0200 Subject: [PATCH] asfmux: port to 0.11 --- configure.ac | 2 +- gst/asfmux/gstasfmux.c | 255 ++++++++++++++++++++++++++------------------- gst/asfmux/gstasfmux.h | 1 - gst/asfmux/gstasfobjects.c | 67 +++++++++--- gst/asfmux/gstasfobjects.h | 2 + gst/asfmux/gstasfparse.c | 127 ++++++++++++++-------- gst/asfmux/gstrtpasfpay.c | 143 ++++++++++++------------- gst/asfmux/gstrtpasfpay.h | 6 +- 8 files changed, 357 insertions(+), 246 deletions(-) diff --git a/configure.ac b/configure.ac index ef88440..4baf1ec 100644 --- a/configure.ac +++ b/configure.ac @@ -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 \ diff --git a/gst/asfmux/gstasfmux.c b/gst/asfmux/gstasfmux.c index d43ae39..be1a09e 100644 --- a/gst/asfmux/gstasfmux.c +++ b/gst/asfmux/gstasfmux.c @@ -73,6 +73,7 @@ #endif #include +#include #include #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, @@ -234,26 +238,6 @@ gst_asf_mux_reset (GstAsfMux * 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 "); - - GST_DEBUG_CATEGORY_INIT (asfmux_debug, "asfmux", 0, "Muxer for ASF streams"); -} - -static void gst_asf_mux_finalize (GObject * object) { GstAsfMux *asfmux; @@ -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 "); + + 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); diff --git a/gst/asfmux/gstasfmux.h b/gst/asfmux/gstasfmux.h index 4036aa1..b0f5fab 100644 --- a/gst/asfmux/gstasfmux.h +++ b/gst/asfmux/gstasfmux.h @@ -144,7 +144,6 @@ struct _GstAsfMux GstPad *srcpad; GstCollectPads *collect; - GstPadEventFunction collect_event; }; struct _GstAsfMuxClass diff --git a/gst/asfmux/gstasfobjects.c b/gst/asfmux/gstasfobjects.c index 6496062..206cb68 100644 --- a/gst/asfmux/gstasfobjects.c +++ b/gst/asfmux/gstasfobjects.c @@ -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; @@ -425,6 +422,33 @@ gst_asf_match_and_peek_obj_size (const guint8 * data, const Guid * guid) } /** + * 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 * @has_keyframe: pointer to return the result @@ -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; + + gst_buffer_map (buffer, &map, GST_MAP_READ); - object_size = gst_asf_match_and_peek_obj_size (GST_BUFFER_DATA (buffer), + 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; } diff --git a/gst/asfmux/gstasfobjects.h b/gst/asfmux/gstasfobjects.h index 2a91a4c..01939be 100644 --- a/gst/asfmux/gstasfobjects.h +++ b/gst/asfmux/gstasfobjects.h @@ -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 diff --git a/gst/asfmux/gstasfparse.c b/gst/asfmux/gstasfparse.c index 9efb390..32265a6 100644 --- a/gst/asfmux/gstasfparse.c +++ b/gst/asfmux/gstasfparse.c @@ -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, @@ -468,23 +511,6 @@ end: } 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 "); - - GST_DEBUG_CATEGORY_INIT (asfparse_debug, "asfparse", 0, - "Parser for ASF streams"); -} - -static void gst_asf_parse_finalize (GObject * object) { GstAsfParse *asfparse = GST_ASF_PARSE (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 "); + + 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); diff --git a/gst/asfmux/gstrtpasfpay.c b/gst/asfmux/gstrtpasfpay.c index 1bc4dd6..aa6be25 100644 --- a/gst/asfmux/gstrtpasfpay.c +++ b/gst/asfmux/gstrtpasfpay.c @@ -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; @@ -81,43 +81,39 @@ gst_rtp_asf_pay_finalize (GObject * 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 "); -} - -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 "); + 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; } } diff --git a/gst/asfmux/gstrtpasfpay.h b/gst/asfmux/gstrtpasfpay.h index 8c7505a..8857aca 100644 --- a/gst/asfmux/gstrtpasfpay.h +++ b/gst/asfmux/gstrtpasfpay.h @@ -22,7 +22,7 @@ #define __GST_RTP_ASF_PAY_H__ #include -#include +#include #include #include @@ -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); -- 2.7.4