Commits

Anonymous committed fd164a2

Moved code-base into threaded mode, fixed basic threading issues.
Fixed stop, pause, and play issues.

Comments (0)

Files changed (3)

  void packet_queue_init(PacketQueue *q)
 {
     if(!q)
+    {
+		DECLAREGIL
+		GRABGIL    	
     	q=(PacketQueue *)PyMem_Malloc(sizeof(PacketQueue));
+  		RELEASEGIL
+    }
     if(!q->mutex)
 	    q->mutex = SDL_CreateMutex();
     if(!q->cond)
     AVPacketList *pkt, *pkt1;
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_LockMutex(q->mutex)	
+		SDL_LockMutex(q->mutex);
 #endif    
     for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
         pkt1 = pkt->next;
         av_free_packet(&pkt->pkt);
-        av_freep(&pkt);
+        PyMem_Free(&pkt);
     }
     q->last_pkt = NULL;
     q->first_pkt = NULL;
     q->size = 0;
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_UnlockMutex(q->mutex)	
+		SDL_UnlockMutex(q->mutex);	
 #endif
 }
 
 {
     AVPacketList *pkt1;
 
-	
-    pkt1 = av_malloc(sizeof(AVPacketList));
+	DECLAREGIL
+	GRABGIL
+    pkt1 = PyMem_Malloc(sizeof(AVPacketList));
+    RELEASEGIL
     if (!pkt1)
         return -1;
     pkt1->pkt = *pkt;
 
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_LockMutex(q->mutex)	
+		SDL_LockMutex(q->mutex);	
 #endif
     if (!q->last_pkt)
 
 
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_UnlockMutex(q->mutex)	
+		SDL_UnlockMutex(q->mutex);	
 #endif
     return 0;
 }
 {
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_LockMutex(q->mutex)	
+		SDL_LockMutex(q->mutex);	
 #endif
     q->abort_request = 1;
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_UnlockMutex(q->mutex)	
+		SDL_UnlockMutex(q->mutex);	
 #endif
 }
 
     
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_LockMutex(q->mutex)	
+		SDL_LockMutex(q->mutex);
 #endif
     for(;;) {
         if (q->abort_request) {
             q->nb_packets--;
             q->size -= pkt1->pkt.size;
             *pkt = pkt1->pkt;
-            av_free(pkt1);
+            DECLAREGIL
+            GRABGIL
+            PyMem_Free(pkt1);
+            RELEASEGIL
             ret = 1;
             break;
         } else if (!block) {
     }
 #if THREADFREE!=1
 	if(q->mutex)
-		SDL_UnlockMutex(q->mutex)	
+		SDL_UnlockMutex(q->mutex);	
 #endif
     return ret;
 }
 int video_display(PyMovie *movie)
 {
 /*DECODE THREAD - from video_refresh_timer*/
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(movie);
 	double ret=1;
+#if THREADFREE!=1
+	SDL_LockMutex(movie->dest_mutex);
+#endif
 	VidPicture *vp = &movie->pictq[movie->pictq_rindex];
+    RELEASEGIL
     if(!vp->dest_overlay)
     {
     	video_open(movie, movie->pictq_rindex);
     {
     	ret=0;
     }
+#if THREADFREE !=1
+	SDL_UnlockMutex(movie->dest_mutex);
+#endif
+	GRABGIL
 	Py_DECREF(movie);
+	RELEASEGIL
 	return ret;
 }
 
 void video_image_display(PyMovie *is)
 {
+	/* Wrapped by video_display, which has a lock on the movie object */
+    DECLAREGIL
+    GRABGIL
     Py_INCREF( is);
+    RELEASEGIL
     SubPicture *sp;
     VidPicture *vp;
     AVPicture pict;
         vp->dest_rect.y = vp->ytop  + y;
         vp->dest_rect.w = width;
         vp->dest_rect.h = height;
-        //int64_t t_before = av_gettime();
         if(vp->overlay>0) 
-        {       
+        {      
+        	SDL_LockYUVOverlay(vp->dest_overlay); 
             SDL_DisplayYUVOverlay(vp->dest_overlay, &vp->dest_rect);
+        	SDL_UnlockYUVOverlay(vp->dest_overlay);
         }
         
     } 
     is->pictq_rindex= (is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE;
     is->pictq_size--;
     video_refresh_timer(is);
+    GRABGIL
     Py_DECREF( is);
+	RELEASEGIL
 }
 
  int video_open(PyMovie *is, int index){
     int w,h;
+    DECLAREGIL
+    GRABGIL
     Py_INCREF( is);
-    
+    RELEASEGIL
     w = is->video_st->codec->width;
     h = is->video_st->codec->height;
 
     vp->width = w;
     is->height = h;
     vp->height = h;
-
+	GRABGIL
     Py_DECREF( is);
+    RELEASEGIL
     return 0;
 }
 
  void video_refresh_timer(PyMovie* movie)
 {
 /*moving to DECODE THREAD, from queue_frame*/
-	
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(movie);
+    RELEASEGIL
     double actual_delay, delay, sync_threshold, ref_clock, diff;
 	VidPicture *vp;
 	
 	    if (actual_delay < 0.010) {
 	        /* XXX: should skip picture */
 	        actual_delay = 0.010;
-	    }	
+	    }
+	    GRABGIL
 		movie->timing = (actual_delay*500.0)+0.5;
+    	RELEASEGIL
     }
+    GRABGIL
     Py_DECREF(movie);
+	RELEASEGIL
 }
 
  int queue_picture(PyMovie *movie, AVFrame *src_frame)
 {
 /*Video Thread LOOP*/
-
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(movie);
+    RELEASEGIL
     int dst_pix_fmt;
     AVPicture pict;
     VidPicture *vp;
         /* get a pointer on the bitmap */
         
         dst_pix_fmt = PIX_FMT_YUV420P;
-            
+           
         SDL_LockYUVOverlay(vp->dest_overlay);
 
         pict.data[0] = vp->dest_overlay->pixels[0];
 		movie->pictq_size++;
 		vp->ready=1;
     }
