[PATCH 5/6] ffplay: add support for selecting a single audio channel

Anssi Hannula anssi.hannula
Fri Jul 16 05:55:11 CEST 2010


---
 doc/ffplay-doc.texi |   12 +++++++++---
 ffplay.c            |   45 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/doc/ffplay-doc.texi b/doc/ffplay-doc.texi
index 5e8032f..724cc9a 100644
--- a/doc/ffplay-doc.texi
+++ b/doc/ffplay-doc.texi
@@ -108,6 +108,9 @@ Select the desired subtitle stream number, counting from 0. The number
 refers to the list of all the input subtitle streams. If it is greater
 than the number of subtitle streams minus one, then the last one is
 selected, if it is negative the subtitle rendering is disabled.
+ at item -ach @var{audio_channel_number}
+Select the desired audio channel number, counting from 0. Negative
+values select all channels (default behavior).
 @item -autoexit
 Exit when video is done playing.
 @item -exitonkeydown
@@ -129,13 +132,16 @@ Toggle full screen.
 Pause.
 
 @item a
-Cycle audio channel.
+Cycle audio stream.
 
 @item v
-Cycle video channel.
+Cycle video stream.
 
 @item t
-Cycle subtitle channel.
+Cycle subtitle stream.
+
+ at item c
+Cycle audio channel.
 
 @item w
 Show audio waves.
diff --git a/ffplay.c b/ffplay.c
index 4f254df..eaea568 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -161,6 +161,7 @@ typedef struct VideoState {
     AVPacket audio_pkt;
     enum SampleFormat audio_src_fmt;
     AVAudioConvert *reformat_ctx;
+    int output_channels;
 
     int show_audio; /* if true, display audio samples */
     int16_t sample_array[SAMPLE_ARRAY_SIZE];
@@ -238,6 +239,7 @@ static int wanted_stream[AVMEDIA_TYPE_NB]={
     [AVMEDIA_TYPE_VIDEO]=-1,
     [AVMEDIA_TYPE_SUBTITLE]=-1,
 };
+static int wanted_channel = -1;
 static int seek_by_bytes=-1;
 static int display_disable;
 static int show_status = 1;
@@ -823,7 +825,7 @@ static void video_audio_display(VideoState *s)
     nb_freq= 1<<(rdft_bits-1);
 
     /* compute display index : center on currently output samples */
-    channels = s->audio_st->codec->channels;
+    channels = s->output_channels;
     nb_display_channels = channels;
     if (!s->paused) {
         int data_used= s->show_audio==1 ? s->width : (2*nb_freq);
@@ -1037,7 +1039,7 @@ static double get_audio_clock(VideoState *is)
     bytes_per_sec = 0;
     if (is->audio_st) {
         bytes_per_sec = is->audio_st->codec->sample_rate *
-            2 * is->audio_st->codec->channels;
+            2 * is->output_channels;
     }
     if (bytes_per_sec)
         pts -= (double)hw_buf_size / bytes_per_sec;
@@ -1947,7 +1949,7 @@ static void update_sample_display(VideoState *is, short *samples, int samples_si
 {
     int size, len, channels;
 
-    channels = is->audio_st->codec->channels;
+    channels = is->output_channels;
 
     size = samples_size / sizeof(short);
     while (size > 0) {
@@ -1971,7 +1973,7 @@ static int synchronize_audio(VideoState *is, short *samples,
     int n, samples_size;
     double ref_clock;
 
-    n = 2 * is->audio_st->codec->channels;
+    n = 2 * is->output_channels;
     samples_size = samples_size1;
 
     /* if not master, then we try to remove or add samples to correct the clock */
@@ -2099,10 +2101,20 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
                 is->audio_buf= is->audio_buf1;
             }
 
+            if (wanted_channel >= 0 && wanted_channel < dec->channels) {
+                uint16_t *in_buf = (uint16_t *)is->audio_buf;
+                uint16_t *out_buf = (uint16_t *)(is->reformat_ctx ? is->audio_buf1 : is->audio_buf2);
+                int i = 0;
+                for (uint16_t *p = in_buf + wanted_channel; p - in_buf < data_size; p += dec->channels)
+                    out_buf[i++] = *p;
+                is->audio_buf = (uint8_t *)out_buf;
+                data_size /= dec->channels;
+            }
+
             /* if no pts, then compute it */
             pts = is->audio_clock;
             *pts_ptr = pts;
-            n = 2 * dec->channels;
+            n = 2 * is->output_channels;
             is->audio_clock += (double)data_size /
                 (double)(n * dec->sample_rate);
 #if defined(DEBUG_SYNC)
@@ -2231,9 +2243,14 @@ static int stream_component_open(VideoState *is, int stream_index)
 
     /* prepare audio output */
     if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (wanted_channel >= 0 && wanted_channel < avctx->channels)
+            is->output_channels = 1;
+        else
+            is->output_channels = avctx->channels;
+
         wanted_spec.freq = avctx->sample_rate;
         wanted_spec.format = AUDIO_S16SYS;
-        wanted_spec.channels = avctx->channels;
+        wanted_spec.channels = is->output_channels;
         wanted_spec.silence = 0;
         wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
         wanted_spec.callback = sdl_audio_callback;
@@ -2740,6 +2757,17 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
     stream_component_open(is, stream_index);
 }
 
+static void stream_cycle_audio_channel(VideoState *is)
+{
+    int stream_index = is->audio_stream;
+    if (stream_index < 0)
+        return;
+    wanted_channel = FFMAX(wanted_channel, -1);
+    if (++wanted_channel >= is->ic->streams[stream_index]->codec->channels)
+        wanted_channel = -1;
+    stream_component_close(is, stream_index);
+    stream_component_open(is, stream_index);
+}
 
 static void toggle_full_screen(void)
 {
@@ -2842,6 +2870,10 @@ static void event_loop(void)
                 if (cur_stream)
                     stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
                 break;
+            case SDLK_c:
+                if (cur_stream)
+                    stream_cycle_audio_channel(cur_stream);
+                break;
             case SDLK_w:
                 toggle_audio_display();
                 break;
@@ -3045,6 +3077,7 @@ static const OptionDef options[] = {
     { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_AUDIO]}, "select desired audio stream", "stream_number" },
     { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_VIDEO]}, "select desired video stream", "stream_number" },
     { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" },
+    { "ach", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_channel}, "select desired audio channel", "channel_number" },
     { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
     { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play  \"duration\" seconds of audio/video", "duration" },
     { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" },
-- 
1.7.1


--Boundary-00=_ZzOQMxVxT486NZ+
Content-Type: text/plain;
  charset="iso-8859-15";
  name="0006-ffmpeg-add-support-for-selecting-a-single-audio-chan.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
	filename="0006-ffmpeg-add-support-for-selecting-a-single-audio-chan.patch"




More information about the ffmpeg-devel mailing list