Author: rolf
Date: 2007-10-19 15:02:14 -0400 (Fri, 19 Oct 2007)
New Revision: 87842

Modified:
   trunk/moon/src/asf/ChangeLog
   trunk/moon/src/asf/asf-ffmpeg.cpp
   trunk/moon/src/asf/asf-ffmpeg.h
   trunk/moon/src/asf/asf-structures.h
   trunk/moon/src/asf/asf.cpp
   trunk/moon/src/asf/asf.h
Log:
* asf-structures.h, asf.cpp, asf-ffmpeg.cpp, asf.h, asf-ffmpeg.h:
  Today's work.

Modified: trunk/moon/src/asf/ChangeLog
===================================================================
--- trunk/moon/src/asf/ChangeLog        2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/ChangeLog        2007-10-19 19:02:14 UTC (rev 87842)
@@ -1,3 +1,8 @@
+2007-10-19  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
+
+       * asf-structures.h, asf.cpp, asf-ffmpeg.cpp, asf.h, asf-ffmpeg.h: 
Today's
+         work.
+
 2007-10-18  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
        * asf-structures.h, asf-generated.cpp, asf.mdp, asf.cpp, asf.mds,

Modified: trunk/moon/src/asf/asf-ffmpeg.cpp
===================================================================
--- trunk/moon/src/asf/asf-ffmpeg.cpp   2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/asf-ffmpeg.cpp   2007-10-19 19:02:14 UTC (rev 87842)
@@ -192,7 +192,39 @@
        MoonASFContext *context = (MoonASFContext*) s->priv_data;
        FFMPEGParser* parser = context->parser;
        FFMPEGPacket* packet = NULL;
+       ASFFrameReader* reader = parser->reader;
        