-	
+	GRABGIL
 	Py_DECREF(movie);
+    RELEASEGIL
     return 0;
 }
 
 
  void update_video_clock(PyMovie *movie, AVFrame* frame, double pts1) {
+	DECLAREGIL
+	GRABGIL
+	Py_INCREF(movie);
+	RELEASEGIL
 	double frame_delay, pts;
 
     pts = pts1;
     movie->video_clock += frame_delay;
 
 	movie->pts = pts;
+	GRABGIL
+	Py_INCREF(movie);
+	RELEASEGIL
 }
 
  int audio_write_get_buf_size(PyMovie *movie)
 {
+	DECLAREGIL
+	GRABGIL
     Py_INCREF(movie);
-   
+    RELEASEGIL
+    
     int temp = movie->audio_buf_size - movie->audio_buf_index;
+   	GRABGIL
    	Py_DECREF(movie);
+    RELEASEGIL
     return temp;
 }
 
 /* get the current audio clock value */
  double get_audio_clock(PyMovie *is)
 {
+	DECLAREGIL
+	GRABGIL
     Py_INCREF( is);
+    RELEASEGIL
     double pts;
     int hw_buf_size, bytes_per_sec;
 
     }
     if (bytes_per_sec)
         pts -= (double)hw_buf_size / bytes_per_sec;
+    GRABGIL
     Py_DECREF( is);
+    RELEASEGIL
     return pts;
 }
 
 /* get the current external clock value */
  double get_external_clock(PyMovie *is)
 {
+	DECLAREGIL
+	GRABGIL
     Py_INCREF( is);
+    RELEASEGIL
     int64_t ti;
     ti = av_gettime();
     double res = is->external_clock + ((ti - is->external_clock_time) * 1e-6);
+    GRABGIL
     Py_DECREF( is);
+	RELEASEGIL
     return res;
 }
 
 /* get the current master clock value */
  double get_master_clock(PyMovie *is)
 {
+	DECLAREGIL
+	GRABGIL
     Py_INCREF( is);
+    RELEASEGIL
     double val;
     
     if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
     } else {
         val = get_external_clock(is);
     }
+    GRABGIL
     Py_DECREF( is);
