[gst-devel] AAC -> AC3 -> SPDIF (via Alsa)

Matt Piermarini mattpiermarini at yahoo.com
Fri May 19 07:34:27 CEST 2006


Hello all.

First, I'd like to mention I've only learned about gstreamer a week ago,
and I'm not really a coder, so please bear with me.

I recently moved my Media Center (Athlon 64 3200) from windows (meedio,
they sold out) to linux and MythTV.  My main purpose for this thing is to
watch my DVD collection, which I've encoded into MP4 using Nero Recode. 
Nero produces H264 video and AAC 5.1 audio in a mp4 container.  I have the
PC connected to a external receiver via the SPDIF digital connection. 
Since most receivers don't decode AAC (at least not in the USA), and I
need to use the SPDIF, the only way to get 5.1 is AC3 or DTS.  In the
windows world, ffdshow has the ability to dynamically convert 6 channel
AAC to 6 channel AC3, then pass via SPDIF. I can not find such
functionality in the Linux world.

I was going back to windoze, then I stumbled on gstreamer.  After screwing
around for a week or so, I came up with this pipeline:

gst-launch-0.10 -v  --gst-debug-level=0 filesrc location=XX.mp4  ! qtdemux
name=mp4demux  mp4demux. ! queue ! ffdec_h264 !  xvimagesink mp4demux. !
queue ! faad ! audioconvert !  ffenc_ac3 !  ac3iec958 raw-audio=true !
audioconvert ! audioresample !  alsasink device=spdif

This only produces 2-channel audio (not 5.1), so I looked at the ffenc_ac3
ffmpeg plugin and say that it's sink only accepted 2 channels
(gst-inspect-0.10 ffenc_ac3).  So, I got the gst FFMPEG source and
modified "gstffmpegcodecmap.c" and changed the 1, 2 to a 1, 8 as seen here

#define GST_FF_AUD_CAPS_NEW(mimetype, ...)                      \
    (context != NULL) ?                                         \
    gst_caps_new_simple (mimetype,                              \
        "rate", G_TYPE_INT, context->sample_rate,               \
        "channels", G_TYPE_INT, context->channels,              \
        __VA_ARGS__, NULL)                                      \
    :                                                           \
    gst_caps_new_simple (mimetype,                              \
        "rate", GST_TYPE_INT_RANGE, 8000, 96000,                \
        "channels", GST_TYPE_INT_RANGE, 1, 8,                   \
        __VA_ARGS__, NULL)

Now, I DO get 5.1 AC3 audio dynamically over the SPDIF with my AAC files.
So, not being really familiar w/gst, my questions

0) I'm not sure if the way I changed the code will break anything else. 
Is there a better way to change the ffenc_ac3 sink to accept [1,8]
channels?

1) The video is jerky, even with a basic pipleline w/o AAC->AC3.  I think
I didn't comple FFMPEG properly, as the libgstffmpeg.so file is 9.5MB (vs
3.2).  I just pulled it from CVS, and ran autogen.sh.  The sound seems ok,
just the video is jerky.  Any hints on here?

2) Is the pipeline above optimized?  Do I need to add clocks or buffers?

3) The audio channel mappings are not correct. For example, the CENTER
comes out the LeftRight speaker, etc.   Is there any way to remap
channels?

4) Any suggestions on what media player I can use with the above pipeline.
It needs to support LIRC for remote control.

Thanks a million!
Matt


