1. pygame
  2. Untitled project
  3. pygame

Commits

zeroth  committed 198711a

Massive updates to ff_movie.c, lots of memory holes fixed. Just need to
do python interface functions now.

Also merged with trunk revision 2185

  • Participants
  • Parent commits 79e954a
  • Branches tylerthemovie

Comments (0)

Files changed (4)

File Setup.in

View file
  • Ignore whitespace
 
 
 
-#experimental new movie movie. requires libavcodec and libavformat.
-#add any necessary compile flags to this line and uncomment.
-#movieext src/movie.c  src/ffmovie.c $(SDL) -lavcodec -lavformat
-
 #these modules are required for pygame to run. they only require
 #SDL as a dependency. these should not be altered
 

File lib/midi.py

  • Ignore whitespace
File contents unchanged.

File src/ff_movie.c

View file
  • Ignore whitespace
 
 /*internal functions for video playing. Not accessible to Python */
 
+int __Y[256];
+int __CrtoR[256];
+int __CrtoG[256];
+int __CbtoG[256];
+int __CbtoB[256];
+
+void initializeLookupTables() {
+
+    float f;
+    int i;
+
+    for(i=0; i<256; i++) {
+
+        f = ( float)i;
+
+        __Y[i] = (int)( 1.164 * ( f-16.0) );
+
+        __CrtoR[i] = (int)( 1.596 * ( f-128.0) );
+
+        __CrtoG[i] = (int)( 0.813 * ( f-128.0) );
+        __CbtoG[i] = (int)( 0.392 * ( f-128.0) );
+
+        __CbtoB[i] = (int)( 2.017 * ( f-128.0) );
+    }
+}
+
+
 /* packet queue handling */
 static void packet_queue_init(PacketQueue *q)
 {
     int i;
 
     //vp = &is->pictq[is->pictq_rindex];
-    PyObject *pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
+    PyVideoStream *pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    PyINCREF((PyObject *)pvs);
+    
     vp = &pvs->pictq[pvs->pictq_rindex];
     if (pvs->out_surf || pvs->bmp) {
         /* XXX: use variable in the frame */
         
         if (is->subtitle_stream>-1)
         {
-            PyObject *pyon = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-            PyINCREF(pyon);
-            PySubStream * pss = _get_sub_stream(pyo);
-            PyDECREF(pyon);
+            PySubtitleStream *pss;
+            pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+            PyINCREF((PyObject *)pss);
+            
             if (pss->subpq_size > 0)
             {
                 sp = &pss->subpq[pss->subpq_rindex];
 
                         SDL_UnlockYUVOverlay (pvs->bmp);
                     }
-                    //TODO: add for writing to pygame.Surface
                     else
                     {
+                        if (pvs->out_surf->flags & SDL_OPENGL && !(pvs->out_surf->flags & (SDL_OPENGLBLIT & ~SDL_OPENGL)))
+                                return RAISE (PyExc_SDLError,
+                                              "Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)");
+                        SDL_LockSurface(pvs->out_surf);
+                        pict.data[0] = pvs->out_surf->pixels[0];
+                        pict.data[1] = pvs->out_surf->pixels[1];
+                        pict.data[2] = pvs->out_surf->pixels[2];
+
+                        pict.linesize[0] = pvs->out_surf->pitch;
+                        pict.linesize[1] = pvs->out_surf->pitch;
+                        pict.linesize[2] = pvs->out_surf->pitch;
+
+                        for (i = 0; i < pss->sub.num_rects; i++)
+                            //TODO:check if blend_subrect works with RGB
+                            blend_subrect(&pict, pss->sub.rects[i],
+                                          pvs->out_surf->w, pvs->out_surf->h);
+                                              
                         
                     }
                 }
             }
+        Py_DECREF((PyObject *)pss);
         }
 
 
         {       
             SDL_DisplayYUVOverlay(pvs->bmp, &rect);
         }
+        
     } else {
 #if 0
         fill_rectangle(screen,
                        QERGB(0x00, 0x00, 0x00));
 #endif
     }
+    Py_DECREF((PyObject *)pvs);
 }
 
+
 static inline int compute_mod(int a, int b)
 {
     a = a % b;
 static int video_open(PyMovie *is){
     int w,h;
 
-    PyObject *pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
+    PyVideoStream *pvs;
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    PyINCREF((PyObject *) pvs);
     
     w = pvs->video_st->codec->width;
     h = pvs->video_st->codec->height;
         /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
         screen = SDL_SetVideoMode(w, h, 24, flags);
         #endif
-        pvs->out_surf=PySurface_New(screen);
+        pvs->out_surf=(SDL_Surface *)PyMem_Malloc(sizeof(SDL_Surface));
         if (!pvs->out_surf)
-            return RAISE (PyExc_SDLError, "Could not create pygame.Surface object");
+            return RAISE (PyExc_SDLError, "Could not create Surface object");
     }
 
 
     pvs->width = w;
     pvs->height = h;
-
+    PyDECREF((PyObject *) pvs);
     return 0;
 }
 
 /* display the current picture, if any */
 static void video_display(PyMovie *is)
 {
-    PyObject *pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
+    PyVideoStream *pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *) pvs);
+    
     if (!pvs->out_surf||!pvs->bmp)
         video_open(is);
 
     else if (is->video_stream>0)
         video_image_display(is);
+    Py_DECREF((PyObject *) pvs);
 }
 
 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
 /* get the current audio clock value */
 static double get_audio_clock(PyMovie *is)
 {
-    //TODO: add offset functionality
     double pts;
     int hw_buf_size, bytes_per_sec;
 
-    PyObject *pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    PyAudioStream * pas = _get_audio_stream(pyo);
-    PyDECREF(pyo);
-
+    PyAudioStream *pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF((PyObject *) pas);
+    
     pts = pas->audio_clock;
     hw_buf_size = audio_write_get_buf_size(is);
     bytes_per_sec = 0;
     }
     if (bytes_per_sec)
         pts -= (double)hw_buf_size / bytes_per_sec;
+    Py_DECREF((PyObject *) pas);
     return pts;
 }
 
 /* get the current video clock value */
 static double get_video_clock(PyMovie *is)
 {
-    //TODO: add offset functionality
     double delta;
-    PyObject *pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);    
+    PyVideoStream *pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *)pvs);
+    
     if (pvs->paused) {
         delta = 0;
     } else {
         delta = (av_gettime() - pvs->video_current_pts_time) / 1000000.0;
     }
