实战FFmpeg + OpenGLES--iOS平台上视频解码和播放

  一个星期的努力终于搞定了视频的播放,利用FFmpeg解码视频,将解码的数据通过OpenGLES渲染播放。搞清楚了自己想知道的和完成了自己的学习计划,有点小兴奋。明天就是“五一”,放假三天,更开心啦。

  本文实现视频文件的播放是在自己之前写的文章实战FFmpeg--iOS平台使用FFmpeg将视频文件转换为YUV文件 、 实战OpenGLES--iOS平台使用OpenGLES渲染YUV图片 的基础上改进合成来完成的。不多种解释,直接上代码,清晰明了。

NSString *path = [[NSBundle mainBundle] pathForResource:@"nwn" ofType:@"mp4"];
    const char *filepath= [path UTF8String];

    av_register_all();
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();
    if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
        printf("Couldn‘t open input stream.\n");
        exit(1);
    }

    /*
     * av_find_stream_info():ffmpeg版本更新后没有这个函数了,用avformat_find_stream_info这个函数,可以自己看一下版本更新改动
     */
    //    if(av_find_stream_info(pFormatCtx)<0)
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
    {
        printf("Couldn‘t find stream information.\n");
        exit(1);
    }

    videoindex=-1;
    for(int i=0; i<pFormatCtx->nb_streams; i++)
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
        {
            videoindex=i;
            break;
        }
    if(videoindex==-1)
    {
        printf("Didn‘t find a video stream.\n");
        exit(1);
    }
    pCodecCtx=pFormatCtx->streams[videoindex]->codec;
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        printf("Codec not found.\n");
        exit(1);
    }
    /*
     * avcodec_open():ffmpeg版本更新后没有这个函数了,用avformat_find_stream_info这个函数,可以自己看一下版本更新改动
     * avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
     */
    //    if(avcodec_open(pCodecCtx, pCodec)<0)
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
    {
        printf("Could not open codec.\n");
        exit(1);
    }
    AVFrame    *pFrame,*pFrameYUV;
    pFrame=avcodec_alloc_frame();
    pFrameYUV=avcodec_alloc_frame();
    uint8_t *out_buffer;
    out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];
    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);

    int ret, got_picture;
    int y_size = pCodecCtx->width * pCodecCtx->height;

    AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));
    av_new_packet(packet, y_size);

    printf("video infomation:\n");
    av_dump_format(pFormatCtx,0,filepath,0);

    while(av_read_frame(pFormatCtx, packet)>=0)
    {
        if(packet->stream_index==videoindex)
        {
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
            if(ret < 0)
            {
                printf("Decode Error.\n");
                exit(1);
            }
            if(got_picture)
            {
                char *buf = (char *)malloc(pFrame->width * pFrame->height * 3 / 2);

                AVPicture *pict;
                int w, h;
                char *y, *u, *v;
                pict = (AVPicture *)pFrame;//这里的frame就是解码出来的AVFrame
                w = pFrame->width;
                h = pFrame->height;
                y = buf;
                u = y + w * h;
                v = u + w * h / 4;

                for (int i=0; i<h; i++)
                    memcpy(y + w * i, pict->data[0] + pict->linesize[0] * i, w);
                for (int i=0; i<h/2; i++)
                    memcpy(u + w / 2 * i, pict->data[1] + pict->linesize[1] * i, w / 2);
                for (int i=0; i<h/2; i++)
                    memcpy(v + w / 2 * i, pict->data[2] + pict->linesize[2] * i, w / 2);

                [myview setVideoSize:pFrame->width height:pFrame->height];
                [myview displayYUV420pData:buf width:pFrame->width height:pFrame->height]; //利用OpenGLES渲染YUV
                free(buf);
            }
        }
        av_free_packet(packet);
    }
    delete[] out_buffer;
    av_free(pFrameYUV);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

  本周的学习任务完成啦,写完这篇博客就下班回家,哈哈。五一长假,我要休息下,列出自己下一步的学习计划。下周我想做的是本地音频文件解码播放,以及本地视频文件中音频与视频同步播放。现在所做的都是本地音视频文件的处理,因为本地文件处理起来方便一些,这也让自己学起来也快速一些。关于网络音视频实时流的同步与播放,这个涉及的内容就要复杂一些了,有效学习+时间规划,我肯定能玩透播放器的开发。

  本文完整工程 FFmpegDecode_OpenGLESRenderYUV 的下载地址为:http://pan.baidu.com/s/1dDvpECh

时间: 2024-10-27 21:31:08

实战FFmpeg + OpenGLES--iOS平台上视频解码和播放的相关文章

使用Vitamio开发iOS平台上的万能播放器

