Author: fejj
Date: 2008-01-24 16:41:27 -0500 (Thu, 24 Jan 2008)
New Revision: 93844

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/asf/asf-structures.h
   trunk/moon/src/asf/asf.cpp
   trunk/moon/src/media.cpp
   trunk/moon/src/media.h
   trunk/moon/src/pipeline.h
Log:
2008-01-24  Jeffrey Stedfast  <[EMAIL PROTECTED]>

        * media.cpp (UpdateProgress): When switching to Buffering mode,
        save the position where we're currently at in the file so that we
        can use that as a reference point when calculating progress. Also,
        pause the MPlayer so that audio won't continue to play while we're
        waiting for buffering to complete. Fixes bug #356051.



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/ChangeLog    2008-01-24 21:41:27 UTC (rev 93844)
@@ -1,3 +1,11 @@
+2008-01-24  Jeffrey Stedfast  <[EMAIL PROTECTED]>
+
+       * media.cpp (UpdateProgress): When switching to Buffering mode,
+       save the position where we're currently at in the file so that we
+       can use that as a reference point when calculating progress. Also,
+       pause the MPlayer so that audio won't continue to play while we're
+       waiting for buffering to complete. Fixes bug #356051.
+
 2008-01-24  Sebastien Pouliot  <[EMAIL PROTECTED]>
 
        * shape.cpp: Avoid calls to cairo_in_[stroke|fill] if no stroke 
@@ -5,16 +13,17 @@
 
 2008-01-24  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
-       * pipeline.cpp, pipeline.h: Create a more general worker thread, and use
-         unions to save some space in WorkItem. In the ASFDemuxer, when 
seeking,
-         we need to seek to the audio stream, since that's what we're using to
-         sync against (if we have audio).
+       * pipeline.cpp, pipeline.h: Create a more general worker thread,
+       and use unions to save some space in WorkItem. In the ASFDemuxer,
+       when seeking, we need to seek to the audio stream, since that's
+       what we're using to sync against (if we have audio).
+         
        * list.cpp, list.h: Added List::InsertBefore.
 
 2008-01-24  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
-       * media.cpp: MediaElement::SetSource: only trigger the download after 
we've
-         attached to the CompletedEvent.
+       * media.cpp: MediaElement::SetSource: only trigger the download
+       after we've attached to the CompletedEvent.
 
 2008-01-23  Chris Toshok  <[EMAIL PROTECTED]>
 

Modified: trunk/moon/src/asf/asf-structures.h
===================================================================
--- trunk/moon/src/asf/asf-structures.h 2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/asf/asf-structures.h 2008-01-24 21:41:27 UTC (rev 93844)
@@ -211,7 +211,7 @@
                return 0;
        }
        
-       int64_t get_presentation_time ()
+       uint64_t get_presentation_time ()
        {
                return presentation_time;
        }

Modified: trunk/moon/src/asf/asf.cpp
===================================================================
--- trunk/moon/src/asf/asf.cpp  2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/asf/asf.cpp  2008-01-24 21:41:27 UTC (rev 93844)
@@ -488,12 +488,12 @@
        while (ReadPacket (packet, result)) {
                uint64_t current_pts = packet->GetPts (stream_id);
                
-               if (current_pts == ULLONG_MAX) // 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 the previous one.
+                       return result - 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++;
        }
        
@@ -649,12 +649,13 @@
 uint64_t
 ASFPacket::GetPts (int stream_id)
 {
+       asf_single_payload *first;
+       
        if (!payloads)
-               return ULLONG_MAX;
+               return 0;
        
-       asf_single_payload *first = GetFirstPayload (stream_id);
-       if (!first)
-               return ULLONG_MAX;
+       if (!(first = GetFirstPayload (stream_id)))
+               return 0;
        
        return first->get_presentation_time ();
 }

Modified: trunk/moon/src/media.cpp
===================================================================
--- trunk/moon/src/media.cpp    2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/media.cpp    2008-01-24 21:41:27 UTC (rev 93844)
@@ -252,9 +252,9 @@
 int MediaElement::MediaFailedEvent = -1;
 int MediaElement::MediaOpenedEvent = -1;
 
-const char* media_element_states [] = {"Closed", "Opening", "Buffering", 
"Playing", "Paused", "Stopped", "Error", NULL};
+const char *media_element_states[] = { "Closed", "Opening", "Buffering", 
"Playing", "Paused", "Stopped", "Error", NULL };
 
-const char*
+const char *
 MediaElement::GetStateName (State state)
 {
        if ((int) state >= 0 && (int) state <= Error) { 
@@ -264,17 +264,17 @@
        }
 }
 