PS: Here is the basic output from the above pipeline:
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/pipeline0/queue0.sink: caps = video/x-h264,
codec_data=(buffer)014d0028ffe10015674d0028ab201684f602200000030020000006528001000468eaed48,
width=(int)720, height=(int)304, framerate=(fraction)25/1
/pipeline0/queue0.src: caps = video/x-h264,
codec_data=(buffer)014d0028ffe10015674d0028ab201684f602200000030020000006528001000468eaed48,
width=(int)720, height=(int)304, framerate=(fraction)25/1
/pipeline0/ffdec_h2640.sink: caps = video/x-h264,
codec_data=(buffer)014d0028ffe10015674d0028ab201684f602200000030020000006528001000468eaed48,
width=(int)720, height=(int)304, framerate=(fraction)25/1
/pipeline0/ffdec_h2640.src: caps = video/x-raw-yuv, width=(int)720,
height=(int)304, framerate=(fraction)25/1, format=(fourcc)I420,
pixel-aspect-ratio=(fraction)1/1
/pipeline0/xvimagesink0.sink: caps = video/x-raw-yuv, format=(fourcc)I420,
width=(int)720, height=(int)304, framerate=(fraction)25/1,
pixel-aspect-ratio=(fraction)1/1
/pipeline0/queue1.sink: caps = audio/mpeg, mpegversion=(int)4,
framed=(boolean)true, codec_data=(buffer)133056e598, rate=(int)24000,
channels=(int)6
/pipeline0/queue1.src: caps = audio/mpeg, mpegversion=(int)4,
framed=(boolean)true, codec_data=(buffer)133056e598, rate=(int)24000,
channels=(int)6
/pipeline0/faad0.sink: caps = audio/mpeg, mpegversion=(int)4,
framed=(boolean)true, codec_data=(buffer)133056e598, rate=(int)24000,
channels=(int)6
/pipeline0/faad0.src: caps = audio/x-raw-int, endianness=(int)1234,
signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)48000,
channels=(int)6, channel-positions=(GstAudioChannelPosition)<
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE >
/pipeline0/audioconvert0.src: caps = audio/x-raw-int,
endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16,
rate=(int)48000, channels=(int)6,
channel-positions=(GstAudioChannelPosition)<
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE >
/pipeline0/audioconvert0.sink: caps = audio/x-raw-int,
endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16,
rate=(int)48000, channels=(int)6,
channel-positions=(GstAudioChannelPosition)<
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE >
/pipeline0/ffenc_ac30.src: caps = audio/x-ac3, rate=(int)48000,
channels=(int)6
/pipeline0/ffenc_ac30.sink: caps = audio/x-raw-int, endianness=(int)1234,
signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)48000,
channels=(int)6, channel-positions=(GstAudioChannelPosition)<
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE >
/pipeline0/ac3iec0.sink: caps = audio/x-ac3, rate=(int)48000,
channels=(int)6
/pipeline0/audioconvert1.src: caps = audio/x-raw-int,
endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16,
rate=(int)48000, channels=(int)2/pipeline0/audioconvert1.sink: caps =
audio/x-raw-int, endianness=(int)4321, signed=(boolean)true,
width=(int)16, depth=(int)16, rate=(int)48000, channels=(int)2
/pipeline0/audioresample0.src: caps = audio/x-raw-int,
endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16,
rate=(int)48000, channels=(int)2
/pipeline0/audioresample0.sink: caps = audio/x-raw-int,
endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16,
rate=(int)48000, channels=(int)2
/pipeline0/alsasink0.sink: caps = audio/x-raw-int, endianness=(int)1234,
signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)48000,
channels=(int)2
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: audioclock0
Caught interrupt -- Pausing pipeline.
Pipeline paused.
WARNING: Element "pipeline0" warns: pipeline interrupted
Element "pipeline0" has gone from PLAYING to PAUSED, quitting.
Execution ended after 7032884000 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
/pipeline0/alsasink0.sink: caps = NULL
/pipeline0/xvimagesink0.sink: caps = NULL
/pipeline0/audioresample0.sink: caps = NULL
/pipeline0/audioresample0.src: caps = NULL
/pipeline0/ffdec_h2640.sink: caps = NULL
/pipeline0/ffdec_h2640.src: caps = NULL
/pipeline0/audioconvert1.sink: caps = NULL
/pipeline0/audioconvert1.src: caps = NULL
/pipeline0/queue0.sink: caps = NULL
/pipeline0/queue0.src: caps = NULL
/pipeline0/ac3iec0.sink: caps = NULL
/pipeline0/ac3iec0.src: caps = NULL
/pipeline0/ffenc_ac30.sink: caps = NULL
/pipeline0/ffenc_ac30.src: caps = NULL
/pipeline0/audioconvert0.sink: caps = NULL
/pipeline0/audioconvert0.src: caps = NULL
/pipeline0/faad0.sink: caps = NULL
/pipeline0/faad0.src: caps = NULL
/pipeline0/queue1.sink: caps = NULL
/pipeline0/queue1.src: caps = NULL
/pipeline0/mp4demux.audio_00: caps = NULL
/pipeline0/mp4demux.video_00: caps = NULL
Setting pipeline to NULL ...
FREEING pipeline ...


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 




More information about the gstreamer-devel mailing list