+	RELEASEGIL
     return val;
 }
 
 /* seek in the stream */
  void stream_seek(PyMovie *is, int64_t pos, int rel)
 {
+	DECLAREGIL
+	GRABGIL
     Py_INCREF( is);
+    RELEASEGIL
     if (!is->seek_req) {
         is->seek_pos = pos;
         is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
 
         is->seek_req = 1;
     }
+    GRABGIL
     Py_DECREF( is);
+	RELEASEGIL
 }
 
 /* pause or resume the video */
 void stream_pause(PyMovie *is)
 {
+	//DECLAREGIL
+	//GRABGIL
     Py_INCREF( is);
+    //RELEASEGIL
     is->paused = !is->paused;
     if (!is->paused) {
 
         
         is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
     }
+    //GRABGIL
     Py_DECREF( is);
+	//RELEASEGIL
 }
 
 
 int subtitle_thread(void *arg)
 {
+	DECLAREGIL
     PyMovie *movie = arg;
-    PyGILState_STATE gstate;
-	gstate = PyGILState_Ensure();
-    
+    GRABGIL
     Py_INCREF( movie);
-	PyGILState_Release(gstate);
-    
+	RELEASEGIL
+	    
     SubPicture *sp;
     AVPacket pkt1, *pkt = &pkt1;
     int len1, got_subtitle;
 
     
     for(;;) {
-		gstate = PyGILState_Ensure();
         while (movie->paused && !movie->subtitleq.abort_request) {
             SDL_Delay(10);
 	    }
         if (packet_queue_get(&movie->subtitleq, pkt, 1) < 0)
         {    
-			PyGILState_Release(gstate);
             break;
         }
         if(pkt->data == flush_pkt.data){
             avcodec_flush_buffers(movie->subtitle_st->codec);
-			PyGILState_Release(gstate);
             continue;
         }
         SDL_LockMutex(movie->subpq_mutex);
 
         if (movie->subtitleq.abort_request)
         {
-			PyGILState_Release(gstate);
             goto the_end;
         }
         sp = &movie->subpq[movie->subpq_windex];
 //        if (step)
 //            if (cur_stream)
 //                stream_pause(cur_stream);
-		PyGILState_Release(gstate);
 	
     }
  
  the_end:
-	gstate = PyGILState_Ensure();
+	GRABGIL
     Py_DECREF( movie);
-	PyGILState_Release(gstate);
+	RELEASEGIL
     return 0;
 }
 
  int synchronize_audio(PyMovie *is, short *samples,
                              int samples_size1, double pts)
 {
+	
     Py_INCREF( is);
     
     int n, samples_size;
 /* open a given stream. Return 0 if OK */
  int stream_component_open(PyMovie *movie, int stream_index)
 {
-    
+    DECLAREGIL
+    GRABGIL
     Py_INCREF( movie);
+    RELEASEGIL
     AVFormatContext *ic = movie->ic;
     AVCodecContext *enc;
     AVCodec *codec;
         movie->video_last_pts_time=av_gettime();
 
         packet_queue_init(&movie->videoq);
-      	if(!THREADFREE)
-	        movie->video_tid = SDL_CreateThread(video_thread, movie);
-        break;
+      	break;
     case CODEC_TYPE_SUBTITLE:
         movie->subtitle_stream = stream_index;
         
     default:
         break;
     }
+    GRABGIL
     Py_DECREF( movie);
+    RELEASEGIL
     return 0;
 }
 
  void stream_component_close(PyMovie *is, int stream_index)
 {
+	DECLAREGIL
+	GRABGIL
     if(is->ob_refcnt!=0)Py_INCREF( is);
+	RELEASEGIL
     AVFormatContext *ic = is->ic;
     AVCodecContext *enc;
 
         break;
     }
 
