Commits

Anonymous committed ad8a925

Finished expansion of CommandQueue. Results in a much more stable
interface. Still a "hiccup" when starting a video up, which can cause
desync...

As well, using surfaces right now causes flickering. Must investigate.

Comments (0)

Files changed (4)

 #include <SDL_thread.h>
 #include <Python.h>
 
-#define COMMON_COMMAND \
-	int type;\
-	size_t size; 
-
+/* Documentation: Command Queue Infrastructure
+ *  This lower-level infrastructure code is meant to provide greater stability and 
+ *  thread safety to the _movie module. Since we cannot manipulate the SDL event queue
+ *  we have to use our own hand-rolled solution. It is just a singly linked list, 
+ *  with references to the first and last item, allowing us to do a
+ *  simple push/pop implementation. The items in the list are structs that have
+ *  all the first members of the default Command struct, making it safe to 
+ *  cast the pointers from the pseudo-Command structs to a pointer to 
+ *  Command struct. Realistically, you can cast any pointer to any other kind of
+ *  pointer(as long as they are the same size!), and C will let you. This is dangerous,
+ *  and should only be done very, very carefully. This facility is only useful 
+ *  when you need a OO approach, like we did here.
+ *  
+ *  When making new commands, use the FULL_COMMAND macro, and add a line to registerCommands 
+ *  in _gmovie.c to add a new type value. This also enables future proofing as any changes to 
+ *  the Command struct will be opaque to the user... mostly.
+ * 
+ *  -Tyler Laing, August 4th, 2009
+ */
 
 typedef struct Command
 {
-	COMMON_COMMAND
+	int type;
 	struct Command *next;
 } Command;
 
-#define FULL COMMAND \
+#define FULL_COMMAND \
 	int type;\
-	size_t size;\
-	struct Command *next;
+	Command *next;
 
 typedef struct CommandQueue
 {
     if(!q->mutex)
         q->mutex = SDL_CreateMutex();
     q->abort_request=0;
-
 }
 
 void packet_queue_flush(PacketQueue *q)
 {
     AVPacketList *pkt, *pkt1;
-#if THREADFREE!=1
 
     if(q->mutex)
         SDL_LockMutex(q->mutex);
-#endif
 
     for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1)
     {
     q->first_pkt = NULL;
     q->nb_packets = 0;
     q->size = 0;
-#if THREADFREE!=1
 
     if(q->mutex)
         SDL_UnlockMutex(q->mutex);
-#endif
 }
 
 void packet_queue_end(PacketQueue *q, int end)
     pkt1->pkt = *pkt;
     pkt1->next = NULL;
 
-#if THREADFREE!=1
-
     if(q->mutex)
         SDL_LockMutex(q->mutex);
-#endif
 
     if (!q->last_pkt)
         q->first_pkt = pkt1;
     q->size += pkt1->pkt.size;
     /* XXX: should duplicate packet data in DV case */
 
-#if THREADFREE!=1
 
     if(q->mutex)
         SDL_UnlockMutex(q->mutex);
-#endif
 
     return 0;
 }
 
 void packet_queue_abort(PacketQueue *q)
 {
-#if THREADFREE!=1
     if(q->mutex)
         SDL_LockMutex(q->mutex);
-#endif
 
     q->abort_request = 1;
-#if THREADFREE!=1
 
     if(q->mutex)
         SDL_UnlockMutex(q->mutex);
-#endif
 }
 
 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
     AVPacketList *pkt1;
     int ret;
 
-#if THREADFREE!=1
-
     if(q->mutex)
         SDL_LockMutex(q->mutex);
-#endif
 
     for(;;)
     {
             break;
         }
     }
-#if THREADFREE!=1
     if(q->mutex)
         SDL_UnlockMutex(q->mutex);
-#endif
 
     return ret;
 }
 	    {
 	    	dst_pix_fmt = PIX_FMT_RGBA;
 	    }