-    return pvs->video_current_pts + delta;
+    double temp = pvs->video_current_pts+delta;
+    Py_DECREF((PyObject *) pvs);
+    return temp;
 }
 
 /* get the current external clock value */
 /* get the current master clock value */
 static double get_master_clock(PyMovie *is)
 {
-    //TODO:fix syncing issues here
+    
     double val;
-    PyObject *pyo;
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo); 
+    PyVideoStream *pvs;
+    PyAudioStream *pas;
     
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    PyAudioStream * pas = _get_audio_stream(pyo);
-    PyDECREF(pyo)
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *)pvs);
     
-
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF((PyObject *)pas);
+    
     if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
         if (pvs->video_st)
             val = get_video_clock(is);
     } else {
         val = get_external_clock(is);
     }
+    Py_DECREF((PyObject *)pvs);
+    Py_DECREF((PyObject *)pas);
     return val;
 }
 
 {
     is->paused = !is->paused;
     if (!is->paused) {
-        PyObject *pyo;
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-        PyINCREF(pyo);
-        PyVideoStream * pvs = _get_video_stream(pyo);
-        PyDECREF(pyo); 
+        PyObject *pvs;
+        pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+        Py_INCREF((PyObject *)pvs);
         
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-        PyINCREF(pyo);
-        PyAudioStream * pas = _get_audio_stream(pyo);
-        PyDECREF(pyo)
+        pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+        Py_INCREF((PyObject *)pas);
 
         pvs->video_current_pts = get_video_clock(is);
         
         is->frame_timer += (av_gettime() - pvs->video_current_pts_time) / 1000000.0;
+        Py_DECREF((PyObject *) pvs);
+        Py_DECREF((PyObject *) pas);
     }
 }
 
     }
     is->frame_last_pts = frame_current_pts;
 
-    PyObject *pyo;
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    PyVideoStream * pvs = _get_video_stream(pyo);
-    PyDECREF(pyo); 
-        
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    PyAudioStream * pas = _get_audio_stream(pyo);
-    PyDECREF(pyo)
-    
-
+    PyVideoStream *pvs;
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *)pvs);
+       
+    PyAudioStream *pas; 
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF((PyObject *)pas);
+   
     /* update delay to follow master synchronisation source */
     if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && pas->audio_st) ||
          is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
     printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
             delay, actual_delay, frame_current_pts, -diff);
 #endif
-
+    Py_DECREF((PyObject *) pvs);
+    Py_DECREF((PyObject *) pas);
     return actual_delay;
 }
 
 
     SubPicture *sp, *sp2;
 
-    PyObject      *pyo;
     PyVideoStream *pvs;
     PyAudioStream *pas;
-    PySubStream   *pss;
+    PySubtitleStream   *pss;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo); 
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF(pvs); 
         
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    pas = _get_audio_stream(pyo);
-    PyDECREF(pyo)
-
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF(pas);
 
     if (pvs->video_st) {
         if (pvs->pictq_size == 0) {
             /* if no picture, need to wait */
-            //TODO:check schedule_refresh
             schedule_refresh(is, 1);
         } else {
             /* dequeue the picture */
             schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5));
 
             if(is->subtitle_stream>-1) {
-                pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-                PyINCREF(pyo);
-                pss = _get_sub_stream(pyo);
-                PyDECREF(pyo)
-
+                pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+                Py_INCREF(pss);
+                
                 if (pss->subtitle_stream_changed) {
                     SDL_LockMutex(pss->subpq_mutex);
 
                         }
                     }
                 }
+                Py_DECREF((PyObject *)pss);
             }
 
             /* display picture */
     } else {
         schedule_refresh(is, 100);
     }
-    /*if (show_status) {
-        static int64_t last_time;
-        int64_t cur_time;
-        int aqsize, vqsize, sqsize;
-        double av_diff;
-
-        cur_time = av_gettime();
-        if (!last_time || (cur_time - last_time) >= 500 * 1000) {
-            aqsize = 0;
-            vqsize = 0;
-            sqsize = 0;
-            if (is->audio_st)
-                aqsize = is->audioq.size;
-            if (is->video_st)
-                vqsize = is->videoq.size;
-            if (is->subtitle_st)
-                sqsize = is->subtitleq.size;
-            av_diff = 0;
-            if (is->audio_st && is->video_st)
-                av_diff = get_audio_clock(is) - get_video_clock(is);
-            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB    \r",
-                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
-            fflush(stdout);
-            last_time = cur_time;
-        }
-    }*/
+    Py_DECREF((PyObject *) pvs);
+    Py_DECREF((PyObject *) pas);
 }
 
 /* allocate a picture (needs to do that in main thread to avoid
 {
     PyMovie *is = opaque;
     VideoPicture *vp;
-
-    PyObject      *pyo;
+    
     PyVideoStream *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
-
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF(pvs);
+    
     vp = &pvs->pictq[pvs->pictq_windex];
 
     if (pvs->bmp)
         SDL_FreeYUVOverlay(pvs->bmp);
-
+    if (pvs->out_surf)
+        SDL_FreeSurface(pvs->out_surf);
 #if 0
     /* XXX: use generic function */
     /* XXX: disable overlay if no hardware acceleration or if RGB format */
         break;
     }
 #endif
