Ted*_*opp 31 audio android playback android-mediaplayer
我在播放存储在原始资源中的mp3文件时遇到了问题:当文件首次开始播放时,它可能会生成四分之一秒的声音,然后重新启动.(我知道这基本上是这里描述的问题的重复,但是那里提供的解决方案对我来说没有用.)我已经尝试了几个方面并且在这个问题上取得了一些进展,但它并没有完全修复.
这是我设置播放文件的方式:
mPlayer.reset();
try {
AssetFileDescriptor afd = getResources().openRawResourceFd(mAudioId);
if (afd == null) {
Toast.makeText(mOwner, "Could not load sound.",
Toast.LENGTH_LONG).show();
return;
}
mPlayer.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
afd.close();
mPlayer.prepare();
} catch (Exception e) {
Log.d(LOG_TAG, "Could not load sound.", e);
Toast.makeText(mOwner, "Could not load sound.", Toast.LENGTH_LONG)
.show();
}
Run Code Online (Sandbox Code Playgroud)
如果我退出活动(调用mPlayer.release()
)并返回它(创建一个新的MediaPlayer),口吃通常(但不总是)消失 - 只要我加载相同的声音文件.我尝试了几件没有任何区别的事情:
MediaPlayer.create(getContext(), mAudioId)
,并跳到调用setDataSource(...)
和prepare()
.然后我注意到LogCat总是在播放开始时显示这一行:
DEBUG/AudioSink(37): bufferCount (4) is too small and increased to 12
Run Code Online (Sandbox Code Playgroud)
它让我想知道口吃是否是由于明显的重新缓解.这导致我尝试别的东西:
prepare()
,拨打电话mPlayer.start()
并立即拨打电话mPlayer.pause()
.令我惊喜的是,这产生了很大的影响.很多口吃都消失了,加上没有声音(我能听到的)实际上是在这个过程中播放的.
然而,当我呼唤mPlayer.start()
真实时,它仍然不时地口吃.此外,这似乎是一个巨大的kludge.有没有办法完全干净地解决这个问题?
编辑更多信息; 不确定是否相关.如果我pause()
在播放过程中拨打电话,寻找较早的位置,然后start()
再次拨打电话,我会听到一声短暂的声音(约1/4秒)从暂停播放到新位置之前暂停.这似乎指向更多的缓冲问题.
此外,口吃(和暂停的缓冲区)问题出现在1.6到3.0的仿真器上.
Reu*_*ton 67
AFAIK MediaPlayer内部创建的缓冲区用于存储解压缩的样本,而不是用于存储预取的压缩数据.我怀疑你的口吃来自I/O缓慢,因为它加载了更多的MP3数据进行解压缩.
我最近不得不解决视频播放的类似问题.由于MediaPlayer
无法发挥任意性InputStream
(API非常蹩脚),我提出的解决方案是编写一个小型进程内Web服务器,通过HTTP提供本地文件(在SD卡上).MediaPlayer
然后通过形式为http://127.0.0.1:8888/videofilename的URI加载它.
编辑:
下面是我用来将内容提供给MediaPlayer实例的StreamProxy类.基本用法是你实例化它,start()它,并设置你的媒体播放器MediaPlayer.setDataSource("http://127.0.0.1:8888/localfilepath");
我应该注意到它是相当实验性的,可能并非完全没有bug.它是为解决类似问题而编写的,即MediaPlayer无法播放也正在下载的文件.以这种方式在本地流式传输文件可以解决这个限制(即我有一个线程下载文件,而StreamProxy将它传送到mediaplayer).
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.Looper;
import android.util.Log;
public class StreamProxy implements Runnable {
private static final int SERVER_PORT=8888;
private Thread thread;
private boolean isRunning;
private ServerSocket socket;
private int port;
public StreamProxy() {
// Create listening socket
try {
socket = new ServerSocket(SERVER_PORT, 0, InetAddress.getByAddress(new byte[] {127,0,0,1}));
socket.setSoTimeout(5000);
port = socket.getLocalPort();
} catch (UnknownHostException e) { // impossible
} catch (IOException e) {
Log.e(TAG, "IOException initializing server", e);
}
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void stop() {
isRunning = false;
thread.interrupt();
try {
thread.join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
Looper.prepare();
isRunning = true;
while (isRunning) {
try {
Socket client = socket.accept();
if (client == null) {
continue;
}
Log.d(TAG, "client connected");
StreamToMediaPlayerTask task = new StreamToMediaPlayerTask(client);
if (task.processRequest()) {
task.execute();
}
} catch (SocketTimeoutException e) {
// Do nothing
} catch (IOException e) {
Log.e(TAG, "Error connecting to client", e);
}
}
Log.d(TAG, "Proxy interrupted. Shutting down.");
}
private class StreamToMediaPlayerTask extends AsyncTask<String, Void, Integer> {
String localPath;
Socket client;
int cbSkip;
public StreamToMediaPlayerTask(Socket client) {
this.client = client;
}
public boolean processRequest() {
// Read HTTP headers
String headers = "";
try {
headers = Utils.readTextStreamAvailable(client.getInputStream());
} catch (IOException e) {
Log.e(TAG, "Error reading HTTP request header from stream:", e);
return false;
}
// Get the important bits from the headers
String[] headerLines = headers.split("\n");
String urlLine = headerLines[0];
if (!urlLine.startsWith("GET ")) {
Log.e(TAG, "Only GET is supported");
return false;
}
urlLine = urlLine.substring(4);
int charPos = urlLine.indexOf(' ');
if (charPos != -1) {
urlLine = urlLine.substring(1, charPos);
}
localPath = urlLine;
// See if there's a "Range:" header
for (int i=0 ; i<headerLines.length ; i++) {
String headerLine = headerLines[i];
if (headerLine.startsWith("Range: bytes=")) {
headerLine = headerLine.substring(13);
charPos = headerLine.indexOf('-');
if (charPos>0) {
headerLine = headerLine.substring(0,charPos);
}
cbSkip = Integer.parseInt(headerLine);
}
}
return true;
}
@Override
protected Integer doInBackground(String... params) {
long fileSize = GET CONTENT LENGTH HERE;
// Create HTTP header
String headers = "HTTP/1.0 200 OK\r\n";
headers += "Content-Type: " + MIME TYPE HERE + "\r\n";
headers += "Content-Length: " + fileSize + "\r\n";
headers += "Connection: close\r\n";
headers += "\r\n";
// Begin with HTTP header
int fc = 0;
long cbToSend = fileSize - cbSkip;
OutputStream output = null;
byte[] buff = new byte[64 * 1024];
try {
output = new BufferedOutputStream(client.getOutputStream(), 32*1024);
output.write(headers.getBytes());
// Loop as long as there's stuff to send
while (isRunning && cbToSend>0 && !client.isClosed()) {
// See if there's more to send
File file = new File(localPath);
fc++;
int cbSentThisBatch = 0;
if (file.exists()) {
FileInputStream input = new FileInputStream(file);
input.skip(cbSkip);
int cbToSendThisBatch = input.available();
while (cbToSendThisBatch > 0) {
int cbToRead = Math.min(cbToSendThisBatch, buff.length);
int cbRead = input.read(buff, 0, cbToRead);
if (cbRead == -1) {
break;
}
cbToSendThisBatch -= cbRead;
cbToSend -= cbRead;
output.write(buff, 0, cbRead);
output.flush();
cbSkip += cbRead;
cbSentThisBatch += cbRead;
}
input.close();
}
// If we did nothing this batch, block for a second
if (cbSentThisBatch == 0) {
Log.d(TAG, "Blocking until more data appears");
Thread.sleep(1000);
}
}
}
catch (SocketException socketException) {
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
}
catch (Exception e) {
Log.e(TAG, "Exception thrown from streaming task:");
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
e.printStackTrace();
}
// Cleanup
try {
if (output != null) {
output.close();
}
client.close();
}
catch (IOException e) {
Log.e(TAG, "IOException while cleaning up streaming task:");
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
e.printStackTrace();
}
return 1;
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
26227 次 |
最近记录: |