• EasyDarwin接入ffmpeg实现264转图片快照功能


    本文转自:http://blog.csdn.net/cai6811376/article/details/51774467

    EasyDarwin一直坚持开源精神,所以我们着手把EasyDarwin中使用的非开源工具替换为开源项目。

    我们将EasyCMS中使用的图片保存替换为FFmpeg。(这里说明Windows版)

    • 首先到ffmpeg官网下载编译好的ffmpeg文件

    下载页面:https://ffmpeg.zeranoe.com/builds/

    ffmpeg

    Shared包含.dll文件,Dev包含.h和.lib文件

    将.h/.lib/.dll引入EasyDarwin工程

    .h放入EasyDarwin/Include/FFmpeg下

    .lib放入EasyDarwin/Lib/FFmpeg/x86下

    .dll放入EasyDarwin/Bin/FFmpeg/x86下

    • 编写DecoderHelper类

    DecoderHelper.h

    #ifndef _DECODER_HELPER_
    #define _DECODER_HELPER_
    
    #define __STDC_CONSTANT_MACROS
    
    extern "C" 
    {
    #include <inttypes.h>
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/avutil.h"
    #include "libavutil/imgutils.h"
    #include "libswresample/swresample.h"
    #include "libswscale/swscale.h"
    }
    
    class DecoderHelper
    {
    public:
        DecoderHelper();
        ~DecoderHelper();
    
        int     SetVideoDecoderParam(int width, int height, int codec, int format);
        int     DecodeVideo(char *inBuff, int inBuffSize, void *yuvBuff, int width, int height);
    
    private:
        void    releaseVideoDecoder();
    
    private:
        AVFormatContext*    _formatContext;
        AVCodecContext*     _videoCodecContext;
        AVFrame*            _videoFrame420;
    
        struct SwsContext*  _swsContext;
        uint8_t*            _buffYUV420;
        AVPacket            _videoAVPacket;
    
        uint8_t*            _buffYUV;
        AVFrame*            _avframeYUV;
    
        AVFrame*            _avframeSWS;
    
        int                 _codec;
        int                 _width;
        int                 _height;
        int                 _outputFormat;
    
    };
    
    #endif //_DECODER_HELPER_

    DecoderHelper.cpp

    #include "DecoderHelper.h"
    
    DecoderHelper::DecoderHelper()
        : _formatContext(NULL),
        _videoCodecContext(NULL),
        _videoFrame420(NULL),
        _buffYUV420(NULL),
        _buffYUV(NULL),
        _avframeYUV(NULL),
        _avframeSWS(NULL),
        _swsContext(NULL),
        _codec(0),
        _width(0),
        _height(0),
        _outputFormat(0)
    {
        //Register all the codec
        avcodec_register_all();
        //Register all types of decoding
        av_register_all();
    }
    
    DecoderHelper::~DecoderHelper()
    {
        releaseVideoDecoder();
    }
    
    int DecoderHelper::SetVideoDecoderParam(int width, int height, int codec, int format)
    {
        if (_width != width || _height != height || _codec != codec)
        {
            releaseVideoDecoder();
        }
    
        if (NULL != _videoCodecContext)
        {
            return -1;
        }
    
        AVCodec *avcodec = avcodec_find_decoder((AVCodecID)codec);
        if (NULL == avcodec)
        {
            return -1;
        }
    
        _videoCodecContext = avcodec_alloc_context3(avcodec);
        _videoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
        _videoCodecContext->width   = width;
        _videoCodecContext->height  = height;
    
        int ret = avcodec_open2(_videoCodecContext, avcodec, NULL);
        if (ret < 0)
        {
            goto $fail;
        }
    
        int numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, width, height);
        _buffYUV420 = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
        _videoFrame420 = av_frame_alloc();
        if (avpicture_fill((AVPicture *)_videoFrame420, _buffYUV420, AV_PIX_FMT_YUV420P,
            _width, _height) < 0)
        {
    
        }
    
        av_init_packet(&_videoAVPacket);
        _width = width;
        _height = height;
        _codec = codec;
        _outputFormat = format;
    
        return 0;
    
    $fail:
        {
            return -1;
        }
    
    }
    
    int DecoderHelper::DecodeVideo(char *inBuff, int inBuffSize, void *yuvBuff, int width, int height)
    {
        if (NULL == inBuff)         return -1;
        if (1 > inBuffSize)         return -1;
        if (NULL == yuvBuff)        return -1;
        if (NULL == _videoCodecContext)     return -2;
    
        _videoAVPacket.size = inBuffSize;
        _videoAVPacket.data = (uint8_t*)inBuff;
    
        int frameFinished = 0;
        int nDecode = avcodec_decode_video2(_videoCodecContext, _videoFrame420, &frameFinished, &_videoAVPacket);//(uint8_t*)pInBuffer, inputSize);
        if (nDecode < 0)    return -3;
        if (!frameFinished) return -4;
    
        if  (width != _width || height != _height)
        {
            if (NULL != _avframeYUV)
            {
                av_frame_free(&_avframeYUV);
                _avframeYUV = NULL;
            }
    
            if (NULL != _swsContext)
            {
                sws_freeContext(_swsContext);
                _swsContext = NULL;
            }
    
            _width = width;
            _height = height;
        }
    
        if (NULL == _avframeYUV)
        {
            int numBytes = avpicture_get_size((AVPixelFormat)_outputFormat, width, height);
            _avframeYUV = av_frame_alloc();
        }
        if (NULL == _avframeYUV)        return -5;
    
        if (avpicture_fill((AVPicture *)_avframeYUV, (uint8_t*)yuvBuff, (AVPixelFormat)_outputFormat,
            width, height) < 0)
        {
            return -1;
        }
    
        if (NULL == _swsContext)
        {
            _swsContext = sws_getCachedContext(_swsContext, _videoCodecContext->width, _videoCodecContext->height, (AVPixelFormat)AV_PIX_FMT_YUV420P, 
                width, height, (AVPixelFormat)_outputFormat, SWS_BICUBIC, NULL, NULL, NULL);
        }
        if (NULL == _swsContext)        return -1;
    
        int ret = sws_scale(_swsContext, _videoFrame420->data, _videoFrame420->linesize, 0, _videoCodecContext->height, 
            _avframeYUV->data, _avframeYUV->linesize);
    
        return 0;
    }
    
    void DecoderHelper::releaseVideoDecoder()
    {
        if (NULL != _videoFrame420)
        {
            av_frame_free(&_videoFrame420);
            _videoFrame420 = NULL;
        }
        if (NULL != _buffYUV420)
        {
            av_free(_buffYUV420);
            _buffYUV420 = NULL;
        }
        if (NULL != _avframeSWS)
        {
            av_frame_free(&_avframeSWS);
            _avframeSWS = NULL;
        }
        if (NULL != _avframeYUV)
        {
            av_frame_free(&_avframeYUV);
            _avframeYUV = NULL;
        }
        if (NULL != _buffYUV)
        {
            av_free(_buffYUV);
            _buffYUV = NULL;
        }
    
        if (NULL != _swsContext)
        {
            sws_freeContext(_swsContext);
            _swsContext = NULL;
        }
    
        if (NULL != _videoCodecContext)
        {
            avcodec_close(_videoCodecContext);
            av_free(_videoCodecContext);
            _videoCodecContext = NULL;
        }
    }
    • 使用
    DecoderHelper decoderHelper;
    decoderHelper.SetVideoDecoderParam();
    decoderHelper.DecodeVideo();

    获取更多信息

    邮件:support@easydarwin.org

    WEB:www.EasyDarwin.org

    QQ交流群:288214068

    Copyright © EasyDarwin.org 2012-2015

    EasyDarwin

  • 相关阅读:
    Revit API改变风管及管件尺寸
    Revit API注册事件
    Revit API创建标高,单位转换
    Revit API判断直线相交关系移动风管
    Revit MEP API找到连接器连接的连接器
    Revit MEP API连接器类别
    AngularJS如何编译和呈现页面
    AngularJS自定义Directive初体验
    Webpack基本用法
    对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解
  • 原文地址:https://www.cnblogs.com/babosa/p/9217919.html
Copyright © 2020-2023  润新知