//初始化解封装
    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. 有关于mfc webbrowser插件的使用

    最近写的东西中常常需要嵌入一些浏览器,微软提供了一个比较好的接口,可以在MFC写的程序中嵌入一个简易的浏览器,是以ActiveX插件的形式提供的接口,使用起来也比较的方便,这里我就简单记录下这个插件的 ...

  2. CentOS日志列表

    anaconda/* 包含至少5个日志文件:anaccmda.log用于保存一般安装消息:anaconda.packaging.log用于保存包安装消息:anaconda.programJog用于调用 ...

  3. Java8 改进的匿名内部类:

    1.匿名内部类适合创建那种只需要一次使用的类 2.匿名内部类定义格式: new 实现接口() | 父类构造器(实参列表){ //匿名内部类类体部分 } 3.从上面定义格式可以看出,匿名内部类必须实现一 ...

  4. loadrunner--TPS和平均事务响应时间

    TPS就是每秒事务数,但是事务是基于虚拟用户数的,假如1个虚拟用户在1秒内完成1笔事务,那么TPS明显就是1:如果 某笔业务响应时间是1ms,那么1个用户在1秒内能完成1000笔事务,TPS就是100 ...

  5. Luogu 2154 [SDOI2009]虔诚的墓主人

    弄了很久,状态很烂…… 首先发现可用的点一共只有$1e5$个,所以可以离散化坐标来方便计算. 发现对于一个空格,设它的上.下.左.右分别有$u, d, l, r$个点,它产生的贡献是$\binom{u ...

  6. c++ 中的符号与关键字

    符号按照符号的ASC码数值从小到达排列,关键字按照英文字母排序. & [38] 位运算:取地址:左值引用[指针.引用都是可以做类型转换的] #include <iostream> ...

  7. 设计规范VS设计创造力,谁更胜一筹?

    设计规范和设计创造力哪个更重要?这是一个颇具争议性的话题.如果是3年前问我这个问题我会毫不犹豫的选择设计创造力,毫无疑问,一个好的设计创造力真的是可以让人像打了鸡血一样疯狂. 原来在上大学的时候,我就 ...

  8. HttpClient的几个实现类

    DefaultHttpClient最基本的HttpClient实现 org.apache.http.impl.client.DefaultHttpClient占用内存23字节 第一次初始化的时候需要2 ...

  9. linux tty设置详解

    http://blog.csdn.net/againyuan/article/details/3905380 linux串口termios NAME termios, tcgetattr, tcset ...

  10. python pip国内源

    pip国内的这个源最快   清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/ 修改源方法: 临时使用: 可以在使用pip的时候在后面加上-i参数,指定pip ...