-    if(is->ob_refcnt!=0){
-    	Py_DECREF( is);}
+	GRABGIL
+    if(is->ob_refcnt!=0)
+    {
+    	Py_DECREF( is);
+    }
+	RELEASEGIL
 }
 
 
 {
     if (!is)
         return NULL;
+    DECLAREGIL
+    GRABGIL
     Py_INCREF(is);
+	RELEASEGIL
 	AVFormatContext *ic;
     int err, i, ret, video_index, audio_index, subtitle_index;
     AVFormatParameters params, *ap = &params;
 	
     err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
     if (err < 0) {
+    	GRABGIL
         PyErr_Format(PyExc_IOError, "There was a problem opening up %s", is->filename);
+        RELEASEGIL
         ret = -1;
         goto fail;
     }
     is->ic = ic;
     err = av_find_stream_info(ic);
     if (err < 0) {
+    	GRABGIL
         PyErr_Format(PyExc_IOError, "%s: could not find codec parameters", is->filename);
+        RELEASEGIL
         ret = -1;
         goto fail;
     }
             timestamp += ic->start_time;
         ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
         if (ret < 0) {
+        	GRABGIL
             PyErr_Format(PyExc_IOError, "%s: could not seek to position %0.3f", is->filename, (double)timestamp/AV_TIME_BASE);
+        	RELEASEGIL
         }
     }
     for(i = 0; i < ic->nb_streams; i++) {
         stream_component_open(is, subtitle_index);
     }*/
     if (is->video_stream < 0 && is->audio_stream < 0) {
+    	GRABGIL
         PyErr_Format(PyExc_IOError, "%s: could not open codecs", is->filename);
+        RELEASEGIL
         ret = -1;		
 		goto fail;
     }
 
 	if(ret!=0)
 	{
+		GRABGIL
 		//throw python error
 		PyObject *er;
 		er=PyErr_Occurred();
 		}
 		Py_DECREF(er);
 		Py_DECREF(is);
+		RELEASEGIL
 		return is;
 	}
-
+	GRABGIL
 	Py_DECREF(is);
+    RELEASEGIL
     return is;
 }
 
-
  void stream_close(PyMovie *is)
 {
 	if(is->ob_refcnt!=0) Py_INCREF(is);
     AVFormatContext *ic = is->ic;
     int start_index, stream_index;
     AVStream *st;
-
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(is);
+	RELEASEGIL
 	
     if (codec_type == CODEC_TYPE_VIDEO)
         start_index = is->video_stream;
  the_end:
     stream_component_close(is, start_index);
     stream_component_open(is, stream_index);
-    
+    GRABGIL
     Py_DECREF(is);
+	RELEASEGIL
 }
 
 
 /* this thread gets the stream from the disk or the network */
- int decoder(PyMovie *is)
+ int decoder(void *arg)
 {
+	PyMovie *is = arg;
+	DECLAREGIL
+	GRABGIL
     Py_INCREF( is);
+    //RELEASEGIL
     AVFormatContext *ic;
     int ret;
     AVPacket pkt1, *pkt = &pkt1;
 	}
 	is->pictq_size=is->pictq_rindex=is->pictq_windex=0;
 	packet_queue_flush(&is->videoq);
-		
+	GRABGIL		
     Py_DECREF( is);
+    RELEASEGIL
     return 0;
 }
 
 int video_render(PyMovie *movie)
 {
-    
+    DECLAREGIL
+    GRABGIL
     Py_INCREF( movie);
+    RELEASEGIL
     AVPacket pkt1, *pkt = &pkt1;
     int len1, got_picture;
     AVFrame *frame= avcodec_alloc_frame();
     }
     while(0);
  the_end:
+ 	GRABGIL
     Py_DECREF(movie);
+    RELEASEGIL
     av_free(frame);
     return 0;
 }
 {\
     ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
 }
+
+
 //sets the module to single-thread mode.
-#define THREADFREE 1
+#define THREADFREE 0
 
+#if THREADFREE!=1
+	#define DECLAREGIL PyGILState_STATE gstate;
+	#define GRABGIL    gstate=PyGILState_Ensure();
+	#define RELEASEGIL PyGILState_Release(gstate);
+#else
+	#define DECLAREGIL 
+	#define GRABGIL   
+	#define RELEASEGIL
+#endif
 //backwards compatibility with blend_subrect
 #define BPP 1
 
 int stream_component_open(PyMovie *is, int stream_index); //TODO: break down into separate functions
 void stream_component_close(PyMovie *is, int stream_index);
 int decode_thread(void *arg);
