首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >android查找代理流和stagefright播放器的问题

android查找代理流和stagefright播放器的问题
EN

Stack Overflow用户
提问于 2011-01-13 03:52:14
回答 4查看 2.4K关注 0票数 3

我想播放来自url的音频流,该url仅在一段时间内有效。由于缓冲机制的原因,仅仅使用内置的stagefright流功能并不能很好地发挥作用(当第二次填充缓冲区时,url将是死的),因此我实现了一个代理流,类似于npr应用程序中的操作。

http://code.google.com/p/npr-android-app/source/browse/trunk/Npr/src/org/npr/android/news/StreamProxy.java

这实际上工作得非常好,除了一个例外,任何seek调用都会有效地破坏代理流。我很难确定在stagefright中寻找到底是如何工作的。每次我寻找的时候我都会得到一条信息

代码语言:javascript
复制
01-12 13:35:57.201: ERROR/(4870): Connection reset by peer
01-12 13:35:57.201: ERROR/(4870): java.net.SocketException: Connection reset by peer
01-12 13:35:57.201: ERROR/(4870): at org.apache.harmony.luni.platform.OSNetworkSystem.writeSocketImpl(Native Method)
01-12 13:35:57.201: ERROR/(4870):     at org.apache.harmony.luni.platform.OSNetworkSystem.write(OSNetworkSystem.java:723)
01-12 13:35:57.201: ERROR/(4870):     at org.apache.harmony.luni.net.PlainSocketImpl.write(PlainSocketImpl.java:578)
01-12 13:35:57.201: ERROR/(4870):     at org.apache.harmony.luni.net.SocketOutputStream.write(SocketOutputStream.java:59)
01-12 13:35:57.201: ERROR/(4870):     at com.soundcloud.utils.StreamProxy.processRequest(StreamProxy.java:209)

然后暂停几秒钟,然后stagefright重试连接到相同的url,通常会抛出一个错误(我可以想象,因为代理流还没有被重置)。另一个潜在的问题是,代理流似乎总是线性地读取数据源:

代码语言:javascript
复制
while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) 

我只是猜测,但我认为为了支持查找,代理必须能够在从缓冲区读取时提供偏移量。有没有办法计算出从套接字客户端请求的偏移量(预期的寻道位置)?

我在套接字方面的经验有限。有人对这里的实现有什么建议吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-03-13 08:45:24

MediaPlayer发出HTTP range请求,指定播放器期望的字节偏移量。您可以从提交给代理服务器的请求标头中读取这些范围值。然后,您可以打开“仅将这些范围发送回MediaPlayer”。

票数 1
EN

Stack Overflow用户

发布于 2013-01-21 10:46:43

当您查找或跳过或连接丢失而MediaPlayer不断重新连接到代理服务器时,您必须在收到客户端的请求和范围(整型)后发送状态为206的响应。

代码语言:javascript
复制
String headers += "HTTP/1.1 206 OK\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + (fileSize-range) + "\r\n";
headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n";
headers += "\r\n";

当你收到一个来自MediaPlayer的请求,该请求不包含HTTP头中的Range,那么它就是在请求一个新的流文件,在这种情况下,你的响应头应该是这样的:

代码语言:javascript
复制
String headers = "HTTP/1.1 200 OK\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + fileSize + "\r\n";
headers += "\r\n";

享受吧!

票数 2
EN

Stack Overflow用户

发布于 2012-05-31 13:34:23

我不确定你是否弄明白了这一点,但我所需要做的就是把头从原始请求传递到代理请求:

代码语言:javascript
复制
  private HttpResponse download(String url, Header[] headers) {
DefaultHttpClient seed = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
SingleClientConnManager mgr = new MyClientConnManager(seed.getParams(),
    registry);
DefaultHttpClient http = new DefaultHttpClient(mgr, seed.getParams());
HttpGet method = new HttpGet(url);
for (Header header : headers) {
    method.addHeader(header);
}
HttpResponse response = null;
try {
  Log.d(getClass().getName(), "starting download");
  response = http.execute(method);
  Log.d(getClass().getName(), "downloaded");

}catch(java.net.UnknownHostException e)
{
    Intent i=new Intent("org.prx.errorInStream");
    mContext.sendBroadcast(i);
}
catch (ClientProtocolException e) {
  Log.e(getClass().getName(), "Error downloading", e);
} catch (IOException e) {
  Log.e(getClass().getName(), "Error downloading", e);
}
return response;

}

代码语言:javascript
复制
private void processRequest(HttpRequest request, Socket client)
  throws IllegalStateException, IOException {
if (request == null) {
  return;
}
Log.d(getClass().getName(), "processing");
String url = request.getRequestLine().getUri();

HttpResponse realResponse = download(url, request.getAllHeaders());

if (realResponse == null) {
  return;
}

...

}

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4673362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档