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 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_rtp_asf_pay_handle_buffer (GstRTPBasePayload * rtppay, GstBuffer * buffer) { GstRtpAsfPay *rtpasfpay = GST_RTP_ASF_PAY_CAST (rtppay); if (G_UNLIKELY (rtpasfpay->state == ASF_END)) { GST_LOG_OBJECT (rtpasfpay, "Dropping buffer as we already pushed all packets"); gst_buffer_unref (buffer); return GST_FLOW_EOS; /* we already finished our job */ } /* receive headers * we only accept if they are in a single buffer */ if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) { guint64 header_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_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_get_size (buffer) < header_size) { GST_ERROR_OBJECT (rtpasfpay, "Headers should be contained in a single" " buffer"); gst_buffer_unref (buffer); return GST_FLOW_ERROR; } else { rtpasfpay->state = ASF_DATA_OBJECT; /* clear previous headers, if any */ if (rtpasfpay->headers) { gst_buffer_unref (rtpasfpay->headers); } GST_DEBUG_OBJECT (rtpasfpay, "Storing headers"); 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_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); } } } else { GST_ERROR_OBJECT (rtpasfpay, "Missing ASF header start"); gst_buffer_unref (buffer); return GST_FLOW_ERROR; } } if (G_UNLIKELY (rtpasfpay->state == ASF_DATA_OBJECT)) { 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; } 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); return GST_FLOW_ERROR; } } if (G_LIKELY (rtpasfpay->state == ASF_PACKETS)) { /* in broadcast mode we can't trust the packets count information * from the headers * We assume that if this is on broadcast mode it is a live stream * and we are going to keep receiving packets indefinitely */ if (rtpasfpay->asfinfo.broadcast || rtpasfpay->packets_count < rtpasfpay->asfinfo.packets_count) { GST_DEBUG_OBJECT (rtpasfpay, "Received packet %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, rtpasfpay->packets_count, rtpasfpay->asfinfo.packets_count); rtpasfpay->packets_count++; return gst_rtp_asf_pay_handle_packet (rtpasfpay, buffer); } else { GST_INFO_OBJECT (rtpasfpay, "Packets ended"); rtpasfpay->state = ASF_END; gst_buffer_unref (buffer); return GST_FLOW_EOS; } } gst_buffer_unref (buffer); return GST_FLOW_OK; }