-    pvs->bmp = SDL_CreateYUVOverlay(pvs->video_st->codec->width,
+    if(is->overlay>0)
+    {
+        pvs->bmp = SDL_CreateYUVOverlay(pvs->video_st->codec->width,
                                    pvs->video_st->codec->height,
                                    SDL_YV12_OVERLAY,
                                    screen);
+    }
+    else
+    {
+        
+    }
     vp->width = pvs->video_st->codec->width;
     vp->height = pvs->video_st->codec->height;
 
     vp->allocated = 1;
     SDL_CondSignal(pvs->pictq_cond);
     SDL_UnlockMutex(pvs->pictq_mutex);
+    Py_DECREF((PyObject *) pvs);
 }
 
 /**
 {
     VideoPicture *vp;
 
-    PyObject      *pyo;
     PyVideoStream *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF(pvs);
 
     int dst_pix_fmt;
     AVPicture pict;
         return -1;
 
     vp = &pvs->pictq[pvs->pictq_windex];
-    //TODO: here, check for which one to allocate, either overlay or pygame.Surface
+
     /* alloc or resize hardware picture buffer */
     if (!pvs->bmp || !pvs->out_surf ||
         vp->width != pvs->video_st->codec->width ||
         /* get a pointer on the bitmap */
         if(is->overlay>0)
         {
+            dst_pix_fmt = PIX_FMT_YUV422;
+              
             SDL_LockYUVOverlay (pvs->bmp);
 
-            dst_pix_fmt = PIX_FMT_YUV420P;
             pict.data[0] = pvs->bmp->pixels[0];
             pict.data[1] = pvs->bmp->pixels[2];
             pict.data[2] = pvs->bmp->pixels[1];
             /* update the bitmap content */
             SDL_UnlockYUVOverlay(pvs->bmp);
         }
-        //TODO: add equivalent write to Surface, after conversion to RGB
+        else
+        {
+            dst_pix_fmt = PIX_FMT_RGB48;
+              
+            SDL_LockSurface (pvs->out_surf);
+
+            pict.data[0] = pvs->out_surf->pixels[0];
+            pict.data[1] = pvs->out_surf->pixels[1];
+            pict.data[2] = pvs->out_surf->pixels[2];
+
+            pict.linesize[0] = pvs->out_surf->pitch;
+            pict.linesize[1] = pvs->out_surf->pitch;
+            pict.linesize[2] = pvs->out_surf->pitch;
+            sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
+            img_convert_ctx = sws_getCachedContext(img_convert_ctx,
+                pvs->video_st->codec->width, pvs->video_st->codec->height,
+                pvs->video_st->codec->pix_fmt,
+                pvs->video_st->codec->width, pvs->video_st->codec->height,
+                dst_pix_fmt, sws_flags, NULL, NULL, NULL);
+            if (img_convert_ctx == NULL) {
+                
+                PyErr_SetString(PyExc_MemoryError ,"Cannot initialize the conversion context.");
+                //fprintf(stderr, "Cannot initialize the conversion context\n");
+                //exit(1);
+            }
+            sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
+                      0, pvs->video_st->codec->height, pict.data, pict.linesize);
+            /* update the bitmap content */
+            SDL_UnlockSurface(pvs->out_surf);
+        }
+        
         vp->pts = pts;
 
         /* now we can update the picture count */
         pvs->pictq_size++;
         SDL_UnlockMutex(pvs->pictq_mutex);
     }
+    Py_DECREF((PyObject *) pvs);
     return 0;
 }
 
 
     pts = pts1;
 
-    PyObject      *pyo;
     PyVideoStream *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
-
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *) pvs);
+    
     if (pts != 0) {
         /* update video clock with pts, if present */
         pvs->video_clock = pts;
                ftype, pts, pts1);
     }
 #endif
+    Py_DECREF((PyObject *)pvs);
     return queue_picture(is, src_frame, pts);
 }
 
     AVFrame *frame= avcodec_alloc_frame();
     double pts;
 
-    PyObject      *pyo;
     PyVideoStream *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
-
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *)pvs);
+    
     for(;;) {
         while (pvs->paused && !pvs->videoq.abort_request) {
             SDL_Delay(10);
                 stream_pause(is);
     }
  the_end:
+    Py_DECREF((PyObject *) pvs);
     av_free(frame);
     return 0;
 }
     int i, j;
     int r, g, b, y, u, v, a;
 
-    PyObject      *pyo;
-    PySubStream   *pss;
+    PySubtitleStream   *pss;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-    PyINCREF(pyo);
-    pss = _get_sub_stream(pyo);
-    PyDECREF(pyo);
-
+    pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+    Py_INCREF((PyObject *)pss);
+    
     for(;;) {
         while (pss->paused && !pss->subtitleq.abort_request) {
             SDL_Delay(10);
 //                stream_pause(cur_stream);
     }
  the_end:
+    Py_DECREF((PyObject *) pss);
     return 0;
 }
 
     int n, samples_size;
     double ref_clock;
 
-    PyObject        *pyo;
     PyAudioStream   *pas;
     PyVideoStream   *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    pas = _get_audio_stream(pyo);
-    PyDECREF(pyo);
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF((PyObject *)pas);
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-    PyINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyDECREF(pyo);
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+    Py_INCREF((PyObject *)pvs);
 
     n = 2 * pas->audio_st->codec->channels;
     samples_size = samples_size1;
                         samples_end = (uint8_t *)samples + samples_size - n;
                         q = samples_end + n;
                         while (nb > 0) {
-                           //TODO: possible future bug here, with memcpy
+                           
                             memcpy(q, samples_end, n);
                             q += n;
                             nb -= n;
             pas->audio_diff_cum = 0;
         }
     }
-
+    Py_DECREF((PyObject *)pas);
+    Py_DECREF((PyObject *)pvs);
     return samples_size;
 }
 
 /* decode one audio frame and returns its uncompressed size */
 static int audio_decode_frame(PyMovie *is, double *pts_ptr)
 {
-    PyObject        *pyo;
     PyAudioStream   *pas;
-    PyVideoStream   *pvs;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    pas = _get_audio_stream(pyo);
-    PyDECREF(pyo);    
-
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF(pas);
+    
     AVPacket *pkt = &pas->audio_pkt;
     AVCodecContext *dec= pas->audio_st->codec;
     int n, len1, data_size;
     double pts;
 
-    
-
     for(;;) {
         /* NOTE: the audio packet can contain several frames */
         while (pas->audio_pkt_size > 0) {
                 int ostride[6]= {2};
                 int len= data_size/istride[0];
                 if (av_audio_convert(pas->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
-                    //TODO: remove this printf for a proper python error.
-                    printf("av_audio_convert() failed\n");
+                    PyErr_WarnEx(NULL, "av_audio_convert() failed", 1);
+                    //printf("av_audio_convert() failed\n");
                     break;
                 }
                 pas->audio_buf= pas->audio_buf2;
                 last_clock = pas->audio_clock;
             }
 #endif
+            Py_DECREF((PyObject *)pas);
             return data_size;
         }
 
             pas->audio_clock = av_q2d(pas->audio_st->time_base)*pkt->pts;
         }
     }
+    Py_DECREF((PyObject *) pas);
 }
 
 /* get the current audio output buffer size, in samples. With SDL, we
 static int audio_write_get_buf_size(PyMovie *is)
 {
 
-    PyObject        *pyo;
     PyAudioStream   *pas;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    pas = _get_audio_stream(pyo);
-    PyDECREF(pyo);
-
-    return pas->audio_buf_size - pas->audio_buf_index;
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF((PyObject *)pas);
+    
+    int temp = pas->audio_buf_size - pas->audio_buf_index;
+    Py_DECREF((PyObject *) pas);
+    return temp;
 }
 
 /* prepare a new audio buffer */
     int audio_size, len1;
     double pts;
 
-    PyObject        *pyo;
     PyAudioStream   *pas;
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-    PyINCREF(pyo);
-    pas = _get_audio_stream(pyo);
-    PyDECREF(pyo);
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+    Py_INCREF(pas);
 
     audio_callback_time = av_gettime();
 
         stream += len1;
         pas->audio_buf_index += len1;
     }
