(前序:这个号已经申请很久了,一直比较懒,没写过博客,但是最近公司让做一个视频播放器,自己维护下载,解码等功能,期间遇到了很多问题,网上搜了各种资源。总之问题太多,突然感觉应该记录下来以免别人有同样需求时再遇到相同问题,所以,我还是记录一下吧。
由于公司跟广电交流比较多,所以公司服务器上的视频全部是ts流形式的,需求是开发一个可以播放ts流的视频播放器,设计部给的样子感觉跟各大视频网站的样子差不多,就是不知道实现起来会有哪些问题。我一个c语言开发,最近任务较少,直接被拉去做这个播放器了,个人感觉可以学习新东西,也就答应下来了。
思路:其实基本已经做出来了,用NetStream的数据生成模式,先将下载的ts数据解析为很多NALU块,然后再拼装成flv的tag,最后将tag直接appendBytes到NetStream对象中就可以播放出画面了。
出现两个较大问题:1.数据生成模式无法seek 公司的ts流是几个G的大文件,没有切片一说,只能直接下载到结束,seek会将缓存数据清空,暂时做的是从seek的时间点重新请求数据,这导致的结果是每次seek都是新请求,现象为每次seek都会停2s多2.内存占用偏高 用URLStream下载的东西没有暂停,只有close,或者下完才会停止,这就很伤了,一直下载,我本地受不了,多几个请求连服务器那边都受不了。
最后出来是基本满足了需求,但是根本达不到公司要求,还是自己用socket来下载吧,自己控制下载进度,做之前那些工作遇到的问题太多,解决方法什么时候有空再写吧,从今天开始写的是现阶段开始出现的问题的解决方法,希望现在开始记录不会太晚。)
正文:ActionScript3.0 socket获取http响应头
as3 socket的http请求一搜一大把,就不写了,需要注意一点的是,请求头里边是这样的
"GET /web/test.htm HTTP/1.1\r\nHost:.......\r\n\r\n" 需要注意的是HTTP前边有个空格,
之前我写的: var req:String = "GET "+_host+"\r\n"+
"HTTP/1.1\r\n"+
Host:127.0.0.1\r\n"+
.......\r\n\r\n";
其实看了半天感觉挺好的,但就是拿不到响应头,只能拿到test.htm的内容,应该是自己对http请求头学习的不够到位吧。
改: ”GET "+_host+" HTTP/1.1\r\n"+
"Host:127.0.0.1\r\n"+
" ......\r\n\r\n";
由于服务器是公司自己的,这个播放器也是公司自己用,所以在请求头里边加上某些特定字段后,响应头里边会返回很多关于请求的视频的信息。
获取http响应头源码:
package
{
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
public class CommonSocket
{
private var _host:String = null;
private var _port:Number = 80;
private var _buf:ByteArray = new ByteArray;
private var _sock:Socket;
private var _isFirstCome:Boolean = false;
private var _header:String = null;
public function CommonSocket(host:String,port:Number)
{
_host = host;
_port = port;
_sock = new Socket();
_sock.addEventListener(Event.CONNECT, connectHandler, false, 0, true);
_sock.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
_sock.connect(_host, _port);
}
private function connectHandler(evt:Event):void
{
var headers:String = 'GET '+ _path + ' HTTP/1.1\r\n'+ //这个_path是要请求的资源路径,自己从url中解析出来吧
'Host: ' + _host + '\r\n'+
'Accept: */*\r\n'+
'Accept-Encoding: deflate\r\n' + //不要用gzip
'Accept-Language: zh-cn\r\n'+
'Connection: Close\r\n\r\n';
_sock.writeUTFBytes(headers);
_sock.flush();//发送请求
}
private function socketDataHandler(evt:ProgressEvent):void
{
_sock.readBytes(_buf, 0, _sock.bytesAvailable);
if (_isFirstCome) //第一次进来,解析头
{
_isFirstCome = true;
parseHeader(_buf);
}
}
private function parseHeader(b:ByteArray):void
{
var tmp:String = b.readUTFBytes(1);
var flag:int = 0; //用来标志是否出现了\r\n\r\n,即header结尾
var end:Boolean = false;//同上
while(b.bytesAvailable){
switch(tmp){
case '\r':
break;
case '\n'://读到一行结尾,不管
flag ++;
if(flag == 2)
end = true;
break;
default:
flag = 0; //出现字符,标志清0
break;
}
_header += tmp;
if(end) //到结尾了,直接不读了
break;
tmp = b.readUTFBytes(1);//读下一个字符
}
}
public function get header():String{//把header提供出去
return _header;
}
}
}</span></strong>
</span>
拿到header就可以从里边解出自己想要的字段了,都是一些String的相关操作了,直接参考String类的方法就行了。
下次遇到问题再写吧。