浏览代码

fix video/audio synchronization code in theora

Juan Linietsky 9 年之前
父节点
当前提交
eb419bee04
共有 2 个文件被更改,包括 33 次插入12 次删除
  1. 31 11
      drivers/theora/video_stream_theora.cpp
  2. 2 1
      drivers/theora/video_stream_theora.h

+ 31 - 11
drivers/theora/video_stream_theora.cpp

@@ -266,14 +266,14 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
 				theora_p=1;
 				theora_p=1;
 			}else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
 			}else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
 				/* it is vorbis */
 				/* it is vorbis */
-                if (audio_track_skip) {
-                    vorbis_info_clear(&vi);
-                    vorbis_comment_clear(&vc);
-                    audio_track_skip--;
-                } else {
-                    copymem(&vo,&test,sizeof(test));
-                    vorbis_p=1;
-                }
+		if (audio_track_skip) {
+		    vorbis_info_clear(&vi);
+		    vorbis_comment_clear(&vc);
+		    audio_track_skip--;
+		} else {
+		    copymem(&vo,&test,sizeof(test));
+		    vorbis_p=1;
+		}
 			}else{
 			}else{
 				/* whatever it is, we don't care about it */
 				/* whatever it is, we don't care about it */
 				ogg_stream_clear(&test);
 				ogg_stream_clear(&test);
@@ -392,6 +392,7 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
 		fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
 		fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
 				vo.serialno,vi.channels,vi.rate);
 				vo.serialno,vi.channels,vi.rate);
 		//_setup(vi.channels, vi.rate);
 		//_setup(vi.channels, vi.rate);
+
 	}else{
 	}else{
 		/* tear down the partial vorbis setup */
 		/* tear down the partial vorbis setup */
 		vorbis_info_clear(&vi);
 		vorbis_info_clear(&vi);
@@ -401,6 +402,7 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
 	playing = false;
 	playing = false;
 	buffering=true;
 	buffering=true;
 	time=0;
 	time=0;
+	audio_frames_wrote=0;
 };
 };
 
 
 float VideoStreamPlaybackTheora::get_time() const {
 float VideoStreamPlaybackTheora::get_time() const {
@@ -431,8 +433,9 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
 		return; //no new frames need to be produced
 		return; //no new frames need to be produced
 
 
 	bool frame_done=false;
 	bool frame_done=false;
+	bool audio_done=false;
 
 
-	while (!frame_done) {
+	while (!frame_done || !audio_done) {
 		//a frame needs to be produced
 		//a frame needs to be produced
 
 
 		ogg_packet op;
 		ogg_packet op;
@@ -490,6 +493,17 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
 				audio_pending=true;
 				audio_pending=true;
 
 
 
 
+				if (vd.granulepos>=0) {
+				//	print_line("wrote: "+itos(audio_frames_wrote)+" gpos: "+itos(vd.granulepos));
+				}
+
+				//print_line("mix audio!");
+
+				audio_frames_wrote+=ret-to_read;
+
+				//print_line("AGP: "+itos(vd.granulepos)+" added "+itos(ret-to_read));
+
+
 			} else {
 			} else {
 
 
 				/* no pending audio; is there a pending packet to decode? */
 				/* no pending audio; is there a pending packet to decode? */
@@ -503,6 +517,9 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
 				};
 				};
 			}
 			}
 
 
+
+			audio_done = videobuf_time < (audio_frames_wrote/float(vi.rate));
+
 			if (buffer_full)
 			if (buffer_full)
 				break;
 				break;
 		}
 		}
@@ -567,7 +584,9 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
 			}
 			}
 		}
 		}
 	#else
 	#else
-		if (!frame_done){
+
+
+		if (!frame_done || !audio_done){
 			//what's the point of waiting for audio to grab a page?
 			//what's the point of waiting for audio to grab a page?
 
 
 			buffer_data();
 			buffer_data();
@@ -709,8 +728,9 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
 	texture = Ref<ImageTexture>( memnew(ImageTexture ));
 	texture = Ref<ImageTexture>( memnew(ImageTexture ));
 	mix_callback=NULL;
 	mix_callback=NULL;
 	mix_udata=NULL;
 	mix_udata=NULL;
-    audio_track=0;
+	    audio_track=0;
 	delay_compensation=0;
 	delay_compensation=0;
+	audio_frames_wrote=0;
 };
 };
 
 
 VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {
 VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {

+ 2 - 1
drivers/theora/video_stream_theora.h

@@ -32,6 +32,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
 	void video_write(void);
 	void video_write(void);
 	float get_time() const;
 	float get_time() const;
 
 
+
 	ogg_sync_state   oy;
 	ogg_sync_state   oy;
 	ogg_page         og;
 	ogg_page         og;
 	ogg_stream_state vo;
 	ogg_stream_state vo;
@@ -122,7 +123,7 @@ public:
 
 
 	Ref<VideoStreamPlayback> instance_playback() {
 	Ref<VideoStreamPlayback> instance_playback() {
 		Ref<VideoStreamPlaybackTheora> pb = memnew( VideoStreamPlaybackTheora );
 		Ref<VideoStreamPlaybackTheora> pb = memnew( VideoStreamPlaybackTheora );
-        pb->set_audio_track(audio_track);
+	pb->set_audio_track(audio_track);
 		pb->set_file(file);
 		pb->set_file(file);
 		return pb;
 		return pb;
 	}
 	}