1. pygame
  2. Untitled project
  3. pygame

Commits

zeroth  committed e765c03

Rolled back threaded code. Moved only audio to its own thread, to not be
stopped by the frame issues of large surfaces. Wrote a slightly more
optimized routine for transferring data from an AVPicture to an
SDL_Surface.

  • Participants
  • Parent commits e3bba48
  • Branches tylerthemovie

Comments (0)

Files changed (4)

File movie_test.py

View file
 
 print "Please give an (absolute)filename of a movie file you'd like to play: ",
 #filename = raw_input()
-filename="/home/tyler/avatar.avi"
+filename="/home/tyler/War3.avi"
 #initialization. It could also have a surface as a second argument, and every 
 # frame will be blitted to that surface. It is the programmer's responsibility
 # to be on time for rendering that surface.

File src/_gmovie.c

View file
     get_width(movie, width);
 }
 
+inline void jamPixels(int ix, AVPicture *picture, uint32_t *rgb, SDL_Surface *surface)
+{
+	//uint32_t *rgb           = surface->pixels;
+	uint8_t red   = picture->data[0][ix]; 
+	uint8_t green = picture->data[0][ix+1];
+	uint8_t blue  = picture->data[0][ix+2];
+	//skip the alpha... we don't care
+    /* shift components to the correct place in pixel */
+    *rgb = ( red   << (long) surface->format->Rshift) | /* red */
+            ( blue  << (long) surface->format->Bshift ) | /* green */
+            ( green << (long) surface->format->Gshift ) | /* blue */
+            ( 0   << (long) surface->format->Ashift);
+}
+
 //transfers data from the AVPicture written to by swscale to a surface
 void WritePicture2Surface(AVPicture *picture, SDL_Surface *surface)
 {
 	/* AVPicture initialized with PIX_FMT_RGBA only fills pict->data[0]
 	 *  This however is only in {R,G,B, A} format. So we just copy the data over. 
 	 */
-	uint32_t *rgb = surface->pixels;
-	int BytesPerPixel =0;
-	if(RGBA)
-		BytesPerPixel=4;
-	else
-		BytesPerPixel=3;
-	int64_t size = surface->w*surface->h*BytesPerPixel;
-	int64_t ix=0;
-	while(ix<size)
+	/* Loop unrolling:
+	 * 	We define a blocksize, and so we increment the index counter by blocksize*rgbstep
+	 * 	All common resolutions are nicely divisible by 8(because 8 is a power of 2...)
+	 *  An uncommon resolution  could have between 1 and 7 bytes left to convert... 
+	 *   which I guess we'll leave alone. Its just 1-2 pixels in the lower right corner.
+	 *  So we repeat the same actions blocksize times.  
+	 */
+	int64_t   blocksize     = 8;
+	uint32_t *rgb           = surface->pixels;
+	int       BytesPerPixel = RGBSTEP;
+	int64_t   size          = surface->w*surface->h*BytesPerPixel;
+	int64_t   ix            = 0;
+	int64_t   blocklimit    = (size/blocksize)*blocksize;  
+	while(ix<blocklimit)
 	{
-		uint8_t red   = picture->data[0][ix]; 
-		uint8_t green = picture->data[0][ix+1];
-		uint8_t blue  = picture->data[0][ix+2];
-		//skip the alpha... we don't care
-        /* shift components to the correct place in pixel */
-        *rgb = ( red   << (long) surface->format->Rshift) | /* red */
-                ( blue  << (long) surface->format->Bshift ) | /* green */
-                ( green << (long) surface->format->Gshift ) | /* blue */
-                ( 0   << (long) surface->format->Ashift);
-        /* goto next pixel */
-        rgb++;
-        /* this increments our index value, depending on the format we use*/
-		if(RGB24)
-	    {
-	        ix+=3;
-	    }
-	    else if(RGBA)
-	    {
-	    	ix+=4;
-	    }	    
+		//this will be unrolled by the compiler, meaning that we do less comparisons by a factor of blocksize
+		int i =0;
+		for(;i<blocksize;i++)
+		{
+			jamPixels(ix, picture, rgb, surface);
+			rgb++;
+			ix+=RGBSTEP;
+		}	
 	}
 }
 
     int filled =0;
     len1=0;
     int co = 0;
