Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >mediacodec解码ffmpeg AvPacket

mediacodec解码ffmpeg AvPacket

作者头像
曾大稳
发布于 2018-09-11 02:32:36
发布于 2018-09-11 02:32:36
1.8K00
代码可运行
举报
文章被收录于专栏:曾大稳的博客曾大稳的博客
运行总次数:0
代码可运行
初始化MediaCodec
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

private MediaFormat mediaFormat;
private MediaCodec mediaCodec;
private MediaCodec.BufferInfo info;
private Surface surface;//这个是OpenGL渲染的Surface

/**
 * 初始化MediaCodec
 *
 * @param codecName
 * @param width
 * @param height
 * @param csd_0
 * @param csd_1
 */
public void initMediaCodec(String codecName, int width, int height, byte[] csd_0, byte[] csd_1) {
        try {
          if (surface != null) {
                String mime = VideoSupportUtil.findVideoCodecName(codecName);
                mediaFormat = MediaFormat.createVideoFormat(mime, width, height);
                mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
                mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(csd_0));
                mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd_1));
                MyLog.d(mediaFormat.toString());
                mediaCodec = MediaCodec.createDecoderByType(mime);
                info = new MediaCodec.BufferInfo();
                if(mediaCodec == null) {
                    MyLog.d("craete mediaCodec wrong");
                    return;
                }
                mediaCodec.configure(mediaFormat, surface, null, 0);
                mediaCodec.start();
          }
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 
}

VideoSupportUtil.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制


import android.media.MediaCodecList;

import java.util.HashMap;
import java.util.Map;

public class VideoSupportUtil {

    private static Map<String, String> codecMap = new HashMap<>();
    static {
        codecMap.put("h264", "video/avc");
    }

    public static String findVideoCodecName(String ffcodename){
        if(codecMap.containsKey(ffcodename))
        {
            return codecMap.get(ffcodename);
        }
        return "";
    }

    public static boolean isSupportCodec(String ffcodecname){
        boolean supportvideo = false;
        int count = MediaCodecList.getCodecCount();
        for(int i = 0; i < count; i++){
            String[] tyeps = MediaCodecList.getCodecInfoAt(i).getSupportedTypes();
            for(int j = 0; j < tyeps.length; j++){
                if(tyeps[j].equals(findVideoCodecName(ffcodecname))){
                    supportvideo = true;
                    break;
                }
            }
            if(supportvideo){
                break;
            }
        }
        return supportvideo;
    }
}

c++层:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制



const char* codecName = ((const AVCodec*)avCodecContext->codec)->name;
onCallInitMediacodec(
                codecName,
                avCodecContext->width,
                avCodecContext->height,
                avCodecContext->extradata_size,
                avCodecContext->extradata_size,
                avCodecContext->extradata,
                avCodecContext->extradata
        );

//获取jmid_initmediacodec
jclass  jlz = jniEnv->GetObjectClass(jobj);
jmethodID jmid_initmediacodec = env->GetMethodID(jlz, "initMediaCodec", "(Ljava/lang/String;II[B[B)V");

//在子线程
void onCallInitMediacodec(const char* mime, int width, int height, int csd0_size, int csd1_size, uint8_t *csd_0, uint8_t *csd_1) {

    JNIEnv *jniEnv;
    if(javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK)
    {
        if(LOG_DEBUG)
        {
            LOGE("call onCallComplete worng");
        }
    }

    jstring type = jniEnv->NewStringUTF(mime);
    jbyteArray csd0 = jniEnv->NewByteArray(csd0_size);
    jniEnv->SetByteArrayRegion(csd0, 0, csd0_size, reinterpret_cast<const jbyte *>(csd_0));
    jbyteArray csd1 = jniEnv->NewByteArray(csd1_size);
    jniEnv->SetByteArrayRegion(csd1, 0, csd1_size, reinterpret_cast<const jbyte *>(csd_1));

    jniEnv->CallVoidMethod(jobj, jmid_initmediacodec, type, width, height, csd0, csd1);

    jniEnv->DeleteLocalRef(csd0);
    jniEnv->DeleteLocalRef(csd1);
    jniEnv->DeleteLocalRef(type);
    javaVM->DetachCurrentThread();

}
解码AvPacket数据
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void decodeAVPacket(int datasize, byte[] data) {
    if (surface != null && datasize > 0 && data != null) {
        int intputBufferIndex = mediaCodec.dequeueInputBuffer(10);
        if (intputBufferIndex >= 0) {
            ByteBuffer byteBuffer = mediaCodec.getOutputBuffers()[intputBufferIndex];
            byteBuffer.clear();
            byteBuffer.put(data);
            mediaCodec.queueInputBuffer(intputBufferIndex, 0, datasize, 0, 0);
        }
        //这里拿到outputBufferIndex然后就可以获取到数据,这里会通过surface达到渲染
        int outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
        while (outputBufferIndex >= 0) {
            mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
            outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
        }
    }
}