+       if (!reader->Advance ())
+               return -1;
+               
+       AVPacket* pkt = new AVPacket ();
+       
+       av_new_packet (pkt, reader->Size ());
+               
+       pkt->pts = reader->Pts ();
+       pkt->dts = 0;
+       pkt->stream_index = parser->ConvertStreamIndex (reader->StreamNumber 
()); 
+       pkt->pos = -1;
+       pkt->size = reader->Size ();
+       reader->Write (pkt->data);
+       if (reader->IsKeyFrame () || s->streams 
[pkt->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO) {
+               pkt->flags |= PKT_FLAG_KEY;
+       }
+               
+       //AVPacket_dump (pkt, 1);
+       
+       *av_packet = *pkt; 
+       
+       return 0;
+       
+       //////////////
+       
+#if 0
+       
+       MoonASFContext *context = (MoonASFContext*) s->priv_data;
+       FFMPEGParser* parser = context->parser;
+       FFMPEGPacket* packet = NULL;
+       
        packet = (FFMPEGPacket*) parser->GetCurrentPacket ();
        
        if (packet == NULL) {
@@ -215,6 +247,7 @@
                if (!parser->ReadPacket (packet)) {
                        return -1;
                }
+               parser->SetCurrentPacket (packet);
                parser->packets_read++;
                FFMPEG_LOG ("ffmpeg_asf_read_packet: Created new packet %p with 
%i payloads.\n", packet, packet->GetPayloadCount ());
        }
@@ -230,16 +263,16 @@
        
        FFMPEG_LOG ("ffmpeg_asf_read_packet: Reading payload #%i/%i with size 
%u.\n", current_payload, packet->GetPayloadCount (), payload_size);
        
-       if (false && packet->current_payload == packet->GetPayloadCount ()) {
+       if (packet->current_payload == packet->GetPayloadCount ()) {
                int64_t pos = parser->GetPacketOffset (parser->packets_read);
                parser->source->Seek (pos, SEEK_SET);
-               
+               parser->SetCurrentPacket (NULL);
                if (parser->ReadPacket (new FFMPEGPacket ())) {
                        parser->packets_read++;
                        
                        asf_single_payload* next_payload;
                        packet = (FFMPEGPacket*) parser->GetCurrentPacket ();
-                       next_payload = packet->GetPayload 
(++packet->current_payload);
+                       next_payload = packet->GetPayload 
(packet->current_payload++);
                        if (next_payload != NULL && 
                                next_payload->media_object_number == 
payload->media_object_number &&
                                next_payload->stream_number == 
payload->stream_number) {
@@ -262,7 +295,7 @@
        if (payload->is_key_frame || s->streams 
[pkt->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO) {
                pkt->flags |= PKT_FLAG_KEY;
        }
-       printf ("pkt: %p, pkt->data: %p, payload_size: %i, next_data_size: 
%i\n", pkt, pkt->data, payload_size, next_data_size);
+       //printf ("pkt: %p, pkt->data: %p, payload_size: %i, next_data_size: 
%i\n", pkt, pkt->data, payload_size, next_data_size);
        memcpy (pkt->data, payload->payload_data, payload_size);
        if (next_data_size > 0) {
                memcpy (pkt->data + payload_size, next_data, next_data_size);
@@ -270,13 +303,14 @@
        }
                
        //AVPacket_dump (pkt, 1);
-       if (packet->current_payload == packet->GetPayloadCount ()) {
+       if (false && packet->current_payload == packet->GetPayloadCount ()) {
                parser->FreeCurrentPacket ();
        }
        
        *av_packet = *pkt; 
        
        return 0;
+#endif
 }
 
 int ffmpeg_asf_read_close(AVFormatContext *s)
@@ -297,12 +331,10 @@
        
        FFMPEG_LOG ("ffmpeg_asf_read_seek (%p, %i, %lld, %i).\n", s, 
stream_index, pts, flags);
        
+       if (parser->reader->Seek (parser->ConvertFFMpegStreamIndex 
(stream_index), pts))
+               return 0;
        
-       printf ("FIXME: Seeking to the first packet. This will normally not be 
correct.\n");
-       parser->packets_read = 0;
-       parser->FreeCurrentPacket ();
-       
-       return 0;
+       return -1;
 }
 
 int64_t ffmpeg_asf_read_pts(AVFormatContext *s, int ffmpeg_stream_index, 
int64_t *start_pos, int64_t pos_limit)
@@ -352,29 +384,28 @@
        
        bool is_audio_stream = parser->GetStream (stream_index)->is_audio ();
        int64_t result = AV_NOPTS_VALUE;
-       ASFPacket* old_packet = parser->GetCurrentPacket ();
-       parser->SetCurrentPacket (NULL);
        while (packet_offset > pos_limit) {
                packet_offset += file_properties->min_packet_size;
                packet_index++;
-               if (!parser->ReadPacket ()) {
+               
+               ASFPacket* packet = new ASFPacket ();
+               if (!parser->ReadPacket (packet)) {
                        FFMPEG_LOG ("ffmpeg_asf_read_pts: could not read packet 
index %lld at position %lld.\n", packet_index, packet_offset);
+                       delete packet;
                        return AV_NOPTS_VALUE;
                }
                
-               ASFPacket* packet = parser->GetCurrentPacket ();
-               
                if (!is_audio_stream && !packet->payloads->is_key_frame 
(stream_index))
                        continue;
 
                *start_pos = packet_offset;
                
                result = packet->payloads->get_presentation_time (stream_index);
+               
+               delete packet;
+               
                break;
        }
-       parser->FreeCurrentPacket ();
-       
-       parser->SetCurrentPacket (old_packet);
                
        FFMPEG_LOG ("fmpeg_asf_read_pts: found pts (%lld) of packet index 
%lld.\n", pts, packet_index);
        
@@ -789,4 +820,4 @@
        FFMPEG_DUMP ("%sduration = %i\n", tabs, pkt->duration);
        FFMPEG_DUMP ("%spos = %lld\n", tabs, pkt->pos);
        
-}
\ No newline at end of file
+}

Modified: trunk/moon/src/asf/asf-ffmpeg.h
===================================================================
--- trunk/moon/src/asf/asf-ffmpeg.h     2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/asf-ffmpeg.h     2007-10-19 19:02:14 UTC (rev 87842)
@@ -70,11 +70,13 @@
        FFMPEGParser (const char* filename) : ASFParser (filename)
        {
                memset (ffmpeg_stream_indices, -1, 128);
-               packets_read = 0;
+               reader = new ASFFrameReader (this);
        }
        
        virtual ~FFMPEGParser ()
        {
+               delete reader;
+               reader = NULL;
        }
        
        void AddStreamIndex (gint32 ffmpeg_stream_index, gint32 
asf_stream_index)
@@ -114,7 +116,7 @@
        
        gint32 ffmpeg_stream_indices [128];
        
-       int64_t packets_read;
+       ASFFrameReader* reader;
 };
 
 class FFMPEGSource : public ASFSource {

Modified: trunk/moon/src/asf/asf-structures.h
===================================================================
--- trunk/moon/src/asf/asf-structures.h 2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/asf-structures.h 2007-10-19 19:02:14 UTC (rev 87842)
@@ -192,12 +192,12 @@
        
        bool FillInAll (ASFSource* source, asf_error_correction_data* ecd, 
asf_payload_parsing_information ppi, asf_multiple_payloads* mp);
        
-       asf_dword get_presentation_time ()
+       gint64 get_presentation_time ()
        {
                if (replicated_data_length >= 8) {
                        return * (((asf_dword*) replicated_data) + 1);
                }
-               return 0;
+               return -1;
        }
        
        asf_single_payload () 
@@ -312,6 +312,13 @@
                }
                return false;
        }
+       
+       asf_single_payload** steal_payloads ()
+       {
+               asf_single_payload** result = payloads;
+               payloads = NULL;
+               return result;
+       }
 
 };
 

Modified: trunk/moon/src/asf/asf.cpp
===================================================================
--- trunk/moon/src/asf/asf.cpp  2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/asf.cpp  2007-10-19 19:02:14 UTC (rev 87842)
@@ -23,8 +23,9 @@
        ASFParser* parser = new ASFParser (filename);
        parser->ReadHeader ();
        parser->ReadData ();
-       while (parser->ReadPacket ()) {
-               ASF_LOG ("One more packet read.\n");
+       ASFPacket* packet;
+       while ((packet = new ASFPacket ()) && parser->ReadPacket (packet)) {
+               delete packet;
        }
        delete parser;
 }
@@ -51,7 +52,6 @@
        packet_offset_end = 0;
        header_objects = NULL;
        last_error = NULL;
-       current_packet = NULL;
        file_properties = NULL;
        
        memset (stream_properties, 0, sizeof (asf_stream_properties*) * 127);
@@ -74,8 +74,6 @@
        
        g_free (header_objects);
        header_objects = NULL;
-       
-       FreeCurrentPacket ();
 }
 
 asf_object*
@@ -113,44 +111,40 @@
 }
 
 bool
-ASFParser::ReadPacket ()
+ASFParser::ReadPacket (ASFPacket* packet, gint32 packet_index)
 {
-       return ASFParser::ReadPacket (new ASFPacket ());
+       ASF_LOG ("ASFParser::ReadPacket (%p, %i).\n", packet, packet_index);
+       
+       if (packet_index >= 0) {
+               guint64 position = GetPacketOffset (packet_index);
+
+               if (position == 0 || !source->Seek (position, SEEK_SET))
+                       return false;
+       }
+       
+       return ASFParser::ReadPacket (packet);
 }
 
 bool
-ASFParser::ReadPacket (ASFPacket* next_packet)
+ASFParser::ReadPacket (ASFPacket* packet)
 {
-       ASF_LOG ("ASFParser::ReadPacket (%p), data: %p\n", next_packet, data);
+       ASF_LOG ("ASFParser::ReadPacket (%p): Reading packet at %lld (index: 
%i) of %lld packets.\n", packet, source->Position (), GetPacketIndex 
(source->Position ()), data->data_packet_count);
        
-       if (!data && !ReadData ())
-               return false;
-
-       FreeCurrentPacket ();
-       
-       ASF_LOG ("ASFParser::ReadPacket (): Reading packet at %lld (index: %i) 
of %lld packets.\n", source->Position (), GetPacketIndex (source->Position ()), 
data->data_packet_count);
-       
        asf_error_correction_data ecd;
        asf_payload_parsing_information ppi;
        
-       int64_t start_position = source->Position ();
+       //int64_t start_position = source->Position ();
        
-       //printf ("Current position: %llx (%lld)\n", source->Position (), 
source->Position ());
-       
        if (!ecd.FillInAll (source))
                return false;
        
-       //asf_error_correction_data_dump (&ecd);
+       asf_error_correction_data_dump (&ecd);
        
-       //printf ("Current position: %llx (%lld)\n", source->Position (), 
source->Position ());
-       
        if (!ppi.FillInAll (source))
                return false;
        
-       //asf_payload_parsing_information_dump (&ppi);
+       asf_payload_parsing_information_dump (&ppi);
        
-       //printf ("Current position: %llx (%lld)\n", source->Position (), 
source->Position ());
-       
        asf_multiple_payloads* mp = new asf_multiple_payloads ();
        if (ppi.is_multiple_payloads_present ()) {
                ASF_LOG ("ASFParser::ReadPacket (), reading multiple 
payloads.\n");
@@ -170,13 +164,11 @@
                mp->payload_flags = 1; // 1 payload
        }
        //asf_multiple_payloads_dump (mp);
-       next_packet->payloads = mp;
+       packet->payloads = mp;
        
-       if (!source->Skip (ppi.padding_length))
-               return false;
+//     if (!source->Skip (ppi.padding_length))
+//             return false;
        
-       current_packet = next_packet;
-       
        ASF_LOG ("ASFParser::ReadPacket (): Current position (end of packet): 
%llx (%lld), start position was: %llx (%lld), difference: %llx (%lld)\n", 
                source->Position (), source->Position (), 
                start_position, start_position,
@@ -254,6 +246,9 @@
 
        ASF_LOG ("ASFParser::ReadHeader (): Header read successfully.\n");
        
+       if (!ReadData ())
+               return false;
+               
        return true;
 }
 
@@ -404,7 +399,222 @@
        }
 }
 
+/*
+       ASFFrameReader
+*/
 
+ASFFrameReader::ASFFrameReader (ASFParser* p)
+{
+       parser = p;
+       first = NULL;
+       last = NULL;
+       size = 0;
+       is_key_frame = true;
+       pts = 0;
+       stream_number = 0;
+       payloads = NULL;
+       current_packet_index = CanSeek () ? 0 : -1;
+       
+       // Most streams has at least once a media object spanning two payloads.
+       // so we allocate space for two (+ NULL at the end).
+       payloads_size = 2;
+       payloads = (asf_single_payload**) g_malloc0 (sizeof 
(asf_single_payload*) * (payloads_size + 1));
+}
 
+ASFFrameReader::~ASFFrameReader ()
+{
+       parser = NULL;
+       
+       RemoveAll ();
+       
+       gint32 i = -1;
+       while (payloads [++i] != NULL)
+               delete payloads [i];
+       g_free (payloads); payloads = NULL;
+}
 
+bool
+ASFFrameReader::Seek (gint32 stream_number, guint64 pts)
+{
+       ASF_LOG ("ASFFrameReader::Seek (%i, %llu).\n", stream_number, pts);
+       
+       if (!CanSeek ())
+               return false;
+               
+       // Now this is an algorithm that needs some optimization.
+       // We seek from the first frame to the frame AFTER the one we want 
(counting the numbers of frames)
+       // then we seek again from the first frame until the number of frames 
counted - 1.      
+       
+       gint32 counter = 0;
+       bool found = true;
+       
+       current_packet_index = 0;
+       RemoveAll ();
+       
+       while (Advance ()) {
+               if (Pts () > pts) {
+                       found = true;
+                       break;
+               }
+               counter++;
+       }
+       
+       if (!found)
+               return false;
+       
+       current_packet_index = 0;
+       RemoveAll ();
+       
+       while (counter-- > 0) {
+               if (!Advance ()) {
+                       return false;
+               }
+       }
+               
+       return true;
+}
 
+bool
+ASFFrameReader::Advance ()
+{
+       ASF_LOG ("ASFFrameReader::Advance ().\n");
+       // Clear the current list of payloads.
+       int i = -1;
+       while (payloads [++i] != NULL) {
+               delete payloads [i];
+               payloads [i] = NULL;
+       }
+       
+       if (first == NULL) {
+               if (!ReadMore ())
+                       return false;
+               if (first == NULL)
+                       return false;
+       }
+       gint32 payload_count = 1;
+       payloads [0] = first->payload;
+       gint32 media_object_number = payloads [0]->media_object_number;
+       size = payloads [0]->payload_data_length;
+       is_key_frame = payloads [0]->is_key_frame;
+       pts = payloads [0]->get_presentation_time ();
+       stream_number = payloads [0]->stream_number;
+       
+       ASF_LOG ("ASFFrameReader::Advance (): frame data: size = %lld, key = 
%s, pts = %llu, stream# = %i.\n", 
+               size, is_key_frame ? "true" : "false", pts, stream_number);
+       
+       bool end = false;
+       ASFFrameReaderData *current = first->next;
+       
+       Remove (first);
+       
+       while (!end) {
+               // Loop through payloads until we find a payload with the same 
stream number.
+               // if the media number is different, no more payloads in the 
current frame,
+               // otherwise add the payload to the current frame's payloads 
and continue looping.
+               while (current == NULL) {
+                       // We went past the end, read another packet to get 
more data.
+                       current = last; // go back to the last element.
+                       if (!ReadMore ()) {
+                               end = true; // No more data, we've reached the 
end
+                               break;
+                       } else {
+                               if (current == NULL) {
+                                       // There was no elements before reading 
more, our next element is the first one
+                                       current = first;
+                               } else {
+                                       current = current->next;
+                               }
+                       }
+               }
+               
+               if (end)
+                       break;
+               
+               if (current->payload->stream_number == stream_number) {
+                       if (current->payload->media_object_number == 
media_object_number) {
+                               // Add the payload to the current frame's 
payloads
+                               payload_count++;
+                               size += current->payload->payload_data_length;
+                               if (payload_count > payloads_size) {
+                                       gint32 new_size = payload_count + 3;
+                                       payloads = (asf_single_payload**) 
g_realloc (payloads, sizeof (asf_single_payload*) * (new_size + 1));
+                                       memset (payloads + payloads_size, 0, 
sizeof (asf_single_payload*) * (new_size - payloads_size));
+                                       payloads_size = new_size;
+                               }
+                               payloads [payload_count - 1] = current->payload;
+                               
+                               // Remove it from the queue
+                               ASFFrameReaderData* tmp = current;
+                               current = current->prev;
+                               
+                               tmp->payload = NULL;
+                               Remove (tmp);
+                               delete tmp;
+                       } else {
+                               // We've found the end of the current frame's 
payloads
+                               end = true;
+                       }
+               }
+               
+               if (current != NULL)
+                       current = current->next;
+       }
+       
+       return true;
+}
+
+bool
+ASFFrameReader::ReadMore ()
+{
+       ASFPacket* packet = new ASFPacket ();
+       
+       ASF_LOG ("ASFFrameReader::ReadMore ().\n");
+       
+       if (!parser->ReadPacket (packet, current_packet_index)) {
+               ASF_LOG ("ASFFrameReader::ReadMore (): could not read more 
packets.\n");
+               delete packet;
+               return false;
+       }
+       
+       if (CanSeek ()) {
+               current_packet_index++;
+       }
+       
+       asf_single_payload** payloads = packet->payloads->steal_payloads ();
+       int i = -1;
+       while (payloads [++i] != NULL) {
+               // Append the payload at the end of the queue of payloads.
+               ASFFrameReaderData* node = new ASFFrameReaderData (payloads 
[i]);
+                       
+               if (first == NULL) {
+                       first = node;
+                       last = node;
+               } else {
+                       node->prev = last;
+                       last->next = node;
+                       last = node;
+               }
+       }
+       
+       ASF_LOG ("ASFFrameReader::ReadMore (): read %i payloads.\n", i);
+               
+       delete packet;
+       return true;
+}
+
+bool
+ASFFrameReader::Write (void* destination)
+{
+       if (payloads == NULL)
+               return false;
+
+       void* start = destination;
+       gint32 i = -1;
+       while (payloads [++i] != NULL) {
+               memcpy (destination, payloads [i]->payload_data, payloads 
[i]->payload_data_length);
+               destination = payloads [i]->payload_data_length + (char*) 
destination;
+       }
+       
+       return true;
+}
+

Modified: trunk/moon/src/asf/asf.h
===================================================================
--- trunk/moon/src/asf/asf.h    2007-10-19 18:17:33 UTC (rev 87841)
+++ trunk/moon/src/asf/asf.h    2007-10-19 19:02:14 UTC (rev 87842)
@@ -142,11 +142,131 @@
                return NULL;
        }
        
+       // Gets the pts of the first payload.
+       int64_t GetPts (gint32 stream_number)
+       {
+               if (!payloads)
+                       return -1;
+               
+               asf_single_payload* first = GetFirstPayload (stream_number);
+               if (!first)
+                       return -1;
+                       
+               return first->get_presentation_time ();
+       }
+       
+       asf_single_payload* GetFirstPayload (gint32 stream_number)
+       {
+               if (!payloads)
+                       return NULL;
+                       
+               int index = 0;
+               while (payloads->payloads [index] != NULL) {
+                       if (payloads->payloads [index]->stream_number == 
stream_number)
+                               return payloads->payloads [index];
+                       index++;
+               }
+               return NULL;
+       }
+       
        asf_multiple_payloads* payloads;
-       int64_t index;
+       
+       gint32 index; // The index of this packet. -1 if not known.
+       gint64 position; // The position of this packet. -1 if not known.
                
 };
 