+    Py_DECREF((PyObject *) pas);
 }
 
 /* open a given stream. Return 0 if OK */
     /* prepare audio output */
     if (enc->codec_type == CODEC_TYPE_AUDIO) {
         
-        //TODO: add func _new_audio_stream
+        
         pas = _new_audio_stream();
+        Py_INCREF((PyObject *) pas);
         wanted_spec.freq = enc->sample_rate;
         wanted_spec.format = AUDIO_S16SYS;
         wanted_spec.channels = enc->channels;
         wanted_spec.callback = sdl_audio_callback;
         wanted_spec.userdata = is;
         if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
-            //TODO: replace with python exception
             RAISE(PyExc_SDLError, SDL_GetError ());
             //fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
-            return -1;
+            //return -1;
         }
         pas->audio_hw_buf_size = spec.size;
         pas->audio_src_fmt= SAMPLE_FMT_S16;
         avcodec_thread_init(enc, thread_count);
     enc->thread_count= thread_count;
     ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
+    
     switch(enc->codec_type) {
     case CODEC_TYPE_AUDIO:
         is->aud_stream_ix = stream_index;
         packet_queue_init(&pas->audioq);
         is->audio_stream=(int) PyList_Size(is->streams);
         PyList_Append(is->streams, (PyObject *)pas);
+        Py_DECREF((PyObject *) pas);
         SDL_PauseAudio(0);
         break;
     case CODEC_TYPE_VIDEO:
-        //TODO: add func _new_video_stream
+
         pvs = _new_video_stream();
+        Py_INCREF((PyObject *)pvs);
         is->vid_stream_ix = stream_index;
         pvs->video_st = ic->streams[stream_index];
 
         is->video_stream=(int) PyList_Size(is->streams);
         PyList_Append(is->streams, (PyObject *)pvs);        
 
+        Py_DECREF((PyObject *)pvs);
         break;
     case CODEC_TYPE_SUBTITLE:
         is->sub_stream_ix = stream_index;
-        //TODO: add func _new_sub_stream
+        
         pss = _new_sub_stream();
+        Py_INCREF((PyObject *) pss);
         pss->subtitle_st = ic->streams[stream_index];
         packet_queue_init(&pss->subtitleq);
 
         PyList_Append(is->streams, (PyObject *)pss); 
 
         pss->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
+        Py_DECREF((PyObject *) pss);
         break;
     default:
         break;
 
 static void stream_component_close(PyMovie *is, int stream_index)
 {
-    //TODO: need to do proper python deallocation of all the stuff in each of the stream structs.
     AVFormatContext *ic = is->ic;
     AVCodecContext *enc;
 
-    PyObject*      pyo;
     PyAudioStream* pas; 
     PyVideoStream* pvs;
-    PySubStream*   pss;
-
+    PySubtitleStream*   pss;
     if (stream_index < 0 || stream_index >= ic->nb_streams)
         return;
     enc = ic->streams[stream_index]->codec;
 
     switch(enc->codec_type) {
     case CODEC_TYPE_AUDIO:
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-        PyINCREF(pyo);
-        pas = _get_audio_stream(pyo);
-        PyDECREF(pyo);
+        pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+        Py_INCREF((PyObject *)pas);
+        
         packet_queue_abort(&pas->audioq);
 
         SDL_CloseAudio();
             av_audio_convert_free(pas->reformat_ctx);
         break;
     case CODEC_TYPE_VIDEO:
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-        PyINCREF(pyo);
-        pvs = _get_video_stream(pyo);
-        PyDECREF(pyo);
+        pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+        Py_INCREF((PyObject *)pvs);
         
         packet_queue_abort(&pvs->videoq);
 
         packet_queue_end(&pvs->videoq);
         break;
     case CODEC_TYPE_SUBTITLE:
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-        PyINCREF(pyo);
-        pss = _get_video_stream(pyo);
-        PyDECREF(pyo);
+        pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+        Py_INCREF((PyObject *)pss);
         
         packet_queue_abort(&pss->subtitleq);
 
     case CODEC_TYPE_AUDIO:
         pas->audio_st = NULL;
         is->audio_stream = -1;
+        Py_DECREF((PyObject *) pas);
+        _dealloc_aud_stream(pas);
         break;
     case CODEC_TYPE_VIDEO:
         pvs->video_st = NULL;
         is->video_stream = -1;
+        Py_DECREF((PyObject *) pvs);
+        _dealloc_vid_stream(pvs);
         break;
     case CODEC_TYPE_SUBTITLE:
         pss->subtitle_st = NULL;
+        Py_DECREF(pss);
         is->subtitle_stream = -1;
+        _dealloc_sub_stream(pss);
         break;
     default:
         break;
     is->audio_stream = -1;
     is->subtitle_stream = -1;
 
-    PyObject*      pyo;
     PyAudioStream* pas;
     PyVideoStream* pvs;
     PySubStream*   pss;
 
     err = av_find_stream_info(ic);
     if (err < 0) {
-        //TODO:Python exception here please
-        fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
+        PyErr_Format(PyExc_IOError, "%s: could not find codec parameters", is->filename);
+        //fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
         ret = -1;
         goto fail;
     }
             timestamp += ic->start_time;
         ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
         if (ret < 0) {
-            //TODO:Python exception here please
-            fprintf(stderr, "%s: could not seek to position %0.3f\n",
-                    is->filename, (double)timestamp / AV_TIME_BASE);
+            PyErr_Format(PyExc_IOError, "%s: could not seek to position %0.3f", is->filename, (double)timestamp/AV_TIME_BASE);
+            //fprintf(stderr, "%s: could not seek to position %0.3f\n",
+            //        is->filename, (double)timestamp / AV_TIME_BASE);
         }
     }
 
     }
 
     if (is->video_stream < 0 && is->audio_stream < 0) {
-        //TODO:Python exception here please
-        fprintf(stderr, "%s: could not open codecs\n", is->filename);
+        PyErr_Format(PyExc_IOError, "%s: could not open codecs", is->filename);
+        //fprintf(stderr, "%s: could not open codecs\n", is->filename);
         ret = -1;
         goto fail;
     }
 
             ret = av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags);
             if (ret < 0) {
-                //TODO:Python exception here please
-                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
+                PyErr_Format(PyExc_IOError, "%s: error while seeking", is->ic->filename);
+                //fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
             }else{
                 
                 
                 if (is->audio_stream >= 0) {
-                    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-                    PyINCREF(pyo);
-                    pas = _get_audio_stream(pyo);
-                    PyDECREF(pyo);
+                    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+                    Py_INCREF((PyObject *)pas);
+                    
         
                     packet_queue_flush(&pas->audioq);
                     packet_queue_put(&pas->audioq, &flush_pkt);
                 }
                 if (is->subtitle_stream >= 0) {
-                    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-                    PyINCREF(pyo);
-                    pss = _get_sub_stream(pyo);
-                    PyDECREF(pyo);
+                    pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+                    Py_INCREF((PyObject *)pss);
 
                     packet_queue_flush(&pss->subtitleq);
                     packet_queue_put(&pss->subtitleq, &flush_pkt);
                 }
                 if (is->video_stream >= 0) {
-                    pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-                    PyINCREF(pyo);
-                    pvs = _get_video_stream(pyo);
-                    PyDECREF(pyo);
+                    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+                    Py_INCREF((PyObject *)pvs);
 
                     packet_queue_flush(&pvs->videoq);
                     packet_queue_put(&pvs->videoq, &flush_pkt);
             }
             is->seek_req = 0;
         }
