精华内容
下载资源
问答
  • mediacodec
    2022-03-16 17:00:51

    MediaCodec解码方式

            

            一般是有16个盒子进行存放处理数据

             左边客户端从codec的左边队列中取出空的盒子,将需要解码的数据放入此盒子中,交给codec,codec再将数据交给dsp进行解码

            解码的数据放入右端的队列中,给到接收数据方,接收数据方再讲数据渲染到手机上,在渲染之后,需要把盒子给释放掉,Codec能够继续进行解码

     mediaCodec.getInputBuffers();        不推荐此用法

    左边的输入队列是所有app使用的,mediaCodec.getInputBuffers();是获取左边输入队列的所有盒子,如果获取所有的盒子,会有安全问题        

    H264解码代码

            

    package com.thundersoft.mediacodecdemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.pm.PackageManager;
    import android.media.MediaCodec;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    import java.io.File;
    
    public class MainActivity extends AppCompatActivity {
        SurfaceView surfaceView;
        String path;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            checkPermission();
    
            surfaceView = findViewById(R.id.sfv);
            path = new File(Environment.getExternalStorageDirectory(),"out.h264").getAbsolutePath();
            initSurfaceView();
        }
    
        public void initSurfaceView(){
            SurfaceHolder holder = surfaceView.getHolder();
    
            holder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    H264Player h264Player = new H264Player(MainActivity.this,path,holder.getSurface());
                    h264Player.play();
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
    
                }
            });
        }
    
    
    
        public boolean checkPermission() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(
                    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                }, 1);
    
            }
            return false;
        }
    }

            

    package com.thundersoft.mediacodecdemo;
    
    import android.content.Context;
    import android.media.MediaCodec;
    import android.media.MediaFormat;
    import android.util.Log;
    import android.view.Surface;
    import java.io.ByteArrayOutputStream;
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.nio.ByteBuffer;
    
    public class H264Player implements Runnable{
    
        private static final String TAG = "H264Player";
        Context context;
        String path;
        Surface surface;
    
        MediaCodec mediaCodec;
    
        public H264Player(Context context, String path, Surface surface) {
            this.context = context;
            this.path = path;
            this.surface = surface;
    
            try{
                mediaCodec = MediaCodec.createDecoderByType("video/avc");
                //配置视频的宽高,如果宽高不对,会出现花屏状态
                MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",368,384);
                //设置帧率为15帧
                mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,15);
    
                //第2个参数代表只能往一个地方传输数据,是能往手机屏幕端,或者网络端传输
                //第3个参数代表是否要加密
                mediaCodec.configure(mediaFormat,surface,null,0);
    
            }catch (Exception e){
                //如果报异常,可能底层不支持该解码方式
                e.printStackTrace();
            }
    
        }
    
        public void decodeH264(){
    
            byte[] bytes = null;
            try{
                bytes = getBytes(path);
    
                //获取mediaCodec所有的输入端队列的盒子
                ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
    
                //获取一帧开始的索引
                int statrFrame = 0;
                //获取下一帧的索引
                int nextFrame = 0;
    
                //获取总长度
                int totalFrame = bytes.length;
    
                //设置一个空盒子获取mediaCodec解码队列解码后的数据
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                //开始解码每一帧数据
                while(true){
                    if (totalFrame == 0 || statrFrame >= totalFrame){
                        break;
                    }
                    //获取一帧的开始
                    nextFrame = getNextFrame(bytes,statrFrame+2,totalFrame);
                    //获取当前闲置的输入队列的盒子
                    int inIndex = mediaCodec.dequeueInputBuffer(10000);
                    if (inIndex > 0){
                        //获取到一个空盒子对象
                        ByteBuffer inputBuffer = inputBuffers[inIndex];
                        inputBuffer.clear();
                        //将空盒子对象中填充数据
                        inputBuffer.put(bytes,statrFrame,nextFrame-statrFrame);
                        mediaCodec.queueInputBuffer(inIndex,0,nextFrame - statrFrame,0,0);
    
                        //为下一帧做准备
                        statrFrame = nextFrame;
                    }else{
                        //未获取到闲置的队列的盒子
                        continue;
                    }
    
                    //获取解码后的数据
                    // 在规定的时间内获取解码后的数据的队列的索引
                    int outIndex = mediaCodec.dequeueOutputBuffer(info, 10000);
    
                    if (outIndex > 0){
                        //如果之前已经设置过需要绑定的surface则第二个参数为true
                        //渲染的代码底层已经写好
                        Thread.sleep(33);
                        mediaCodec.releaseOutputBuffer(outIndex,true);
                    }else{
                        Log.e(TAG, "没有解码成功");
                    }
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        private int getNextFrame(byte[] bytes,int statrFrame, int totalFrame) {
            for (int i = statrFrame; i < totalFrame - 4; i++){
                if (bytes[i] == 0x00 && bytes[i+1] == 0x00 && bytes[i+2] == 0x00 &&bytes[i+3] == 0x01){
                    return i;
                }
            }
            return -1;
        }
    
        private byte[] getBytes(String path) throws IOException {
            InputStream is = new DataInputStream(new FileInputStream(new File(path)));
            int len;
            int size = 1024;
            byte[] buf;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            buf = new byte[size];
            while((len = is.read(buf,0,size)) != -1){
                baos.write(buf,0,len);
            }
            buf = baos.toByteArray();
            return buf;
        }
    
        public void play(){
            mediaCodec.start();
            new Thread(this).start();
        }
    
        @Override
        public void run() {
            decodeH264();
        }
    }

    音视频开发中缓冲区尽量都用全局变量

            如果使用Camera时,摄像头捕捉到的画面会一直往缓冲区写入数据,如果声明一个局部变量接收接收画面数据,当接收完数据此变量又会被立即销毁,如此反复容易造成栈溢出,摄像头捕捉到的画面都是YUV数据(没有被压缩的数据)假如一帧画面2M,在栈中会形成锯齿状的画面

    摄像头捕捉到的画面模糊(花屏)

            宽高设置有问题

    安卓摄像头捕捉到的画面格式与推流使用的画面格式

            安卓摄像头捕捉到的画面为NV21

            

             推流使用的画面格式为NV12别名(YUVI420)

            

    webrtc适合视频通话,不适合短视频播放

            编码格式vp8/vp9谷歌开发

    更多相关内容
  • 这是通过MediaCodec进行的JPEG / M-JPEG测试应用程序。 这也可能是一个很好的教程,说明如何在Android上使用MediaCodec API 。 必需品 测试之前,应将输入帧放入目标的外部存储中。 对于编码器测试,将10个YUV帧...
  • 将Camera数据显示到OpenGL ES渲染的图像中,并通过MediaCodeC 将 OpenGL ES 缓冲数据,硬编码写入到 mp4 视频文件中,完成视频的录制。
  • MediaCodec_Mirroring

    2021-06-01 03:17:10
    使用 MediaCodec 进行镜像。 它在后台运行。 因此,它不会停止中断。 ※ 打断 ? 呼叫,消息,主页按钮等。 服务器 使用 getDrawingCache() 获取位图。 位图到字节[] 字节[]到编码器 从 Encoder 获取 Byte[]...
  • 本文实例为大家分享了Android使用MediaCodec将摄像头采集的视频编码为h264,供大家参考,具体内容如下 MainActivity.java import android.app.Activity; import android.graphics.ImageFormat; import android....
  • 对应的文章《【Android 视频硬件编码】在Native层实现MediaCodec H264 编码 Demon》 压缩包中含源代码,转换前后的图片,编译后的可执行程序
  • MediacodecDemo.zip

    2020-06-29 00:59:24
    Android MediaCodec+OpenGL视频编解码 H264编码以及保存视频 H264解码渲染 Opengl绘制相机视频帧 VP8解码渲染(工程根目录下out.vp8是一段使用libvpx中demo编码的vp8视频,ivf封装,可以使用IVFDataReader读取) H...
  • MediaCodec NDK

    2018-09-16 21:39:21
    ffmpeg MediaCodec NDK SurfaceTexture 因为Demo中大部分是工程的代码,不便上传。只提供核心代码。
  • MediaCodec 投屏demo

    2018-11-21 09:56:04
    投屏功能的实现,MediaCodec编解码,MediaProjection获取屏幕视频,WebSocket传视频数据,SurfaceView显示。
  • 适用于Android的高性能视频压缩器,使用硬件解码和编码API(MediaCodec)。 演示版 用法 调用compressVideoLow,compressVideoMedium和compressVideoHigh,表示3种压缩质量。 VideoCompressTask task = ...
  • mediacodec c++.

    热门讨论 2016-12-11 22:19:55
    实现在Android4.1以上的系统直接在jni c++ 使用MediaCodec,无需Android5.0以上。 提供了C++代码加载so库并动态导出符号的方法
  • Android 版 FLV 播放器(用于实验) 使用 MediaCodec 播放 flv 的测试应用程序。由于使用终端标准解码器,因此可以使用紧凑的硬件解码器。音频:mp3、aac视频:H.264/AVC H.263 也将得到支持,但 Sorenson H.263 ...
  • Android RTSP H264播放客户端。自己组包,喂给Android MediaCodec解码器,实时播放直播流。史上最简单的demo。亲测在三星S8+,小米平板,华为平板,摩托罗拉手机可用。
  • 媒体编解码器示例展示了 MediaCodec 的用例用例。 对于在 H.264 中(例如)通过网络等进行编码、解码和传输样本的应用程序来说,它可能很有价值。 示例包含: 创建要绘制的表面和关联的画布将表面绑定到编码器以生成...
  • RK3399-MediaCodec C++使用

    2018-01-23 20:23:18
    通过native C++调用mediaCodec
  • Mediacodec

    2013-04-01 23:40:24
    Mediacodec
  • #Android MediaCodec 示例 API 级别 21 是必需的 视频播放流程 1.MediaExtractor set source video resource (R.raw.xxx) 2.MediaExtractor get video type (In MediaFormat) and select first video track ("video...
  • Android 硬解码MediaCodecDemo

    热门讨论 2017-12-12 18:54:10
    1 MediaCodec硬解码demo 2 包含h264码流资源 3 包含如何处理硬解码过程中出现的各种crash/anr/黑屏
  • 实时MediaCodec音频硬编解码,音频录制,编码,解码,播放都正常,本人已亲自测试
  • Rtmp Live Publish Kit 是简洁的 Android 平台直播推流SDK,使用 Mediacodec进行H264 和 AAC 编码, 网络部分 Java 重写了RTMP协议,方便阅读定位,YUV处理考虑性能采用了LibYUV。整体延时在1-3秒左右。 A simple ...
  • 支持从摄像头采集图像,并用MediaCodec API进行硬编码,编码后的数据保存到一个H264文件。这个例子也支持软编码,使用的是FFmpeg。
  • 本Demo使用MediaCodec解码AAC音频数据,解码之后直接使用AudioTrack播放PCM音频数据
  • ⠀ 寻找强大的相机库来拍摄视频吗? 看看我们的 。 需要支持,咨询或有任何其他与业务有关的问题? 随时。 像该项目一样,从中获利,还是只是想回头? 请考虑!转码器使用设备上可用的硬件加速的Android编解码器,将...
  • 使用mediacodec/mediamuxer的同时音频和视频录制示例
  • 博客 用于记录生活,学习,工作等内容。 面试 颤振系列 数据结构和算法系列 Java源码分析 Android原始分析 第三方流行框架源码分析 性能优化系列 移动架构师系列 ...如果这个面试题库对您很有帮助,可以扫描下方二维码...
  • Android利用MediaCodec硬解码H264,AAC文件并播放Demo [注:本内容来自网络,在此分享仅为帮助有需要的网友,如果侵犯了您的权利,麻烦联系我,我会第一时间删除,谢谢您。]
  • Android MediaCodec 实现Camera预览帧数据编解码并投射至另外的SurfaceView显示,另外附加Camera2的使用。
  • MediaCodec 解码音频输出PCM数据,和播放PCM数据文件的库 AAR 库生成方法: 1、修改根目录的 config.gradle 的 isDebugType = false (true 是调试模式生成的是app) 2、直接运行批处理文件 build-aar.bat (这个就是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,028
精华内容 3,611
关键字:

mediacodec