c++层回调decodeAVPacket

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
datasize = avPacket->size;
data = avPacket->data;//jni这里需要把uint8_t转为jbyteArray,类似初始化那
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
OpenGLES渲染画面通过MediaCodec录制
通过fbo处理视频数据,通过samplerExternalOES纹理来创建SurfaceTexture,这样的话摄像头数据就和fbo相关联,具体可以看OpenGLES通过SurfaceTexture预览摄像头画面
曾大稳
2018/09/11
2.3K0
OpenGLES渲染画面通过MediaCodec录制
Android原生编解码接口 MediaCodec 之——踩坑
MediaCodec 有两种方式触发输出关键帧,一是由配置时设置的 KEY_FRAME_RATE 和KEY_I_FRAME_INTERVAL参数自动触发,二是运行过程中通过 setParameters 手动触发输出关键帧。
全栈程序员站长
2022/11/01
6.8K1
Android原生编解码接口 MediaCodec 之——踩坑
给Android工程师的音视频教程之一文弄懂MediaCodec
音视频学习项目:LearnVideo AndroidMediaCodecDemo
老马的编程之旅
2022/06/23
1.9K0
给Android工程师的音视频教程之一文弄懂MediaCodec
MediaCodec录制音视频并将合成为一个文件
音频录制 相关参考 MediaCodec硬编码pcm2aac 主要分为以下几步骤:
曾大稳
2020/01/20
2.4K0
MediaCodec录制音视频并将合成为一个文件
手写 Android 录屏直播
观看手游直播时,我们观众端看到的是选手的屏幕上的内容,这是如何实现的呢?这篇博客将手写一个录屏直播 Demo,实现类似手游直播的效果。
字节流动
2021/06/09
2.1K0
手写 Android 录屏直播
Android PC投屏简单尝试(录屏直播)2—硬解章(MediaCodec+RMTP)
代码地址 :https://github.com/deepsadness/MediaProjectionDemo
deep_sadness
2018/12/10
3K0
Android PC投屏简单尝试(录屏直播)2—硬解章(MediaCodec+RMTP)
Android MediaCodec 使用说明
最近公司要求提供一个支持 Android 硬件转码的底层库,所以自己从头去看了 MediaCodec 相关的知识,费了老大的劲终于完成了。
字节流动
2021/03/16
1.9K0
Android MediaCodec 使用说明
Android MediaCodec 硬编码 H264 文件
在 Android 4.1 版本提供了 MediaCodec 接口来访问设备的编解码器,不同于 FFmpeg 的软件编解码,它采用的是硬件编解码能力,因此在速度上会比软解更具有优势,但是由于 Android 的碎片化问题,机型众多,版本各异,导致 MediaCodec 在机型兼容性上需要花精力去适配,并且编解码流程不可控,全交由厂商的底层硬件去实现,最终得到的视频质量不一定很理想。
音视频开发进阶
2019/11/18
3.6K0
「音视频直播技术」Android下视频H264编码
今天为大家介绍一下音视频直播技术中的视频编码。在移动端通过Camera采集到视频数据后,我们不会直接将它发送出去。因为采集后的视频数据量非常大,比如 1280x720 分辨率的一帧数据,就有可能达到6M大小(码率越高,图像越清晰)。这6M数据如果送到网上传输,会给网络带来非常大的负担。
音视频_李超
2020/04/01
1.9K0
「音视频直播技术」Android下视频H264编码
Android FFmpeg + MediaCodec 实现视频硬解码
本文将利用 FFmpeg+ MediaCodec 做一个播放器,实现视频的硬解码和音视频同步等功能。
字节流动
2022/01/05
3.9K0
Android FFmpeg + MediaCodec 实现视频硬解码
使用 MediaExtractor 及 MediaCodec 解码音视频
大家好,本文是 iOS/Android 音视频专题 的第四篇,从本篇文章开始我们将动手编写代码。代码工程将在 Github 进行托管。
100001509164
2022/01/20
2.7K0
使用 MediaExtractor 及 MediaCodec 解码音视频
Android 获取视频缩略图(获取视频每帧数据)的优化方案
注意:如果不缩小图片的话,建议还是使用MediaMetadataRetriever。 使用当前库的话,调用metadataRetriever.forceFallBack(true);
deep_sadness
2019/01/28
5K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】六、Android音视频硬编码:生成一个MP4
在【音视频硬解码流程:封装基础解码框架】这篇文章中,介绍了如何使用Android原生提供的硬编解码工具MediaCodec,对视频进行解码。同时,MediaCodec也可以实现对音视频的硬编码。
开发的猫
2020/04/02
2.2K1
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】六、Android音视频硬编码:生成一个MP4
Android平台硬件编码总结一
MediaCodec编码的套路 状态 来自官网的状态图 codec_status.png 创建 find Support Codec 通过这种方式可以得到当前设备所有的MedaCodecInfo
deep_sadness
2018/08/30
2.8K0
Android平台硬件编码总结一
【Android 音视频开发打怪升级:音视频硬解码篇】三、音视频播放:音视频同步
在上一篇文章定义的解码流程框架基类中,预留了几个虚函数,留给子类初始化自己的东西,本篇,就来看看如何实现。
开发的猫
2020/04/01
2.6K0
【Android 音视频开发打怪升级:音视频硬解码篇】三、音视频播放:音视频同步
MediaCodec基本原理及使用「建议收藏」
MediaCodec类Android提供的用于访问低层多媒体编/解码器接口,它是Android低层多媒体架构的一部分,通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,能够编解码诸如H.264、H.265、AAC、3gp等常见的音视频格式。广义而言,MediaCodec的工作原理就是处理输入数据以产生输出数据。具体来说,MediaCodec在编解码的过程中使用了一组输入/输出缓存区来同步或异步处理数据:首先,客户端向获取到的编解码器输入缓存区写入要编解码的数据并将其提交给编解码器,待编解码器处理完毕后将其转存到编码器的输出缓存区,同时收回客户端对输入缓存区的所有权;然后,客户端从获取到编解码输出缓存区读取编码好的数据进行处理,待处理完毕后编解码器收回客户端对输出缓存区的所有权。不断重复整个过程,直至编码器停止工作或者异常退出。
全栈程序员站长
2022/08/03
3K0
MediaCodec基本原理及使用「建议收藏」
Android AVDemo(4):音频解封装,从 MP4 中解封装出 AAC丨音视频工程示例
iOS/Android 客户端开发同学如果想要开始学习音视频开发,最丝滑的方式是对音视频基础概念知识有一定了解后,再借助 iOS/Android 平台的音视频能力上手去实践音视频的采集 → 编码 → 封装 → 解封装 → 解码 → 渲染过程,并借助音视频工具来分析和理解对应的音视频数据。
关键帧
2022/06/13
1.2K0
Android AVDemo(4):音频解封装,从 MP4 中解封装出 AAC丨音视频工程示例
Android AVDemo(12):视频解码,MP4 → H.264/H.265 → YUV 的源码丨音视频工程示例
这个公众号会路线图式的遍历分享音视频技术:音视频基础(完成) → 音视频工具(完成) → 音视频工程示例(进行中) → 音视频工业实战(准备)。关注一下成本不高,错过干货损失不小 ↓↓↓
关键帧
2022/11/29
1.3K0
Android AVDemo(12):视频解码,MP4 → H.264/H.265 → YUV 的源码丨音视频工程示例
FFmpeg进行音频的解码和播放
上一篇FFmpeg 内容介绍 音视频解码和播放 介绍了FFmpeg进行解码的常见函数和,解码的过程。相关的函数介绍忘记了,可以参考上一篇。
包子388321
2020/07/27
6.7K2
使用MediaCodeC将图片集编码为视频
这是MediaCodeC系列的第三章,主题是如何使用MediaCodeC将图片集编码为视频文件。在Android多媒体的处理上,MediaCodeC是一套非常有用的API。此次实验中,所使用的图片集正是MediaCodeC硬解码视频,并将视频帧存储为图片文件文章中,对视频解码出来的图片文件集,总共332张图片帧。 若是对MediaCodeC视频解码感兴趣的话,也可以浏览之前的文章:MediaCodeC解码视频指定帧,迅捷、精确
AiLo
2019/11/22
2.7K0
推荐阅读
相关推荐
OpenGLES渲染画面通过MediaCodec录制
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档