+	    //pict.data = (uint8_t *)vp->dest_surface->pixels;
         avpicture_alloc(&pict, dst_pix_fmt, w, h);
         SDL_LockSurface(vp->dest_surface);
     }
     self->pauseCommandType=registerCommand(self->commands);
     self->stopCommandType=registerCommand(self->commands);
     self->resizeCommandType=registerCommand(self->commands);
+    self->shiftCommandType = registerCommand(self->commands);
 }
 
 /* seek in the stream */
 {
     seekCommand *seek = (seekCommand *) PyMem_Malloc(sizeof(seekCommand));
     seek->type = movie->seekCommandType;
-    seek->size = sizeof(seekCommand);
     seek->pos = pos;
     seek->rel = rel;
     addCommand(movie->commands, (Command *)seek);
 /* pause or resume the video */
 void stream_pause(PyMovie *movie)
 {
-    /*if(movie->ob_refcnt !=0)Py_INCREF( movie);
-    int paused=movie->paused;
-    movie->paused = !movie->paused;
-    if (!movie->paused)
-    {
-        movie->video_current_pts = get_video_clock(movie);
-        movie->frame_timer += (av_gettime() - movie->video_current_pts_time) / 1000000.0;
-    }
-    movie->last_paused=paused;
-    if(movie->ob_refcnt !=0) {Py_DECREF( movie);}
-	*/
 	pauseCommand *pause = (pauseCommand *) PyMem_Malloc(sizeof(pauseCommand));
 	pause->type = movie->pauseCommandType;
-	pause->size = sizeof(pauseCommand);
 	addCommand(movie->commands, (Command *)pause);
 }
 
     	if(hasCommand(movie->commands) && !movie->working)
     	{
     		Command *comm = getCommand(movie->commands);
+    		
     		if(comm->type==movie->seekCommandType)
     		{
     			seekCommand *seek = (seekCommand *)comm;
     			movie->seek_flags |= seek->rel;
     			/* clear stuff away now */
     			comm = NULL;
-    			//GRABGIL
     			PyMem_Free(seek);
-				//RELEASEGIL
     			movie->working=1;
     		}
     		else if(comm->type==movie->pauseCommandType)
     			comm=NULL;
     			PyMem_Free(resize);
     		}	
+    		else if (comm->type == movie->shiftCommandType)
+    		{
+    			shiftCommand *shift = (shiftCommand *)comm;
+    			if(shift->ytop)
+    			{
+    				movie->ytop=shift->ytop;
+    			}
+    			if(shift->xleft)
+    			{
+    				movie->xleft=shift->xleft;
+    			}
+    			comm=NULL;
+    			PyMem_Free(shift);
+    			
+    		}
+    		else if(comm->type == movie->surfaceCommandType)
+    		{
+    			surfaceCommand *surf = (surfaceCommand *)comm;
+    			if(movie->canon_surf)
+    			{
+    				SDL_FreeSurface(movie->canon_surf);
+    				movie->canon_surf=NULL;
+    			}
+    			if(surf->surface)
+    			{
+    				movie->canon_surf=surf->surface;
+    				movie->overlay=0;
+    			}
+    			else
+    			{
+    				movie->overlay=1;
+    			}
+    			
+    		}
     		
     	}
     	
 #define SUBPICTURE_QUEUE_SIZE    4
 /* RGB24 or RGBA... */
 /* In this case I've chosen RGB24 because its smaller */
-#define RGB24 1
-#define RGBA  0
+#define RGB24 0
+#define RGBA  1
 
 #if RGB24
 	#define RGBSTEP 3
 	int pauseCommandType; 
     int stopCommandType;
     int resizeCommandType;