-int decoder(PyMovie *is);
+int decoder(void *arg);
 PyMovie *stream_open(PyMovie *is, const char *filename, AVInputFormat *iformat);
 void stream_close(PyMovie *is);
 void stream_cycle_channel(PyMovie *is, int codec_type);
 
  PyMovie*  _movie_init_internal(PyMovie *self, const char *filename, SDL_Surface *surf)
 {
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(self);
+	RELEASEGIL
 	//already malloced memory for PyMovie.
 	if(!surf)
 	{
 		self->dest_surface=surf;
 	}
 	self->start_time = AV_NOPTS_VALUE;
-	AVInputFormat *iformat;
-	self=stream_open(self, filename, iformat);
+	self=stream_open(self, filename, NULL);
 	if(!self)
 	{
+		GRABGIL
 		PyErr_SetString(PyExc_IOError, "stream_open failed");
         Py_DECREF(self);
-        Py_RETURN_NONE;
-    }	
+		RELEASEGIL
+        return self;
+    }
+    GRABGIL	
 	PySys_WriteStdout("Movie->filename: %s\n", self->filename);
 	Py_DECREF(self);
+	RELEASEGIL
 	return self;
 }
 
  int _movie_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
+	DECLAREGIL
+	GRABGIL
 	Py_INCREF(self);
+	RELEASEGIL
 	const char *c;
+	GRABGIL
 	if (!PyArg_ParseTuple (args, "s", &c))
     {
         PyErr_SetString(PyExc_TypeError, "No valid arguments");
+    	RELEASEGIL
     	return -1;
     }	
+    RELEASEGIL
 	self = _movie_init_internal(self, c, NULL);
+	GRABGIL
 	PyObject *er;
     er = PyErr_Occurred();
+    Py_XINCREF(er);
     if(er)
     {
         PyErr_Print();
     }
+    Py_XDECREF(er);
+    RELEASEGIL
     if(!self)
     {
+    	GRABGIL
         PyErr_SetString(PyExc_IOError, "No movie object created.");
         PyErr_Print();
         Py_DECREF(self);
+        RELEASEGIL
         return -1;
     }
+    GRABGIL
     Py_DECREF(self);
     PySys_WriteStdout("Returning from _movie_init\n");
+    RELEASEGIL
     return 0;
 }   
 
  PyObject* _movie_repr (PyMovie *movie)
 {
     /*Eventually add a time-code call */
+    DECLAREGIL
+    GRABGIL
     Py_INCREF(movie);
     char buf[100];
-    //PySys_WriteStdout("_movie_repr: %10s\n", movie->filename); 
     PyOS_snprintf(buf, sizeof(buf), "(Movie: %s)", movie->filename);
     Py_DECREF(movie);
-    return PyString_FromString(buf);
+    PyObject *buffer = PyString_FromString(buf);
+    RELEASEGIL
+    return buffer;
 }
  PyObject* _movie_play(PyMovie *movie, PyObject* args)
 {
+//	DECLAREGIL
 	Py_INCREF(movie);
     int loops;
     if(!PyArg_ParseTuple(args, "i", &loops))
     movie->paused = 0;
     movie->playing = 1;
     SDL_UnlockMutex(movie->dest_mutex);
-    while((loops-1)!=-1)
-    {
-    	decoder(movie);
-    	PySys_WriteStdout("Loops: %i\n", loops);
-    	loops--;
-    	if(loops==1)
-    	{
-    		PySys_WriteStdout("Second Loop Around\n");
-    	}
-    	movie=stream_open(movie, movie->filename, NULL);
-    	movie->paused=0;
-    }
+ 	int state;
+	//GRABGIL
+	movie->parse_tid = SDL_CreateThread(decoder, movie);
     Py_DECREF(movie);
+    //RELEASEGIL
     Py_RETURN_NONE;
 }
 
  PyObject* _movie_stop(PyMovie *movie)
 {
+	//DECLAREGIL
+	//GRABGIL
     Py_INCREF(movie);
-    SDL_LockMutex(movie->dest_mutex);
+    //SDL_LockMutex(movie->dest_mutex);
+    //RELEASEGIL
     stream_pause(movie);
     movie->seek_req = 1;
     movie->seek_pos = 0;
     movie->seek_flags =AVSEEK_FLAG_BACKWARD;
-    SDL_UnlockMutex(movie->dest_mutex);  
+    //SDL_UnlockMutex(movie->dest_mutex);  
     Py_DECREF(movie);
+	//RELEASEGIL
     Py_RETURN_NONE;
 }