//初始化解封装
    av_register_all();
    avformat_network_init();
    avcodec_register_all();
    //封装文件的上下文
    AVFormatContext *ic = NULL;
    char path[] = "sdcard/shape.mp4";
    //打开文件并且解析
    int re = avformat_open_input(&ic, path, NULL, NULL);
    if(re != 0)
    {
        Logw("avformat_open_input %s failed", av_err2str(re));
        return env->NewStringUTF(hello.c_str());
    }
    
    Logw("duration = %lld  nb_stream = %d", ic->duration , ic->nb_streams);
    //找到流的信息
    int re1 = avformat_find_stream_info(ic, NULL);
    if(re1!=0)
    {
        Logw("avformat_find_stream_info failed");
    }
    Logw("duration = %lld nb_stream = %d" , ic->duration , ic->nb_streams);

//找流的信息有两种方案
    //1.遍历整个信息
    int fps = 0 ;
    int wigth = 0;
    int height = 0;
    int videoStream = 0;
    int audioStream = 0;
    for (int i = 0; i < ic->nb_streams; i++)
    {
        AVStream *as = ic->streams[i];
        if(as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            Logw("视频数据");
            videoStream = i;
            fps = r2d(as->avg_frame_rate);
            Logw("fps = %d width = %d height = %d codeid = %d" , fps , as->codecpar->width ,
                 as->codecpar->height , as->codecpar->codec_id);
            Logw("tag = %d  format = %d" , as->codecpar->codec_tag , as->codecpar->format);
        }
        else if(as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            Logw("音频数据");
            audioStream = i;
            Logw("sample_rate = %d channel = %d format = %d" , as->codecpar->sample_rate ,
                  as->codecpar->channels , as->codecpar->format);
        }
    }

//av_find_best_stream()来找到对应的流
    audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    Logw("av_find_best_stream audioStream = %d " , audioStream);
    Logw("sample_rate = %d channel = %d format = %d" , ic->streams[audioStream]->codecpar->sample_rate ,
         ic->streams[audioStream]->codecpar->channels , ic->streams[audioStream]->codecpar->format);

/*****************打开视频解码器*********************************/
    //找到软解码器
    AVCodec *codec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
    //找到硬解码器
    codec = avcodec_find_decoder_by_name("h264_mediacodec");

//解码器初始化
    AVCodecContext *vc = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(vc, ic->streams[videoStream]->codecpar);
    vc->thread_count = 4;

//打开解码器
    re  = avcodec_open2(vc, 0, 0);
    if(re != 0)
    {
        Logw("avcodec open failed");
        return env->NewStringUTF(hello.c_str());
    }

/*****************打开音频解码器*********************************/
    AVCodec *avCodec = avcodec_find_decoder(ic->streams[audioStream]->codecpar->codec_id);

//初始化软解码器
    AVCodecContext *av = avcodec_alloc_context3(avCodec);
    avcodec_parameters_to_context(av, ic->streams[audioStream]->codecpar);
    av->thread_count = 4;

//打开音视频解码器
    re = avcodec_open2(av, 0, 0);
    if(re != 0)
    {
        Logw("avcodec open failed");
        return env->NewStringUTF(hello.c_str());
    }

//读取帧数据
    AVPacket *pkt = av_packet_alloc();
    AVFrame *frame = av_frame_alloc();
    long long start = GetNowMs();
    int frameCount = 0;
    for(;;)
    {
        //时间超过3秒
        if(GetNowMs() - start >= 3000)
        {
            Logw("now decodec fps is %d", frameCount / 3);
            start = GetNowMs();
            frameCount = 0;
        }
        int re = av_read_frame(ic, pkt);
        if(re != 0)
        {
            Logw("读取到结尾处");
//            int pos = 10 * r2d(ic->streams[videoStream]->time_base);
//            av_seek_frame(ic, videoStream, pos,
//                          AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
            break;
        }

AVCodecContext *cc = vc;
        if(pkt->stream_index == audioStream) {
            cc = av;
        }
        //把数据发送到数据缓冲空间去
        re = avcodec_send_packet(cc, pkt);
        av_packet_unref(pkt);
        if(re != 0)
        {
            Logw("avcodec_send_packet failed");
            continue;
        }

for(;;)
        {
            re = avcodec_receive_frame(cc, frame);
            if(re != 0)
            {
                //Logw("avcodec_receive_frame failed");
                break;
            }
            //Logw("avcodec_receive_frame %lld " , frame->pts);
            //如果是视频帧
            if(cc == vc)
            {
                frameCount++;
            }

}
    }
    avformat_close_input(&ic);
    return env->NewStringUTF(hello.c_str());
}

