Commits

Anonymous committed 5a8fbae

Fixed unpause issue, fixed sound restart issue, and started working on
sound/audio drift issue. When synced to audio, the sound is very
staticky and not right.

Comments (0)

Files changed (6)

 
 print "Please give an (absolute)filename of a movie file you'd like to play: ",
 #filename = raw_input()
-filename="/home/tyler/War3.avi"
+filename="/home/tyler/dhs1.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.
 
 print "Playing infinitely"
 
-m.play(3)       #We're going to use infinite play, so we can demonstrate all 
+m.play(-1)       #We're going to use infinite play, so we can demonstrate all 
                 # the features.
-while(1):
-#    time.sleep(0.01)
-#    pygame.display.update()
-    pass
 time.sleep(10)  #sleep for ten seconds to let one see the video play, and hear 
                 # the audio
 print m.paused
 print "and again, sleeping..."
 #back to our original size
 time.sleep(10)
-import sys;sys.exit(1)
 #Here we demonstrate the use of pause. You pause, then call pause again to play
 print "Pausing..."
 m.pause()
 print "done pausing..."
 print m.paused
 print m.playing
-time.sleep(2)
+time.sleep(10)
 print "Unpausing..."
 m.pause()
 print m.paused
 	/* Wrapped by video_display, which has a lock on the movie object */
     DECLAREGIL
     GRABGIL
+    //PySys_WriteStdout("Blitting...\n");
     Py_INCREF( movie);
     RELEASEGIL
     VidPicture *vp;
     float aspect_ratio;
     int width, height, x, y;