-       
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
-        PyXINCREF(pyo);
-        pas = _get_audio_stream(pyo);
-        PyXDECREF(pyo);
-
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
-        PyXINCREF(pyo);
-        pss = _get_sub_stream(pyo);
-        PyXDECREF(pyo);
-
-        pyo = PyList_GetItem(is->streams, (Py_ssize_t) is->video_stream);
-        PyXINCREF(pyo);
-        pvs = _get_video_stream(pyo);
-        PyXDECREF(pyo);
-
+        if(!pas)
+        {
+            pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->audio_stream);
+            Py_INCREF((PyObject *)pas);
+        }
+        if(!pss)
+        {
+            pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->subtitle_stream);
+            Py_INCREF((PyObject *) pss);
+        }
+        if(!pvs)
+        {
+            pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t) is->video_stream);
+            Py_INCREF((PyObject *)pvs);
+        }
         /* if the queue are full, no need to read more */
         if ((pas !=NULL && pas->audioq.size > MAX_AUDIOQ_SIZE) || //yay for short circuit logic testing
             (pvs !=NULL && pvs->videoq.size > MAX_VIDEOQ_SIZE )||
         event.user.data1 = is;
         SDL_PushEvent(&event);
     }
+    Py_XDECREF((PyObject *)pas);
+    Py_XDECREF((PyObject *)pvs);
+    Py_XDECREF((PyObject *)pss);
     return 0;
 }
 
 static void stream_close(PyMovie *is)
 {
 
-    //TODO: replace with proper python deallocation functions.
+    
     VideoPicture *vp;
     int i;
     /* XXX: use a special url_shutdown call to abort parse cleanly */
 
     /* free all pictures */
     
-    PyObject* pyo;
     PyVideoStream* pvs;
-    PySubStream  * pss;
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t)is->video_stream);
-    PyXINCREF(pyo);
-    pvs = _get_video_stream(pyo);
-    PyXDECREF(pyo);  
+    PySubtitleStream  * pss;
+    PyAudioStream   *pas;
+    
+    pvs = (PyVideoStream *)PySequence_GetItem(is->streams, (Py_ssize_t)is->video_stream);
+    Py_XINCREF((PyObject *)pvs);
 
-    pyo = PyList_GetItem(is->streams, (Py_ssize_t)is->subtitle_stream);
-    PyXINCREF(pyo);
-    pss = _get_sub_stream(pyo);
-    PyXDECREF(pyo);   
+    pss = (PySubtitleStream *)PySequence_GetItem(is->streams, (Py_ssize_t)is->subtitle_stream);
+    Py_XINCREF((PyObject *)pss);
 
+    pas = (PyAudioStream *)PySequence_GetItem(is->streams, (Py_ssize_t)is->audio_stream);
+    Py_XINCREF((PyObject *)pas);
+    
     for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
         vp = &pvs->pictq[i];
         if (pvs->bmp) {
             SDL_FreeYUVOverlay(pvs->bmp);
             pvs->bmp = NULL;
         }
+        if(pvs->out_surf)
+        {
+            SDL_FreeSurface(pvs->out_surf);
+        }
     }
     
     SDL_DestroyMutex(pvs->pictq_mutex);
     SDL_DestroyCond(pvs->pictq_cond);
     SDL_DestroyMutex(pss->subpq_mutex);
     SDL_DestroyCond(pss->subpq_cond);
+   
+    Py_XDECREF((PyObject *)pvs);
+    Py_XDECREF((PyObject *)pss);
+    Py_XDECREF((PyObject *)pas);
+    
+    if(is->audio_stream)
+    {
+        PyList_SetItem(is->streams, (Py_ssize_t)is->audio_stream, PyNone) 
+    }
+    if(is->video_stream)
+    {
+        PyList_SetItem(is->streams, (Py_ssize_t)is->video_stream, PyNone)
+    }
+    if(is->subtitle_stream)
+    {
+        PyList_SetItem(is->streams, (Py_ssize_t)is->subtitle_stream, PyNone)
+    }
+    
+    _dealloc_vid_stream(pvs);
+    _dealloc_sub_stream(pss);
+    _dealloc_aud_stream(pas);
+    
+    Py_INCREF(is->streams);
+    PyObject *pyo=is->streams;
+    Py_DECREF(is->streams);
+    is->streams =NULL;
+    Py_DECREF(pyo);
+    PyMem_Free(pyo);
+    
+    Py_DECREF((PyObject *)is);
+    PyMem_Free((PyObject *)is);
 }
 
 static void stream_cycle_channel(PyMovie *is, int codec_type)
 }
 
 
