[MPlayer-dev-eng] [PATCH] Online audio stream switching

Michael Behrisch behrisch at informatik.hu-berlin.de
Sun Feb 27 20:03:16 CET 2005


On Thu, Feb 24, 2005 at 07:01:14PM +0100, Michael Behrisch wrote:
> The attached patch enables audio stream switching
> in the mpg demuxer using the #-key. It is not complete yet,
> because manpage is not updated, but I wanted to get some
> opinions before doing the really hard work ;-)

It seems like my patches need more advertising before even getting noticed.
OK here we go. This patch lets you instantly switch from german to english
on your favorite dvd to hear the original version of that four letter word.

A single keypress instead of stopping, looking for the right aid and 
restarting and searching over and over again. (It works only if both audio 
streams have the same format, but it works.) And it can also walk your dog.


Michael

-------------- next part --------------
--- mplayer/mplayer.c	2005-02-23 12:43:24.000000000 +0100
+++ mplayer.build/mplayer.c	2005-02-23 22:42:21.000000000 +0100
@@ -3511,6 +3511,9 @@
     case MP_CMD_GET_PERCENT_POS : {
 	mp_msg(MSGT_GLOBAL,MSGL_INFO,MSGTR_AnsPercentPos, demuxer_get_percent_pos(demuxer));
     } break;
+    case MP_CMD_SWITCH_AUDIO :
+        demuxer_switch_audio(demuxer);
+        break;
     case MP_CMD_RUN : {
 #ifndef __MINGW32__
         if(!fork()) {
diff -u mplayer/input/input.c mplayer.build/input/input.c
--- mplayer/input/input.c	2005-02-23 12:43:25.000000000 +0100
+++ mplayer.build/input/input.c	2005-02-23 22:42:20.000000000 +0100
@@ -82,6 +82,7 @@
   { MP_CMD_SUB_LOG, "sub_log", 0, { {-1,{0}} } },
   { MP_CMD_GET_PERCENT_POS, "get_percent_pos", 0, { {-1,{0}} } },
   { MP_CMD_GET_TIME_LENGTH, "get_time_length", 0, { {-1,{0}} } },
+  { MP_CMD_SWITCH_AUDIO, "switch_audio", 0, { {-1,{0}} } },
 #ifdef USE_TV
   { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", 1,  { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} }},
   { MP_CMD_TV_STEP_NORM, "tv_step_norm",0, { {-1,{0}} }  },
@@ -317,6 +318,7 @@
   { { 'b', 0 }, "sub_select" },
   { { 'j', 0 }, "vobsub_lang" },
   { { 'F', 0 }, "forced_subs_only" },
+  { { '#', 0 }, "switch_audio" },
 #ifdef USE_EDL
   { { 'i', 0 }, "edl_mark" },
 #endif
diff -u mplayer/input/input.h mplayer.build/input/input.h
--- mplayer/input/input.h	2005-02-23 12:43:25.000000000 +0100
+++ mplayer.build/input/input.h	2005-02-23 22:45:00.000000000 +0100
@@ -63,6 +63,7 @@
 #define MP_CMD_SPEED_SET 59
 #define MP_CMD_RUN 60
 #define MP_CMD_SUB_LOG 61
+#define MP_CMD_SWITCH_AUDIO 62
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
diff -u mplayer/libmpdemux/demuxer.c mplayer.build/libmpdemux/demuxer.c
--- mplayer/libmpdemux/demuxer.c	2005-02-23 12:44:09.000000000 +0100
+++ mplayer.build/libmpdemux/demuxer.c	2005-02-23 22:42:21.000000000 +0100
@@ -1348,26 +1348,7 @@
    break;
  }
 
- case DEMUXER_TYPE_MPEG_TY: {
-  sh_video=d_video->sh;sh_video->ds=d_video;
-
-  if(audio_id!=-2) {
-   if(!ds_fill_buffer(d_audio)){
-    mp_msg(MSGT_DEMUXER,MSGL_INFO,"MPEG: " MSGTR_MissingAudioStream);
-    sh_audio=NULL;
-   } else {
-    sh_audio=d_audio->sh;sh_audio->ds=d_audio;
-    switch(d_audio->id & 0xE0){  // 1110 0000 b  (high 3 bit: type  low 5: id)
-      case 0x00: sh_audio->format=0x50;break; // mpeg
-      case 0xA0: sh_audio->format=0x10001;break;  // dvd pcm
-      case 0x80: if((d_audio->id & 0xF8) == 0x88) sh_audio->format=0x2001;//dts
-                 else sh_audio->format=0x2000;break; // ac3
-      default: sh_audio=NULL; // unknown type
-    }
-   }
-  }
-  break;
- }
+ case DEMUXER_TYPE_MPEG_TY: 
  case DEMUXER_TYPE_MPEG_PS: {
   sh_video=d_video->sh;sh_video->ds=d_video;
 //  if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
@@ -1378,13 +1359,6 @@
     sh_audio=NULL;
    } else {
     sh_audio=d_audio->sh;sh_audio->ds=d_audio;
-    switch(d_audio->id & 0xE0){  // 1110 0000 b  (high 3 bit: type  low 5: id)
-      case 0x00: sh_audio->format=0x50;break; // mpeg
-      case 0xA0: sh_audio->format=0x10001;break;  // dvd pcm
-      case 0x80: if((d_audio->id & 0xF8) == 0x88) sh_audio->format=0x2001;//dts
-                 else sh_audio->format=0x2000;break; // ac3
-      default: sh_audio=NULL; // unknown type
-    }
    }
   }
   break;
@@ -1797,3 +1771,8 @@
     return ans;
 }
 
