11
2020
12

使用PIXI播放Yuv422视频

公司实现了自己的视频播放器,自己解码,生成Yuv422数据,然后用WebGL显示。

现在我们想要在pixi中渲染Yuv视频数据。

第一步,实现自己的render。参考:pixi自定义shader-BatchPluginFactory

第二步,写一个自己的Sprite,重写_render方法。

PIXI中,BatchRender的渲染流程是:

start-render-flush

flush之前,可以调用多次render。

Sprite默认的_render:

_render(renderer)
{
    this.calculateVertices();

    renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
    renderer.plugins[this.pluginName].render(this);
}

重写之后:

_render(renderer) {
      this.calculateVertices();
      renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
      for(let i = 0; i < this.textureArr.length; i++) {
          this.texture = this.textureArr[i];
          renderer.plugins[this.pluginName].render(this);
      }
      this.texture = this.textureArr[0];
  }

可以发现,我们调用了多次render。每次切换一个Texture,热农户调用render。因为没有调flush,所有的Texture都被上传了,存在了uniform sampler2D uSamplers[%count%]中。然后我们就可以在片段着色器中取纹理的像素,进行处理了。

完整代码:

(function(){
  const fragment = `
  varying vec2 vTextureCoord;
  varying vec4 vColor;
  varying float vTextureId;
  uniform sampler2D uSamplers[%count%];


  const mat4 YUV2RGB = mat4(
      1.1643828125, 0, 1.59602734375, -.87078515625,
      1.1643828125, -.39176171875, -.81296875, .52959375,
      1.1643828125, 2.017234375, 0, -1.081390625,
      0, 0, 0, 1
  );

  void main(void){
      vec4 color;
      %forloop%

      highp float y = texture2D(uSamplers[0],  vTextureCoord).r;
      highp float u = texture2D(uSamplers[1],  vTextureCoord).r;
      highp float v = texture2D(uSamplers[2],  vTextureCoord).r;
      gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;
  }
  `;
  const YuvBatchRenderer = PIXI.BatchPluginFactory.create({fragment});
  PIXI.Renderer.registerPlugin('yuvBatch', YuvBatchRenderer);
})();

class YuvSprite extends PIXI.Sprite {
  
  constructor(yData, cbData, crData, width, height){
    super();
    this.textureArr = [
      PIXI.Texture.fromBuffer(yData, width, height, {format: PIXI.FORMATS.LUMINANCE}),
      PIXI.Texture.fromBuffer(cbData, width / 2, height / 2, {format: PIXI.FORMATS.LUMINANCE}),
      PIXI.Texture.fromBuffer(crData, width / 2, height / 2, {format: PIXI.FORMATS.LUMINANCE})
    ];
    this.yData = yData;
    this.cbData = cbData;
    this.crData = crData;
    this.pluginName = 'yuvBatch';
    this.texture = this.textureArr[0];
  }

  destroy(options) {
    super.destroy(options);
    this.textureArr = null;
    this.yData = null;
    this.cbData = null;
    this.crData = null;
  }

  setYuvData(yData, cbData, crData){
    this.yData.set(yData);
    this.cbData.set(cbData);
    this.crData.set(crData);
    this.textureArr.forEach((texture) => {
      texture.update();
    });
  }

  _render(renderer) {
      this.calculateVertices();
      renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
      for(let i = 0; i < this.textureArr.length; i++) {
          this.texture = this.textureArr[i];
          renderer.plugins[this.pluginName].render(this);
      }
      this.texture = this.textureArr[0];
  }
}


« 上一篇下一篇 »

相关文章:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。