zl程序教程

您现在的位置是:首页 >  后端

当前栏目

FFMPEG SDK 开发介绍

SDK开发 介绍 FFMPEG
2023-09-14 09:03:11 时间
1.简介:     ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。 使用ffmpeg能够完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,stream和player等. 2.下载和编译:     下载地址:  http://ffmpeg.
1.简介:
    ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。
使用ffmpeg能够完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,stream和player等.

2.下载和编译:

    下载地址:  http://ffmpeg.org/download.html

    编译:
       1)windows平台static library/shared library, 编译工具:mingw-gcc或者在linux平台下交叉编译(推荐)
       2)linux平台static library/shared library, 编译工具:gcc

    模块:
        libavcodec    - 编码解码器
        libavdevice   - 输入输出设备的支持
        libavfilter   - 视音频滤镜支持
        libavformat   - 视音频等格式的解析
        libavutil     - 工具库
        libpostproc   - 后期效果处理
        libswscale    - 图像颜色、尺寸转换
    
3.SDK介绍和开发(基于ffmpeg 0.8 sdk)
    ffmpeg每部分功能都采用plugin的方式,使用统一的接口调用,这样就能够非常方便的使用和扩展。
    plugin分为几种:muxer,demuxer,protocol,hwaccel,encoder,decoder,parser,bitstream,filter,...
    因此在使用SDK的时候第一步就是注册plugin
    
    avcodec_register_all()  : 注册 hwaccel,encoder,decoder,parser,bitstream
    av_register_all()       : 注册 muxer,demuxer,protocol
    avfilter_register_all() : 注册 滤镜filter
    
    下面根据不同的应用场景,给出主要的代码示例(仅是代码片断,不一定能编译通过):
    
    1)如何获取媒体文件的信息(Parser):
    // 参考V3代码: interface IFileDecoder, media/impl/filedecoderimpl.cpp
    
    {
        av_register_all();
        AVFormatContext * pFormatCtx = NULL;
        int err = 0;
        const char *fileName = "c:\\test.mp4";
        err = av_open_input_file( pFormatCtx, fileName, NULL, 0, NULL);
        if(err != 0)
        {
            // break ;
        }
        err = av_find_stream_info(pFormatCtx);
        if(err 0)
        {
            // break ;
        }
        for(uint32_t i = 0; i pFormatCtx- nb_streams; i ++)
        {
            // stream 结构数据
            AVStream *pStream = pFormatCtx- streams[i];
            // 帧率信息
            AVRational frameRate = pStream- r_frame_rate;
            // 时间单位比率
            AVRational timeBase = pStream- time_base;
            // stream duration
            int64_t duration = pStream- duration;
            
            // 获取Codec数据结构
            AVCodecContext *pCodecCtx = pStream- codec;
            AVMediaType codecType = pCodecCtx- codec_type;
           
            CodecID codecId = pCodecCtx- codec_id;
           
            
            if(codecType == AVMEDIA_TYPE_VIDEO)
            {
                // 获取Video基本信息
                int width = pCodecCtx- width;
                int height = pCodecCtx- height;
                PixelFormat pixelFormat = pCodecCtx- pix_fmt;
            }
            else if(codecType == AVMEDIA_TYPE_AUDIO)
            {
                // 获取Audio基本信息
                int channels = pCodecCtx- channels;
                int sample_rate = pCodecCtx- sample_rate;
                AVSampleFormat sampleFmt = pCodecCtx- sample_fmt;
            }
        }
        // 释放
        if(pFormatCtx != NULL)
        {
            av_close_input_file(pFormatCtx);
            pFormatCtx = NULL;
        }    
    }
    
    2)读取sample数据(Read raw sample不解码)
    // 参考V3代码: interface IFileDecoder, media/impl/filedecoderimpl.cpp

    {
        // 参考Parser代码
        // av_register_all();
        // AVFormatContext * pFormatCtx = NULL;
        // err = av_open_input_file( pFormatCtx, fileName, NULL, 0, NULL);
    
        AVPacket packet;
        av_init_packet( packet);
        int ret = av_read_frame(pFormatCtx, packet);
        if(ret = 0)
        {
            int streamIndex = packet.stream_index;
            AVStream *pStream = pFormatCtx- streams[streamIndex];
            AVCodecContext *pCodecCtx = pStream- codec;
            // 计算timestamp
    
            // 转换时间到1/1000000秒
            AVRational time_base;
            time_base.num = 1;
            time_base.den = 1000000;
            
            // 25.0     1/25,   29.97    1001/30000
            
            // 获取 dts/pts
            const int64_t dts = av_rescale_q(packet.dts, pStream- time_base, time_base);
            const int64_t pts = av_rescale_q(packet.pts, pStream- time_base, time_base);
            uint8_t *data = packet.data;
            int size = packet.size;
            bool isKey = ((packet.flags AV_PKT_FLAG_KEY) == AV_PKT_FLAG_KEY);    
        }
        av_free_packet( packet);        
    }
    
    3)解码sample(Video ES= YUV/RGB,  Audio ES= PCM)
    // 参考V3代码: interface IVideoDecoder/IAudioDecoder, media/impl/videodecoderimpl.cpp/audiodecoderimpl.cpp
    {
        // 参考Parser,Read raw sample代码
        
RK3568开发笔记(五):在虚拟机上使用SDK编译制作uboot、kernel和ubuntu镜像 buildroot虽然灵活,但是基于实际情况,本身是侧重驱动和应用定制开发的只定制一次文件系统投入有点多,还不如直接ubunt自己交叉编译依赖库,做一些库的移植裁剪。   于是本篇就使用ubuntu系统了,至于其他库自己下源码在宿主机交叉编译号后,再拷贝过去或者直接在板子上编译也行(只是会比较慢),但是意义不大,因为开发过程肯定是用宿主机,不然核心板编译太慢,在编译上会花费不少可以省去的时间。