论坛首页 Java版 J2ME

自缓冲输入流--构建流媒体的利器

浏览 3713 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-03-28
package redduke.game.j2me.io;

import java.io.IOException;
import java.io.InputStream;

import redduke.game.j2me.util.Util;
/**
 * 自缓冲输入流,用于构建流媒体
 * @author redduke
 * @since 0.6
 */
public class SelfBufferedInputStream extends InputStream
{
	/*
	 * 输入流
	 */
	protected InputStream in;
	/*
	 * 缓冲
	 */
	protected byte[] buf;
	/*
	 * 可读取字节数
	 */
	protected int size=0;
	/*
	 * 缓冲池当前可读位置
	 */
	protected int pos=0;
	
	/*
	 * 流结束
	 */
	protected boolean closed=false;
	
	/*
	 * 自动缓冲比例
	 */
	protected int autoBufferScale=100;
	/**
	 * 构造方法
	 * 缺省缓冲池大小为2048,缺省自动缓冲比例为100
	 */
	public SelfBufferedInputStream(InputStream in) {
		this(in,2048,100);
	}
	/**
	 * 构造方法,指定缓冲池大小,缺省自动缓冲比例为100
	 */
	public SelfBufferedInputStream(InputStream in,int bufferSize)
	{
		this(in,bufferSize,100);
	}
	/**
	 * 构造方法,指定缓冲池大小和自动缓冲比例
	 */
	public SelfBufferedInputStream(InputStream in,int bufferSize,int autoBufferScale)
	{
		this.in=in;
		createBuffer(bufferSize);
		setAutoBufferScale(autoBufferScale);
		startBuffer();		
	}
	/*
	 * 创建缓冲数组
	 */
	private void createBuffer(int bufferSize)
	{
		if(bufferSize<2048)
			bufferSize=2048;
		buf=new byte[bufferSize];
	}
	/**
	 * 读取单个字节
	 * @see java.io.InputStream#read();
	 */
	public int read() throws IOException {
		//结束
		if(closed && size<1)
			return -1;
		//低于缓冲阙值,开始缓冲
		if(!closed && !this.buffering && this.getBufferScale()<this.autoBufferScale)
			this.startBuffer();
		//等待缓冲		
		while(size<1)
		{
			if(size<1 && closed)
				return -1;
			Util.sleep(5);
		}
		//从缓冲中读取
		size--;
		int ret=this.buf[pos++]&0xff;
		pos%=buf.length;
		return ret;
	}
	/**
	 * 返回可读字节数
	 * @see java.io.InputStream#available()
	 */
	public int available() throws IOException {
		return in.available()+size;
	}
	/**
	 * 关闭此流
	 * @see java.io.InputStream#close()
	 */
	public void close() throws IOException {

		this.closed=true;
		in.close();
	}
	/**
	 * @see java.io.InputStream#mark(int)
	 */
	public synchronized void mark(int readlimit) {
	}
	/**
	 * 测试是否支持mark,此类不支持mark
	 */
	public boolean markSupported() {
		return false;
	}
	/**
	 * @see java.io.InputStream#read(byte[], int, int)
	 */
	public int read(byte[] b, int off, int len) throws IOException {
		int read=0;
		int ch;
		for(int i=0;i<len;i++)
			if((ch=read())!=-1)
			{
				b[off+i]=(byte)ch;
				read++;
			}
			else
				return read;
		return len;
	}
	/**
	 * @see java.io.InputStream#read(byte[])
	 */
	public int read(byte[] b) throws IOException {
		int read=0;
		int ch;
		for(int i=0;i<b.length;i++)
			if((ch=read())!=-1)
			{
				b[i]=(byte)ch;
				read++;
			}
			else
				return read;
		return b.length;
	}
	/**
	 * @see java.io.InputStream#read()
	 */
	public synchronized void reset() throws IOException {
	}
	/**
	 * 从输入流跳过n个字节
	 * @see java.io.InputStream#skip(long)
	 */
	public long skip(long n) throws IOException {
		if(n<=0)
			return 0;
		for(long i=0;i<n;i++)
			if(read()==-1)
				return i+1;
		return n;
	}
	/*
	 * 正在缓冲的标记
	 */
	private boolean buffering=false;
	/**
	 * 测试是否正在缓冲
	 */
	public boolean isBuffering()
	{
		return buffering;
	}
	/*
	 * 开始缓冲
	 */
	protected void startBuffer()
	{
		if(buffering || closed)
			return;
		buffering=true;
		new Thread(){
			public void run(){
				buffer();				
			}}.start();
	}
	/*
	 * 缓冲 
	 */
	protected void buffer()
	{
		while(size<this.buf.length)
		{
			int ch=-1;
			try
			{
				ch=in.read();
			}
			catch(IOException ex){
				this.closed=true;
				break;
			}
			
			if(ch==-1)
			{
				this.closed=true;
				break;
			}
			else
			{
				this.buf[(pos+size)%buf.length]=(byte)ch;
				size++;
			}
		}
		buffering=false;
	}
	/**
	 * 获取缓冲池缓冲百分比,如果源数据流已经关闭,则总是返回100
	 */
	public int getBufferScale()
	{
		if(this.closed)
			return 100;
		return this.size*100/buf.length;
	}
	/**
	 * 设置开始自动缓冲的比例
	 * @param scale 如果缓冲池的比例小于scale,则自动缓冲,1~100
	 */
	public void setAutoBufferScale(int scale)
	{
		if(scale<1 || scale>100)
			scale=100;
		this.autoBufferScale=scale;
	}
}
   
最后更新时间:2007-03-28
根据网络和机器性能
调整缓冲池的大小
   
0 请登录后投票
最后更新时间:2007-04-09
没有研究过流媒体,应该说这是一种非常好的缓冲机制。能否再说说服务器端如何配合这种机制呢?
   
0 请登录后投票
最后更新时间:2007-04-10
这种缓冲模式不需要服务器端配合
使用方法:
打开http连接或者socket连接,打开输入流
用输入流构造此自缓冲输入流
然后由此自缓冲输入流构造流媒体,并播放
   
0 请登录后投票
最后更新时间:2007-05-05
的确是好东西,顶,希望像楼主这样有奉献精神的人多些,期待楼主的新文章
   
0 请登录后投票
最后更新时间:2007-05-26
能否写个具体的例子,证明这个缓冲能在流媒体上的作用,
我也打算实现一个流媒体的东西,希望可以跟你多交流
   
0 请登录后投票
最后更新时间:2007-05-26
最近写了一点视频播放方面的测试代码
发现在player realize的时候,会把整个流都读进去,就失去了缓冲的意义
另:缓冲逻辑似乎还有点问题


测试环境设置:
wtk 设置内存512k
视频文件 800k
结果发现realize把800k数据全读进去,才开始播放
   
0 请登录后投票
最后更新时间:2007-05-31
redduke1202 写道
最近写了一点视频播放方面的测试代码
发现在player realize的时候,会把整个流都读进去,就失去了缓冲的意义
另:缓冲逻辑似乎还有点问题


测试环境设置:
wtk 设置内存512k
视频文件 800k
结果发现realize把800k数据全读进去,才开始播放

其实j2me的的视频api暂时还不支持流媒体的功能
好像有些手机支持。不过太少了
   
0 请登录后投票
论坛首页 Java版 J2ME

跳转论坛:
JavaEye推荐