-    
+	//we do this so that unpausing works. The problem is that when we pause, we end up invalidating all the frames in the queue.
+    // so we must short-circuit any checking or manipulation of frames... 
+	/*if(movie->paused)
+	{
+		goto closing;
+	}*/    
     vp = &movie->pictq[movie->pictq_rindex];
     vp->ready =0;
     if (movie->video_st->sample_aspect_ratio.num)
     movie->pictq_rindex= (movie->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE;
     movie->pictq_size--;
     video_refresh_timer(movie);
+closing:
     GRABGIL
     Py_DECREF( movie);
 	RELEASEGIL
 	GRABGIL
     Py_INCREF( movie);
     RELEASEGIL
-    double pts;
-    int hw_buf_size, bytes_per_sec;
-
     
-    pts = movie->audio_clock;
-    hw_buf_size = audio_write_get_buf_size(movie);
-    bytes_per_sec = 0;
-    if (movie->audio_st) {
-        bytes_per_sec = movie->audio_st->codec->sample_rate *
-            2 * movie->audio_st->codec->channels;
-    }
-    if (bytes_per_sec)
-        pts -= (double)hw_buf_size / bytes_per_sec;
+    double pts= getAudioClock();
+    
     GRABGIL
     Py_DECREF( movie);
     RELEASEGIL
 void stream_pause(PyMovie *movie)
 {
     Py_INCREF( movie);
-    int paused = movie->paused;
+    int paused=movie->paused;
     movie->paused = !movie->paused;
     if (!movie->paused) 
     {
                 continue;
             //reformat_ctx here, but deleted    
             /* if no pts, then compute it */
-            pts = movie->audio_clock;
+            /*pts = movie->audio_clock;
             n = 2 * dec->channels;
             movie->audio_clock += (double)data_size / (double)(n * dec->sample_rate);
-            filled=1;
+            */filled=1;
         	   
         }
         //either buffer filled or no packets yet
             avcodec_flush_buffers(dec);
             goto closing;
         }
-
+		movie->audio_pts      = pkt->pts;
         movie->audio_pkt_data = pkt->data;
         movie->audio_pkt_size = pkt->size;
         
-        /* if update the audio clock with the pts */
-        if (pkt->pts != AV_NOPTS_VALUE) {
-            movie->audio_clock = av_q2d(movie->audio_st->time_base)*pkt->pts;
-        }
         if(filled)
         {
         	/* Buffer is filled up with a new frame, we spin lock/wait for a signal, where we then call playBuffer */
         	SDL_LockMutex(movie->audio_mutex);
         	//SDL_CondWait(movie->audio_sig, movie->audio_mutex);
-        	int chan = playBuffer(movie->audio_buf1, data_size, movie->channel);
+        	int chan = playBuffer(movie->audio_buf1, data_size, movie->channel, movie->audio_pts);
         	movie->channel = chan;
         	filled=0;
         	len1=0;
 	
     //in case we've called stream open once before...
     movie->abort_request = 0;
-    movie->av_sync_type = AV_SYNC_VIDEO_MASTER;
+    movie->av_sync_type = AV_SYNC_AUDIO_MASTER;
 	
     video_index = -1;
     audio_index = -1;
         
         freq = enc->sample_rate;
         channels = enc->channels;
-        if (soundInit  (freq, -16, channels, 1024) < 0) {
+        if (soundInit  (freq, -16, channels, 1024, av_q2d(enc->time_base)) < 0) {
             RAISE(PyExc_SDLError, SDL_GetError ());
         }
         //movie->audio_hw_buf_size = 1024;
         {
         	break;
         }
+        
         if (movie->paused != movie->last_paused) {
             movie->last_paused = movie->paused;
             if (movie->paused)
             else
                 av_read_play(ic);
         }
+        if(movie->paused)
+        {
+        	SDL_Delay(10);
+        	continue;
+        }
         if (movie->seek_req) {
             int stream_index= -1;
             int64_t seek_target= movie->seek_pos;
     AVPacket audio_pkt;
     uint8_t *audio_pkt_data;
     int      audio_pkt_size;
+    int64_t  audio_pts;
     //int audio_volume; /*must self implement*/
 	enum SampleFormat audio_src_fmt;
     AVAudioConvert *reformat_ctx;
 #define _MIXER_DEFAULT_CHANNELS 2
 #define _MIXER_DEFAULT_CHUNKSIZE 4096
 
-BufferQueue queue;
-int playing =0;
-int s_channel;
+AudioInfo ainfo;
+
 int queue_get(BufferQueue *q, BufferNode **pkt1)
 {
 	//BufferNode *pkt1;
 
 void cb_mixer(int channel)
 {
-	//PyGILState_STATE gstate;
-	//gstate=PyGILState_Ensure();
-	Mix_Chunk *mix = Mix_GetChunk(channel);
+	/*Mix_Chunk *mix = Mix_GetChunk(channel);
 	if(mix==NULL)
 	{
 		playBuffer(NULL, (uint32_t) 0, channel);
 		mix=NULL;
 		playBuffer(NULL, (uint32_t) 0, channel);
 		return;
-	}
-	//PyMem_Free(mix->abuf);
-	//mix->abuf=NULL;
-	//PyMem_Free(mix);
-	//mix=NULL;
-	//PySys_WriteStdout("Callback called.\n");
-	playBuffer(NULL, (uint32_t) 0, channel);
-	//PySys_WriteStdout("Callback finished.\n");
-	//PyGILState_Release(gstate);
+	}*/
+	playBuffer(NULL, (uint32_t) 0, channel, 0);
 }
 
 //initialize the mixer audio subsystem, code cribbed from mixer.c
-int soundInit  (int freq, int size, int channels, int chunksize)
+int soundInit  (int freq, int size, int channels, int chunksize, double time_base)
 {
 	Uint16 fmt = 0;
     int i;
             SDL_QuitSubSystem (SDL_INIT_AUDIO);
             return -1;
         }
-		s_channel = 0;
+		
         /* A bug in sdl_mixer where the stereo is reversed for 8 bit.
            So we use this CPU hogging effect to reverse it for us.
            Hopefully this bug is fixed in SDL_mixer 1.2.9
 #endif
        
     }
-    
-	
-	queue.size=0;
-	queue.first=queue.last=NULL;	
+    ainfo.channel = 0;
+	ainfo.channels = channels;
+	ainfo.audio_clock=0.0;
+	ainfo.queue.size=0;
+	ainfo.queue.first=ainfo.queue.last=NULL;
+	ainfo.sample_rate=freq;
+	ainfo.time_base = time_base;	
     return 0;
 }
 
 	if (SDL_WasInit (SDL_INIT_AUDIO))
     {
         Mix_HaltMusic ();
-		queue_flush(&queue);
+		queue_flush(&ainfo.queue);
 		Mix_ChannelFinished(NULL);
 		Mix_CloseAudio ();
         SDL_QuitSubSystem (SDL_INIT_AUDIO);
 {
 	Mix_VolumeMusic (127);
     Mix_ChannelFinished(&cb_mixer);
+	ainfo.ended=0;
+	ainfo.audio_clock =0.0;
+	ainfo.playing=0;
+	ainfo.current_frame_size=1;
 	return 0;
 }
 	
 int soundEnd   (void)
 {
-	Mix_Volume(-1, 0);
-	Mix_ChannelFinished(NULL);
-	Mix_HaltChannel(-1);
+	ainfo.ended = 1;
 	return 0;
 }
 	
 /* Play a sound buffer, with a given length */
-int playBuffer (uint8_t *buf, uint32_t len, int channel)
+int playBuffer (uint8_t *buf, uint32_t len, int channel, int64_t pts)
 {
 	Mix_Chunk *mix;
 	int allocated=0;
-	if(queue.size>0||playing)
+	if(!ainfo.ended && (ainfo.queue.size>0||ainfo.playing))
 	{
 		if(buf)
 		{
 			memcpy(node->buf, buf, (size_t)len);
 			node->len = len;
 			node->next =NULL;
-			queue_put(&queue, node);
-			return channel;
+			node->pts = pts;
+			queue_put(&ainfo.queue, node);
+			return ainfo.channel;
 		}
-		else if(!buf && queue.size==0)
+		else if(!buf && ainfo.queue.size==0)
 		{
 			//callback call but when the queue is empty, so we just load a short empty sound.
 			buf = (uint8_t *) PyMem_Malloc((size_t)128);
 		{
 			//callback call, and convenienty enough, the queue has a buffer ready to go, so we copy it into buf
 			BufferNode *new;
-			queue_get(&queue, &new);
+			queue_get(&ainfo.queue, &new);
 			if(!new)
 				return -1;
+			ainfo.current_frame_size=new->len;
+			if (new->pts != AV_NOPTS_VALUE) {
+         	   ainfo.audio_clock = ainfo.time_base*new->pts;
+        	}
 			buf = (uint8_t *)PyMem_Malloc((size_t)new->len);
 			memcpy(buf, new->buf, new->len);
 			len=new->len;
 			allocated=1;
 		}	
 	}
+	//we assume that if stopped is true, then 
+	if(ainfo.ended)
+	{
+		//callback call but when the queue is empty, so we just load a short empty sound.
+		buf = (uint8_t *) PyMem_Malloc((size_t)128);
+		memset(buf, 0, (size_t)128);
+		ainfo.current_frame_size=1;
+		len=128;
+		allocated =1;
+	}
 	//regardless of 1st call, or a callback, we load the data from buf into a newly allocated block.
 	mix= (Mix_Chunk *)PyMem_Malloc(sizeof(Mix_Chunk));
 	mix->allocated=0;
 	memcpy(mix->abuf, buf, len);
 	mix->alen = (Uint32 )len;
 	mix->volume = 127;
-	playing = 1;
-	int ret = Mix_PlayChannel(s_channel, mix, 0);
-	s_channel = ret;
+	ainfo.playing = 1;
+	int bytes_per_sec = ainfo.channels*ainfo.sample_rate*2;
+	ainfo.audio_clock+= (double) len/(double) bytes_per_sec;
+	ainfo.current_frame_size =len;
+	int ret = Mix_PlayChannel(ainfo.channel, mix, 0);
+	ainfo.channel = ret;
 	//if buffer was allocated, we gotta clean it up.
 	if(allocated)
 	{
 {
 	if(!channel)
 		return 0;
-	Mix_Chunk *mix;
-	mix = Mix_GetChunk(channel);
-	Mix_HaltChannel(channel);
-	if(mix)
-	{
-		mix->alen = -1;
-		mix->abuf=NULL; //this data still exists, we just make the pointer to it be NULL
-		mix->allocated=0;
-		mix->volume = 0;
-		Mix_FreeChunk(mix);
-		mix=NULL; //safety
-	}
+	//Mix_HaltChannel(channel);
 	return 0;
 }
 int pauseBuffer(int channel)
 	int paused = Mix_Paused(channel);
 	if(paused)
 	{
-		Mix_Resume(channel);
+		Mix_Resume(-1);
 	}
 	else
 	{
-		Mix_Pause(channel);
+		Mix_Pause(-1);
 	}
 	return 0;
 }
 int seekBuffer (uint8_t *buf, uint32_t len, int channel)
 {
 	stopBuffer(channel);
-	return playBuffer(buf, len, channel);
+	return playBuffer(buf, len, channel, 0);
 }
 
 int setCallback(void (*callback)(int channel))
 	return 1;
 }
 
+int getAudioClock(void)
+{
+	int bytes_per_sec = ainfo.channels*ainfo.sample_rate*2;
+	int pts = ainfo.audio_clock;
+	pts -= (double) ainfo.current_frame_size/bytes_per_sec;
+	return pts;
+}
+
+
 #include <SDL/SDL_mixer.h>
 #include <SDL.h>
 #include <SDL_thread.h>
-
+#include <libavformat/avformat.h>
 typedef struct BufferNode{
 	uint8_t *buf;
 	int      len;
-	struct BufferNode *next;
+	int64_t  pts;
+	struct BufferNode 
+			*next;
 } BufferNode;
 
 typedef struct BufferQueue{
 	int size;
 } BufferQueue;
 
-int soundInit  (int freq, int size, int channels, int chunksize);
-int soundQuit  (void);
-int soundStart (void);
-int soundEnd   (void);
-int playBuffer (uint8_t *buf, uint32_t len, int channel);
-int stopBuffer (int channel);
-int pauseBuffer(int channel);
-int getPaused  (int channel);
-int seekBuffer (uint8_t *buf, uint32_t len, int channel );
-int setCallback(void (*callback) (int channel));
+typedef struct AudioInfo{
+	double      audio_clock;        //keeps track of our PTS, in seconds
+	int         channels;           //data for keeping track of the fraction of a second the current frame will take
+	int         sample_rate;        //''
+	int         current_frame_size; //''
+	int         pts;                //current pts
+	int         playing;            //if we've started playing any buffers
+	int         channel;            //what channel the last buffer played on
+	int         ended;              //whether or not we've "ended", so we know to output silence.
+	double      time_base;          //the base 1/frames per second value
+	BufferQueue queue;              //queue of our buffers
 
+} AudioInfo;
+
+int soundInit     (int freq, int size, int channels, int chunksize, double time_base);
+int soundQuit     (void);
+int soundStart    (void);
+int soundEnd      (void);
+int playBuffer    (uint8_t *buf, uint32_t len, int channel, int64_t pts);
+int stopBuffer    (int channel);
+int pauseBuffer   (int channel);
+int getPaused     (int channel);
+int getAudioClock (void);
+int seekBuffer    (uint8_t *buf, uint32_t len, int channel );
+int setCallback   (void (*callback) (int channel));
+int resetAudioInfo(void);
 #endif /*_GSOUND_H_*/
     PyObject *pyo;
     if(movie->video_st)
     {
-    	if(movie->width)
+    	if(movie->resize_w)
     		{pyo = PyInt_FromLong((long)movie->width);}
     	else
     	{
     PyObject *pyo;
     if(movie->video_st)
     {
-    	if(movie->height)
+    	if(movie->resize_h)
     		{pyo=PyInt_FromLong((long)movie->height);}
     	else
     		{pyo= PyInt_FromLong((long)movie->video_st->codec->height);}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.