1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
20 #include "mediaelement.h"
26 ASFParser::ASFParser (IMediaSource
*source
, Media
*media
)
27 : EventObject (Type::ASFPARSER
)
29 LOG_ASF ("ASFParser::ASFParser ('%p'), this: %p.\n", source
, this);
33 g_return_if_fail (media
!= NULL
);
34 g_return_if_fail (source
!= NULL
);
36 this->source
= source
;
44 ASFParser::GetPacketCount ()
46 return file_properties
->data_packet_count
;
50 ASFParser::GetMedia ()
56 ASFParser::GetSequentialStreamNumber (int stream_index
)
59 for (int i
= 1; i
<= stream_index
; i
++) {
60 if (IsValidStream (i
))
67 ASFParser::GetStreamCount ()
70 for (int i
= 1; i
<= 127; i
++) {
71 if (IsValidStream (i
))
78 ASFParser::Initialize ()
80 LOG_ASF ("ASFParser::Initialize ()\n");
85 packet_offset_end
= 0;
86 header_objects
= NULL
;
87 header_extension
= NULL
;
88 script_command
= NULL
;
90 file_properties
= NULL
;
92 header_read_successfully
= false;
93 embedded_script_command
= NULL
;
94 embedded_script_command_state
= NULL
;
95 memset (stream_properties
, 0, sizeof (asf_stream_properties
*) * 127);
96 memset (extended_stream_properties
, 0, sizeof (asf_extended_stream_properties
*) * 127);
99 ASFParser::~ASFParser ()
101 LOG_ASF ("ASFParser::~ASFParser ().\n");
110 if (header_objects
) {
111 for (int i
= 0; header_objects
[i
]; i
++)
112 g_free (header_objects
[i
]);
114 g_free (header_objects
);
119 ASFParser::ReadEncoded (IMediaSource
*source
, guint32 length
, guint32
*dest
)
128 if (!source
->ReadAll (&result1
, 1))
133 if (!source
->ReadAll (&result2
, 2))
138 return source
->ReadAll (dest
, 4);
140 //TODO: parser->AddError (g_strdup_printf ("Invalid read length: %i.", length));
146 ASFParser::VerifyHeaderDataSize (guint32 size
)
151 return size
>= 0 && size
< header
->size
;
155 ASFParser::MallocVerified (guint32 size
)
157 void *result
= g_try_malloc0 (size
);
160 AddError ("Out of memory.");
166 ASFParser::Malloc (guint32 size
)
168 if (!VerifyHeaderDataSize (size
))
171 return MallocVerified (size
);
175 ASFParser::ReadObject (asf_object
*obj
)
177 ASFTypes type
= asf_get_guid_type (&obj
->id
);
178 asf_object
*result
= NULL
;
181 LOG_ASF ("ASFParser::ReadObject ('%s', %" G_GUINT64_FORMAT
")\n", asf_guid_tostring (&obj
->id
), obj
->size
);
183 if (obj
->size
< sizeof (asf_object
) || obj
->size
> ASF_OBJECT_MAX_SIZE
) {
184 AddError (g_strdup_printf ("Header corrupted (invalid size: %" G_GUINT64_FORMAT
")", obj
->size
));
188 if (type
== ASF_NONE
) {
189 guid
= asf_guid_tostring (&obj
->id
);
190 AddError (g_strdup_printf ("Unrecognized guid: %s.", guid
));
195 result
= (asf_object
*) Malloc (obj
->size
);
196 if (result
== NULL
) {
197 guid
= asf_guid_tostring (&obj
->id
);
198 AddError (g_strdup_printf ("Header corrupted (id: %s)", guid
));
203 memcpy (result
, obj
, sizeof (asf_object
));
205 if (obj
->size
> sizeof (asf_object
)) {
206 if (!source
->ReadAll (((char *) result
) + sizeof (asf_object
), obj
->size
- sizeof (asf_object
))) {
212 if (!asf_object_validate_exact (result
, this)) {
221 ASFParser::ReadPacket (ASFPacket
**packet
, int packet_index
)
225 LOG_ASF ("ASFParser::ReadPacket (%s, %d) at %" G_GUINT64_FORMAT
".\n", packet
? "non-null" : "null", packet_index
, GetPacketOffset (packet_index
));
227 if (packet_index
>= 0) {
228 gint64 packet_count
= GetPacketCount ();
229 if (packet_count
> 0 && packet_count
< packet_index
+ 1)
230 return MEDIA_NO_MORE_DATA
;
232 gint64 position
= GetPacketOffset (packet_index
);
234 if (!source
->IsPositionAvailable (position
+ GetPacketSize (), &eof
))
235 return eof
? MEDIA_NO_MORE_DATA
: MEDIA_NOT_ENOUGH_DATA
;
237 LOG_ASF ("ASFParser::ReadPacket (%p, %i): determined that position %lld + size %i = %lld is available.\n",
238 packet
, packet_index
, position
, GetPacketSize (), position
+ GetPacketSize ());
239 if (position
== 0 || (source
->GetPosition () != position
))
240 source
->Seek (position
, SEEK_SET
);
243 return ASFParser::ReadPacket (packet
);
247 ASFParser::ReadPacket (ASFPacket
**packet
)
250 MmsPlaylistEntry
*mqs
;
251 gint64 initial_position
;
257 if (source
->GetType () == MediaSourceTypeMmsEntry
) {
258 mqs
= (MmsPlaylistEntry
*) source
;
259 *packet
= mqs
->Pop ();
261 if (*packet
== NULL
) {
262 LOG_ASF ("ASFParser::ReadPacket (%p): no more data in queue source (finished: %i).\n", packet
, mqs
->IsFinished ());
263 return mqs
->IsFinished () ? MEDIA_NO_MORE_DATA
: MEDIA_BUFFER_UNDERFLOW
;
266 return MEDIA_SUCCESS
;
269 initial_position
= source
->GetPosition ();
270 pi
= GetPacketIndex (initial_position
);
271 next_pos
= GetPacketOffset (1 + pi
);
273 LOG_ASF ("ASFParser::ReadPacket (%s): Reading packet at %lld (index: %lld) of %lld packets.\n",
274 packet
? "non-null" : "null", initial_position
, pi
, data
->data_packet_count
);
277 *packet
= new ASFPacket (this, source
);
279 result
= (*packet
)->Read ();
280 if (!MEDIA_SUCCEEDED (result
)) {
281 source
->Seek (next_pos
, SEEK_SET
);
285 /* If we are "positioned", need to seek to the start of the next packet */
287 if (source
->GetType () != MediaSourceTypeMemory
)
288 source
->Seek (next_pos
, SEEK_SET
);
294 ASFParser::ReadData ()
296 LOG_ASF ("ASFParser::ReadData ().\n");
298 if (this->data
!= NULL
) {
299 AddError ("ReadData has already been called.");
304 // We should already be positioned at where the data is
305 if (source
->CanSeek () && source
->GetPosition () != (gint64
) header
->size
) {
306 fprintf (stderr
, "Moonlight assert failure, asf source isn't positioned correctly.\n");
310 data
= (asf_data
*) Malloc (sizeof (asf_data
));
312 AddError ("Data corruption in data.");
316 if (!source
->ReadAll (data
, sizeof (asf_data
))) {
322 asf_object_dump_exact (data
);
324 LOG_ASF ("Data %p has %lld packets.\n", data
, data
->data_packet_count
);
328 return MEDIA_SUCCESS
;
332 ASFParser::ReadHeader ()
336 LOG_ASF ("ASFParser::ReadHeader (), header_read_successfully: %i\n", header_read_successfully
);
338 if (header_read_successfully
)
339 return MEDIA_SUCCESS
;
341 header
= (asf_header
*) MallocVerified (sizeof (asf_header
));
342 if (header
== NULL
) {
343 LOG_ASF ("ASFParser::ReadHeader (): Malloc failed.\n");
347 if (!source
->IsPositionAvailable (sizeof (asf_header
), &eof
)) {
348 LOG_ASF ("ASFParser::ReadHeader (): Not enough data, eof: %i, requested pos: %i, actual available pos: %i\n", eof
, (int) sizeof (asf_header
), (int) source
->GetLastAvailablePosition ());
349 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
352 if (!source
->Peek (header
, sizeof (asf_header
))) {
353 LOG_ASF ("ASFParser::ReadHeader (): source->Read () failed.\n");
357 asf_header_dump (header
);
359 // We are not allowed to leave the stream with a position > 0 if we return MEDIA_NOT_ENOUGH_DATA,
360 // so check if there is enough data to read both the header object and the data object header here,
361 // which is what we need to read in order to return true from this method. This way we avoid peeking
362 // after this point, we just read ahead.
363 if (!source
->IsPositionAvailable (header
->size
+ sizeof (asf_data
), &eof
)) {
364 LOG_ASF ("ASFParser::ReadHeader (): Not enough data, eof: %i, requested pos: %i, actual available pos: %i\n", eof
, (int) (header
->size
+ sizeof (asf_data
)), (int) source
->GetLastAvailablePosition ());
365 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
368 if (!asf_header_validate (header
, this)) {
369 LOG_ASF ("Header validation failed, error: '%s'\n", GetLastErrorStr ());
373 header_objects
= (asf_object
**) Malloc ((header
->object_count
+ 1) * sizeof (asf_object
*));
374 if (header_objects
== NULL
) {
375 AddError ("Data corruption in header.");
379 LOG_ASF ("ASFParser::ReadHeader (): about to read streams...\n");
380 if (!source
->ReadAll (header
, sizeof (asf_header
))) {
381 // We just peeked the header above, read it for real.
382 LOG_ASF ("ASFParser::ReadHeader (): re-reading header failed.\n");
386 bool any_streams
= false;
387 for (guint32 i
= 0; i
< header
->object_count
; i
++) {
390 if (!source
->ReadAll (&tmp
, sizeof (asf_object
)))
393 if (!(header_objects
[i
] = ReadObject (&tmp
)))
396 if (asf_guid_compare (&asf_guids_stream_properties
, &header_objects
[i
]->id
)) {
397 asf_stream_properties
*stream
= (asf_stream_properties
*) header_objects
[i
];
398 SetStream (stream
->get_stream_id (), stream
);
402 if (asf_guid_compare (&asf_guids_file_properties
, &header_objects
[i
]->id
)) {
403 if (file_properties
!= NULL
) {
404 AddError ("Multiple file property object in the asf data.");
407 file_properties
= (asf_file_properties
*) header_objects
[i
];
410 if (asf_guid_compare (&asf_guids_header_extension
, &header_objects
[i
]->id
)) {
411 if (header_extension
!= NULL
) {
412 AddError ("Multiple header extension objects in the asf data.");
415 header_extension
= (asf_header_extension
*) header_objects
[i
];
418 if (asf_guid_compare (&asf_guids_marker
, &header_objects
[i
]->id
)) {
419 if (marker
!= NULL
) {
420 AddError ("Multiple marker objects in the asf data.");
423 marker
= (asf_marker
*) header_objects
[i
];
426 if (asf_guid_compare (&asf_guids_script_command
, &header_objects
[i
]->id
)) {
427 if (script_command
!= NULL
) {
428 AddError ("Multiple script command objects in the asf data.");
431 script_command
= (asf_script_command
*) header_objects
[i
];
434 asf_object_dump_exact (header_objects
[i
]);
437 // Check if there are stream properties in any extended stream properties object.
438 if (header_extension
!= NULL
) {
439 asf_object
**objects
= header_extension
->get_objects ();
440 for (int i
= 0; objects
!= NULL
&& objects
[i
] != NULL
; i
++) {
441 if (asf_guid_compare (&asf_guids_extended_stream_properties
, &objects
[i
]->id
)) {
442 asf_extended_stream_properties
*aesp
= (asf_extended_stream_properties
*) objects
[i
];
443 SetExtendedStream (aesp
->stream_id
, aesp
);
444 const asf_stream_properties
*stream
= aesp
->get_stream_properties ();
445 if (stream
!= NULL
) {
446 if (stream
->get_stream_id () != aesp
->stream_id
) {
448 AddError ("There is an invalid extended stream properties object (it contains a stream properties object whose stream id doesn't match the stream id of the extended stream properties object).");
451 SetStream (stream
->get_stream_id (), stream
);
453 } else if (!IsValidStream (aesp
->stream_id
)) {
455 AddError ("There is an extended stream properties object that doesn't have a corresponding strem properties object.");
464 // Check for required objects.
466 if (file_properties
== NULL
) {
467 AddError ("No file property object in the asf data.");
471 if (header_extension
== NULL
) {
472 AddError ("No header extension object in the asf data.");
477 AddError ("No streams in the asf data.");
481 data_offset
= header
->size
;
482 packet_offset
= data_offset
+ sizeof (asf_data
);
483 if (file_properties
->data_packet_count
!= 0)
484 packet_offset_end
= packet_offset
+ file_properties
->data_packet_count
* file_properties
->min_packet_size
;
486 packet_offset_end
= -1;
488 LOG_ASF ("ASFParser::ReadHeader (): Header read successfully, position: %lld, header size: %lld\n", source
->GetPosition (), header
->size
);
490 if (!MEDIA_SUCCEEDED (ReadData ()))
493 LOG_ASF ("ASFParser::ReadHeader (): Header read successfully [2].\n");
495 header_read_successfully
= true;
497 return MEDIA_SUCCESS
;
501 ASFParser::SetSource (IMediaSource
*source
)
504 this->source
->unref ();
505 this->source
= source
;
507 this->source
->ref ();
511 ASFParser::GetLastError ()
517 ASFParser::GetLastErrorStr ()
519 return error
? error
->error_message
: "";
523 ASFParser::AddError (const char *msg
)
525 AddError (MEDIA_CORRUPTED_MEDIA
, msg
);
529 ASFParser::AddError (char *msg
)
531 AddError (MEDIA_CORRUPTED_MEDIA
, msg
);
535 ASFParser::AddError (MediaResult code
, const char *msg
)
537 AddError (code
, g_strdup (msg
));
541 ASFParser::AddError (MediaResult code
, char *msg
)
543 fprintf (stdout
, "ASF error: %s.\n", msg
);
545 if (error
== NULL
&& media
)
546 media
->ReportErrorOccurred (new ErrorEventArgs (MediaError
, 4001, msg
));
551 const asf_stream_properties
*
552 ASFParser::GetStream (int stream_index
)
554 if (stream_index
< 1 || stream_index
> 127)
557 return stream_properties
[stream_index
- 1];
560 const asf_extended_stream_properties
*
561 ASFParser::GetExtendedStream (int stream_index
)
563 if (stream_index
< 1 || stream_index
> 127)
566 return extended_stream_properties
[stream_index
- 1];
570 ASFParser::SetStream (int stream_index
, const asf_stream_properties
*stream
)
572 if (stream_index
< 1 || stream_index
> 127) {
573 printf ("ASFParser::SetStream (%i, %p): Invalid stream index.\n", stream_index
, stream
);
577 stream_properties
[stream_index
- 1] = stream
;
581 ASFParser::SetExtendedStream (int stream_index
, const asf_extended_stream_properties
*stream
)
583 if (stream_index
< 1 || stream_index
> 127) {
584 printf ("ASFParser::SetExtendedStream (%i, %p): Invalid stream index.\n", stream_index
, stream
);
588 extended_stream_properties
[stream_index
- 1] = stream
;
592 ASFParser::IsValidStream (int stream_index
)
594 return GetStream (stream_index
) != NULL
;
598 ASFParser::GetPacketOffset (guint64 packet_index
)
600 if (packet_index
< 0 || (file_properties
->data_packet_count
> 0 && packet_index
>= file_properties
->data_packet_count
)) {
601 // AddError (g_strdup_printf ("ASFParser::GetPacketOffset (%i): Invalid packet index (there are %" G_GUINT64_FORMAT " packets).", packet_index, file_properties->data_packet_count));
605 // CHECK: what if min_packet_size != max_packet_size?
606 return packet_offset
+ packet_index
* file_properties
->min_packet_size
;
610 ASFParser::GetPacketSize ()
612 return file_properties
->min_packet_size
;
616 ASFParser::GetPacketIndex (gint64 offset
)
618 if (offset
< packet_offset
)
621 if (packet_offset_end
> 0 && offset
> packet_offset_end
)
622 return file_properties
->data_packet_count
- 1;
624 return (offset
- packet_offset
) / file_properties
->min_packet_size
;
628 ASFParser::GetHeader ()
633 asf_file_properties
*
634 ASFParser::GetFileProperties ()
636 return file_properties
;
640 ASFParser::GetHeaderObject (const asf_guid
*guid
)
642 int index
= GetHeaderObjectIndex (guid
);
645 return header_objects
[index
];
652 ASFParser::GetHeaderObjectIndex (const asf_guid
*guid
, int start
)
659 while (header_objects
[i
] != NULL
) {
660 if (asf_guid_compare (guid
, &header_objects
[i
]->id
))
670 ASFParser::GetHeader (int index
)
675 return header_objects
[index
];
682 ASFPacket::ASFPacket (ASFParser
*parser
, IMediaSource
*source
)
683 : EventObject (Type::ASFPACKET
)
688 this->source
= source
;
690 this->source
->ref ();
691 this->parser
= parser
;
693 this->parser
->ref ();
696 ASFPacket::~ASFPacket ()
700 this->source
->unref ();
702 this->parser
->unref ();
706 ASFPacket::SetSource (IMediaSource
*source
)
708 if (this->source
!= NULL
)
709 this->source
->unref ();
710 this->source
= source
;
711 if (this->source
!= NULL
)
712 this->source
->ref ();
716 ASFPacket::GetPayloadCount ()
721 return payloads
->get_number_of_payloads ();
725 ASFPacket::GetPayload (int index
/* 0 based */)
727 if (index
>= 0 && index
< GetPayloadCount ())
728 return payloads
->payloads
[index
];
734 ASFPacket::GetPts (int stream_id
)
736 asf_single_payload
*first
;
741 if (!(first
= GetFirstPayload (stream_id
)))
744 return first
->get_presentation_time ();
748 ASFPacket::GetFirstPayload (int stream_id
/* 1 - 127 */)
754 while (payloads
->payloads
[index
] != NULL
) {
755 if (payloads
->payloads
[index
]->stream_id
== stream_id
)
756 return payloads
->payloads
[index
];
767 asf_payload_parsing_information ppi
;
768 asf_error_correction_data ecd
;
771 LOG_ASF ("ASFPacket::Read (): source: %s, source position: %lld\n", source
->ToString (), source
->GetPosition ());
773 context
.parser
= parser
;
774 context
.source
= this->source
;
776 result
= ecd
.FillInAll (&context
);
777 if (!MEDIA_SUCCEEDED (result
))
780 asf_error_correction_data_dump (&ecd
);
782 result
= ppi
.FillInAll (&context
);
783 if (!MEDIA_SUCCEEDED (result
)) {
784 ASF_LOG_ERROR ("ASFPacket::Read (): FillIn payload parsing information failed.\n");
788 asf_payload_parsing_information_dump (&ppi
);
790 asf_multiple_payloads
*mp
= new asf_multiple_payloads ();
791 result
= mp
->FillInAll (&context
, &ecd
, ppi
);
792 if (!MEDIA_SUCCEEDED (result
)) {
793 ASF_LOG_ERROR ("ASFPacket::Read (): FillIn multiple payloads failed, current position: %lld, in stream %s\n", source
->GetPosition (), source
->ToString ());
800 return MEDIA_SUCCESS
;
807 ASFReader::ASFReader (ASFParser
*parser
, ASFDemuxer
*demuxer
)
809 this->parser
= parser
;
810 this->demuxer
= demuxer
;
811 this->source
= demuxer
->GetSource ();
812 next_packet_index
= 0;
813 memset (readers
, 0, sizeof (ASFFrameReader
*) * 128);
816 ASFReader::~ASFReader ()
818 for (int i
= 0; i
< 128; i
++)
823 ASFReader::SelectStream (gint32 stream_index
, bool value
)
825 LOG_ASF ("ASFReader::SelectStream (%i, %i)\n", stream_index
, value
);
827 if (stream_index
<= 0 || stream_index
>= 128) {
828 fprintf (stderr
, "ASFReader::SelectStream (%i, %i): Invalid stream index\n", stream_index
, value
);
833 if (readers
[stream_index
] == NULL
) {
834 readers
[stream_index
] = new ASFFrameReader (parser
, stream_index
, demuxer
, this, demuxer
->GetStreamOfASFIndex (stream_index
));
837 if (readers
[stream_index
] != NULL
) {
838 delete readers
[stream_index
];
839 readers
[stream_index
] = NULL
;
845 ASFReader::GetFrameReader (gint32 stream_index
)
847 if (stream_index
<= 0 || stream_index
>= 128) {
848 fprintf (stderr
, "ASFReader::GetFrameReader (%i): Invalid stream index.\n", stream_index
);
852 return readers
[stream_index
];
856 ASFReader::TryReadMore ()
858 LOG_ASF ("ASFReader::TryReadMore (), source: %s, next_packet_index: %i\n", source
->ToString (), (int) next_packet_index
);
860 int payloads_added
= 0;
861 guint64 current_packet_index
;
862 gint64 position
, last_available_position
;
863 MediaResult read_result
= MEDIA_FAIL
;
864 ASFPacket
* packet
= NULL
;
866 g_return_val_if_fail (parser
!= NULL
, MEDIA_FAIL
);
867 g_return_val_if_fail (parser
->GetMedia () != NULL
, MEDIA_FAIL
);
870 if (!parser
->GetMedia ()->InMediaThread ())
871 printf ("ASFReader::TryReadMore (): This method should only be called on the media thread (media id: %i).\n", GET_OBJ_ID (parser
->GetMedia ()));
876 LOG_ASF ("ASFReader::ReadMore (): eof\n");
877 return MEDIA_NO_MORE_DATA
;
880 LOG_ASF ("ASFReader::TryReadMore (), current_packet_index: %lld, next_packet_index: %lld\n", current_packet_index
, next_packet_index
);
882 if (source
->GetType () == MediaSourceTypeMmsEntry
) {
883 read_result
= parser
->ReadPacket (&packet
);
884 } else if (source
->CanSeek ()) {
885 position
= source
->GetPosition ();
886 last_available_position
= source
->GetLastAvailablePosition ();
887 if (last_available_position
!= -1 && position
+ parser
->GetPacketSize () > last_available_position
) {
888 LOG_ASF ("ASFReader::TryReadMore (), position: %lld, last_available_position: %lld, packet size: %i\n", position
, last_available_position
, parser
->GetPacketSize ());
889 return MEDIA_BUFFER_UNDERFLOW
;
891 LOG_ASF ("ASFReader::TryReadMore (), position: %lld, last_available_position: %lld, packet size: %i, current packet index: %lld [READING]\n", position
, last_available_position
, parser
->GetPacketSize (), next_packet_index
);
893 read_result
= parser
->ReadPacket (&packet
, next_packet_index
);
895 // We should either be seekable, or be MediaSourceTypeMmsEntry.
896 fprintf (stderr
, "Moonlight: Media assert failure (source should be either MmsSource or seekable). Media playback errors will probably occur.\n");
900 if (read_result
== MEDIA_NOT_ENOUGH_DATA
) {
901 LOG_ASF ("ASFReader::ReadMore (): Not enough data.\n");
907 current_packet_index
= next_packet_index
;
910 LOG_ASF ("ASFReader::ReadMore (): current packet index: %" G_GUINT64_FORMAT
", position: %lld, calculated packet index: %llu\n",
911 current_packet_index
, source
->GetPosition (), parser
->GetPacketIndex (source
->GetPosition ()));
913 if (read_result
== MEDIA_INVALID_DATA
) {
914 LOG_ASF ("ASFReader::ReadMore (): Skipping invalid packet (index: %" G_GUINT64_FORMAT
")\n", current_packet_index
);
920 if (!MEDIA_SUCCEEDED (read_result
)) {
921 LOG_ASF ("ASFReader::ReadMore (): could not read more packets (error: %i)\n", (int) read_result
);
927 // Distribute the payloads to the per-stream readers.
928 asf_single_payload
** payloads
= packet
->payloads
->steal_payloads ();
929 ASFFrameReader
*reader
;
933 while (payloads
[++i
] != NULL
) {
934 stream_id
= payloads
[i
]->stream_id
;
935 reader
= GetFrameReader (stream_id
);
936 if (reader
== NULL
) {
937 LOG_ASF ("ASFReader::ReadMore (): skipped, stream: %i, added pts: %" G_GUINT64_FORMAT
"\n", payloads
[i
]->stream_id
, (guint64
) payloads
[i
]->get_presentation_time ());
942 LOG_ASF ("ASFReader::ReadMore (): delivered payload for stream %i with pts %" G_GUINT64_FORMAT
"\n", payloads
[i
]->stream_id
, (guint64
) payloads
[i
]->get_presentation_time () - 5000);
943 reader
->AppendPayload (payloads
[i
], current_packet_index
);
948 LOG_ASF ("ASFReader::ReadMore (): read %d payloads.\n", payloads_added
);
951 } while (payloads_added
== 0);
953 return MEDIA_SUCCESS
;
959 guint64 packet_count
= parser
->GetPacketCount ();
961 if (packet_count
== 0)
964 if (source
->GetType () == MediaSourceTypeMms
|| source
->GetType () == MediaSourceTypeMmsEntry
)
965 return source
->Eof ();
967 if (source
->GetSize () <= 0)
970 return (source
->GetPosition() >= source
->GetSize () ||
971 next_packet_index
>= packet_count
);
976 ASFReader::ResetAll ()
978 for (int i
= 0; i
< 128; i
++) {
979 if (readers
[i
] != NULL
)
980 readers
[i
]->Reset ();
985 ASFReader::EstimatePacketIndexOfPts (guint64 pts
)
987 guint64 result
= G_MAXUINT64
;
988 for (int i
= 0; i
< 128; i
++) {
989 if (readers
[i
] == NULL
)
992 result
= MIN (readers
[i
]->EstimatePacketIndexOfPts (pts
), result
);
994 return result
== G_MAXUINT64
? 0 : result
;
998 ASFReader::SeekToPts (guint64 pts
)
1002 return source
->SeekToPts (pts
);
1006 ASFReader::Seek (guint64 pts
)
1008 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"), CanSeek: %i, CanSeekToPts(): %i\n", pts
, CanSeek (), source
->CanSeekToPts ());
1011 if (!parser
->GetMedia ()->InMediaThread ())
1012 printf ("ASFReader::TryReadMore (): This method should only be called on the media thread.\n");
1018 if (source
->CanSeekToPts ())
1019 return SeekToPts (pts
);
1021 // We know 0 is at the beginning of the media, so just optimize this case slightly
1024 next_packet_index
= 0;
1025 return MEDIA_SUCCESS
;
1028 // For each stream we need to find a keyframe whose pts is below the requested one.
1029 // Read a packet, and check each payload for keyframes. If we don't find one, read
1030 // the previous packet, and check again.
1032 MediaResult result
= MEDIA_FAIL
;
1033 guint64 start_pi
= EstimatePacketIndexOfPts (pts
); // The packet index we start testing for key frames.
1034 guint64 tested_counter
= 0; // The number of packet indices we have tested.
1035 guint64 test_pi
= 0; // The packet index we're currently testing.
1036 bool found_all_highest
= false;
1037 bool found_all_keyframes
= false;
1038 bool found_keyframe
[128]; // If we've found a key frame below the requested pts.
1039 bool found_above
[128]; // If we've found a frame which is above the requested pts.
1040 guint64 highest_pts
[128]; // The highest key frame pts below the requested pts.
1041 guint64 highest_pi
[128]; // The packet index where we found the highest key frame (see above).
1043 for (int i
= 0; i
< 128; i
++) {
1044 found_keyframe
[i
] = readers
[i
] == NULL
;
1045 found_above
[i
] = readers
[i
] == NULL
;
1046 highest_pts
[i
] = 0;
1047 highest_pi
[i
] = G_MAXUINT64
;
1050 // Start with the latest available packet, otherwise we may end up waiting for some position
1051 // which is way ahead of the position we'll actually end up wanting
1052 // (if the initial start_pi estimate is way off)
1053 if (start_pi
> GetLastAvailablePacketIndex ())
1054 start_pi
= GetLastAvailablePacketIndex ();
1057 // We can't read before the first packet
1058 if (start_pi
< tested_counter
)
1061 test_pi
= start_pi
- tested_counter
++;
1063 ASFPacket
*packet
= NULL
;
1064 result
= parser
->ReadPacket (&packet
, test_pi
);
1066 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Searching packet index %llu for key frames..\n", pts
, test_pi
);
1068 if (result
== MEDIA_INVALID_DATA
) {
1069 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Skipping invalid packet (index: %llu)\n", pts
, test_pi
);
1075 if (result
== MEDIA_NOT_ENOUGH_DATA
) {
1076 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): not enough data (index: %llu)\n", pts
, test_pi
);
1082 if (!MEDIA_SUCCEEDED (result
)) {
1083 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): could not read more packets (error: %i)\n", pts
, (int) result
);
1089 asf_single_payload
** payloads
= packet
->payloads
->payloads
;
1090 for (int i
= 0; payloads
[i
] != NULL
; i
++) {
1091 asf_single_payload
*payload
= payloads
[i
];
1092 int stream_id
= payload
->stream_id
;
1093 guint64 payload_pts
= MilliSeconds_ToPts (payload
->get_presentation_time () - parser
->GetFileProperties ()->preroll
);
1094 ASFFrameReader
*reader
= readers
[stream_id
];
1096 // Ignore payloads for streams we're not handling
1100 reader
->GetStream ()->SetLastAvailablePts (payload_pts
);
1102 // We're not interested in payloads with pts above the requested pts
1103 if (payload_pts
> pts
) {
1104 found_above
[stream_id
] = true;
1108 // We've already found a key frame for the given stream, no need to look for another one.
1109 if (found_keyframe
[stream_id
])
1112 // We're not interested in payloads which doesn't represent the start of a frame
1113 if (payload
->offset_into_media_object
!= 0)
1116 // We're only interested in key frames.
1117 if (!payload
->is_key_frame
&& !reader
->IsAudio ())
1120 // We've found a key frame with pts below the requested pts.
1121 found_keyframe
[stream_id
] = true;
1122 highest_pts
[stream_id
] = MAX (highest_pts
[stream_id
], payload_pts
);
1123 highest_pi
[stream_id
] = highest_pi
[stream_id
] == G_MAXUINT64
? test_pi
: MAX (highest_pi
[stream_id
], test_pi
);
1124 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Found key frame of stream #%i with pts %llu in packet index %llu\n", pts
, stream_id
, payload_pts
, test_pi
);
1129 // Check if we found key frames for all streams, if not, continue looping.
1130 found_all_keyframes
= true;
1131 for (int i
= 0; i
< 128; i
++) {
1132 if (!found_keyframe
[i
]) {
1133 found_all_keyframes
= false;
1137 } while (!found_all_keyframes
);
1139 // Check if we found key frames for all streams, if not, just return false.
1140 // We haven't changed any reader state, so the readers will continue
1141 // returning data as if nothing had happened.
1142 for (int i
= 0; i
< 128; i
++) {
1143 if (!found_keyframe
[i
]) {
1144 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Could not find the requested pts.\n", pts
);
1149 // Now we have a packet index we know has key frames whose pts is below the
1150 // requested pts in all streams. We do not know if those key frames are the key frames
1151 // immediately before the requested pts (an example: we might have
1152 // found the first keyframe in every stream when we wanted to seek to the last
1153 // pts). We need to continue reading ahead finding key frames with pts below than the
1154 // requested one, until we find a frame with pts above the requested one, in which case
1155 // we know that we've found the key frame immediately before the requested pts.
1157 tested_counter
= 1; // Since we've already tested start_pi, now we want to start with start_pi + 1.
1159 // Make this check before reading any packets, since we might already have found
1160 // all the highest packet indices.
1161 found_all_highest
= true;
1162 for (int i
= 0; i
< 128; i
++) {
1163 if (!found_above
[i
]) {
1164 found_all_highest
= false;
1168 if (found_all_highest
)
1171 test_pi
= start_pi
+ tested_counter
++;
1173 ASFPacket
*packet
= NULL
;
1174 result
= parser
->ReadPacket (&packet
, test_pi
);
1176 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Searching packet index %llu for higher key frames..\n", pts
, test_pi
);
1178 if (result
== MEDIA_INVALID_DATA
) {
1179 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Skipping invalid packet (index: %llu)\n", pts
, test_pi
);
1185 if (result
== MEDIA_NOT_ENOUGH_DATA
) {
1186 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Not enough data (index: %llu)\n", pts
, test_pi
);
1192 if (!MEDIA_SUCCEEDED (result
)) {
1193 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): could not read more packets (error: %i)\n", pts
, (int) result
);
1199 if (packet
->payloads
!= NULL
) {
1200 asf_single_payload
** payloads
= packet
->payloads
->payloads
;
1201 for (int i
= 0; payloads
[i
] != NULL
; i
++) {
1202 asf_single_payload
*payload
= payloads
[i
];
1203 int stream_id
= payload
->stream_id
;
1204 guint64 payload_pts
= MilliSeconds_ToPts (payload
->get_presentation_time () - parser
->GetFileProperties ()->preroll
);
1205 ASFFrameReader
*reader
= readers
[stream_id
];
1207 // Ignore payloads for streams we're not handling
1211 reader
->GetStream ()->SetLastAvailablePts (payload_pts
);
1213 // Found a pts above the requested pts, save it.
1214 if (payload_pts
> pts
) {
1215 found_above
[stream_id
] = true;
1219 // We've already found a higher pts for the given stream, no need to look for another one.
1220 if (found_above
[stream_id
])
1223 // We're not interested in payloads which doesn't represent the start of a frame
1224 if (payload
->offset_into_media_object
!= 0)
1227 // We're only interested in key frames.
1228 if (!payload
->is_key_frame
&& !reader
->IsAudio ())
1231 // We've found another key frame which is below the requested one
1232 highest_pts
[stream_id
] = MAX (highest_pts
[stream_id
], payload_pts
);
1233 highest_pi
[stream_id
] = test_pi
;
1235 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Found higher key frame of stream #%i with pts %llu in packet index %llu\n", pts
, stream_id
, payload_pts
, test_pi
);
1242 // Finally we have all the data we need.
1245 test_pi
= G_MAXUINT64
;
1246 for (int i
= 0; i
< 128; i
++) {
1247 if (readers
[i
] == NULL
)
1250 // Find the packet index for which it is true that all streams have a key frame below the requested pts.
1251 test_pi
= MIN (test_pi
, highest_pi
[i
]);
1252 // Set the first pts to be returned by each reader to the highest key-frame pts we found.
1253 readers
[i
]->SetFirstPts (highest_pts
[i
]);
1256 // Don't return any frames before the pts we seeked to.
1257 next_packet_index
= (test_pi
== G_MAXUINT64
) ? 0 : test_pi
;
1259 LOG_ASF ("ASFReader::Seek (%" G_GUINT64_FORMAT
"): Seeked to packet index %lld.\n", pts
, test_pi
);
1261 return MEDIA_SUCCESS
;
1265 ASFReader::GetLastAvailablePacketIndex ()
1267 gint64 last_pos
= source
->GetLastAvailablePosition ();
1270 if (last_pos
< parser
->GetPacketOffset (0) + parser
->GetPacketSize ()) {
1271 LOG_ASF ("ASFReader::GetLastAvailablePacketIndex (): returing 0 (not a single packet available)\n");
1275 pi
= parser
->GetPacketIndex (last_pos
);
1278 LOG_ASF ("ASFReader::GetLastAvailablePacketIndex (): returing 0 (only first packet available)\n");
1282 // We want the packet just before the one which contains the last available position.
1292 ASFFrameReader::ASFFrameReader (ASFParser
*parser
, int stream_number
, ASFDemuxer
*demuxer
, ASFReader
*reader
, IMediaStream
*stream
)
1294 this->reader
= reader
;
1295 this->stream_number
= stream_number
;
1296 this->parser
= parser
;
1297 this->demuxer
= demuxer
;
1298 this->stream
= stream
;
1299 this->stream
->ref ();
1313 key_frames_only
= true;
1315 buffer_underflow
= false;
1318 ASFFrameReader::~ASFFrameReader ()
1322 if (payloads
!= NULL
) {
1323 for (int i
= 0; payloads
[i
]; i
++)
1338 ASFFrameReader::Reset ()
1340 key_frames_only
= true;
1342 if (payloads
!= NULL
) {
1343 for (int i
= 0; payloads
[i
]; i
++) {
1344 delete payloads
[i
];
1345 payloads
[i
] = NULL
;
1352 ASFFrameReader::IsAudio ()
1354 return IsAudio (StreamId ());
1358 ASFFrameReader::IsAudio (int stream
)
1360 const asf_stream_properties
*asp
= parser
->GetStream (stream
);
1361 return asp
!= NULL
&& asp
->is_audio ();
1365 ASFFrameReader::AddFrameIndex (guint64 packet_index
)
1367 // No need to create an index if we can't seek.
1368 if (!reader
->CanSeek ())
1371 gint64 packet_count
= parser
->GetPacketCount ();
1373 // Create the index.
1374 if (index_size
== 0) {
1375 if (packet_count
> 0xFFFF) {
1376 // This is some really huge file (or a corrupted file).
1377 // Don't create any indices, since it would consume a whole lot of memory.
1378 //printf ("ASFFrameReader::AddFrameIndex (): Not creating index, too many packets to track (%" G_GUINT64_FORMAT ")\n", packet_count);
1382 // Max size here is 0xFFFF packets * 16 bytes per index = 1.048.560 bytes
1383 index_size
= packet_count
;
1385 // Don't create any indices if there are no packets.
1386 if (index_size
== 0)
1389 index
= (ASFFrameReaderIndex
*) g_malloc0 (index_size
* sizeof (ASFFrameReaderIndex
));
1391 //printf ("ASFFrameReader::AddFrameIndex (): Created index: stream_count: %i, packet_count: %lld, index_size: %i, item size: %i, gives index size: %i bytes\n", stream_count, packet_count, index_size, sizeof (ASFFrameReaderIndex), index_size * sizeof (ASFFrameReaderIndex));
1393 if (index
== NULL
) {
1398 for (int i
= 0; i
< (int) packet_count
; i
++) {
1399 index
[i
].start_pts
= INVALID_START_PTS
;
1403 // index_size can't be 0 here.
1404 guint32 k
= MIN (packet_index
, index_size
- 1);
1405 guint64 current_start
= index
[k
].start_pts
;
1406 index
[k
].start_pts
= MIN (index
[k
].start_pts
, Pts ());
1407 index
[k
].end_pts
= MAX (index
[k
].end_pts
, Pts ());
1408 if (k
> 1 && current_start
!= INVALID_START_PTS
) {
1409 index
[k
].start_pts
= MAX (index
[k
- 1].end_pts
, current_start
);
1412 //printf ("ASFFrameReader::AddFrameIndex (%" G_GUINT64_FORMAT "). k = %u, start_pts = %llu, end_pts = %llu, stream = %i\n", packet_index, k, index [k].start_pts, index [k].end_pts, stream_number);
1416 ASFFrameReader::FrameSearch (guint64 pts
)
1418 for (guint32 i
= 0; i
< index_size
; i
++) {
1419 //printf ("ASFFrameReader::FrameSearch (%" G_GUINT64_FORMAT "): Checking start_pts: %llu, end_pts: %llu, pi: %i\n", pts, index [i].start_pts, index [i].end_pts, index [i].packet_index);
1421 if (index
[i
].start_pts
== INVALID_START_PTS
)
1422 continue; // This index isn't set
1424 if (index
[i
].start_pts
> pts
) {
1425 //printf ("ASFFrameReader::FrameSearch (%" G_GUINT64_FORMAT "): index not created for the desired pts (found starting pts after the requested one)\n", pts);
1429 if (index
[i
].start_pts
<= pts
&& index
[i
].end_pts
>= pts
) {
1430 //printf ("ASFFrameReader::FrameSearch (%" G_GUINT64_FORMAT "): found packet index: %i.\n", pts, index [i].packet_index);
1436 //printf ("ASFFrameReader::FrameSearch (%" G_GUINT64_FORMAT "d): searched entire index and didn't find anything.\n", pts);
1442 ASFFrameReader::ResizeList (int size
)
1444 asf_single_payload
**new_list
= NULL
;
1446 if (payloads_size
>= size
&& size
> 0)
1449 // Allocate a new list
1450 new_list
= (asf_single_payload
**) parser
->Malloc (sizeof (asf_single_payload
*) * (size
+ 1));
1452 if (new_list
== NULL
) {
1456 if (payloads
!= NULL
) {
1457 // Copy the old list to the new one
1458 memcpy (new_list
, payloads
, payloads_size
* sizeof (asf_single_payload
*));
1462 payloads
= new_list
;
1463 payloads_size
= size
;
1469 ASFFrameReader::SetOnlyKeyFrames ()
1471 key_frames_only
= true;
1475 ASFFrameReader::SetFirstPts (guint64 pts
)
1481 ASFFrameReader::Advance (bool read_if_needed
)
1483 MediaResult result
= MEDIA_SUCCESS
;
1484 MediaResult read_result
;
1485 int payload_count
= 0;
1486 guint32 media_object_number
= 0;
1487 guint64 current_pts
= 0;
1488 guint64 first_packet_index
= 0; // The packet index where the frame starts.
1489 ASFFrameReaderData
* current
= NULL
;
1491 LOG_ASF ("ASFFrameReader::Advance ().\n");
1493 if (buffer_underflow
) {
1494 // Set initial values according to where we left off when the buffer underflowed
1495 for (int i
= 0; payloads
[i
] != NULL
; i
++) {
1498 if (payload_count
== 0) {
1502 media_object_number
= payloads
[0]->media_object_number
;
1504 first_packet_index
= G_MAXUINT64
;
1507 // Clear the current list of payloads.
1508 // Most streams has at least once a media object spanning two payloads.
1509 // so we allocate space for two (+ NULL at the end).
1510 if (payloads
== NULL
) {
1511 if (!ResizeList (2)) {
1512 parser
->AddError ("Out of memory.");
1513 return MEDIA_OUT_OF_MEMORY
;
1516 // Free all old payloads, they belong to the previous frame.
1517 for (int i
= 0; payloads
[i
]; i
++) {
1528 LOG_ASF ("ASFFrameReader::Advance (): frame data: size = %lld, key = %s, pts = %" G_GUINT64_FORMAT
", stream# = %d, media_object_number = %u.\n",
1529 size
, IsKeyFrame () ? "true" : "false", Pts (), StreamId (), media_object_number
);
1531 buffer_underflow
= false;
1534 // Loop through payloads until we find a payload with the different media number
1535 // than the first payload in the queue.
1537 // Make sure we have any payloads in our queue of payloads
1538 while (current
== NULL
) {
1539 // We went past the end of the payloads, read another packet to get more data.
1540 current
= last
; // go back to the last element.
1542 LOG_ASF ("ASFFrameReader::Advance (): No more payloads, requesting more data.\n");
1544 if (!read_if_needed
) {
1545 read_result
= MEDIA_NO_MORE_DATA
;
1549 read_result
= reader
->TryReadMore ();
1550 if (read_result
== MEDIA_NO_MORE_DATA
) {
1551 // No more data, we've reached the end
1552 LOG_ASF ("ASFFrameReader::Advance (): No more data, payload count: %i\n", payload_count
);
1553 if (payload_count
== 0)
1554 result
= read_result
;
1556 } else if (read_result
== MEDIA_BUFFER_UNDERFLOW
) {
1557 result
= read_result
;
1558 buffer_underflow
= true;
1560 } else if (!MEDIA_SUCCEEDED (read_result
)) {
1561 result
= read_result
;
1564 if (current
== NULL
) {
1565 // There were no elements before reading more, our next element is the first one
1568 current
= current
->next
;
1573 LOG_ASF ("ASFFrameReader::Advance (): checking payload, stream: %d, media object number %d, size: %d\n", current
->payload
->stream_id
, current
->payload
->media_object_number
, current
->payload
->payload_data_length
);
1575 asf_single_payload
* payload
= current
->payload
;
1576 current_pts
= MilliSeconds_ToPts (payload
->get_presentation_time () - parser
->GetFileProperties ()->preroll
);
1578 stream
->SetLastAvailablePts (current_pts
);
1580 if (current_pts
< first_pts
) {
1581 ASFFrameReaderData
* tmp
= current
;
1582 current
= current
->next
;
1585 if (payload_count
> 0 && payload
->media_object_number
!= media_object_number
) {
1586 // We've found the end of the current frame's payloads
1587 LOG_ASF ("ASFFrameReader::Advance (): reached media object number %i (while reading %i).\n", payload
->media_object_number
, media_object_number
);
1591 if (key_frames_only
&& !IsAudio () && !payload
->is_key_frame
) {
1592 LOG_ASF ("ASFFrameReader::Advance (): dropped non-key frame, pts: %" G_GUINT64_FORMAT
"\n", current_pts
);
1593 ASFFrameReaderData
* tmp
= current
;
1594 current
= current
->next
;
1599 if (payload_count
== 0 && payload
->offset_into_media_object
!= 0) {
1600 // This frame isn't complete, it's probably split over several packets (and we haven't read the first of those packets).
1601 LOG_ASF ("ASFFrameReader::Advance (): skipping incomplete frame, pts: %" G_GUINT64_FORMAT
", offset into media object: %i.\n", current_pts
, payload
->offset_into_media_object
);
1602 ASFFrameReaderData
*tmp
= current
;
1603 current
= current
->next
;
1608 key_frames_only
= false;
1609 media_object_number
= payload
->media_object_number
;
1610 first_packet_index
= current
->packet_index
;
1612 // add the payload to the current frame's payloads
1614 if (payload_count
== 1)
1615 this->pts
= current_pts
;
1616 size
+= payload
->payload_data_length
;
1617 if (payload_count
> payloads_size
) {
1618 if (!ResizeList (payload_count
+ 3)) {
1622 payloads
[payload_count
- 1] = payload
;
1623 current
->payload
= NULL
;
1625 // Remove it from the queue
1626 ASFFrameReaderData
* tmp
= current
;
1627 current
= current
->next
;
1631 LOG_ASF ("ASFFrameReader::Advance (): current is %p.\n", current
);
1636 printf ("ASFFrameReader::Advance (): frame data: size = %.4lld, key = %s, pts = %.5llu, stream# = %i, media_object_number = %.3u (advanced).",
1637 size, IsKeyFrame () ? "true " : "false", Pts (), StreamNumber (), media_object_number);
1639 dump_int_data (payloads [0]->payload_data, payloads [0]->payload_data_length, 4);
1643 if (MEDIA_SUCCEEDED (result)) {
1644 printf ("ASFFrameReader::Advance (): frame data: size = %.4lld, key = %s, Pts = %.5llu = %" G_GUINT64_FORMAT " ms, pts = %.5u, stream# = %i (%s), media_object_number = %.3u (advanced).\n",
1645 size, IsKeyFrame () ? "true " : "false", Pts (), MilliSeconds_FromPts (Pts ()), payloads [0]->presentation_time, StreamId (), stream->GetStreamTypeName (), media_object_number);
1649 if (MEDIA_SUCCEEDED (result
)) {
1650 if (first_packet_index
!= G_MAXUINT64
)
1651 AddFrameIndex (first_packet_index
);
1658 ASFFrameReader::EstimatePtsPosition (guint64 pts
)
1660 return parser
->GetPacketOffset (MIN (parser
->GetPacketCount () - 1, EstimatePacketIndexOfPts (pts
) + 1));
1664 ASFFrameReader::EstimatePacketIndexOfPts (guint64 pts
)
1666 //printf ("ASFFrameReader::GetPacketIndexOfPts (%" G_GUINT64_FORMAT ")\n", pts);
1669 guint64 average
= 0; // average duration per packet
1670 guint64 last_good_pi
= 0;
1671 guint64 last_good_pts
= 0;
1672 guint64 duration
= 0;
1673 guint64 total_duration
= 0;
1675 guint64 packet_index
= 0;
1681 total_duration
= parser
->GetFileProperties ()->play_duration
- MilliSeconds_ToPts (parser
->GetFileProperties ()->preroll
);
1682 if (pts
>= total_duration
) {
1683 return parser
->GetPacketCount () - 1;
1686 packet_index
= FrameSearch (pts
);
1688 if (packet_index
!= G_MAXUINT32
) {
1689 //printf ("ASFFrameReader::GetPositionOfPts (%" G_GUINT64_FORMAT "): Found pts in index, position: %lld, pi: %i\n", pts, parser->GetPacketOffset (packet_index), packet_index);
1690 return packet_index
;
1693 for (guint32 i
= 0; i
< index_size
; i
++) {
1694 if (!(index
[i
].start_pts
!= INVALID_START_PTS
&& index
[i
].end_pts
> index
[i
].start_pts
))
1697 if (index
[i
].start_pts
>= pts
)
1701 last_good_pts
= index
[i
].start_pts
;
1703 duration
= index
[i
].end_pts
- index
[i
].start_pts
;
1705 average
= (average
/ (double) counter
) * (counter
- 1) + (duration
/ (double) counter
);
1707 //printf ("ASFFrameReader::GetPacketIndexOfPts (%" G_GUINT64_FORMAT "): Calculated average %llu after pi: %i, duration: %llu, start_pts: %llu, end_pts: %llu\n", pts, average, i, duration, index [i].start_pts, index [i].end_pts);
1711 // calculate packet index from duration
1712 guint64 duration
= MAX (1, parser
->GetFileProperties ()->play_duration
- MilliSeconds_ToPts (parser
->GetFileProperties ()->preroll
));
1713 double percent
= MAX (0, pts
/ (double) duration
);
1714 result
= percent
* parser
->GetPacketCount ();
1715 //printf ("ASFFrameReader::GetPacketIndexOfPts (%" G_GUINT64_FORMAT "): No average, calculated by percent %.2f, pi: %i, pts: %llu, preroll: %llu\n", pts, percent, pi, pts, preroll);
1717 // calculate packet index from the last known packet index / pts and average pts per packet index
1718 last_good_pts
= MIN (last_good_pts
, pts
);
1719 result
= last_good_pi
+ (pts
- last_good_pts
) / average
;
1720 //printf ("ASFFrameReader::GetPacketIndexOfPts (%" G_GUINT64_FORMAT "): Calculated by averate %llu, last_good_pts: %llu, pi: %i\n", pts, average, last_good_pts, pi);
1723 result
= MAX (0, result
);
1724 result
= MIN (result
, MAX (0, parser
->GetPacketCount () - 1));
1726 //printf ("ASFFrameReader::GetPacketIndexOfPts (%" G_GUINT64_FORMAT "): Final position: %lld of pi: %i. Total packets: %llu, total duration: %llu\n", pts, parser->GetPacketOffset (pi), pi, parser->GetFileProperties ()->data_packet_count, parser->GetFileProperties ()->play_duration);
1731 ASFFrameReader::AppendPayload (asf_single_payload
*payload
, guint64 packet_index
)
1733 LOG_ASF ("ASFFrameReader::AppendPayload (%p, %" G_GUINT64_FORMAT
"). Stream #%i, pts: %i ms\n", payload
, packet_index
, StreamId (), (int) payload
->get_presentation_time () - 5000);
1736 bool restore
= false;
1738 ASFFrameReaderData
* node
= new ASFFrameReaderData (payload
);
1739 node
->packet_index
= packet_index
;
1740 if (first
== NULL
) {
1749 if (stream
->GetType () == MediaTypeMarker
) {
1750 // Here we try to figure out if we have an entire marker or not
1751 // (determined by finding two NULL WCHARs in the data).
1752 // Make a copy of our payloads, Advance will delete them,
1753 // and we might want to keep them until the next payload arrives.
1754 ASFFrameReaderData
*clone_head
= NULL
;
1755 ASFFrameReaderData
*clone
= NULL
;
1756 ASFFrameReaderData
*tmp
= first
;
1757 ASFFrameReaderData
*copy
= NULL
;
1759 while (tmp
!= NULL
) {
1760 copy
= new ASFFrameReaderData (tmp
->payload
->Clone ());
1761 if (clone
== NULL
) {
1767 clone
= clone
->next
;
1772 advanced
= MEDIA_SUCCEEDED (Advance (false));
1775 // Check if we got all the data
1776 // determined by finding two NULL WCHARs
1777 gint16
*data
= (gint16
*) g_malloc (Size ());
1781 for (guint32 i
= 0; i
< Size () / 2; i
++) {
1782 if (data
[i
] == 0) {
1790 LOG_ASF ("ASFFrameReader::AppendPayload () in data with size %" G_GUINT64_FORMAT
" found %i nulls.\n", Size (), nulls
);
1793 MarkerStream
*marker_stream
= (MarkerStream
*) stream
;
1794 MediaFrame
*frame
= new MediaFrame (marker_stream
);
1795 frame
->pts
= Pts ();
1796 frame
->buflen
= Size ();
1797 frame
->buffer
= (guint8
*) data
;
1798 marker_stream
->MarkerFound (frame
);
1807 if (restore
&& first
== NULL
) {
1808 LOG_ASF ("ASFFrameReader::AppendPayload (%p, %" G_GUINT64_FORMAT
"). Restoring nodes.\n", payload
, packet_index
);
1809 // Restore everything
1810 // Advance () should have consumed all of the ASFFrameReaderDataNodes
1811 // otherwise we're having corruption (since the only way to not have consumed
1812 // all nodes is to get a second payload with a different media object number
1813 // than a first payload, and the first payload doesn't contain 2 NULLs).
1816 while (last
->next
!= NULL
)
1819 LOG_ASF ("ASFFrameReader::AppendPayload (%p, %" G_GUINT64_FORMAT
"). Freeing copied list of nodes.\n", payload
, packet_index
);
1820 // Free the copied list of nodes.
1822 while (tmp
!= NULL
) {
1832 while (node
!= NULL
) {
1836 printf ("ASFFrameReader::AppendPayload (%p, %" G_GUINT64_FORMAT
"). Stream #%i now has %i payloads.\n", payload
, packet_index
, StreamId (), counter
);
1841 ASFFrameReader::Write (void *dest
)
1843 if (payloads
== NULL
)
1846 for (int i
= 0; payloads
[i
]; i
++) {
1847 memcpy (dest
, payloads
[i
]->payload_data
, payloads
[i
]->payload_data_length
);
1848 dest
= ((char *) dest
) + payloads
[i
]->payload_data_length
;
1855 ASFFrameReader::RemoveAll ()
1857 ASFFrameReaderData
* current
= first
, *next
= NULL
;
1858 while (current
!= NULL
) {
1859 next
= current
->next
;
1868 ASFFrameReader::Remove (ASFFrameReaderData
* data
)
1870 if (data
->prev
!= NULL
)
1871 data
->prev
->next
= data
->next
;
1873 if (data
->next
!= NULL
)
1874 data
->next
->prev
= data
->prev
;