在 Android 上使用 OpenSL ES 通过套接字通信流式传输 MP3 音频

Posted

技术标签:

【中文标题】在 Android 上使用 OpenSL ES 通过套接字通信流式传输 MP3 音频【英文标题】:Streaming MP3 audio via socket communication using OpenSL ES on Android 【发布时间】:2013-01-14 14:36:19 【问题描述】:

我正在尝试通过接入点使用 WiFi 将 MP3 从 android 手机流式传输到另一部 Android 手机。问题是 OpenSL ES 似乎只支持 PCM 音频缓冲区作为源(除非使用 URI)。与其在发送之前在“主”端解码一个潜在的巨大文件,我更愿意让“客户端”将 MP3 解码为 PCM。请记住,这必须作为文件流发生,而不是简单地发送整个文件然后解码。有什么方法可以使用 OpenSL ES 来实现这一点?音轨?这似乎是一个相当普遍的要求。

【问题讨论】:

【参考方案1】:

您是正确的,opensl 似乎没有使用带有 mp3 源的简单缓冲区队列。话虽如此,您应该能够改用 SLDataLocator_URI。现在,我知道您在开始时没有可用的完整文件(因为您正在流式传输),但是有一种方法可以解决这个问题。如果您创建一个空文件,并将其用作 opensl URI 播放器的源,那么一切都应该正常工作。当您获取数据(mp3 文件的位)时,只需将此数据添加到您创建的空文件中。您可以让 OpenSL 在完成向其附加数据之前从该文件开始播放。

创建一个空文件:

RandomAccessFile raf = new RandomAccessFile(new File(mFileUri), "rw");
raf.setLength(audioFileSize);

将您的音频源创建为:

SLDataLocator_URI loc_uri = SL_DATALOCATOR_URI, (SLchar *) fileLoc;
SLDataFormat_MIME format_mime = SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED;
SLDataSource audiosrc = &loc_uri, &format_mime;

加载缓冲区:

for (int i = 0; i < BUFFER_COUNT; i++) 
    // get byte[] data from stream
    raf.seek(i*Constants.BUFFER_SIZE);
    raf.write(data);

随时使用 OpenSL 开始播放音频,然后继续加载缓冲区。只要您在流式传输过程中保持领先,就应该没问题。

【讨论】:

【参考方案2】:

你必须使用opensl。 MediaCodec(在 Android 4.2 中可用)可以将 mp3 解码为 PCM 块,这些块可以传递给 AudioTrack。

【讨论】:

【参考方案3】:

您是否尝试过 Victor Lazzarini 的 OpenSL ES 音频编程示例 http://audioprograming.wordpress.com/2012/10/29/lock-free-audio-io-with-opensl-es-on-android/

它提供了基于http://mobilepearls.com/labs/native-android-api/ndk/docs/opensles/的良好流实现

【讨论】:

在第一个链接中,音频源在播放时已经是PCM格式。我相信原始海报正在寻找一种使用 MP3 块作为源的方法。 正确。正如 tboling1 所假设的,问题不在于流式传输。在插入音频缓冲区之前,它会将 MP3 流式传输到音频缓冲区或将这些 MP3 块解码为 PCM。

以上是关于在 Android 上使用 OpenSL ES 通过套接字通信流式传输 MP3 音频的主要内容,如果未能解决你的问题,请参考以下文章

Android音视频十三OpenSL ES介绍&基于OpenSL ES实现音频采集

Android音视频十三OpenSL ES介绍&基于OpenSL ES实现音频采集

Android音视频十三OpenSL ES介绍&基于OpenSL ES实现音频采集

Android音视频十三OpenSL ES介绍&基于OpenSL ES实现音频采集

Android 音频录制-OpenSL ES

Android : 如何使用 OpenSL ES 更改音乐的播放速率