FFmpeg编写的代码的更多相关文章

  1. [转]通过Visual Studio为Linux编写C++代码

    Build 2016大会上Microsoft首次公布的Visual Studio 2015扩展提供了在VS2015中编写C++代码,随后通过Linux/UNIX计算机进行编译和执行的能力.这种想法非常 ...

  2. 基于CkEditor实现.net在线开发之路(2)编写C#代码,怎么调用它。

    上一章简约的介绍了CkEditor编辑器,可以编辑js逻辑代码,css,html,C#代码,这章我根据实际例子,讲解怎么编写C#代码和怎么调用它. 大家都还记得刚刚接触程序编时的hello Word吧 ...

  3. 解决VS2012编写JQuery代码不能智能提示的问题(其他js库的代码提示设置估计类似)

    VS默认设置下编写jQuery代码是这样的: 解决办法: 1.在项目的"管理NuGet程序包"中安装JQuery: 2.打开:工具 -> 选项 -> 文本编辑器 -&g ...

  4. JNI技术基础(2)——从零开始编写JNI代码

    书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h ...

  5. 最新的JavaScript核心语言标准——ES6,彻底改变你编写JS代码的方式!【转载+整理】

    原文地址 本文内容 ECMAScript 发生了什么变化? 新标准 版本号6 兑现承诺 迭代器和for-of循环 生成器 Generators 模板字符串 不定参数和默认参数 解构 Destructu ...

  6. AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码

    AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码 添加Watch应用对象时新增内容介绍 Watch应用对象添加到创建的项目中后,会包含两个部分:Watch App 和 Wa ...

  7. mvn编写主代码与测试代码

    maven编写主代码与测试代码 3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目 ...

  8. [JS进阶] 编写可维护性代码 (1)

    今天的web应用大至成千上万行的javascript代码,执行各种复杂的过程,这种演化让我们开发者必须得对可维护性有一定的认识!编写可维护性代码很重要,很多情况下我们是以他人的工作成果为基础,确保代码 ...

  9. Java认证:JavaRunnable线程编写接口代码

    Java认证:JavaRunnable线程编写接口代码.JavaRunnable线程如何才能更好的适应目前的编程环境呢?下面我们就看看如何才能更好的进行相关环境.希望下面的文章对大家有所帮助.Java ...

随机推荐

  1. dede搜索页面上某些标签无法使用

    dede默认的搜索模板是search.htm,但在模板文件中使用{dede:type}{/dede:type}或{dede:flink}{/dede:flink}时,发现标签并没有被解析,显示为空. ...

  2. tp中url地址大小写问题

    在tp配置文件中有一个URL_CASE_INSENSITIVE选项,设置为true,表示大小写不敏感. 'URL_CASE_INSENSITIVE' => true

  3. Spring框架整合Struts2框架的传统方法

    1. 导入CRM项目的UI页面,找到添加客户的页面,修改form表单,访问Action * 将menu.jsp中133行的新增客户的跳转地址改为:href="${pageContext.re ...

  4. 清除所有Cookie

    代码 /// <summary> /// 清除所有Cookie /// </summary> public static void RemoveAll() { System.W ...

  5. Java jdk 8 新特性

    list 统计(求和.最大.最小.平均) 第一种方式 int suma = listUsers.stream().map(e -> e.getAge()).reduce(Integer::sum ...

  6. Java中弹出对话框中的几种方式

    1.显示一个错误对话框,该对话框显示的 message 为 'alert': JOptionPane.showMessageDialog(null, "alert", " ...

  7. This page contains the following error

    解决办法:将header头注释掉 header("content-type:text/xml; charset=UTF-8");

  8. How to Set Up an Rsync Daemon on Your Linux Server

    Introduction This tutorial will take you through setting up an rsync daemon on your Linux server. Yo ...

  9. 情感分析snownlp包部分核心代码理解

    snownlps是用Python写的个中文情感分析的包,自带了中文正负情感的训练集,主要是评论的语料库.使用的是朴素贝叶斯原理来训练和预测数据.主要看了一下这个包的几个主要的核心代码,看的过程作了一些 ...

  10. 基于beego orm 针对oracle定制

    目前golang的ORM对oracle支持都没有mysql那样完整,一个orm要同时兼容mysql和oracle由于在sql语法上区别,会使整orm变的非常臃肿. 本项目是在beego orm上修改, ...