-    for(;co<2;co++)
+    for(;;)
     {
     	if(movie->paused!=movie->audio_paused)
     	{
     		pauseBuffer(movie->channel);
     		movie->audio_paused=movie->paused;
     		if(movie->audio_paused)
-    			goto closing;
+    			continue;
     	}
-       
+        if(movie->paused)
+        {
+        	SDL_Delay(10);
+        	continue;
+        }
         //check if the movie has ended
-        if(movie->stop)
+        if(movie->stop || movie->audioq.abort_request)
         {
             stopBuffer(movie->channel);
             goto closing;
         }
+        
+        
         //fill up the buffer
         while(movie->audio_pkt_size > 0)
         {
             movie->channel = chan;
             filled=0;
             len1=0;
-            goto closing;
         }
 		
         //either buffer filled or no packets yet
         /* read next packet */
         if (packet_queue_get(&movie->audioq, pkt, 1) <= 0)
         {
-            goto closing;
+        	SDL_Delay(10);
+            continue;
         }
         
         if(pkt->data == flush_pkt.data)
         {
             avcodec_flush_buffers(dec);
-            goto closing;
+            SDL_Delay(10);
+            continue;
         }
       
         movie->audio_pts      = pkt->pts;
         packet_queue_init(&movie->audioq);
         movie->audio_mutex = SDL_CreateMutex();
         soundStart();
+        movie->audio_tid = SDL_CreateThread(audio_thread, movie);
         break;
     case CODEC_TYPE_VIDEO:
         if(movie->replay)
     {
     case CODEC_TYPE_AUDIO:
         packet_queue_abort(&movie->audioq);
+        SDL_WaitThread(movie->audio_tid, NULL);
         soundEnd();
         memset(&movie->audio_buf1, 0, sizeof(movie->audio_buf1));
         packet_queue_flush(&movie->audioq);
         channels = enc->channels;
         if(!movie->replay)
         {
-	        if (soundInit  (freq, -16, channels, 1024, movie->_tstate) < 0)
+	        if (soundInit  (freq, -16, channels, 1024) < 0)
 	        {
 	            RAISE(PyExc_SDLError, SDL_GetError ());
 	        }
             movie->seek_req = 0;
         }
         /* if the queue are full, no need to read more */
-        if ((movie->audioq.size > MAX_AUDIOQ_SIZE) || //yay for short circuit logic testing
+        if ( //yay for short circuit logic testing
                 (movie->videoq.size > MAX_VIDEOQ_SIZE ))
         {
             /* wait 10 ms */
                 {
                     video_render(movie);
                 }
-                if(movie->audioq.size > MAX_AUDIOQ_SIZE && movie->audio_st)
+                /*if(movie->audioq.size > MAX_AUDIOQ_SIZE && movie->audio_st)
                 {
                     audio_thread(movie);
-                }
+                }*/
             }
             continue;
         }
             }
         if(movie->video_st)
             video_render(movie);
-        if(movie->audio_st)
-            audio_thread(movie);
+        /*if(movie->audio_st)
+            audio_thread(movie);*/
         if(movie->sub_st)
         	subtitle_render(movie);
         if(co<2)

File src/_gmovie.h

View file
 #define RGB24 1
 #define RGBA  0
 
+#if RGB24
+	#define RGBSTEP 3
+#else
+	#define RGBSTEP 4
+#endif
+
 #define BPP 1
 
 //included from ffmpeg header files, as the header file is not publically available.

File src/_gsound.c

View file
 
 double getAudioClock(void)
 {
-    SDL_mutexP(ainfo.mutex);//lock
+    //SDL_mutexP(ainfo.mutex);//lock
     int bytes_per_sec = ainfo.channels*ainfo.sample_rate*2;
     double pts = ainfo.audio_clock;
     pts -= (double) ainfo.current_frame_size/(double) bytes_per_sec;
-    SDL_mutexV(ainfo.mutex);
+    //SDL_mutexV(ainfo.mutex);
     return pts;
 }