Android上的MP3解码 [英] MP3 Decoding on Android

查看:653
本文介绍了Android上的MP3解码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在为Android手机实现一个程序,该程序可以播放从互联网流式传输的音频.这大约是我们的工作:

We're implementing a program for Android phones that plays audio streamed from the internet. Here's approximately what we do:

  1. 下载自定义加密格式.
  2. 解密以获取常规MP3数据块.
  3. 在内存缓冲区中将MP3数据解码为原始PCM数据.
  4. 将原始PCM数据插入到AudioTrack

到目前为止,我们的目标设备是Droid和Nexus One.一切都可以在Nexus One上正常运行,但Droid上的MP3解码速度太慢.如果将Droid置于负载下,音频播放将开始跳过.我们不允许将MP3数据解码到SD卡,但是我知道这绝对不是我们的问题.

Our target devices so far are Droid and Nexus One. Everything works great on Nexus One, but the MP3 decode is too slow on Droid. The audio playback starts to skip if we put the Droid under load. We are not permitted to decode the MP3 data to SD card, but I know that's not our problem anyways.

我们没有编写自己的MP3解码器,而是使用了MPADEC( http://sourceforge.net/项目/mpadec/).它是免费的,并且很容易与我们的程序集成.我们使用NDK进行编译.

We didn't write our own MP3 decoder, but used MPADEC (http://sourceforge.net/projects/mpadec/). It's free and was easy to integrate with our program. We compile it with the NDK.

在使用各种配置工具进行详尽的分析之后,我们确信正是这种解码器落后了.

After exhaustive analysis with various profiling tools, we're convinced that it's this decoder that is falling behind.

以下是我们正在考虑的选项:

Here's the options we're thinking about:

  1. 找到另一个可以与Android NDK一起编译的MP3解码器.这种MP3解码器必须经过优化才能在移动ARM设备上运行,或者可能使用纯整数数学或其他一些优化来提高性能.

  1. Find another MP3 decoder that we can compile with the Android NDK. This MP3 decoder would have to be either optimized to run on mobile ARM devices or maybe use integer-only math or some other optimizations to increase performance.

由于内置的​​Android MediaPlayer服务将使用URL,因此我们可以在程序中实现一个微型HTTP服务器,并为解密的MP3提供MediaPlayer服务.这样我们就可以利用内置的MP3解码器.

Since the built-in Android MediaPlayer service will take URLs, we might be able to implement a tiny HTTP server in our program and serve the MediaPlayer with the decrypted MP3s. That way we can take advantage of the built-in MP3 decoder.

通过NDK访问内置的MP3解码器.我不知道这是否可能.

Get access to the built-in MP3 decoder through the NDK. I don't know if this is possible.

有人对我们可以如何加快MP3解码速度有任何建议吗?

Does anyone have any suggestions on what we can do to speed up our MP3 decoding?

- 罗伯·史密斯(Rob Sz)

-- Rob Sz

推荐答案

做到这一点的正确方法是构建自己的固件,并作为自定义OpenCORE编解码器的一部分进行解密.当然,这会将您限制在可以安装该固件的设备上.

The right way to do this is to build your own firmware and do the decryption as part of a custom OpenCORE codec. That, of course, will limit you to devices where you can install that firmware.

请记住,其余的内容都是推测性的.实际上,我需要做与您描述的内容类似的事情,但是几个月来我没有时间解决这个问题.因此,我将以解决问题的方式对此进行描述.

Bear in mind that the rest of this is somewhat speculative. I actually have a need to do something similar to what you're describing, but I don't have time set aside to tackle the problem for a couple of months. So, I'll describe this in the fashion of how I'd approach the problem.

一种解决方案是twk的答案中描述的解决方案.您不必使用SD卡,但可能必须在应用程序本地文件存储(getFilesDir())中拥有一个世界可读的临时文件.下载第一个块,解密,将其写为一个完整的世界可读MP3文件(但具有适当的模糊目录/路径),然后通过setDataSource()将其交给MediaPlayer.在播放的同时,您下载/解密并设置第二个MediaPlayer实例,该实例在第一个实例结束时立即开始播放,以尽可能无缝地进行过渡.然后,您重置第一个MediaPlayer并将其与第三个块重用,在两个块之间进行ping操作.

One solution is the one described in twk's answer. You don't have to use the SD card, but you probably do have to have a world-readable temporary file in your app-local file store (getFilesDir()). Download the first chunk, decrypt it, write it out as a complete world-readable MP3 file (but with a suitably obscure directory/path), and hand it to a MediaPlayer via setDataSource(). While that plays, you download/decrypt and set up a second MediaPlayer instance, which starts playback as soon as the first one ends, for as seamless a transition as possible. You then reset the first MediaPlayer and reuse it with your third chunk, ping-ponging between the two.

一个相关的解决方案将在jleedev的评论中.除了通过ContentProvider提供FileDescriptor之外,几乎是同一回事.该选项可以让您使用套接字,而可以可以让您避免使用临时文件.但是,ContentProvider本身必须是可公开访问的,因此带有晦涩目录的临时文件实际上可能会更私有.

A related solution would be in jleedev's comment. It's pretty much the same thing, except that you provide a FileDescriptor via a ContentProvider. This has an option to let you use a socket, which may let you avoid the temporary file. However, the ContentProvider will have to itself be publicly accessible, and so the temporary file, with an obscure directory, might actually be more private.

如果您担心这些内容可以被其他进程读取,请理解MediaPlayer本身(或OpenCORE子系统)在另一个进程中.同样,您建议的HTTP服务器在设备上也是世界可读的.因此,如果要让MediaPlayer进行解码,那么隐秘的安全性是唯一可行的选择.

If you are worried about the fact that these things can be read by other processes, please understand that MediaPlayer itself (or, rather, the OpenCORE subsystem) is in another process. Also, your proposed HTTP server is world-readable on the device as well. So, security by obscurity is your only viable option if you are going to let MediaPlayer do the decoding.

AFAIK,尽管我承认对NDK的经验有限,但NDK并不授予对OpenCORE的访问权,所以我可能是错的.当然还可以使用其他MP3解码器(ffmpeg/mplayer等),尽管尚不清楚这些解码器可以多么容易地转换为NDK库.

AFAIK, the NDK does not grant access to OpenCORE, though I confess as to having limited NDK experience, so I may be wrong. There are certainly other MP3 decoders available (ffmpeg/mplayer, etc.), though how readily these could be converted into an NDK library is unclear.

因此,这实际上归结为您要防御的对象.如果您要防御用户,则可能必须自己以某种方式对其进行解码.

So, it really boils down to who you're trying to defend against. If you're trying to defend against the user, you're probably going to have to decode it yourself, somehow.

这篇关于Android上的MP3解码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