1 /* GStreamer ASF/WMV/WMA demuxer
2 * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * file:///home/tpm/samples/video/asf//336370-regis-velo862.wmv
22 * file:///home/tpm/samples/video/asf//336370-eichhoer.wmv
23 * throw errors (not always necessarily) in this code path
24 * (looks like they carry broken payloads/packets though) */
26 #include "asfpacket.h"
28 #include <gst/gstutils.h>
29 #include <gst/gstinfo.h>
32 #define GST_ASF_PAYLOAD_KF_COMPLETE(stream, payload) (stream->is_video && payload->keyframe && payload->buf_filled >= payload->mo_size)
34 /* we are unlikely to deal with lengths > 2GB here any time soon, so just
35 * return a signed int and use that for error reporting */
37 asf_packet_read_varlen_int (guint lentype_flags, guint lentype_bit_offset,
38 const guint8 ** p_data, guint * p_size)
40 static const guint lens[4] = { 0, 1, 2, 4 };
43 len = lens[(lentype_flags >> lentype_bit_offset) & 0x03];
45 /* will make caller bail out with a short read if there's not enough data */
46 if (G_UNLIKELY (*p_size < len)) {
47 GST_WARNING ("need %u bytes, but only %u bytes available", len, *p_size);
56 val = GST_READ_UINT8 (*p_data);
59 val = GST_READ_UINT16_LE (*p_data);
62 val = GST_READ_UINT32_LE (*p_data);
66 g_assert_not_reached ();
76 asf_packet_create_payload_buffer (AsfPacket * packet, const guint8 ** p_data,
77 guint * p_size, guint payload_len)
81 g_assert (payload_len <= *p_size);
83 off = (guint) (*p_data - packet->bdata);
84 g_assert (off < gst_buffer_get_size (packet->buf));
86 *p_data += payload_len;
87 *p_size -= payload_len;
89 return gst_buffer_copy_region (packet->buf, GST_BUFFER_COPY_ALL, off,
94 asf_payload_search_payloads_queue (AsfPayload * payload, GArray * payload_list)
96 AsfPayload *ret = NULL;
98 for (idx = payload_list->len - 1; idx >= 0; idx--) {
99 ret = &g_array_index (payload_list, AsfPayload, idx);
101 if (G_UNLIKELY (ret->mo_size == payload->mo_size &&
102 ret->mo_number == payload->mo_number)) {
110 asf_payload_find_previous_fragment (GstASFDemux * demux, AsfPayload * payload,
113 AsfPayload *ret = NULL;
115 if (GST_ASF_DEMUX_IS_REVERSE_PLAYBACK (demux->segment)) {
117 /* Search in queued payloads list */
118 ret = asf_payload_search_payloads_queue (payload, stream->payloads);
121 ("previous fragments found in payloads queue for reverse playback : object ID %d",
126 /* Search in payloads 'to be queued' list */
127 ret = asf_payload_search_payloads_queue (payload, stream->payloads_rev);
130 ("previous fragments found in temp payload queue for reverse playback : object ID %d",
135 if (G_UNLIKELY (stream->payloads->len == 0)) {
136 GST_DEBUG ("No previous fragments to merge with for stream %u",
142 &g_array_index (stream->payloads, AsfPayload,
143 stream->payloads->len - 1);
145 if (G_UNLIKELY (ret->mo_size != payload->mo_size ||
146 ret->mo_number != payload->mo_number || ret->mo_offset != 0)) {
147 if (payload->mo_size != 0) {
148 GST_WARNING ("Previous fragment does not match continued fragment");
151 /* Warn about this case, but accept it anyway: files in the wild sometimes
152 * have continued packets where the subsequent fragments say that they're
154 GST_WARNING ("Previous fragment found, but current fragment has "
155 "zero size, accepting anyway");
161 if (this_fragment->mo_offset + this_payload_len > first_fragment->mo_size) {
162 GST_WARNING ("Merged fragments would be bigger than the media object");
170 /* TODO: if we have another payload already queued for this stream and that
171 * payload doesn't have a duration, maybe we can calculate a duration for it
172 * (if the previous timestamp is smaller etc. etc.) */
174 gst_asf_payload_queue_for_stream_forward (GstASFDemux * demux,
175 AsfPayload * payload, AsfStream * stream)
177 GST_DEBUG_OBJECT (demux, "Got payload for stream %d ts:%" GST_TIME_FORMAT,
178 stream->id, GST_TIME_ARGS (payload->ts));
180 /* make timestamps start from 0; first_ts will be determined during activation (once we have enough data),
181 which will also update ts of all packets queued before we knew first_ts; */
182 if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (demux->first_ts)
183 && GST_CLOCK_TIME_IS_VALID (payload->ts))) {
184 if (payload->ts > demux->first_ts)
185 payload->ts -= demux->first_ts;
190 /* remove any incomplete payloads that will never be completed */
191 while (stream->payloads->len > 0) {
195 idx_last = stream->payloads->len - 1;
196 prev = &g_array_index (stream->payloads, AsfPayload, idx_last);
198 if (G_UNLIKELY (gst_asf_payload_is_complete (prev)))
201 GST_DEBUG_OBJECT (demux, "Dropping incomplete fragmented media object "
202 "queued for stream %u", stream->id);
204 gst_buffer_replace (&prev->buf, NULL);
205 g_array_remove_index (stream->payloads, idx_last);
207 /* there's data missing, so there's a discontinuity now */
208 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
211 /* If we're about to queue a key frame that is before the segment start, we
212 * can ditch any previously queued payloads (which would also be before the
213 * segment start). This makes sure the decoder doesn't decode more than
214 * absolutely necessary after a seek (we don't push out payloads that are
215 * before the segment start until we have at least one that falls within the
217 if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
218 payload->ts < demux->segment.start && payload->keyframe)) {
219 GST_DEBUG_OBJECT (demux, "Queueing keyframe before segment start, removing"
220 " %u previously-queued payloads, which would be out of segment too and"
221 " hence don't have to be decoded", stream->payloads->len);
222 while (stream->payloads->len > 0) {
226 idx_last = stream->payloads->len - 1;
227 last = &g_array_index (stream->payloads, AsfPayload, idx_last);
228 gst_buffer_replace (&last->buf, NULL);
229 g_array_remove_index (stream->payloads, idx_last);
232 /* Mark discontinuity (should be done via stream->discont anyway though) */
233 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
236 g_array_append_vals (stream->payloads, payload, 1);
240 gst_asf_payload_queue_for_stream_reverse (GstASFDemux * demux,
241 AsfPayload * payload, AsfStream * stream)
243 GST_DEBUG_OBJECT (demux, "Got payload for stream %d ts:%" GST_TIME_FORMAT,
244 stream->id, GST_TIME_ARGS (payload->ts));
246 if (demux->multiple_payloads) {
247 /* store the payload in temporary buffer, until we parse all payloads in this packet */
248 g_array_append_vals (stream->payloads_rev, payload, 1);
250 if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts))) {
251 g_array_append_vals (stream->payloads, payload, 1);
252 if (GST_ASF_PAYLOAD_KF_COMPLETE (stream, payload)) {
253 stream->kf_pos = stream->payloads->len - 1;
256 gst_buffer_unref (payload->buf);
263 gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload,
266 GST_DEBUG_OBJECT (demux, "Got payload for stream %d ts:%" GST_TIME_FORMAT,
267 stream->id, GST_TIME_ARGS (payload->ts));
269 if (GST_ASF_DEMUX_IS_REVERSE_PLAYBACK (demux->segment)) {
270 gst_asf_payload_queue_for_stream_reverse (demux, payload, stream);
272 gst_asf_payload_queue_for_stream_forward (demux, payload, stream);
278 asf_payload_parse_replicated_data_extensions (AsfStream * stream,
279 AsfPayload * payload)
281 AsfPayloadExtension *ext;
285 if (!stream->ext_props.valid || stream->ext_props.payload_extensions == NULL)
289 for (ext = stream->ext_props.payload_extensions; ext->len > 0; ++ext) {
291 if (ext_len == 0xFFFF) { /* extension length is determined by first two bytes in replicated data */
292 ext_len = GST_READ_UINT16_LE (payload->rep_data + off);
295 if (G_UNLIKELY (off + ext_len > payload->rep_data_len)) {
296 GST_WARNING ("not enough replicated data for defined extensions");
300 case ASF_PAYLOAD_EXTENSION_DURATION:
301 if (G_LIKELY (ext_len == 2)) {
302 guint16 tdur = GST_READ_UINT16_LE (payload->rep_data + off);
303 /* packet durations of 1ms are mostly invalid */
305 payload->duration = tdur * GST_MSECOND;
307 GST_WARNING ("unexpected DURATION extensions len %u", ext_len);
310 case ASF_PAYLOAD_EXTENSION_SYSTEM_CONTENT:
311 if (G_LIKELY (ext_len == 1)) {
312 guint8 data = payload->rep_data[off];
314 payload->interlaced = data & 0x1;
315 payload->rff = data & 0x8;
316 payload->tff = (data & 0x2) || !(data & 0x4);
317 GST_DEBUG ("SYSTEM_CONTENT: interlaced:%d, rff:%d, tff:%d",
318 payload->interlaced, payload->rff, payload->tff);
320 GST_WARNING ("unexpected SYSTEM_CONTE extensions len %u", ext_len);
323 case ASF_PAYLOAD_EXTENSION_SYSTEM_PIXEL_ASPECT_RATIO:
324 if (G_LIKELY (ext_len == 2)) {
325 payload->par_x = payload->rep_data[off];
326 payload->par_y = payload->rep_data[off + 1];
327 GST_DEBUG ("PAR %d / %d", payload->par_x, payload->par_y);
329 GST_WARNING ("unexpected SYSTEM_PIXEL_ASPECT_RATIO extensions len %u",
333 case ASF_PAYLOAD_EXTENSION_TIMING:
335 /* dvr-ms timing - this will override packet timestamp */
336 guint64 time = GST_READ_UINT64_LE (payload->rep_data + off + 8);
337 if (time != 0xFFFFFFFFFFFFFFFF)
338 payload->ts = time * 100;
340 payload->ts = GST_CLOCK_TIME_NONE;
344 GST_LOG ("UNKNOWN PAYLOAD EXTENSION!");
352 gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
353 gint lentype, const guint8 ** p_data, guint * p_size)
355 AsfPayload payload = { 0, };
357 gboolean is_compressed;
361 if (G_UNLIKELY (*p_size < 1)) {
362 GST_WARNING_OBJECT (demux, "Short packet!");
366 stream_num = GST_READ_UINT8 (*p_data) & 0x7f;
367 payload.keyframe = ((GST_READ_UINT8 (*p_data) & 0x80) != 0);
372 payload.ts = GST_CLOCK_TIME_NONE;
373 payload.duration = GST_CLOCK_TIME_NONE;
376 payload.interlaced = FALSE;
381 asf_packet_read_varlen_int (packet->prop_flags, 4, p_data, p_size);
383 asf_packet_read_varlen_int (packet->prop_flags, 2, p_data, p_size);
384 payload.rep_data_len =
385 asf_packet_read_varlen_int (packet->prop_flags, 0, p_data, p_size);
387 is_compressed = (payload.rep_data_len == 1);
389 GST_LOG_OBJECT (demux, "payload for stream %u", stream_num);
390 GST_LOG_OBJECT (demux, "keyframe : %s", (payload.keyframe) ? "yes" : "no");
391 GST_LOG_OBJECT (demux, "compressed : %s", (is_compressed) ? "yes" : "no");
393 if (G_UNLIKELY (*p_size < payload.rep_data_len)) {
394 GST_WARNING_OBJECT (demux, "Short packet! rep_data_len=%u, size=%u",
395 payload.rep_data_len, *p_size);
399 memcpy (payload.rep_data, *p_data,
400 MIN (sizeof (payload.rep_data), payload.rep_data_len));
402 *p_data += payload.rep_data_len;
403 *p_size -= payload.rep_data_len;
405 if (G_UNLIKELY (*p_size == 0)) {
406 GST_WARNING_OBJECT (demux, "payload without data!?");
410 /* we use -1 as lentype for a single payload that's the size of the packet */
411 if (G_UNLIKELY ((lentype >= 0 && lentype <= 3))) {
412 payload_len = asf_packet_read_varlen_int (lentype, 0, p_data, p_size);
413 if (*p_size < payload_len) {
414 GST_WARNING_OBJECT (demux, "Short packet! payload_len=%u, size=%u",
415 payload_len, *p_size);
419 payload_len = *p_size;
422 GST_LOG_OBJECT (demux, "payload length: %u", payload_len);
424 stream = gst_asf_demux_get_stream (demux, stream_num);
426 if (G_UNLIKELY (stream == NULL)) {
427 if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
428 GST_WARNING_OBJECT (demux, "Payload for unknown stream %u, skipping",
431 if (*p_size < payload_len) {
435 *p_data += payload_len;
436 *p_size -= payload_len;
441 if (!stream->is_video)
444 if (G_UNLIKELY (!is_compressed)) {
445 GST_LOG_OBJECT (demux, "replicated data length: %u", payload.rep_data_len);
447 if (payload.rep_data_len >= 8) {
448 payload.mo_size = GST_READ_UINT32_LE (payload.rep_data);
449 payload.ts = GST_READ_UINT32_LE (payload.rep_data + 4) * GST_MSECOND;
450 if (G_UNLIKELY (payload.ts < demux->preroll))
453 payload.ts -= demux->preroll;
454 asf_payload_parse_replicated_data_extensions (stream, &payload);
456 GST_LOG_OBJECT (demux, "media object size : %u", payload.mo_size);
457 GST_LOG_OBJECT (demux, "media object ts : %" GST_TIME_FORMAT,
458 GST_TIME_ARGS (payload.ts));
459 GST_LOG_OBJECT (demux, "media object dur : %" GST_TIME_FORMAT,
460 GST_TIME_ARGS (payload.duration));
461 } else if (payload.rep_data_len == 0) {
463 } else if (payload.rep_data_len != 0) {
464 GST_WARNING_OBJECT (demux, "invalid replicated data length, very bad");
465 *p_data += payload_len;
466 *p_size -= payload_len;
470 GST_LOG_OBJECT (demux, "media object offset : %u", payload.mo_offset);
472 GST_LOG_OBJECT (demux, "payload length: %u", payload_len);
474 if (payload_len == 0) {
475 GST_DEBUG_OBJECT (demux, "skipping empty payload");
476 } else if (payload.mo_offset == 0 && payload.mo_size == payload_len) {
477 /* if the media object is not fragmented, just create a sub-buffer */
478 GST_LOG_OBJECT (demux, "unfragmented media object size %u", payload_len);
479 payload.buf = asf_packet_create_payload_buffer (packet, p_data, p_size,
481 payload.buf_filled = payload_len;
482 gst_asf_payload_queue_for_stream (demux, &payload, stream);
483 } else if (GST_ASF_DEMUX_IS_REVERSE_PLAYBACK (demux->segment)) {
484 /* Handle fragmented payloads for reverse playback */
486 const guint8 *payload_data = *p_data;
487 prev = asf_payload_find_previous_fragment (demux, &payload, stream);
492 gst_buffer_fill (prev->buf, payload.mo_offset,
493 payload_data, payload_len);
494 prev->buf_filled += payload_len;
495 if (payload.keyframe && payload.mo_offset == 0) {
496 stream->reverse_kf_ready = TRUE;
498 for (idx = stream->payloads->len - 1; idx >= 0; idx--) {
499 p = &g_array_index (stream->payloads, AsfPayload, idx);
500 if (p->mo_number == payload.mo_number) {
501 /* Mark position of KF for reverse play */
502 stream->kf_pos = idx;
507 payload.buf = gst_buffer_new_allocate (NULL, payload.mo_size, NULL); /* can we use (mo_size - offset) for size? */
508 gst_buffer_fill (payload.buf, payload.mo_offset,
509 payload_data, payload_len);
510 payload.buf_filled = payload.mo_size - (payload.mo_offset);
511 gst_asf_payload_queue_for_stream (demux, &payload, stream);
513 *p_data += payload_len;
514 *p_size -= payload_len;
516 const guint8 *payload_data = *p_data;
518 g_assert (payload_len <= *p_size);
520 *p_data += payload_len;
521 *p_size -= payload_len;
523 /* n-th fragment of a fragmented media object? */
524 if (payload.mo_offset != 0) {
528 asf_payload_find_previous_fragment (demux, &payload, stream))) {
529 if (prev->buf == NULL || (payload.mo_size > 0
530 && payload.mo_size != prev->mo_size)
531 || payload.mo_offset >= gst_buffer_get_size (prev->buf)
532 || payload.mo_offset + payload_len >
533 gst_buffer_get_size (prev->buf)) {
534 GST_WARNING_OBJECT (demux, "Offset doesn't match previous data?!");
536 /* we assume fragments are payloaded with increasing mo_offset */
537 if (payload.mo_offset != prev->buf_filled) {
538 GST_WARNING_OBJECT (demux, "media object payload discontinuity: "
539 "offset=%u vs buf_filled=%u", payload.mo_offset,
542 gst_buffer_fill (prev->buf, payload.mo_offset,
543 payload_data, payload_len);
545 MAX (prev->buf_filled, payload.mo_offset + payload_len);
546 GST_LOG_OBJECT (demux, "Merged media object fragments, size now %u",
550 GST_DEBUG_OBJECT (demux, "n-th payload fragment, but don't have "
551 "any previous fragment, ignoring payload");
554 GST_LOG_OBJECT (demux, "allocating buffer of size %u for fragmented "
555 "media object", payload.mo_size);
556 payload.buf = gst_buffer_new_allocate (NULL, payload.mo_size, NULL);
557 gst_buffer_fill (payload.buf, 0, payload_data, payload_len);
558 payload.buf_filled = payload_len;
560 gst_asf_payload_queue_for_stream (demux, &payload, stream);
564 const guint8 *payload_data;
565 GstClockTime ts, ts_delta;
568 GST_LOG_OBJECT (demux, "Compressed payload, length=%u", payload_len);
570 payload_data = *p_data;
572 *p_data += payload_len;
573 *p_size -= payload_len;
575 ts = payload.mo_offset * GST_MSECOND;
576 if (G_UNLIKELY (ts < demux->preroll))
579 ts -= demux->preroll;
580 ts_delta = payload.rep_data[0] * GST_MSECOND;
582 for (num = 0; payload_len > 0; ++num) {
583 guint sub_payload_len;
585 sub_payload_len = GST_READ_UINT8 (payload_data);
587 GST_LOG_OBJECT (demux, "subpayload #%u: len=%u, ts=%" GST_TIME_FORMAT,
588 num, sub_payload_len, GST_TIME_ARGS (ts));
593 if (G_UNLIKELY (payload_len < sub_payload_len)) {
594 GST_WARNING_OBJECT (demux, "Short payload! %u bytes left", payload_len);
598 if (G_LIKELY (sub_payload_len > 0)) {
599 payload.buf = asf_packet_create_payload_buffer (packet,
600 &payload_data, &payload_len, sub_payload_len);
601 payload.buf_filled = sub_payload_len;
604 if (G_LIKELY (ts_delta))
605 payload.duration = ts_delta;
607 payload.duration = GST_CLOCK_TIME_NONE;
609 gst_asf_payload_queue_for_stream (demux, &payload, stream);
619 GstAsfDemuxParsePacketError
620 gst_asf_demux_parse_packet (GstASFDemux * demux, GstBuffer * buf)
622 AsfPacket packet = { 0, };
625 gboolean has_multiple_payloads;
626 GstAsfDemuxParsePacketError ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE;
627 guint8 ec_flags, flags1;
630 gst_buffer_map (buf, &map, GST_MAP_READ);
633 GST_LOG_OBJECT (demux, "Buffer size: %u", size);
635 /* need at least two payload flag bytes, send time, and duration */
636 if (G_UNLIKELY (size < 2 + 4 + 2)) {
637 GST_WARNING_OBJECT (demux, "Packet size is < 8");
638 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_RECOVERABLE;
643 /* evidently transient */
646 ec_flags = GST_READ_UINT8 (data);
648 /* skip optional error correction stuff */
649 if ((ec_flags & 0x80) != 0) {
650 guint ec_len_type, ec_len;
652 ec_len_type = (ec_flags & 0x60) >> 5;
653 if (ec_len_type == 0) {
654 ec_len = ec_flags & 0x0f;
656 GST_WARNING_OBJECT (demux, "unexpected error correction length type %u",
660 GST_LOG_OBJECT (demux, "packet has error correction (%u bytes)", ec_len);
662 /* still need at least two payload flag bytes, send time, and duration */
663 if (size <= (1 + ec_len) + 2 + 4 + 2) {
664 GST_WARNING_OBJECT (demux, "Packet size is < 8 with Error Correction");
665 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_FATAL;
673 /* parse payload info */
674 flags1 = GST_READ_UINT8 (data);
675 packet.prop_flags = GST_READ_UINT8 (data + 1);
680 has_multiple_payloads = (flags1 & 0x01) != 0;
682 packet.length = asf_packet_read_varlen_int (flags1, 5, &data, &size);
684 packet.sequence = asf_packet_read_varlen_int (flags1, 1, &data, &size);
686 packet.padding = asf_packet_read_varlen_int (flags1, 3, &data, &size);
688 if (G_UNLIKELY (size < 6)) {
689 GST_WARNING_OBJECT (demux, "Packet size is < 6");
690 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_FATAL;
694 packet.send_time = GST_READ_UINT32_LE (data) * GST_MSECOND;
695 packet.duration = GST_READ_UINT16_LE (data + 4) * GST_MSECOND;
700 GST_LOG_OBJECT (demux, "flags : 0x%x", flags1);
701 GST_LOG_OBJECT (demux, "multiple payloads: %u", has_multiple_payloads);
702 GST_LOG_OBJECT (demux, "packet length : %u", packet.length);
703 GST_LOG_OBJECT (demux, "sequence : %u", packet.sequence);
704 GST_LOG_OBJECT (demux, "padding : %u", packet.padding);
705 GST_LOG_OBJECT (demux, "send time : %" GST_TIME_FORMAT,
706 GST_TIME_ARGS (packet.send_time));
708 GST_LOG_OBJECT (demux, "duration : %" GST_TIME_FORMAT,
709 GST_TIME_ARGS (packet.duration));
711 if (GST_ASF_DEMUX_IS_REVERSE_PLAYBACK (demux->segment)
712 && demux->seek_to_cur_pos == TRUE) {
713 /* For reverse playback, initially parse packets forward until we reach packet with 'seek' timestamp */
714 if (packet.send_time - demux->preroll > demux->segment.stop) {
715 demux->seek_to_cur_pos = FALSE;
717 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE;
721 if (G_UNLIKELY (packet.padding == (guint) - 1 || size < packet.padding)) {
722 GST_WARNING_OBJECT (demux, "No padding, or padding bigger than buffer");
723 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_RECOVERABLE;
727 size -= packet.padding;
729 /* adjust available size for parsing if there's less actual packet data for
730 * parsing than there is data in bytes (for sample see bug 431318) */
731 if (G_UNLIKELY (packet.length != 0 && packet.padding == 0
732 && packet.length < demux->packet_size)) {
733 GST_LOG_OBJECT (demux, "shortened packet with implicit padding, "
734 "adjusting available data size");
735 if (size < demux->packet_size - packet.length) {
736 /* the buffer is smaller than the implicit padding */
737 GST_WARNING_OBJECT (demux, "Buffer is smaller than the implicit padding");
738 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_RECOVERABLE;
741 /* subtract the implicit padding */
742 size -= (demux->packet_size - packet.length);
746 if (has_multiple_payloads) {
747 guint i, num, lentype;
748 demux->multiple_payloads = TRUE;
750 if (G_UNLIKELY (size < 1)) {
751 GST_WARNING_OBJECT (demux, "No room more in buffer");
752 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_RECOVERABLE;
756 num = (GST_READ_UINT8 (data) & 0x3F) >> 0;
757 lentype = (GST_READ_UINT8 (data) & 0xC0) >> 6;
762 GST_LOG_OBJECT (demux, "num payloads : %u", num);
764 for (i = 0; i < num; ++i) {
765 GST_LOG_OBJECT (demux, "Parsing payload %u/%u, size left: %u", i + 1, num,
768 if (G_UNLIKELY (!gst_asf_demux_parse_payload (demux, &packet, lentype,
770 GST_WARNING_OBJECT (demux, "Failed to parse payload %u/%u", i + 1, num);
771 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_FATAL;
776 if (GST_ASF_DEMUX_IS_REVERSE_PLAYBACK (demux->segment)) {
777 /* In reverse playback, we parsed the packet (with multiple payloads) and stored the payloads in temporary queue.
778 Now, add them to the stream's payload queue */
779 for (i = 0; i < demux->num_streams; i++) {
780 AsfStream *s = &demux->stream[i];
781 while (s->payloads_rev->len > 0) {
783 p = &g_array_index (s->payloads_rev, AsfPayload,
784 s->payloads_rev->len - 1);
785 g_array_append_vals (s->payloads, p, 1);
786 if (GST_ASF_PAYLOAD_KF_COMPLETE (s, p)) {
787 /* Mark position of KF for reverse play */
788 s->kf_pos = s->payloads->len - 1;
790 g_array_remove_index (s->payloads_rev, (s->payloads_rev->len - 1));
796 GST_LOG_OBJECT (demux, "Parsing single payload");
797 demux->multiple_payloads = FALSE;
798 if (G_UNLIKELY (!gst_asf_demux_parse_payload (demux, &packet, -1, &data,
800 GST_WARNING_OBJECT (demux, "Failed to parse payload");
801 ret = GST_ASF_DEMUX_PARSE_PACKET_ERROR_RECOVERABLE;
806 gst_buffer_unmap (buf, &map);