投屏

1,投屏能不能不编码,直接发送yuv?当然不行,投屏的文件很大的。
2,从一个设备投送到另一个设备,数据很大
3,投屏实现原理

左边是推流,右边是拉流。投屏以屏幕录制为主。有投屏层,编码层,传输层

h264推流和拉流

投屏有三种传输方式

推流

package com.maniu.h265maniupush;import static android.media.MediaFormat.KEY_BIT_RATE;
import static android.media.MediaFormat.KEY_FRAME_RATE;
import static android.media.MediaFormat.KEY_I_FRAME_INTERVAL;import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.projection.MediaProjection;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;public class CodecLiveH264 extends Thread {//    录屏private MediaProjection mediaProjection;private MediaCodec mediaCodec;private int width = 720;private int height = 1280;private byte[] sps_pps_buf;VirtualDisplay virtualDisplay;public static final int NAL_I = 5;public static final int NAL_SPS = 7;private SocketLive socketLive;public CodecLiveH264(SocketLive socketLive, MediaProjection mediaProjection) {this.mediaProjection = mediaProjection;this.socketLive = socketLive;}public void startLive() {try {MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);format.setInteger(KEY_BIT_RATE, width * height);format.setInteger(KEY_FRAME_RATE, 20);format.setInteger(KEY_I_FRAME_INTERVAL, 1);mediaCodec = MediaCodec.createEncoderByType("video/avc");mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);Surface surface = mediaCodec.createInputSurface();//创建场地virtualDisplay = mediaProjection.createVirtualDisplay("-display",width, height, 1,DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, surface,null, null);} catch (IOException e) {e.printStackTrace();}start();}@Overridepublic void run() {mediaCodec.start();MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();while (true) {try {int outputBufferId = mediaCodec.dequeueOutputBuffer(bufferInfo,10000);if (outputBufferId >= 0) {ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(outputBufferId);dealFrame(byteBuffer, bufferInfo);mediaCodec.releaseOutputBuffer(outputBufferId, false);}} catch (Exception e) {e.printStackTrace();break;}}}private void dealFrame(ByteBuffer bb, MediaCodec.BufferInfo bufferInfo) {
//0x67      0是否可用        1-2 重要性      后5 位/帧类型int offset = 4;//00 00 00 01if (bb.get(2) == 0x01) {offset = 3;//00 00 01}int type = (bb.get(offset) & 0x1F);//与0x1f相与
//        sps/pps只会输出一份,非常宝贵,必须缓存if (type == NAL_SPS) {//7代表sps.第一帧会走这里sps_pps_buf = new byte[bufferInfo.size];bb.get(sps_pps_buf);//不做操作,I帧发出前再输出sps} else if (NAL_I == type) {//第二帧I帧等于5,第二帧会走这里final byte[] bytes = new byte[bufferInfo.size];bb.get(bytes);//I帧数据大小为45459byte[] newBuf = new byte[sps_pps_buf.length + bytes.length];//sps pps长度+I帧的长度System.arraycopy(sps_pps_buf, 0, newBuf, 0, sps_pps_buf.length);System.arraycopy(bytes, 0, newBuf, sps_pps_buf.length, bytes.length);socketLive.sendData(newBuf);//newBuf就有了sps pps 和I帧的数据,发送走网络只能走socket}else {//p帧和b帧final byte[] bytes = new byte[bufferInfo.size];bb.get(bytes);this.socketLive.sendData(bytes);Log.v("david", "视频数据  " + Arrays.toString(bytes));}}
}

拉流

package com.maniu.h265maniutoupin;import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;import java.io.IOException;
import java.nio.ByteBuffer;public class H264Player implements SocketLive.SocketCallback {private static final String TAG = "H264Player";private MediaCodec mediaCodec;public H264Player(Surface surface) {try {mediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);final MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 720, 1280);format.setInteger(MediaFormat.KEY_BIT_RATE, 720 * 1280);format.setInteger(MediaFormat.KEY_FRAME_RATE, 20);format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);mediaCodec.configure(format,surface,null, 0);mediaCodec.start();} catch (IOException e) {e.printStackTrace();}}
//    收到消息,处理消息
//@Overridepublic void callBack(byte[] data) {Log.i(TAG, "解码器前长度  : " + data.length);//跟读取文件不一样,读取文件需要不断读取分隔符,把分隔符的数据推送到解码器进行解码。//我们收到的data,就是一帧数据,int index = mediaCodec.dequeueInputBuffer(100000);//可用容器的索引if (index >= 0) {//拿到可用的容器ByteBuffer inputBuffer = mediaCodec.getInputBuffer(index);inputBuffer.clear();//数据放到容器中inputBuffer.put(data, 0, data.length);//dsp芯片帮我们解码mediaCodec.queueInputBuffer(index,0, data.length, System.currentTimeMillis(), 0);}MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 100000);Log.i(TAG, "解码器后长度  : " + bufferInfo.size);while (outputBufferIndex >= 0) {//这里最好不写if语句,我们输入100k,输出的大小可能大于100k。mediaCodec.releaseOutputBuffer(outputBufferIndex, true);//输入一个可能输出5个outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);}}
}


输入前的长度是不一样的,如果是i帧会很大

解码后长度一样。