迅速了解 Vitamio是干什么的?看官方怎么说: "Vitamio SDK for iOS是Yixia Ltd官方推出的 iOS 平台上使用的软件开发工具包(SDK),为iOS开发者提供简单.快捷的接口,帮助开发者实现 iOS 平台上的媒体播放应用." 说白了,就是可以帮助你便捷地开发自己的iOS播放器. 本文目标 从0开始建工程,使用VitamioSDK开发一个最简单的播放器:打开app之后,能看到一个播放按钮,点击按钮,就开始播放事先放在Documents目录下的视频文件,再按一

[iOS]FFmpeg框架在iOS平台上的编译和使用

使用环境 Mac OS Yosemite 10.10.5 开发工具 Xcode 7.0 Terminal 需要的文件链接 gas-preprocessor yasm FFmpeg-iOS-build-script ffmpeg-2.8 kxmovie 编译适用于iOS平台的FFmpeg静态库 打开终端Terminal进入下载后的gas-preprocessor文件夹 将文件夹内的gas-preprocessor.pl文件拷贝到/usr/sbin/目录下 修改/usr/sbin/gas-prepr

iOS平台上的音视频即时通讯应用开发

现在IOS很是火热,一大堆开发人员在捣鼓IOS平台的开发,相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于IOS平台的音视频即时通讯的应用,这个应用必须能够做到跨平台 支持iOS平台设备上的音频即时通讯应用开发 提供Objective-C语言API接口,开放示例源代码 集成H.264.AAC.AMR等编解码技术 封装音视频的采集.编解码.传输.显示和播放等模块 支持Android.Web.PC等设备和iOS之间的互联互通 想要在IOS平台下实现音视频通信,最快捷

iOS平台上音频编码成aac

小程之前介绍解码aac时,曾经使用了fadd,并且有提到,如果想编码成aac格式,可以使用facc.fdk-aac等,但使用fdk-aac等编码方式,都是软编码,在cpu的消耗上会明显大于硬件编码. 硬编码的优势是可以用硬件芯片集成的功能,高速且低功耗地完成编码任务. 在iOS平台,也提供了硬编码的能力,APP开发时只需要调用相应的SDK接口就可以了. 这个SDK接口就是AudioConverter. 本文介绍iOS平台上,如何调用AudioConverter来完成aac的硬编码. 从名字来看,

实战AudioToolbox--在iOS平台上播放音频

上午看了关于AudioToolbox.framework相关的资料,结合网上的资料对AudioToolbox的基本使用有了整体上的认识,上一篇文章 笔谈AudioToolbox(一) 中提到使用AudioQueue来实现音频播放功能时最主要的步骤: 1. 打开播放音频文件 2. 取得播放音频文件的数据格式 3. 准备播放用的队列 4. 将缓冲中的数据移动到队列中 5. 开始播放 6. 在回调函数中进行队列处理 按照这个步骤实现了音频的播放. OSStatus status;     NSStri

【cocos2d-js官方文档】二十三、如何在IOS平台上使用js直接调用OC方法

在Cocos2d-JS v3.0 RC2中,与Android上js调用Java一样,Cocos2d-JS也提供了在iOS和Mac上js直接调用Objective-C的方法,示例代码如下: var ojb = jsb.reflection.callStaticMethod(className, methodNmae, arg1, arg2, .....); 在jsb.reflection.callStaticMethod方法中,我们通过传入OC的类名,方法名,参数就可以直接调用OC的静态方法,并且

ios微信上无法自动播放音频的情况

今天做个html5需要自动播放音频,发现在ios下autoplay="autoplay"是失效的 就想着强制用js强制播放 document.getElementById('music').play(); 发现并没有用 加上这段代码后才有作用 document.getElementById('music').play(); document.addEventListener("WeixinJSBridgeReady", function () {//监听微信准备就绪

【转】iOS平台的应用程序调试与分析

转自:看雪学院的文章 iOS平台的应用程序调试与分析 作者:zhuliang转载请保证文章完整并注明来自看雪或cd-team 本文阐述如何在iOS平台上对应用程序进行调试与分析,旨在指导新手分析iOS程序,高手请无视.内容包括软件硬件的准备.代码的解密.符号信息的获取.用gdb调试等,最后以京东LeBook为例子进行演示.1.为什么要进行调试与分析研究iOS程序有很多用处,比如:找bug或者漏洞,想知道某程序有没有漏洞或者bug.某程序能实现某功能,我想知道如何实现,如ios6发短信功能,还有比

ios GitHub上比较不错的开源项目,有时间可以学习下

1.ReactiveCocoa:ReactiveCocoa/ReactiveCocoa · GitHub: GitHub自家的函数式响应式编程泛型的Objective-C实现,名字听着很高大上,学习曲线确实也比较陡,但是绝对会改变你对iOS编程的认知,首推之. 2. Mantle:Mantle/Mantle · GitHub: 又是GitHub自家的产物,轻量级建模的首选,也可以很好的配合CoreData工作. 3. AFNetworking:AFNetworking/AFNetworking