zoukankan      html  css  js  c++  java
  • h.264 to avi

    参考资料:

    http://blog.csdn.net/sunnylion1982/article/details/38376453

    http://blog.csdn.net/happydeer/article/details/8775

    http://blog.csdn.net/zhujinghao_09/article/details/44458245

    https://github.com/Sebmaster/avi.js

    http://blog.csdn.net/yi7900/article/details/7481599

    代码:

    debugger;
    var record=new Worker("/js/media/record.js")
    record.onmessage=function (e) {
    if(e.data.type=="blob"){
    var blob=e.data.data
    var a=document.createElement("a")
    var url=URL.createObjectURL(blob)
    a.href=url
    document.documentElement.appendChild(a)
    a.download="guxi.avi"
    a.id="guxi"
    a.click()
    }
    }

    代码:

    "use strict";

    (function() {

    /**
    * @param {Uint8Array} buf
    * @param {number} idx
    * @param {Array.<number>} bytes
    */
    function writeBytes(buf, idx, bytes) {
    for (var i=0; i < bytes.length; ++i) {
    buf[idx + i] = bytes[i];
    }
    }

    /**
    * @param {Uint8Array} buf
    * @param {number} idx
    * @param {number} num
    */
    function writeShort(buf, idx, num) {
    buf[idx] = num & 255;
    buf[idx + 1] = (num >> 8) & 255;
    }

    /**
    * @param {Uint8Array} buf
    * @param {number} idx
    * @param {number} num
    */
    function writeInt(buf, idx, num) {
    buf[idx] = num & 255;
    buf[idx + 1] = (num >> 8) & 255;
    buf[idx + 2] = (num >> 16) & 255;
    buf[idx + 3] = (num >> 24) & 255;
    }

    /**
    * @param {number} idx
    * @param {string} str
    */
    function writeString(buf, idx, str) {
    for (var i=0; i < str.length; ++i) {
    buf[idx + i] = str.charCodeAt(i) & 255;
    }
    }


    ///////////////////////////////////////////////////////avi数据结构
    //12 "RIFF" SIZE(TYPE+DATA) "AVI "
    //12 "LIST" SIZE(TYPE+DATA) "hdrl"
    //64 AVIMAINHEADER数据结构--"avih" 56+8=64
    //12 "LIST" SIZE "strl"
    //"strh" AVISTREAMHEADER 数据结构 64=56+8
    //"strf" BITMAPINFO数据结构 或 WAVEFORMATEX数据结构 48=40+8 或 38=30+8
    //多个流 两个 视频+音频
    //12 LIST size MOVI
    ///////////////////////////////////////////////////////////////////

    /**
    * @constructor
    */
    function AVIJS(width,height,fps) {
    this.settings = {
    "width": width,
    "height": height,
    "fps":fps
    };
    /** @type {Array.<Object{"data","type"}>} */
    this.frames = [];
    };

    AVIJS.prototype.getBuffer = function() {
    var headerInfoNum=88+124;
    var frames=this.frames.length//所有帧
    var vframe=0;//视频帧
    var aframe=0;//音频帧
    var bytes=0;//所有帧的字节数
    for(var i=0;i<this.frames.length;i++){
    if(this.frames[i].type=="video"){
    vframe++
    }else{
    aframe++
    }
    bytes+=this.frames[i].data.length+(this.frames[i].data.length%2==0?0:1)
    }
    var dataNum=frames*8+12+bytes;//数据及其头的字节数


    var buffer = new Uint8Array(headerInfoNum + dataNum);

    //前88位
    writeString(buffer, 0, 'RIFF');
    writeInt(buffer, 4, headerInfoNum + dataNum-8);
    writeString(buffer, 8, 'AVI ');
    writeString(buffer, 12, 'LIST');
    writeInt(buffer, 16, headerInfoNum-20);//88+124+114
    writeString(buffer, 20, 'hdrl');
    //AVIMAINHEADER数据结构
    writeString(buffer, 24, 'avih');
    writeInt(buffer, 28, 56);
    writeInt(buffer, 32, 1000000/this.settings.fps);
    writeInt(buffer, 36, 0);
    writeInt(buffer, 40, 0);
    writeInt(buffer, 44, 0);
    writeInt(buffer, 48, 0);
    writeInt(buffer, 52, 0); //为交互格式指定初始帧数(非交互格式应该指定为0)
    writeInt(buffer, 56, 2);
    writeInt(buffer, 60, 0);
    writeInt(buffer, 64, this.settings.width);
    writeInt(buffer, 68, this.settings.height);
    writeInt(buffer, 72, 0);
    writeInt(buffer, 76, 0);
    writeInt(buffer, 80, 0);
    writeInt(buffer, 84, 0);

    //视频头信息 124
    var vbuf=new Uint8Array(124)
    writeString(vbuf, 0, 'LIST');
    writeInt(vbuf, 4, 116);
    writeString(vbuf, 8, 'strl');
    writeString(vbuf, 12, 'strh');
    writeInt(vbuf, 16, 56);
    writeString(vbuf, 20, 'vids'); //流的类型
    writeString(vbuf, 24, 'H264'); //解码器
    writeInt(vbuf, 28, 0); //标记:是否允许这个流输出?调色板是否变化?
    writeShort(vbuf, 32, 0); // Priority
    writeShort(vbuf, 34, 0); // Language
    writeInt(vbuf, 36, 0); // Initial frames
    writeInt(vbuf, 40, 1); // Scale
    writeInt(vbuf, 44, this.settings.fps*1); // Rate:fps*scale
    writeInt(vbuf, 48, 0); // Startdelay
    writeInt(vbuf, 52, 500); // Length
    writeInt(vbuf, 56, 0); // suggested buffer size
    writeInt(vbuf, 60, 0); // quality
    writeInt(vbuf, 64, 0); // sampleSize
    writeShort(vbuf, 68, 0); // Rect left
    writeShort(vbuf, 70, 0); // Rect top
    writeShort(vbuf, 72, this.settings.width); // Rect width
    writeShort(vbuf, 74, this.settings.height); // Rect height
    writeString(vbuf, 76, 'strf');
    writeInt(vbuf, 80, 40);
    writeInt(vbuf, 84, 40); // struct size
    writeInt(vbuf, 88, this.settings.width); // width
    writeInt(vbuf, 92, this.settings.height); // height
    writeShort(vbuf, 96, 1); // planes
    writeShort(vbuf, 98, 16); // bits per pixel
    writeString(vbuf, 100, "H264"); // compression
    writeInt(vbuf, 104, 0); // image size 是否乘以3????
    writeInt(vbuf, 108, 0); // x pixels per meter
    writeInt(vbuf, 112, 0); // y pixels per meter
    writeInt(vbuf, 116, 0); // colortable used
    writeInt(vbuf, 120, 0); // colortable important
    buffer.set(vbuf,88);

    // //音频头信息 114
    // var abuf=new Uint8Array(114);
    // writeString(abuf, 0, 'LIST');
    // writeInt(abuf, 4, 106);
    // writeString(abuf, 8, 'strl');
    // writeString(abuf, 12, 'strh');
    // writeInt(abuf, 16, 56);
    // writeString(abuf, 20, 'auds'); //流的类型
    // writeString(abuf, 24, 'PCM '); //解码器 0x55
    // writeInt(abuf, 28, 0); //标记
    // writeShort(abuf, 32, 0); // Priority
    // writeShort(abuf, 34, 0); // Language
    // writeInt(abuf, 36, 0); // Initial frames
    // writeInt(abuf, 40, 1); // Scale
    // writeInt(abuf, 44, 30); // Rate 0x5dc0
    // writeInt(abuf, 48, 0); // Startdelay
    // writeInt(abuf, 52, frames-500); // Length 0x1d19c0
    // writeInt(abuf, 56, 1024*1024); // suggested buffer size 0x240
    // writeInt(abuf, 60, 0xffffffff); // quality
    // writeInt(abuf, 64, 0);
    // writeShort(abuf, 68, 0);
    // writeShort(abuf, 70, 0);
    // writeShort(abuf, 72, 0);
    // writeShort(abuf, 74, 0);
    // //WAVEFORMATEX数据结构
    // writeString(abuf, 76, 'strf');
    // writeInt(abuf, 80, 30);
    // writeShort(abuf,84,1)//wFormatTag pcm
    // writeShort(abuf,86,1)//nChannels 通道
    // writeInt(abuf,88,8000)//nSamplesPerSec 采样率
    // writeInt(abuf,92,16000)//nAvgBytesPerSec 平均数据传输率
    // writeShort(abuf,96,2)//nBlockAlign 最小数据的原子大小
    // writeShort(abuf,98,0)//wBitsPerSample
    // writeShort(abuf,100,0)//cbSize
    // writeShort(abuf,102,1)
    // writeShort(abuf,104,2)
    // writeShort(abuf,106,0)
    // writeShort(abuf,108,32772)
    // writeShort(abuf,110,1)
    // writeShort(abuf,112,0)
    // buffer.set(abuf,212);


    writeString(buffer,headerInfoNum,"LIST")
    writeInt(buffer,headerInfoNum+4,dataNum-8)
    writeString(buffer,headerInfoNum+8,"movi")

    var offset=headerInfoNum+12;
    for(var i=0;i<this.frames.length;i++){
    var tmpnum=this.frames[i].data.length+8+(this.frames[i].data.length%2==0?0:1)
    var tmp=new Uint8Array(tmpnum)
    if(this.frames[i].type=="video"){
    writeString(tmp,0,"00dc")
    }else{
    writeString(tmp,0,"01wb")
    }
    writeInt(tmp,4,tmpnum-8)
    writeBytes(tmp,8,this.frames[i].data)
    buffer.set(tmp,offset)
    offset+=tmpnum
    }
    var blob;
    try {
    blob = new Blob([buffer.buffer], { 'type' : 'video/msvideo' });
    } catch (e) {
    var builder = new (typeof BlobBuilder !== 'undefined' ? BlobBuilder : WebKitBlobBuilder)();
    builder.append(buffer.buffer);
    blob = builder.getBlob('video/msvideo');
    }

    return blob;
    };
    var scope = new Function('return this')();
    scope['AVIJS'] = AVIJS;
    })();
  • 相关阅读:
    摄像机Rtsp地址格式大全
    Html5 播放Hls格式视频
    Libx264 编码错误 Input picture width(320) is greater than stride (0)
    xtrabackup: error: last checkpoint LSN (3409281307) is larger than last copied LSN (3409274368). #2
    通过FEDERATED存储引擎同步两实例间的表数据
    MySQL将内存用在了哪里
    通过performance schema收集慢查询
    记一次定时备份任务的失败原因
    mysqld got signal 11
    修改mysql数据的字符集校验规则使其区分大小写
  • 原文地址:https://www.cnblogs.com/callmeguxi/p/6734738.html
Copyright © 2011-2022 走看看