+struct ASFFrameReaderData {
+       asf_single_payload* payload;
+       ASFFrameReaderData* prev;
+       ASFFrameReaderData* next;
+       
+       ASFFrameReaderData (asf_single_payload* load)
+       {
+               payload = load;
+               prev = NULL;
+               next = NULL;
+       }
+       
+       ~ASFFrameReaderData ()
+       {
+               delete payload;
+       }
+};
+
+class ASFFrameReader {
+public:
+       ASFFrameReader (ASFParser* parser);
+       virtual ~ASFFrameReader ();
+       
+       // Can we seek?
+       bool CanSeek () { return true; }
+       
+       // Seek to the frame with the provided pts 
+       bool Seek (gint32 stream_number, guint64 pts);
+       
+       // Advance to the next frame
+       bool Advance ();
+       
+       // Write the frame's data to a the destination
+       bool Write (void* destination);
+       
+       // Information about the current frame
+       guint64 Size () { return size; }
+       bool IsKeyFrame () { return is_key_frame; }
+       gint64 Pts () { return pts; }
+       gint32 StreamNumber () { return stream_number; }
+       
+private:
+       ASFParser* parser;
+       
+       gint32 current_packet_index;
+       
+       // The queue of payloads we've built.
+       ASFFrameReaderData* first;
+       ASFFrameReaderData* last;
+       
+       // A list of the payloads in the current frame
+       asf_single_payload** payloads;
+       gint32 payloads_size;
+       
+       // Information about the current frame.
+       guint64 size;
+       bool is_key_frame;
+       gint64 pts;
+       gint32 stream_number;
+       
+       // Reads another packet and fills data at the end 
+       bool ReadMore ();
+       
+       void RemoveAll ()
+       {
+               ASFFrameReaderData* current = first, *next = NULL;
+               while (current = NULL) {
+                       next = current->next;
+                       delete current;
+                       current = next;
+               }
+               first = NULL;
+               last = NULL;
+       }
+       
+       void Remove (ASFFrameReaderData* data)
+       {
+               if (data->prev != NULL)
+                       data->prev->next = data->next;
+               
+               if (data->next != NULL)
+                       data->next->prev = data->prev;
+                       
+               if (data == first)
+                       first = data->next;
+                       
+               if (data == last)
+                       last = data->prev;
+       }
+};
+
 class ASFParser {
 public:
        ASFParser (const char* filename);
@@ -154,26 +274,17 @@
        
        bool ReadHeader ();
        bool ReadData ();
-       bool ReadPacket ();
+       // Reads the packet at the current position.
        bool ReadPacket (ASFPacket* packet);
+       // Seeks to the packet index (as long as the packet index >= 0), then 
reads it.
+       // If the packet index is < 0, then just read at the current position
+       bool ReadPacket (ASFPacket* packet, gint32 packet_index); 
+       
        asf_object* ReadObject (asf_object* guid);
        const char* GetLastError ();
        void AddError (const char* err); // Makes a copy of the provided error 
string.
        void AddError (char* err); // Frees the provided error string.
 
-       ASFSource* source;
-       
-       asf_header* header;
-       int64_t data_offset; // location of data object
-       int64_t packet_offset; // location of first packet
-       int64_t packet_offset_end; // location of the end of the last packet
-       asf_data* data;
-       asf_file_properties* file_properties;
-       
-       asf_stream_properties* stream_properties [127];
-       
-       ASFPacket* current_packet;
-       
        // Stream index from 1 to 127
        asf_stream_properties* GetStream (gint32 stream_index)
        {
@@ -197,8 +308,14 @@
                return GetStream (stream_index) != NULL;
        }
        
-       int64_t GetPacketOffset (int64_t packet_index)
+       // Returns 0 on failure, otherwise the offset of the packet index.
+       guint64 GetPacketOffset (gint32 packet_index)
        {
+               if (packet_index < 0 || packet_index >= 
file_properties->data_packet_count) {
+                       AddError (g_strdup_printf ("ASFParser::GetPacketOffset 
(%i): Invalid packet index (there are %llu packets).", packet_index, 
file_properties->data_packet_count)); 
+                       return 0;
+               }
+
                return packet_offset + packet_index * 
file_properties->min_packet_size;
        }
        
@@ -211,22 +328,28 @@
                return (offset - packet_offset) / 
file_properties->min_packet_size;
        }
        
