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
This commit is contained in:
parent
e2b3edbc97
commit
0a90963fcf
@ -1208,13 +1208,40 @@ static void
|
|||||||
gst_asf_mux_write_data_object (GstAsfMux * asfmux, guint8 ** buf)
|
gst_asf_mux_write_data_object (GstAsfMux * asfmux, guint8 ** buf)
|
||||||
{
|
{
|
||||||
gst_asf_put_guid (*buf, guids[ASF_DATA_OBJECT_INDEX]);
|
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_asf_put_guid (*buf + 24, asfmux->file_id);
|
||||||
GST_WRITE_UINT64_LE (*buf + 40, 0); /* total data packets */
|
GST_WRITE_UINT64_LE (*buf + 40, 0); /* total data packets */
|
||||||
GST_WRITE_UINT16_LE (*buf + 48, 0x0101); /* reserved */
|
GST_WRITE_UINT16_LE (*buf + 48, 0x0101); /* reserved */
|
||||||
*buf += ASF_DATA_OBJECT_SIZE;
|
*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:
|
* gst_asf_mux_start_file:
|
||||||
* @asfmux: #GstAsfMux
|
* @asfmux: #GstAsfMux
|
||||||
@ -1387,6 +1414,7 @@ gst_asf_mux_flush_payloads (GstAsfMux * asfmux)
|
|||||||
gboolean has_keyframe;
|
gboolean has_keyframe;
|
||||||
AsfPayload *payload;
|
AsfPayload *payload;
|
||||||
guint32 payload_size;
|
guint32 payload_size;
|
||||||
|
guint offset;
|
||||||
|
|
||||||
if (asfmux->payloads == NULL)
|
if (asfmux->payloads == NULL)
|
||||||
return GST_FLOW_OK; /* nothing to send is ok */
|
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);
|
memset (GST_BUFFER_DATA (buf), 0, asfmux->packet_size);
|
||||||
|
|
||||||
/* 1 for the multiple payload flags */
|
/* 1 for the multiple payload flags */
|
||||||
data = GST_BUFFER_DATA (buf) + ASF_PAYLOAD_PARSING_INFO_SIZE + 1;
|
data = GST_BUFFER_DATA (buf) + asfmux->payload_parsing_info_size + 1;
|
||||||
size_left = asfmux->packet_size - ASF_PAYLOAD_PARSING_INFO_SIZE - 1;
|
size_left = asfmux->packet_size - asfmux->payload_parsing_info_size - 1;
|
||||||
|
|
||||||
has_keyframe = FALSE;
|
has_keyframe = FALSE;
|
||||||
walk = asfmux->payloads;
|
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_DWORD << 3) | /* padding length type */
|
||||||
(ASF_FIELD_TYPE_NONE << 1) | /* sequence type type */
|
(ASF_FIELD_TYPE_NONE << 1) | /* sequence type type */
|
||||||
0x1); /* multiple payloads */
|
0x1); /* multiple payloads */
|
||||||
|
offset = 1;
|
||||||
|
|
||||||
/* property flags - according to the spec, this should not change */
|
/* 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_BYTE << 4) | /* media obj number length type */
|
||||||
(ASF_FIELD_TYPE_DWORD << 2) | /* offset info media object length type */
|
(ASF_FIELD_TYPE_DWORD << 2) | /* offset info media object length type */
|
||||||
(ASF_FIELD_TYPE_BYTE)); /* replicated data length type */
|
(ASF_FIELD_TYPE_BYTE)); /* replicated data length type */
|
||||||
|
offset++;
|
||||||
|
|
||||||
GST_WRITE_UINT32_LE (data + 2, asfmux->packet_size);
|
/* Due to a limitation in WMP while streaming through WMSP we reduce the
|
||||||
GST_WRITE_UINT32_LE (data + 6, size_left); /* padding size */
|
* 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 */
|
/* packet send time */
|
||||||
if (GST_CLOCK_TIME_IS_VALID (send_ts)) {
|
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;
|
GST_BUFFER_TIMESTAMP (buf) = send_ts;
|
||||||
}
|
}
|
||||||
|
offset += 4;
|
||||||
|
|
||||||
/* packet duration */
|
/* 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 */
|
/* 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) {
|
if (payloads_count == 0) {
|
||||||
GST_WARNING_OBJECT (asfmux, "Sending packet without any payload");
|
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,
|
GST_LOG_OBJECT (asfmux, "Payload data size: %" G_GUINT32_FORMAT,
|
||||||
asfmux->payload_data_size);
|
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) {
|
asfmux->packet_size) {
|
||||||
GstFlowReturn ret = gst_asf_mux_flush_payloads (asfmux);
|
GstFlowReturn ret = gst_asf_mux_flush_payloads (asfmux);
|
||||||
if (ret != GST_FLOW_OK)
|
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:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
/* TODO - check if it is possible to mux 2 files without going
|
/* TODO - check if it is possible to mux 2 files without going
|
||||||
* through here */
|
* through here */
|
||||||
|
asfmux->payload_parsing_info_size =
|
||||||
|
gst_asf_mux_find_payload_parsing_info_size (asfmux);
|
||||||
asfmux->packet_size = asfmux->prop_packet_size;
|
asfmux->packet_size = asfmux->prop_packet_size;
|
||||||
asfmux->preroll = asfmux->prop_preroll;
|
asfmux->preroll = asfmux->prop_preroll;
|
||||||
asfmux->merge_stream_tags = asfmux->prop_merge_stream_tags;
|
asfmux->merge_stream_tags = asfmux->prop_merge_stream_tags;
|
||||||
|
@ -120,6 +120,7 @@ struct _GstAsfMux
|
|||||||
|
|
||||||
/* payloads still to be sent in a packet */
|
/* payloads still to be sent in a packet */
|
||||||
guint32 payload_data_size;
|
guint32 payload_data_size;
|
||||||
|
guint32 payload_parsing_info_size;
|
||||||
GSList *payloads;
|
GSList *payloads;
|
||||||
|
|
||||||
Guid file_id;
|
Guid file_id;
|
||||||
|
@ -147,7 +147,6 @@ gboolean gst_asf_tag_present_in_content_description (const gchar * tag);
|
|||||||
#define ASF_AUDIO_SPECIFIC_DATA_SIZE 18
|
#define ASF_AUDIO_SPECIFIC_DATA_SIZE 18
|
||||||
#define ASF_VIDEO_SPECIFIC_DATA_SIZE 51
|
#define ASF_VIDEO_SPECIFIC_DATA_SIZE 51
|
||||||
#define ASF_DATA_OBJECT_SIZE 50
|
#define ASF_DATA_OBJECT_SIZE 50
|
||||||
#define ASF_PAYLOAD_PARSING_INFO_SIZE 16
|
|
||||||
#define ASF_SINGLE_PAYLOAD_HEADER_SIZE 15
|
#define ASF_SINGLE_PAYLOAD_HEADER_SIZE 15
|
||||||
#define ASF_MULTIPLE_PAYLOAD_HEADER_SIZE 17
|
#define ASF_MULTIPLE_PAYLOAD_HEADER_SIZE 17
|
||||||
#define ASF_EXTENDED_STREAM_PROPERTIES_OBJECT_SIZE 88
|
#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_BYTE 1
|
||||||
#define ASF_FIELD_TYPE_WORD 2
|
#define ASF_FIELD_TYPE_WORD 2
|
||||||
#define ASF_FIELD_TYPE_DWORD 3
|
#define ASF_FIELD_TYPE_DWORD 3
|
||||||
|
#define ASF_FIELD_TYPE_MASK 3
|
||||||
|
|
||||||
/* tag types */
|
/* tag types */
|
||||||
#define ASF_TAG_TYPE_UNICODE_STR 0
|
#define ASF_TAG_TYPE_UNICODE_STR 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user