+int demuxer_switch_audio(demuxer_t *demuxer){     
+    int ans = 0;
+    int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &ans);
+    return ans;
+}
diff -u mplayer/libmpdemux/demuxer.h mplayer.build/libmpdemux/demuxer.h
--- mplayer/libmpdemux/demuxer.h	2005-02-23 12:44:09.000000000 +0100
+++ mplayer.build/libmpdemux/demuxer.h	2005-02-23 22:42:21.000000000 +0100
@@ -70,6 +70,7 @@
 #define DEMUXER_CTRL_GUESS 2
 #define DEMUXER_CTRL_GET_TIME_LENGTH 10
 #define DEMUXER_CTRL_GET_PERCENT_POS 11
+#define DEMUXER_CTRL_SWITCH_AUDIO 12
 
 // Holds one packet/frame/whatever
 typedef struct demux_packet_st {
@@ -286,5 +287,6 @@
 
 extern unsigned long demuxer_get_time_length(demuxer_t *demuxer);
 extern int demuxer_get_percent_pos(demuxer_t *demuxer);
+extern int demuxer_switch_audio(demuxer_t *demuxer);
 
 extern int demuxer_type_by_filename(char* filename);
diff -u mplayer/libmpdemux/demux_mpg.c mplayer.build/libmpdemux/demux_mpg.c
--- mplayer/libmpdemux/demux_mpg.c	2005-01-17 14:33:40.000000000 +0100
+++ mplayer.build/libmpdemux/demux_mpg.c	2005-02-24 13:01:24.568988776 +0100
@@ -21,6 +21,8 @@
   float last_pts;
   float final_pts;
   int has_valid_timestamps;
+  int num_a_streams;
+  int a_stream_ids[MAX_A_STREAMS];
 } mpg_demuxer_t;
 
 static int mpeg_pts_error=0;
@@ -38,6 +40,7 @@
   demuxer->priv = mpg_d;
   mpg_d->final_pts = 0.0;
   mpg_d->has_valid_timestamps = 1;
+  mpg_d->num_a_streams = 0;
   if (demuxer->seekable && stream_tell(demuxer->stream) < end_seq_start) {
     stream_seek(s,(pos + end_seq_start / 2));
     while ((!s->eof) && ds_fill_buffer(demuxer->video) && half_pts == 0.0) {
@@ -83,6 +86,23 @@
   return pts;
 }
 
+static void new_audio_stream(demuxer_t *demux, int aid){
+  if(!demux->a_streams[aid]){
+    mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;
+    sh_audio_t* sh_a;
+    new_sh_audio(demux,aid);
+    sh_a = (sh_audio_t*)demux->a_streams[aid];
+    switch(aid & 0xE0){  // 1110 0000 b  (high 3 bit: type  low 5: id)
+      case 0x00: sh_a->format=0x50;break; // mpeg
+      case 0xA0: sh_a->format=0x10001;break;  // dvd pcm
+      case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
+                  else sh_a->format=0x2000;break; // ac3
+    }
+    if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
+  }
+  if(demux->audio->id==-1) demux->audio->id=aid;
+}
+
 static int demux_mpg_read_packet(demuxer_t *demux,int id){
   int d;
   int len;
@@ -190,10 +210,7 @@
 
 //        aid=128+(aid&0x7F);
         // aid=0x80..0xBF
-
-        if(!demux->a_streams[aid]) new_sh_audio(demux,aid);
-        if(demux->audio->id==-1) demux->audio->id=aid;
-
+        new_audio_stream(demux, aid);
       if(demux->audio->id==aid){
         int type;
         ds=demux->audio;
@@ -250,8 +267,7 @@
   if(id>=0x1C0 && id<=0x1DF){
     // mpeg audio
     int aid=id-0x1C0;
-    if(!demux->a_streams[aid]) new_sh_audio(demux,aid);
-    if(demux->audio->id==-1) demux->audio->id=aid;
+    new_audio_stream(demux, aid);
     if(demux->audio->id==aid){
       ds=demux->audio;
       if(!ds->sh) ds->sh=demux->a_streams[aid];
@@ -508,9 +524,7 @@
 }
 
 int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){
-/*    demux_stream_t *d_audio=demuxer->audio;*/
     demux_stream_t *d_video=demuxer->video;
-/*    sh_audio_t *sh_audio=d_audio->sh;*/
     sh_video_t *sh_video=d_video->sh;
     mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
 
@@ -529,6 +543,28 @@
             }
 	    return DEMUXER_CTRL_DONTKNOW;
 
+	case DEMUXER_CTRL_SWITCH_AUDIO:
+            if (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh) {
+              demux_stream_t *d_audio = demuxer->audio;
+              sh_audio_t *sh_audio = d_audio->sh;
+              sh_audio_t *sh_a;
+              int i;
+              for (i = 0; i < mpg_d->num_a_streams; i++) {
+                if (d_audio->id == mpg_d->a_stream_ids[i]) break;
+              }
+              do {
+                i = (i+1) % mpg_d->num_a_streams;
+                sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]];
+              } while (sh_a->format != sh_audio->format);
+              if (d_audio->id != mpg_d->a_stream_ids[i]) {
+                d_audio->id = mpg_d->a_stream_ids[i];
+                d_audio->sh = sh_a;
+                ds_free_packs(d_audio);
+              }
+              *((int *)arg)=(int)d_audio->id;
+            }
+            return DEMUXER_CTRL_OK;
+
 	default:
 	    return DEMUXER_CTRL_NOTIMPL;
     }


More information about the MPlayer-dev-eng mailing list