-       ASFPacket* GetCurrentPacket ()
+       // Returns the packet index where the desired pts is found.
+       // Returns -1 on failure.
+       gint32 GetPacketIndexOfPts (gint32 stream_number, gint64 pts)
        {
-               return current_packet;
+               int result = 0;
+               ASFPacket* packet = NULL;
+               
+               // Read packets until we find the packet which has a pts
+               // greater than the one we're looking for.
+               
+               while (ReadPacket (packet, result)) {
+                       gint64 current_pts = packet->GetPts (stream_number);
+                       if (current_pts < 0) // Can't read pts for some reason.
+                               return -1;
+                       if (current_pts > pts) // We've found the packet after 
the one we're looking for
+                               return result - 1; // return the previous one.
+                       result++;
+               }
+               
+               return -1;
        }
        
-       void SetCurrentPacket (ASFPacket* packet)
-       {
-               current_packet = packet;
-       }
-       
-       void FreeCurrentPacket ()
-       {
-               delete current_packet;
-               current_packet = NULL;
-       }
-       
        asf_header* GetHeader ()
        {
                return header;
@@ -271,11 +394,22 @@
                        return NULL;
                return header_objects [index];
        }
+
+       ASFSource* source;
        
+       asf_object** header_objects;
+       asf_header* header;
+       asf_data* data;
+       asf_file_properties* file_properties;
        
-private:
-       asf_object** header_objects;
-       char* last_error;       
+       asf_stream_properties* stream_properties [127];
+       
+       guint64 data_offset; // location of data object
+       guint64 packet_offset; // location of the beginning of the first packet
+       guint64 packet_offset_end; // location of the end of the last packet
+       
+       
+       char* last_error;
 };
 
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to