+    int shiftCommandType;
+    int surfaceCommandType;
     int diff_co; //counter
 
     /* Seek-info */
 /*command definitions */
 typedef struct seekCommand
 {
-	COMMON_COMMAND
-	struct Command *next;
+	FULL_COMMAND
 	int64_t pos;
 	int rel;
 } seekCommand;
 
 typedef struct pauseCommand
 {
-	COMMON_COMMAND
-	struct Command *next;
+	FULL_COMMAND
 } pauseCommand;
 
 typedef struct stopCommand
 {
-	COMMON_COMMAND
-	struct Command *next;
+	FULL_COMMAND
 } stopCommand;
 
 typedef struct resizeCommand
 {
-	COMMON_COMMAND
-	struct Command *next;
+	FULL_COMMAND
 	int h;
 	int w;
 } resizeCommand;
 
+typedef struct shiftCommand
+{
+	FULL_COMMAND
+	int ytop;
+	int xleft;	
+} shiftCommand;
+
+typedef struct surfaceCommand
+{
+	FULL_COMMAND
+	SDL_Surface *surface;	
+} surfaceCommand;
+
 /* end of struct definitions */
 /* function definitions */
 
 
 PyObject* _movie_stop(PyMovie *movie)
 {
-    /*Py_INCREF(movie);
-    Py_BEGIN_ALLOW_THREADS
-    SDL_LockMutex(movie->dest_mutex);
-    stream_pause(movie);
-    movie->stop = 1;
-    Py_END_ALLOW_THREADS
-    SDL_UnlockMutex(movie->dest_mutex);
-    Py_DECREF(movie);
-    Py_RETURN_NONE;*/
     stream_pause(movie);
     stopCommand *stop = (stopCommand *)PyMem_Malloc(sizeof(stopCommand));
     stop->type = movie->stopCommandType;
 PyObject* _movie_pause(PyMovie *movie)
 {
 
-    //Py_BEGIN_ALLOW_THREADS
     stream_pause(movie);
-    //Py_END_ALLOW_THREADS
     Py_RETURN_NONE;
 }
 
     resize->h = h;
     resize->w  = w;
     addCommand(movie->commands, (Command *)resize);
-    //status indicators for rendering and that. Very important!
-    //movie->resize_w =  movie->resize_h= 1;
     Py_RETURN_NONE;
 
 }
     if(PyInt_Check(ytop))
     {
         y = (int)PyInt_AsLong(ytop);
-        movie->ytop=y;
+        shiftCommand *shift = (shiftCommand *)PyMem_Malloc(sizeof(shiftCommand));
+        shift->ytop = y;
+        shift->xleft = 0;
+        addCommand(movie->commands, (Command *)shift);
         return 0;
     }
     else
     {
         return -1;
     }
-
 }
 
 PyObject* _movie_get_xleft (PyMovie *movie, void *closure)
     if(PyInt_Check(xleft))
     {
         x = (int)PyInt_AsLong(xleft);
-        movie->xleft=x;
+        shiftCommand *shift = (shiftCommand *)PyMem_Malloc(sizeof(shiftCommand));
+        shift->ytop = 0;
+        shift->xleft = x;
+        addCommand(movie->commands, (Command *)shift);
         return 0;
     }
     else
 int _movie_set_surface(PyObject *mov, PyObject *surface, void *closure)
 {
     PyMovie *movie = (PyMovie *)mov;
-    if(movie->canon_surf)
-    {
-        SDL_FreeSurface(movie->canon_surf);
-    }
     if(PySurface_Check(surface))
     {
-        movie->canon_surf=PySurface_AsSurface(surface);
-        movie->overlay=0;
+        /*movie->canon_surf=PySurface_AsSurface(surface);
+        movie->overlay=0;*/
+        surfaceCommand *surf = (surfaceCommand *)PyMem_Malloc(sizeof(surfaceCommand));
+        surf->surface = PySurface_AsSurface(surface);
+        addCommand(movie->commands, (Command *)surf);
         return 0;
     }
+    else if(surface == Py_None)
+    {
+    	surfaceCommand *surf = (surfaceCommand *)PyMem_Malloc(sizeof(surfaceCommand));
+        surf->surface = NULL;
+        addCommand(movie->commands, (Command *)surf);
+    	return 0;
+    }
     return -1;
 }