Commits

pygame  committed db86733

movie rewind

  • Participants
  • Parent commits 6b987b9

Comments (0)

Files changed (6)

 <li>surfarrays should be able to do RGBA along with RGB</li>
 <li>draw with transparancy</li>
 <li>draw large sets of primitives with a single call</li>
+<li>drawing offsets, perhaps as subsurfaces</li>
 </ul></p><br>
 
 
 
 
 static int PyGame_Video_AutoInit(void);
+static void PyGame_Video_AutoQuit(void);
 
 
 
 		}
 	}
 	Py_DECREF(privatefuncs);
+
+        PyGame_Video_AutoQuit();
 	SDL_Quit();
 }
 
 		if(status)
 			return 0;
 		SDL_EnableUNICODE(1);
-		PyGame_RegisterQuit(PyGame_Video_AutoQuit);
+                /*we special case the video quit to last now*/
+		/*PyGame_RegisterQuit(PyGame_Video_AutoQuit);*/
 	}
 	return 1;
 }

File src/display.c

 #if !defined(darwin)
 	if(!icon_was_set)
 	{
+        char* iconpath;
 		SDL_Surface* icon = NULL;
 		PyObject* iconstr = display_resourcepath(icon_defaultname);
+
 		icon_was_set = 1;
+		iconpath = PyString_AsString(iconstr);
 
 		if (!iconpath)
 			PyErr_Clear();

File src/ffmovie.c

 #endif
 
 
+static int Global_abort_all = 0;
+static int Global_num_active = 0;
+
 
 static void print_error(const char *filename, int err)
 {
     SDL_LockMutex(q->mutex);
 
     for(;;) {
-        if (q->abort_request) {
+        if (q->abort_request || Global_abort_all) {
             ret = -1;
             break;
         }
 static void video_display(FFMovie *movie)
 {
 /*DECODE THREAD - from video_refresh_timer*/
-/*would prefer from the decode thread mainloop when time is right*/
 
     SDL_LockMutex(movie->dest_mutex);
     if (movie->dest_overlay) {
     return pts;
 }
 
-#if 0
-/* THIS SEEMS TO RETURN THE SAME TIME EVERYTIME? */
-static double get_master_clock(FFMovie *movie)
-{
-    int64_t ti;
-    ti = av_gettime();
-//    return movie->external_clock + ((ti - movie->external_clock_time) * 1e-6);
-    return ti * 1e-6;
-}
-#else
+
 static double get_master_clock(FFMovie *movie) {
     Uint32 ticks = SDL_GetTicks();
     return (ticks / 1000.0) - movie->time_offset;
 }
-#endif
 
 
 
 {
 /*moving to DECODE THREAD, from queue_frame*/
     double actual_delay, delay, sync_threshold, ref_clock, diff;
+    int skipframe = 0;
 
     if (movie->video_st) { /*shouldn't ever even get this far if no video_st*/
 
         if (delay > sync_threshold)
             sync_threshold = delay;
         if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
-            if (diff <= -sync_threshold)
+            if (diff <= -sync_threshold) {
+                skipframe = 1;
                 delay = 0;
-            else if (diff >= sync_threshold)
+            } else if (diff >= sync_threshold) {
                 delay = 2 * delay;
+            }
         }
 
         movie->frame_timer += delay;
         if (actual_delay > 0.010) {
             movie->dest_showtime = movie->frame_timer;
         }
+        if (skipframe) {
+            movie->dest_showtime = 0;
+            /*movie->dest_showtime = get_master_clock(movie); this shows every frame*/
+        }
     }
 }
 
 
 
 
-
-
 /* return the new audio buffer size (samples can be added or deleted
    to get better sync if video or external master clock) */
 static int synchronize_audio(FFMovie *movie, short *samples,
     double pts;
 
     for(;;) {
-        if (movie->paused || movie->audioq.abort_request) {
+        if (movie->paused || movie->audioq.abort_request || Global_abort_all) {
             return -1;
         }
         while (movie->audio_pkt_size > 0) {
                movie->audio_buf_size = 1024;
                memset(movie->audio_buf, 0, movie->audio_buf_size);
            } else {
-               audio_size = synchronize_audio(movie, (int16_t *)movie->audio_buf, audio_size,
-                                              pts);
+               audio_size = synchronize_audio(movie, (int16_t*)movie->audio_buf, audio_size, pts);
                movie->audio_buf_size = audio_size;
            }
            movie->audio_buf_index = 0;
         SDL_FreeYUVOverlay(movie->dest_overlay);
         movie->dest_overlay = NULL;
     }
+
+    Global_num_active--;
 }
 
 
     int status;
     AVPacket pkt1, *pkt = &pkt1;
 
-    while(!movie->abort_request) {
+    while(!movie->abort_request && !Global_abort_all) {
         /* read if the queues have room */
         if (movie->audioq.size < MAX_AUDIOQ_SIZE &&
             !movie->dest_showtime) {
         
         if(movie->paused) {
             double endpause, startpause = SDL_GetTicks() / 1000.0;
-            while(movie->paused && !movie->abort_request) {
+            while(movie->paused && !movie->abort_request && !Global_abort_all) {
                 SDL_Delay(100);
             }
             endpause = SDL_GetTicks() / 1000.0;
 /* MAIN THREAD */
     AVCodec *codec;
     SDL_AudioSpec wanted_spec, spec;
-    
+
     codec = avcodec_find_decoder(stream->codec.codec_id);
     if (!codec || avcodec_open(&stream->codec, codec) < 0) {
         return -1;
     movie->time_offset = 0.0;
     movie->paused = 1;
 
+    Global_num_active++;
     movie->decode_thread = SDL_CreateThread(decode_thread, movie);
     if (!movie->decode_thread) {
         ffmovie_cleanup(movie);
 void ffmovie_close(FFMovie *movie)
 {
 /*MAIN THREAD*/
-    movie->abort_request = 1;
+   movie->abort_request = 1;
+printf("ffmovie_close, wait thread %p\n", movie);
     SDL_WaitThread(movie->decode_thread, NULL);
+printf("ffmovie_close, freemem %p\n", movie);
     av_free(movie);
+printf("ffmovie_close, finished\n");
 }
 
 void ffmovie_play(FFMovie *movie) {
         /*note, i'll need to multiply the sound data myself*/
     }
 }
+
+
+
+void ffmovie_abortall() {
+    Global_abort_all = 1;
+printf("Movie abort all waiting for %d movies...\n", Global_num_active);
+    while(Global_num_active > 0) {
+        SDL_Delay(200);
+    }
+printf("Movie abort all, finished\n");
+    Global_abort_all = 0;
+}

File src/ffmovie.h

 void ffmovie_pause(FFMovie *movie);
 void ffmovie_setvolume(FFMovie *movie, int volume);
 void ffmovie_setdisplay(FFMovie *movie, SDL_Surface *dest, SDL_Rect *rect);
+void ffmovie_abortall(void);
 
 
 #include "ffmovie.h"
 
 
+
 typedef struct {
   PyObject_HEAD
   FFMovie* movie;
 
 
 
+static void autoquit(void)
+{
+    ffmovie_abortall();
+}
 
 
 /* movie object methods */
     /*DOC*/    "Stops playback of a movie. If sound and video are being\n"
     /*DOC*/    "rendered, both will be stopped at their current position.\n"
     /*DOC*/ ;
-/*FIX, movies cannot stop, only kill or pause*/
 
 static PyObject* movie_stop(PyObject* self, PyObject* args)
 {
     /*DOC*/    "set playback position to the beginning of the movie\n"
     /*DOC*/    "\n"
     /*DOC*/    "Sets the movie playback position to the start of\n"
-    /*DOC*/    "the movie.\n"
+    /*DOC*/    "the movie. This can raise a ValueError if the movie\n"
+    /*DOC*/    "cannot be rewound.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "The movie will automatically start playing if the movie\n"
+    /*DOC*/    "is currently playing.\n"
     /*DOC*/ ;
 /*need something for this, if anything reinit a new movie and start*/
 
 static PyObject* movie_rewind(PyObject* self, PyObject* args)
 {
-/*	FFMovie* movie = PyMovie_AsFFMovie(self);*/
+        PyObject* source;
+        char* sourcename = NULL;
+	FFMovie* movie = PyMovie_AsFFMovie(self);
+        SDL_Surface* dest = NULL;
+        int waspaused = movie->paused;
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
+        
+        source = ((PyMovieObject*)self)->filesource;
+        if(source && PyString_Check(source))
+            sourcename = PyString_AsString(source);
+        if(((PyMovieObject*)self)->surftarget)
+            dest = PySurface_AsSurface(((PyMovieObject*)self)->surftarget);
+        
+        if(!sourcename) {
+            return RAISE(PyExc_ValueError, "Unable to rewind movie source");
+        }
+        
         Py_BEGIN_ALLOW_THREADS
+        ffmovie_close(movie);
+        movie = ffmovie_open(sourcename);
+        ffmovie_setdisplay(movie, dest, NULL); /*need to set rect!*/
+        if(!waspaused) {
+            ffmovie_play(movie);
+        }
         Py_END_ALLOW_THREADS
 	RETURN_NONE
 }
 
 	if(PySurface_Check(surfobj))
 	{
-                SDL_Surface* surf = PySurface_AsSurface(surfobj);
+       SDL_Surface* surf = PySurface_AsSurface(surfobj);
+
+	   ((PyMovieObject*)self)->surftarget = surfobj;
+       Py_INCREF(surfobj);
 
 		if(posobj == NULL)
 		{
 	return PyInt_FromLong(movie->context != NULL);
 }
 
+    /*DOC*/ static char doc_movie_skip[] =
+    /*DOC*/    "Movie.skip(seconds) -> None\n"
+    /*DOC*/    "skip ahead a given amount of time\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "Skips ahead in the movie a given number of seconds.\n"
+    /*DOC*/ ;
+
+static PyObject* movie_skip(PyObject* self, PyObject* args)
+{
+	FFMovie* movie = PyMovie_AsFFMovie(self);
+        float seconds;
+
+	if(!PyArg_ParseTuple(args, "f", &seconds))
+		return NULL;
+
+printf("Skipping: %.3f\n", seconds);
+        movie->time_offset -= seconds;
+        
+	return PyInt_FromLong(movie->context != NULL);
+}
+
+
 static PyObject* movie_noop(PyObject* self, PyObject* args)
 {
 	return PyInt_FromLong(0);
 	{ "get_length", movie_get_length, 1, doc_movie_get_length },
 	{ "get_busy", movie_get_busy, 1, doc_movie_get_busy },
 
-	{ "skip", movie_noop, 1, "obsolete, does nothing" },
+	{ "skip", movie_skip, 1, doc_movie_skip },
         { "render_frame", movie_noop, 1, "obsolete, does nothing"},
 
 	{ NULL, NULL }
 static void movie_dealloc(PyObject* self)
 {
 	FFMovie* movie = PyMovie_AsFFMovie(self);
-        Py_BEGIN_ALLOW_THREADS
+ 
+       Py_BEGIN_ALLOW_THREADS
 	ffmovie_close(movie);
         Py_END_ALLOW_THREADS
 	Py_XDECREF(((PyMovieObject*)self)->surftarget);
 	SDL_Surface* screen;
 	if(!PyArg_ParseTuple(arg, "O", &file))
 		return NULL;
-printf("MOVIE ENTER\n");fflush(stdout);
+
 	if(PyString_Check(file) || PyUnicode_Check(file))
 	{
 		if(!PyArg_ParseTuple(arg, "s", &name))
 			return NULL;
+
 printf("  ^opening movie %s\n", name);fflush(stdout);
 		movie = ffmovie_open(name);
 printf("  ^done %p\n", movie);fflush(stdout);
 
       	screen = SDL_GetVideoSurface();
 
-        Py_BEGIN_ALLOW_THREADS
-
-//	if(screen)
-//		SMPEG_setdisplay(movie, screen, NULL, NULL);
-
-        Py_END_ALLOW_THREADS
 
 	final = PyMovie_New(movie);
-	if(!final)
+	if(!final) {
 		ffmovie_close(movie);
-	((PyMovieObject*)final)->filesource = filesource;
+        } else {
+            filesource = PyString_FromString(name);
+            ((PyMovieObject*)final)->filesource = filesource;
+        }
 
 	return final;
 }
 	dict = PyModule_GetDict(module);
 
 	PyDict_SetItemString(dict, "MovieType", (PyObject *)&PyMovie_Type);
-printf("  #movie module initialized\n");
-	/*imported needed apis*/
+
+        /*imported needed apis*/
 	import_pygame_base();
 	import_pygame_surface();
 	import_pygame_rwobject();
 	import_pygame_rect();
+
+    PyGame_RegisterQuit(autoquit);
 }