[xiph-commits] r2999 - liboggplay/trunk/plugin

tahn at svn.annodex.net tahn at svn.annodex.net
Tue Jun 19 01:53:43 PDT 2007


Author: tahn
Date: 2007-06-19 01:53:43 -0700 (Tue, 19 Jun 2007)
New Revision: 2999

Modified:
   liboggplay/trunk/plugin/plugin_gui_mac.c
Log:
Reworked audio processing in the display loop to handle "patchy" audio tracks.


Modified: liboggplay/trunk/plugin/plugin_gui_mac.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_mac.c	2007-06-19 07:45:16 UTC (rev 2998)
+++ liboggplay/trunk/plugin/plugin_gui_mac.c	2007-06-19 08:53:43 UTC (rev 2999)
@@ -378,11 +378,11 @@
     }
 
     /*
-     * Swap the media source on the fly. Shut down and restart the audio to
-     * (a) flush the audio buffer, and (b) handle changes in the audio data
-     * format. If we're currently paused, temporarily unpause until the first
-     * frame of data is retrieved and displayed so the user will get some
-     * feedback that the movie has actually been changed.
+     * Swap the media source on the fly. Shut down the audio to (a) flush the
+     * audio buffer and (b) handle changes in the audio data format. If we're
+     * currently paused, temporarily unpause until the first frame of video
+     * data is retrieved and displayed so the user will get some feedback
+     * that the movie has actually been changed.
      */
     if (info->new_oggplay_handle != NULL) {
       SEM_WAIT(info->oggplay_replace_sem);
@@ -425,8 +425,8 @@
     }
 
     /*
-     * Spin until we have some data (but wait for a bit first so we don't
-     * chew too many cycles).
+     * Spin until we have some video or audio data (but wait for a bit first
+     * so we don't chew too many cycles).
      */
     bool have_video = (td.frame_data.video_data != NULL);
     bool have_audio = (td.frame_data.samples != NULL && td.frame_data.size > 0);
@@ -474,46 +474,40 @@
     }
 
     /*
-     * Start up the audio output unit as soon as we have some data to play
-     * with. If the media source stops supplying audio, we shouldn't keep
-     * the audio unit open.
+     * Process the audio data. We only start the audio output unit once
+     * we have some audio data, because only then do we know the sample
+     * rate and number of channels. Once started, we keep the audio unit going
+     * even if there's no audio data for a given frame, because some input
+     * files have "patchy" audio tracks -- they provide large chunks of audio
+     * every few video frames, with nothing in between.
      */
-    if (have_audio && td.audio_handle == NULL) {
-      init_audio(info, &td);
-    } else if (!have_audio && td.audio_handle != NULL) {
-      shutdown_audio(info, &td);
-      playback_target = 0;
-    }
-
-    /*
-     * If we have some audio data, send it to the output device and calculate
-     * our current playing time using the number of audio bytes consumed.
-     */
-    cur_time = -1;
-    if (have_audio && td.audio_handle != NULL) {
-      if (
-        sa_stream_write(td.audio_handle, td.frame_data.samples, td.frame_data.size) == SA_SUCCESS
-        &&
-        sa_stream_get_position(td.audio_handle, SA_POSITION_WRITE_SOFTWARE, &bytes) == SA_SUCCESS
-      ) {
-        cur_time = bytes * 1000 / get_audio_rate(info->oggplay_handle) /
-                    (sizeof(short) * get_audio_channels(info->oggplay_handle));
-      } else {
-        /*
-         * Something's gone wrong with the audio; revert to using the system
-         * clock for controlling our playback time.
-         */
-        shutdown_audio(info, &td);
-        playback_target = 0;
+    if (have_audio) {
+      if (td.audio_handle == NULL) {
+        init_audio(info, &td);
       }
+      if (td.audio_handle != NULL) {
+        if (sa_stream_write(td.audio_handle, td.frame_data.samples,
+                            td.frame_data.size) != SA_SUCCESS) {
+          /*
+           * Something's gone wrong with the audio; revert to using the
+           * system clock for controlling our playback time.
+           */
+          shutdown_audio(info, &td);
+          playback_target = 0;
+        }
+      }
     }
 
     /*
-     * If we can't use the audio device to determine our playback time, track
-     * it with the system clock. Use the time at which the first frame is
-     * displayed as a reference.
+     * Calculate our current playback time using the number of audio bytes
+     * consumed. If we can't do that, track it with the system clock, using
+     * the time at which the first frame is displayed as a reference.
      */
-    if (cur_time == -1) {
+    if (td.audio_handle != NULL) {
+      sa_stream_get_position(td.audio_handle, SA_POSITION_WRITE_SOFTWARE, &bytes);
+      cur_time = bytes * 1000 / get_audio_rate(info->oggplay_handle) /
+                    (sizeof(short) * get_audio_channels(info->oggplay_handle));
+    } else {
       if (playback_target == 0) {
         time_ref = oggplay_sys_time_in_ms();
       }
@@ -532,7 +526,8 @@
     offset = playback_target - cur_time;
     drop_video_frame = (offset < 0);
 #ifdef TIMING_TRACE
-    printf("\npt %6lld    ct %6lld    off %6lld    %s",
+    printf("\nv %d   a %6d    pt %6lld    ct %6lld    off %4lld    %s",
+        td.frame_data.frame != NULL, td.frame_data.size,
         playback_target, cur_time, offset, drop_video_frame ? "*" : "");
 #endif
     if (drop_video_frame) {



More information about the commits mailing list