假如传输的时候I P B 帧大小不一样,但解码后,就无所谓ipb帧了,大小就一样了。解码后只跟宽高编码有关 :计算公式为:长x宽x1.5(yuv计算公式)
我们计算下:720x1280x1.5=1382400
y的范围是0-255,一个字节存储

王学岗——————H265实现低延时投屏,从零实现高清无损投屏(对应第六节课)相关推荐

  1. 华为Ascend Mate | 6.1英寸大屏手机 | 零距离高清图赏

    在今年1月份举行的CES大展上,国产品牌华为可谓是出尽了风头,在其大会上,最引人注目的莫过于华为的新一代大屏机器[华为Ascend Mate]了.华为Mate配备了一块6.1英寸的超大屏幕,720P的 ...

  2. 移动端高清、多屏适配方案

    2019独角兽企业重金招聘Python工程师标准>>> 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件 ...

  3. 迅雷看看引领高清内容多屏合一新趋势

    优酷土豆这两大行业领先企业的合并没有像某些人预测的那样,快速促成行业寡头垄断局面的出现,反而刺激了有意角逐这一市场的厂商加快差异化的步伐. 11月23日,迅雷看看正式宣布了将独立运营品牌的重大举措,并 ...

  4. 王学岗——H265编码原理详解与码流分析(对应第五节课)

    H264在分辨率高的情况下缺点 1,94年h264开始研制. 2,现在屏幕变的越来越大.假设h264以16X16进行编码,但我们的屏幕宽达到了32000像素.编码一帧画面需要400000个宏块.94年 ...

  5. iphone主屏幕动态壁纸_灵动优美的iphone高清动态锁屏壁纸

    看惯了千篇一律的静态壁纸,厌烦了自带的动态壁纸,不妨来试试小编给大家精心挑选的几款Live Photos,除了惊艳还是惊艳^_^ 先来几个样张: 大家不要直接将这两张图用作设置为锁屏壁纸,这样就没有原 ...

  6. android下实现4分屏播放4路高清h264格式的rtsp流

    ====================问题描述==================== 用videoview做显示的话.播放一路一点问题都没有,不卡,很实时,但是,多了就播放不了了,还报错.自动弹出 ...

  7. 《王福朋petshop4.0视频教程》新浪视频(高清)

    什么是petshop PetShop是一个范例,微软用它来展示.Net企业系统开发的能力.业界有许多.Net与J2EE之争,许多数据是从微软的PetShop和Sun的PetStore而来.这种争论不可 ...

  8. 浏览器低延时播放监控摄像头RTSP海康大华硬盘录像机NVR视频(EasyNVR播放FLV视频流)

    背景描述 EasyNVR的使用者应该都是清楚的知道,EasyNVR一个强大的功能就是可以进行全平台的无插件直播.主要原因在于rtsp协议的视频流(默认是需要插件才可以播放的)经由EasyNVR处理后可 ...

  9. 详解音视频直播中的低延时

    高泽华,声网 Agora 音频工匠,先后在中磊电子.士兰微电子.虹软科技主导音频项目.任职 YY 期间负责语音音频技术工作.在音乐.语音编解码方面有超过十年的研发经验. 音视频实时通讯的应用场景已经随 ...

最新文章

  1. CMB标量功率谱第二个谱指数跑动项n(2)跑动带来的影响
  2. 重入锁:ReentrantLock 详解
  3. 动态代理案例1:运用Proxy动态代理来增强方法
  4. 02_3中方式的反射,通过Class.forName获得Class对象,通过类.class获得字节码对象,通过类实例.getClass()的方式获得Class对象
  5. 修正 010 Editor 模板文件 MachO.bt 的错误
  6. Unity 2017 Game Optimization 读书笔记(2)Scripting Strategies Part 2
  7. ACM 网址和一些建议
  8. 26. 删除排序数组中的重复项
  9. [导入]将Byte数组转化为String
  10. JAVA中extends 与implements区别
  11. 微信服务通知消息找回_如何通过微信第三方平台群发服务号消息通知?
  12. 细说.NET中的多线程 (四 使用锁进行同步)
  13. hashmap-put方法过程
  14. lenna的真实面目
  15. this绑定丢失的问题
  16. 定时器工作方式0初值除32_理解定时器/计数器的特殊功能寄存器Ⅱ--TCON
  17. 电子护照阅读器|证件阅读机MEPR100+与MEPR100性能分析与差异化对比
  18. android Button 和 TabLayout 英文自动大写的问题
  19. Resources文件夹
  20. 程序员怎么提高英语阅读水平?

热门文章

  1. 【30】GPU(上):为什么玩游戏需要使用GPU?
  2. 浙江电信IPTV+上网 Padavan老毛子固件单线复用
  3. 算法竞赛入门经典——训练指南
  4. 统计学、深度学习、机器学习、数据挖掘
  5. (转)Windows 7 系统下载安装一贴导航
  6. 输入你的密码来连接到_查看电脑已连接的WIFI密码
  7. 装VMware后在主机找不到VMnet1和VMnet8问题(巨详细已解决)
  8. dump文件深度分析
  9. 第十四届蓝桥杯集训——for——判断质数/素数
  10. 栋的月结 | 第二回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)[含泪总结.. 憋泪分享!]