From 04134671c930cc2c6ba04d5980c4d2155b07e677 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 10 Dec 2013 10:34:02 -0300 Subject: [PATCH] asfparse: port to baseparse asfparse was not really functional after the port to 1.0 Now porting it to baseparse to get it working again --- gst/asfmux/gstasfobjects.c | 23 +- gst/asfmux/gstasfobjects.h | 1 + gst/asfmux/gstasfparse.c | 642 ++++++++++++++++----------------------------- gst/asfmux/gstasfparse.h | 17 +- 4 files changed, 241 insertions(+), 442 deletions(-) diff --git a/gst/asfmux/gstasfobjects.c b/gst/asfmux/gstasfobjects.c index b8ec94d..df4f69c 100644 --- a/gst/asfmux/gstasfobjects.c +++ b/gst/asfmux/gstasfobjects.c @@ -762,25 +762,35 @@ gst_asf_parse_file_properties_obj (GstByteReader * reader, gboolean gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info) { + GstMapInfo map; + gboolean ret; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + ret = gst_asf_parse_headers_from_data (map.data, map.size, file_info); + gst_buffer_unmap (buffer, &map); + + return ret; +} + +gboolean +gst_asf_parse_headers_from_data (guint8 * data, guint size, + GstAsfFileInfo * file_info) +{ gboolean ret = TRUE; guint32 header_objects = 0; 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 (map.data, + object_size = gst_asf_match_and_peek_obj_size (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 (map.data, map.size); + reader = gst_byte_reader_new (data, size); if (!gst_byte_reader_skip (reader, ASF_GUID_OBJSIZE_SIZE)) goto error; @@ -818,7 +828,6 @@ 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 0c1e202..fd8e97c 100644 --- a/gst/asfmux/gstasfobjects.h +++ b/gst/asfmux/gstasfobjects.h @@ -115,6 +115,7 @@ guint64 gst_asf_match_and_peek_obj_size (const guint8 * data, guint64 gst_asf_match_and_peek_obj_size_buf (GstBuffer * buf, const Guid * guid); gboolean gst_asf_parse_headers (GstBuffer * buffer, GstAsfFileInfo * file_info); +gboolean gst_asf_parse_headers_from_data (guint8 * data, guint size, GstAsfFileInfo * file_info); /* ASF tags * found at http://msdn.microsoft.com/en-us/library/dd562330(VS.85).aspx diff --git a/gst/asfmux/gstasfparse.c b/gst/asfmux/gstasfparse.c index 55bfe1d..bd23a79 100644 --- a/gst/asfmux/gstasfparse.c +++ b/gst/asfmux/gstasfparse.c @@ -42,99 +42,46 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_CAPS ("video/x-ms-asf, parsed = (boolean) false") ); -static GstStateChangeReturn gst_asf_parse_change_state (GstElement * element, - GstStateChange transition); -static void gst_asf_parse_loop (GstPad * pad); - #define gst_asf_parse_parent_class parent_class -G_DEFINE_TYPE (GstAsfParse, gst_asf_parse, GST_TYPE_ELEMENT); +G_DEFINE_TYPE (GstAsfParse, gst_asf_parse, GST_TYPE_BASE_PARSE); -static void -gst_asf_parse_reset (GstAsfParse * asfparse) +static gboolean +gst_asf_parse_start (GstBaseParse * parse) { - gst_adapter_clear (asfparse->adapter); + GstAsfParse *asfparse = GST_ASF_PARSE_CAST (parse); gst_asf_file_info_reset (asfparse->asfinfo); asfparse->parse_state = ASF_PARSING_HEADERS; - asfparse->headers_size = 0; - asfparse->data_size = 0; asfparse->parsed_packets = 0; - asfparse->offset = 0; -} -static gboolean -gst_asf_parse_sink_activate (GstPad * sinkpad, GstObject * parent) -{ - GstQuery *query; - gboolean pull_mode; + /* ASF Obj header length */ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + ASF_GUID_OBJSIZE_SIZE); - query = gst_query_new_scheduling (); + gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (asfparse), FALSE); - if (!gst_pad_peer_query (sinkpad, query)) { - gst_query_unref (query); - goto activate_push; - } - - pull_mode = gst_query_has_scheduling_mode_with_flags (query, - GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); - 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); - } + return TRUE; } static gboolean -gst_asf_parse_sink_activate_mode (GstPad * pad, GstObject * parent, - GstPadMode mode, gboolean active) +gst_asf_parse_stop (GstBaseParse * parse) { - gboolean res; - - switch (mode) { - case GST_PAD_MODE_PULL: - if (active) { - res = - gst_pad_start_task (pad, (GstTaskFunction) gst_asf_parse_loop, pad, - NULL); - } else { - res = gst_pad_stop_task (pad); - } - case GST_PAD_MODE_PUSH: - res = TRUE; - break; - default: - res = FALSE; - break; - } - - return res; -} + GstAsfParse *asfparse = GST_ASF_PARSE_CAST (parse); + gst_asf_file_info_reset (asfparse->asfinfo); -static GstFlowReturn -gst_asf_parse_push (GstAsfParse * asfparse, GstBuffer * buf) -{ - return gst_pad_push (asfparse->srcpad, buf); + return TRUE; } static GstFlowReturn -gst_asf_parse_parse_data_object (GstAsfParse * asfparse, GstBuffer * buffer) +gst_asf_parse_parse_data_object (GstAsfParse * asfparse, guint8 * data, + gsize size) { GstByteReader *reader; GstFlowReturn ret = GST_FLOW_OK; guint64 packet_count = 0; - GstMapInfo map; GST_DEBUG_OBJECT (asfparse, "Parsing data object"); - gst_buffer_map (buffer, &map, GST_MAP_READ); - reader = gst_byte_reader_new (map.data, map.size); + reader = gst_byte_reader_new (data, size); /* skip to packet count */ if (!gst_byte_reader_skip (reader, 40)) goto error; @@ -150,375 +97,279 @@ 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); + return GST_FLOW_OK; 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; } +/* reads the next object and pushes it through without parsing */ static GstFlowReturn -gst_asf_parse_parse_packet (GstAsfParse * asfparse, GstBuffer * buffer) +gst_asf_parse_handle_frame_push_object (GstAsfParse * asfparse, + GstBaseParseFrame * frame, gint * skipsize, const Guid * guid) { - GstAsfPacketInfo *packetinfo = asfparse->packetinfo; + GstBuffer *buffer = frame->buffer; + GstMapInfo map; + GstFlowReturn ret = GST_FLOW_OK; - if (!gst_asf_parse_packet (buffer, packetinfo, FALSE, - asfparse->asfinfo->packet_size)) - goto error; + gst_buffer_map (buffer, &map, GST_MAP_READ); + if (map.size >= ASF_GUID_OBJSIZE_SIZE) { + guint64 size; - GST_DEBUG_OBJECT (asfparse, "Received packet of length %" G_GUINT32_FORMAT - ", padding %" G_GUINT32_FORMAT ", send time %" G_GUINT32_FORMAT - ", duration %" G_GUINT16_FORMAT " and %s keyframe(s)", - packetinfo->packet_size, packetinfo->padding, - packetinfo->send_time, packetinfo->duration, - (packetinfo->has_keyframe) ? "with" : "without"); + size = gst_asf_match_and_peek_obj_size (map.data, guid); - /* set gstbuffer fields */ - if (!packetinfo->has_keyframe) { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - } - GST_BUFFER_TIMESTAMP (buffer) = ((GstClockTime) packetinfo->send_time) - * GST_MSECOND; - GST_BUFFER_DURATION (buffer) = ((GstClockTime) packetinfo->duration) - * GST_MSECOND; + if (size == 0) { + GST_ERROR_OBJECT (asfparse, "GUID starting identifier missing"); + ret = GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + goto end; + } - return gst_asf_parse_push (asfparse, buffer); + if (size > map.size) { + /* request all the obj data */ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), size); + gst_buffer_unmap (buffer, &map); + goto end; + } -error: - GST_ERROR_OBJECT (asfparse, "Error while parsing data packet"); - return GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + ASF_GUID_OBJSIZE_SIZE); + gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, size); + } else { + gst_buffer_unmap (buffer, &map); + *skipsize = 0; + } + +end: + return ret; } static GstFlowReturn -gst_asf_parse_pull_headers (GstAsfParse * asfparse) +gst_asf_parse_handle_frame_headers (GstAsfParse * asfparse, + GstBaseParseFrame * frame, gint * skipsize) { - GstBuffer *guid_and_size = NULL; - GstBuffer *headers = NULL; - guint64 size; - GstFlowReturn ret; + GstBuffer *buffer = frame->buffer; GstMapInfo map; + GstFlowReturn ret = GST_FLOW_OK; - if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, - ASF_GUID_OBJSIZE_SIZE, &guid_and_size)) != GST_FLOW_OK) { - GST_ERROR_OBJECT (asfparse, "Failed to pull data from headers"); - goto leave; - } - asfparse->offset += ASF_GUID_OBJSIZE_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"); - goto leave; - } + gst_buffer_map (buffer, &map, GST_MAP_READ); + if (map.size >= ASF_GUID_OBJSIZE_SIZE) { + guint64 size; - if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, - size - ASF_GUID_OBJSIZE_SIZE, &headers)) != GST_FLOW_OK) { - GST_ERROR_OBJECT (asfparse, "Failed to pull data from headers"); - goto leave; - } - headers = gst_buffer_append (guid_and_size, headers); - guid_and_size = NULL; - asfparse->offset += size - ASF_GUID_OBJSIZE_SIZE; - if (!gst_asf_parse_headers (headers, asfparse->asfinfo)) { - goto leave; + size = gst_asf_match_and_peek_obj_size (map.data, + &(guids[ASF_HEADER_OBJECT_INDEX])); + + if (size == 0) { + GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing"); + ret = GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + goto end; + } + + if (size > map.size) { + /* request all the obj data */ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), size); + gst_buffer_unmap (buffer, &map); + goto end; + } + + if (gst_asf_parse_headers_from_data (map.data, map.size, asfparse->asfinfo)) { + GST_DEBUG_OBJECT (asfparse, "Successfully parsed headers"); + asfparse->parse_state = ASF_PARSING_DATA; + gst_buffer_unmap (buffer, &map); + + GST_INFO_OBJECT (asfparse, "Broadcast mode %s", + asfparse->asfinfo->broadcast ? "on" : "off"); + + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + ASF_GUID_OBJSIZE_SIZE); + + gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (asfparse), + gst_event_new_caps (gst_caps_new_simple ("video/x-ms-asf", "parsed", + G_TYPE_BOOLEAN, TRUE, NULL))); + gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, size); + } else { + ret = GST_FLOW_ERROR; + } + } else { + gst_buffer_unmap (buffer, &map); + *skipsize = 0; } - return gst_asf_parse_push (asfparse, headers); -leave: - if (headers) - gst_buffer_unref (headers); - if (guid_and_size) - gst_buffer_unref (guid_and_size); +end: return ret; } static GstFlowReturn -gst_asf_parse_pull_data_header (GstAsfParse * asfparse) +gst_asf_parse_handle_frame_data_header (GstAsfParse * asfparse, + GstBaseParseFrame * frame, gint * skipsize) { - GstBuffer *buf = NULL; - GstFlowReturn ret; + GstBuffer *buffer = frame->buffer; + GstMapInfo map; + GstFlowReturn ret = GST_FLOW_OK; - if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, - ASF_DATA_OBJECT_SIZE, &buf)) != GST_FLOW_OK) { - GST_ERROR_OBJECT (asfparse, "Failed to pull data header"); - return ret; - } - asfparse->offset += ASF_DATA_OBJECT_SIZE; - 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"); - gst_buffer_unref (buf); - return GST_FLOW_ERROR; + gst_buffer_map (buffer, &map, GST_MAP_READ); + if (map.size >= ASF_GUID_OBJSIZE_SIZE) { + guint64 size; + + size = gst_asf_match_and_peek_obj_size (map.data, + &(guids[ASF_DATA_OBJECT_INDEX])); + + if (size == 0) { + GST_ERROR_OBJECT (asfparse, "ASF data object missing"); + ret = GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + goto end; + } + + if (ASF_DATA_OBJECT_SIZE > map.size) { + /* request all the obj data header size */ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + ASF_DATA_OBJECT_SIZE); + gst_buffer_unmap (buffer, &map); + goto end; + } + + if (gst_asf_parse_parse_data_object (asfparse, map.data, + map.size) == GST_FLOW_OK) { + GST_DEBUG_OBJECT (asfparse, "Successfully parsed data object"); + asfparse->parse_state = ASF_PARSING_PACKETS; + gst_buffer_unmap (buffer, &map); + + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + asfparse->asfinfo->packet_size); + + gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, + ASF_DATA_OBJECT_SIZE); + } + } else { + gst_buffer_unmap (buffer, &map); + *skipsize = 0; } - return gst_asf_parse_parse_data_object (asfparse, buf); +end: + return ret; } static GstFlowReturn -gst_asf_parse_pull_packets (GstAsfParse * asfparse) +gst_asf_parse_handle_frame_packets (GstAsfParse * asfparse, + GstBaseParseFrame * frame, gint * skipsize) { - GstFlowReturn ret; - while (asfparse->asfinfo->broadcast || - asfparse->parsed_packets < asfparse->asfinfo->packets_count) { - GstBuffer *packet; + GstBuffer *buffer = frame->buffer; + GstMapInfo map; + GstFlowReturn ret = GST_FLOW_OK; + + GST_LOG_OBJECT (asfparse, "Packet parsing"); + gst_buffer_map (buffer, &map, GST_MAP_READ); + if (G_LIKELY (map.size >= asfparse->asfinfo->packet_size)) { + gst_buffer_unmap (buffer, &map); GST_DEBUG_OBJECT (asfparse, "Parsing packet %" G_GUINT64_FORMAT, asfparse->parsed_packets); - - /* get the packet */ - packet = NULL; - ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, - asfparse->asfinfo->packet_size, &packet); - if (ret != GST_FLOW_OK) - return ret; asfparse->parsed_packets++; - asfparse->offset += asfparse->asfinfo->packet_size; + gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, + asfparse->asfinfo->packet_size); + + /* test if all packets have been processed */ + if (G_UNLIKELY (!asfparse->asfinfo->broadcast && + asfparse->parsed_packets == asfparse->asfinfo->packets_count)) { + GST_INFO_OBJECT (asfparse, + "All %" G_GUINT64_FORMAT " packets processed", + asfparse->parsed_packets); + asfparse->parse_state = ASF_PARSING_INDEXES; + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + ASF_GUID_OBJSIZE_SIZE); + } - /* parse the packet */ - ret = gst_asf_parse_parse_packet (asfparse, packet); - if (ret != GST_FLOW_OK) - return ret; + } else { + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + asfparse->asfinfo->packet_size); + gst_buffer_unmap (buffer, &map); + *skipsize = 0; } - return GST_FLOW_OK; + + return ret; } static GstFlowReturn -gst_asf_parse_pull_indexes (GstAsfParse * asfparse) +gst_asf_parse_handle_frame_indexes (GstAsfParse * asfparse, + GstBaseParseFrame * frame, gint * skipsize) { - GstBuffer *guid_and_size; - GstBuffer *buf; - guint64 obj_size; - GstFlowReturn ret = GST_FLOW_OK; - while (1) { - guid_and_size = NULL; - ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, - ASF_GUID_OBJSIZE_SIZE, &guid_and_size); - if (ret != GST_FLOW_OK) - break; - /* we can peek at the object size */ - 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); - ret = GST_FLOW_ERROR; - break; - } - asfparse->offset += ASF_GUID_OBJSIZE_SIZE; - - /* pull the rest of the object */ - buf = NULL; - ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, obj_size, - &buf); - if (ret != GST_FLOW_OK) { - gst_buffer_unref (guid_and_size); - break; - } - asfparse->offset += obj_size - ASF_GUID_OBJSIZE_SIZE; - - buf = gst_buffer_append (guid_and_size, buf); - ret = gst_asf_parse_push (asfparse, buf); - if (ret != GST_FLOW_OK) - break; - } - return ret; + /* don't care about indexes, just push them forward */ + return gst_asf_parse_handle_frame_push_object (asfparse, frame, skipsize, + NULL); } -static void -gst_asf_parse_loop (GstPad * pad) + +static GstFlowReturn +gst_asf_parse_handle_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, gint * skipsize) { - GstFlowReturn ret = GST_FLOW_OK; - GstAsfParse *asfparse = GST_ASF_PARSE_CAST (GST_OBJECT_PARENT (pad)); + GstAsfParse *asfparse = GST_ASF_PARSE_CAST (parse); - GST_LOG_OBJECT (asfparse, "Processing data in loop function"); switch (asfparse->parse_state) { case ASF_PARSING_HEADERS: - GST_INFO_OBJECT (asfparse, "Starting to parse headers"); - ret = gst_asf_parse_pull_headers (asfparse); - if (ret != GST_FLOW_OK) - goto pause; - asfparse->parse_state = ASF_PARSING_DATA; - + return gst_asf_parse_handle_frame_headers (asfparse, frame, skipsize); case ASF_PARSING_DATA: - GST_INFO_OBJECT (asfparse, "Parsing data object headers"); - ret = gst_asf_parse_pull_data_header (asfparse); - if (ret != GST_FLOW_OK) - goto pause; - asfparse->parse_state = ASF_PARSING_PACKETS; - + return gst_asf_parse_handle_frame_data_header (asfparse, frame, skipsize); case ASF_PARSING_PACKETS: - GST_INFO_OBJECT (asfparse, "Starting packet parsing"); - GST_INFO_OBJECT (asfparse, "Broadcast mode %s", - asfparse->asfinfo->broadcast ? "on" : "off"); - ret = gst_asf_parse_pull_packets (asfparse); - if (ret != GST_FLOW_OK) - goto pause; - - /* test if all packets have been processed */ - if (!asfparse->asfinfo->broadcast && - asfparse->parsed_packets == asfparse->asfinfo->packets_count) { - GST_INFO_OBJECT (asfparse, - "All %" G_GUINT64_FORMAT " packets processed", - asfparse->parsed_packets); - asfparse->parse_state = ASF_PARSING_INDEXES; - } - + return gst_asf_parse_handle_frame_packets (asfparse, frame, skipsize); case ASF_PARSING_INDEXES: - /* we currently don't care about indexes, so just push them forward */ - GST_INFO_OBJECT (asfparse, "Starting indexes parsing"); - ret = gst_asf_parse_pull_indexes (asfparse); - if (ret != GST_FLOW_OK) - goto pause; + return gst_asf_parse_handle_frame_indexes (asfparse, frame, skipsize); default: break; } -pause: - { - const gchar *reason = gst_flow_get_name (ret); - - GST_INFO_OBJECT (asfparse, "Pausing sinkpad task"); - gst_pad_pause_task (pad); - - 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_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 ()); - } - } + g_assert_not_reached (); + return GST_FLOW_ERROR; } + +#if 0 static GstFlowReturn -gst_asf_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +gst_asf_parse_parse_packet (GstAsfParse * asfparse, GstBuffer * buffer) { - GstAsfParse *asfparse; - GstFlowReturn ret = GST_FLOW_OK; + GstAsfPacketInfo *packetinfo = asfparse->packetinfo; - asfparse = GST_ASF_PARSE (parent); - gst_adapter_push (asfparse->adapter, buffer); + if (!gst_asf_parse_packet (buffer, packetinfo, FALSE, + asfparse->asfinfo->packet_size)) + goto error; - switch (asfparse->parse_state) { - case ASF_PARSING_HEADERS: - if (asfparse->headers_size == 0 && - gst_adapter_available (asfparse->adapter) >= ASF_GUID_OBJSIZE_SIZE) { - - /* we can peek at the object size */ - asfparse->headers_size = - 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 */ - GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing"); - ret = GST_FLOW_ERROR; - goto end; - } - } - if (gst_adapter_available (asfparse->adapter) >= asfparse->headers_size) { - GstBuffer *headers = gst_adapter_take_buffer (asfparse->adapter, - asfparse->headers_size); - if (gst_asf_parse_headers (headers, asfparse->asfinfo)) { - ret = gst_asf_parse_push (asfparse, headers); - asfparse->parse_state = ASF_PARSING_DATA; - } else { - ret = GST_FLOW_ERROR; - GST_ERROR_OBJECT (asfparse, "Failed to parse headers"); - } - } - break; - case ASF_PARSING_DATA: - if (asfparse->data_size == 0 && - gst_adapter_available (asfparse->adapter) >= ASF_GUID_OBJSIZE_SIZE) { - - /* we can peek at the object size */ - asfparse->data_size = - 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 */ - GST_ERROR_OBJECT (asfparse, "Unexpected object after headers, was " - "expecting a data object"); - ret = GST_FLOW_ERROR; - goto end; - } - } - /* if we have received the full data object headers */ - if (gst_adapter_available (asfparse->adapter) >= ASF_DATA_OBJECT_SIZE) { - ret = gst_asf_parse_parse_data_object (asfparse, - gst_adapter_take_buffer (asfparse->adapter, ASF_DATA_OBJECT_SIZE)); - if (ret != GST_FLOW_OK) { - goto end; - } - asfparse->parse_state = ASF_PARSING_PACKETS; - } - break; - case ASF_PARSING_PACKETS: - g_assert (asfparse->asfinfo->packet_size); - while ((asfparse->asfinfo->broadcast || - asfparse->parsed_packets < asfparse->asfinfo->packets_count) && - gst_adapter_available (asfparse->adapter) >= - asfparse->asfinfo->packet_size) { - GstBuffer *packet = gst_adapter_take_buffer (asfparse->adapter, - asfparse->asfinfo->packet_size); - asfparse->parsed_packets++; - ret = gst_asf_parse_parse_packet (asfparse, packet); - if (ret != GST_FLOW_OK) - goto end; - } - if (!asfparse->asfinfo->broadcast && - asfparse->parsed_packets >= asfparse->asfinfo->packets_count) { - GST_INFO_OBJECT (asfparse, "Finished parsing packets"); - asfparse->parse_state = ASF_PARSING_INDEXES; - } - break; - case ASF_PARSING_INDEXES: - /* we currently don't care about any of those objects */ - 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_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, - gst_adapter_take_buffer (asfparse->adapter, obj_size)); - if (ret != GST_FLOW_OK) { - goto end; - } - } - } - break; - default: - break; + GST_DEBUG_OBJECT (asfparse, "Received packet of length %" G_GUINT32_FORMAT + ", padding %" G_GUINT32_FORMAT ", send time %" G_GUINT32_FORMAT + ", duration %" G_GUINT16_FORMAT " and %s keyframe(s)", + packetinfo->packet_size, packetinfo->padding, + packetinfo->send_time, packetinfo->duration, + (packetinfo->has_keyframe) ? "with" : "without"); + + /* set gstbuffer fields */ + if (!packetinfo->has_keyframe) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); } + GST_BUFFER_TIMESTAMP (buffer) = ((GstClockTime) packetinfo->send_time) + * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = ((GstClockTime) packetinfo->duration) + * GST_MSECOND; -end: - return ret; + return gst_asf_parse_push (asfparse, buffer); + +error: + GST_ERROR_OBJECT (asfparse, "Error while parsing data packet"); + return GST_FLOW_ERROR; } +#endif + static void gst_asf_parse_finalize (GObject * object) { GstAsfParse *asfparse = GST_ASF_PARSE (object); - gst_adapter_clear (asfparse->adapter); - g_object_unref (G_OBJECT (asfparse->adapter)); - gst_caps_unref (asfparse->outcaps); gst_asf_file_info_free (asfparse->asfinfo); g_free (asfparse->packetinfo); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -529,16 +380,17 @@ gst_asf_parse_class_init (GstAsfParseClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseParseClass *gstbaseparse_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_peek_parent (klass); + gstbaseparse_class = (GstBaseParseClass *) klass; gobject_class->finalize = gst_asf_parse_finalize; - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_asf_parse_change_state); + gstbaseparse_class->start = gst_asf_parse_start; + gstbaseparse_class->stop = gst_asf_parse_stop; + gstbaseparse_class->handle_frame = gst_asf_parse_handle_frame; gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&src_factory)); @@ -555,62 +407,8 @@ gst_asf_parse_class_init (GstAsfParseClass * klass) static void 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_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"); - gst_pad_use_fixed_caps (asfparse->srcpad); - gst_element_add_pad (GST_ELEMENT (asfparse), asfparse->srcpad); - - asfparse->adapter = gst_adapter_new (); - 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); -} - -static GstStateChangeReturn -gst_asf_parse_change_state (GstElement * element, GstStateChange transition) -{ - GstAsfParse *asfparse; - GstStateChangeReturn ret; - - asfparse = GST_ASF_PARSE (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_asf_parse_reset (asfparse); - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - goto done; - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - -done: - return ret; } gboolean diff --git a/gst/asfmux/gstasfparse.h b/gst/asfmux/gstasfparse.h index 95c7f47..f01dd26 100644 --- a/gst/asfmux/gstasfparse.h +++ b/gst/asfmux/gstasfparse.h @@ -23,6 +23,7 @@ #include +#include #include #include @@ -54,29 +55,19 @@ typedef struct _GstAsfParse GstAsfParse; typedef struct _GstAsfParseClass GstAsfParseClass; struct _GstAsfParse { - GstElement element; + GstBaseParse baseparse; enum GstAsfParsingState parse_state; - GstAdapter *adapter; - - GstPad *srcpad; - GstPad *sinkpad; - GstCaps *outcaps; - guint64 parsed_packets; - guint64 offset; /* used in pull mode */ - /* parsed info */ GstAsfFileInfo *asfinfo; - GstAsfPacketInfo *packetinfo; /* we keep it here to avoid allocs */ - guint64 headers_size; - guint64 data_size; + GstAsfPacketInfo *packetinfo; }; struct _GstAsfParseClass { - GstElementClass parent_class; + GstBaseParseClass parent_class; }; GType gst_asf_parse_get_type(void); -- 2.7.4