diff options
author | HÃ¥kon Skjelten <skjelten@pvv.org> | 2010-01-21 10:51:16 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.co.uk> | 2010-01-25 19:32:15 -0300 |
commit | 0a90963fcf91bd77be019cc813da16f4500f295c (patch) | |
tree | 369a3a97e30aa65a836946dd5c200f0df08003d2 | |
parent | e2b3edbc975175b185c7ee8da6d8c35e3ede1fb3 (diff) |
asfmux: Compatibility with WMSP in WMP
Makes the asfmux content compatible with WMSP and does
some hacks to make it playable in WMP, it doesn't accept
data objects with 0 size indicating that we don't know
its size, though the spec says it should be possible.
Fixes #607555
-rw-r--r-- | gst/asfmux/gstasfmux.c | 73 | ||||
-rw-r--r-- | gst/asfmux/gstasfmux.h | 1 | ||||
-rw-r--r-- | gst/asfmux/gstasfobjects.h | 2 |
3 files changed, 65 insertions, 11 deletions
diff --git a/gst/asfmux/gstasfmux.c b/gst/asfmux/gstasfmux.c index 521e05432..31325670d 100644 --- a/gst/asfmux/gstasfmux.c +++ b/gst/asfmux/gstasfmux.c @@ -1208,13 +1208,40 @@ static void gst_asf_mux_write_data_object (GstAsfMux * asfmux, guint8 ** buf) { gst_asf_put_guid (*buf, guids[ASF_DATA_OBJECT_INDEX]); - GST_WRITE_UINT64_LE (*buf + 16, 0); /* object size - needs updating */ + + /* Data object size. This is always >= ASF_DATA_OBJECT_SIZE. The standard + * specifically accepts the value 0 in live streams, but WMP is not accepting + * this while streaming using WMSP, so we default to minimum size also for + * live streams. Otherwise this field must be updated later on when we know + * the complete stream size. + */ + GST_WRITE_UINT64_LE (*buf + 16, ASF_DATA_OBJECT_SIZE); + gst_asf_put_guid (*buf + 24, asfmux->file_id); GST_WRITE_UINT64_LE (*buf + 40, 0); /* total data packets */ GST_WRITE_UINT16_LE (*buf + 48, 0x0101); /* reserved */ *buf += ASF_DATA_OBJECT_SIZE; } +guint +gst_asf_mux_find_payload_parsing_info_size (GstAsfMux * asfmux) +{ + /* Minimum payload parsing information size is 8 bytes */ + guint size = 8; + + if (asfmux->prop_packet_size > 65535) + size += 4; + else + size += 2; + + if (asfmux->prop_padding > 65535) + size += 4; + else + size += 2; + + return size; +} + /** * gst_asf_mux_start_file: * @asfmux: #GstAsfMux @@ -1387,6 +1414,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux) gboolean has_keyframe; AsfPayload *payload; guint32 payload_size; + guint offset; if (asfmux->payloads == NULL) return GST_FLOW_OK; /* nothing to send is ok */ @@ -1397,8 +1425,8 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux) memset (GST_BUFFER_DATA (buf), 0, asfmux->packet_size); /* 1 for the multiple payload flags */ - data = GST_BUFFER_DATA (buf) + ASF_PAYLOAD_PARSING_INFO_SIZE + 1; - size_left = asfmux->packet_size - ASF_PAYLOAD_PARSING_INFO_SIZE - 1; + data = GST_BUFFER_DATA (buf) + asfmux->payload_parsing_info_size + 1; + size_left = asfmux->packet_size - asfmux->payload_parsing_info_size - 1; has_keyframe = FALSE; walk = asfmux->payloads; @@ -1523,27 +1551,50 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux) (ASF_FIELD_TYPE_DWORD << 3) | /* padding length type */ (ASF_FIELD_TYPE_NONE << 1) | /* sequence type type */ 0x1); /* multiple payloads */ + offset = 1; /* property flags - according to the spec, this should not change */ - GST_WRITE_UINT8 (data + 1, (ASF_FIELD_TYPE_BYTE << 6) | /* stream number length type */ + GST_WRITE_UINT8 (data + offset, (ASF_FIELD_TYPE_BYTE << 6) | /* stream number length type */ (ASF_FIELD_TYPE_BYTE << 4) | /* media obj number length type */ (ASF_FIELD_TYPE_DWORD << 2) | /* offset info media object length type */ (ASF_FIELD_TYPE_BYTE)); /* replicated data length type */ + offset++; - GST_WRITE_UINT32_LE (data + 2, asfmux->packet_size); - GST_WRITE_UINT32_LE (data + 6, size_left); /* padding size */ + /* Due to a limitation in WMP while streaming through WMSP we reduce the + * packet & padding size to 16bit if theay are <= 65535 bytes + */ + if (asfmux->packet_size > 65535) { + GST_WRITE_UINT32_LE (data + offset, asfmux->packet_size - size_left); + offset += 4; + } else { + *data &= ~(ASF_FIELD_TYPE_MASK << 5); + *data |= ASF_FIELD_TYPE_WORD << 5; + GST_WRITE_UINT16_LE (data + offset, asfmux->packet_size - size_left); + offset += 2; + } + if (asfmux->prop_padding > 65535) { + GST_WRITE_UINT32_LE (data + offset, size_left); + offset += 4; + } else { + *data &= ~(ASF_FIELD_TYPE_MASK << 3); + *data |= ASF_FIELD_TYPE_WORD << 3; + GST_WRITE_UINT16_LE (data + offset, size_left); + offset += 2; + } /* packet send time */ if (GST_CLOCK_TIME_IS_VALID (send_ts)) { - GST_WRITE_UINT32_LE (data + 10, (send_ts / GST_MSECOND)); + GST_WRITE_UINT32_LE (data + offset, (send_ts / GST_MSECOND)); GST_BUFFER_TIMESTAMP (buf) = send_ts; } + offset += 4; /* packet duration */ - GST_WRITE_UINT16_LE (data + 14, 0); /* FIXME send duration needs to be estimated */ + GST_WRITE_UINT16_LE (data + offset, 0); /* FIXME send duration needs to be estimated */ + offset += 2; /* multiple payloads flags */ - GST_WRITE_UINT8 (data + 16, 0x2 << 6 | payloads_count); + GST_WRITE_UINT8 (data + offset, 0x2 << 6 | payloads_count); if (payloads_count == 0) { GST_WARNING_OBJECT (asfmux, "Sending packet without any payload"); @@ -1799,7 +1850,7 @@ gst_asf_mux_process_buffer (GstAsfMux * asfmux, GstAsfPad * pad, GST_LOG_OBJECT (asfmux, "Payload data size: %" G_GUINT32_FORMAT, asfmux->payload_data_size); - while (asfmux->payload_data_size + ASF_PAYLOAD_PARSING_INFO_SIZE >= + while (asfmux->payload_data_size + asfmux->payload_parsing_info_size >= asfmux->packet_size) { GstFlowReturn ret = gst_asf_mux_flush_payloads (asfmux); if (ret != GST_FLOW_OK) @@ -2276,6 +2327,8 @@ gst_asf_mux_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: /* TODO - check if it is possible to mux 2 files without going * through here */ + asfmux->payload_parsing_info_size = + gst_asf_mux_find_payload_parsing_info_size (asfmux); asfmux->packet_size = asfmux->prop_packet_size; asfmux->preroll = asfmux->prop_preroll; asfmux->merge_stream_tags = asfmux->prop_merge_stream_tags; diff --git a/gst/asfmux/gstasfmux.h b/gst/asfmux/gstasfmux.h index 015c8b9ab..dd157c566 100644 --- a/gst/asfmux/gstasfmux.h +++ b/gst/asfmux/gstasfmux.h @@ -120,6 +120,7 @@ struct _GstAsfMux /* payloads still to be sent in a packet */ guint32 payload_data_size; + guint32 payload_parsing_info_size; GSList *payloads; Guid file_id; diff --git a/gst/asfmux/gstasfobjects.h b/gst/asfmux/gstasfobjects.h index a608dcee0..affde86b6 100644 --- a/gst/asfmux/gstasfobjects.h +++ b/gst/asfmux/gstasfobjects.h @@ -147,7 +147,6 @@ gboolean gst_asf_tag_present_in_content_description (const gchar * tag); #define ASF_AUDIO_SPECIFIC_DATA_SIZE 18 #define ASF_VIDEO_SPECIFIC_DATA_SIZE 51 #define ASF_DATA_OBJECT_SIZE 50 -#define ASF_PAYLOAD_PARSING_INFO_SIZE 16 #define ASF_SINGLE_PAYLOAD_HEADER_SIZE 15 #define ASF_MULTIPLE_PAYLOAD_HEADER_SIZE 17 #define ASF_EXTENDED_STREAM_PROPERTIES_OBJECT_SIZE 88 @@ -163,6 +162,7 @@ gboolean gst_asf_tag_present_in_content_description (const gchar * tag); #define ASF_FIELD_TYPE_BYTE 1 #define ASF_FIELD_TYPE_WORD 2 #define ASF_FIELD_TYPE_DWORD 3 +#define ASF_FIELD_TYPE_MASK 3 /* tag types */ #define ASF_TAG_TYPE_UNICODE_STR 0 |