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
This commit is contained in:
Thiago Santos 2013-12-10 10:34:02 -03:00
parent 6cf1f629a3
commit 04134671c9
4 changed files with 272 additions and 473 deletions

View file

@ -761,26 +761,36 @@ 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;
}

View file

@ -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

View file

@ -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;
/* ASF Obj header length */
gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse),
ASF_GUID_OBJSIZE_SIZE);
gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (asfparse), FALSE);
return TRUE;
}
static gboolean
gst_asf_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
gst_asf_parse_stop (GstBaseParse * parse)
{
GstQuery *query;
gboolean pull_mode;
GstAsfParse *asfparse = GST_ASF_PARSE_CAST (parse);
gst_asf_file_info_reset (asfparse->asfinfo);
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_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);
}
}
static gboolean
gst_asf_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active)
{
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;
return TRUE;
}
static GstFlowReturn
gst_asf_parse_push (GstAsfParse * asfparse, GstBuffer * buf)
{
return gst_pad_push (asfparse->srcpad, buf);
}
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,18 +97,241 @@ 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_handle_frame_push_object (GstAsfParse * asfparse,
GstBaseParseFrame * frame, gint * skipsize, const Guid * guid)
{
GstBuffer *buffer = frame->buffer;
GstMapInfo map;
GstFlowReturn ret = GST_FLOW_OK;
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, guid);
if (size == 0) {
GST_ERROR_OBJECT (asfparse, "GUID 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;
}
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_handle_frame_headers (GstAsfParse * asfparse,
GstBaseParseFrame * frame, gint * skipsize)
{
GstBuffer *buffer = frame->buffer;
GstMapInfo map;
GstFlowReturn ret = GST_FLOW_OK;
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_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;
}
end:
return ret;
}
static GstFlowReturn
gst_asf_parse_handle_frame_data_header (GstAsfParse * asfparse,
GstBaseParseFrame * frame, gint * skipsize)
{
GstBuffer *buffer = frame->buffer;
GstMapInfo map;
GstFlowReturn ret = GST_FLOW_OK;
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;
}
end:
return ret;
}
static GstFlowReturn
gst_asf_parse_handle_frame_packets (GstAsfParse * asfparse,
GstBaseParseFrame * frame, gint * skipsize)
{
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);
asfparse->parsed_packets++;
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);
}
} 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 ret;
}
static GstFlowReturn
gst_asf_parse_handle_frame_indexes (GstAsfParse * asfparse,
GstBaseParseFrame * frame, gint * skipsize)
{
/* don't care about indexes, just push them forward */
return gst_asf_parse_handle_frame_push_object (asfparse, frame, skipsize,
NULL);
}
static GstFlowReturn
gst_asf_parse_handle_frame (GstBaseParse * parse,
GstBaseParseFrame * frame, gint * skipsize)
{
GstAsfParse *asfparse = GST_ASF_PARSE_CAST (parse);
switch (asfparse->parse_state) {
case ASF_PARSING_HEADERS:
return gst_asf_parse_handle_frame_headers (asfparse, frame, skipsize);
case ASF_PARSING_DATA:
return gst_asf_parse_handle_frame_data_header (asfparse, frame, skipsize);
case ASF_PARSING_PACKETS:
return gst_asf_parse_handle_frame_packets (asfparse, frame, skipsize);
case ASF_PARSING_INDEXES:
return gst_asf_parse_handle_frame_indexes (asfparse, frame, skipsize);
default:
break;
}
g_assert_not_reached ();
return GST_FLOW_ERROR;
}
#if 0
static GstFlowReturn
gst_asf_parse_parse_packet (GstAsfParse * asfparse, GstBuffer * buffer)
{
@ -194,331 +364,12 @@ error:
return GST_FLOW_ERROR;
}
static GstFlowReturn
gst_asf_parse_pull_headers (GstAsfParse * asfparse)
{
GstBuffer *guid_and_size = NULL;
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) {
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;
}
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;
}
return gst_asf_parse_push (asfparse, headers);
leave:
if (headers)
gst_buffer_unref (headers);
if (guid_and_size)
gst_buffer_unref (guid_and_size);
return ret;
}
static GstFlowReturn
gst_asf_parse_pull_data_header (GstAsfParse * asfparse)
{
GstBuffer *buf = NULL;
GstFlowReturn ret;
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;
}
return gst_asf_parse_parse_data_object (asfparse, buf);
}
static GstFlowReturn
gst_asf_parse_pull_packets (GstAsfParse * asfparse)
{
GstFlowReturn ret;
while (asfparse->asfinfo->broadcast ||
asfparse->parsed_packets < asfparse->asfinfo->packets_count) {
GstBuffer *packet;
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;
/* parse the packet */
ret = gst_asf_parse_parse_packet (asfparse, packet);
if (ret != GST_FLOW_OK)
return ret;
}
return GST_FLOW_OK;
}
static GstFlowReturn
gst_asf_parse_pull_indexes (GstAsfParse * asfparse)
{
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;
}
static void
gst_asf_parse_loop (GstPad * pad)
{
GstFlowReturn ret = GST_FLOW_OK;
GstAsfParse *asfparse = GST_ASF_PARSE_CAST (GST_OBJECT_PARENT (pad));
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;
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;
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;
}
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;
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 ());
}
}
}
static GstFlowReturn
gst_asf_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
GstAsfParse *asfparse;
GstFlowReturn ret = GST_FLOW_OK;
asfparse = GST_ASF_PARSE (parent);
gst_adapter_push (asfparse->adapter, buffer);
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;
}
end:
return ret;
}
#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

View file

@ -23,6 +23,7 @@
#include <gst/gst.h>
#include <gst/base/gstbaseparse.h>
#include <gst/base/gstadapter.h>
#include <gst/base/gstbytereader.h>
@ -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);