+static PyAudioStream* _new_audio_stream(void)
+{
+    PyAudioStream *pas;
+    pas=(PyAudioStream *)PyMem_Malloc(sizeof(PyAudioStream));
+    pas->paused      =0;
+    pas->last_paused =0;
+    pas->seek_req    =0;
+    pas->seek_flags  =0;
+    pas->seek_pos    =0;
+    
+    pas->av_sync_type=AV_SYNC_EXTERNAL_CLOCK;      /* Normally external. */
+    pas->offset          =0; 
+    pas->frame_timer     =0;
+    pas->frame_last_pts  =0;
+    pas->frame_last_delay=0;
+    pas->frame_offset    =0;
+    return pas;
+}
+
+static PyVideoStream* _new_video_stream(void)
+{
+    PyVideoStream *pvs;
+    pvs=(PyVideoStream *)PyMem_Malloc(sizeof(PyVideoStream));
+    pvs->paused      =0;
+    pvs->last_paused =0;
+    pvs->seek_req    =0;
+    pvs->seek_flags  =0;
+    pvs->seek_pos    =0;
+    
+    pvs->av_sync_type=AV_SYNC_EXTERNAL_CLOCK;      /* Normally external. */
+    pvs->offset          =0; 
+    pvs->frame_timer     =0;
+    pvs->frame_last_pts  =0;
+    pvs->frame_last_delay=0;
+    pvs->frame_offset    =0;
+    return pvs;
+
+}
+
+static PySubtitleStream* _new_sub_stream(void)
+{
+    PySubtitleStream *pss;
+    pss=(PySubtitleStream *)PyMem_Malloc(sizeof(PySubtitleStream));
+    pss->paused      =0;
+    pss->last_paused =0;
+    pss->seek_req    =0;
+    pss->seek_flags  =0;
+    pss->seek_pos    =0;
+    
+    pss->av_sync_type=AV_SYNC_EXTERNAL_CLOCK;      /* Normally external. */
+    pss->offset          =0; 
+    pss->frame_timer     =0;
+    pss->frame_last_pts  =0;
+    pss->frame_last_delay=0;
+    pss->frame_offset    =0;
+    return pss;
+
+}
+
+static void _dealloc_aud_stream(PyAudioStream *pas)
+{
+    PyMem_Free((void *)pas);
+}
+
+static void _dealloc_vid_stream(PyVideoStream *pvs)
+{
+    PyMem_Free((void *) pvs);
+}
+
+static void _dealloc_sub_stream(PySubtitleStream *pss)
+{
+    PyMem_Free((void *) pss);
+}
+
 /* Python C-API stuff */
 
 static PyMethodDef

File src/movieext.c

  • Ignore whitespace