-static MediaResult marker_callback (MediaClosure* closure)
+static MediaResult marker_callback (MediaClosure *closure)
 {
-       MediaElement* element = (MediaElement*) closure->context;
-       MediaMarker* marker = closure->marker;
+       MediaElement *element = (MediaElement *) closure->context;
+       MediaMarker *marker = closure->marker;
        
        if (marker == NULL)
                return MEDIA_FAIL;
        
-       guint64 pts = (marker->Pts () - closure->media->GetStartTime ()) * 
10000;
+       uint64_t pts = (marker->Pts () - closure->media->GetStartTime ()) * 
10000;
        
-       TimelineMarker* tl_marker = new TimelineMarker ();
+       TimelineMarker *tl_marker = new TimelineMarker ();
        tl_marker->SetValue (TimelineMarker::TextProperty, marker->Text ());
        tl_marker->SetValue (TimelineMarker::TypeProperty, marker->Type ());
        tl_marker->SetValue (TimelineMarker::TimeProperty, Value (pts, 
Type::TIMESPAN));
@@ -285,7 +285,7 @@
 }
 
 void
-MediaElement::AddStreamedMarker (TimelineMarker* marker)
+MediaElement::AddStreamedMarker (TimelineMarker *marker)
 {
        if (streamed_markers == NULL)
                streamed_markers = new TimelineMarkerCollection ();
@@ -295,10 +295,8 @@
 void
 MediaElement::ReadMarkers ()
 {
-       //printf ("MediaElement::ReadMarkers ()\n");
-
-       IMediaDemuxer* demuxer;
-       Media* media;
+       IMediaDemuxer *demuxer;
+       Media *media;
        
        if (mplayer == NULL || mplayer->media == NULL || 
mplayer->media->GetDemuxer () == NULL)
                return;
@@ -308,8 +306,8 @@
 
        for (int i = 0; i < demuxer->GetStreamCount (); i++) {
                if (demuxer->GetStream (i)->GetType () == MediaTypeMarker) {
-                       MarkerStream* stream = (MarkerStream*) 
demuxer->GetStream (i);
-                       MediaClosure* closure = new MediaClosure ();
+                       MarkerStream *stream = (MarkerStream *) 
demuxer->GetStream (i);
+                       MediaClosure *closure = new MediaClosure ();
                        closure->callback = marker_callback;
                        closure->context = this;
                        closure->media = media;
@@ -319,7 +317,7 @@
        }
        
        TimelineMarkerCollection *col = NULL;
-       MediaMarker::Node* current = (MediaMarker::Node*) media->GetMarkers 
()->First ();
+       MediaMarker::Node *current = (MediaMarker::Node *) media->GetMarkers 
()->First ();
        
        if (current == NULL) {
                //printf ("MediaElement::ReadMarkers (): no markers.\n");
@@ -332,12 +330,11 @@
                TimelineMarker *new_marker = new TimelineMarker ();
                new_marker->SetValue (TimelineMarker::TextProperty, 
marker->Text ());
                new_marker->SetValue (TimelineMarker::TypeProperty, 
marker->Type ());
-               new_marker->SetValue (TimelineMarker::TimeProperty, Value 
((marker->Pts () - media->GetStartTime ())* 10000, Type::TIMESPAN));
+               new_marker->SetValue (TimelineMarker::TimeProperty, Value 
((marker->Pts () - media->GetStartTime ()) * 10000, Type::TIMESPAN));
                col->Add (new_marker);
-               //printf ("MediaElement::ReadMarkers (): Adding marker with 
Text: '%s', Type: '%s', Pts: %llu\n", new_marker->GetValue 
(TimelineMarker::TextProperty)->AsString (), new_marker->GetValue 
(TimelineMarker::TypeProperty)->AsString (), new_marker->GetValue 
(TimelineMarker::TimeProperty)->AsTimeSpan ());
                new_marker->unref ();
                
-               current = (MediaMarker::Node*) current->next;
+               current = (MediaMarker::Node *) current->next;
        }
        
        // Docs says we overwrite whatever's been loaded already.
@@ -347,10 +344,8 @@
 }
 
 void
-MediaElement::CheckMarkers (int64_t from, int64_t to)
+MediaElement::CheckMarkers (uint64_t from, uint64_t to)
 {
-       //printf ("MediaElement::CheckMarkers (%llu, %llu)\n", from, to);
-       
        if (from == to)
                return;
        
@@ -364,41 +359,41 @@
 }
 
 void
-MediaElement::CheckMarkers (int64_t from, int64_t to, 
TimelineMarkerCollection* col, bool remove)
+MediaElement::CheckMarkers (uint64_t from, uint64_t to, 
TimelineMarkerCollection *col, bool remove)
 {
+       Collection::Node *node, *next;
+       TimelineMarker *marker;
        Value *val = NULL;
-
+       uint64_t pts;
+       
        if (col == NULL)
                return;
        
        // We might want to use a more intelligent algorithm here, 
        // this code only loops through all markers on every frame.
        
-       Collection::Node *node = (Collection::Node *) col->list->First ();
+       node = (Collection::Node *) col->list->First ();
        while (node != NULL) {
-               TimelineMarker *marker = (TimelineMarker *) node->obj;
+               if (!(marker = (TimelineMarker *) node->obj))
+                       return;
                
-               if (marker == NULL)
+               if (!(val = marker->GetValue (TimelineMarker::TimeProperty)))
                        return;
                
-               val = marker->GetValue (TimelineMarker::TimeProperty);
+               pts = (uint64_t) val->AsTimeSpan ();
                
-               if (val == NULL)
-                       return;
-                       
-               int64_t pts = (int64_t) val->AsTimeSpan ();
-               
                //printf ("MediaElement::CheckMarkers (%llu, %llu): Checking 
pts: %llu\n", from, to, pts);
                
                if (pts >= from && pts <= to) {
                        marker->ref ();
-                       //printf ("MediaElement::CheckMarkers (%llu, %llu): 
Found marker, text = %s.\n", from, to, marker->GetValue 
(TimelineMarker::TextProperty)->AsString ());
                        Emit (MarkerReachedEvent, marker);
                        marker->unref ();
                }
                
-               Collection::Node *next = (Collection::Node *) node->next;
-               if (remove && pts <= to) { // Also delete markers we've passed 
by already
+               next = (Collection::Node *) node->next;
+               
+               if (remove && pts <= to) {
+                       // Also delete markers we've passed by already
                        col->list->Remove (node);
                }
                
@@ -460,6 +455,7 @@
        part_name = NULL;
        mplayer = NULL;
        loaded = false;
+       
        Cleanup (true);
 }
 
@@ -467,11 +463,12 @@
 MediaElement::Cleanup (bool recreate)
 {
        if (media != NULL) {
-               if (media->GetSource () == downloaded_file) {
+               if (media->GetSource () == downloaded_file)
                        downloaded_file = NULL;
-               }
+               
                if (mplayer != NULL && mplayer->media != media)
                        delete media;
+               
                media = NULL;
        }
        
@@ -495,6 +492,7 @@
                DownloaderAbort ();
        downloader = NULL;
        
+       buffering_start = 0;
        delete downloaded_file;
        downloaded_file = NULL;
        
@@ -653,48 +651,58 @@
        cairo_restore (cr);
 }
 
+
+// TODO: make BUFFERING_SIZE configurable
+#define BUFFERING_SIZE (1024 * 1024)
+
+
 void
 MediaElement::UpdateProgress ()
 {
+       double progress, current;
+       bool emit = false;
+       
        //printf ("MediaElement::UpdateProgress (). Current state: %s\n", 
GetStateName (state));
        
        if (downloaded_file != NULL && !IsBuffering () && 
downloaded_file->IsWaiting ()) {
                // We're waiting for more data, switch to the 'Buffering' state.
                //printf ("MediaElement::UpdateProgress (): Switching to 
'Buffering'.\n");
+               SetValue (MediaElement::BufferingProgressProperty, Value (0.0));
+               buffering_start = downloaded_file->GetPosition ();
                SetState (Buffering);
+               mplayer->Pause ();
+               emit = true;
        }
-
-       //printf ("UpdateProgress (): progress = %f, buffer_progress = %f, 
current = %f, buffer_current = %f, update_buffer = %s\n", progress, 
buffer_progress, current, buffer_current, update_buffer ? "true" : "false");
        
-       // BufferingProgressChangedEvent and DownloadProgressChangedEvent 
aren't both emitted,
-       // it's either one or the other.
        // CHECK: if buffering, will DownloadCompletedEvent be emitted?
-
+       
        if (IsBuffering ()) {
-               int buffer_size = 1024 * 1024; // TODO: Honor BufferTimeProperty
-               double progress = (downloaded_file->GetWritePosition () - 
downloaded_file->GetPosition ()) / (double) buffer_size;
-               double current = GetValue 
(MediaElement::BufferingProgressProperty)->AsDouble ();
+               int64_t pos = downloaded_file->GetWritePosition ();
+               int64_t size = downloaded_file->GetTotalSize ();
+               int64_t buffer_size = BUFFERING_SIZE;
+               
+               if (size != -1 && (size - pos) < BUFFERING_SIZE)
+                       buffer_size = size - pos;
+               
+               current = GetValue 
(MediaElement::BufferingProgressProperty)->AsDouble ();
+               if ((progress = ((double) (pos - buffering_start)) / 
buffer_size) > 1.0)
+                       progress = 1.0;
+               
                // Emit the event if it's 100%, or a change of at least 0.05%
-               bool emit_event = (progress == 1.0 && current != 1.0) || 
(fabs(progress - current) >= 0.0005);
-
-               progress = MIN (1.0, progress); // Don't allow progress > 1.0
-
-               if (emit_event) {
+               if (emit || progress == 1.0 || (progress - current) >= 0.0005) {
                        SetValue (MediaElement::BufferingProgressProperty, 
Value (progress));
                        Emit (MediaElement::BufferingProgressChangedEvent);
                }
                
-               if (progress == 1.0) {
+               if (progress == 1.0)
                        BufferingComplete ();
-               }
        } else { 
                // FIXME: Do we emit DownloadProgressChangedEvent if we're 
playing the media?
-               double progress = downloader->GetValue 
(Downloader::DownloadProgressProperty)->AsDouble ();
-               double current = GetValue 
(MediaElement::DownloadProgressProperty)->AsDouble ();
+               progress = downloader->GetValue 
(Downloader::DownloadProgressProperty)->AsDouble ();
+               current = GetValue 
(MediaElement::DownloadProgressProperty)->AsDouble ();
+               
                // Emit the event if it's 100%, or a change of at least 0.05%
-               bool emit_event = (progress == 1.0 && current != 1.0) || 
(progress - current) >= 0.0005;
-
-               if (emit_event) {
+               if (progress == 1.0 || (progress - current) >= 0.0005) {
                        SetValue (MediaElement::DownloadProgressProperty, Value 
(progress));
                        Emit (MediaBase::DownloadProgressChangedEvent);
                }
@@ -704,25 +712,28 @@
 void
 MediaElement::SetState (State new_state)
 {
-       //printf ("MediaElement::SetState ('%s'). Current state: %s, Previous 
state: %s\n", GetStateName (new_state), GetStateName (state), GetStateName 
(previous_state));
+       const char *name;
+       
        if (new_state == Buffering && downloaded_file == NULL) {
                // The code assumes that if Buffering then downloaded_file 
isn't NULL
                // (crashes might occur if this took place)
                // So don't allow it to happen.
-               fprintf (stderr, "MediaElement::SetState (%d): Trying to change 
to 'Buffering' but there's no file to save buffered data to.\n", new_state);
+               fprintf (stderr, "MediaElement::SetState (%d): Trying to change 
to 'Buffering' "
+                        "but there's no file to save buffered data to.\n", 
new_state);
                return;
        }
-
+       
        if (state != new_state) {
                previous_state = state;
-               const char* state_name = GetStateName (new_state);
-               if (state_name == NULL) {
+               if (!(name = GetStateName (new_state))) {
                        printf ("MediaElement::SetState (%d) state is not 
valid.\n", new_state);
                        return;
                }
+               
                //printf ("MediaElement::SetState (%d): New state: %s\n", 
new_state, state_name);
+               
                state = new_state;
-               media_element_set_current_state (this, state_name);             
+               media_element_set_current_state (this, name);           
        }
 }
 

Modified: trunk/moon/src/media.h
===================================================================
--- trunk/moon/src/media.h      2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/media.h      2008-01-24 21:41:27 UTC (rev 93844)
@@ -221,9 +221,11 @@
        // disable buffering (since can't get the start of the file).
        bool disable_buffering;
        
+       int64_t buffering_start;
+       
        ProgressiveSource *downloaded_file;
        Media *media;
-
+       
        bool recalculate_matrix;
        cairo_matrix_t matrix;
        bool updating;
@@ -260,8 +262,8 @@
        static void size_notify (int64_t size, gpointer data);
        
        void ReadMarkers ();
-       void CheckMarkers (int64_t from, int64_t to);
-       void CheckMarkers (int64_t from, int64_t to, TimelineMarkerCollection 
*col, bool remove);
+       void CheckMarkers (uint64_t from, uint64_t to);
+       void CheckMarkers (uint64_t from, uint64_t to, TimelineMarkerCollection 
*col, bool remove);
        
 public:
        // properties

Modified: trunk/moon/src/pipeline.h
===================================================================
--- trunk/moon/src/pipeline.h   2008-01-24 21:35:36 UTC (rev 93843)
+++ trunk/moon/src/pipeline.h   2008-01-24 21:41:27 UTC (rev 93844)
@@ -590,6 +590,7 @@
        void SetCurrentSize (int64_t size);
        
        // The total size of the file (might not be available)
+       int64_t GetTotalSize () { return size; }
        void SetTotalSize (int64_t size);
        
        // Blocks until the position have data

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

Reply via email to