-/*
-    pygame - Python Game Library
-    Copyright (C) 2000-2001  Pete Shinners
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Pete Shinners
-    pete@shinners.org
-*/
-
-/*
- *  movie playback for pygame
- */
-#include "pygame.h"
-#include "ffmovie.h"
-
-
-
-typedef struct {
-  PyObject_HEAD
-  FFMovie* movie;
-  PyObject* surftarget;
-} PyMovieObject;
-#define PyMovie_AsFFMovie(x) (((PyMovieObject*)x)->movie)
-
-
-staticforward PyTypeObject PyMovie_Type;
-static PyObject* PyMovie_New(FFMovie*);
-#define PyMovie_Check(x) ((x)->ob_type == &PyMovie_Type)
-
-
-
-static void autoquit(void)
-{
-    ffmovie_abortall();
-}
-
-
-/* movie object methods */
-
-    /*DOC*/ static char doc_movie_play[] =
-    /*DOC*/    "Movie.play() -> None\n"
-    /*DOC*/    "start movie playback\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Starts playback of a movie. If audio or video is enabled\n"
-    /*DOC*/    "for the Movie, those outputs will be created. \n"
-    /*DOC*/ ;
-
-static PyObject* movie_play(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-	int loops=0;
-
-        if(!PyArg_ParseTuple(args, "|i", &loops))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-        Py_BEGIN_ALLOW_THREADS
-	ffmovie_play(movie);
-        Py_END_ALLOW_THREADS
-	RETURN_NONE
-}
-
-
-
-    /*DOC*/ static char doc_movie_stop[] =
-    /*DOC*/    "Movie.stop() -> None\n"
-    /*DOC*/    "stop movie playback\n"
-    /*DOC*/    "\n"
-    /*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*/ ;
-
-static PyObject* movie_stop(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-        Py_BEGIN_ALLOW_THREADS
-	ffmovie_stop(movie);
-        Py_END_ALLOW_THREADS
-	RETURN_NONE
-}
-
-
-    /*DOC*/ static char doc_movie_pause[] =
-    /*DOC*/    "Movie.pause() -> None\n"
-    /*DOC*/    "pause/resume movie playback\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "This will temporarily stop playback of the movie. When called\n"
-    /*DOC*/    "a second time, playback will resume where it left off.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_pause(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-        Py_BEGIN_ALLOW_THREADS
-	ffmovie_pause(movie);
-        Py_END_ALLOW_THREADS
-	RETURN_NONE
-}
-
-
-    /*DOC*/ static char doc_movie_rewind[] =
-    /*DOC*/    "Movie.rewind() -> None\n"
-    /*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. 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*/    "\n"
-    /*DOC*/    "If rewinding the movie fails, it will invalidate this Movie\n"
-    /*DOC*/    "object.\n"
-    /*DOC*/ ;
-/*need something for this, if anything reinit a new movie and start*/
-
-static PyObject* movie_rewind(PyObject* self, PyObject* args)
-{
-        PyMovieObject* movieobj = (PyMovieObject*)self;
-        if(!movieobj->movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-        Py_BEGIN_ALLOW_THREADS
-        movieobj->movie = ffmovie_reopen(movieobj->movie);        
-        Py_END_ALLOW_THREADS
-        
-        if(!movieobj->movie)
-            RAISE(PyExc_SDLError, "Error handling movie source for rewind");
-	RETURN_NONE
-}
-
-
-    /*DOC*/ static char doc_movie_set_volume[] =
-    /*DOC*/    "Movie.set_volume(val) -> None\n"
-    /*DOC*/    "change volume for sound\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Set the play volume for this Movie. The volume value is between\n"
-    /*DOC*/    "0.0 and 1.0.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_set_volume(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-	float value;
-    
-	if(!PyArg_ParseTuple(args, "f", &value))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-        Py_BEGIN_ALLOW_THREADS
-        ffmovie_setvolume(movie, (int)(value*128));
-        Py_END_ALLOW_THREADS
-
-	RETURN_NONE
-}
-
-
-    /*DOC*/ static char doc_movie_set_display[] =
-    /*DOC*/    "Movie.set_display(Surface, [rect]) -> None\n"
-    /*DOC*/    "change the video output surface\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Set the output surface for the Movie's video. You may\n"
-    /*DOC*/    "also specify a position for the topleft corner of the\n"
-    /*DOC*/    "video.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "The position argument must be a rectstyle if given.\n"
-    /*DOC*/    "The video will be stretched to fill the rectangular area.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "You may also pass None as the destination Surface, and\n"
-    /*DOC*/    "no video will be rendered for the movie playback.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_set_display(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-	PyObject* surfobj, *posobj=NULL;
-        SDL_Rect* sdlrect, sdltemp;
-	GAME_Rect *rect, temp;
-    
-	if(!PyArg_ParseTuple(args, "O|O", &surfobj, &posobj))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	Py_XDECREF(((PyMovieObject*)self)->surftarget);
-	((PyMovieObject*)self)->surftarget = NULL;
-
-	if(PySurface_Check(surfobj))
-	{
-       SDL_Surface* surf = PySurface_AsSurface(surfobj);
-
-	   ((PyMovieObject*)self)->surftarget = surfobj;
-       Py_INCREF(surfobj);
-
-		if(posobj == NULL)
-		{
-			sdlrect = NULL;
-		}
-		else if((rect = GameRect_FromObject(posobj, &temp)))
-                {
-                        sdlrect = &sdltemp;
-                        sdltemp.x = rect->x;
-                        sdltemp.y = rect->y;
-                        sdltemp.w = rect->w;
-                        sdltemp.h = rect->h;
-                }
-                else
-			return RAISE(PyExc_TypeError, "Invalid position argument");
-
-            Py_BEGIN_ALLOW_THREADS            
-            ffmovie_setdisplay(movie, surf, sdlrect);
-            Py_END_ALLOW_THREADS
-	}
-	else
-	{
-            Py_BEGIN_ALLOW_THREADS
-	    ffmovie_setdisplay(movie, NULL, NULL);
-            Py_END_ALLOW_THREADS
-	    if(surfobj != Py_None)
-		       return RAISE(PyExc_TypeError, "destination must be a Surface");
-	}
-
-	RETURN_NONE;
-}
-
-
-    /*DOC*/ static char doc_movie_has_video[] =
-    /*DOC*/    "Movie.has_video() -> bool\n"
-    /*DOC*/    "query if movie stream has video\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Returns a true value when the Movie object has a valid\n"
-    /*DOC*/    "video stream.\n"
-    /*DOC*/ ;
-
-
-static PyObject* movie_has_video(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	return PyInt_FromLong(movie->video_st != NULL);
-}
-
-    /*DOC*/ static char doc_movie_has_audio[] =
-    /*DOC*/    "Movie.has_audio() -> bool\n"
-    /*DOC*/    "query if movie stream has audio\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Returns a true value when the Movie object has a valid\n"
-    /*DOC*/    "audio stream.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_has_audio(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-
-	return PyInt_FromLong(movie->audio_st != NULL);
-}
-
-    /*DOC*/ static char doc_movie_get_size[] =
-    /*DOC*/    "Movie.get_size() -> width,height\n"
-    /*DOC*/    "query the size of the video image\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Returns the size of the video image the mpeg provides.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_get_size(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-        int w=0, h=0;
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	if(movie->video_st != NULL) {
-                w = movie->video_st->codec.width;
-                h = movie->video_st->codec.height;
-        }
-	return Py_BuildValue("(ii)", w, h);
-}
-
-    /*DOC*/ static char doc_movie_get_frame[] =
-    /*DOC*/    "Movie.get_frame() -> int\n"
-    /*DOC*/    "query the current frame in the movie\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Gets the current video frame number for the movie.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_get_frame(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	return PyInt_FromLong(movie->frame_count);
-}
-
-    /*DOC*/ static char doc_movie_get_time[] =
-    /*DOC*/    "Movie.get_time() -> float\n"
-    /*DOC*/    "query the current time in the movie\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Gets the current time (in seconds) for the movie.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_get_time(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	return PyFloat_FromDouble(movie->frame_last_pts);
-}
-
-    /*DOC*/ static char doc_movie_get_length[] =
-    /*DOC*/    "Movie.get_length() -> float\n"
-    /*DOC*/    "query playback time of the movie\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Returns the total time (in seconds) of the movie.\n"
-    /*DOC*/ ;
-/*FIX, currently a no op*/
-static PyObject* movie_get_length(PyObject* self, PyObject* args)
-{
-/*	FFMovie* movie = PyMovie_AsFFMovie(self);*/
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-
-	return PyFloat_FromDouble(0.0);
-}
-
-
-    /*DOC*/ static char doc_movie_get_busy[] =
-    /*DOC*/    "Movie.get_busy() -> bool\n"
-    /*DOC*/    "query the playback state\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Returns true if the movie is currently playing.\n"
-    /*DOC*/ ;
-
-static PyObject* movie_get_busy(PyObject* self, PyObject* args)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
-
-	if(!PyArg_ParseTuple(args, ""))
-		return NULL;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-	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*/    "Totally experimental, and doesn't work very foos.\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;
-        if(!movie)
-            RAISE(PyExc_SDLError, "Movie object invalid");
-
-        movie->time_offset -= seconds;
-        
-	return PyInt_FromLong(movie->context != NULL);
-}
-
-
-static PyObject* movie_noop(PyObject* self, PyObject* args)
-{
-	return PyInt_FromLong(0);
-}
-
-
-
-static PyMethodDef movie_builtins[] =
-{
-	{ "play", movie_play, 1, doc_movie_play },
-	{ "stop", movie_stop, 1, doc_movie_stop },
-	{ "pause", movie_pause, 1, doc_movie_pause },
-	{ "rewind", movie_rewind, 1, doc_movie_rewind },
-
-	{ "set_volume", movie_set_volume, 1, doc_movie_set_volume },
-	{ "set_display", movie_set_display, 1, doc_movie_set_display },
-
-	{ "has_video", movie_has_video, 1, doc_movie_has_video },
-	{ "has_audio", movie_has_audio, 1, doc_movie_has_audio },
-	{ "get_size", movie_get_size, 1, doc_movie_get_size },
-	{ "get_frame", movie_get_frame, 1, doc_movie_get_frame },
-	{ "get_time", movie_get_time, 1, doc_movie_get_time },
-	{ "get_length", movie_get_length, 1, doc_movie_get_length },
-	{ "get_busy", movie_get_busy, 1, doc_movie_get_busy },
-
-	{ "skip", movie_skip, 1, doc_movie_skip },
-        { "render_frame", movie_noop, 1, "obsolete, does nothing"},
-
-	{ NULL, NULL }
-};
-
-
-/*sound object internals*/
-
-static void movie_dealloc(PyObject* self)
-{
-	FFMovie* movie = PyMovie_AsFFMovie(self);
- 
-        if(movie) {
-            Py_BEGIN_ALLOW_THREADS
-            ffmovie_close(movie);
-            Py_END_ALLOW_THREADS
-        }
-	Py_XDECREF(((PyMovieObject*)self)->surftarget);
-	PyObject_DEL(self);
-}
-
-
-static PyObject* movie_getattr(PyObject* self, char* attrname)
-{
-	return Py_FindMethod(movie_builtins, self, attrname);
-}
-
-
-    /*DOC*/ static char doc_Movie_MODULE[] =
-    /*DOC*/    "The Movie object represents an opened MPEG file.\n"
-    /*DOC*/    "You control playback similar to a Sound object.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Movie objects have a target display Surface.\n"
-    /*DOC*/    "The movie is rendered to this Surface in a background\n"
-    /*DOC*/    "thread. If the Surface is the display surface, and\n"
-    /*DOC*/    "the system supports it, the movie will render into a\n"
-    /*DOC*/    "Hardware YUV overlay plane. If you don't set a display\n"
-    /*DOC*/    "Surface, it will default to the display Surface.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Movies are played back in background threads, so there\n"
-    /*DOC*/    "is very little management needed on the user end. Just\n"
-    /*DOC*/    "load the Movie, set the destination, and Movie.play()\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Movies will only playback audio if the pygame.mixer\n"
-    /*DOC*/    "module is not initialized. It is easy to temporarily\n"
-    /*DOC*/    "call pygame.mixer.quit() to disable audio, then create\n"
-    /*DOC*/    "and play your movie. Finally calling pygame.mixer.init()\n"
-    /*DOC*/    "again when finished with the Movie.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "NOTE: When disabling the mixer so a movie may play audio,\n"
-    /*DOC*/    "you must disable the audio before calling pygame.movie.Movie\n"
-    /*DOC*/    "or the movie will not realise that it may access the audio.\n"
-    /*DOC*/    "Before reinitialising the mixer, You must remove all\n"
-    /*DOC*/    "references to the movie before calling pygame.mixer.init()\n"
-    /*DOC*/    "or the init will fail, leading to errors when you attempt to\n"
-    /*DOC*/    "use the mixer.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "eg.\n"
-    /*DOC*/    "pygame.mixer.quit()\n"
-    /*DOC*/    "movie=pygame.movie.Movie(\"my.mpg\")\n"
-    /*DOC*/    "movie.play()\n"
-    /*DOC*/    "# process events until movie finished here\n"
-    /*DOC*/    "movie.stop()\n"
-    /*DOC*/    "movie=None # if you don't do this bit the init will fail\n"
-    /*DOC*/    "pygame.mixer.init()\n"
-    /*DOC*/ ;
-
-static PyTypeObject PyMovie_Type =
-{
-	PyObject_HEAD_INIT(NULL)
-	0,
-	"Movie",
-	sizeof(PyMovieObject),
-	0,
-	movie_dealloc,
-	0,
-	movie_getattr,
-	NULL,					/*setattr*/
-	NULL,					/*compare*/
-	NULL,					/*repr*/
-	NULL,					/*as_number*/
-	NULL,					/*as_sequence*/
-	NULL,					/*as_mapping*/
-	(hashfunc)NULL, 		/*hash*/
-	(ternaryfunc)NULL,		/*call*/
-	(reprfunc)NULL, 		/*str*/
-	0L,0L,0L,0L,
-	doc_Movie_MODULE /* Documentation string */
-};
-
-
-
-
-/*movie module methods*/
-
-
-    /*DOC*/ static char doc_Movie[] =
-    /*DOC*/    "pygame.movie.Movie(file) -> Movie\n"
-    /*DOC*/    "load a new MPEG stream\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Loads a new movie stream from a MPEG file. The file\n"
-    /*DOC*/    "argument is either a filename, or any python file-like object\n"
-    /*DOC*/ ;
-
-static PyObject* Movie(PyObject* self, PyObject* arg)
-{
-	PyObject* file, *final;
-	char* name = NULL;
-	FFMovie* movie=NULL;
-	SDL_Surface* screen;
-	if(!PyArg_ParseTuple(arg, "O", &file))
-		return NULL;
-
-	if(PyString_Check(file) || PyUnicode_Check(file))
-	{
-		if(!PyArg_ParseTuple(arg, "s", &name))
-			return NULL;
-
-		movie = ffmovie_open(name);
-	}
-        
-	if(!movie)
-		return RAISE(PyExc_SDLError, "Cannot create Movie object");
-
-      	screen = SDL_GetVideoSurface();
-
-
-	final = PyMovie_New(movie);
-	if(!final) {
-		ffmovie_close(movie);
-        }
-
-	return final;
-}
-
-
-
-
-
-static PyMethodDef moviemod_builtins[] =
-{
-	{ "Movie", Movie, 1, doc_Movie },
-
-	{ NULL, NULL }
-};
-
-
-
-static PyObject* PyMovie_New(FFMovie* movie)
-{
-	PyMovieObject* movieobj;
-
-	if(!movie)
-		return RAISE(PyExc_RuntimeError, "unable to create movie.");
-
-	movieobj = PyObject_NEW(PyMovieObject, &PyMovie_Type);
-	if(movieobj)
-		movieobj->movie = movie;
-
-	movieobj->surftarget = NULL;
-
-	return (PyObject*)movieobj;
-}
-
-
-
-    /*DOC*/ static char doc_pygame_movie_MODULE[] =
-    /*DOC*/    "The movie module is an optional pygame module that\n"
-    /*DOC*/    "allows for decoding and playback of MPEG movie files.\n"
-    /*DOC*/    "The module only contains a single function, Movie()\n"
-    /*DOC*/    "which creates a new Movie object.\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Movies are played back in background threads, so there\n"
-    /*DOC*/    "is very little management needed on the user end. Just\n"
-    /*DOC*/    "load the Movie, set the destination, and Movie.play()\n"
-    /*DOC*/    "\n"
-    /*DOC*/    "Movies will only playback audio if the pygame.mixer\n"
-    /*DOC*/    "module is not initialized. It is easy to temporarily\n"
-    /*DOC*/    "call pygame.mixer.quit() to disable audio, then create\n"
-    /*DOC*/    "and play your movie. Finally calling pygame.mixer.init()\n"
-    /*DOC*/    "again when finished with the Movie.\n"
-    /*DOC*/ ;
-
-PYGAME_EXPORT
-void initmovieext(void)
-{
-        PyObject *module, *dict;
-
-	/* imported needed apis; Do this first so if there is an error
-	   the module is not loaded.
-	*/
-	import_pygame_base();
-        if (PyErr_Occurred ()) {
-	    return;
-        }
-	import_pygame_surface();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-	import_pygame_rwobject();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-	import_pygame_rect();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-    
-	/* type preparation */
-	PyType_Init(PyMovie_Type);
-
-	/* create the module */
-	module = Py_InitModule3("movieext", moviemod_builtins, doc_pygame_movie_MODULE);
-	dict = PyModule_GetDict(module);
-
-	PyDict_SetItemString(dict, "MovieType", (PyObject *)&PyMovie_Type);
-
-        /*imported needed apis*/
-	import_pygame_base();
-        if (PyErr_Occurred ()) {
-	    return;
-        }
-	import_pygame_surface();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-	import_pygame_rwobject();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-	import_pygame_rect();
-	if (PyErr_Occurred ()) {
-	    return;
-	}
-    
-    PyGame_RegisterQuit(autoquit);
-}
-